#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::clear() { Display::clear(); SDL_FillRect(SDL_GetWindowSurface(mpWindow), nullptr, mBgColor); SDL_UpdateWindowSurface(mpWindow); miTopDirtyScanline = chocochip8::gcHeight - 1; miBottomDirtyScanline = 0; } void DisplaySDL::updateWindow() const { if(miTopDirtyScanline > miBottomDirtyScanline) { // No changes since the last update return; } SDL_Surface *pSurface = SDL_GetWindowSurface(mpWindow); for(int y = 0; y < chocochip8::gcHeight; y++) { if(y < miTopDirtyScanline || miBottomDirtyScanline < y) { // Skip scanlines that haven't changed since the last update continue; } for(int x = 0; x < chocochip8::gcWidth; x++) { // Map framebuffer pixel to SDL surface rectangle int x1 = ( x * pSurface->w) / chocochip8::gcWidth; int x2 = ((x + 1) * pSurface->w) / chocochip8::gcWidth; int y1 = ( y * pSurface->h) / chocochip8::gcHeight; int y2 = ((y + 1) * pSurface->h) / chocochip8::gcHeight; SDL_Rect rect; rect.x = x1; rect.y = y1; rect.w = x2 - x1; rect.h = y2 - y1; // Read Chocochip8 Framebuffer and choose appropriate color, // note that the MSB of an scanline's bitset is the leftmost pixel. Uint32 color = (mpFramebuffer->at(y)[(chocochip8::gcWidth - 1) - x] ? mFgColor : mBgColor); SDL_FillRect(pSurface, &rect, color); } } miTopDirtyScanline = chocochip8::gcHeight - 1; miBottomDirtyScanline = 0; SDL_UpdateWindowSurface(mpWindow); }