From 5429c5fac19bc4e019ed13fdbff85a0dd2bc5892 Mon Sep 17 00:00:00 2001 From: Pablo Rodriguez Date: Thu, 28 Nov 2024 04:08:37 -0500 Subject: [PATCH] implemented DisplaySDL --- CMakeLists.txt | 2 +- DisplaySDL.cpp | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ DisplaySDL.hpp | 18 ++++++++++++ Peripherals.hpp | 6 ++-- main.cpp | 15 +++++++++- 5 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 DisplaySDL.cpp create mode 100644 DisplaySDL.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 1187052..b0b5ee0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,5 +5,5 @@ SET(CMAKE_BUILD_TYPE Debug) add_subdirectory(submodules/sdl2) SET(CMAKE_EXPORT_COMPILE_COMMANDS ON) -add_executable(chocochip8 main.cpp Interpreter.cpp BuzzerSDL.cpp) +add_executable(chocochip8 main.cpp Interpreter.cpp DisplaySDL.cpp BuzzerSDL.cpp) target_link_libraries(chocochip8 SDL2::SDL2-static) diff --git a/DisplaySDL.cpp b/DisplaySDL.cpp new file mode 100644 index 0000000..9303a6e --- /dev/null +++ b/DisplaySDL.cpp @@ -0,0 +1,77 @@ +#include "DisplaySDL.hpp" + +#include + +DisplaySDL::DisplaySDL(int w, int h, uint32_t fgColor, uint32_t bgColor) { + // Create SDL Window + mpWindow = SDL_CreateWindow( + "ChocoChip-8", + SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + w, h, + 0 + ); + if(mpWindow == NULL) { + throw std::runtime_error(SDL_GetError()); + } + + // Convert our foreground/background colors to the format expected by SDL + SDL_PixelFormat *fmt = SDL_AllocFormat(SDL_GetWindowPixelFormat(mpWindow)); + mFgColor = SDL_MapRGB( + fmt, + (fgColor & 0x00FF0000) >> 16, + (fgColor & 0x0000FF00) >> 8, + (fgColor & 0x000000FF) + ); + mBgColor = SDL_MapRGB( + fmt, + (bgColor & 0x00FF0000) >> 16, + (bgColor & 0x0000FF00) >> 8, + (bgColor & 0x000000FF) + ); + SDL_FreeFormat(fmt); +}; + +DisplaySDL::~DisplaySDL() { + SDL_DestroyWindow(mpWindow); +} + +void DisplaySDL::updateWindow() const { + SDL_Surface *pSurface = SDL_GetWindowSurface(mpWindow); + SDL_LockSurface(pSurface); + + int fx, fy; // ChocoChip8 Framebuffer coordinates + int sx, sy; // SDL Surface coordinates + int lx, ly; // Last-used ChocoChip8 Framebuffer coordinates + Uint32 lc; // Last-used SDL color + + // Fill the entire SDL surface, one pixel at a time + lx = -1; + ly = -1; + for(sy = 0; sy < pSurface->h; sy++) { + for(sx = 0; sx < pSurface->w; sx++) { + // Map SDL surface coordinates to Chocochip8 Framebuffer coordinates + fx = sx * (double(chocochip8::gcWidth) / pSurface->w); + fy = sy * (double(chocochip8::gcHeight) / pSurface->h); + + // Reuse color if this screen pixel maps to the same ChocoChip8 pixel as the last + if(fx != lx || fy != ly) { + lx = fx; + ly = ly; + // Read Chocochip8 Framebuffer and choose appropriate color, + // note that the MSB of an scanline's bitset is the leftmost pixel. + lc = (mpFramebuffer->at(fy)[(chocochip8::gcWidth - 1) - fx] ? mFgColor : mBgColor); + } + + // Convert (x, y) indexes into SDL Surface pixel array index + Uint32 *pPixel = static_cast(static_cast( + static_cast(pSurface->pixels) + + sy * pSurface->pitch + + sx * pSurface->format->BytesPerPixel + )); + *pPixel = lc; + } + } + + SDL_UnlockSurface(pSurface); + SDL_UpdateWindowSurface(mpWindow); +} diff --git a/DisplaySDL.hpp b/DisplaySDL.hpp new file mode 100644 index 0000000..6f88350 --- /dev/null +++ b/DisplaySDL.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "Peripherals.hpp" + +#include +#include + +class DisplaySDL : public chocochip8::Display { +public: + DisplaySDL(int w, int h, uint32_t fgCol, uint32_t bgCol); + ~DisplaySDL() override; + void updateWindow() const; + +private: + SDL_Window *mpWindow; + Uint32 mFgColor; + Uint32 mBgColor; +}; diff --git a/Peripherals.hpp b/Peripherals.hpp index b69c3ef..7ed23a7 100644 --- a/Peripherals.hpp +++ b/Peripherals.hpp @@ -6,8 +6,10 @@ namespace chocochip8 { - using Scanline = std::bitset<128>; - using Framebuffer = std::array; + constexpr size_t gcWidth = 128; + constexpr size_t gcHeight = 64; + using Scanline = std::bitset; + using Framebuffer = std::array; enum class Key { KEY_0, KEY_1, KEY_2, KEY_3, diff --git a/main.cpp b/main.cpp index 766ed8b..2b1513b 100644 --- a/main.cpp +++ b/main.cpp @@ -2,6 +2,8 @@ #include #include "BuzzerSDL.hpp" +#include "DisplaySDL.hpp" +#include "Peripherals.hpp" int main(int argc, char* args[]) { if (SDL_Init(SDL_INIT_EVERYTHING) < 0) { @@ -9,11 +11,22 @@ int main(int argc, char* args[]) { return 1; } + class DisplayTest : public DisplaySDL { + public: + DisplayTest() : DisplaySDL(1280, 640, 0xff0000, 0x00ff00) { + for(int i = 0; i < chocochip8::gcHeight; i+=2) { + mpFramebuffer->at(i).set(); + } + } + }; + BuzzerSDL buzzer(440); - buzzer.on(); + //buzzer.on(); + DisplayTest display; SDL_Event event; while(SDL_WaitEvent(&event) && event.type != SDL_QUIT) { + display.updateWindow(); } buzzer.off();