From 0e633ea69b587f5fd5e41a55bb5f06e37c400bfd Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 27 Jan 2022 00:29:16 -0500 Subject: [PATCH] GUI: add a debug window --- CMakeLists.txt | 1 + demos/bruno_time.fur | Bin 0 -> 10272 bytes src/engine/dispatch.h | 6 + src/engine/engine.cpp | 10 ++ src/engine/engine.h | 13 +- src/engine/orders.h | 5 + src/engine/platform/abstract.cpp | 4 + src/engine/platform/amiga.cpp | 4 + src/engine/platform/amiga.h | 3 + src/engine/platform/arcade.cpp | 4 + src/engine/platform/arcade.h | 3 + src/engine/platform/ay.cpp | 4 + src/engine/platform/ay.h | 3 + src/engine/platform/ay8930.cpp | 4 + src/engine/platform/ay8930.h | 3 + src/engine/platform/c64.cpp | 4 + src/engine/platform/c64.h | 3 + src/engine/platform/dummy.cpp | 4 + src/engine/platform/dummy.h | 2 + src/engine/platform/gb.cpp | 4 + src/engine/platform/gb.h | 2 + src/engine/platform/genesis.cpp | 4 + src/engine/platform/genesis.h | 3 + src/engine/platform/genesisext.cpp | 6 + src/engine/platform/genesisext.h | 2 + src/engine/platform/nes.cpp | 4 + src/engine/platform/nes.h | 2 + src/engine/platform/pce.cpp | 4 + src/engine/platform/pce.h | 2 + src/engine/platform/saa.cpp | 4 + src/engine/platform/saa.h | 2 + src/engine/platform/sms.cpp | 4 + src/engine/platform/sms.h | 2 + src/engine/platform/tia.cpp | 4 + src/engine/platform/tia.h | 2 + src/engine/platform/ym2610.cpp | 4 + src/engine/platform/ym2610.h | 2 + src/engine/platform/ym2610ext.cpp | 7 + src/engine/platform/ym2610ext.h | 2 + src/engine/song.h | 4 + src/gui/debug.cpp | 202 +++++++++++++++++++++++++++++ src/gui/debug.h | 6 + src/gui/gui.cpp | 132 +++++++++++++++++++ src/gui/gui.h | 4 +- 44 files changed, 490 insertions(+), 4 deletions(-) create mode 100644 demos/bruno_time.fur create mode 100644 src/gui/debug.cpp create mode 100644 src/gui/debug.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 86e491c7c..c638befe5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,6 +170,7 @@ src/gui/font_ptMono.cpp src/gui/font_unifont.cpp src/gui/font_icon.cpp src/gui/fonts.cpp +src/gui/debug.cpp src/gui/gui.cpp) if (NOT WIN32 AND NOT APPLE) diff --git a/demos/bruno_time.fur b/demos/bruno_time.fur new file mode 100644 index 0000000000000000000000000000000000000000..7905bed61cc1191e19121886d513f4ce984204f3 GIT binary patch literal 10272 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 return NULL; + return &chan[ch]; +} + +void* DivEngine::getDispatchChanState(int ch) { + if (ch<0 || ch>=chans) return NULL; + return disCont[dispatchOfChan[ch]].dispatch->getChanState(dispatchChanOfChan[ch]); +} + void DivEngine::playSub(bool preserveDrift) { reset(); if (preserveDrift && curOrder==0) return; diff --git a/src/engine/engine.h b/src/engine/engine.h index 5bd36304b..de643fbe5 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -150,9 +150,6 @@ class DivEngine { std::map conf; std::queue pendingNotes; bool isMuted[DIV_MAX_CHANS]; - DivSystem sysOfChan[DIV_MAX_CHANS]; - int dispatchOfChan[DIV_MAX_CHANS]; - int dispatchChanOfChan[DIV_MAX_CHANS]; std::mutex isBusy; String configPath; String configFile; @@ -206,6 +203,10 @@ class DivEngine { public: DivSong song; + DivSystem sysOfChan[DIV_MAX_CHANS]; + int dispatchOfChan[DIV_MAX_CHANS]; + int dispatchChanOfChan[DIV_MAX_CHANS]; + void runExportThread(); void nextBuf(float** in, float** out, int inChans, int outChans, unsigned int size); DivInstrument* getIns(int index); @@ -448,6 +449,12 @@ class DivEngine { // set remaining loops. -1 means loop forever. void setLoops(int loops); + // get channel state + DivChannelState* getChanState(int chan); + + // get dispatch channel state + void* getDispatchChanState(int chan); + // set the audio system. void setAudio(DivAudioEngines which); diff --git a/src/engine/orders.h b/src/engine/orders.h index eb8cc2e09..2f7717994 100644 --- a/src/engine/orders.h +++ b/src/engine/orders.h @@ -1,3 +1,6 @@ +#ifndef _ORDERS_H +#define _ORDERS_H + struct DivOrders { unsigned char ord[DIV_MAX_CHANS][128]; @@ -5,3 +8,5 @@ struct DivOrders { memset(ord,0,DIV_MAX_CHANS*128); } }; + +#endif \ No newline at end of file diff --git a/src/engine/platform/abstract.cpp b/src/engine/platform/abstract.cpp index 60cf94b18..2577119e1 100644 --- a/src/engine/platform/abstract.cpp +++ b/src/engine/platform/abstract.cpp @@ -6,6 +6,10 @@ void DivDispatch::acquire(short* bufL, short* bufR, size_t start, size_t len) { void DivDispatch::tick() { } +void* DivDispatch::getChanState(int chan) { + return NULL; +} + void* DivDispatch::getState() { return NULL; } diff --git a/src/engine/platform/amiga.cpp b/src/engine/platform/amiga.cpp index 1c81e6b8a..80a06483a 100644 --- a/src/engine/platform/amiga.cpp +++ b/src/engine/platform/amiga.cpp @@ -205,6 +205,10 @@ void DivPlatformAmiga::forceIns() { } } +void* DivPlatformAmiga::getChanState(int ch) { + return &chan[ch]; +} + void DivPlatformAmiga::reset() { for (int i=0; i<4; i++) { chan[i]=DivPlatformAmiga::Channel(); diff --git a/src/engine/platform/amiga.h b/src/engine/platform/amiga.h index dd40738bc..14e8a6e2f 100644 --- a/src/engine/platform/amiga.h +++ b/src/engine/platform/amiga.h @@ -45,9 +45,12 @@ class DivPlatformAmiga: public DivDispatch { Channel chan[4]; bool isMuted[4]; + friend void putDispatchChan(void*,int,int); + public: void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); + void* getChanState(int chan); void reset(); void forceIns(); void tick(); diff --git a/src/engine/platform/arcade.cpp b/src/engine/platform/arcade.cpp index b3766fbab..3764702e6 100644 --- a/src/engine/platform/arcade.cpp +++ b/src/engine/platform/arcade.cpp @@ -548,6 +548,10 @@ void DivPlatformArcade::notifyInsChange(int ins) { } } +void* DivPlatformArcade::getChanState(int ch) { + return &chan[ch]; +} + void DivPlatformArcade::reset() { while (!writes.empty()) writes.pop(); if (useYMFM) { diff --git a/src/engine/platform/arcade.h b/src/engine/platform/arcade.h index 7b0ae818f..1eba2a4aa 100644 --- a/src/engine/platform/arcade.h +++ b/src/engine/platform/arcade.h @@ -63,9 +63,12 @@ class DivPlatformArcade: public DivDispatch { void acquire_nuked(short* bufL, short* bufR, size_t start, size_t len); void acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len); + friend void putDispatchChan(void*,int,int); + public: void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); + void* getChanState(int chan); void reset(); void forceIns(); void tick(); diff --git a/src/engine/platform/ay.cpp b/src/engine/platform/ay.cpp index 511de8159..b10ae364f 100644 --- a/src/engine/platform/ay.cpp +++ b/src/engine/platform/ay.cpp @@ -290,6 +290,10 @@ void DivPlatformAY8910::forceIns() { immWrite(0x0d,ayEnvMode); } +void* DivPlatformAY8910::getChanState(int ch) { + return &chan[ch]; +} + void DivPlatformAY8910::reset() { while (!writes.empty()) writes.pop(); ay->device_reset(); diff --git a/src/engine/platform/ay.h b/src/engine/platform/ay.h index 401e03c83..4a74fd7f9 100644 --- a/src/engine/platform/ay.h +++ b/src/engine/platform/ay.h @@ -49,10 +49,13 @@ class DivPlatformAY8910: public DivDispatch { short ayEnvSlide; short* ayBuf[3]; size_t ayBufLen; + + friend void putDispatchChan(void*,int,int); public: void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); + void* getChanState(int chan); void reset(); void forceIns(); void tick(); diff --git a/src/engine/platform/ay8930.cpp b/src/engine/platform/ay8930.cpp index 9953d6c4f..c0f1c65e7 100644 --- a/src/engine/platform/ay8930.cpp +++ b/src/engine/platform/ay8930.cpp @@ -328,6 +328,10 @@ void DivPlatformAY8930::forceIns() { } } +void* DivPlatformAY8930::getChanState(int ch) { + return &chan[ch]; +} + void DivPlatformAY8930::reset() { while (!writes.empty()) writes.pop(); ay->device_reset(); diff --git a/src/engine/platform/ay8930.h b/src/engine/platform/ay8930.h index a79f67aef..71b838a6a 100644 --- a/src/engine/platform/ay8930.h +++ b/src/engine/platform/ay8930.h @@ -43,10 +43,13 @@ class DivPlatformAY8930: public DivDispatch { short ayEnvSlide[3]; short* ayBuf[3]; size_t ayBufLen; + + friend void putDispatchChan(void*,int,int); public: void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); + void* getChanState(int chan); void reset(); void forceIns(); void tick(); diff --git a/src/engine/platform/c64.cpp b/src/engine/platform/c64.cpp index eb590b781..b5760a3a5 100644 --- a/src/engine/platform/c64.cpp +++ b/src/engine/platform/c64.cpp @@ -327,6 +327,10 @@ void DivPlatformC64::notifyInsDeletion(void* ins) { } } +void* DivPlatformC64::getChanState(int ch) { + return &chan[ch]; +} + void DivPlatformC64::reset() { for (int i=0; i<3; i++) { chan[i]=DivPlatformC64::Channel(); diff --git a/src/engine/platform/c64.h b/src/engine/platform/c64.h index 1d44efd6d..e1785fc54 100644 --- a/src/engine/platform/c64.h +++ b/src/engine/platform/c64.h @@ -52,10 +52,13 @@ class DivPlatformC64: public DivDispatch { SID sid; + friend void putDispatchChan(void*,int,int); + void updateFilter(); public: void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); + void* getChanState(int chan); void reset(); void forceIns(); void tick(); diff --git a/src/engine/platform/dummy.cpp b/src/engine/platform/dummy.cpp index 497e2a01d..d8512d408 100644 --- a/src/engine/platform/dummy.cpp +++ b/src/engine/platform/dummy.cpp @@ -31,6 +31,10 @@ void DivPlatformDummy::tick() { } } +void* DivPlatformDummy::getChanState(int ch) { + return &chan[ch]; +} + int DivPlatformDummy::dispatch(DivCommand c) { switch (c.cmd) { case DIV_CMD_NOTE_ON: diff --git a/src/engine/platform/dummy.h b/src/engine/platform/dummy.h index 958e4a7cf..2b33a92b9 100644 --- a/src/engine/platform/dummy.h +++ b/src/engine/platform/dummy.h @@ -15,10 +15,12 @@ class DivPlatformDummy: public DivDispatch { Channel chan[128]; bool isMuted[128]; unsigned char chans; + friend void putDispatchChan(void*,int,int); public: void acquire(short* bufL, short* bufR, size_t start, size_t len); void muteChannel(int ch, bool mute); int dispatch(DivCommand c); + void* getChanState(int chan); void reset(); void tick(); int init(DivEngine* parent, int channels, int sugRate, bool pal); diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index 802a118d7..702139f30 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -301,6 +301,10 @@ void DivPlatformGB::forceIns() { updateWave(); } +void* DivPlatformGB::getChanState(int ch) { + return &chan[ch]; +} + void DivPlatformGB::reset() { for (int i=0; i<4; i++) { chan[i]=DivPlatformGB::Channel(); diff --git a/src/engine/platform/gb.h b/src/engine/platform/gb.h index 6da4376db..424f5bc61 100644 --- a/src/engine/platform/gb.h +++ b/src/engine/platform/gb.h @@ -38,9 +38,11 @@ class DivPlatformGB: public DivDispatch { GB_gameboy_t* gb; unsigned char procMute(); void updateWave(); + friend void putDispatchChan(void*,int,int); public: void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); + void* getChanState(int chan); void reset(); void forceIns(); void tick(); diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index 53ab5ce7b..0c358c51b 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -567,6 +567,10 @@ void DivPlatformGenesis::toggleRegisterDump(bool enable) { psg.toggleRegisterDump(enable); } +void* DivPlatformGenesis::getChanState(int ch) { + return &chan[ch]; +} + void DivPlatformGenesis::reset() { while (!writes.empty()) writes.pop(); OPN2_Reset(&fm); diff --git a/src/engine/platform/genesis.h b/src/engine/platform/genesis.h index 3e007a57a..b9d9e4b05 100644 --- a/src/engine/platform/genesis.h +++ b/src/engine/platform/genesis.h @@ -67,10 +67,13 @@ class DivPlatformGenesis: public DivDispatch { int octave(int freq); int toFreq(int freq); + + friend void putDispatchChan(void*,int,int); public: void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); + void* getChanState(int chan); void reset(); void forceIns(); void tick(); diff --git a/src/engine/platform/genesisext.cpp b/src/engine/platform/genesisext.cpp index 15c5e7717..7f354d452 100644 --- a/src/engine/platform/genesisext.cpp +++ b/src/engine/platform/genesisext.cpp @@ -296,6 +296,12 @@ void DivPlatformGenesisExt::forceIns() { } } +void* DivPlatformGenesisExt::getChanState(int ch) { + if (ch>=6) return &chan[ch-3]; + if (ch>=2) return &opChan[ch-2]; + return &chan[ch]; +} + void DivPlatformGenesisExt::reset() { DivPlatformGenesis::reset(); diff --git a/src/engine/platform/genesisext.h b/src/engine/platform/genesisext.h index 80b497e0b..de7ca9d21 100644 --- a/src/engine/platform/genesisext.h +++ b/src/engine/platform/genesisext.h @@ -16,8 +16,10 @@ class DivPlatformGenesisExt: public DivPlatformGenesis { }; OpChannel opChan[4]; bool isOpMuted[4]; + friend void putDispatchChan(void*,int,int); public: int dispatch(DivCommand c); + void* getChanState(int chan); void reset(); void forceIns(); void tick(); diff --git a/src/engine/platform/nes.cpp b/src/engine/platform/nes.cpp index 35014a2c1..e5c8c8673 100644 --- a/src/engine/platform/nes.cpp +++ b/src/engine/platform/nes.cpp @@ -344,6 +344,10 @@ void DivPlatformNES::forceIns() { } } +void* DivPlatformNES::getChanState(int ch) { + return &chan[ch]; +} + void DivPlatformNES::reset() { for (int i=0; i<5; i++) { chan[i]=DivPlatformNES::Channel(); diff --git a/src/engine/platform/nes.h b/src/engine/platform/nes.h index a511a7a10..3249da985 100644 --- a/src/engine/platform/nes.h +++ b/src/engine/platform/nes.h @@ -42,10 +42,12 @@ class DivPlatformNES: public DivDispatch { struct NESAPU* nes; float freqBase; + friend void putDispatchChan(void*,int,int); public: void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); + void* getChanState(int chan); void reset(); void forceIns(); void tick(); diff --git a/src/engine/platform/pce.cpp b/src/engine/platform/pce.cpp index 9ed7254a1..59ebc08f5 100644 --- a/src/engine/platform/pce.cpp +++ b/src/engine/platform/pce.cpp @@ -340,6 +340,10 @@ void DivPlatformPCE::forceIns() { } } +void* DivPlatformPCE::getChanState(int ch) { + return &chan[ch]; +} + void DivPlatformPCE::reset() { while (!writes.empty()) writes.pop(); for (int i=0; i<6; i++) { diff --git a/src/engine/platform/pce.h b/src/engine/platform/pce.h index bdf0bf324..e0739c9e4 100644 --- a/src/engine/platform/pce.h +++ b/src/engine/platform/pce.h @@ -56,9 +56,11 @@ class DivPlatformPCE: public DivDispatch { unsigned char sampleBank; PCE_PSG* pce; void updateWave(int ch); + friend void putDispatchChan(void*,int,int); public: void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); + void* getChanState(int chan); void reset(); void forceIns(); void tick(); diff --git a/src/engine/platform/saa.cpp b/src/engine/platform/saa.cpp index a264cf449..6cc341a1e 100644 --- a/src/engine/platform/saa.cpp +++ b/src/engine/platform/saa.cpp @@ -255,6 +255,10 @@ void DivPlatformSAA1099::forceIns() { rWrite(0x16,saaNoise[0]|(saaNoise[1]<<4)); } +void* DivPlatformSAA1099::getChanState(int ch) { + return &chan[ch]; +} + void DivPlatformSAA1099::reset() { while (!writes.empty()) writes.pop(); saa=saa1099_device(); diff --git a/src/engine/platform/saa.h b/src/engine/platform/saa.h index 26f6d25ca..4bda01009 100644 --- a/src/engine/platform/saa.h +++ b/src/engine/platform/saa.h @@ -47,10 +47,12 @@ class DivPlatformSAA1099: public DivDispatch { size_t saaBufLen; unsigned char saaEnv[2]; unsigned char saaNoise[2]; + friend void putDispatchChan(void*,int,int); public: void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); + void* getChanState(int chan); void reset(); void forceIns(); void tick(); diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index 831aec87e..70d3d4bf7 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -187,6 +187,10 @@ void DivPlatformSMS::forceIns() { } } +void* DivPlatformSMS::getChanState(int ch) { + return &chan[ch]; +} + void DivPlatformSMS::reset() { for (int i=0; i<4; i++) { chan[i]=DivPlatformSMS::Channel(); diff --git a/src/engine/platform/sms.h b/src/engine/platform/sms.h index 5dc754119..798685cca 100644 --- a/src/engine/platform/sms.h +++ b/src/engine/platform/sms.h @@ -31,10 +31,12 @@ class DivPlatformSMS: public DivDispatch { unsigned char snNoiseMode; bool updateSNMode; sn76496_device* sn; + friend void putDispatchChan(void*,int,int); public: int acquireOne(); void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); + void* getChanState(int chan); void reset(); void forceIns(); void tick(); diff --git a/src/engine/platform/tia.cpp b/src/engine/platform/tia.cpp index e31c507d7..ebd587cc0 100644 --- a/src/engine/platform/tia.cpp +++ b/src/engine/platform/tia.cpp @@ -228,6 +228,10 @@ void DivPlatformTIA::forceIns() { } } +void* DivPlatformTIA::getChanState(int ch) { + return &chan[ch]; +} + void DivPlatformTIA::reset() { tia.reset(); for (int i=0; i<2; i++) { diff --git a/src/engine/platform/tia.h b/src/engine/platform/tia.h index 8843ef678..180e20351 100644 --- a/src/engine/platform/tia.h +++ b/src/engine/platform/tia.h @@ -19,10 +19,12 @@ class DivPlatformTIA: public DivDispatch { Channel chan[2]; bool isMuted[2]; TIASound tia; + friend void putDispatchChan(void*,int,int); public: void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); + void* getChanState(int chan); void reset(); void forceIns(); void tick(); diff --git a/src/engine/platform/ym2610.cpp b/src/engine/platform/ym2610.cpp index 8087c98e1..fd5e367a7 100644 --- a/src/engine/platform/ym2610.cpp +++ b/src/engine/platform/ym2610.cpp @@ -570,6 +570,10 @@ void DivPlatformYM2610::forceIns() { immWrite(0x0d,ayEnvMode); } +void* DivPlatformYM2610::getChanState(int ch) { + return &chan[ch]; +} + void DivPlatformYM2610::reset() { while (!writes.empty()) writes.pop(); if (dumpWrites) { diff --git a/src/engine/platform/ym2610.h b/src/engine/platform/ym2610.h index 0269a5b0f..93879e6bc 100644 --- a/src/engine/platform/ym2610.h +++ b/src/engine/platform/ym2610.h @@ -63,10 +63,12 @@ class DivPlatformYM2610: public DivDispatch { int octave(int freq); int toFreq(int freq); + friend void putDispatchChan(void*,int,int); public: void acquire(short* bufL, short* bufR, size_t start, size_t len); int dispatch(DivCommand c); + void* getChanState(int chan); void reset(); void forceIns(); void tick(); diff --git a/src/engine/platform/ym2610ext.cpp b/src/engine/platform/ym2610ext.cpp index d582199f5..71072edad 100644 --- a/src/engine/platform/ym2610ext.cpp +++ b/src/engine/platform/ym2610ext.cpp @@ -268,6 +268,13 @@ void DivPlatformYM2610Ext::forceIns() { } } + +void* DivPlatformYM2610Ext::getChanState(int ch) { + if (ch>=5) return &chan[ch-3]; + if (ch>=1) return &opChan[ch-1]; + return &chan[ch]; +} + void DivPlatformYM2610Ext::reset() { DivPlatformYM2610::reset(); diff --git a/src/engine/platform/ym2610ext.h b/src/engine/platform/ym2610ext.h index f5064c7fb..942198036 100644 --- a/src/engine/platform/ym2610ext.h +++ b/src/engine/platform/ym2610ext.h @@ -16,8 +16,10 @@ class DivPlatformYM2610Ext: public DivPlatformYM2610 { }; OpChannel opChan[4]; bool isOpMuted[4]; + friend void putDispatchChan(void*,int,int); public: int dispatch(DivCommand c); + void* getChanState(int chan); void reset(); void forceIns(); void tick(); diff --git a/src/engine/song.h b/src/engine/song.h index f663d6cc2..d05975a83 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -1,3 +1,5 @@ +#ifndef _SONG_H +#define _SONG_H #include #include @@ -158,3 +160,5 @@ struct DivSong { system[0]=DIV_SYSTEM_GENESIS; } }; + +#endif \ No newline at end of file diff --git a/src/gui/debug.cpp b/src/gui/debug.cpp new file mode 100644 index 000000000..01988959b --- /dev/null +++ b/src/gui/debug.cpp @@ -0,0 +1,202 @@ +#include "debug.h" +#include "imgui.h" +#include "../engine/platform/genesis.h" +#include "../engine/platform/genesisext.h" +#include "../engine/platform/sms.h" +#include "../engine/platform/gb.h" +#include "../engine/platform/pce.h" +#include "../engine/platform/nes.h" +#include "../engine/platform/c64.h" +#include "../engine/platform/arcade.h" +#include "../engine/platform/ym2610.h" +#include "../engine/platform/ym2610ext.h" +#include "../engine/platform/ay.h" +#include "../engine/platform/ay8930.h" +#include "../engine/platform/tia.h" +#include "../engine/platform/saa.h" +#include "../engine/platform/amiga.h" +#include "../engine/platform/dummy.h" + +void putDispatchChan(void* data, int chanNum, int type) { + ImVec4 colorOn=ImVec4(1.0f,1.0f,0.0f,1.0f); + ImVec4 colorOff=ImVec4(0.3f,0.3f,0.3f,1.0f); + switch (type) { + case DIV_SYSTEM_GENESIS: { + DivPlatformGenesis::Channel* ch=(DivPlatformGenesis::Channel*)data; + ImGui::Text("> Genesis"); + ImGui::Text("- freqHL: %.2x%.2x",ch->freqH,ch->freqL); + ImGui::Text("* freq: %d",ch->freq); + ImGui::Text(" - base: %d",ch->baseFreq); + ImGui::Text(" - pitch: %d",ch->pitch); + ImGui::Text("- note: %d",ch->note); + ImGui::Text("- ins: %d",ch->ins); + ImGui::Text("- vol: %.2x",ch->vol); + ImGui::Text("- outVol: %.2x",ch->outVol); + ImGui::Text("- pan: %x",ch->pan); + ImGui::TextColored(ch->active?colorOn:colorOff,">> Active"); + ImGui::TextColored(ch->insChanged?colorOn:colorOff,">> InsChanged"); + ImGui::TextColored(ch->freqChanged?colorOn:colorOff,">> FreqChanged"); + ImGui::TextColored(ch->keyOn?colorOn:colorOff,">> KeyOn"); + ImGui::TextColored(ch->keyOff?colorOn:colorOff,">> KeyOff"); + ImGui::TextColored(ch->portaPause?colorOn:colorOff,">> PortaPause"); + ImGui::TextColored(ch->furnaceDac?colorOn:colorOff,">> FurnaceDAC"); + ImGui::TextColored(ch->inPorta?colorOn:colorOff,">> InPorta"); + break; + } + case DIV_SYSTEM_SMS: { + DivPlatformSMS::Channel* ch=(DivPlatformSMS::Channel*)data; + ImGui::Text("> SMS"); + ImGui::Text("* freq: %d",ch->freq); + ImGui::Text(" - base: %d",ch->baseFreq); + ImGui::Text(" - pitch: %d",ch->pitch); + ImGui::Text("- note: %d",ch->note); + ImGui::Text("- ins: %d",ch->ins); + ImGui::Text("- vol: %.2x",ch->vol); + ImGui::Text("- outVol: %.2x",ch->outVol); + ImGui::TextColored(ch->active?colorOn:colorOff,">> Active"); + ImGui::TextColored(ch->insChanged?colorOn:colorOff,">> InsChanged"); + ImGui::TextColored(ch->freqChanged?colorOn:colorOff,">> FreqChanged"); + ImGui::TextColored(ch->keyOn?colorOn:colorOff,">> KeyOn"); + ImGui::TextColored(ch->keyOff?colorOn:colorOff,">> KeyOff"); + break; + } + case DIV_SYSTEM_GB: { + DivPlatformGB::Channel* ch=(DivPlatformGB::Channel*)data; + ImGui::Text("> GameBoy"); + ImGui::Text("* freq: %d",ch->freq); + ImGui::Text(" - base: %d",ch->baseFreq); + ImGui::Text(" - pitch: %d",ch->pitch); + ImGui::Text("- note: %d",ch->note); + ImGui::Text("- ins: %d",ch->ins); + ImGui::Text("- duty: %d",ch->duty); + ImGui::Text("- sweep: %.2x",ch->sweep); + ImGui::Text("- vol: %.2x",ch->vol); + ImGui::Text("- outVol: %.2x",ch->outVol); + ImGui::Text("- wave: %d",ch->wave); + ImGui::TextColored(ch->active?colorOn:colorOff,">> Active"); + ImGui::TextColored(ch->insChanged?colorOn:colorOff,">> InsChanged"); + ImGui::TextColored(ch->freqChanged?colorOn:colorOff,">> FreqChanged"); + ImGui::TextColored(ch->sweepChanged?colorOn:colorOff,">> SweepChanged"); + ImGui::TextColored(ch->keyOn?colorOn:colorOff,">> KeyOn"); + ImGui::TextColored(ch->keyOff?colorOn:colorOff,">> KeyOff"); + ImGui::TextColored(ch->inPorta?colorOn:colorOff,">> InPorta"); + break; + } + case DIV_SYSTEM_PCE: { + DivPlatformPCE::Channel* ch=(DivPlatformPCE::Channel*)data; + ImGui::Text("> PCEngine"); + ImGui::Text("* freq: %d",ch->freq); + ImGui::Text(" - base: %d",ch->baseFreq); + ImGui::Text(" - pitch: %d",ch->pitch); + ImGui::Text("- note: %d",ch->note); + ImGui::Text("* DAC:"); + ImGui::Text(" - period: %d",ch->dacPeriod); + ImGui::Text(" - rate: %d",ch->dacRate); + ImGui::Text(" - pos: %d",ch->dacPos); + ImGui::Text(" - sample: %d",ch->dacSample); + ImGui::Text("- ins: %d",ch->ins); + ImGui::Text("- pan: %.2x",ch->pan); + ImGui::Text("- vol: %.2x",ch->vol); + ImGui::Text("- outVol: %.2x",ch->outVol); + ImGui::Text("- wave: %d",ch->wave); + ImGui::TextColored(ch->active?colorOn:colorOff,">> Active"); + ImGui::TextColored(ch->insChanged?colorOn:colorOff,">> InsChanged"); + ImGui::TextColored(ch->freqChanged?colorOn:colorOff,">> FreqChanged"); + ImGui::TextColored(ch->keyOn?colorOn:colorOff,">> KeyOn"); + ImGui::TextColored(ch->keyOff?colorOn:colorOff,">> KeyOff"); + ImGui::TextColored(ch->inPorta?colorOn:colorOff,">> InPorta"); + ImGui::TextColored(ch->noise?colorOn:colorOff,">> Noise"); + ImGui::TextColored(ch->pcm?colorOn:colorOff,">> DAC"); + ImGui::TextColored(ch->furnaceDac?colorOn:colorOff,">> FurnaceDAC"); + break; + } + case DIV_SYSTEM_NES: { + DivPlatformNES::Channel* ch=(DivPlatformNES::Channel*)data; + ImGui::Text("> NES"); + ImGui::Text("* freq: %d",ch->freq); + ImGui::Text(" - base: %d",ch->baseFreq); + ImGui::Text(" - pitch: %d",ch->pitch); + ImGui::Text(" - prev: %d",ch->prevFreq); + ImGui::Text("- note: %d",ch->note); + ImGui::Text("- ins: %d",ch->ins); + ImGui::Text("- duty: %d",ch->duty); + ImGui::Text("- sweep: %.2x",ch->sweep); + ImGui::Text("- vol: %.2x",ch->vol); + ImGui::Text("- outVol: %.2x",ch->outVol); + ImGui::Text("- wave: %d",ch->wave); + ImGui::TextColored(ch->active?colorOn:colorOff,">> Active"); + ImGui::TextColored(ch->insChanged?colorOn:colorOff,">> InsChanged"); + ImGui::TextColored(ch->freqChanged?colorOn:colorOff,">> FreqChanged"); + ImGui::TextColored(ch->sweepChanged?colorOn:colorOff,">> SweepChanged"); + ImGui::TextColored(ch->keyOn?colorOn:colorOff,">> KeyOn"); + ImGui::TextColored(ch->keyOff?colorOn:colorOff,">> KeyOff"); + ImGui::TextColored(ch->inPorta?colorOn:colorOff,">> InPorta"); + ImGui::TextColored(ch->furnaceDac?colorOn:colorOff,">> FurnaceDAC"); + break; + } + case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580: { + DivPlatformC64::Channel* ch=(DivPlatformC64::Channel*)data; + ImGui::Text("> C64"); + ImGui::Text("* freq: %d",ch->freq); + ImGui::Text(" - base: %d",ch->baseFreq); + ImGui::Text(" - pitch: %d",ch->pitch); + ImGui::Text(" - prev: %d",ch->prevFreq); + ImGui::Text("- testWhen: %d",ch->testWhen); + ImGui::Text("- note: %d",ch->note); + ImGui::Text("- ins: %d",ch->ins); + ImGui::Text("- duty: %d",ch->duty); + ImGui::Text("- sweep: %.2x",ch->sweep); + ImGui::Text("- wave: %.1x",ch->wave); + ImGui::Text("- ADSR: %.1x %.1x %.1x %.1x",ch->attack,ch->decay,ch->sustain,ch->release); + ImGui::Text("- vol: %.2x",ch->vol); + ImGui::Text("- outVol: %.2x",ch->outVol); + ImGui::TextColored(ch->active?colorOn:colorOff,">> Active"); + ImGui::TextColored(ch->insChanged?colorOn:colorOff,">> InsChanged"); + ImGui::TextColored(ch->freqChanged?colorOn:colorOff,">> FreqChanged"); + ImGui::TextColored(ch->sweepChanged?colorOn:colorOff,">> SweepChanged"); + ImGui::TextColored(ch->keyOn?colorOn:colorOff,">> KeyOn"); + ImGui::TextColored(ch->keyOff?colorOn:colorOff,">> KeyOff"); + ImGui::TextColored(ch->inPorta?colorOn:colorOff,">> InPorta"); + ImGui::TextColored(ch->filter?colorOn:colorOff,">> Filter"); + ImGui::TextColored(ch->resetMask?colorOn:colorOff,">> ResetMask"); + ImGui::TextColored(ch->resetFilter?colorOn:colorOff,">> ResetFilter"); + ImGui::TextColored(ch->resetDuty?colorOn:colorOff,">> ResetDuty"); + ImGui::TextColored(ch->ring?colorOn:colorOff,">> Ring"); + ImGui::TextColored(ch->sync?colorOn:colorOff,">> Sync"); + break; + } + case DIV_SYSTEM_ARCADE: { + DivPlatformArcade::Channel* ch=(DivPlatformArcade::Channel*)data; + ImGui::Text("> Arcade"); + ImGui::Text("- freqHL: %.2x%.2x",ch->freqH,ch->freqL); + ImGui::Text("* freq: %d",ch->freq); + ImGui::Text(" - base: %d",ch->baseFreq); + ImGui::Text(" - pitch: %d",ch->pitch); + //ImGui::Text("- note: %d",ch->note); + ImGui::Text("- ins: %d",ch->ins); + ImGui::Text("- KOnCycles: %d",ch->konCycles); + ImGui::Text("- vol: %.2x",ch->vol); + //ImGui::Text("- outVol: %.2x",ch->outVol); + ImGui::Text("- chVolL: %.2x",ch->chVolL); + ImGui::Text("- chVolR: %.2x",ch->chVolR); + ImGui::Text("* PCM:"); + ImGui::Text(" - sample: %d",ch->pcm.sample); + ImGui::Text(" - pos: %d",ch->pcm.pos>>8); + ImGui::Text(" - subPos: %d",ch->pcm.pos&0xff); + ImGui::Text(" - len: %d",ch->pcm.len); + ImGui::Text(" - freq: %.2x",ch->pcm.freq); + ImGui::TextColored(ch->active?colorOn:colorOff,">> Active"); + ImGui::TextColored(ch->insChanged?colorOn:colorOff,">> InsChanged"); + ImGui::TextColored(ch->freqChanged?colorOn:colorOff,">> FreqChanged"); + ImGui::TextColored(ch->keyOn?colorOn:colorOff,">> KeyOn"); + ImGui::TextColored(ch->keyOff?colorOn:colorOff,">> KeyOff"); + ImGui::TextColored(ch->portaPause?colorOn:colorOff,">> PortaPause"); + ImGui::TextColored(ch->furnacePCM?colorOn:colorOff,">> FurnacePCM"); + //ImGui::TextColored(ch->inPorta?colorOn:colorOff,">> InPorta"); + break; + } + default: + ImGui::Text("Unknown system! Help!"); + break; + } +} \ No newline at end of file diff --git a/src/gui/debug.h b/src/gui/debug.h new file mode 100644 index 000000000..49f01bdc4 --- /dev/null +++ b/src/gui/debug.h @@ -0,0 +1,6 @@ +#ifndef _GUI_DEBUG_H +#define _GUI_DEBUG_H +#include "../engine/song.h" + +void putDispatchChan(void* data, int chanNum, int type); +#endif \ No newline at end of file diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index d5face38b..8d1771d74 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -1,5 +1,6 @@ #define _USE_MATH_DEFINES #include "gui.h" +#include "debug.h" #include "SDL_clipboard.h" #include "SDL_events.h" #include "SDL_keycode.h" @@ -2780,6 +2781,131 @@ void FurnaceGUI::commitSettings() { ImGui::GetIO().Fonts->Build(); } +void FurnaceGUI::drawDebug() { + static int bpOrder; + static int bpRow; + static int bpTick; + static bool bpOn; + if (!debugOpen) return; + if (ImGui::Begin("Debug",&debugOpen,ImGuiWindowFlags_NoDocking)) { + ImGui::Text("NOTE: use with caution."); + if (ImGui::TreeNode("Debug Controls")) { + ImGui::Button("Pause"); + ImGui::SameLine(); + ImGui::Button("Frame Advance"); + ImGui::SameLine(); + ImGui::Button("Row Advance"); + ImGui::SameLine(); + ImGui::Button("Pattern Advance"); + + ImGui::Button("Panic"); + ImGui::SameLine(); + if (ImGui::Button("Abort")) { + abort(); + } + ImGui::TreePop(); + } + if (ImGui::TreeNode("Breakpoint")) { + ImGui::InputInt("Order",&bpOrder); + ImGui::InputInt("Row",&bpRow); + ImGui::InputInt("Tick",&bpTick); + ImGui::Checkbox("Enable",&bpOn); + ImGui::TreePop(); + } + if (ImGui::TreeNode("Dispatch Status")) { + ImGui::Text("for best results set latency to minimum or use the Frame Advance button."); + ImGui::Columns(e->getTotalChannelCount()); + for (int i=0; igetTotalChannelCount(); i++) { + void* ch=e->getDispatchChanState(i); + ImGui::TextColored(uiColors[GUI_COLOR_ACCENT_PRIMARY],"Ch. %d: %d, %d",i,e->dispatchOfChan[i],e->dispatchChanOfChan[i]); + if (ch==NULL) { + ImGui::Text("NULL"); + } else { + putDispatchChan(ch,e->dispatchChanOfChan[i],e->sysOfChan[i]); + } + ImGui::NextColumn(); + } + ImGui::Columns(); + ImGui::TreePop(); + } + if (ImGui::TreeNode("Playback Status")) { + ImGui::Text("for best results set latency to minimum or use the Frame Advance button."); + ImGui::Columns(e->getTotalChannelCount()); + for (int i=0; igetTotalChannelCount(); i++) { + DivChannelState* ch=e->getChanState(i); + ImGui::TextColored(uiColors[GUI_COLOR_ACCENT_PRIMARY],"Channel %d:",i); + if (ch==NULL) { + ImGui::Text("NULL"); + } else { + ImGui::Text("* General:"); + ImGui::Text("- note = %d",ch->note); + ImGui::Text("- oldNote = %d",ch->oldNote); + ImGui::Text("- pitch = %d",ch->pitch); + ImGui::Text("- portaSpeed = %d",ch->portaSpeed); + ImGui::Text("- portaNote = %d",ch->portaNote); + ImGui::Text("- volume = %.4x",ch->volume); + ImGui::Text("- volSpeed = %d",ch->volSpeed); + ImGui::Text("- cut = %d",ch->cut); + ImGui::Text("- rowDelay = %d",ch->rowDelay); + ImGui::Text("- volMax = %.4x",ch->volMax); + ImGui::Text("- delayOrder = %d",ch->delayOrder); + ImGui::Text("- delayRow = %d",ch->delayRow); + ImGui::Text("- retrigSpeed = %d",ch->retrigSpeed); + ImGui::Text("- retrigTick = %d",ch->retrigTick); + ImGui::PushStyleColor(ImGuiCol_Text,(ch->vibratoDepth>0)?uiColors[GUI_COLOR_MACRO_VOLUME]:uiColors[GUI_COLOR_TEXT]); + ImGui::Text("* Vibrato:"); + ImGui::Text("- depth = %d",ch->vibratoDepth); + ImGui::Text("- rate = %d",ch->vibratoRate); + ImGui::Text("- pos = %d",ch->vibratoPos); + ImGui::Text("- dir = %d",ch->vibratoDir); + ImGui::Text("- fine = %d",ch->vibratoFine); + ImGui::PopStyleColor(); + ImGui::PushStyleColor(ImGuiCol_Text,(ch->tremoloDepth>0)?uiColors[GUI_COLOR_MACRO_VOLUME]:uiColors[GUI_COLOR_TEXT]); + ImGui::Text("* Tremolo:"); + ImGui::Text("- depth = %d",ch->tremoloDepth); + ImGui::Text("- rate = %d",ch->tremoloRate); + ImGui::Text("- pos = %d",ch->tremoloPos); + ImGui::PopStyleColor(); + ImGui::PushStyleColor(ImGuiCol_Text,(ch->arp>0)?uiColors[GUI_COLOR_MACRO_VOLUME]:uiColors[GUI_COLOR_TEXT]); + ImGui::Text("* Arpeggio:"); + ImGui::Text("- arp = %.2X",ch->arp); + ImGui::Text("- stage = %d",ch->arpStage); + ImGui::Text("- ticks = %d",ch->arpTicks); + ImGui::PopStyleColor(); + ImGui::Text("* Miscellaneous:"); + ImGui::TextColored(ch->doNote?uiColors[GUI_COLOR_MACRO_VOLUME]:uiColors[GUI_COLOR_HEADER],">> Do Note"); + ImGui::TextColored(ch->legato?uiColors[GUI_COLOR_MACRO_VOLUME]:uiColors[GUI_COLOR_HEADER],">> Legato"); + ImGui::TextColored(ch->portaStop?uiColors[GUI_COLOR_MACRO_VOLUME]:uiColors[GUI_COLOR_HEADER],">> PortaStop"); + ImGui::TextColored(ch->keyOn?uiColors[GUI_COLOR_MACRO_VOLUME]:uiColors[GUI_COLOR_HEADER],">> Key On"); + ImGui::TextColored(ch->keyOff?uiColors[GUI_COLOR_MACRO_VOLUME]:uiColors[GUI_COLOR_HEADER],">> Key Off"); + ImGui::TextColored(ch->nowYouCanStop?uiColors[GUI_COLOR_MACRO_VOLUME]:uiColors[GUI_COLOR_HEADER],">> NowYouCanStop"); + ImGui::TextColored(ch->stopOnOff?uiColors[GUI_COLOR_MACRO_VOLUME]:uiColors[GUI_COLOR_HEADER],">> Stop on Off"); + ImGui::TextColored(ch->arpYield?uiColors[GUI_COLOR_MACRO_VOLUME]:uiColors[GUI_COLOR_HEADER],">> Arp Yield"); + ImGui::TextColored(ch->delayLocked?uiColors[GUI_COLOR_MACRO_VOLUME]:uiColors[GUI_COLOR_HEADER],">> DelayLocked"); + ImGui::TextColored(ch->inPorta?uiColors[GUI_COLOR_MACRO_VOLUME]:uiColors[GUI_COLOR_HEADER],">> InPorta"); + ImGui::TextColored(ch->scheduledSlideReset?uiColors[GUI_COLOR_MACRO_VOLUME]:uiColors[GUI_COLOR_HEADER],">> SchedSlide"); + } + ImGui::NextColumn(); + } + ImGui::Columns(); + ImGui::TreePop(); + } + if (ImGui::TreeNode("Settings")) { + if (ImGui::Button("Sync")) syncSettings(); + ImGui::SameLine(); + if (ImGui::Button("Commit")) commitSettings(); + ImGui::SameLine(); + if (ImGui::Button("Force Load")) e->loadConf(); + ImGui::SameLine(); + if (ImGui::Button("Force Save")) e->saveConf(); + ImGui::TreePop(); + } + ImGui::Text("Song format version %d",e->song.version); + ImGui::Text("Furnace version " DIV_VERSION " (%d)",DIV_ENGINE_VERSION); + } + ImGui::End(); +} + void FurnaceGUI::startSelection(int xCoarse, int xFine, int y) { if (xCoarse!=selStart.xCoarse || xFine!=selStart.xFine || y!=selStart.y) { curNibble=false; @@ -4379,6 +4505,7 @@ bool FurnaceGUI::loop() { ImGui::EndMenu(); } if (ImGui::BeginMenu("help")) { + if (ImGui::MenuItem("debug menu")) debugOpen=!debugOpen; if (ImGui::MenuItem("about...")) { aboutOpen=true; aboutScroll=0; @@ -4413,6 +4540,7 @@ bool FurnaceGUI::loop() { drawMixer(); drawPattern(); drawSettings(); + drawDebug(); if (ImGuiFileDialog::Instance()->Display("FileDialog",ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoMove,ImVec2(600.0f*dpiScale,400.0f*dpiScale),ImVec2(scrW*dpiScale,scrH*dpiScale))) { if (ImGuiFileDialog::Instance()->IsOk()) { @@ -4994,6 +5122,9 @@ FurnaceGUI::FurnaceGUI(): soloTimeout(0), orderEditMode(0), orderCursor(-1), + loopOrder(-1), + loopRow(-1), + loopEnd(-1), editControlsOpen(true), ordersOpen(true), insListOpen(true), @@ -5007,6 +5138,7 @@ FurnaceGUI::FurnaceGUI(): aboutOpen(false), settingsOpen(false), mixerOpen(false), + debugOpen(false), selecting(false), curNibble(false), orderNibble(false), diff --git a/src/gui/gui.h b/src/gui/gui.h index 62142ae38..4f6f67b55 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -230,9 +230,10 @@ class FurnaceGUI { char finalLayoutPath[4096]; int curIns, curWave, curSample, curOctave, oldRow, oldOrder, oldOrder1, editStep, exportLoops, soloChan, soloTimeout, orderEditMode, orderCursor; + int loopOrder, loopRow, loopEnd; bool editControlsOpen, ordersOpen, insListOpen, songInfoOpen, patternOpen, insEditOpen; bool waveListOpen, waveEditOpen, sampleListOpen, sampleEditOpen, aboutOpen, settingsOpen; - bool mixerOpen; + bool mixerOpen, debugOpen; SelectionPoint selStart, selEnd, cursor; bool selecting, curNibble, orderNibble, extraChannelButtons, followOrders, followPattern, changeAllOrders; FurnaceGUIWindows curWindow; @@ -313,6 +314,7 @@ class FurnaceGUI { void drawMixer(); void drawAbout(); void drawSettings(); + void drawDebug(); void syncSettings(); void commitSettings();