Merge pull request #27 from audetto/memory

Memory
This commit is contained in:
Andrea 2021-03-18 19:41:15 +00:00 committed by GitHub
commit 199a344e37
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 653 additions and 106 deletions

3
.gitmodules vendored
View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -53,6 +53,7 @@ typedef UINT64 uint64_t;
#include <stdexcept>
#include <cstdarg>
#include <cstring>
#include <algorithm>
#include "linux/win.h"

View file

@ -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()

View file

@ -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

View file

@ -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

@ -0,0 +1 @@
Subproject commit 02e679b7f4cfb01f9480dcbcac59552879f96573

View file

@ -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();

View file

@ -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();
}
}

View file

@ -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();
};
}

View file

@ -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);
}
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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);
}
}
}

View file

@ -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;

View file

@ -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");
}

View file

@ -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;
}

View file

@ -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