delay condensation and nop removal
This commit is contained in:
parent
491a361392
commit
c110f87548
|
@ -121,6 +121,7 @@ bool DivCSPlayer::tick() {
|
||||||
stream.readC();
|
stream.readC();
|
||||||
break;
|
break;
|
||||||
case 0xf1: // nop
|
case 0xf1: // nop
|
||||||
|
break;
|
||||||
case 0xf7:
|
case 0xf7:
|
||||||
command=stream.readC();
|
command=stream.readC();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include "../ta-log.h"
|
#include "../ta-log.h"
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
#define WRITE_TICK(x) \
|
#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) {
|
void reloc(unsigned char* buf, size_t len, unsigned int sourceAddr, unsigned int destAddr) {
|
||||||
// TODO... this is important!
|
|
||||||
unsigned int delta=destAddr-sourceAddr;
|
unsigned int delta=destAddr-sourceAddr;
|
||||||
for (size_t i=0; i<len;) {
|
for (size_t i=0; i<len;) {
|
||||||
int insLen=getInsLength(buf[i]);
|
int insLen=getInsLength(buf[i]);
|
||||||
|
@ -329,9 +329,8 @@ SafeWriter* DivEngine::saveCommand() {
|
||||||
bool oldCmdStreamEnabled=cmdStreamEnabled;
|
bool oldCmdStreamEnabled=cmdStreamEnabled;
|
||||||
cmdStreamEnabled=true;
|
cmdStreamEnabled=true;
|
||||||
double curDivider=divider;
|
double curDivider=divider;
|
||||||
int lastTick[DIV_MAX_CHANS];
|
|
||||||
|
|
||||||
memset(lastTick,0,DIV_MAX_CHANS*sizeof(int));
|
// PASS 0: play the song and log channel command streams
|
||||||
while (!done) {
|
while (!done) {
|
||||||
for (int i=0; i<chans; i++) {
|
for (int i=0; i<chans; i++) {
|
||||||
tickPos[i].push_back(chanStream[i]->tell());
|
tickPos[i].push_back(chanStream[i]->tell());
|
||||||
|
@ -341,6 +340,13 @@ SafeWriter* DivEngine::saveCommand() {
|
||||||
if ((ticks-((tempoAccum+virtualTempoN)/virtualTempoD))<=0) {
|
if ((ticks-((tempoAccum+virtualTempoN)/virtualTempoD))<=0) {
|
||||||
logI("loop is on tick %d",tick);
|
logI("loop is on tick %d",tick);
|
||||||
loopTick=tick;
|
loopTick=tick;
|
||||||
|
// marker
|
||||||
|
for (int i=0; i<chans; i++) {
|
||||||
|
chanStream[i]->writeC(0xf0);
|
||||||
|
chanStream[i]->writeC(0x00);
|
||||||
|
chanStream[i]->writeC(0x00);
|
||||||
|
chanStream[i]->writeC(0x00);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,6 +406,12 @@ SafeWriter* DivEngine::saveCommand() {
|
||||||
logV("%d",tick);
|
logV("%d",tick);
|
||||||
cmdStreamEnabled=oldCmdStreamEnabled;
|
cmdStreamEnabled=oldCmdStreamEnabled;
|
||||||
|
|
||||||
|
// PASS 1: find sub-blocks and isolate them
|
||||||
|
|
||||||
|
// PASS 2: find loops
|
||||||
|
|
||||||
|
// PASS 3: optimize command calls
|
||||||
|
/*
|
||||||
int sortCand=-1;
|
int sortCand=-1;
|
||||||
int sortPos=0;
|
int sortPos=0;
|
||||||
while (sortPos<16) {
|
while (sortPos<16) {
|
||||||
|
@ -419,10 +431,34 @@ SafeWriter* DivEngine::saveCommand() {
|
||||||
sortedCmd[sortPos]=sortCand;
|
sortedCmd[sortPos]=sortCand;
|
||||||
cmdPopularity[sortCand]=0;
|
cmdPopularity[sortCand]=0;
|
||||||
sortPos++;
|
sortPos++;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
// PASS 4: condense delays
|
||||||
|
// calculate delay usage
|
||||||
|
for (int h=0; h<chans; h++) {
|
||||||
|
unsigned char* buf=chanStream[h]->getFinalBuf();
|
||||||
|
int delayCount=0;
|
||||||
|
for (size_t i=0; i<chanStream[h]->size();) {
|
||||||
|
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;
|
// preset delays
|
||||||
sortPos=0;
|
int sortCand=-1;
|
||||||
|
int sortPos=0;
|
||||||
while (sortPos<16) {
|
while (sortPos<16) {
|
||||||
sortCand=-1;
|
sortCand=-1;
|
||||||
for (int i=0; i<256; i++) {
|
for (int i=0; i<256; i++) {
|
||||||
|
@ -442,6 +478,120 @@ SafeWriter* DivEngine::saveCommand() {
|
||||||
sortPos++;
|
sortPos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// condense delays
|
||||||
|
for (int h=0; h<chans; h++) {
|
||||||
|
unsigned char* buf=chanStream[h]->getFinalBuf();
|
||||||
|
int delayPos=-1;
|
||||||
|
int delayCount=0;
|
||||||
|
int delayLast=0;
|
||||||
|
for (size_t i=0; i<chanStream[h]->size();) {
|
||||||
|
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 (delayLast<delayPos) {
|
||||||
|
logE("delayLast<delayPos! %d<%d",delayLast,delayPos);
|
||||||
|
} else {
|
||||||
|
// write condensed delay and fill the rest with nop
|
||||||
|
if (delayCount>255) {
|
||||||
|
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<chans; h++) {
|
||||||
|
std::unordered_map<unsigned int,unsigned int> 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; i<oldStream->size();) {
|
||||||
|
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; i<oldStream->size();) {
|
||||||
|
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; i<chans; i++) {
|
for (int i=0; i<chans; i++) {
|
||||||
// optimize stream
|
// optimize stream
|
||||||
SafeWriter* oldStream=chanStream[i];
|
SafeWriter* oldStream=chanStream[i];
|
||||||
|
@ -552,8 +702,9 @@ SafeWriter* DivEngine::saveCommand() {
|
||||||
|
|
||||||
oldStream->finish();
|
oldStream->finish();
|
||||||
delete oldStream;
|
delete oldStream;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
|
// write results
|
||||||
for (int i=0; i<chans; i++) {
|
for (int i=0; i<chans; i++) {
|
||||||
chanStreamOff[i]=w->tell();
|
chanStreamOff[i]=w->tell();
|
||||||
logI("- %d: off %x size %ld",i,chanStreamOff[i],chanStream[i]->size());
|
logI("- %d: off %x size %ld",i,chanStreamOff[i],chanStream[i]->size());
|
||||||
|
|
Loading…
Reference in a new issue