diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 683bcc98..12106ddb 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -60,13 +60,13 @@ set(SOURCE_FILES linux/registry.cpp linux/keyboard.cpp linux/linuxframe.cpp + linux/context.cpp linux/duplicates/Debug.cpp linux/duplicates/Joystick.cpp linux/duplicates/SerialComms.cpp linux/duplicates/PropertySheet.cpp linux/duplicates/Tfe.cpp - linux/duplicates/AppleWin.cpp Z80VICE/z80.cpp Z80VICE/z80mem.cpp diff --git a/source/frontends/sdl/CMakeLists.txt b/source/frontends/sdl/CMakeLists.txt index f215b190..0bd7da18 100644 --- a/source/frontends/sdl/CMakeLists.txt +++ b/source/frontends/sdl/CMakeLists.txt @@ -7,6 +7,7 @@ set(SOURCE_FILES gamepad.cpp sdirectsound.cpp utils.cpp + sdlframe.cpp ) set(HEADER_FILES @@ -14,6 +15,7 @@ set(HEADER_FILES gamepad.h sdirectsound.h utils.h + sdlframe.h ) add_executable(sa2 diff --git a/source/frontends/sdl/emulator.cpp b/source/frontends/sdl/emulator.cpp index 74af1107..7e36cf8a 100644 --- a/source/frontends/sdl/emulator.cpp +++ b/source/frontends/sdl/emulator.cpp @@ -1,13 +1,15 @@ +#include "StdAfx.h" + #include "frontends/sdl/emulator.h" #include "frontends/sdl/sdirectsound.h" #include "frontends/sdl/utils.h" +#include "frontends/sdl/sdlframe.h" #include #include "linux/paddle.h" #include "linux/keyboard.h" -#include "StdAfx.h" #include "Common.h" #include "Interface.h" #include "CardManager.h" @@ -27,38 +29,6 @@ namespace { - void updateWindowTitle(const std::shared_ptr & win) - { - GetAppleWindowTitle(); - SDL_SetWindowTitle(win.get(), g_pAppTitle.c_str()); - } - - void cycleVideoType(const std::shared_ptr & win) - { - Video & video = GetVideo(); - video.IncVideoType(); - - video.VideoReinitialize(false); - video.Config_Save_Video(); - - updateWindowTitle(win); - } - - void cycle50ScanLines(const std::shared_ptr & win) - { - Video & video = GetVideo(); - - VideoStyle_e videoStyle = video.GetVideoStyle(); - videoStyle = VideoStyle_e(videoStyle ^ VS_HALF_SCANLINES); - - video.SetVideoStyle(videoStyle); - - video.VideoReinitialize(false); - video.Config_Save_Video(); - - updateWindowTitle(win); - } - void processAppleKey(const SDL_KeyboardEvent & key) { // using keycode (or scan code) one takes a physical view of the keyboard @@ -141,27 +111,14 @@ namespace Emulator::Emulator( - const std::shared_ptr & window, - const std::shared_ptr & renderer, - const std::shared_ptr & texture, + const std::shared_ptr & frame, const bool fixedSpeed ) - : myWindow(window) - , myRenderer(renderer) - , myTexture(texture) + : myFrame(frame) , myMultiplier(1) , myFullscreen(false) , mySpeed(fixedSpeed) { - Video & video = GetVideo(); - - myRect.x = video.GetFrameBufferBorderWidth(); - myRect.y = video.GetFrameBufferBorderHeight(); - myRect.w = video.GetFrameBufferBorderlessWidth(); - myRect.h = video.GetFrameBufferBorderlessHeight(); - myPitch = video.GetFrameBufferWidth() * sizeof(bgra_t); - - myFrameBuffer = video.GetFrameBuffer(); } void Emulator::execute(const size_t next) @@ -182,17 +139,6 @@ void Emulator::execute(const size_t next) } } -void Emulator::updateTexture() -{ - SDL_UpdateTexture(myTexture.get(), nullptr, myFrameBuffer, myPitch); -} - -void Emulator::refreshVideo() -{ - SDL_RenderCopyEx(myRenderer.get(), myTexture.get(), &myRect, nullptr, 0.0, nullptr, SDL_FLIP_VERTICAL); - SDL_RenderPresent(myRenderer.get()); -} - void Emulator::processEvents(bool & quit) { SDL_Event e; @@ -232,6 +178,7 @@ void Emulator::processKeyDown(const SDL_KeyboardEvent & key, bool & quit) // if the user has decided to change the layout, we just go with it and use the keycode if (!key.repeat) { + const std::shared_ptr & window = myFrame->GetWindow(); switch (key.keysym.sym) { case SDLK_F12: @@ -245,7 +192,7 @@ void Emulator::processKeyDown(const SDL_KeyboardEvent & key, bool & quit) const std::string & pathname = Snapshot_GetPathname(); const std::string message = "Do you want to save the state to " + pathname + "?"; SoundCore_SetFade(FADE_OUT); - if (show_yes_no_dialog(myWindow, "Save state", message)) + if (show_yes_no_dialog(window, "Save state", message)) { Snapshot_SaveState(); } @@ -255,14 +202,14 @@ void Emulator::processKeyDown(const SDL_KeyboardEvent & key, bool & quit) } case SDLK_F9: { - cycleVideoType(myWindow); + myFrame->CycleVideoType(); break; } case SDLK_F6: { if ((key.keysym.mod & KMOD_CTRL) && (key.keysym.mod & KMOD_SHIFT)) { - cycle50ScanLines(myWindow); + myFrame->Cycle50ScanLines(); } else if (key.keysym.mod & KMOD_CTRL) { @@ -270,12 +217,12 @@ void Emulator::processKeyDown(const SDL_KeyboardEvent & key, bool & quit) myMultiplier = myMultiplier == 1 ? 2 : 1; const int sw = video.GetFrameBufferBorderlessWidth(); const int sh = video.GetFrameBufferBorderlessHeight(); - SDL_SetWindowSize(myWindow.get(), sw * myMultiplier, sh * myMultiplier); + SDL_SetWindowSize(window.get(), sw * myMultiplier, sh * myMultiplier); } else if (!(key.keysym.mod & KMOD_SHIFT)) { myFullscreen = !myFullscreen; - SDL_SetWindowFullscreen(myWindow.get(), myFullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); + SDL_SetWindowFullscreen(window.get(), myFullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); } break; } @@ -329,7 +276,7 @@ void Emulator::processKeyDown(const SDL_KeyboardEvent & key, bool & quit) mySpeed.reset(); break; } - updateWindowTitle(myWindow); + GetFrame().FrameRefreshStatus(DRAW_TITLE); break; } } diff --git a/source/frontends/sdl/emulator.h b/source/frontends/sdl/emulator.h index af5b1909..7288027a 100644 --- a/source/frontends/sdl/emulator.h +++ b/source/frontends/sdl/emulator.h @@ -5,21 +5,18 @@ #include "frontends/common2/speed.h" +class SDLFrame; + class Emulator { public: Emulator( - const std::shared_ptr & window, - const std::shared_ptr & renderer, - const std::shared_ptr & texture, + const std::shared_ptr & frame, const bool fixedSpeed ); void execute(const size_t milliseconds); - void updateTexture(); - void refreshVideo(); - void processEvents(bool & quit); private: @@ -27,16 +24,10 @@ private: void processKeyUp(const SDL_KeyboardEvent & key); void processText(const SDL_TextInputEvent & text); - const std::shared_ptr myWindow; - const std::shared_ptr myRenderer; - const std::shared_ptr myTexture; + const std::shared_ptr myFrame; int myMultiplier; bool myFullscreen; Speed mySpeed; - - SDL_Rect myRect; - int myPitch; - uint8_t* myFrameBuffer; }; diff --git a/source/frontends/sdl/main.cpp b/source/frontends/sdl/main.cpp index 0456e646..3dad0012 100644 --- a/source/frontends/sdl/main.cpp +++ b/source/frontends/sdl/main.cpp @@ -1,11 +1,11 @@ -#include #include -#include + +#include #include -#include #include "linux/interface.h" #include "linux/benchmark.h" +#include "linux/context.h" #include "frontends/common2/fileregistry.h" #include "frontends/common2/utils.h" @@ -16,6 +16,7 @@ #include "frontends/sdl/gamepad.h" #include "frontends/sdl/sdirectsound.h" #include "frontends/sdl/utils.h" +#include "frontends/sdl/sdlframe.h" #include "StdAfx.h" #include "Core.h" @@ -30,6 +31,7 @@ namespace { + int getRefreshRate() { SDL_DisplayMode current; @@ -64,16 +66,6 @@ namespace return interval; } - void setApplicationIcon(const std::shared_ptr & win) - { - const std::string path = getResourcePath() + "APPLEWIN.ICO"; - std::shared_ptr icon(IMG_Load(path.c_str()), SDL_FreeSurface); - if (icon) - { - SDL_SetWindowIcon(win.get(), icon.get()); - } - } - } int MessageBox(HWND, const char * text, const char * caption, UINT type) @@ -94,6 +86,9 @@ void run_sdl(int argc, const char * argv []) if (!run) return; + const std::shared_ptr frame(new SDLFrame(options)); + SetFrame(frame); + if (options.log) { LogInit(); @@ -110,38 +105,10 @@ void run_sdl(int argc, const char * argv []) Video & video = GetVideo(); - const int width = video.GetFrameBufferWidth(); - const int height = video.GetFrameBufferHeight(); - const int sw = video.GetFrameBufferBorderlessWidth(); - const int sh = video.GetFrameBufferBorderlessHeight(); - - std::cerr << std::fixed << std::setprecision(2); - - std::shared_ptr win(SDL_CreateWindow(g_pAppTitle.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, sw, sh, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE), SDL_DestroyWindow); - if (!win) - { - std::cerr << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl; - return; - } - - setApplicationIcon(win); - - std::shared_ptr ren(SDL_CreateRenderer(win.get(), options.sdlDriver, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC), SDL_DestroyRenderer); - if (!ren) - { - std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl; - return; - } - - const Uint32 format = SDL_PIXELFORMAT_ARGB8888; - printRendererInfo(std::cerr, ren, format, options.sdlDriver); - - std::shared_ptr tex(SDL_CreateTexture(ren.get(), format, SDL_TEXTUREACCESS_STATIC, width, height), SDL_DestroyTexture); - const int fps = getRefreshRate(); std::cerr << "Video refresh rate: " << fps << " Hz, " << 1000.0 / fps << " ms" << std::endl; - Emulator emulator(win, ren, tex, options.fixedSpeed); + Emulator emulator(frame, options.fixedSpeed); #ifdef EMULATOR_RUN if (options.benchmark) @@ -151,10 +118,10 @@ void run_sdl(int argc, const char * argv []) const int res = SDL_GL_SetSwapInterval(0); // if this fails, should we throw, print something or just ignore? - const auto redraw = [&emulator, res]{ - emulator.updateTexture(); + const auto redraw = [&frame, res]{ + frame->UpdateTexture(); if (res == 0) { - emulator.refreshVideo(); + frame->RenderPresent(); } }; @@ -221,7 +188,7 @@ void run_sdl(int argc, const char * argv []) } updateTextureTimer.tic(); - emulator.updateTexture(); + frame->UpdateTexture(); updateTextureTimer.toc(); if (!options.looseMutex) @@ -234,7 +201,7 @@ void run_sdl(int argc, const char * argv []) if (!options.headless) { refreshScreenTimer.tic(); - emulator.refreshVideo(); + frame->RenderPresent(); refreshScreenTimer.toc(); } @@ -270,13 +237,13 @@ void run_sdl(int argc, const char * argv []) cpuTimer.toc(); updateTextureTimer.tic(); - emulator.updateTexture(); + frame->UpdateTexture(); updateTextureTimer.toc(); if (!options.headless) { refreshScreenTimer.tic(); - emulator.refreshVideo(); + frame->RenderPresent(); refreshScreenTimer.toc(); } } while (!quit); @@ -324,9 +291,9 @@ int main(int argc, const char * argv []) std::cerr << e.what() << std::endl; } - // this must happen BEFORE the SDL_Quit() as otherwise we have a double free (of the game controller). Paddle::instance.reset(); + SetFrame(std::shared_ptr()); SDL_Quit(); return exit; diff --git a/source/frontends/sdl/sdlframe.cpp b/source/frontends/sdl/sdlframe.cpp new file mode 100644 index 00000000..a574a501 --- /dev/null +++ b/source/frontends/sdl/sdlframe.cpp @@ -0,0 +1,94 @@ +#include "StdAfx.h" +#include "frontends/sdl/sdlframe.h" +#include "frontends/sdl/utils.h" +#include "frontends/common2/programoptions.h" +#include "frontends/common2/resources.h" + +#include "Interface.h" +#include "Core.h" +#include "Utilities.h" + +#include +#include + +#include + +SDLFrame::SDLFrame(const EmulatorOptions & options) +{ + Video & video = GetVideo(); + + const int width = video.GetFrameBufferWidth(); + const int height = video.GetFrameBufferHeight(); + const int sw = video.GetFrameBufferBorderlessWidth(); + const int sh = video.GetFrameBufferBorderlessHeight(); + + std::cerr << std::fixed << std::setprecision(2); + + myWindow.reset(SDL_CreateWindow(g_pAppTitle.c_str(), SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, sw, sh, SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE), SDL_DestroyWindow); + if (!myWindow) + { + std::cerr << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl; + return; + } + + SetApplicationIcon(); + + myRenderer.reset(SDL_CreateRenderer(myWindow.get(), options.sdlDriver, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC), SDL_DestroyRenderer); + if (!myRenderer) + { + std::cout << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl; + return; + } + + const Uint32 format = SDL_PIXELFORMAT_ARGB8888; + printRendererInfo(std::cerr, myRenderer, format, options.sdlDriver); + + myTexture.reset(SDL_CreateTexture(myRenderer.get(), format, SDL_TEXTUREACCESS_STATIC, width, height), SDL_DestroyTexture); + + myRect.x = video.GetFrameBufferBorderWidth(); + myRect.y = video.GetFrameBufferBorderHeight(); + myRect.w = video.GetFrameBufferBorderlessWidth(); + myRect.h = video.GetFrameBufferBorderlessHeight(); + myPitch = video.GetFrameBufferWidth() * sizeof(bgra_t); +} + +void SDLFrame::FrameRefreshStatus(int drawflags) +{ + if (drawflags & DRAW_TITLE) + { + GetAppleWindowTitle(); + SDL_SetWindowTitle(myWindow.get(), g_pAppTitle.c_str()); + } +} + +void SDLFrame::SetApplicationIcon() +{ + const std::string path = getResourcePath() + "APPLEWIN.ICO"; + std::shared_ptr icon(IMG_Load(path.c_str()), SDL_FreeSurface); + if (icon) + { + SDL_SetWindowIcon(myWindow.get(), icon.get()); + } +} + +void SDLFrame::UpdateTexture() +{ + SDL_UpdateTexture(myTexture.get(), nullptr, myFramebuffer.data(), myPitch); +} + +void SDLFrame::RenderPresent() +{ + SDL_RenderCopyEx(myRenderer.get(), myTexture.get(), &myRect, nullptr, 0.0, nullptr, SDL_FLIP_VERTICAL); + SDL_RenderPresent(myRenderer.get()); +} + +void SDLFrame::VideoPresentScreen() +{ + UpdateTexture(); + RenderPresent(); +} + +const std::shared_ptr & SDLFrame::GetWindow() const +{ + return myWindow; +} diff --git a/source/frontends/sdl/sdlframe.h b/source/frontends/sdl/sdlframe.h new file mode 100644 index 00000000..58be4274 --- /dev/null +++ b/source/frontends/sdl/sdlframe.h @@ -0,0 +1,30 @@ +#pragma once + +#include "linux/linuxframe.h" +#include + +class EmulatorOptions; + +class SDLFrame : public LinuxFrame +{ +public: + SDLFrame(const EmulatorOptions & options); + + virtual void VideoPresentScreen(); + virtual void FrameRefreshStatus(int drawflags); + + void UpdateTexture(); + void RenderPresent(); + + const std::shared_ptr & GetWindow() const; + +private: + void SetApplicationIcon(); + + SDL_Rect myRect; + int myPitch; + + std::shared_ptr myWindow; + std::shared_ptr myRenderer; + std::shared_ptr myTexture; +}; diff --git a/source/linux/duplicates/AppleWin.cpp b/source/linux/context.cpp similarity index 61% rename from source/linux/duplicates/AppleWin.cpp rename to source/linux/context.cpp index 19071ad1..d1fbf9fd 100644 --- a/source/linux/duplicates/AppleWin.cpp +++ b/source/linux/context.cpp @@ -1,9 +1,16 @@ #include "StdAfx.h" +#include "linux/context.h" + #include "Interface.h" #include "linux/duplicates/PropertySheet.h" #include "linux/linuxframe.h" +namespace +{ + std::shared_ptr sg_LinuxFrame; +} + IPropertySheet& GetPropertySheet() { static CPropertySheet sg_PropertySheet; @@ -12,8 +19,12 @@ IPropertySheet& GetPropertySheet() FrameBase& GetFrame() { - static LinuxFrame sg_LinuxFrame; - return sg_LinuxFrame; + return *sg_LinuxFrame; +} + +void SetFrame(const std::shared_ptr & frame) +{ + sg_LinuxFrame = frame; } Video& GetVideo() diff --git a/source/linux/context.h b/source/linux/context.h new file mode 100644 index 00000000..427b3ace --- /dev/null +++ b/source/linux/context.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +class FrameBase; + +void SetFrame(const std::shared_ptr & frame); diff --git a/source/linux/linuxframe.cpp b/source/linux/linuxframe.cpp index 85fc29df..c0b7c02d 100644 --- a/source/linux/linuxframe.cpp +++ b/source/linux/linuxframe.cpp @@ -10,7 +10,7 @@ void LinuxFrame::FrameDrawDiskStatus() { } -void LinuxFrame::FrameRefreshStatus(int drawflags) +void LinuxFrame::FrameRefreshStatus(int /* drawflags */) { } @@ -51,13 +51,13 @@ void LinuxFrame::Initialize() const size_t numberOfPixels = video.GetFrameBufferWidth() * video.GetFrameBufferHeight(); const size_t numberOfBytes = sizeof(bgra_t) * numberOfPixels; - myFramebufferbits.resize(numberOfBytes); - video.Initialize(myFramebufferbits.data()); + myFramebuffer.resize(numberOfBytes); + video.Initialize(myFramebuffer.data()); } void LinuxFrame::Destroy() { - myFramebufferbits.clear(); + myFramebuffer.clear(); GetVideo().Destroy(); // this resets the Video's FrameBuffer pointer } @@ -76,3 +76,36 @@ void LinuxFrame::Benchmark() void LinuxFrame::DisplayLogo() { } + +void LinuxFrame::ApplyVideoModeChange() +{ + // this is similar to Win32Frame::ApplyVideoModeChange + // but it does not refresh the screen + // TODO see if the screen should refresh right now + Video & video = GetVideo(); + + video.VideoReinitialize(false); + video.Config_Save_Video(); + + FrameRefreshStatus(DRAW_TITLE); +} + +void LinuxFrame::CycleVideoType() +{ + Video & video = GetVideo(); + video.IncVideoType(); + + ApplyVideoModeChange(); +} + +void LinuxFrame::Cycle50ScanLines() +{ + Video & video = GetVideo(); + + VideoStyle_e videoStyle = video.GetVideoStyle(); + videoStyle = VideoStyle_e(videoStyle ^ VS_HALF_SCANLINES); + + video.SetVideoStyle(videoStyle); + + ApplyVideoModeChange(); +} diff --git a/source/linux/linuxframe.h b/source/linux/linuxframe.h index 3f6bb2c3..76a99edb 100644 --- a/source/linux/linuxframe.h +++ b/source/linux/linuxframe.h @@ -28,6 +28,11 @@ public: virtual void Benchmark(); virtual void DisplayLogo(); -private: - std::vector myFramebufferbits; + void CycleVideoType(); + void Cycle50ScanLines(); + +protected: + void ApplyVideoModeChange(); + + std::vector myFramebuffer; };