From 876bb3cc5c420aed203f8a27c49536ba94dbb5e9 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Tue, 8 Apr 2025 19:52:26 -0500 Subject: [PATCH] HOW IS THIS LESS OPTIMAL - DO NOT USE!!! THIS FAILS HORRIBLY... I am trying to do a global search --- src/engine/cmdStreamOps.cpp | 248 +++++++++++++++++++++--------------- 1 file changed, 147 insertions(+), 101 deletions(-) diff --git a/src/engine/cmdStreamOps.cpp b/src/engine/cmdStreamOps.cpp index 5114b35d8..94a01e7ba 100644 --- a/src/engine/cmdStreamOps.cpp +++ b/src/engine/cmdStreamOps.cpp @@ -578,6 +578,38 @@ int estimateBlockSize(unsigned char* buf, size_t len, unsigned char* speedDial) return ret; } +void reloc8(unsigned char* buf, size_t len, unsigned int sourceAddr, unsigned int destAddr) { + unsigned int delta=destAddr-sourceAddr; + for (size_t i=0; i>8)&0xff; + buf[i+3]=(addr>>16)&0xff; + buf[i+4]=(addr>>24)&0xff; + break; + } + case 0xf8: { // call + unsigned int addr=buf[i+1]|(buf[i+2]<<8); + addr+=delta; + if (addr>0xffff) { + buf[i]=0xf5; + buf[i+1]=addr&0xff; + buf[i+2]=(addr>>8)&0xff; + buf[i+3]=(addr>>16)&0xff; + buf[i+4]=(addr>>24)&0xff; + } else { + buf[i+1]=addr&0xff; + buf[i+2]=(addr>>8)&0xff; + } + break; + } + } + } +} void reloc(unsigned char* buf, size_t len, unsigned int sourceAddr, unsigned int destAddr, unsigned char* speedDial) { unsigned int delta=destAddr-sourceAddr; @@ -997,6 +1029,7 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, unsigned int disable unsigned char sortedCmd[16]; unsigned char sortedDelay[16]; + SafeWriter* globalStream; SafeWriter* chanStream[DIV_MAX_CHANS]; unsigned int chanStreamOff[DIV_MAX_CHANS]; std::vector tickPos[DIV_MAX_CHANS]; @@ -1014,6 +1047,9 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, unsigned int disable SafeWriter* w=new SafeWriter; w->init(); + globalStream=new SafeWriter; + globalStream->init(); + // write header w->write("FCS",4); w->writeI(chans); @@ -1038,6 +1074,18 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, unsigned int disable double curDivider=divider; // PASS 0: play the song and log channel command streams + // song beginning marker + for (int i=0; iwriteC(0xf0); + chanStream[i]->writeC(0x00); + chanStream[i]->writeC(0x00); + chanStream[i]->writeC(i); + // padding + chanStream[i]->writeC(0x00); + chanStream[i]->writeC(0x00); + chanStream[i]->writeC(0x00); + chanStream[i]->writeC(0x00); + } while (!done) { for (int i=0; itell()); @@ -1047,12 +1095,12 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, unsigned int disable if ((ticks-((tempoAccum+virtualTempoN)/virtualTempoD))<=0) { logI("loop is on tick %d",tick); loopTick=tick; - // marker + // loop marker for (int i=0; iwriteC(0xf0); + chanStream[i]->writeC(0x01); chanStream[i]->writeC(0x00); - chanStream[i]->writeC(0x00); - chanStream[i]->writeC(0x00); + chanStream[i]->writeC(i); // padding chanStream[i]->writeC(0x00); chanStream[i]->writeC(0x00); @@ -1297,111 +1345,109 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, unsigned int disable chanStream[h]=stripNops(chanStream[h]); } - // PASS 4: find sub-blocks and isolate them - if (!(disablePasses&4)) { - for (int h=0; h subBlocks; - size_t beforeSize=chanStream[h]->size(); - - // 6 is the minimum size that can be reliably optimized - logI("finding sub-blocks in chan %d",h); - chanStream[h]=findSubBlocks(chanStream[h],subBlocks,sortedCmd); - // find sub-blocks within sub-blocks - size_t subBlocksLast=0; - size_t subBlocksLen=subBlocks.size(); - logI("finding sub-blocks within sub-blocks",h); - while (subBlocksLast!=subBlocksLen) { - logI("got %d blocks... starting from %d",(int)subBlocksLen,(int)subBlocksLast); - for (size_t i=subBlocksLast; i blockOff; - chanStream[h]->seek(0,SEEK_END); - for (size_t i=0; isize()==subBlocks[i]->size()) { - if (memcmp(subBlocks[j]->getFinalBuf(),subBlocks[i]->getFinalBuf(),subBlocks[j]->size())==0) { - logW("we have one"); - dupOf=j; - break; - } - } - } - - if (dupOf>=0) { - // push address of original block (discard duplicate) - blockOff.push_back(blockOff[dupOf]); - } else { - // write sub-block - blockOff.push_back(chanStream[h]->tell()); - logV("block size: %d",(int)block->size()); - assert(!(block->size()&7)); - chanStream[h]->write(block->getFinalBuf(),block->size()); - } - } - - for (SafeWriter* block: subBlocks) { - block->finish(); - delete block; - } - subBlocks.clear(); - - // resolve symbols - unsigned char* buf=chanStream[h]->getFinalBuf(); - for (size_t j=0; jsize(); j+=8) { - if (buf[j]==0xf4) { // callsym - unsigned int addr=buf[j+1]|(buf[j+2]<<8)|(buf[j+3]<<16)|(buf[j+4]<<24); - if (addr>8)&0xff; - //buf[j+3]=(addr>>16)&0xff; - //buf[j+4]=(addr>>24)&0xff; - } else { - logE("requested symbol %d is out of bounds!",addr); - } - } - } - - size_t afterSize=chanStream[h]->size(); - logI("(before: %d - after: %d)",(int)beforeSize,(int)afterSize); - assert(!(chanStream[h]->size()&7)); - } - } - - // PASS 5: remove nop's (again) - for (int h=0; htell(); logI("- %d: off %x size %ld",i,chanStreamOff[i],chanStream[i]->size()); - reloc(chanStream[i]->getFinalBuf(),chanStream[i]->size(),0,w->tell(),sortedCmd); - w->write(chanStream[i]->getFinalBuf(),chanStream[i]->size()); + reloc8(chanStream[i]->getFinalBuf(),chanStream[i]->size(),0,w->tell()); + globalStream->write(chanStream[i]->getFinalBuf(),chanStream[i]->size()); chanStream[i]->finish(); delete chanStream[i]; } + // PASS 5: find sub-blocks and isolate them + if (!(disablePasses&4)) { + std::vector subBlocks; + size_t beforeSize=globalStream->size(); + + // 6 is the minimum size that can be reliably optimized + logI("finding sub-blocks"); + globalStream=findSubBlocks(globalStream,subBlocks,sortedCmd); + // find sub-blocks within sub-blocks + size_t subBlocksLast=0; + size_t subBlocksLen=subBlocks.size(); + logI("finding sub-blocks within sub-blocks"); + while (subBlocksLast!=subBlocksLen) { + logI("got %d blocks... starting from %d",(int)subBlocksLen,(int)subBlocksLast); + for (size_t i=subBlocksLast; i blockOff; + globalStream->seek(0,SEEK_END); + for (size_t i=0; isize()==subBlocks[i]->size()) { + if (memcmp(subBlocks[j]->getFinalBuf(),subBlocks[i]->getFinalBuf(),subBlocks[j]->size())==0) { + logW("we have one"); + dupOf=j; + break; + } + } + } + + if (dupOf>=0) { + // push address of original block (discard duplicate) + blockOff.push_back(blockOff[dupOf]); + } else { + // write sub-block + blockOff.push_back(globalStream->tell()); + logV("block size: %d",(int)block->size()); + assert(!(block->size()&7)); + globalStream->write(block->getFinalBuf(),block->size()); + } + } + + for (SafeWriter* block: subBlocks) { + block->finish(); + delete block; + } + subBlocks.clear(); + + // resolve symbols + unsigned char* buf=globalStream->getFinalBuf(); + for (size_t j=0; jsize(); j+=8) { + if (buf[j]==0xf4) { // callsym + unsigned int addr=buf[j+1]|(buf[j+2]<<8)|(buf[j+3]<<16)|(buf[j+4]<<24); + if (addr>8)&0xff; + //buf[j+3]=(addr>>16)&0xff; + //buf[j+4]=(addr>>24)&0xff; + } else { + logE("requested symbol %d is out of bounds!",addr); + } + } + } + + size_t afterSize=globalStream->size(); + logI("(before: %d - after: %d)",(int)beforeSize,(int)afterSize); + assert(!(globalStream->size()&7)); + } + + // PASS 6: remove nop's (again) + globalStream=stripNops(globalStream); + + // PASS 7: pack stream + globalStream=packStream(globalStream,sortedCmd); + + // write results + // TODO: FUCK THIS + w->write(globalStream->getFinalBuf(),globalStream->size()); + w->seek(8,SEEK_SET); for (int i=0; iwriteI(chanStreamOff[i]);