commit
199a344e37
20 changed files with 653 additions and 106 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -4,3 +4,6 @@
|
|||
[submodule "source/frontends/sdl/imgui/imgui"]
|
||||
path = source/frontends/sdl/imgui/imgui
|
||||
url = ../../ocornut/imgui
|
||||
[submodule "source/frontends/sdl/imgui/imgui_club"]
|
||||
path = source/frontends/sdl/imgui/imgui_club
|
||||
url = ../../ocornut/imgui_club
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
include(FindPkgConfig)
|
||||
|
||||
set(SOURCE_FILES
|
||||
Debugger/Debugger_Disassembler.cpp
|
||||
Debugger/Debugger_Symbols.cpp
|
||||
Debugger/Debugger_DisassemblerData.cpp
|
||||
Debugger/Debugger_Console.cpp
|
||||
Debugger/Debugger_Assembler.cpp
|
||||
Debugger/Debugger_Parser.cpp
|
||||
Debugger/Debugger_Range.cpp
|
||||
|
||||
Speaker.cpp
|
||||
SoundCore.cpp
|
||||
AY8910.cpp
|
||||
|
@ -180,5 +188,10 @@ target_compile_options(appleii PUBLIC
|
|||
-Wno-multichar
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
TARGET appleii POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_SOURCE_DIR}/bin/*.SYM ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
|
||||
install(TARGETS appleii
|
||||
DESTINATION lib)
|
||||
|
|
|
@ -627,7 +627,7 @@ void FormatDisassemblyLine(const DisasmLine_t& line, char* sDisassembly, const i
|
|||
//===========================================================================
|
||||
void DisasmCalcTopFromCurAddress(bool bUpdateTop)
|
||||
{
|
||||
int nLen = ((g_nDisasmWinHeight - g_nDisasmCurLine) * 3); // max 3 opcodes/instruction, is our search window
|
||||
int nLen = g_nDisasmCurLine * 3; // max 3 opcodes/instruction, is our search window
|
||||
|
||||
// Look for a start address that when disassembled,
|
||||
// will have the cursor on the specified line and address
|
||||
|
|
|
@ -53,6 +53,7 @@ typedef UINT64 uint64_t;
|
|||
#include <stdexcept>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
#include "linux/win.h"
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "Riff.h"
|
||||
#include "Utilities.h"
|
||||
#include "Interface.h"
|
||||
#include "Debugger/Debug.h"
|
||||
|
||||
#include <libgen.h>
|
||||
#include <unistd.h>
|
||||
|
@ -87,6 +88,8 @@ namespace common2
|
|||
GetCardMgr().GetDisk2CardMgr().Reset();
|
||||
HD_Reset();
|
||||
Snapshot_Startup();
|
||||
|
||||
DebugInitialize();
|
||||
}
|
||||
|
||||
Initialisation::~Initialisation()
|
||||
|
|
|
@ -4,6 +4,7 @@ find_package(SDL2 REQUIRED)
|
|||
pkg_search_module(SDL2_IMAGE REQUIRED SDL2_image)
|
||||
pkg_search_module(GLES2 REQUIRED glesv2)
|
||||
set(IMGUI_PATH "imgui/imgui")
|
||||
set(IMGUI_CLUB_PATH "imgui/imgui_club")
|
||||
|
||||
add_executable(sa2)
|
||||
|
||||
|
@ -66,11 +67,14 @@ target_sources(sa2 PRIVATE
|
|||
${IMGUI_PATH}/imgui_widgets.cpp
|
||||
${IMGUI_PATH}/backends/imgui_impl_sdl.cpp
|
||||
${IMGUI_PATH}/backends/imgui_impl_opengl3.cpp
|
||||
|
||||
${IMGUI_CLUB_PATH}/imgui_memory_editor/imgui_memory_editor.h
|
||||
)
|
||||
|
||||
target_include_directories(sa2 PRIVATE
|
||||
${IMGUI_PATH}
|
||||
${IMGUI_PATH}/backends
|
||||
${IMGUI_CLUB_PATH}/imgui_memory_editor
|
||||
)
|
||||
|
||||
target_compile_definitions(sa2 PRIVATE
|
||||
|
|
|
@ -31,3 +31,5 @@
|
|||
#include "imgui.h"
|
||||
#include "imgui_impl_sdl.h"
|
||||
#include "imgui_impl_opengl3.h"
|
||||
|
||||
#include "imgui_memory_editor.h"
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit cdf1926f21d17a3d9be7f69434cc18dc65dd6609
|
||||
Subproject commit 287bd9b98488d5f7bc0f730904af7f0c842971eb
|
1
source/frontends/sdl/imgui/imgui_club
Submodule
1
source/frontends/sdl/imgui/imgui_club
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 02e679b7f4cfb01f9480dcbcac59552879f96573
|
|
@ -149,7 +149,8 @@ namespace sa2
|
|||
ImGui_ImplSDL2_NewFrame(myWindow.get());
|
||||
ImGui::NewFrame();
|
||||
|
||||
mySettings.show();
|
||||
// "this" is a bit circular
|
||||
mySettings.show(this);
|
||||
DrawAppleVideo();
|
||||
|
||||
ImGui::Render();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "StdAfx.h"
|
||||
#include "frontends/sdl/imgui/sdlsettings.h"
|
||||
#include "frontends/sdl/imgui/settingshelper.h"
|
||||
#include "frontends/sdl/sdlframe.h"
|
||||
|
||||
#include "Interface.h"
|
||||
#include "CardManager.h"
|
||||
|
@ -10,6 +11,10 @@
|
|||
#include "Speaker.h"
|
||||
#include "Mockingboard.h"
|
||||
#include "Registry.h"
|
||||
#include "Memory.h"
|
||||
|
||||
#include "Debugger/Debug.h"
|
||||
#include "Debugger/DebugDefs.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -27,6 +32,59 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
void formatDisassemblyLine(const DisasmLine_t& line, const int bDisasmFormatFlags, char* sDisassembly, const int nBufferSize)
|
||||
{
|
||||
sDisassembly[0] = 0;
|
||||
|
||||
const char* pMnemonic = g_aOpcodes[line.iOpcode].sMnemonic;
|
||||
strcat(sDisassembly, pMnemonic);
|
||||
strcat(sDisassembly, " ");
|
||||
|
||||
if (line.bTargetImmediate)
|
||||
{
|
||||
strcat(sDisassembly, "#$");
|
||||
}
|
||||
|
||||
if (line.bTargetIndexed || line.bTargetIndirect)
|
||||
{
|
||||
strcat(sDisassembly, "(");
|
||||
}
|
||||
|
||||
strcat(sDisassembly, line.sTarget);
|
||||
|
||||
if (bDisasmFormatFlags & DISASM_FORMAT_OFFSET)
|
||||
{
|
||||
if (line.nTargetOffset > 0)
|
||||
{
|
||||
strcat(sDisassembly, "+");
|
||||
}
|
||||
else if (line.nTargetOffset < 0)
|
||||
{
|
||||
strcat(sDisassembly, "-");
|
||||
}
|
||||
strcat(sDisassembly, line.sTargetOffset);
|
||||
}
|
||||
|
||||
if (line.bTargetX)
|
||||
{
|
||||
strcat(sDisassembly, ",X");
|
||||
}
|
||||
else if ((line.bTargetY) && (!line.bTargetIndirect))
|
||||
{
|
||||
strcat(sDisassembly, ",Y");
|
||||
}
|
||||
|
||||
if (line.bTargetIndexed || line.bTargetIndirect)
|
||||
{
|
||||
strcat(sDisassembly, ")");
|
||||
}
|
||||
|
||||
if (line.bTargetIndexed && line.bTargetY)
|
||||
{
|
||||
strcat(sDisassembly, ",Y");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace sa2
|
||||
|
@ -43,7 +101,16 @@ namespace sa2
|
|||
if (ImGui::BeginTabItem("General"))
|
||||
{
|
||||
ImGui::Checkbox("Apple Video windowed", &windowed);
|
||||
ImGui::SameLine(); HelpMarker("Show Apple Video in a separate window.");
|
||||
ImGui::SameLine(); HelpMarker("Show Apple video in a separate window.");
|
||||
|
||||
ImGui::Checkbox("Memory", &myShowMemory);
|
||||
ImGui::SameLine(); HelpMarker("Show Apple memory.");
|
||||
|
||||
if (ImGui::Checkbox("Debugger", &myShowDebugger) && myShowDebugger)
|
||||
{
|
||||
DebugBegin();
|
||||
}
|
||||
ImGui::SameLine(); HelpMarker("Show Apple CPU.");
|
||||
|
||||
ImGui::Checkbox("Show Demo", &myShowDemo);
|
||||
ImGui::SameLine(); HelpMarker("Show Dear ImGui DemoWindow.");
|
||||
|
@ -92,6 +159,11 @@ namespace sa2
|
|||
const eCpuType cpu = GetMainCpu();
|
||||
ImGui::Selectable(getCPUName(cpu).c_str());
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Selectable("Mode");
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Selectable(getModeName(g_nAppMode).c_str());
|
||||
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
|
@ -123,13 +195,23 @@ namespace sa2
|
|||
ImGui::End();
|
||||
}
|
||||
|
||||
void ImGuiSettings::show()
|
||||
void ImGuiSettings::show(SDLFrame * frame)
|
||||
{
|
||||
if (myShowSettings)
|
||||
{
|
||||
showSettings();
|
||||
}
|
||||
|
||||
if (myShowMemory)
|
||||
{
|
||||
showMemory();
|
||||
}
|
||||
|
||||
if (myShowDebugger)
|
||||
{
|
||||
showDebugger(frame);
|
||||
}
|
||||
|
||||
if (myShowDemo)
|
||||
{
|
||||
ImGui::ShowDemoWindow(&myShowDemo);
|
||||
|
@ -146,6 +228,12 @@ namespace sa2
|
|||
if (ImGui::BeginMenu("System"))
|
||||
{
|
||||
ImGui::MenuItem("Settings", nullptr, &myShowSettings);
|
||||
ImGui::MenuItem("Memory", nullptr, &myShowMemory);
|
||||
if (ImGui::MenuItem("Debugger", nullptr, &myShowDebugger) && myShowDebugger)
|
||||
{
|
||||
DebugBegin();
|
||||
}
|
||||
ImGui::Separator();
|
||||
ImGui::MenuItem("Demo", nullptr, &myShowDemo);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
@ -159,4 +247,204 @@ namespace sa2
|
|||
return menuBarHeight;
|
||||
}
|
||||
|
||||
void ImGuiSettings::showMemory()
|
||||
{
|
||||
if (ImGui::Begin("Memory Viewer", &myShowMemory))
|
||||
{
|
||||
if (ImGui::BeginTabBar("Memory"))
|
||||
{
|
||||
if (ImGui::BeginTabItem("Main"))
|
||||
{
|
||||
void * mainBase = MemGetMainPtr(0);
|
||||
myMainMemoryEditor.DrawContents(mainBase, _6502_MEM_LEN);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("AUX"))
|
||||
{
|
||||
void * auxBase = MemGetAuxPtr(0);
|
||||
myMainMemoryEditor.DrawContents(auxBase, _6502_MEM_LEN);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void ImGuiSettings::drawDisassemblyTable()
|
||||
{
|
||||
const ImGuiTableFlags flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingStretchProp | ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_ScrollY;
|
||||
if (ImGui::BeginTable("Disassembly", 8, flags))
|
||||
{
|
||||
// weigths proportional to column width (including header)
|
||||
ImGui::TableSetupScrollFreeze(0, 1); // Make top row always visible
|
||||
ImGui::TableSetupColumn("Address", 0, 7);
|
||||
ImGui::TableSetupColumn("Opcode", 0, 8);
|
||||
ImGui::TableSetupColumn("Symbol", 0, 10);
|
||||
ImGui::TableSetupColumn("Disassembly", 0, 20);
|
||||
ImGui::TableSetupColumn("Target", 0, 6);
|
||||
ImGui::TableSetupColumn("Value", 0, 6);
|
||||
ImGui::TableSetupColumn("Immediate", 0, 9);
|
||||
ImGui::TableSetupColumn("Branch", 0, 6);
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
ImGuiListClipper clipper;
|
||||
clipper.Begin(1000);
|
||||
int row = 0;
|
||||
WORD nAddress = g_nDisasmTopAddress;
|
||||
while (clipper.Step())
|
||||
{
|
||||
for (; row < clipper.DisplayStart; ++row)
|
||||
{
|
||||
int iOpcode, iOpmode, nOpbyte;
|
||||
_6502_GetOpmodeOpbyte(nAddress, iOpmode, nOpbyte, nullptr);
|
||||
nAddress += nOpbyte;
|
||||
}
|
||||
IM_ASSERT(row == clipper.DisplayStart && "Clipper position mismatch");
|
||||
for (; row < clipper.DisplayEnd; ++row)
|
||||
{
|
||||
DisasmLine_t line;
|
||||
const char* pSymbol = FindSymbolFromAddress(nAddress);
|
||||
const int bDisasmFormatFlags = GetDisassemblyLine(nAddress, line);
|
||||
|
||||
char buffer[256];
|
||||
formatDisassemblyLine(line, bDisasmFormatFlags, buffer, sizeof(buffer));
|
||||
|
||||
ImGui::TableNextRow();
|
||||
|
||||
if (nAddress == regs.pc)
|
||||
{
|
||||
const ImU32 currentBgColor = ImGui::GetColorU32(ImVec4(0, 0, 1, 1));
|
||||
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, currentBgColor);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(line.sAddress);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(line.sOpCodes);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (pSymbol)
|
||||
{
|
||||
ImGui::TextUnformatted(pSymbol);
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Selectable(buffer, false, ImGuiSelectableFlags_SpanAllColumns);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (bDisasmFormatFlags & DISASM_FORMAT_TARGET_POINTER)
|
||||
{
|
||||
ImGui::TextUnformatted(line.sTargetPointer);
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (bDisasmFormatFlags & DISASM_FORMAT_TARGET_VALUE)
|
||||
{
|
||||
ImGui::TextUnformatted(line.sTargetValue);
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (bDisasmFormatFlags & DISASM_FORMAT_CHAR)
|
||||
{
|
||||
ImGui::TextUnformatted(line.sImmediate);
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
if (bDisasmFormatFlags & DISASM_FORMAT_BRANCH)
|
||||
{
|
||||
ImGui::TextUnformatted(line.sBranch);
|
||||
}
|
||||
|
||||
nAddress += line.nOpbyte;
|
||||
}
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiSettings::drawConsole()
|
||||
{
|
||||
const ImGuiTableFlags flags = ImGuiTableFlags_BordersV | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_ScrollY;
|
||||
if (ImGui::BeginTable("Console", 1, flags))
|
||||
{
|
||||
{
|
||||
for (int i = 0; i < CONSOLE_HEIGHT; ++i)
|
||||
{
|
||||
char line[CONSOLE_WIDTH + 1];
|
||||
line[CONSOLE_WIDTH] = 0;
|
||||
const conchar_t * src = g_aConsoleDisplay[CONSOLE_HEIGHT - i - 1];
|
||||
for (size_t j = 0; j < CONSOLE_WIDTH; ++j)
|
||||
{
|
||||
line[j] = ConsoleChar_GetChar(src[j]);
|
||||
if (!line[j])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (line[0])
|
||||
{
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::TextUnformatted(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
|
||||
void ImGuiSettings::showDebugger(SDLFrame * frame)
|
||||
{
|
||||
if (ImGui::Begin("Debugger", &myShowDebugger))
|
||||
{
|
||||
if (ImGui::BeginTabBar("Settings"))
|
||||
{
|
||||
if (ImGui::BeginTabItem("CPU"))
|
||||
{
|
||||
ImGui::Checkbox("Auto-sync PC", &mySyncCPU);
|
||||
|
||||
// complicated if condition to preserve widget order
|
||||
const bool recalc = mySyncCPU || (ImGui::SameLine(), ImGui::Button("Sync PC"));
|
||||
|
||||
if (ImGui::Button("Step"))
|
||||
{
|
||||
frame->ChangeMode(MODE_STEPPING);
|
||||
frame->Execute(myStepCycles);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::PushItemWidth(150);
|
||||
ImGui::DragInt("cycles", &myStepCycles, 0.2f, 0, 256, "%d");
|
||||
ImGui::PopItemWidth();
|
||||
|
||||
if ((ImGui::SameLine(), ImGui::Button("Run")))
|
||||
{
|
||||
frame->ChangeMode(MODE_RUNNING);
|
||||
}
|
||||
if ((ImGui::SameLine(), ImGui::Button("Pause")))
|
||||
{
|
||||
frame->ChangeMode(MODE_PAUSED);
|
||||
}
|
||||
ImGui::SameLine(); ImGui::Text("%016llu - %04X", g_nCumulativeCycles, regs.pc);
|
||||
|
||||
if (ImGui::SliderInt("PC position", &g_nDisasmCurLine, 0, 100) || recalc)
|
||||
{
|
||||
g_nDisasmCurAddress = regs.pc;
|
||||
DisasmCalcTopBotAddress();
|
||||
}
|
||||
drawDisassemblyTable();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("Console"))
|
||||
{
|
||||
drawConsole();
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
ImGui::EndTabBar();
|
||||
}
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -5,10 +5,12 @@
|
|||
namespace sa2
|
||||
{
|
||||
|
||||
class SDLFrame;
|
||||
|
||||
class ImGuiSettings
|
||||
{
|
||||
public:
|
||||
void show();
|
||||
void show(SDLFrame* frame);
|
||||
float drawMenuBar();
|
||||
|
||||
bool windowed = false;
|
||||
|
@ -16,10 +18,23 @@ namespace sa2
|
|||
private:
|
||||
bool myShowDemo = false;
|
||||
bool myShowSettings = false;
|
||||
bool myShowMemory = false;
|
||||
bool myShowDebugger = false;
|
||||
bool mySyncCPU = true;
|
||||
|
||||
int myStepCycles = 0;
|
||||
int mySpeakerVolume = 50;
|
||||
int myMockingboardVolume = 50;
|
||||
|
||||
MemoryEditor myMainMemoryEditor;
|
||||
MemoryEditor myAuxMemoryEditor;
|
||||
|
||||
void showSettings();
|
||||
void showDebugger(SDLFrame* frame);
|
||||
void showMemory();
|
||||
|
||||
void drawDisassemblyTable();
|
||||
void drawConsole();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -46,6 +46,16 @@ namespace
|
|||
{CPU_65C02, "CPU_65C02"},
|
||||
{CPU_Z80, "CPU_Z80"},
|
||||
};
|
||||
|
||||
const std::map<AppMode_e, std::string> modes =
|
||||
{
|
||||
{MODE_LOGO, "MODE_LOGO"},
|
||||
{MODE_PAUSED, "MODE_PAUSED"},
|
||||
{MODE_RUNNING, "MODE_RUNNING"},
|
||||
{MODE_DEBUG, "MODE_DEBUG"},
|
||||
{MODE_STEPPING, "MODE_STEPPING"},
|
||||
{MODE_BENCHMARK, "MODE_BENCHMARCK"},
|
||||
};
|
||||
}
|
||||
|
||||
namespace sa2
|
||||
|
@ -66,4 +76,9 @@ namespace sa2
|
|||
return cpuTypes.at(cpu);
|
||||
}
|
||||
|
||||
const std::string & getModeName(AppMode_e mode)
|
||||
{
|
||||
return modes.at(mode);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,5 +12,6 @@ namespace sa2
|
|||
const std::string & getCardName(SS_CARDTYPE card);
|
||||
const std::string & getApple2Name(eApple2Type type);
|
||||
const std::string & getCPUName(eCpuType cpu);
|
||||
const std::string & getModeName(AppMode_e mode);
|
||||
|
||||
}
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
#include "NTSC.h"
|
||||
#include "SaveState.h"
|
||||
#include "Interface.h"
|
||||
#include "Mockingboard.h"
|
||||
#include "Speaker.h"
|
||||
|
||||
// comment out to test / debug init / shutdown only
|
||||
#define EMULATOR_RUN
|
||||
|
@ -50,27 +48,9 @@ namespace
|
|||
return current.refresh_rate;
|
||||
}
|
||||
|
||||
void execute(common2::Speed speed, const size_t next)
|
||||
{
|
||||
if (g_nAppMode == MODE_RUNNING)
|
||||
{
|
||||
const size_t cyclesToExecute = speed.getCyclesTillNext(next * 1000);
|
||||
|
||||
const bool bVideoUpdate = true;
|
||||
const UINT dwClksPerFrame = NTSC_GetCyclesPerFrame();
|
||||
|
||||
const DWORD executedCycles = CpuExecute(cyclesToExecute, bVideoUpdate);
|
||||
|
||||
g_dwCyclesThisFrame = (g_dwCyclesThisFrame + executedCycles) % dwClksPerFrame;
|
||||
GetCardMgr().GetDisk2CardMgr().UpdateDriveState(executedCycles);
|
||||
MB_PeriodicUpdate(executedCycles);
|
||||
SpkrUpdate(executedCycles);
|
||||
}
|
||||
}
|
||||
|
||||
struct Data
|
||||
{
|
||||
common2::Speed * speed;
|
||||
sa2::SDLFrame * frame;
|
||||
SDL_mutex * mutex;
|
||||
common2::Timer * timer;
|
||||
};
|
||||
|
@ -81,7 +61,7 @@ namespace
|
|||
SDL_LockMutex(data->mutex);
|
||||
|
||||
data->timer->tic();
|
||||
execute(*data->speed, interval);
|
||||
data->frame->ExecuteOneFrame(interval);
|
||||
data->timer->toc();
|
||||
|
||||
SDL_UnlockMutex(data->mutex);
|
||||
|
@ -100,8 +80,8 @@ void run_sdl(int argc, const char * argv [])
|
|||
const int sw = video.GetFrameBufferBorderlessWidth();
|
||||
const int sh = video.GetFrameBufferBorderlessHeight();
|
||||
|
||||
options.geometry.width = sw;
|
||||
options.geometry.height = sh;
|
||||
options.geometry.width = sw * 2;
|
||||
options.geometry.height = sh * 2;
|
||||
options.geometry.x = SDL_WINDOWPOS_UNDEFINED;
|
||||
options.geometry.y = SDL_WINDOWPOS_UNDEFINED;
|
||||
options.memclear = g_nMemoryClearType;
|
||||
|
@ -156,15 +136,15 @@ void run_sdl(int argc, const char * argv [])
|
|||
}
|
||||
|
||||
const auto redraw = [&frame]{
|
||||
frame->UpdateTexture();
|
||||
frame->RenderPresent();
|
||||
};
|
||||
frame->UpdateTexture();
|
||||
frame->RenderPresent();
|
||||
};
|
||||
|
||||
const auto refresh = [redraw, &video]{
|
||||
NTSC_SetVideoMode( video.GetVideoMode() );
|
||||
NTSC_VideoRedrawWholeScreen();
|
||||
redraw();
|
||||
};
|
||||
NTSC_SetVideoMode( video.GetVideoMode() );
|
||||
NTSC_VideoRedrawWholeScreen();
|
||||
redraw();
|
||||
};
|
||||
|
||||
VideoBenchmark(redraw, refresh);
|
||||
}
|
||||
|
@ -180,8 +160,6 @@ void run_sdl(int argc, const char * argv [])
|
|||
const std::string globalTag = ". .";
|
||||
std::string updateTextureTimerTag, refreshScreenTimerTag, cpuTimerTag, eventTimerTag;
|
||||
|
||||
common2::Speed speed(options.fixedSpeed);
|
||||
|
||||
if (options.multiThreaded)
|
||||
{
|
||||
refreshScreenTimerTag = "0 .";
|
||||
|
@ -189,11 +167,11 @@ void run_sdl(int argc, const char * argv [])
|
|||
eventTimerTag = "0 M";
|
||||
if (options.looseMutex)
|
||||
{
|
||||
updateTextureTimerTag = "0 .";
|
||||
updateTextureTimerTag = "0 .";
|
||||
}
|
||||
else
|
||||
{
|
||||
updateTextureTimerTag = "0 M";
|
||||
updateTextureTimerTag = "0 M";
|
||||
}
|
||||
|
||||
std::shared_ptr<SDL_mutex> mutex(SDL_CreateMutex(), SDL_DestroyMutex);
|
||||
|
@ -201,49 +179,49 @@ void run_sdl(int argc, const char * argv [])
|
|||
Data data;
|
||||
data.mutex = mutex.get();
|
||||
data.timer = &cpuTimer;
|
||||
data.speed = &speed;
|
||||
data.frame = frame.get();
|
||||
|
||||
const SDL_TimerID timer = SDL_AddTimer(options.timerInterval, emulator_callback, &data);
|
||||
|
||||
bool quit = false;
|
||||
do
|
||||
{
|
||||
frameTimer.tic();
|
||||
SDL_LockMutex(data.mutex);
|
||||
frameTimer.tic();
|
||||
SDL_LockMutex(data.mutex);
|
||||
|
||||
eventTimer.tic();
|
||||
sa2::writeAudio();
|
||||
frame->ProcessEvents(quit);
|
||||
eventTimer.toc();
|
||||
eventTimer.tic();
|
||||
sa2::writeAudio();
|
||||
frame->ProcessEvents(quit);
|
||||
eventTimer.toc();
|
||||
|
||||
if (options.looseMutex)
|
||||
{
|
||||
// loose mutex
|
||||
// unlock early and let CPU run again in the timer callback
|
||||
SDL_UnlockMutex(data.mutex);
|
||||
// but the texture will be updated concurrently with the CPU updating the video buffer
|
||||
// pixels are not atomic, so a pixel error could happen (if pixel changes while being read)
|
||||
// on the positive side this will release pressure from CPU and allow for more parallelism
|
||||
}
|
||||
if (options.looseMutex)
|
||||
{
|
||||
// loose mutex
|
||||
// unlock early and let CPU run again in the timer callback
|
||||
SDL_UnlockMutex(data.mutex);
|
||||
// but the texture will be updated concurrently with the CPU updating the video buffer
|
||||
// pixels are not atomic, so a pixel error could happen (if pixel changes while being read)
|
||||
// on the positive side this will release pressure from CPU and allow for more parallelism
|
||||
}
|
||||
|
||||
updateTextureTimer.tic();
|
||||
frame->UpdateTexture();
|
||||
updateTextureTimer.toc();
|
||||
updateTextureTimer.tic();
|
||||
frame->UpdateTexture();
|
||||
updateTextureTimer.toc();
|
||||
|
||||
if (!options.looseMutex)
|
||||
{
|
||||
// safe mutex, only unlock after texture has been updated
|
||||
// this will stop the CPU for longer
|
||||
SDL_UnlockMutex(data.mutex);
|
||||
}
|
||||
if (!options.looseMutex)
|
||||
{
|
||||
// safe mutex, only unlock after texture has been updated
|
||||
// this will stop the CPU for longer
|
||||
SDL_UnlockMutex(data.mutex);
|
||||
}
|
||||
|
||||
if (!options.headless)
|
||||
{
|
||||
refreshScreenTimer.tic();
|
||||
frame->RenderPresent();
|
||||
refreshScreenTimer.toc();
|
||||
}
|
||||
frameTimer.toc();
|
||||
if (!options.headless)
|
||||
{
|
||||
refreshScreenTimer.tic();
|
||||
frame->RenderPresent();
|
||||
refreshScreenTimer.toc();
|
||||
}
|
||||
frameTimer.toc();
|
||||
} while (!quit);
|
||||
|
||||
SDL_RemoveTimer(timer);
|
||||
|
@ -266,28 +244,28 @@ void run_sdl(int argc, const char * argv [])
|
|||
|
||||
do
|
||||
{
|
||||
frameTimer.tic();
|
||||
frameTimer.tic();
|
||||
|
||||
eventTimer.tic();
|
||||
sa2::writeAudio();
|
||||
frame->ProcessEvents(quit);
|
||||
eventTimer.toc();
|
||||
eventTimer.tic();
|
||||
sa2::writeAudio();
|
||||
frame->ProcessEvents(quit);
|
||||
eventTimer.toc();
|
||||
|
||||
cpuTimer.tic();
|
||||
execute(speed, oneFrame);
|
||||
cpuTimer.toc();
|
||||
cpuTimer.tic();
|
||||
frame->ExecuteOneFrame(oneFrame);
|
||||
cpuTimer.toc();
|
||||
|
||||
updateTextureTimer.tic();
|
||||
frame->UpdateTexture();
|
||||
updateTextureTimer.toc();
|
||||
updateTextureTimer.tic();
|
||||
frame->UpdateTexture();
|
||||
updateTextureTimer.toc();
|
||||
|
||||
if (!options.headless)
|
||||
{
|
||||
refreshScreenTimer.tic();
|
||||
frame->RenderPresent();
|
||||
refreshScreenTimer.toc();
|
||||
}
|
||||
frameTimer.toc();
|
||||
if (!options.headless)
|
||||
{
|
||||
refreshScreenTimer.tic();
|
||||
frame->RenderPresent();
|
||||
refreshScreenTimer.toc();
|
||||
}
|
||||
frameTimer.toc();
|
||||
} while (!quit);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#include "Speaker.h"
|
||||
#include "SoundCore.h"
|
||||
#include "Interface.h"
|
||||
#include "NTSC.h"
|
||||
#include "CPU.h"
|
||||
#include "Mockingboard.h"
|
||||
|
||||
#include "linux/paddle.h"
|
||||
#include "linux/keyboard.h"
|
||||
|
@ -329,19 +332,8 @@ namespace sa2
|
|||
}
|
||||
case SDLK_PAUSE:
|
||||
{
|
||||
switch (g_nAppMode)
|
||||
{
|
||||
case MODE_RUNNING:
|
||||
g_nAppMode = MODE_PAUSED;
|
||||
SoundCore_SetFade(FADE_OUT);
|
||||
break;
|
||||
case MODE_PAUSED:
|
||||
g_nAppMode = MODE_RUNNING;
|
||||
SoundCore_SetFade(FADE_IN);
|
||||
mySpeed.reset();
|
||||
break;
|
||||
}
|
||||
GetFrame().FrameRefreshStatus(DRAW_TITLE);
|
||||
const AppMode_e newMode = (g_nAppMode == MODE_RUNNING) ? MODE_PAUSED : MODE_RUNNING;
|
||||
ChangeMode(newMode);
|
||||
break;
|
||||
}
|
||||
case SDLK_CAPSLOCK:
|
||||
|
@ -402,4 +394,48 @@ namespace sa2
|
|||
}
|
||||
}
|
||||
|
||||
void SDLFrame::Execute(const DWORD cyclesToExecute)
|
||||
{
|
||||
const bool bVideoUpdate = true;
|
||||
const UINT dwClksPerFrame = NTSC_GetCyclesPerFrame();
|
||||
|
||||
const DWORD executedCycles = CpuExecute(cyclesToExecute, bVideoUpdate);
|
||||
|
||||
g_dwCyclesThisFrame = (g_dwCyclesThisFrame + executedCycles) % dwClksPerFrame;
|
||||
GetCardMgr().GetDisk2CardMgr().UpdateDriveState(executedCycles);
|
||||
MB_PeriodicUpdate(executedCycles);
|
||||
SpkrUpdate(executedCycles);
|
||||
}
|
||||
|
||||
void SDLFrame::ExecuteOneFrame(const size_t msNextFrame)
|
||||
{
|
||||
// when running in adaptive speed
|
||||
// the value msNextFrame is only a hint for when the next frame will arrive
|
||||
if (g_nAppMode == MODE_RUNNING)
|
||||
{
|
||||
const size_t cyclesToExecute = mySpeed.getCyclesTillNext(msNextFrame * 1000);
|
||||
Execute(cyclesToExecute);
|
||||
}
|
||||
// else do nothing, it is either paused, debugged or stepped
|
||||
}
|
||||
|
||||
void SDLFrame::ChangeMode(const AppMode_e mode)
|
||||
{
|
||||
if (mode != g_nAppMode)
|
||||
{
|
||||
g_nAppMode = mode;
|
||||
switch (g_nAppMode)
|
||||
{
|
||||
case MODE_RUNNING:
|
||||
SoundCore_SetFade(FADE_IN);
|
||||
mySpeed.reset();
|
||||
break;
|
||||
default:
|
||||
SoundCore_SetFade(FADE_OUT);
|
||||
break;
|
||||
}
|
||||
FrameRefreshStatus(DRAW_TITLE);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "Common.h"
|
||||
#include "frontends/common2/commonframe.h"
|
||||
#include "frontends/common2/speed.h"
|
||||
#include <SDL.h>
|
||||
|
@ -24,6 +25,10 @@ namespace sa2
|
|||
|
||||
void ProcessEvents(bool &quit);
|
||||
|
||||
void Execute(const DWORD uCycles);
|
||||
void ExecuteOneFrame(const size_t msNextFrame);
|
||||
void ChangeMode(const AppMode_e mode);
|
||||
|
||||
virtual void UpdateTexture() = 0;
|
||||
virtual void RenderPresent() = 0;
|
||||
|
||||
|
|
|
@ -2,13 +2,172 @@
|
|||
#include "Common.h"
|
||||
|
||||
#include "Debug.h"
|
||||
#include "DebugDefs.h"
|
||||
#include "CPU.h"
|
||||
#include "Core.h"
|
||||
#include "Interface.h"
|
||||
|
||||
const int MIN_DISPLAY_CONSOLE_LINES = 5; // doesn't include ConsoleInput
|
||||
int g_iWindowThis = WINDOW_CODE; // TODO: FIXME! should be offset into WindowConfig!!!
|
||||
|
||||
void WindowUpdateDisasmSize()
|
||||
{
|
||||
g_nDisasmWinHeight = (MAX_DISPLAY_LINES - g_nConsoleDisplayLines) / 2;
|
||||
g_nDisasmCurLine = MAX(0, (g_nDisasmWinHeight - 1) / 2);
|
||||
}
|
||||
|
||||
void WindowUpdateConsoleDisplayedSize()
|
||||
{
|
||||
g_nConsoleDisplayLines = MIN_DISPLAY_CONSOLE_LINES;
|
||||
#if USE_APPLE_FONT
|
||||
g_bConsoleFullWidth = true;
|
||||
g_nConsoleDisplayWidth = CONSOLE_WIDTH - 1;
|
||||
|
||||
if (g_iWindowThis == WINDOW_CONSOLE)
|
||||
{
|
||||
g_nConsoleDisplayLines = MAX_DISPLAY_LINES;
|
||||
g_nConsoleDisplayWidth = CONSOLE_WIDTH - 1;
|
||||
g_bConsoleFullWidth = true;
|
||||
}
|
||||
#else
|
||||
g_nConsoleDisplayWidth = (CONSOLE_WIDTH / 2) + 10;
|
||||
g_bConsoleFullWidth = false;
|
||||
|
||||
// g_bConsoleFullWidth = false;
|
||||
// g_nConsoleDisplayWidth = CONSOLE_WIDTH - 10;
|
||||
|
||||
if (g_iWindowThis == WINDOW_CONSOLE)
|
||||
{
|
||||
g_nConsoleDisplayLines = MAX_DISPLAY_LINES;
|
||||
g_nConsoleDisplayWidth = CONSOLE_WIDTH - 1;
|
||||
g_bConsoleFullWidth = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void InitDisasm()
|
||||
{
|
||||
g_nDisasmCurAddress = regs.pc;
|
||||
DisasmCalcTopBotAddress();
|
||||
}
|
||||
|
||||
void DebugInitialize()
|
||||
{
|
||||
WindowUpdateDisasmSize();
|
||||
WindowUpdateConsoleDisplayedSize();
|
||||
|
||||
extern bool g_bSymbolsDisplayMissingFile;
|
||||
g_bSymbolsDisplayMissingFile = false;
|
||||
|
||||
g_iCommand = CMD_SYMBOLS_ROM;
|
||||
CmdSymbolsLoad(0);
|
||||
|
||||
g_iCommand = CMD_SYMBOLS_APPLESOFT;
|
||||
CmdSymbolsLoad(0);
|
||||
|
||||
g_iCommand = CMD_SYMBOLS_USER_1;
|
||||
CmdSymbolsLoad(0);
|
||||
|
||||
g_bSymbolsDisplayMissingFile = true;
|
||||
}
|
||||
|
||||
void DebugReset(void)
|
||||
{
|
||||
}
|
||||
|
||||
void DebugBegin()
|
||||
{
|
||||
// This is called every time the debugger is entered.
|
||||
g_nAppMode = MODE_DEBUG;
|
||||
GetFrame().FrameRefreshStatus(DRAW_TITLE | DRAW_DISK_STATUS);
|
||||
|
||||
if (GetMainCpu() == CPU_6502)
|
||||
{
|
||||
g_aOpcodes = & g_aOpcodes6502[ 0 ]; // Apple ][, ][+, //e
|
||||
g_aOpmodes[ AM_2 ].m_nBytes = 1;
|
||||
g_aOpmodes[ AM_3 ].m_nBytes = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_aOpcodes = & g_aOpcodes65C02[ 0 ]; // Enhanced Apple //e
|
||||
g_aOpmodes[ AM_2 ].m_nBytes = 2;
|
||||
g_aOpmodes[ AM_3 ].m_nBytes = 3;
|
||||
}
|
||||
|
||||
InitDisasm();
|
||||
}
|
||||
|
||||
|
||||
DWORD extbench = 0;
|
||||
|
||||
void DebugReset(void)
|
||||
// NOTE: BreakpointSource_t and g_aBreakpointSource must match!
|
||||
const char *g_aBreakpointSource[ NUM_BREAKPOINT_SOURCES ] =
|
||||
{ // Used to be one char, since ArgsCook also uses // TODO/FIXME: Parser use Param[] ?
|
||||
// Used for both Input & Output!
|
||||
// Regs
|
||||
"A", // Reg A
|
||||
"X", // Reg X
|
||||
"Y", // Reg Y
|
||||
// Special
|
||||
"PC", // Program Counter -- could use "$"
|
||||
"S" , // Stack Pointer
|
||||
// Flags -- .8 Moved: Flag names from g_aFlagNames[] to "inlined" g_aBreakpointSource[]
|
||||
"P", // Processor Status
|
||||
"C", // ---- ---1 Carry
|
||||
"Z", // ---- --1- Zero
|
||||
"I", // ---- -1-- Interrupt
|
||||
"D", // ---- 1--- Decimal
|
||||
"B", // ---1 ---- Break
|
||||
"R", // --1- ---- Reserved
|
||||
"V", // -1-- ---- Overflow
|
||||
"N", // 1--- ---- Sign
|
||||
// Misc
|
||||
"OP", // Opcode/Instruction/Mnemonic
|
||||
"M", // Mem RW
|
||||
"M", // Mem READ_ONLY
|
||||
"M", // Mem WRITE_ONLY
|
||||
// TODO: M0 ram bank 0, M1 aux ram ?
|
||||
};
|
||||
|
||||
WORD g_nDisasmTopAddress = 0;
|
||||
WORD g_nDisasmBotAddress = 0;
|
||||
WORD g_nDisasmCurAddress = 0;
|
||||
|
||||
bool g_bDisasmCurBad = false;
|
||||
int g_nDisasmCurLine = 0; // Aligned to Top or Center
|
||||
int g_iDisasmCurState = CURSOR_NORMAL;
|
||||
|
||||
int g_nDisasmWinHeight = 0;
|
||||
|
||||
MemorySearchResults_t g_vMemorySearchResults;
|
||||
|
||||
int g_iCommand; // last command (enum) // used for consecutive commands
|
||||
|
||||
bool g_bConfigDisasmAddressView = true;
|
||||
int g_bConfigDisasmClick = 4; // GH#462 alt=1, ctrl=2, shift=4 bitmask (default to Shift-Click)
|
||||
bool g_bConfigDisasmAddressColon = true;
|
||||
bool g_bConfigDisasmOpcodesView = true;
|
||||
bool g_bConfigDisasmOpcodeSpaces = true;
|
||||
int g_iConfigDisasmTargets = DISASM_TARGET_BOTH;
|
||||
int g_iConfigDisasmBranchType = DISASM_BRANCH_FANCY;
|
||||
int g_bConfigDisasmImmediateChar = DISASM_IMMED_BOTH;
|
||||
int g_iConfigDisasmScroll = 3; // favor 3 byte opcodes
|
||||
// Config - Info
|
||||
bool g_bConfigInfoTargetPointer = false;
|
||||
|
||||
MemoryTextFile_t g_ConfigState;
|
||||
|
||||
int FindParam(LPCTSTR pLookupName, Match_e eMatch, int & iParam_, int iParamBegin, int iParamEnd )
|
||||
{
|
||||
throw std::runtime_error("FindParam: not implemented");
|
||||
}
|
||||
|
||||
void DebugDisplay ( BOOL bInitDisasm )
|
||||
void DebugDisplay ( BOOL bInitDisasm )
|
||||
{
|
||||
throw std::runtime_error("DebugDisplay: not implemented");
|
||||
}
|
||||
|
||||
Update_t Help_Arg_1( int iCommandHelp )
|
||||
{
|
||||
throw std::runtime_error("Help_Arg_1: not implemented");
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "linux/windows/strings.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
|
||||
// make all chars in buffer lowercase
|
||||
DWORD CharLowerBuff(LPTSTR lpsz, DWORD cchLength)
|
||||
|
@ -16,3 +17,11 @@ void strcpy_s(char * dest, size_t size, const char * source)
|
|||
{
|
||||
strncpy(dest, source, size);
|
||||
}
|
||||
|
||||
int vsnprintf_s(char *buffer, size_t sizeOfBuffer, size_t count, const char *format, va_list argptr)
|
||||
{
|
||||
// is this even right?
|
||||
const int res = vsnprintf(buffer, sizeOfBuffer, format, argptr);
|
||||
buffer[sizeOfBuffer - 1] = 0;
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -4,9 +4,20 @@
|
|||
|
||||
#include <cstddef>
|
||||
#include <ctype.h>
|
||||
#include <cstdarg>
|
||||
|
||||
void strcpy_s(char * dest, size_t size, const char * source);
|
||||
|
||||
int vsnprintf_s(
|
||||
char *buffer,
|
||||
size_t sizeOfBuffer,
|
||||
size_t count,
|
||||
const char *format,
|
||||
va_list argptr
|
||||
);
|
||||
|
||||
#define _TRUNCATE ((size_t)-1)
|
||||
|
||||
#define sprintf_s snprintf
|
||||
|
||||
#define _strdup strdup
|
||||
|
@ -21,6 +32,8 @@ void strcpy_s(char * dest, size_t size, const char * source);
|
|||
#define _tcschr strchr
|
||||
#define _tcsstr strstr
|
||||
#define _tcscpy strcpy
|
||||
#define _tcstol strtol
|
||||
#define _tcstoul strtoul
|
||||
#define _snprintf snprintf
|
||||
#define wsprintf sprintf
|
||||
#define sscanf_s sscanf
|
||||
|
|
Loading…
Add table
Reference in a new issue