HOW IS THIS LESS OPTIMAL - DO NOT USE!!!
THIS FAILS HORRIBLY... I am trying to do a global search
This commit is contained in:
parent
d4e34db5b6
commit
876bb3cc5c
|
@ -578,6 +578,38 @@ int estimateBlockSize(unsigned char* buf, size_t len, unsigned char* speedDial)
|
||||||
return ret;
|
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<len; i+=8) {
|
||||||
|
switch (buf[i]) {
|
||||||
|
case 0xf5: // calli
|
||||||
|
case 0xfa: { // jmp
|
||||||
|
unsigned int addr=buf[i+1]|(buf[i+2]<<8)|(buf[i+3]<<16)|(buf[i+4]<<24);
|
||||||
|
addr+=delta;
|
||||||
|
buf[i+1]=addr&0xff;
|
||||||
|
buf[i+2]=(addr>>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) {
|
void reloc(unsigned char* buf, size_t len, unsigned int sourceAddr, unsigned int destAddr, unsigned char* speedDial) {
|
||||||
unsigned int delta=destAddr-sourceAddr;
|
unsigned int delta=destAddr-sourceAddr;
|
||||||
|
@ -997,6 +1029,7 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, unsigned int disable
|
||||||
unsigned char sortedCmd[16];
|
unsigned char sortedCmd[16];
|
||||||
unsigned char sortedDelay[16];
|
unsigned char sortedDelay[16];
|
||||||
|
|
||||||
|
SafeWriter* globalStream;
|
||||||
SafeWriter* chanStream[DIV_MAX_CHANS];
|
SafeWriter* chanStream[DIV_MAX_CHANS];
|
||||||
unsigned int chanStreamOff[DIV_MAX_CHANS];
|
unsigned int chanStreamOff[DIV_MAX_CHANS];
|
||||||
std::vector<size_t> tickPos[DIV_MAX_CHANS];
|
std::vector<size_t> tickPos[DIV_MAX_CHANS];
|
||||||
|
@ -1014,6 +1047,9 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, unsigned int disable
|
||||||
SafeWriter* w=new SafeWriter;
|
SafeWriter* w=new SafeWriter;
|
||||||
w->init();
|
w->init();
|
||||||
|
|
||||||
|
globalStream=new SafeWriter;
|
||||||
|
globalStream->init();
|
||||||
|
|
||||||
// write header
|
// write header
|
||||||
w->write("FCS",4);
|
w->write("FCS",4);
|
||||||
w->writeI(chans);
|
w->writeI(chans);
|
||||||
|
@ -1038,6 +1074,18 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, unsigned int disable
|
||||||
double curDivider=divider;
|
double curDivider=divider;
|
||||||
|
|
||||||
// PASS 0: play the song and log channel command streams
|
// PASS 0: play the song and log channel command streams
|
||||||
|
// song beginning marker
|
||||||
|
for (int i=0; i<chans; i++) {
|
||||||
|
chanStream[i]->writeC(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) {
|
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());
|
||||||
|
@ -1047,12 +1095,12 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, unsigned int disable
|
||||||
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
|
// loop marker
|
||||||
for (int i=0; i<chans; i++) {
|
for (int i=0; i<chans; i++) {
|
||||||
chanStream[i]->writeC(0xf0);
|
chanStream[i]->writeC(0xf0);
|
||||||
|
chanStream[i]->writeC(0x01);
|
||||||
chanStream[i]->writeC(0x00);
|
chanStream[i]->writeC(0x00);
|
||||||
chanStream[i]->writeC(0x00);
|
chanStream[i]->writeC(i);
|
||||||
chanStream[i]->writeC(0x00);
|
|
||||||
// padding
|
// padding
|
||||||
chanStream[i]->writeC(0x00);
|
chanStream[i]->writeC(0x00);
|
||||||
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]);
|
chanStream[h]=stripNops(chanStream[h]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PASS 4: find sub-blocks and isolate them
|
// PASS 4: put all channels together
|
||||||
if (!(disablePasses&4)) {
|
|
||||||
for (int h=0; h<chans; h++) {
|
|
||||||
std::vector<SafeWriter*> 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<subBlocksLen; i++) {
|
|
||||||
SafeWriter* newBlock=findSubBlocks(subBlocks[i],subBlocks,sortedCmd);
|
|
||||||
subBlocks[i]=newBlock;
|
|
||||||
}
|
|
||||||
subBlocksLast=subBlocksLen;
|
|
||||||
subBlocksLen=subBlocks.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert sub-blocks and resolve symbols
|
|
||||||
logI("%d sub-blocks total",(int)subBlocks.size());
|
|
||||||
std::vector<size_t> blockOff;
|
|
||||||
chanStream[h]->seek(0,SEEK_END);
|
|
||||||
for (size_t i=0; i<subBlocks.size(); i++) {
|
|
||||||
SafeWriter* block=subBlocks[i];
|
|
||||||
|
|
||||||
// check whether this block is duplicate
|
|
||||||
int dupOf=-1;
|
|
||||||
for (size_t j=0; j<i; j++) {
|
|
||||||
if (subBlocks[j]->size()==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; j<chanStream[h]->size(); 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<blockOff.size()) {
|
|
||||||
// turn it into call
|
|
||||||
addr=blockOff[addr];
|
|
||||||
buf[j]=0xf8;
|
|
||||||
buf[j+1]=addr&0xff;
|
|
||||||
buf[j+2]=(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; h<chans; h++) {
|
|
||||||
chanStream[h]=stripNops(chanStream[h]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// PASS 6: pack streams
|
|
||||||
for (int h=0; h<chans; h++) {
|
|
||||||
chanStream[h]=packStream(chanStream[h],sortedCmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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());
|
||||||
reloc(chanStream[i]->getFinalBuf(),chanStream[i]->size(),0,w->tell(),sortedCmd);
|
reloc8(chanStream[i]->getFinalBuf(),chanStream[i]->size(),0,w->tell());
|
||||||
w->write(chanStream[i]->getFinalBuf(),chanStream[i]->size());
|
globalStream->write(chanStream[i]->getFinalBuf(),chanStream[i]->size());
|
||||||
chanStream[i]->finish();
|
chanStream[i]->finish();
|
||||||
delete chanStream[i];
|
delete chanStream[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PASS 5: find sub-blocks and isolate them
|
||||||
|
if (!(disablePasses&4)) {
|
||||||
|
std::vector<SafeWriter*> 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<subBlocksLen; i++) {
|
||||||
|
SafeWriter* newBlock=findSubBlocks(subBlocks[i],subBlocks,sortedCmd);
|
||||||
|
subBlocks[i]=newBlock;
|
||||||
|
}
|
||||||
|
subBlocksLast=subBlocksLen;
|
||||||
|
subBlocksLen=subBlocks.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert sub-blocks and resolve symbols
|
||||||
|
logI("%d sub-blocks total",(int)subBlocks.size());
|
||||||
|
std::vector<size_t> blockOff;
|
||||||
|
globalStream->seek(0,SEEK_END);
|
||||||
|
for (size_t i=0; i<subBlocks.size(); i++) {
|
||||||
|
SafeWriter* block=subBlocks[i];
|
||||||
|
|
||||||
|
// check whether this block is duplicate
|
||||||
|
int dupOf=-1;
|
||||||
|
for (size_t j=0; j<i; j++) {
|
||||||
|
if (subBlocks[j]->size()==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; j<globalStream->size(); 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<blockOff.size()) {
|
||||||
|
// turn it into call
|
||||||
|
addr=blockOff[addr];
|
||||||
|
buf[j]=0xf8;
|
||||||
|
buf[j+1]=addr&0xff;
|
||||||
|
buf[j+2]=(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);
|
w->seek(8,SEEK_SET);
|
||||||
for (int i=0; i<chans; i++) {
|
for (int i=0; i<chans; i++) {
|
||||||
w->writeI(chanStreamOff[i]);
|
w->writeI(chanStreamOff[i]);
|
||||||
|
|
Loading…
Reference in a new issue