mirror of
https://github.com/tildearrow/furnace.git
synced 2024-12-29 02:51:24 +00:00
GUI: improve debug menu
This commit is contained in:
parent
c8f57afda4
commit
584b8426ff
28 changed files with 167 additions and 10 deletions
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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")) {
|
||||
|
|
Loading…
Reference in a new issue