From 24e7338dc56ddbf83397cd1a5dffb48e97e110ce Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 4 Sep 2025 05:01:48 -0500 Subject: [PATCH] GUI: add visualizer to cmd stream player --- src/engine/cmdStream.cpp | 5 +++ src/engine/cmdStream.h | 3 +- src/gui/csPlayer.cpp | 71 ++++++++++++++++++++++++++++++++++++++++ src/gui/gui.h | 2 ++ 4 files changed, 80 insertions(+), 1 deletion(-) diff --git a/src/engine/cmdStream.cpp b/src/engine/cmdStream.cpp index f1605426e..21ed84b5c 100644 --- a/src/engine/cmdStream.cpp +++ b/src/engine/cmdStream.cpp @@ -682,6 +682,11 @@ bool DivCSPlayer::init() { chan[i].readPos=chan[i].startPos; } } + + // read stack sizes + for (unsigned int i=0; igetTotalChannelCount(); i++) { diff --git a/src/engine/cmdStream.h b/src/engine/cmdStream.h index 326134dbd..459a49d62 100644 --- a/src/engine/cmdStream.h +++ b/src/engine/cmdStream.h @@ -41,7 +41,7 @@ struct DivCSChannelState { unsigned char arp, arpStage, arpTicks; unsigned int callStack[DIV_MAX_CSSTACK]; - unsigned char callStackPos; + unsigned char callStackPos, callStackSize; unsigned int trace[DIV_MAX_CSTRACE]; unsigned char tracePos; @@ -67,6 +67,7 @@ struct DivCSChannelState { arpStage(0), arpTicks(0), callStackPos(0), + callStackSize(0), tracePos(0) { for (int i=0; igetDataLen()); + + ImGui::PushFont(patFont); + if (ImGui::BeginTable("CSHexPos",chans,ImGuiTableFlags_SizingStretchSame)) { + ImGui::TableNextRow(); + for (int i=0; igetChanState(i); + ImGui::TableNextColumn(); + ImGui::Text("$%.4x",state->readPos); + } + ImGui::EndTable(); + } + ImGui::PopFont(); + + if (csTex==NULL || !rend->isTextureValid(csTex)) { + logD("recreating command stream data texture."); + csTex=rend->createTexture(true,256,256,false,GUI_TEXFORMAT_ABGR32); + if (csTex==NULL) { + logE("error while creating command stream data texture! %s",SDL_GetError()); + } + } + if (csTex!=NULL) { + unsigned int* dataT=NULL; + int pitch=0; + if (!rend->lockTexture(csTex,(void**)&dataT,&pitch)) { + logE("error while locking command stream data texture! %s",SDL_GetError()); + } else { + unsigned short* accessTS=cs->getDataAccess(); + unsigned int csTick=cs->getCurTick(); + const float fadeTime=64.0f; + size_t bufSize=cs->getDataLen(); + if (bufSize>65536) bufSize=65536; + + for (size_t i=0; i0.0f) { + dataT[i]=ImGui::GetColorU32(ImGuiCol_HeaderActive,cellAlpha); + } else { + dataT[i]=0; + } + } + for (size_t i=bufSize; i<65536; i++) { + dataT[i]=0; + } + + for (int i=0; igetTotalChannelCount(); i++) { + unsigned int pos=cs->getChanState(i)->readPos; + if (pos<65536) { + ImVec4 col=ImVec4(1.0f,1.0f,1.0f,1.0f); + ImGui::ColorConvertHSVtoRGB((float)i/(float)e->getTotalChannelCount(),0.8f,1.0f,col.x,col.y,col.z); + dataT[pos]=ImGui::GetColorU32(col); + } + } + rend->unlockTexture(csTex); + } + + ImGui::Image(rend->getTextureID(csTex),ImVec2(768.0*dpiScale,768.0*dpiScale)); + } + ImGui::EndTabItem(); + } if (ImGui::BeginTabItem(_("Stream Info"))) { ImGui::Text("%d bytes",(int)cs->getDataLen()); ImGui::Text("%u channels",cs->getFileChans()); @@ -538,6 +604,11 @@ void FurnaceGUI::drawCSPlayer() { ImGui::SameLine(); ImGui::Text("%d",cs->getFastCmds()[i]); } + ImGui::Text("stack sizes:"); + for (unsigned int i=0; igetFileChans(); i++) { + ImGui::SameLine(); + ImGui::Text("%d",cs->getChanState(i)->callStackSize); + } ImGui::Text("ticks: %u",cs->getCurTick()); ImGui::EndTabItem(); } diff --git a/src/gui/gui.h b/src/gui/gui.h index cdea368d9..9473fa5bd 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -1666,6 +1666,8 @@ class FurnaceGUI { int sampleTexW, sampleTexH; bool updateSampleTex; + FurnaceGUITexture* csTex; + String workingDir, fileName, clipboard, warnString, errorString, lastError, curFileName, nextFile, sysSearchQuery, newSongQuery, paletteQuery, sampleBankSearchQuery; String workingDirSong, workingDirIns, workingDirWave, workingDirSample, workingDirAudioExport; String workingDirVGMExport, workingDirROMExport;