diff --git a/src/engine/cmdStream.cpp b/src/engine/cmdStream.cpp index f18c78646..8b36ecf8e 100644 --- a/src/engine/cmdStream.cpp +++ b/src/engine/cmdStream.cpp @@ -121,6 +121,7 @@ bool DivCSPlayer::tick() { stream.readC(); break; case 0xf1: // nop + break; case 0xf7: command=stream.readC(); break; diff --git a/src/engine/cmdStreamOps.cpp b/src/engine/cmdStreamOps.cpp index 0cbfb7d0a..917221c23 100644 --- a/src/engine/cmdStreamOps.cpp +++ b/src/engine/cmdStreamOps.cpp @@ -19,6 +19,7 @@ #include "engine.h" #include "../ta-log.h" +#include /* #define WRITE_TICK(x) \ @@ -245,7 +246,6 @@ 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! unsigned int delta=destAddr-sourceAddr; for (size_t i=0; itell()); @@ -341,6 +340,13 @@ SafeWriter* DivEngine::saveCommand() { if ((ticks-((tempoAccum+virtualTempoN)/virtualTempoD))<=0) { logI("loop is on tick %d",tick); loopTick=tick; + // marker + for (int i=0; iwriteC(0xf0); + chanStream[i]->writeC(0x00); + chanStream[i]->writeC(0x00); + chanStream[i]->writeC(0x00); + } } } } @@ -400,6 +406,12 @@ SafeWriter* DivEngine::saveCommand() { logV("%d",tick); cmdStreamEnabled=oldCmdStreamEnabled; + // PASS 1: find sub-blocks and isolate them + + // PASS 2: find loops + + // PASS 3: optimize command calls + /* int sortCand=-1; int sortPos=0; while (sortPos<16) { @@ -419,10 +431,34 @@ SafeWriter* DivEngine::saveCommand() { sortedCmd[sortPos]=sortCand; cmdPopularity[sortCand]=0; sortPos++; + }*/ + + // PASS 4: condense delays + // calculate delay usage + for (int h=0; hgetFinalBuf(); + int delayCount=0; + for (size_t i=0; isize();) { + int insLen=getInsLength(buf[i]); + if (insLen<1) { + logE("INS %x NOT IMPLEMENTED...",buf[i]); + break; + } + if (buf[i]==0xfe) { + delayCount++; + } else { + if (delayCount>1 && delayCount<=255) { + delayPopularity[delayCount]++; + } + delayCount=0; + } + i+=insLen; + } } - sortCand=-1; - sortPos=0; + // preset delays + int sortCand=-1; + int sortPos=0; while (sortPos<16) { sortCand=-1; for (int i=0; i<256; i++) { @@ -442,6 +478,120 @@ SafeWriter* DivEngine::saveCommand() { sortPos++; } + + // condense delays + for (int h=0; hgetFinalBuf(); + int delayPos=-1; + int delayCount=0; + int delayLast=0; + for (size_t i=0; isize();) { + int insLen=getInsLength(buf[i]); + if (insLen<1) { + logE("INS %x NOT IMPLEMENTED...",buf[i]); + break; + } + if (buf[i]==0xfe) { + if (delayPos==-1) delayPos=i; + delayCount++; + delayLast=i; + } else { + // finish the last delay if any + if (delayPos!=-1) { + if (delayCount>1) { + if (delayLast255) { + buf[delayPos++]=0xfc; + buf[delayPos++]=delayCount&0xff; + buf[delayPos++]=(delayCount>>8)&0xff; + } else { + bool foundShort=false; + for (int j=0; j<16; j++) { + if (sortedDelay[j]==delayCount) { + buf[delayPos++]=0xe0+j; + foundShort=true; + break; + } + } + if (!foundShort) { + buf[delayPos++]=0xfd; + buf[delayPos++]=delayCount; + } + } + // fill with nop + for (int j=delayPos; j<=delayLast; j++) { + buf[j]=0xf1; + } + } + } + delayPos=-1; + delayCount=0; + } + } + i+=insLen; + } + } + + // PASS 5: remove all remaining nop's + // this includes modifying call addresses to compensate + for (int h=0; h addrTable; + SafeWriter* oldStream=chanStream[h]; + unsigned char* buf=oldStream->getFinalBuf(); + chanStream[h]=new SafeWriter; + chanStream[h]->init(); + + // prepare address map + size_t addr=0; + for (size_t i=0; isize();) { + int insLen=getInsLength(buf[i]); + if (insLen<1) { + logE("INS %x NOT IMPLEMENTED...",buf[i]); + break; + } + addrTable[i]=addr; + if (buf[i]!=0xf1) addr+=insLen; + i+=insLen; + } + + // translate addresses + for (size_t i=0; isize();) { + int insLen=getInsLength(buf[i]); + if (insLen<1) { + logE("INS %x NOT IMPLEMENTED...",buf[i]); + break; + } + switch (buf[i]) { + case 0xf5: // call + case 0xfa: { // jmp + unsigned int addr=buf[i+1]|(buf[i+2]<<8)|(buf[i+3]<<8)|(buf[i+4]<<24); + try { + addr=addrTable[addr]; + buf[i+1]=addr&0xff; + buf[i+2]=(addr>>8)&0xff; + buf[i+3]=(addr>>16)&0xff; + buf[i+4]=(addr>>24)&0xff; + } catch (std::out_of_range& e) { + logW("address %x is not mappable!",addr); + } + break; + } + } + if (buf[i]!=0xf1) { + chanStream[h]->write(&buf[i],insLen); + } + i+=insLen; + } + + + oldStream->finish(); + delete oldStream; + } + + /* for (int i=0; ifinish(); delete oldStream; - } + }*/ + // write results for (int i=0; itell(); logI("- %d: off %x size %ld",i,chanStreamOff[i],chanStream[i]->size());