From a1ab7c5d577a862b39ddb79cca6b902a51b21f35 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 27 May 2021 13:30:37 -0500 Subject: [PATCH] game boy progress, part 1 noise and wave channels don't play correctly yet --- src/engine/engine.cpp | 10 +++++ src/engine/engine.h | 1 + src/engine/platform/gb.cpp | 59 +++++++++++++++++++++++++----- src/engine/platform/gb.h | 1 + src/engine/platform/sound/gb/apu.c | 4 +- src/engine/song.h | 1 + 6 files changed, 66 insertions(+), 10 deletions(-) diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 65804ebd7..1130d6a59 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -188,6 +188,11 @@ bool DivEngine::load(void* f, size_t slen) { try { DivSong ds; + ds.nullWave.len=32; + for (int i=0; i<32; i++) { + ds.nullWave.data[i]=15; + } + if (!reader.seek(16,SEEK_SET)) { logE("premature end of file!"); return false; @@ -645,6 +650,11 @@ DivInstrument* DivEngine::getIns(int index) { return song.ins[index]; } +DivWavetable* DivEngine::getWave(int index) { + if (index<0 || index>=song.waveLen) return &song.nullWave; + return song.wave[index]; +} + void DivEngine::play() { } diff --git a/src/engine/engine.h b/src/engine/engine.h index b2727be04..046fc24c1 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -74,6 +74,7 @@ class DivEngine { DivSong song; void nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size); DivInstrument* getIns(int index); + DivWavetable* getWave(int index); // load a .dmf. bool load(void* f, size_t length); // save as .dmf. diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index 44eafeffa..b7b2a3c13 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -13,6 +13,22 @@ void DivPlatformGB::acquire(int& l, int& r) { r=gb->apu_output.final_sample.right<<3; } +void DivPlatformGB::updateWave() { + printf("updating wave\n"); + for (int i=0; i<16; i++) { + DivWavetable* wt=parent->getWave(chan[2].wave); + unsigned char next=((wt->data[i*2]&15)<<4)|(wt->data[1+i*2]&15); + rWrite(0x30+i,next); + } +} + +static unsigned char gbVolMap[16]={ + 0x00, 0x60, 0x60, 0x60, + 0x60, 0x60, 0x40, 0x40, + 0x40, 0x40, 0x40, 0x40, + 0x20, 0x20, 0x20, 0x20 +}; + void DivPlatformGB::tick() { for (int i=0; i<4; i++) { chan[i].std.next(); @@ -26,20 +42,38 @@ void DivPlatformGB::tick() { } if (chan[i].std.hadDuty) { chan[i].duty=chan[i].std.duty; - rWrite(16+i*5+1,(chan[i].duty&3)<<6); + if (i!=2) { + rWrite(16+i*5+1,(chan[i].duty&3)<<6); + } } - if (chan[i].freqChanged) { + if (chan[i].std.hadWave) { + chan[i].wave=chan[i].std.wave; + if (i==2) updateWave(); + } + if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { chan[i].freq=(chan[i].baseFreq*(ONE_SEMITONE-chan[i].pitch))/ONE_SEMITONE; if (chan[i].note>0x5d) chan[i].freq=0x01; - if (i==0 || i==1) { - if (chan[i].keyOn) { - DivInstrument* ins=parent->getIns(chan[i].ins); - rWrite(16+i*5+2,((chan[i].vol*ins->gb.envVol)&0xf0)|(ins->gb.envLen&7)|((ins->gb.envDir&1)<<3)); + if (chan[i].keyOn) { + DivInstrument* ins=parent->getIns(chan[i].ins); + if (i==2) { // wave + rWrite(16+i*5,0x80); + rWrite(16+i*5+2,gbVolMap[chan[i].vol]); + } else { + rWrite(16+i*5,0x00); + rWrite(16+i*5+2,((chan[i].vol<<4))|(ins->gb.envLen&7)|((ins->gb.envDir&1)<<3)); } - rWrite(16+i*5+3,(2048-chan[i].freq)&0xff); - rWrite(16+i*5+4,(((2048-chan[i].freq)>>8)&7)|(chan[i].keyOn?0x80:0x00)); - if (chan[i].keyOn) chan[i].keyOn=false; } + if (chan[i].keyOff) { + if (i==2) { + rWrite(16+i*5+2,0); + } else { + rWrite(16+i*5+2,8); + } + } + rWrite(16+i*5+3,(2048-chan[i].freq)&0xff); + rWrite(16+i*5+4,(((2048-chan[i].freq)>>8)&7)|((chan[i].keyOn||chan[i].keyOff)?0x80:0x00)); + if (chan[i].keyOn) chan[i].keyOn=false; + if (chan[i].keyOff) chan[i].keyOff=false; chan[i].freqChanged=false; } } @@ -60,6 +94,7 @@ int DivPlatformGB::dispatch(DivCommand c) { chan[c.chan].note=c.value; chan[c.chan].active=true; chan[c.chan].keyOn=true; + if (c.chan==2) updateWave(); chan[c.chan].std.init(parent->getIns(chan[c.chan].ins)); break; case DIV_CMD_NOTE_OFF: @@ -69,10 +104,16 @@ int DivPlatformGB::dispatch(DivCommand c) { break; case DIV_CMD_INSTRUMENT: chan[c.chan].ins=c.value; + if (c.chan!=2) { + chan[c.chan].vol=parent->getIns(chan[c.chan].ins)->gb.envVol; + } break; case DIV_CMD_VOLUME: if (chan[c.chan].vol!=c.value) { chan[c.chan].vol=c.value; + if (c.chan==2) { + rWrite(16+c.chan*5+2,gbVolMap[chan[c.chan].vol]); + } } break; case DIV_CMD_GET_VOLUME: diff --git a/src/engine/platform/gb.h b/src/engine/platform/gb.h index 4460817a8..d503726cf 100644 --- a/src/engine/platform/gb.h +++ b/src/engine/platform/gb.h @@ -34,6 +34,7 @@ class DivPlatformGB: public DivDispatch { short pendingWrites[64]; GB_gameboy_t* gb; + void updateWave(); public: void acquire(int& l, int& r); int dispatch(DivCommand c); diff --git a/src/engine/platform/sound/gb/apu.c b/src/engine/platform/sound/gb/apu.c index 8c56a1a2f..7abac9021 100644 --- a/src/engine/platform/sound/gb/apu.c +++ b/src/engine/platform/sound/gb/apu.c @@ -266,6 +266,7 @@ static void render(GB_gameboy_t *gb) } + /* if (gb->apu_output.interference_volume) { signed interference_bias = interference(gb); int16_t interference_sample = (interference_bias - gb->apu_output.interference_highpass); @@ -275,7 +276,8 @@ static void render(GB_gameboy_t *gb) filtered_output.left = MAX(MIN(filtered_output.left + interference_bias, 0x7FFF), -0x8000); filtered_output.right = MAX(MIN(filtered_output.right + interference_bias, 0x7FFF), -0x8000); - } + }*/ + gb->apu_output.final_sample=filtered_output; } diff --git a/src/engine/song.h b/src/engine/song.h index b779a09f2..b81dc0eca 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -96,4 +96,5 @@ struct DivSong { std::vector sample; DivInstrument nullIns; + DivWavetable nullWave; };