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) {
for (int i=0; i<6; i++) {
chan[i].std.next();
if (chan[i].std.vol.had) {
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].inPorta) {
@ -209,7 +214,7 @@ int DivPlatformVB::dispatch(DivCommand c) {
chan[c.chan].macroInit(ins);
if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) {
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) {
chan[c.chan].wave=0;
@ -240,7 +245,7 @@ int DivPlatformVB::dispatch(DivCommand c) {
if (!chan[c.chan].std.vol.has) {
chan[c.chan].outVol=c.value;
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].keyOn=true;
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: {
int destFreq=NOTE_PERIODIC(c.value2);
bool return2=false;
@ -298,8 +289,30 @@ int DivPlatformVB::dispatch(DivCommand c) {
break;
}
case DIV_CMD_STD_NOISE_MODE:
chan[c.chan].noise=c.value;
chWrite(c.chan,0x07,chan[c.chan].noise?(0x80|chan[c.chan].note):0);
if (c.chan!=5) break;
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;
case DIV_CMD_PANNING: {
chan[c.chan].pan=(c.value&0xf0)|(c.value2>>4);
@ -385,8 +398,7 @@ void DivPlatformVB::reset() {
tempR=0;
cycles=0;
curChan=-1;
lfoMode=0;
lfoSpeed=255;
modulation=0;
// set per-channel initial values
for (int i=0; i<6; i++) {
chWrite(i,0x01,isMuted[i]?0:chan[i].pan);

View file

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