From 4281acc9dcbcbfa7f39c531e3c957bea53f3d3ac Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sat, 19 Oct 2024 14:24:26 -0500 Subject: [PATCH] VGM export: prepare to implement 30xx issue #1798 --- src/engine/dispatch.h | 9 ++++++ src/engine/vgmOps.cpp | 74 ++++++++++++++++++++++++------------------- 2 files changed, 50 insertions(+), 33 deletions(-) diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 273c58957..fa57dda44 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -394,9 +394,18 @@ struct DivRegWrite { struct DivDelayedWrite { int time; + // this variable is internal. + // it is used by VGM export to make sure these writes are in order. + // do not change. + int order; DivRegWrite write; + DivDelayedWrite(int t, int o, unsigned int a, unsigned int v): + time(t), + order(o), + write(a,v) {} DivDelayedWrite(int t, unsigned int a, unsigned int v): time(t), + order(0), write(a,v) {} }; diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index 1ec5125ed..932155510 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -2679,17 +2679,21 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p } } } - // get register dumps + + // calculate number of samples in this tick + int totalWait=cycles>>MASTER_CLOCK_PREC; + + // get register dumps and put them into delayed writes + int writeNum=0; 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,setPos,sampleOff8,sampleLen8,bankOffset[i],directStream,sampleStoppable); - writeCount++; + sortedWrites.push_back(std::pair(i,DivDelayedWrite(0,writeNum++,j.addr,j.val))); } writes.clear(); } - // check whether we need to loop - int totalWait=cycles>>MASTER_CLOCK_PREC; + + // handle direct stream writes if (directStream) { // render stream of all chips for (int i=0; i1) { - std::sort(sortedWrites.begin(),sortedWrites.end(),[](const std::pair& a, const std::pair& b) -> bool { - return a.second.time& a, const std::pair& b) -> bool { + if (a.second.time==b.second.time) { + return a.second.order& i: sortedWrites) { - if (i.second.time>lastOne) { - // write delay - int delay=i.second.time-lastOne; - if (delay>16) { - w->writeC(0x61); - w->writeS(delay); - } else if (delay>0) { - w->writeC(0x70+delay-1); - } - lastOne=i.second.time; + // write it out + int lastOne=0; + for (std::pair& i: sortedWrites) { + if (i.second.time>lastOne) { + // write delay + int delay=i.second.time-lastOne; + if (delay>16) { + w->writeC(0x61); + w->writeS(delay); + } else if (delay>0) { + w->writeC(0x70+delay-1); } - // write write - performVGMWrite(w,song.system[i.first],i.second.write,streamIDs[i.first],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i.first],pendingFreq,playingSample,setPos,sampleOff8,sampleLen8,bankOffset[i.first],directStream,sampleStoppable); - // handle global Furnace commands - - writeCount++; + lastOne=i.second.time; } - sortedWrites.clear(); - totalWait-=lastOne; - tickCount+=lastOne; + // write write + performVGMWrite(w,song.system[i.first],i.second.write,streamIDs[i.first],loopTimer,loopFreq,loopSample,sampleDir,isSecond[i.first],pendingFreq,playingSample,setPos,sampleOff8,sampleLen8,bankOffset[i.first],directStream,sampleStoppable); + writeCount++; } - } else { + sortedWrites.clear(); + totalWait-=lastOne; + tickCount+=lastOne; + } + + // handle streams + if (!directStream) { for (int i=0; i=0) { loopTimer[i]-=(loopFreq[i]/44100.0)*(double)totalWait; @@ -2786,6 +2793,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p } } } + // write wait if (totalWait>0) { if (totalWait==735) {