diff --git a/src/engine/cmdStream.cpp b/src/engine/cmdStream.cpp index f6aa7f120..7e24c7d42 100644 --- a/src/engine/cmdStream.cpp +++ b/src/engine/cmdStream.cpp @@ -24,7 +24,7 @@ #include "../ta-log.h" bool DivCSChannelState::doCall(unsigned int addr) { - if (callStackPos>=8) { + if (callStackPos>=16) { readPos=0; return false; } @@ -47,6 +47,10 @@ DivCSChannelState* DivCSPlayer::getChanState(int ch) { return &chan[ch]; } +unsigned int DivCSPlayer::getFileChans() { + return fileChans; +} + unsigned char* DivCSPlayer::getFastDelays() { return fastDelays; } @@ -471,9 +475,9 @@ bool DivCSPlayer::init() { if (memcmp(magic,"FCS",4)!=0) return false; - unsigned int chans=stream.readI(); + fileChans=stream.readI(); - for (unsigned int i=0; i=DIV_MAX_CHANS) { stream.readI(); continue; diff --git a/src/engine/cmdStream.h b/src/engine/cmdStream.h index 85d106e15..58f27a83f 100644 --- a/src/engine/cmdStream.h +++ b/src/engine/cmdStream.h @@ -39,7 +39,7 @@ struct DivCSChannelState { int portaTarget, portaSpeed; unsigned char arp, arpStage, arpTicks, loopCount; - unsigned int callStack[8]; + unsigned int callStack[16]; unsigned char callStackPos; unsigned int trace[DIV_MAX_CSTRACE]; @@ -83,12 +83,14 @@ class DivCSPlayer { unsigned char fastDelays[16]; unsigned char fastCmds[16]; unsigned char arpSpeed; + unsigned int fileChans; short vibTable[64]; public: unsigned char* getData(); size_t getDataLen(); DivCSChannelState* getChanState(int ch); + unsigned int getFileChans(); unsigned char* getFastDelays(); unsigned char* getFastCmds(); void cleanup(); @@ -101,4 +103,9 @@ class DivCSPlayer { stream(buf,len) {} }; +// command stream utilities +namespace DivCS { + int getInsLength(unsigned char ins, unsigned char ext=0); +}; + #endif diff --git a/src/engine/cmdStreamOps.cpp b/src/engine/cmdStreamOps.cpp index 589686a3c..04c5c1858 100644 --- a/src/engine/cmdStreamOps.cpp +++ b/src/engine/cmdStreamOps.cpp @@ -23,7 +23,7 @@ //#define DISABLE_BLOCK_SEARCH -int getInsLength(unsigned char ins) { +int DivCS::getInsLength(unsigned char ins, unsigned char ext) { switch (ins) { case 0xb8: // ins case 0xc0: // pre porta @@ -49,8 +49,11 @@ int getInsLength(unsigned char ins) { case 0xf0: // opt return 4; case 0xf2: // opt command - case 0xf7: // cmd + case 0xf7: { // cmd + // determine length from secondary + if (ext==0) return 0; return 0; + } case 0xf8: // callb16 case 0xfc: // waits return 3; @@ -232,6 +235,8 @@ void writePackedCommandValues(SafeWriter* w, const DivCommand& c) { } } +using namespace DivCS; + void reloc(unsigned char* buf, size_t len, unsigned int sourceAddr, unsigned int destAddr) { unsigned int delta=destAddr-sourceAddr; for (size_t i=0; i& subBlock size_t subBlockID=subBlocks.size(); int insLen=getInsLength(buf[searchPos]); bool haveSub=false; + bool onlyCalls=true; if (insLen<1) { logE("INS %x NOT IMPLEMENTED...",buf[searchPos]); @@ -333,6 +339,7 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector& subBlock // register this block for (size_t i=0; isize();) { + if (buf[searchPos+i]!=0xf4) onlyCalls=false; int insLenI=getInsLength(buf[searchPos+i]); if (insLenI<1) { logE("INS %x NOT IMPLEMENTED...",buf[searchPos+i]); @@ -356,6 +363,13 @@ SafeWriter* findSubBlocks(SafeWriter* stream, std::vector& subBlock continue; } + // don't do anything if this block only consists of calls + if (onlyCalls) { + logW("nothing but calls."); + searchPos+=insLen; + continue; + } + // find identical blocks for (size_t i=searchPos+groupLen; i+groupLensize();) { int insLenI=getInsLength(buf[i]); @@ -564,6 +578,12 @@ SafeWriter* DivEngine::saveCommand() { logV("%d",tick); cmdStreamEnabled=oldCmdStreamEnabled; + remainingLoops=-1; + playing=false; + freelance=false; + extValuePresent=false; + BUSY_END; + // PASS 1: condense delays // calculate delay usage for (int h=0; hgetChanState(i); ImGui::TableNextColumn(); - ImGui::Text("%d: $%.4x",i,state->readPos); + ImGui::Text("%d: $%.4x (>>%d)",i,state->readPos,state->callStackPos); } ImGui::TableNextRow(); @@ -303,6 +303,90 @@ void FurnaceGUI::drawCSPlayer() { ImGui::EndTabItem(); } if (ImGui::BeginTabItem(_("Disassemble"))) { + bool mustProceed=false; + ImGui::AlignTextToFramePadding(); + ImGui::Text("Address"); + ImGui::SameLine(); + ImGui::InputScalar("##DisAsmAddr",ImGuiDataType_U32,&csDisAsmAddr,0,0,"%.8X",ImGuiInputTextFlags_CharsHexadecimal); + ImGui::SameLine(); + if (ImGui::Button("Go")) { + mustProceed=true; + } + + if (mustProceed) { + csDisAsm.clear(); + unsigned char* buf=cs->getData(); + for (size_t i=csDisAsmAddr; igetDataLen();) { + int insLen=DivCS::getInsLength(buf[i]); + if (insLen<1) { + logE("INS %x NOT IMPLEMENTED...",buf[i]); + break; + } + + CSDisAsmIns ins; + ins.addr=i; + memcpy(ins.data,&buf[i],insLen); + ins.len=insLen; + csDisAsm.push_back(ins); + + i+=insLen; + } + } + + if (!csDisAsm.empty()) { + ImGui::PushFont(patFont); + if (ImGui::BeginTable("CSDisAsm",chans,ImGuiTableFlags_SizingFixedFit|ImGuiTableFlags_ScrollY)) { + ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed,oneChar.x*2.0f); + ImGui::TableSetupColumn("c1",ImGuiTableColumnFlags_WidthFixed,oneChar.x*9.0f); + ImGui::TableSetupColumn("c3",ImGuiTableColumnFlags_WidthFixed,oneChar.x*3.0f*6.0f); + ImGui::TableSetupColumn("c2",ImGuiTableColumnFlags_WidthStretch); + ImGui::TableNextRow(ImGuiTableRowFlags_Headers); + ImGui::TableNextColumn(); + ImGui::Text("pc"); + ImGui::TableNextColumn(); + ImGui::Text("addr"); + ImGui::TableNextColumn(); + ImGui::Text("hex"); + ImGui::TableNextColumn(); + ImGui::Text("ins"); + + for (CSDisAsmIns& i: csDisAsm) { + ImGui::TableNextRow(0,oneChar.y); + ImGui::TableNextColumn(); + // this is the "PC is here row"... + + + ImGui::TableNextColumn(); + ImGui::Text("%.8x",i.addr); + + ImGui::TableNextColumn(); + for (int j=0; jgetDataLen()); + ImGui::Text("%u channels",cs->getFileChans()); + ImGui::Text("preset delays:"); + for (int i=0; i<16; i++) { + ImGui::SameLine(); + ImGui::Text("%d",cs->getFastDelays()[i]); + } + ImGui::Text("speed dial commands:"); + for (int i=0; i<16; i++) { + ImGui::SameLine(); + ImGui::Text("%d",cs->getFastCmds()[i]); + } + ImGui::EndTabItem(); + } ImGui::EndTabBar(); } } diff --git a/src/gui/gui.h b/src/gui/gui.h index f60cc6c02..95032fa2c 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1613,6 +1613,17 @@ struct MappedInput { scan(s), val(v) {} }; +struct CSDisAsmIns { + unsigned int addr; + unsigned char data[8]; + unsigned char len; + CSDisAsmIns(): + addr(0), + len(0) { + memset(data,0,8); + } +}; + struct FurnaceCV; class FurnaceGUI { @@ -2743,6 +2754,8 @@ class FurnaceGUI { // command stream player ImGuiListClipper csClipper; + unsigned int csDisAsmAddr; + std::vector csDisAsm; // export options DivAudioExportOptions audioExportOptions;