From 5aeeb0961676600948e7e0c19134ecb28070728f Mon Sep 17 00:00:00 2001 From: cam900 Date: Thu, 31 Aug 2023 20:34:04 +0900 Subject: [PATCH] Prepare for NMK112 bankswitching support --- src/engine/platform/msm6295.cpp | 165 ++++++++++++++++++++++++-------- src/engine/platform/msm6295.h | 12 ++- src/gui/debug.cpp | 22 +++++ src/gui/sysConf.cpp | 6 ++ 4 files changed, 164 insertions(+), 41 deletions(-) diff --git a/src/engine/platform/msm6295.cpp b/src/engine/platform/msm6295.cpp index 3d823d16..e72b8c42 100644 --- a/src/engine/platform/msm6295.cpp +++ b/src/engine/platform/msm6295.cpp @@ -34,6 +34,12 @@ u8 DivPlatformMSM6295::read_byte(u32 address) { if (adpcmMem==NULL || address>=getSampleMemCapacity(0)) { return 0; } + if (isBanked) { + if (address<0x400) { + return adpcmMem[(bank[(address>>8)&0x3]<<16)|(address&0x3ff)]; + } + return adpcmMem[(bank[(address>>16)&0x3]<<16)|(address&0xffff)]; + } return adpcmMem[address&0x3ffff]; } @@ -62,6 +68,7 @@ void DivPlatformMSM6295::acquire(short** buf, size_t len) { case 17: case 18: case 19: + bank[w.addr-16]=w.val; break; } writes.pop(); @@ -109,7 +116,12 @@ void DivPlatformMSM6295::tick(bool sysTick) { rWriteDelay(0,(8<=0 && chan[i].samplesong.sampleLen) { - rWrite(0,0x80|chan[i].sample); // set phrase + if (isBanked) { + rWrite(16+i,bankedPhrase[chan[i].sample].bank); + rWrite(0,0x80|(i<<5)|bankedPhrase[chan[i].sample].phrase); + } else { + rWrite(0,0x80|chan[i].sample); // set phrase + } rWrite(0,(16<getSample(12*sampleBank+c.value%12); chan[c.chan].sample=12*sampleBank+c.value%12; rWriteDelay(0,(8<song.sampleLen; - if (sampleCount>127) sampleCount=127; - for (int i=0; isong.sample[i]; - if (!s->renderOn[0][sysID]) { - sampleOffVOX[i]=0; - continue; - } + if (isBanked) { + int bankInd=0; + int phraseInd=0; + for (int i=0; isong.sampleLen; i++) { + DivSample* s=parent->song.sample[i]; + if (!s->renderOn[0][sysID]) { + sampleOffVOX[i]=0; + continue; + } - int paddedLen=s->lengthVOX; - if (memPos>=getSampleMemCapacity(0)) { - logW("out of ADPCM memory for sample %d!",i); - break; + int paddedLen=s->lengthVOX; + // fit to single bank size + if (paddedLen>65536-0x400) { + paddedLen=65536-0x400; + } + // 32 phrase per bank + if ((phraseInd>=32)||((memPos&0xff0000)!=((memPos+paddedLen)&0xff0000))) { + memPos=((memPos+0xffff)&0xff0000)+0x400; + bankInd++; + phraseInd=0; + } + if (memPos>=getSampleMemCapacity(0)) { + logW("out of ADPCM memory for sample %d!",i); + break; + } + if (memPos+paddedLen>=getSampleMemCapacity(0)) { + memcpy(adpcmMem+memPos,s->dataVOX,getSampleMemCapacity(0)-memPos); + logW("out of ADPCM memory for sample %d!",i); + } else { + memcpy(adpcmMem+memPos,s->dataVOX,paddedLen); + sampleLoaded[i]=true; + } + sampleOffVOX[i]=memPos; + bankedPhrase[i].bank=bankInd; + bankedPhrase[i].phrase=phraseInd; + memPos+=paddedLen; + phraseInd++; } - if (memPos+paddedLen>=getSampleMemCapacity(0)) { - memcpy(adpcmMem+memPos,s->dataVOX,getSampleMemCapacity(0)-memPos); - logW("out of ADPCM memory for sample %d!",i); - } else { - memcpy(adpcmMem+memPos,s->dataVOX,paddedLen); - sampleLoaded[i]=true; - } - sampleOffVOX[i]=memPos; - memPos+=paddedLen; - } - adpcmMemLen=memPos+256; + adpcmMemLen=memPos+256; - // phrase book - for (int i=0; isong.sample[i]; - int endPos=sampleOffVOX[i]+s->lengthVOX; - adpcmMem[i*8]=(sampleOffVOX[i]>>16)&0xff; - adpcmMem[1+i*8]=(sampleOffVOX[i]>>8)&0xff; - adpcmMem[2+i*8]=(sampleOffVOX[i])&0xff; - adpcmMem[3+i*8]=(endPos>>16)&0xff; - adpcmMem[4+i*8]=(endPos>>8)&0xff; - adpcmMem[5+i*8]=(endPos)&0xff; + // phrase book + for (int i=0; isong.sampleLen; i++) { + DivSample* s=parent->song.sample[i]; + int endPos=sampleOffVOX[i]+s->lengthVOX; + for (int b=0; b<4; b++) { + unsigned int bankedAddr=(bankedPhrase[i].bank<<16)+(b<<8)+(bankedPhrase[i].phrase*8); + adpcmMem[bankedAddr]=b; + adpcmMem[bankedAddr+1]=(sampleOffVOX[i]>>8)&0xff; + adpcmMem[bankedAddr+2]=(sampleOffVOX[i])&0xff; + adpcmMem[bankedAddr+3]=b; + adpcmMem[bankedAddr+4]=(endPos>>8)&0xff; + adpcmMem[bankedAddr+5]=(endPos)&0xff; + } + } + } else { + int sampleCount=parent->song.sampleLen; + if (sampleCount>127) sampleCount=127; + for (int i=0; isong.sample[i]; + if (!s->renderOn[0][sysID]) { + sampleOffVOX[i]=0; + continue; + } + + int paddedLen=s->lengthVOX; + if (memPos>=getSampleMemCapacity(0)) { + logW("out of ADPCM memory for sample %d!",i); + break; + } + if (memPos+paddedLen>=getSampleMemCapacity(0)) { + memcpy(adpcmMem+memPos,s->dataVOX,getSampleMemCapacity(0)-memPos); + logW("out of ADPCM memory for sample %d!",i); + } else { + memcpy(adpcmMem+memPos,s->dataVOX,paddedLen); + sampleLoaded[i]=true; + } + sampleOffVOX[i]=memPos; + memPos+=paddedLen; + } + adpcmMemLen=memPos+256; + + // phrase book + for (int i=0; isong.sample[i]; + int endPos=sampleOffVOX[i]+s->lengthVOX; + adpcmMem[i*8]=(sampleOffVOX[i]>>16)&0xff; + adpcmMem[1+i*8]=(sampleOffVOX[i]>>8)&0xff; + adpcmMem[2+i*8]=(sampleOffVOX[i])&0xff; + adpcmMem[3+i*8]=(endPos>>16)&0xff; + adpcmMem[4+i*8]=(endPos>>8)&0xff; + adpcmMem[5+i*8]=(endPos)&0xff; + } } } void DivPlatformMSM6295::setFlags(const DivConfig& flags) { rateSelInit=flags.getBool("rateSel",false); + isBanked=flags.getBool("isBanked",false); switch (flags.getInt("clockSel",0)) { case 1: chipClock=4224000/4; @@ -454,11 +540,12 @@ void DivPlatformMSM6295::setFlags(const DivConfig& flags) { rWrite(12,!rateSelInit); rateSel=rateSelInit; } + rWrite(14,isBanked); } int DivPlatformMSM6295::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) { parent=p; - adpcmMem=new unsigned char[getSampleMemCapacity(0)]; + adpcmMem=new unsigned char[16777216]; adpcmMemLen=0; dumpWrites=false; skipRegisterWrites=false; diff --git a/src/engine/platform/msm6295.h b/src/engine/platform/msm6295.h index dfa59a0c..041d3686 100644 --- a/src/engine/platform/msm6295.h +++ b/src/engine/platform/msm6295.h @@ -49,7 +49,6 @@ class DivPlatformMSM6295: public DivDispatch, public vgsound_emu_mem_intf { }; FixedQueue writes; msm6295_core msm; - unsigned char lastBusy; unsigned char* adpcmMem; size_t adpcmMemLen; @@ -58,7 +57,16 @@ class DivPlatformMSM6295: public DivDispatch, public vgsound_emu_mem_intf { int delay, updateOsc; - bool rateSel=false, rateSelInit=false; + bool rateSel=false, rateSelInit=false, isBanked=false; + + unsigned int bank[4]; + struct BankedPhrase { + unsigned char bank=0; + unsigned char phrase=0; + BankedPhrase(): + bank(0), + phrase(0) {} + } bankedPhrase[256]; friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); diff --git a/src/gui/debug.cpp b/src/gui/debug.cpp index df634f1e..8436e661 100644 --- a/src/gui/debug.cpp +++ b/src/gui/debug.cpp @@ -55,6 +55,7 @@ #include "../engine/platform/pv1000.h" #include "../engine/platform/k053260.h" #include "../engine/platform/c140.h" +#include "../engine/platform/msm6295.h" #include "../engine/platform/dummy.h" #define COMMON_CHIP_DEBUG \ @@ -554,6 +555,18 @@ void putDispatchChip(void* data, int type) { COMMON_CHIP_DEBUG_BOOL; break; } + case DIV_SYSTEM_MSM6295: { + DivPlatformMSM6295* ch=(DivPlatformMSM6295*)data; + ImGui::Text("> MSM6295"); + COMMON_CHIP_DEBUG; + ImGui::Text("- delay: %d",ch->delay); + ImGui::Text("- updateOsc: %d",ch->updateOsc); + COMMON_CHIP_DEBUG_BOOL; + ImGui::TextColored(ch->rateSel?colorOn:colorOff,">> RateSel"); + ImGui::TextColored(ch->rateSelInit?colorOn:colorOff,">> rateSelInit"); + ImGui::TextColored(ch->isBanked?colorOn:colorOff,">> IsBanked"); + break; + } default: ImGui::Text("Unimplemented chip! Help!"); break; @@ -1092,6 +1105,15 @@ void putDispatchChan(void* data, int chanNum, int type) { ImGui::TextColored(ch->setPos?colorOn:colorOff,">> SetPos"); break; } + case DIV_SYSTEM_MSM6295: { + DivPlatformMSM6295::Channel* ch=(DivPlatformMSM6295::Channel*)data; + ImGui::Text("> MSM6295"); + COMMON_CHAN_DEBUG; + ImGui::Text("* Sample: %d",ch->sample); + COMMON_CHAN_DEBUG_BOOL; + ImGui::TextColored(ch->furnacePCM?colorOn:colorOff,">> FurnacePCM"); + break; + } default: ImGui::Text("Unimplemented chip! Help!"); break; diff --git a/src/gui/sysConf.cpp b/src/gui/sysConf.cpp index f2358312..87d94ec0 100644 --- a/src/gui/sysConf.cpp +++ b/src/gui/sysConf.cpp @@ -1349,6 +1349,7 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo case DIV_SYSTEM_MSM6295: { int clockSel=flags.getInt("clockSel",0); bool rateSel=flags.getBool("rateSel",false); + bool isBanked=flags.getBool("isBanked",false); ImGui::Text("Clock rate:"); ImGui::Indent(); @@ -1425,10 +1426,15 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo } ImGui::Unindent(); + if (ImGui::Checkbox("Bankswitched (NMK112)",&isBanked)) { + altered=true; + } + if (altered) { e->lockSave([&]() { flags.set("clockSel",clockSel); flags.set("rateSel",rateSel); + flags.set("isBanked",isBanked); }); } break;