new off + wait 1 command
This commit is contained in:
parent
b398108534
commit
4899513194
|
@ -109,7 +109,7 @@ hex | description
|
||||||
f3 | loop (negative offset and count follow... both are 8-bit)
|
f3 | loop (negative offset and count follow... both are 8-bit)
|
||||||
f4 | UNUSED - call symbol (32-bit index follows; only used internally)
|
f4 | UNUSED - call symbol (32-bit index follows; only used internally)
|
||||||
f5 | call sub-block (32-bit address follows)
|
f5 | call sub-block (32-bit address follows)
|
||||||
f6 | UNUSED
|
f6 | note off + wait one tick
|
||||||
f7 | full command (command and data follows)
|
f7 | full command (command and data follows)
|
||||||
f8 | call sub-block (16-bit address follows)
|
f8 | call sub-block (16-bit address follows)
|
||||||
f9 | return from sub-block
|
f9 | return from sub-block
|
||||||
|
|
|
@ -210,6 +210,11 @@ bool DivCSPlayer::tick() {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 0xf6: // note off + wait 1
|
||||||
|
e->dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF,i));
|
||||||
|
chan[i].waitTicks=1;
|
||||||
|
chan[i].lastWaitLen=chan[i].waitTicks;
|
||||||
|
break;
|
||||||
case 0xf7:
|
case 0xf7:
|
||||||
command=stream.readC();
|
command=stream.readC();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -113,10 +113,13 @@ class DivCSPlayer {
|
||||||
|
|
||||||
struct DivCSProgress {
|
struct DivCSProgress {
|
||||||
int stage, count, total;
|
int stage, count, total;
|
||||||
|
int optCurrent, optTotal;
|
||||||
DivCSProgress():
|
DivCSProgress():
|
||||||
stage(0),
|
stage(0),
|
||||||
count(0),
|
count(0),
|
||||||
total(0) {}
|
total(0),
|
||||||
|
optCurrent(0),
|
||||||
|
optTotal(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DivCSOptions {
|
struct DivCSOptions {
|
||||||
|
|
|
@ -836,8 +836,6 @@ struct MatchBenefit {
|
||||||
|
|
||||||
#define MIN_MATCH_SIZE 32
|
#define MIN_MATCH_SIZE 32
|
||||||
|
|
||||||
// TODO:
|
|
||||||
// - see if we can optimize even more
|
|
||||||
SafeWriter* findSubBlocks(SafeWriter* stream, std::vector<SafeWriter*>& subBlocks, unsigned char* speedDial, DivCSProgress* progress) {
|
SafeWriter* findSubBlocks(SafeWriter* stream, std::vector<SafeWriter*>& subBlocks, unsigned char* speedDial, DivCSProgress* progress) {
|
||||||
unsigned char* buf=stream->getFinalBuf();
|
unsigned char* buf=stream->getFinalBuf();
|
||||||
size_t matchSize=MIN_MATCH_SIZE;
|
size_t matchSize=MIN_MATCH_SIZE;
|
||||||
|
@ -869,6 +867,11 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector<SafeWriter*>& subBlock
|
||||||
logD("%d candidates",(int)matches.size());
|
logD("%d candidates",(int)matches.size());
|
||||||
logD("%d origs",(int)origs.size());
|
logD("%d origs",(int)origs.size());
|
||||||
|
|
||||||
|
if (progress!=NULL) {
|
||||||
|
if ((int)matches.size()>progress->optTotal) progress->optTotal=matches.size();
|
||||||
|
progress->optCurrent=matches.size();
|
||||||
|
}
|
||||||
|
|
||||||
// quit if there isn't anything
|
// quit if there isn't anything
|
||||||
if (matches.empty()) return stream;
|
if (matches.empty()) return stream;
|
||||||
|
|
||||||
|
@ -1446,7 +1449,6 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, DivCSOptions options
|
||||||
sortPos++;
|
sortPos++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// condense delays
|
// condense delays
|
||||||
for (int h=0; h<chans; h++) {
|
for (int h=0; h<chans; h++) {
|
||||||
unsigned char* buf=chanStream[h]->getFinalBuf();
|
unsigned char* buf=chanStream[h]->getFinalBuf();
|
||||||
|
@ -1500,13 +1502,34 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, DivCSOptions options
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// PASS 3: remove nop's
|
// PASS 3: note off + one-tick wait
|
||||||
|
// optimize one-tick gaps sometimes used in songs
|
||||||
|
for (int h=0; h<chans; h++) {
|
||||||
|
unsigned char* buf=chanStream[h]->getFinalBuf();
|
||||||
|
if (chanStream[h]->size()<8) continue;
|
||||||
|
for (size_t i=0; i<chanStream[h]->size()-8; i+=8) {
|
||||||
|
// find note off
|
||||||
|
if (buf[i]==0xb5) {
|
||||||
|
// check for contiguous wait 1
|
||||||
|
if (buf[i+8]==0xfe) {
|
||||||
|
// turn it into 0xf6 (note off + wait 1) and change the next one to nop
|
||||||
|
buf[i]=0xf6;
|
||||||
|
buf[i+8]=0xf1;
|
||||||
|
|
||||||
|
// skip the next instruction
|
||||||
|
i+=8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// PASS 4: remove nop's
|
||||||
// this includes modifying call addresses to compensate
|
// this includes modifying call addresses to compensate
|
||||||
for (int h=0; h<chans; h++) {
|
for (int h=0; h<chans; h++) {
|
||||||
chanStream[h]=stripNops(chanStream[h]);
|
chanStream[h]=stripNops(chanStream[h]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PASS 4: put all channels together
|
// PASS 5: put all channels together
|
||||||
for (int i=0; i<chans; i++) {
|
for (int i=0; i<chans; i++) {
|
||||||
chanStreamOff[i]=globalStream->tell();
|
chanStreamOff[i]=globalStream->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());
|
||||||
|
@ -1516,7 +1539,7 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, DivCSOptions options
|
||||||
delete chanStream[i];
|
delete chanStream[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// PASS 5: find sub-blocks and isolate them
|
// PASS 6: find sub-blocks and isolate them
|
||||||
if (!options.noSubBlock) {
|
if (!options.noSubBlock) {
|
||||||
std::vector<SafeWriter*> subBlocks;
|
std::vector<SafeWriter*> subBlocks;
|
||||||
size_t beforeSize=globalStream->size();
|
size_t beforeSize=globalStream->size();
|
||||||
|
@ -1579,13 +1602,13 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, DivCSOptions options
|
||||||
assert(!(globalStream->size()&7));
|
assert(!(globalStream->size()&7));
|
||||||
}
|
}
|
||||||
|
|
||||||
// PASS 6: pack stream
|
// PASS 7: pack stream
|
||||||
globalStream=packStream(globalStream,sortedCmd);
|
globalStream=packStream(globalStream,sortedCmd);
|
||||||
|
|
||||||
// PASS 7: remove nop's which may be produced by 32-bit call conversion
|
// PASS 8: remove nop's which may be produced by 32-bit call conversion
|
||||||
globalStream=stripNopsPacked(globalStream,sortedCmd);
|
globalStream=stripNopsPacked(globalStream,sortedCmd);
|
||||||
|
|
||||||
// PASS 8: find new offsets
|
// PASS 9: find new offsets
|
||||||
{
|
{
|
||||||
unsigned char* buf=globalStream->getFinalBuf();
|
unsigned char* buf=globalStream->getFinalBuf();
|
||||||
for (size_t i=0; i<globalStream->size();) {
|
for (size_t i=0; i<globalStream->size();) {
|
||||||
|
|
|
@ -142,6 +142,9 @@ String disasmCmd(unsigned char* buf, size_t bufLen, unsigned int addr, unsigned
|
||||||
if (addr+4>=bufLen) return "???";
|
if (addr+4>=bufLen) return "???";
|
||||||
return fmt::sprintf("call $%.8x",(unsigned int)(buf[addr+1]|(buf[addr+2]<<8)|(buf[addr+3]<<16)|(buf[addr+4]<<24)));
|
return fmt::sprintf("call $%.8x",(unsigned int)(buf[addr+1]|(buf[addr+2]<<8)|(buf[addr+3]<<16)|(buf[addr+4]<<24)));
|
||||||
break;
|
break;
|
||||||
|
case 0xf6:
|
||||||
|
return "offwait";
|
||||||
|
break;
|
||||||
case 0xf7: {
|
case 0xf7: {
|
||||||
if (addr+1>=bufLen) return "???";
|
if (addr+1>=bufLen) return "???";
|
||||||
int cmdLen=DivCS::getCmdLength(buf[addr+1]);
|
int cmdLen=DivCS::getCmdLength(buf[addr+1]);
|
||||||
|
|
|
@ -6064,7 +6064,8 @@ bool FurnaceGUI::loop() {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
WAKE_UP;
|
WAKE_UP;
|
||||||
ImGui::Text("Exporting... %d",csProgress.count);
|
ImGui::Text("Exporting...");
|
||||||
|
ImGui::Text("%d/%d",csProgress.optCurrent,csProgress.optTotal);
|
||||||
|
|
||||||
// check whether we're done
|
// check whether we're done
|
||||||
if (csExportDone) {
|
if (csExportDone) {
|
||||||
|
|
Loading…
Reference in a new issue