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)
|
||||
f4 | UNUSED - call symbol (32-bit index follows; only used internally)
|
||||
f5 | call sub-block (32-bit address follows)
|
||||
f6 | UNUSED
|
||||
f6 | note off + wait one tick
|
||||
f7 | full command (command and data follows)
|
||||
f8 | call sub-block (16-bit address follows)
|
||||
f9 | return from sub-block
|
||||
|
|
|
@ -210,6 +210,11 @@ bool DivCSPlayer::tick() {
|
|||
}
|
||||
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:
|
||||
command=stream.readC();
|
||||
break;
|
||||
|
|
|
@ -113,10 +113,13 @@ class DivCSPlayer {
|
|||
|
||||
struct DivCSProgress {
|
||||
int stage, count, total;
|
||||
int optCurrent, optTotal;
|
||||
DivCSProgress():
|
||||
stage(0),
|
||||
count(0),
|
||||
total(0) {}
|
||||
total(0),
|
||||
optCurrent(0),
|
||||
optTotal(0) {}
|
||||
};
|
||||
|
||||
struct DivCSOptions {
|
||||
|
|
|
@ -836,8 +836,6 @@ struct MatchBenefit {
|
|||
|
||||
#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) {
|
||||
unsigned char* buf=stream->getFinalBuf();
|
||||
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 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
|
||||
if (matches.empty()) return stream;
|
||||
|
||||
|
@ -1446,7 +1449,6 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, DivCSOptions options
|
|||
sortPos++;
|
||||
}
|
||||
|
||||
|
||||
// condense delays
|
||||
for (int h=0; h<chans; h++) {
|
||||
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
|
||||
for (int h=0; h<chans; 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++) {
|
||||
chanStreamOff[i]=globalStream->tell();
|
||||
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];
|
||||
}
|
||||
|
||||
// PASS 5: find sub-blocks and isolate them
|
||||
// PASS 6: find sub-blocks and isolate them
|
||||
if (!options.noSubBlock) {
|
||||
std::vector<SafeWriter*> subBlocks;
|
||||
size_t beforeSize=globalStream->size();
|
||||
|
@ -1579,13 +1602,13 @@ SafeWriter* DivEngine::saveCommand(DivCSProgress* progress, DivCSOptions options
|
|||
assert(!(globalStream->size()&7));
|
||||
}
|
||||
|
||||
// PASS 6: pack stream
|
||||
// PASS 7: pack stream
|
||||
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);
|
||||
|
||||
// PASS 8: find new offsets
|
||||
// PASS 9: find new offsets
|
||||
{
|
||||
unsigned char* buf=globalStream->getFinalBuf();
|
||||
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 "???";
|
||||
return fmt::sprintf("call $%.8x",(unsigned int)(buf[addr+1]|(buf[addr+2]<<8)|(buf[addr+3]<<16)|(buf[addr+4]<<24)));
|
||||
break;
|
||||
case 0xf6:
|
||||
return "offwait";
|
||||
break;
|
||||
case 0xf7: {
|
||||
if (addr+1>=bufLen) return "???";
|
||||
int cmdLen=DivCS::getCmdLength(buf[addr+1]);
|
||||
|
|
|
@ -6064,7 +6064,8 @@ bool FurnaceGUI::loop() {
|
|||
}
|
||||
} else {
|
||||
WAKE_UP;
|
||||
ImGui::Text("Exporting... %d",csProgress.count);
|
||||
ImGui::Text("Exporting...");
|
||||
ImGui::Text("%d/%d",csProgress.optCurrent,csProgress.optTotal);
|
||||
|
||||
// check whether we're done
|
||||
if (csExportDone) {
|
||||
|
|
Loading…
Reference in a new issue