diff --git a/papers/export-tech.md b/papers/export-tech.md index ef569f935..77caae46f 100644 --- a/papers/export-tech.md +++ b/papers/export-tech.md @@ -69,6 +69,8 @@ hex | description .. | ... ef | preset delay 15 ----|------------------------------------ + f0 | UNUSED - placeholder used during optimization passes (3-byte nonce follows) + f1 | no operation f4 | call symbol (16-bit index follows; only used internally) f5 | jump to sub-block (address follows) f6 | go to sub-block (32-bit offset follows) diff --git a/src/engine/cmdStream.cpp b/src/engine/cmdStream.cpp index 6942c7bf7..f18c78646 100644 --- a/src/engine/cmdStream.cpp +++ b/src/engine/cmdStream.cpp @@ -115,6 +115,12 @@ bool DivCSPlayer::tick() { case 0xc7: case 0xc8: case 0xc9: case 0xca: command=next-0xb4; break; + case 0xf0: // placeholder + stream.readC(); + stream.readC(); + stream.readC(); + break; + case 0xf1: // nop case 0xf7: command=stream.readC(); break; diff --git a/src/engine/cmdStreamOps.cpp b/src/engine/cmdStreamOps.cpp index 98a1c482e..ac39ebc27 100644 --- a/src/engine/cmdStreamOps.cpp +++ b/src/engine/cmdStreamOps.cpp @@ -22,20 +22,17 @@ /* #define WRITE_TICK(x) \ - if (!wroteTick[x]) { \ - wroteTick[x]=true; \ - if (tick-lastTick[x]>255) { \ - chanStream[x]->writeC(0xfc); \ - chanStream[x]->writeS(tick-lastTick[x]); \ - } else if (tick-lastTick[x]>1) { \ - delayPopularity[tick-lastTick[x]]++; \ - chanStream[x]->writeC(0xfd); \ - chanStream[x]->writeC(tick-lastTick[x]); \ - } else if (tick-lastTick[x]>0) { \ - chanStream[x]->writeC(0xfe); \ - } \ - lastTick[x]=tick; \ - } + if (tick-lastTick[x]>255) { \ + chanStream[x]->writeC(0xfc); \ + chanStream[x]->writeS(tick-lastTick[x]); \ + } else if (tick-lastTick[x]>1) { \ + delayPopularity[tick-lastTick[x]]++; \ + chanStream[x]->writeC(0xfd); \ + chanStream[x]->writeC(tick-lastTick[x]); \ + } else if (tick-lastTick[x]>0) { \ + chanStream[x]->writeC(0xfe); \ + } \ + lastTick[x]=tick; \ */ void writePackedCommandValues(SafeWriter* w, const DivCommand& c) { @@ -205,6 +202,10 @@ void writePackedCommandValues(SafeWriter* w, const DivCommand& c) { } } +void reloc(unsigned char* buf, size_t len, unsigned int sourceAddr, unsigned int destAddr) { + // TODO... this is important! +} + SafeWriter* DivEngine::saveCommand() { stop(); repeatPattern=false; @@ -228,7 +229,8 @@ SafeWriter* DivEngine::saveCommand() { SafeWriter* chanStream[DIV_MAX_CHANS]; unsigned int chanStreamOff[DIV_MAX_CHANS]; - bool wroteTick[DIV_MAX_CHANS]; + std::vector tickPos[DIV_MAX_CHANS]; + int loopTick=-1; memset(cmdPopularity,0,256*sizeof(int)); memset(delayPopularity,0,256*sizeof(int)); @@ -268,12 +270,22 @@ SafeWriter* DivEngine::saveCommand() { memset(lastTick,0,DIV_MAX_CHANS*sizeof(int)); while (!done) { + for (int i=0; itell()); + } + if (loopTick==-1) { + if (loopOrder==curOrder && loopRow==curRow) { + if ((ticks-((tempoAccum+virtualTempoN)/virtualTempoD))<=0) { + logI("loop is on tick %d",tick); + loopTick=tick; + } + } + } if (nextTick(false,true) || !playing) { done=true; break; } // get command stream - memset(wroteTick,0,DIV_MAX_CHANS*sizeof(bool)); if (curDivider!=divider) { curDivider=divider; chanStream[0]->writeC(0xfb); @@ -306,8 +318,23 @@ SafeWriter* DivEngine::saveCommand() { } tick++; } + if (!playing || loopTick<0) { + for (int i=0; iwriteC(0xff); + } + } else { + for (int i=0; iloopTick) { + chanStream[i]->writeC(0xfa); + chanStream[i]->writeI(tickPos[i][loopTick]); + logD("chan %d loop addr: %x",i,tickPos[i][loopTick]); + } else { + logW("chan %d unable to find loop addr!",i); + chanStream[i]->writeC(0xff); + } + } + } logV("%d",tick); - memset(wroteTick,0,DIV_MAX_CHANS*sizeof(bool)); cmdStreamEnabled=oldCmdStreamEnabled; int sortCand=-1; @@ -353,7 +380,6 @@ SafeWriter* DivEngine::saveCommand() { } for (int i=0; iwriteC(0xff); // optimize stream SafeWriter* oldStream=chanStream[i]; SafeReader* reader=oldStream->toReader(); diff --git a/src/gui/csPlayer.cpp b/src/gui/csPlayer.cpp index d35a35816..c637fe6ed 100644 --- a/src/gui/csPlayer.cpp +++ b/src/gui/csPlayer.cpp @@ -94,6 +94,41 @@ String disasmCmd(unsigned char* buf, size_t bufLen, unsigned int addr) { case 0xec: case 0xed: case 0xee: case 0xef: return fmt::sprintf("qwait (%d)",(int)(buf[addr]-0xe0)); break; + case 0xf0: + if (addr+3>=bufLen) return "???"; + return fmt::sprintf("opt %.2x%.2x%.2x",(int)buf[addr+1],(int)buf[addr+2],(int)buf[addr+3]); + break; + case 0xf1: + return "nop"; + break; + case 0xf4: + if (addr+2>=bufLen) return "???"; + return fmt::sprintf("callsym %.4x",(int)(buf[addr+1]|(buf[addr+2]<<8))); + break; + case 0xf5: + if (addr+4>=bufLen) return "???"; + return fmt::sprintf("call %.8x",(unsigned int)(buf[addr+1]|(buf[addr+2]<<8)|(buf[addr+3]<<16)|(buf[addr+4]<<24))); + break; + case 0xf6: + if (addr+4>=bufLen) return "???"; + return fmt::sprintf("callb32 %.8x",(unsigned int)(buf[addr+1]|(buf[addr+2]<<8)|(buf[addr+3]<<16)|(buf[addr+4]<<24))); + break; + case 0xf7: + return "CMD"; + break; + case 0xf8: + if (addr+2>=bufLen) return "???"; + return fmt::sprintf("callb16 %.4x",(int)(buf[addr+1]|(buf[addr+2]<<8))); + break; + case 0xf9: + return "ret"; + break; + case 0xfa: + return fmt::sprintf("jmp %.8x",(unsigned int)(buf[addr+1]|(buf[addr+2]<<8)|(buf[addr+3]<<16)|(buf[addr+4]<<24))); + break; + case 0xfb: + return fmt::sprintf("rate %.8x",(unsigned int)(buf[addr+1]|(buf[addr+2]<<8)|(buf[addr+3]<<16)|(buf[addr+4]<<24))); + break; case 0xfc: if (addr+2>=bufLen) return "???"; return fmt::sprintf("waits %d",(int)(buf[addr+1]|(buf[addr+2]<<8)));