Virtual Boy: how does this work?

This commit is contained in:
tildearrow 2022-10-10 18:48:36 -05:00
parent 6c88c9c798
commit 22dcc610fa
3 changed files with 45 additions and 24 deletions

View file

@ -128,12 +128,17 @@ void DivPlatformVB::updateWave(int ch) {
} }
} }
void DivPlatformVB::writeEnv(int ch) {
chWrite(ch,0x04,(chan[ch].outVol<<4)|(chan[ch].envLow&15));
chWrite(ch,0x05,chan[ch].envHigh);
}
void DivPlatformVB::tick(bool sysTick) { void DivPlatformVB::tick(bool sysTick) {
for (int i=0; i<6; i++) { for (int i=0; i<6; i++) {
chan[i].std.next(); chan[i].std.next();
if (chan[i].std.vol.had) { if (chan[i].std.vol.had) {
chan[i].outVol=VOL_SCALE_LINEAR(chan[i].vol&15,MIN(15,chan[i].std.vol.val),15); chan[i].outVol=VOL_SCALE_LINEAR(chan[i].vol&15,MIN(15,chan[i].std.vol.val),15);
chWrite(i,0x04,chan[i].outVol<<4); writeEnv(i);
} }
if (chan[i].std.arp.had) { if (chan[i].std.arp.had) {
if (!chan[i].inPorta) { if (!chan[i].inPorta) {
@ -209,7 +214,7 @@ int DivPlatformVB::dispatch(DivCommand c) {
chan[c.chan].macroInit(ins); chan[c.chan].macroInit(ins);
if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) { if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol; chan[c.chan].outVol=chan[c.chan].vol;
chWrite(c.chan,0x04,chan[c.chan].outVol<<4); writeEnv(c.chan);
} }
if (chan[c.chan].wave<0) { if (chan[c.chan].wave<0) {
chan[c.chan].wave=0; chan[c.chan].wave=0;
@ -240,7 +245,7 @@ int DivPlatformVB::dispatch(DivCommand c) {
if (!chan[c.chan].std.vol.has) { if (!chan[c.chan].std.vol.has) {
chan[c.chan].outVol=c.value; chan[c.chan].outVol=c.value;
if (chan[c.chan].active) { if (chan[c.chan].active) {
chWrite(c.chan,0x04,chan[c.chan].outVol<<4); writeEnv(c.chan);
} }
} }
} }
@ -260,20 +265,6 @@ int DivPlatformVB::dispatch(DivCommand c) {
chan[c.chan].ws.changeWave1(chan[c.chan].wave); chan[c.chan].ws.changeWave1(chan[c.chan].wave);
chan[c.chan].keyOn=true; chan[c.chan].keyOn=true;
break; break;
case DIV_CMD_PCE_LFO_MODE:
if (c.value==0) {
lfoMode=0;
} else {
lfoMode=c.value;
}
rWrite(0x08,lfoSpeed);
rWrite(0x09,lfoMode);
break;
case DIV_CMD_PCE_LFO_SPEED:
lfoSpeed=255-c.value;
rWrite(0x08,lfoSpeed);
rWrite(0x09,lfoMode);
break;
case DIV_CMD_NOTE_PORTA: { case DIV_CMD_NOTE_PORTA: {
int destFreq=NOTE_PERIODIC(c.value2); int destFreq=NOTE_PERIODIC(c.value2);
bool return2=false; bool return2=false;
@ -298,8 +289,30 @@ int DivPlatformVB::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_STD_NOISE_MODE: case DIV_CMD_STD_NOISE_MODE:
chan[c.chan].noise=c.value; if (c.chan!=5) break;
chWrite(c.chan,0x07,chan[c.chan].noise?(0x80|chan[c.chan].note):0); chan[c.chan].envHigh&=~0x70;
chan[c.chan].envHigh|=(c.value&7)<<4;
writeEnv(c.chan);
break;
case DIV_CMD_STD_NOISE_FREQ:
chan[c.chan].envHigh&=~3;
chan[c.chan].envHigh|=(c.value>>4)&3;
chan[c.chan].envLow=c.value&15;
writeEnv(c.chan);
break;
case DIV_CMD_FDS_MOD_DEPTH: // set modulation
if (c.chan!=4) break;
modulation=c.value;
chWrite(4,0x06,modulation);
if (modulation!=0) {
chan[c.chan].envHigh|=0x10;
} else {
chan[c.chan].envHigh&=~0x10;
}
writeEnv(4);
break;
case DIV_CMD_FDS_MOD_WAVE: // set modulation wave
break; break;
case DIV_CMD_PANNING: { case DIV_CMD_PANNING: {
chan[c.chan].pan=(c.value&0xf0)|(c.value2>>4); chan[c.chan].pan=(c.value&0xf0)|(c.value2>>4);
@ -385,8 +398,7 @@ void DivPlatformVB::reset() {
tempR=0; tempR=0;
cycles=0; cycles=0;
curChan=-1; curChan=-1;
lfoMode=0; modulation=0;
lfoSpeed=255;
// set per-channel initial values // set per-channel initial values
for (int i=0; i<6; i++) { for (int i=0; i<6; i++) {
chWrite(i,0x01,isMuted[i]?0:chan[i].pan); chWrite(i,0x01,isMuted[i]?0:chan[i].pan);

View file

@ -30,7 +30,7 @@ class DivPlatformVB: public DivDispatch {
struct Channel { struct Channel {
int freq, baseFreq, pitch, pitch2, note; int freq, baseFreq, pitch, pitch2, note;
int ins; int ins;
unsigned char pan; unsigned char pan, envLow, envHigh;
bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, noise, deferredWaveUpdate; bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, noise, deferredWaveUpdate;
signed char vol, outVol, wave; signed char vol, outVol, wave;
DivMacroInt std; DivMacroInt std;
@ -47,6 +47,8 @@ class DivPlatformVB: public DivDispatch {
note(0), note(0),
ins(-1), ins(-1),
pan(255), pan(255),
envLow(0),
envHigh(0),
active(false), active(false),
insChanged(true), insChanged(true),
freqChanged(false), freqChanged(false),
@ -73,10 +75,11 @@ class DivPlatformVB: public DivDispatch {
int cycles, curChan, delay; int cycles, curChan, delay;
int tempL; int tempL;
int tempR; int tempR;
unsigned char lfoMode, lfoSpeed; unsigned char modulation;
VSU* vb; VSU* vb;
unsigned char regPool[0x600]; unsigned char regPool[0x600];
void updateWave(int ch); void updateWave(int ch);
void writeEnv(int ch);
friend void putDispatchChip(void*,int); friend void putDispatchChip(void*,int);
friend void putDispatchChan(void*,int,int); friend void putDispatchChan(void*,int,int);
public: public:

View file

@ -1180,7 +1180,13 @@ void DivEngine::registerSystems() {
{DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_NOISE}, {DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_WAVE, DIV_CH_NOISE},
{DIV_INS_VBOY, DIV_INS_VBOY, DIV_INS_VBOY, DIV_INS_VBOY, DIV_INS_VBOY, DIV_INS_VBOY}, {DIV_INS_VBOY, DIV_INS_VBOY, DIV_INS_VBOY, DIV_INS_VBOY, DIV_INS_VBOY, DIV_INS_VBOY},
{}, {},
waveOnlyEffectHandlerMap {
{0x10, {DIV_CMD_WAVE, "10xx: Set waveform"}},
{0x11, {DIV_CMD_STD_NOISE_MODE, "11xx: Set noise length (0 to 7)"}},
{0x12, {DIV_CMD_STD_NOISE_FREQ, "12xy: Setup envelope (x: enabled/loop (1: enable, 2: loop, 3: enable+loop); y: speed/direction (0-7: down, 8-F: up))"}},
{0x14, {DIV_CMD_FDS_MOD_DEPTH, "14xy: Setup modulation (channel 5 only)"}},
{0x15, {DIV_CMD_FDS_MOD_WAVE, "15xx: Set modulation waveform (channel 5 only)"}},
}
); );
sysDefs[DIV_SYSTEM_VRC7]=new DivSysDef( sysDefs[DIV_SYSTEM_VRC7]=new DivSysDef(