diff --git a/papers/export-tech.md b/papers/export-tech.md index 1f13b639d..128cee02b 100644 --- a/papers/export-tech.md +++ b/papers/export-tech.md @@ -31,6 +31,8 @@ size | description | - 16 values ??? | pointers to channel data | - pointers are short (2-byte) or long (4-byte), set in flags + 1?? | maximum stack size per channel + | - length: channel count ??? | channel data ``` diff --git a/src/engine/cmdStreamOps.cpp b/src/engine/cmdStreamOps.cpp index ae8b8a23e..c07315421 100644 --- a/src/engine/cmdStreamOps.cpp +++ b/src/engine/cmdStreamOps.cpp @@ -19,6 +19,7 @@ #include "engine.h" #include "../ta-log.h" +#include #include int DivCS::getCmdLength(unsigned char ext) { @@ -1253,6 +1254,7 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, DivCSOptions options SafeWriter* globalStream; SafeWriter* chanStream[DIV_MAX_CHANS]; unsigned int chanStreamOff[DIV_MAX_CHANS]; + unsigned int chanStackSize[DIV_MAX_CHANS]; std::vector tickPos[DIV_MAX_CHANS]; int loopTick=-1; @@ -1260,6 +1262,7 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, DivCSOptions options memset(delayPopularity,0,256*sizeof(int)); memset(chanStream,0,DIV_MAX_CHANS*sizeof(void*)); memset(chanStreamOff,0,DIV_MAX_CHANS*sizeof(unsigned int)); + memset(chanStackSize,0,DIV_MAX_CHANS*sizeof(unsigned int)); memset(sortedCmdPopularity,0,16*sizeof(int)); memset(sortedDelayPopularity,0,16*sizeof(int)); memset(sortedCmd,0,16); @@ -1292,6 +1295,10 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, DivCSOptions options w->writeS(0); } } + // max stack sizes + for (int i=0; iwriteC(0); + } // play the song ourselves bool done=false; @@ -1682,6 +1689,62 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, DivCSOptions options reloc(globalStream->getFinalBuf(),globalStream->size(),0,w->tell(),sortedCmd,options.bigEndian); w->write(globalStream->getFinalBuf(),globalStream->size()); + // calculate max stack sizes + for (int h=0; h callStack; + unsigned int maxStackSize=0; + unsigned char* buf=w->getFinalBuf(); + bool done=false; + for (size_t i=chanStreamOff[h]; isize();) { + int insLen=getInsLength(buf[i],_EXT(buf,i,w->size()),sortedCmd); + if (insLen<1) { + logE("%d: INS %x NOT IMPLEMENTED...",h,buf[i]); + break; + } + switch (buf[i]) { + case 0xd5: { // calli + unsigned int addr=buf[i+1]|(buf[i+2]<<8)|(buf[i+3]<<16)|(buf[i+4]<<24); + callStack.push(i+insLen); + if (callStack.size()>maxStackSize) maxStackSize=callStack.size(); + i=addr; + insLen=0; + break; + } + case 0xd8: { // call + unsigned short addr=buf[i+1]|(buf[i+2]<<8); + callStack.push(i+insLen); + if (callStack.size()>maxStackSize) maxStackSize=callStack.size(); + i=addr; + insLen=0; + break; + } + case 0xd9: { // ret + if (callStack.empty()) { + logE("%d: trying to ret with empty stack!",h); + done=true; + break; + } + i=callStack.top(); + insLen=0; + callStack.pop(); + break; + } + case 0xda: // jmp + case 0xdf: // stop + done=true; + break; + } + if (maxStackSize>255) { + logE("%d: stack overflow!",h); + break; + } + if (done) break; + i+=insLen; + } + + chanStackSize[h]=maxStackSize; + } + globalStream->finish(); delete globalStream; @@ -1702,6 +1765,15 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, DivCSOptions options } } + logD("maximum stack sizes:"); + unsigned int cumulativeStackSize=0; + for (int i=0; iwriteC(chanStackSize[i]); + logD("- %d: %d",i,chanStackSize[i]); + cumulativeStackSize+=chanStackSize[i]; + } + logD("(total stack size: %d)",cumulativeStackSize); + logD("delay popularity:"); w->seek(8,SEEK_SET); for (int i=0; i<16; i++) {