mirror of
https://github.com/tildearrow/furnace.git
synced 2024-12-28 10:31:25 +00:00
add a chip playground
in debug menu
This commit is contained in:
parent
3ca7ebd1fc
commit
d691ec6d76
30 changed files with 226 additions and 0 deletions
|
@ -277,6 +277,19 @@ class DivDispatch {
|
|||
*/
|
||||
std::vector<DivRegWrite>& getRegisterWrites();
|
||||
|
||||
/**
|
||||
* poke a register.
|
||||
* @param addr address.
|
||||
* @param val value.
|
||||
*/
|
||||
virtual void poke(unsigned int addr, unsigned short val);
|
||||
|
||||
/**
|
||||
* poke a register.
|
||||
* @param wlist a vector containing DivRegWrites.
|
||||
*/
|
||||
virtual void poke(std::vector<DivRegWrite>& wlist);
|
||||
|
||||
/**
|
||||
* initialize this DivDispatch.
|
||||
* @param parent the parent DivEngine.
|
||||
|
|
|
@ -3927,6 +3927,20 @@ bool DivEngine::removeSystem(int index) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void DivEngine::poke(int sys, unsigned int addr, unsigned short val) {
|
||||
if (sys<0 || sys>=song.systemLen) return;
|
||||
isBusy.lock();
|
||||
disCont[sys].dispatch->poke(addr,val);
|
||||
isBusy.unlock();
|
||||
}
|
||||
|
||||
void DivEngine::poke(int sys, std::vector<DivRegWrite>& wlist) {
|
||||
if (sys<0 || sys>=song.systemLen) return;
|
||||
isBusy.lock();
|
||||
disCont[sys].dispatch->poke(wlist);
|
||||
isBusy.unlock();
|
||||
}
|
||||
|
||||
String DivEngine::getLastError() {
|
||||
return lastError;
|
||||
}
|
||||
|
|
|
@ -493,6 +493,12 @@ class DivEngine {
|
|||
|
||||
// remove system
|
||||
bool removeSystem(int index);
|
||||
|
||||
// write to register on system
|
||||
void poke(int sys, unsigned int addr, unsigned short val);
|
||||
|
||||
// write to register on system
|
||||
void poke(int sys, std::vector<DivRegWrite>& wlist);
|
||||
|
||||
// get last error
|
||||
String getLastError();
|
||||
|
|
|
@ -78,6 +78,14 @@ std::vector<DivRegWrite>& DivDispatch::getRegisterWrites() {
|
|||
return regWrites;
|
||||
}
|
||||
|
||||
void DivDispatch::poke(unsigned int addr, unsigned short val) {
|
||||
|
||||
}
|
||||
|
||||
void DivDispatch::poke(std::vector<DivRegWrite>& wlist) {
|
||||
|
||||
}
|
||||
|
||||
int DivDispatch::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -728,6 +728,14 @@ void* DivPlatformArcade::getChanState(int ch) {
|
|||
return &chan[ch];
|
||||
}
|
||||
|
||||
void DivPlatformArcade::poke(unsigned int addr, unsigned short val) {
|
||||
immWrite(addr,val);
|
||||
}
|
||||
|
||||
void DivPlatformArcade::poke(std::vector<DivRegWrite>& wlist) {
|
||||
for (DivRegWrite& i: wlist) immWrite(i.addr,i.val);
|
||||
}
|
||||
|
||||
void DivPlatformArcade::reset() {
|
||||
while (!writes.empty()) writes.pop();
|
||||
if (useYMFM) {
|
||||
|
|
|
@ -79,6 +79,8 @@ class DivPlatformArcade: public DivDispatch {
|
|||
void setFlags(unsigned int flags);
|
||||
bool isStereo();
|
||||
void setYMFM(bool use);
|
||||
void poke(unsigned int addr, unsigned short val);
|
||||
void poke(std::vector<DivRegWrite>& wlist);
|
||||
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
||||
void quit();
|
||||
~DivPlatformArcade();
|
||||
|
|
|
@ -368,6 +368,14 @@ void DivPlatformAY8910::notifyInsDeletion(void* ins) {
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformAY8910::poke(unsigned int addr, unsigned short val) {
|
||||
immWrite(addr,val);
|
||||
}
|
||||
|
||||
void DivPlatformAY8910::poke(std::vector<DivRegWrite>& wlist) {
|
||||
for (DivRegWrite& i: wlist) immWrite(i.addr,i.val);
|
||||
}
|
||||
|
||||
void DivPlatformAY8910::setFlags(unsigned int flags) {
|
||||
switch (flags&15) {
|
||||
case 1:
|
||||
|
|
|
@ -65,6 +65,8 @@ class DivPlatformAY8910: public DivDispatch {
|
|||
bool isStereo();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
void notifyInsDeletion(void* ins);
|
||||
void poke(unsigned int addr, unsigned short val);
|
||||
void poke(std::vector<DivRegWrite>& wlist);
|
||||
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
||||
void quit();
|
||||
};
|
||||
|
|
|
@ -408,6 +408,14 @@ void DivPlatformAY8930::notifyInsDeletion(void* ins) {
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformAY8930::poke(unsigned int addr, unsigned short val) {
|
||||
immWrite(addr,val);
|
||||
}
|
||||
|
||||
void DivPlatformAY8930::poke(std::vector<DivRegWrite>& wlist) {
|
||||
for (DivRegWrite& i: wlist) immWrite(i.addr,i.val);
|
||||
}
|
||||
|
||||
void DivPlatformAY8930::setFlags(unsigned int flags) {
|
||||
switch (flags&15) {
|
||||
case 1:
|
||||
|
|
|
@ -58,6 +58,8 @@ class DivPlatformAY8930: public DivDispatch {
|
|||
bool isStereo();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
void notifyInsDeletion(void* ins);
|
||||
void poke(unsigned int addr, unsigned short val);
|
||||
void poke(std::vector<DivRegWrite>& wlist);
|
||||
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
||||
void quit();
|
||||
};
|
||||
|
|
|
@ -349,6 +349,14 @@ void DivPlatformC64::reset() {
|
|||
vol=15;
|
||||
}
|
||||
|
||||
void DivPlatformC64::poke(unsigned int addr, unsigned short val) {
|
||||
rWrite(addr,val);
|
||||
}
|
||||
|
||||
void DivPlatformC64::poke(std::vector<DivRegWrite>& wlist) {
|
||||
for (DivRegWrite& i: wlist) rWrite(i.addr,i.val);
|
||||
}
|
||||
|
||||
void DivPlatformC64::setChipModel(bool is6581) {
|
||||
if (is6581) {
|
||||
sid.set_chip_model(MOS6581);
|
||||
|
|
|
@ -66,6 +66,8 @@ class DivPlatformC64: public DivDispatch {
|
|||
void setFlags(unsigned int flags);
|
||||
void notifyInsChange(int ins);
|
||||
void notifyInsDeletion(void* ins);
|
||||
void poke(unsigned int addr, unsigned short val);
|
||||
void poke(std::vector<DivRegWrite>& wlist);
|
||||
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
||||
void setChipModel(bool is6581);
|
||||
void quit();
|
||||
|
|
|
@ -349,6 +349,14 @@ void DivPlatformGB::notifyInsDeletion(void* ins) {
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformGB::poke(unsigned int addr, unsigned short val) {
|
||||
immWrite(addr,val);
|
||||
}
|
||||
|
||||
void DivPlatformGB::poke(std::vector<DivRegWrite>& wlist) {
|
||||
for (DivRegWrite& i: wlist) immWrite(i.addr,i.val);
|
||||
}
|
||||
|
||||
int DivPlatformGB::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
|
||||
for (int i=0; i<4; i++) {
|
||||
isMuted[i]=false;
|
||||
|
|
|
@ -51,6 +51,8 @@ class DivPlatformGB: public DivDispatch {
|
|||
void notifyInsChange(int ins);
|
||||
void notifyWaveChange(int wave);
|
||||
void notifyInsDeletion(void* ins);
|
||||
void poke(unsigned int addr, unsigned short val);
|
||||
void poke(std::vector<DivRegWrite>& wlist);
|
||||
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
||||
void quit();
|
||||
~DivPlatformGB();
|
||||
|
|
|
@ -643,6 +643,14 @@ void DivPlatformGenesis::notifyInsDeletion(void* ins) {
|
|||
psg.notifyInsDeletion(ins);
|
||||
}
|
||||
|
||||
void DivPlatformGenesis::poke(unsigned int addr, unsigned short val) {
|
||||
immWrite(addr,val);
|
||||
}
|
||||
|
||||
void DivPlatformGenesis::poke(std::vector<DivRegWrite>& wlist) {
|
||||
for (DivRegWrite& i: wlist) immWrite(i.addr,i.val);
|
||||
}
|
||||
|
||||
int DivPlatformGenesis::getPortaFloor(int ch) {
|
||||
return (ch>5)?12:0;
|
||||
}
|
||||
|
|
|
@ -86,6 +86,8 @@ class DivPlatformGenesis: public DivDispatch {
|
|||
void notifyInsChange(int ins);
|
||||
void notifyInsDeletion(void* ins);
|
||||
int getPortaFloor(int ch);
|
||||
void poke(unsigned int addr, unsigned short val);
|
||||
void poke(std::vector<DivRegWrite>& wlist);
|
||||
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
||||
void quit();
|
||||
~DivPlatformGenesis();
|
||||
|
|
|
@ -397,6 +397,14 @@ void DivPlatformNES::notifyInsDeletion(void* ins) {
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformNES::poke(unsigned int addr, unsigned short val) {
|
||||
rWrite(addr,val);
|
||||
}
|
||||
|
||||
void DivPlatformNES::poke(std::vector<DivRegWrite>& wlist) {
|
||||
for (DivRegWrite& i: wlist) rWrite(i.addr,i.val);
|
||||
}
|
||||
|
||||
int DivPlatformNES::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
|
||||
parent=p;
|
||||
apuType=flags;
|
||||
|
|
|
@ -54,6 +54,8 @@ class DivPlatformNES: public DivDispatch {
|
|||
bool keyOffAffectsArp(int ch);
|
||||
void setFlags(unsigned int flags);
|
||||
void notifyInsDeletion(void* ins);
|
||||
void poke(unsigned int addr, unsigned short val);
|
||||
void poke(std::vector<DivRegWrite>& wlist);
|
||||
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
||||
void quit();
|
||||
~DivPlatformNES();
|
||||
|
|
|
@ -405,6 +405,14 @@ void DivPlatformPCE::setFlags(unsigned int flags) {
|
|||
rate=chipClock/12;
|
||||
}
|
||||
|
||||
void DivPlatformPCE::poke(unsigned int addr, unsigned short val) {
|
||||
rWrite(addr,val);
|
||||
}
|
||||
|
||||
void DivPlatformPCE::poke(std::vector<DivRegWrite>& wlist) {
|
||||
for (DivRegWrite& i: wlist) rWrite(i.addr,i.val);
|
||||
}
|
||||
|
||||
int DivPlatformPCE::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
|
||||
parent=p;
|
||||
dumpWrites=false;
|
||||
|
|
|
@ -70,6 +70,8 @@ class DivPlatformPCE: public DivDispatch {
|
|||
void setFlags(unsigned int flags);
|
||||
void notifyWaveChange(int wave);
|
||||
void notifyInsDeletion(void* ins);
|
||||
void poke(unsigned int addr, unsigned short val);
|
||||
void poke(std::vector<DivRegWrite>& wlist);
|
||||
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
||||
void quit();
|
||||
~DivPlatformPCE();
|
||||
|
|
|
@ -322,6 +322,14 @@ void DivPlatformSAA1099::setFlags(unsigned int flags) {
|
|||
rate=chipClock/32;
|
||||
}
|
||||
|
||||
void DivPlatformSAA1099::poke(unsigned int addr, unsigned short val) {
|
||||
rWrite(addr,val);
|
||||
}
|
||||
|
||||
void DivPlatformSAA1099::poke(std::vector<DivRegWrite>& wlist) {
|
||||
for (DivRegWrite& i: wlist) rWrite(i.addr,i.val);
|
||||
}
|
||||
|
||||
int DivPlatformSAA1099::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
|
||||
parent=p;
|
||||
dumpWrites=false;
|
||||
|
|
|
@ -62,6 +62,8 @@ class DivPlatformSAA1099: public DivDispatch {
|
|||
int getPortaFloor(int ch);
|
||||
bool keyOffAffectsArp(int ch);
|
||||
void notifyInsDeletion(void* ins);
|
||||
void poke(unsigned int addr, unsigned short val);
|
||||
void poke(std::vector<DivRegWrite>& wlist);
|
||||
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
||||
void quit();
|
||||
};
|
||||
|
|
|
@ -230,6 +230,14 @@ void DivPlatformSMS::notifyInsDeletion(void* ins) {
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformSMS::poke(unsigned int addr, unsigned short val) {
|
||||
rWrite(val);
|
||||
}
|
||||
|
||||
void DivPlatformSMS::poke(std::vector<DivRegWrite>& wlist) {
|
||||
for (DivRegWrite& i: wlist) rWrite(i.val);
|
||||
}
|
||||
|
||||
void DivPlatformSMS::setFlags(unsigned int flags) {
|
||||
if ((flags&3)==2) {
|
||||
chipClock=4000000;
|
||||
|
|
|
@ -48,6 +48,8 @@ class DivPlatformSMS: public DivDispatch {
|
|||
int getPortaFloor(int ch);
|
||||
void setFlags(unsigned int flags);
|
||||
void notifyInsDeletion(void* ins);
|
||||
void poke(unsigned int addr, unsigned short val);
|
||||
void poke(std::vector<DivRegWrite>& wlist);
|
||||
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
||||
void quit();
|
||||
~DivPlatformSMS();
|
||||
|
|
|
@ -254,6 +254,14 @@ void DivPlatformTIA::notifyInsDeletion(void* ins) {
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformTIA::poke(unsigned int addr, unsigned short val) {
|
||||
rWrite(addr,val);
|
||||
}
|
||||
|
||||
void DivPlatformTIA::poke(std::vector<DivRegWrite>& wlist) {
|
||||
for (DivRegWrite& i: wlist) rWrite(i.addr,i.val);
|
||||
}
|
||||
|
||||
void DivPlatformTIA::setFlags(unsigned int flags) {
|
||||
if (flags&1) {
|
||||
rate=31250;
|
||||
|
|
|
@ -35,6 +35,8 @@ class DivPlatformTIA: public DivDispatch {
|
|||
bool isStereo();
|
||||
bool keyOffAffectsArp(int ch);
|
||||
void notifyInsDeletion(void* ins);
|
||||
void poke(unsigned int addr, unsigned short val);
|
||||
void poke(std::vector<DivRegWrite>& wlist);
|
||||
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
||||
void quit();
|
||||
};
|
||||
|
|
|
@ -721,6 +721,14 @@ void* DivPlatformYM2610::getChanState(int ch) {
|
|||
return &chan[ch];
|
||||
}
|
||||
|
||||
void DivPlatformYM2610::poke(unsigned int addr, unsigned short val) {
|
||||
immWrite(addr,val);
|
||||
}
|
||||
|
||||
void DivPlatformYM2610::poke(std::vector<DivRegWrite>& wlist) {
|
||||
for (DivRegWrite& i: wlist) immWrite(i.addr,i.val);
|
||||
}
|
||||
|
||||
void DivPlatformYM2610::reset() {
|
||||
while (!writes.empty()) writes.pop();
|
||||
if (dumpWrites) {
|
||||
|
|
|
@ -77,6 +77,8 @@ class DivPlatformYM2610: public DivDispatch {
|
|||
bool keyOffAffectsArp(int ch);
|
||||
void notifyInsChange(int ins);
|
||||
void notifyInsDeletion(void* ins);
|
||||
void poke(unsigned int addr, unsigned short val);
|
||||
void poke(std::vector<DivRegWrite>& wlist);
|
||||
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);
|
||||
void quit();
|
||||
~DivPlatformYM2610();
|
||||
|
|
|
@ -3246,6 +3246,68 @@ void FurnaceGUI::drawDebug() {
|
|||
ImGui::Columns();
|
||||
ImGui::TreePop();
|
||||
}
|
||||
if (ImGui::TreeNode("Playground")) {
|
||||
if (pgSys<0 || pgSys>=e->song.systemLen) pgSys=0;
|
||||
if (ImGui::BeginCombo("System",fmt::sprintf("%d. %s",pgSys+1,e->getSystemName(e->song.system[pgSys])).c_str())) {
|
||||
for (int i=0; i<e->song.systemLen; i++) {
|
||||
if (ImGui::Selectable(fmt::sprintf("%d. %s",i+1,e->getSystemName(e->song.system[i])).c_str())) {
|
||||
pgSys=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
ImGui::Text("Program");
|
||||
if (pgProgram.empty()) {
|
||||
ImGui::Text("-nothing here-");
|
||||
} else {
|
||||
char id[32];
|
||||
for (size_t index=0; index<pgProgram.size(); index++) {
|
||||
DivRegWrite& i=pgProgram[index];
|
||||
snprintf(id,31,"pgw%ld",index);
|
||||
ImGui::PushID(id);
|
||||
ImGui::SetNextItemWidth(100.0f*dpiScale);
|
||||
ImGui::InputScalar("##PAddress",ImGuiDataType_U32,&i.addr,NULL,NULL,"%.2X",ImGuiInputTextFlags_CharsHexadecimal);
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("=");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(100.0f*dpiScale);
|
||||
ImGui::InputScalar("##PValue",ImGuiDataType_U16,&i.val,NULL,NULL,"%.2X",ImGuiInputTextFlags_CharsHexadecimal);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button(ICON_FA_TIMES "##PRemove")) {
|
||||
pgProgram.erase(pgProgram.begin()+index);
|
||||
index--;
|
||||
}
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
if (ImGui::Button("Execute")) {
|
||||
e->poke(pgSys,pgProgram);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Clear")) {
|
||||
pgProgram.clear();
|
||||
}
|
||||
|
||||
ImGui::Text("Address");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(100.0f*dpiScale);
|
||||
ImGui::InputInt("##PAddress",&pgAddr,0,0,ImGuiInputTextFlags_CharsHexadecimal);
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("Value");
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(100.0f*dpiScale);
|
||||
ImGui::InputInt("##PValue",&pgVal,0,0,ImGuiInputTextFlags_CharsHexadecimal);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Write")) {
|
||||
e->poke(pgSys,pgAddr,pgVal);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Add")) {
|
||||
pgProgram.push_back(DivRegWrite(pgAddr,pgVal));
|
||||
}
|
||||
ImGui::TreePop();
|
||||
}
|
||||
if (ImGui::TreeNode("Settings")) {
|
||||
if (ImGui::Button("Sync")) syncSettings();
|
||||
ImGui::SameLine();
|
||||
|
|
|
@ -256,6 +256,9 @@ class FurnaceGUI {
|
|||
FurnaceGUIWindows curWindow;
|
||||
float peak[2];
|
||||
|
||||
std::vector<DivRegWrite> pgProgram;
|
||||
int pgSys, pgAddr, pgVal;
|
||||
|
||||
struct ActiveNote {
|
||||
int chan;
|
||||
int note;
|
||||
|
|
Loading…
Reference in a new issue