From aac2c5139a0c874a19d31814362546d837677862 Mon Sep 17 00:00:00 2001 From: "mariofutire@gmail.com" Date: Sun, 11 Oct 2020 16:34:19 +0100 Subject: [PATCH] Split event handling and "video" state to separate class. Signed-off-by: mariofutire@gmail.com --- source/frontends/sa2/CMakeLists.txt | 1 + source/frontends/sa2/emulator.cpp | 233 ++++++++++++++++++++++++++++ source/frontends/sa2/emulator.h | 29 ++++ source/frontends/sa2/main.cpp | 185 +--------------------- 4 files changed, 267 insertions(+), 181 deletions(-) create mode 100644 source/frontends/sa2/emulator.cpp create mode 100644 source/frontends/sa2/emulator.h diff --git a/source/frontends/sa2/CMakeLists.txt b/source/frontends/sa2/CMakeLists.txt index 5a85e99c..afdf0dc7 100644 --- a/source/frontends/sa2/CMakeLists.txt +++ b/source/frontends/sa2/CMakeLists.txt @@ -3,6 +3,7 @@ include(FindPkgConfig) add_executable(sa2 main.cpp bitmaps.cpp + emulator.cpp ) find_package(Boost REQUIRED diff --git a/source/frontends/sa2/emulator.cpp b/source/frontends/sa2/emulator.cpp new file mode 100644 index 00000000..6e578c52 --- /dev/null +++ b/source/frontends/sa2/emulator.cpp @@ -0,0 +1,233 @@ +#include "frontends/sa2/emulator.h" + +#include + +#include "linux/data.h" +#include "linux/paddle.h" + +#include "StdAfx.h" +#include "Common.h" +#include "CardManager.h" +#include "Applewin.h" +#include "Disk.h" +#include "CPU.h" +#include "Frame.h" +#include "Video.h" +#include "NTSC.h" + +namespace +{ + + SDL_Rect refreshTexture(const std::shared_ptr & tex) + { + uint8_t * data; + int width; + int height; + int sx, sy; + int sw, sh; + + getScreenData(data, width, height, sx, sy, sw, sh); + + void * pixels; + int pitch; + SDL_LockTexture(tex.get(), nullptr, &pixels, &pitch); + + memcpy(pixels, data, width * height * 4); + + SDL_UnlockTexture(tex.get()); + + SDL_Rect srect; + srect.x = sx; + srect.y = sy; + srect.w = sw; + srect.h = sh; + + return srect; + } + + void renderScreen(const std::shared_ptr & ren, const std::shared_ptr & tex, const SDL_Rect & srect) + { + SDL_RenderCopyEx(ren.get(), tex.get(), &srect, nullptr, 0.0, nullptr, SDL_FLIP_VERTICAL); + SDL_RenderPresent(ren.get()); + } + + void cycleVideoType(const std::shared_ptr & win) + { + g_eVideoType++; + if (g_eVideoType >= NUM_VIDEO_MODES) + g_eVideoType = 0; + + SetWindowTitle(); + SDL_SetWindowTitle(win.get(), g_pAppTitle.c_str()); + + Config_Save_Video(); + VideoReinitialize(); + VideoRedrawScreen(); + } + + void cycle50ScanLines(const std::shared_ptr & win) + { + VideoStyle_e videoStyle = GetVideoStyle(); + videoStyle = VideoStyle_e(videoStyle ^ VS_HALF_SCANLINES); + + SetVideoStyle(videoStyle); + + SetWindowTitle(); + SDL_SetWindowTitle(win.get(), g_pAppTitle.c_str()); + + Config_Save_Video(); + VideoReinitialize(); + VideoRedrawScreen(); + } + + int getFPS() + { + SDL_DisplayMode current; + + int should_be_zero = SDL_GetCurrentDisplayMode(0, ¤t); + + if (should_be_zero) + { + throw std::runtime_error(SDL_GetError()); + } + + return current.refresh_rate; + } + +} + + +Emulator::Emulator( + const std::shared_ptr & window, + const std::shared_ptr & renderer, + const std::shared_ptr & texture +) + : myWindow(window) + , myRenderer(renderer) + , myTexture(texture) + , myFPS(getFPS()) + , myMultiplier(1) + , myFullscreen(false) +{ +} + +void Emulator::executeOneFrame() +{ + const DWORD uCyclesToExecute = int(g_fCurrentCLK6502 / myFPS); + const UINT dwClksPerFrame = NTSC_GetCyclesPerFrame(); + const bool bVideoUpdate = true; + const DWORD uActualCyclesExecuted = CpuExecute(uCyclesToExecute, bVideoUpdate); + g_dwCyclesThisFrame += uActualCyclesExecuted; + + g_CardMgr.GetDisk2CardMgr().UpdateDriveState(uActualCyclesExecuted); + + // SDL2 seems to synch with screen refresh rate so we do not need to worry about timers + const SDL_Rect srect = refreshTexture(myTexture); + renderScreen(myRenderer, myTexture, srect); + + g_dwCyclesThisFrame = (g_dwCyclesThisFrame + g_dwCyclesThisFrame) % dwClksPerFrame; +} + +void Emulator::processEvents(bool & quit) +{ + SDL_Event e; + while (SDL_PollEvent(&e) != 0) + { + switch (e.type) + { + case SDL_QUIT: + { + quit = true; + break; + } + case SDL_KEYDOWN: + { + processKeyDown(e, quit); + break; + } + case SDL_KEYUP: + { + processKeyUp(e); + break; + } + } + } +} + +void Emulator::processKeyDown(const SDL_Event & e, bool & quit) +{ + if (!e.key.repeat) + { + switch (e.key.keysym.scancode) + { + case SDL_SCANCODE_F9: + { + cycleVideoType(myWindow); + break; + } + case SDL_SCANCODE_F6: + { + if ((e.key.keysym.mod & KMOD_CTRL) && (e.key.keysym.mod & KMOD_SHIFT)) + { + cycle50ScanLines(myWindow); + } + else if (e.key.keysym.mod & KMOD_CTRL) + { + myMultiplier = myMultiplier == 1 ? 2 : 1; + const int sw = GetFrameBufferBorderlessWidth(); + const int sh = GetFrameBufferBorderlessHeight(); + SDL_SetWindowSize(myWindow.get(), sw * myMultiplier, sh * myMultiplier); + } + else if (!(e.key.keysym.mod & KMOD_SHIFT)) + { + myFullscreen = !myFullscreen; + SDL_SetWindowFullscreen(myWindow.get(), myFullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); + } + break; + } + case SDL_SCANCODE_F5: + { + if (g_CardMgr.QuerySlot(SLOT6) == CT_Disk2) + { + dynamic_cast(g_CardMgr.GetObj(SLOT6))->DriveSwap(); + } + break; + } + case SDL_SCANCODE_F2: + { + quit = true; + break; + } + case SDL_SCANCODE_LALT: + { + Paddle::setButtonPressed(Paddle::ourOpenApple); + break; + } + case SDL_SCANCODE_RALT: + { + Paddle::setButtonPressed(Paddle::ourSolidApple); + break; + } + } + } + std::cerr << "KEY DOWN: " << e.key.keysym.scancode << "," << e.key.keysym.sym << "," << e.key.keysym.mod << "," << bool(e.key.repeat) << std::endl; + +} + +void Emulator::processKeyUp(const SDL_Event & e) +{ + switch (e.key.keysym.scancode) + { + case SDL_SCANCODE_LALT: + { + Paddle::setButtonReleased(Paddle::ourOpenApple); + break; + } + case SDL_SCANCODE_RALT: + { + Paddle::setButtonReleased(Paddle::ourSolidApple); + break; + } + } + std::cerr << "KEY UP: " << e.key.keysym.scancode << "," << e.key.keysym.sym << "," << e.key.keysym.mod << "," << bool(e.key.repeat) << std::endl; +} diff --git a/source/frontends/sa2/emulator.h b/source/frontends/sa2/emulator.h new file mode 100644 index 00000000..06872fe0 --- /dev/null +++ b/source/frontends/sa2/emulator.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +class Emulator +{ +public: + Emulator( + const std::shared_ptr & window, + const std::shared_ptr & renderer, + const std::shared_ptr & texture + ); + + void executeOneFrame(); + void processEvents(bool & quit); + +private: + void processKeyDown(const SDL_Event & e, bool & quit); + void processKeyUp(const SDL_Event & e); + + const std::shared_ptr myWindow; + const std::shared_ptr myRenderer; + const std::shared_ptr myTexture; + const int myFPS; + + int myMultiplier; + bool myFullscreen; +}; diff --git a/source/frontends/sa2/main.cpp b/source/frontends/sa2/main.cpp index 1cac1730..2b1e6b29 100644 --- a/source/frontends/sa2/main.cpp +++ b/source/frontends/sa2/main.cpp @@ -10,6 +10,7 @@ #include "frontends/common2/configuration.h" #include "frontends/common2/utils.h" #include "frontends/common2/programoptions.h" +#include "frontends/sa2/emulator.h" #include "StdAfx.h" #include "Common.h" @@ -106,82 +107,6 @@ namespace LogDone(); } - SDL_Rect refreshTexture(const std::shared_ptr & tex) - { - uint8_t * data; - int width; - int height; - int sx, sy; - int sw, sh; - - getScreenData(data, width, height, sx, sy, sw, sh); - - void * pixels; - int pitch; - SDL_LockTexture(tex.get(), nullptr, &pixels, &pitch); - - memcpy(pixels, data, width * height * 4); - - SDL_UnlockTexture(tex.get()); - - SDL_Rect srect; - srect.x = sx; - srect.y = sy; - srect.w = sw; - srect.h = sh; - - return srect; - } - - void renderScreen(const std::shared_ptr & ren, const std::shared_ptr & tex, const SDL_Rect & srect) - { - SDL_RenderCopyEx(ren.get(), tex.get(), &srect, nullptr, 0.0, nullptr, SDL_FLIP_VERTICAL); - SDL_RenderPresent(ren.get()); - } - - void cycleVideoType(const std::shared_ptr & win) - { - g_eVideoType++; - if (g_eVideoType >= NUM_VIDEO_MODES) - g_eVideoType = 0; - - SetWindowTitle(); - SDL_SetWindowTitle(win.get(), g_pAppTitle.c_str()); - - Config_Save_Video(); - VideoReinitialize(); - VideoRedrawScreen(); - } - - void cycle50ScanLines(const std::shared_ptr & win) - { - VideoStyle_e videoStyle = GetVideoStyle(); - videoStyle = VideoStyle_e(videoStyle ^ VS_HALF_SCANLINES); - - SetVideoStyle(videoStyle); - - SetWindowTitle(); - SDL_SetWindowTitle(win.get(), g_pAppTitle.c_str()); - - Config_Save_Video(); - VideoReinitialize(); - VideoRedrawScreen(); - } - - int getFPS() - { - SDL_DisplayMode current; - - int should_be_zero = SDL_GetCurrentDisplayMode(0, ¤t); - - if (should_be_zero) - { - throw std::runtime_error(SDL_GetError()); - } - - return current.refresh_rate; - } - } int MessageBox(HWND, const char * text, const char * caption, UINT type) @@ -248,9 +173,6 @@ void run_sdl(int argc, const char * argv []) const int sw = GetFrameBufferBorderlessWidth(); const int sh = GetFrameBufferBorderlessHeight(); - int multiplier = 1; - bool fullscreen = false; - std::shared_ptr win(SDL_CreateWindow(g_pAppTitle.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, sw, sh, SDL_WINDOW_SHOWN), SDL_DestroyWindow); if (!win) { @@ -268,112 +190,13 @@ void run_sdl(int argc, const char * argv []) const Uint32 format = SDL_PIXELFORMAT_BGRA32; std::shared_ptr tex(SDL_CreateTexture(ren.get(), format, SDL_TEXTUREACCESS_STREAMING, width, height), SDL_DestroyTexture); - const int fps = getFPS(); - const DWORD uCyclesToExecute = int(g_fCurrentCLK6502 / fps); - const UINT dwClksPerFrame = NTSC_GetCyclesPerFrame(); + Emulator emulator(win, ren, tex); bool quit = false; do { - SDL_Event e; - while (SDL_PollEvent(&e) != 0) - { - switch (e.type) - { - case SDL_QUIT: - { - quit = true; - break; - } - case SDL_KEYDOWN: - { - if (!e.key.repeat) - { - switch (e.key.keysym.scancode) - { - case SDL_SCANCODE_F9: - { - cycleVideoType(win); - break; - } - case SDL_SCANCODE_F6: - { - if ((e.key.keysym.mod & KMOD_CTRL) && (e.key.keysym.mod & KMOD_SHIFT)) - { - cycle50ScanLines(win); - } - else if (e.key.keysym.mod & KMOD_CTRL) - { - multiplier = multiplier == 1 ? 2 : 1; - SDL_SetWindowSize(win.get(), sw * multiplier, sh * multiplier); - } - else if (!(e.key.keysym.mod & KMOD_SHIFT)) - { - fullscreen = !fullscreen; - SDL_SetWindowFullscreen(win.get(), fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); - } - break; - } - case SDL_SCANCODE_F5: - { - if (g_CardMgr.QuerySlot(SLOT6) == CT_Disk2) - { - dynamic_cast(g_CardMgr.GetObj(SLOT6))->DriveSwap(); - } - break; - } - case SDL_SCANCODE_F2: - { - quit = true; - break; - } - case SDL_SCANCODE_LALT: - { - Paddle::setButtonPressed(Paddle::ourOpenApple); - break; - } - case SDL_SCANCODE_RALT: - { - Paddle::setButtonPressed(Paddle::ourSolidApple); - break; - } - } - } - std::cerr << "KEY DOWN: " << e.key.keysym.scancode << "," << e.key.keysym.sym << "," << e.key.keysym.mod << "," << bool(e.key.repeat) << std::endl; - break; - } - case SDL_KEYUP: - { - switch (e.key.keysym.scancode) - { - case SDL_SCANCODE_LALT: - { - Paddle::setButtonReleased(Paddle::ourOpenApple); - break; - } - case SDL_SCANCODE_RALT: - { - Paddle::setButtonReleased(Paddle::ourSolidApple); - break; - } - } - std::cerr << "KEY UP: " << e.key.keysym.scancode << "," << e.key.keysym.sym << "," << e.key.keysym.mod << "," << bool(e.key.repeat) << std::endl; - break; - } - } - } - - const bool bVideoUpdate = true; - const DWORD uActualCyclesExecuted = CpuExecute(uCyclesToExecute, bVideoUpdate); - g_dwCyclesThisFrame += uActualCyclesExecuted; - - g_CardMgr.GetDisk2CardMgr().UpdateDriveState(uActualCyclesExecuted); - - // SDL2 seems to synch with screen refresh rate so we do not need to worry about timers - const SDL_Rect srect = refreshTexture(tex); - renderScreen(ren, tex, srect); - - g_dwCyclesThisFrame = (g_dwCyclesThisFrame + g_dwCyclesThisFrame) % dwClksPerFrame; + emulator.processEvents(quit); + emulator.executeOneFrame(); } while (!quit); stopEmulator();