diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index c9d49861d..134230cbf 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -292,6 +292,12 @@ class DivDispatch { */ virtual void poke(std::vector& wlist); + /** + * get available registers. + * @return an array of C strings, terminated by NULL; or NULL if none available. + */ + virtual const char** getRegisterSheet(); + /** * initialize this DivDispatch. * @param parent the parent DivEngine. diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index be97b86d2..210950e88 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -4775,6 +4775,35 @@ void DivEngine::stop() { isBusy.unlock(); } +void DivEngine::halt() { + isBusy.lock(); + halted=true; + isBusy.unlock(); +} + +void DivEngine::resume() { + isBusy.lock(); + halted=false; + haltOn=DIV_HALT_NONE; + isBusy.unlock(); +} + +void DivEngine::haltWhen(DivHaltPositions when) { + isBusy.lock(); + halted=false; + haltOn=when; + isBusy.unlock(); +} + +bool DivEngine::isHalted() { + return halted; +} + +const char** DivEngine::getRegisterSheet(int sys) { + if (sys<0 || sys>=song.systemLen) return NULL; + return disCont[sys].dispatch->getRegisterSheet(); +} + void DivEngine::recalcChans() { chans=0; int chanIndex=0; diff --git a/src/engine/engine.h b/src/engine/engine.h index 86e708a78..f851e82c4 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -33,6 +33,14 @@ enum DivAudioExportModes { DIV_EXPORT_MODE_MANY_CHAN }; +enum DivHaltPositions { + DIV_HALT_NONE=0, + DIV_HALT_TICK, + DIV_HALT_ROW, + DIV_HALT_PATTERN, + DIV_HALT_BREAKPOINT +}; + struct DivChannelState { std::vector delayed; int note, oldNote, pitch, portaSpeed, portaNote; @@ -139,12 +147,14 @@ class DivEngine { bool repeatPattern; bool metronome; bool exporting; + bool halted; int ticks, curRow, curOrder, remainingLoops, nextSpeed, divider; int cycles, clockDrift; int changeOrd, changePos, totalSeconds, totalTicks, totalTicksR, totalCmds, lastCmds, cmdsPerSecond, globalPitch; unsigned char extValue; unsigned char speed1, speed2; DivStatusView view; + DivHaltPositions haltOn; DivChannelState chan[DIV_MAX_CHANS]; DivAudioEngines audioEngine; DivAudioExportModes exportMode; @@ -483,6 +493,21 @@ class DivEngine { // set metronome void setMetronome(bool enable); + // halt now + void halt(); + + // resume from halt + void resume(); + + // halt on next something + void haltWhen(DivHaltPositions when); + + // is engine halted + bool isHalted(); + + // get register cheatsheet + const char** getRegisterSheet(int sys); + // public render samples void renderSamplesP(); @@ -542,6 +567,7 @@ class DivEngine { repeatPattern(false), metronome(false), exporting(false), + halted(false), ticks(0), curRow(0), curOrder(0), @@ -562,6 +588,7 @@ class DivEngine { speed1(3), speed2(3), view(DIV_STATUS_NOTHING), + haltOn(DIV_HALT_NONE), audioEngine(DIV_AUDIO_NULL), samp_bbInLen(0), samp_temp(0), diff --git a/src/engine/platform/abstract.cpp b/src/engine/platform/abstract.cpp index abfb843c5..369b2a059 100644 --- a/src/engine/platform/abstract.cpp +++ b/src/engine/platform/abstract.cpp @@ -86,6 +86,10 @@ void DivDispatch::poke(std::vector& wlist) { } +const char** DivDispatch::getRegisterSheet() { + return NULL; +} + int DivDispatch::init(DivEngine* p, int channels, int sugRate, unsigned int flags) { return 0; } diff --git a/src/engine/platform/amiga.cpp b/src/engine/platform/amiga.cpp index 83a2e9745..12ab18a5b 100644 --- a/src/engine/platform/amiga.cpp +++ b/src/engine/platform/amiga.cpp @@ -40,6 +40,10 @@ const char* regCheatSheetAmiga[]={ NULL }; +const char** DivPlatformAmiga::getRegisterSheet() { + return regCheatSheetAmiga; +} + void DivPlatformAmiga::acquire(short* bufL, short* bufR, size_t start, size_t len) { for (size_t h=start; h& wlist); + const char** getRegisterSheet(); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); ~DivPlatformArcade(); diff --git a/src/engine/platform/ay.cpp b/src/engine/platform/ay.cpp index e2edfc5e8..b45749602 100644 --- a/src/engine/platform/ay.cpp +++ b/src/engine/platform/ay.cpp @@ -29,6 +29,10 @@ const char* regCheatSheetAY[]={ NULL }; +const char** DivPlatformAY8910::getRegisterSheet() { + return regCheatSheetAY; +} + void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t len) { if (ayBufLen& wlist); + const char** getRegisterSheet(); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); }; diff --git a/src/engine/platform/ay8930.cpp b/src/engine/platform/ay8930.cpp index 02c4855c8..9bbc8084f 100644 --- a/src/engine/platform/ay8930.cpp +++ b/src/engine/platform/ay8930.cpp @@ -41,6 +41,10 @@ const char* regCheatSheetAY8930[]={ NULL }; +const char** DivPlatformAY8930::getRegisterSheet() { + return regCheatSheetAY8930; +} + void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t len) { if (ayBufLen& wlist); + const char** getRegisterSheet(); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); }; diff --git a/src/engine/platform/c64.cpp b/src/engine/platform/c64.cpp index d7f98a2b2..a8e6f95d9 100644 --- a/src/engine/platform/c64.cpp +++ b/src/engine/platform/c64.cpp @@ -39,6 +39,10 @@ const char* regCheatSheetSID[]={ NULL }; +const char** DivPlatformC64::getRegisterSheet() { + return regCheatSheetSID; +} + void DivPlatformC64::acquire(short* bufL, short* bufR, size_t start, size_t len) { for (size_t i=start; i& wlist); + const char** getRegisterSheet(); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void setChipModel(bool is6581); void quit(); diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index fc5f7d9fe..9809aa23b 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -38,6 +38,10 @@ const char* regCheatSheetGB[]={ NULL }; +const char** DivPlatformGB::getRegisterSheet() { + return regCheatSheetGB; +} + void DivPlatformGB::acquire(short* bufL, short* bufR, size_t start, size_t len) { for (size_t i=start; i& wlist); + const char** getRegisterSheet(); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); ~DivPlatformGB(); diff --git a/src/engine/platform/nes.cpp b/src/engine/platform/nes.cpp index 8105740d0..98d3ea894 100644 --- a/src/engine/platform/nes.cpp +++ b/src/engine/platform/nes.cpp @@ -32,6 +32,10 @@ const char* regCheatSheetNES[]={ NULL }; +const char** DivPlatformNES::getRegisterSheet() { + return regCheatSheetNES; +} + void DivPlatformNES::acquire(short* bufL, short* bufR, size_t start, size_t len) { for (size_t i=start; i& wlist); + const char** getRegisterSheet(); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); ~DivPlatformNES(); diff --git a/src/engine/platform/pce.cpp b/src/engine/platform/pce.cpp index 175c66b00..fe246f540 100644 --- a/src/engine/platform/pce.cpp +++ b/src/engine/platform/pce.cpp @@ -29,6 +29,10 @@ const char* regCheatSheetPCE[]={ NULL }; +const char** DivPlatformPCE::getRegisterSheet() { + return regCheatSheetPCE; +} + void DivPlatformPCE::acquire(short* bufL, short* bufR, size_t start, size_t len) { for (size_t h=start; h& wlist); + const char** getRegisterSheet(); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); ~DivPlatformPCE(); diff --git a/src/engine/platform/saa.cpp b/src/engine/platform/saa.cpp index c2cb7224c..6e23569c2 100644 --- a/src/engine/platform/saa.cpp +++ b/src/engine/platform/saa.cpp @@ -33,6 +33,10 @@ const char* regCheatSheetSAA[]={ NULL }; +const char** DivPlatformSAA1099::getRegisterSheet() { + return regCheatSheetSAA; +} + void DivPlatformSAA1099::acquire(short* bufL, short* bufR, size_t start, size_t len) { if (saaBufLen& wlist); + const char** getRegisterSheet(); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); }; diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index 57f346469..e1c806770 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -11,6 +11,10 @@ const char* regCheatSheetSN[]={ NULL }; +const char** DivPlatformSMS::getRegisterSheet() { + return regCheatSheetSN; +} + void DivPlatformSMS::acquire(short* bufL, short* bufR, size_t start, size_t len) { sn->sound_stream_update(bufL+start,len); } diff --git a/src/engine/platform/sms.h b/src/engine/platform/sms.h index aa8725e70..5eced7ed6 100644 --- a/src/engine/platform/sms.h +++ b/src/engine/platform/sms.h @@ -50,6 +50,7 @@ class DivPlatformSMS: public DivDispatch { void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); + const char** getRegisterSheet(); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); ~DivPlatformSMS(); diff --git a/src/engine/platform/tia.cpp b/src/engine/platform/tia.cpp index d3bff8e48..e29e01009 100644 --- a/src/engine/platform/tia.cpp +++ b/src/engine/platform/tia.cpp @@ -15,6 +15,10 @@ const char* regCheatSheetTIA[]={ NULL }; +const char** DivPlatformTIA::getRegisterSheet() { + return regCheatSheetTIA; +} + void DivPlatformTIA::acquire(short* bufL, short* bufR, size_t start, size_t len) { tia.process(bufL+start,len); } diff --git a/src/engine/platform/tia.h b/src/engine/platform/tia.h index a0a9bf21f..b31f4b57c 100644 --- a/src/engine/platform/tia.h +++ b/src/engine/platform/tia.h @@ -37,6 +37,7 @@ class DivPlatformTIA: public DivDispatch { void notifyInsDeletion(void* ins); void poke(unsigned int addr, unsigned short val); void poke(std::vector& wlist); + const char** getRegisterSheet(); int init(DivEngine* parent, int channels, int sugRate, unsigned int flags); void quit(); }; diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index da325ff69..ffc1e4e0d 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -791,8 +791,10 @@ void DivEngine::nextRow() { } changeOrd=-1; } + if (haltOn==DIV_HALT_PATTERN) halted=true; } else if (++curRow>=song.patLen) { nextOrder(); + if (haltOn==DIV_HALT_PATTERN) halted=true; } if (speedAB) { @@ -813,6 +815,8 @@ void DivEngine::nextRow() { } } } + + if (haltOn==DIV_HALT_ROW) halted=true; } bool DivEngine::nextTick(bool noAccum) { @@ -967,6 +971,8 @@ bool DivEngine::nextTick(bool noAccum) { if (consoleMode) fprintf(stderr,"\x1b[2K> %d:%.2d:%.2d.%.2d %.2x/%.2x:%.3d/%.3d %4dcmd/s\x1b[G",totalSeconds/3600,(totalSeconds/60)%60,totalSeconds%60,totalTicks/10000,curOrder,song.ordersLen,curRow,song.patLen,cmdsPerSecond); } + if (haltOn==DIV_HALT_TICK) halted=true; + return ret; } @@ -1076,6 +1082,8 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi int attempts=0; int runLeftG=size<=100) { logE("hang detected! stopping! at %d seconds %d micro\n",totalSeconds,totalTicks); @@ -1137,11 +1151,6 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi disCont[i].fillBuf(runtotal[i],size); } - if (out==NULL) { - isBusy.unlock(); - return; - } - for (int i=0; iisHalted()) { + if (ImGui::Button("Resume")) e->resume(); + } else { + if (ImGui::Button("Pause")) e->halt(); + } ImGui::SameLine(); - ImGui::Button("Frame Advance"); + if (ImGui::Button("Frame Advance")) e->haltWhen(DIV_HALT_TICK); ImGui::SameLine(); - ImGui::Button("Row Advance"); + if (ImGui::Button("Row Advance")) e->haltWhen(DIV_HALT_ROW); ImGui::SameLine(); - ImGui::Button("Pattern Advance"); + if (ImGui::Button("Pattern Advance")) e->haltWhen(DIV_HALT_PATTERN); - ImGui::Button("Panic"); + if (ImGui::Button("Panic")) e->syncReset(); ImGui::SameLine(); if (ImGui::Button("Abort")) { abort(); @@ -3389,6 +3393,29 @@ void FurnaceGUI::drawDebug() { if (ImGui::Button("Add")) { pgProgram.push_back(DivRegWrite(pgAddr,pgVal)); } + if (ImGui::TreeNode("Register Cheatsheet")) { + const char** sheet=e->getRegisterSheet(pgSys); + if (sheet==NULL) { + ImGui::Text("no cheatsheet available for this system."); + } else { + if (ImGui::BeginTable("RegisterSheet",2,ImGuiTableFlags_SizingFixedSame)) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("Name"); + ImGui::TableNextColumn(); + ImGui::Text("Address"); + for (int i=0; sheet[i]!=NULL; i+=2) { + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("%s",sheet[i]); + ImGui::TableNextColumn(); + ImGui::Text("$%s",sheet[i+1]); + } + ImGui::EndTable(); + } + } + ImGui::TreePop(); + } ImGui::TreePop(); } if (ImGui::TreeNode("Settings")) {