GUI: improve debug menu

This commit is contained in:
tildearrow 2022-02-03 18:38:57 -05:00
parent c8f57afda4
commit 584b8426ff
28 changed files with 167 additions and 10 deletions

View file

@ -292,6 +292,12 @@ class DivDispatch {
*/
virtual void poke(std::vector<DivRegWrite>& 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.

View file

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

View file

@ -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<DivDelayedCommand> 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),

View file

@ -86,6 +86,10 @@ void DivDispatch::poke(std::vector<DivRegWrite>& wlist) {
}
const char** DivDispatch::getRegisterSheet() {
return NULL;
}
int DivDispatch::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
return 0;
}

View file

@ -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<start+len; h++) {
bufL[h]=0;

View file

@ -61,6 +61,7 @@ class DivPlatformAmiga: public DivDispatch {
void notifyInsChange(int ins);
void notifyWaveChange(int wave);
void notifyInsDeletion(void* ins);
const char** getRegisterSheet();
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
void quit();
};

View file

@ -57,6 +57,10 @@ const char* regCheatSheetOPM[]={
NULL
};
const char** DivPlatformArcade::getRegisterSheet() {
return regCheatSheetOPM;
}
void DivPlatformArcade::acquire_nuked(short* bufL, short* bufR, size_t start, size_t len) {
static int o[2];

View file

@ -81,6 +81,7 @@ class DivPlatformArcade: public DivDispatch {
void setYMFM(bool use);
void poke(unsigned int addr, unsigned short val);
void poke(std::vector<DivRegWrite>& wlist);
const char** getRegisterSheet();
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
void quit();
~DivPlatformArcade();

View file

@ -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<len) {
ayBufLen=len;

View file

@ -67,6 +67,7 @@ class DivPlatformAY8910: public DivDispatch {
void notifyInsDeletion(void* ins);
void poke(unsigned int addr, unsigned short val);
void poke(std::vector<DivRegWrite>& wlist);
const char** getRegisterSheet();
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
void quit();
};

View file

@ -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<len) {
ayBufLen=len;

View file

@ -60,6 +60,7 @@ class DivPlatformAY8930: public DivDispatch {
void notifyInsDeletion(void* ins);
void poke(unsigned int addr, unsigned short val);
void poke(std::vector<DivRegWrite>& wlist);
const char** getRegisterSheet();
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
void quit();
};

View file

@ -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<start+len; i++) {
sid.clock();

View file

@ -68,6 +68,7 @@ class DivPlatformC64: public DivDispatch {
void notifyInsDeletion(void* ins);
void poke(unsigned int addr, unsigned short val);
void poke(std::vector<DivRegWrite>& wlist);
const char** getRegisterSheet();
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
void setChipModel(bool is6581);
void quit();

View file

@ -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<start+len; i++) {
GB_advance_cycles(gb,16);

View file

@ -53,6 +53,7 @@ class DivPlatformGB: public DivDispatch {
void notifyInsDeletion(void* ins);
void poke(unsigned int addr, unsigned short val);
void poke(std::vector<DivRegWrite>& wlist);
const char** getRegisterSheet();
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
void quit();
~DivPlatformGB();

View file

@ -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<start+len; i++) {
if (dacSample!=-1) {

View file

@ -56,6 +56,7 @@ class DivPlatformNES: public DivDispatch {
void notifyInsDeletion(void* ins);
void poke(unsigned int addr, unsigned short val);
void poke(std::vector<DivRegWrite>& wlist);
const char** getRegisterSheet();
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
void quit();
~DivPlatformNES();

View file

@ -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<start+len; h++) {
// PCM part

View file

@ -72,6 +72,7 @@ class DivPlatformPCE: public DivDispatch {
void notifyInsDeletion(void* ins);
void poke(unsigned int addr, unsigned short val);
void poke(std::vector<DivRegWrite>& wlist);
const char** getRegisterSheet();
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
void quit();
~DivPlatformPCE();

View file

@ -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<len) {
saaBufLen=len;

View file

@ -64,6 +64,7 @@ class DivPlatformSAA1099: public DivDispatch {
void notifyInsDeletion(void* ins);
void poke(unsigned int addr, unsigned short val);
void poke(std::vector<DivRegWrite>& wlist);
const char** getRegisterSheet();
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
void quit();
};

View file

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

View file

@ -50,6 +50,7 @@ class DivPlatformSMS: public DivDispatch {
void notifyInsDeletion(void* ins);
void poke(unsigned int addr, unsigned short val);
void poke(std::vector<DivRegWrite>& wlist);
const char** getRegisterSheet();
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
void quit();
~DivPlatformSMS();

View file

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

View file

@ -37,6 +37,7 @@ class DivPlatformTIA: public DivDispatch {
void notifyInsDeletion(void* ins);
void poke(unsigned int addr, unsigned short val);
void poke(std::vector<DivRegWrite>& wlist);
const char** getRegisterSheet();
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
void quit();
};

View file

@ -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<<MASTER_CLOCK_PREC;
while (++attempts<100) {
// 0. check if we've halted
if (halted) break;
// 1. check whether we are done with all buffers
if (runLeftG<=0) break;
@ -1124,6 +1132,12 @@ void DivEngine::nextBuf(float** in, float** out, int inChans, int outChans, unsi
}
}
}
if (out==NULL || halted) {
isBusy.unlock();
return;
}
logD("attempts: %d\n",attempts);
if (attempts>=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; i<song.systemLen; i++) {
float volL=((float)song.systemVol[i]/64.0f)*((float)MIN(127,127-(int)song.systemPan[i])/127.0f);
float volR=((float)song.systemVol[i]/64.0f)*((float)MIN(127,127+(int)song.systemPan[i])/127.0f);

View file

@ -3229,15 +3229,19 @@ void FurnaceGUI::drawDebug() {
if (ImGui::Begin("Debug",&debugOpen,ImGuiWindowFlags_NoDocking)) {
ImGui::Text("NOTE: use with caution.");
if (ImGui::TreeNode("Debug Controls")) {
ImGui::Button("Pause");
if (e->isHalted()) {
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")) {