From 9ada18a57a8d3ec76ea11eabfbc547ba340f0059 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 15 Jan 2023 01:20:31 -0500 Subject: [PATCH] VGM export: always write stream freq first --- src/engine/engine.h | 2 +- src/engine/vgmOps.cpp | 48 ++++++++++++++++++++++++++++++++----------- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/engine/engine.h b/src/engine/engine.h index 31edc8c85..ffa97d755 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -442,7 +442,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, 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, 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 9e4557de3..51d477554 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, 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, bool directStream) { unsigned char baseAddr1=isSecond?0xa0:0x50; unsigned char baseAddr2=isSecond?0x80:0; unsigned short baseAddr2S=isSecond?0x8000:0; @@ -541,14 +541,19 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write switch (write.addr&0xff) { case 0: // play sample if (write.valwriteC(0x95); - w->writeC(streamID); - w->writeS(write.val); // sample number - w->writeC((sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)==0)|(sampleDir[streamID]?0x10:0)); // flags - if (sample->isLoopable() && !sampleDir[streamID]) { - loopTimer[streamID]=sample->length8; - loopSample[streamID]=write.val; + if (playingSample[streamID]!=write.val) { + pendingFreq[streamID]=write.val; + } else { + DivSample* sample=song.sample[write.val]; + w->writeC(0x95); + w->writeC(streamID); + w->writeS(write.val); // sample number + w->writeC((sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)==0)|(sampleDir[streamID]?0x10:0)); // flags + if (sample->isLoopable() && !sampleDir[streamID]) { + loopTimer[streamID]=sample->length8; + loopSample[streamID]=write.val; + } + playingSample[streamID]=write.val; } } break; @@ -557,11 +562,26 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write w->writeC(streamID); w->writeI(write.val); loopFreq[streamID]=write.val; + if (pendingFreq[streamID]!=-1) { + DivSample* sample=song.sample[pendingFreq[streamID]]; + w->writeC(0x95); + w->writeC(streamID); + w->writeS(pendingFreq[streamID]); // sample number + w->writeC((sample->getLoopStartPosition(DIV_SAMPLE_DEPTH_8BIT)==0)|(sampleDir[streamID]?0x10:0)); // flags + if (sample->isLoopable() && !sampleDir[streamID]) { + loopTimer[streamID]=sample->length8; + loopSample[streamID]=write.val; + } + playingSample[streamID]=pendingFreq[streamID]; + pendingFreq[streamID]=-1; + } break; case 2: // stop sample w->writeC(0x94); w->writeC(streamID); loopSample[streamID]=-1; + playingSample[streamID]=-1; + pendingFreq[streamID]=-1; break; case 3: // set sample direction sampleDir[streamID]=write.val; @@ -979,7 +999,9 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p double loopFreq[DIV_MAX_CHANS]; int loopSample[DIV_MAX_CHANS]; bool sampleDir[DIV_MAX_CHANS]; - std::vector chipVol; + int pendingFreq[DIV_MAX_CHANS]; + int playingSample[DIV_MAX_CHANS]; + std::vector chipVol; std::vector delayedWrites[DIV_MAX_CHIPS]; std::vector> sortedWrites; @@ -987,6 +1009,8 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p loopTimer[i]=0; loopFreq[i]=0; loopSample[i]=-1; + pendingFreq[i]=-1; + playingSample[i]=-1; sampleDir[i]=false; } @@ -1991,7 +2015,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],directStream); + performVGMWrite(w,song.system[i],j,streamIDs[i],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i],pendingFreq,playingSample,directStream); writeCount++; } writes.clear(); @@ -2031,7 +2055,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],directStream); + performVGMWrite(w,song.system[i.first],i.second.write,streamIDs[i.first],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i.first],pendingFreq,playingSample,directStream); writeCount++; } sortedWrites.clear();