From 317aca056465ef026a69a301bd75017068255ad9 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 22 Jun 2023 15:20:48 -0500 Subject: [PATCH] VGM export: NES DPCM, part 1 still does not work --- src/engine/engine.h | 2 +- src/engine/vgmOps.cpp | 38 +++++++++++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/engine/engine.h b/src/engine/engine.h index bae7daa9..85e8f641 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -489,7 +489,7 @@ class DivEngine { void processRow(int i, bool afterDelay); void nextOrder(); void nextRow(); - void performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool* sampleDir, bool isSecond, int* pendingFreq, int* playingSample, bool directStream); + void performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool* sampleDir, bool isSecond, int* pendingFreq, int* playingSample, size_t bankOffset, bool directStream); // returns true if end of song. bool nextTick(bool noAccum=false, bool inhibitLowLat=false); bool perSystemEffect(int ch, unsigned char effect, unsigned char effectVal); diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index 7a6caa67..5cf18e42 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -24,7 +24,7 @@ constexpr int MASTER_CLOCK_PREC=(sizeof(void*)==8)?8:0; -void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool* sampleDir, bool isSecond, int* pendingFreq, int* playingSample, bool directStream) { +void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write, int streamOff, double* loopTimer, double* loopFreq, int* loopSample, bool* sampleDir, bool isSecond, int* pendingFreq, int* playingSample, size_t bankOffset, bool directStream) { unsigned char baseAddr1=isSecond?0xa0:0x50; unsigned char baseAddr2=isSecond?0x80:0; unsigned short baseAddr2S=isSecond?0x8000:0; @@ -577,6 +577,28 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write break; } } + if (write.addr==0xffff0004) { // switch sample bank + switch (sys) { + case DIV_SYSTEM_NES: { + unsigned int bankAddr=bankOffset+(write.val<<14); + w->writeC(0x68); + w->writeC(0x6c); + w->writeC(0x07); + w->writeC(bankAddr&0xff); + w->writeC((bankAddr>>8)&0xff); + w->writeC((bankAddr>>16)&0xff); + w->writeC(0x00); + w->writeC(0xc0); + w->writeC(0x00); + w->writeC(0x00); + w->writeC(0x40); + w->writeC(0x00); + break; + } + default: + break; + } + } if (write.addr>=0xffff0000) { // Furnace special command if (!directStream) { unsigned char streamID=streamOff+((write.addr&0xff00)>>8); @@ -1054,7 +1076,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p bool willExport[DIV_MAX_CHIPS]; bool isSecond[DIV_MAX_CHIPS]; int streamIDs[DIV_MAX_CHIPS]; - + size_t bankOffset[DIV_MAX_CHIPS]; double loopTimer[DIV_MAX_CHANS]; double loopFreq[DIV_MAX_CHANS]; int loopSample[DIV_MAX_CHANS]; @@ -1072,6 +1094,8 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p bool mayWriteRate=(fmod(curSubSong->hz,1.0)<0.00001 || fmod(curSubSong->hz,1.0)>0.99999); int countDown=MAX(0,trailingTicks)+1; + memset(bankOffset,0,DIV_MAX_CHIPS*sizeof(size_t)); + for (int i=0; iwriteI(0); w->write(writeGA20[i]->getSampleMem(),writeGA20[i]->getSampleMemUsage()); } - // TODO if (writeNES[i]!=NULL && writeNES[i]->getSampleMemUsage()>0) { size_t howMuchWillBeWritten=writeNES[i]->getSampleMemUsage(); w->writeC(0x67); @@ -1985,6 +2012,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p w->writeI(howMuchWillBeWritten); w->write(writeNES[i]->getSampleMem(),howMuchWillBeWritten); bankOffsetNES[i]=bankOffsetNESCurrent; + bankOffset[writeNESIndex[i]]=bankOffsetNES[i]; bankOffsetNESCurrent+=howMuchWillBeWritten; } } @@ -2196,7 +2224,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p for (int i=0; i& writes=disCont[i].dispatch->getRegisterWrites(); for (DivRegWrite& j: writes) { - performVGMWrite(w,song.system[i],j,streamIDs[i],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i],pendingFreq,playingSample,directStream); + performVGMWrite(w,song.system[i],j,streamIDs[i],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i],pendingFreq,playingSample,bankOffset[i],directStream); writeCount++; } writes.clear(); @@ -2236,7 +2264,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p lastOne=i.second.time; } // write write - performVGMWrite(w,song.system[i.first],i.second.write,streamIDs[i.first],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i.first],pendingFreq,playingSample,directStream); + performVGMWrite(w,song.system[i.first],i.second.write,streamIDs[i.first],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i.first],pendingFreq,playingSample,bankOffset[i.first],directStream); // handle global Furnace commands writeCount++;