new off + wait 1 command

This commit is contained in:
tildearrow 2025-04-14 13:42:15 -05:00
parent b398108534
commit 4899513194
6 changed files with 47 additions and 12 deletions

View file

@ -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

View file

@ -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;

View file

@ -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 {

View file

@ -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();) {

View file

@ -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]);

View file

@ -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) {