#include #include "../Video.h" #include "Events.h" #define WINDOW_WIDTH 1280 #define WINDOW_HEIGHT 800 Video video; Video::Video() { // TODO } Video::~Video() { exit(); } inline void writePixel(SDL_Surface *surface, unsigned x, unsigned y, Uint8 r, Uint8 g, Uint8 b, Uint8 a) { auto row = reinterpret_cast(static_cast(surface->pixels) + y * surface->pitch); row[x] = SDL_MapRGBA(surface->format, r, g, b, a); } void Video::enter() { _window = SDL_CreateWindow("game", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1280, 800, SDL_WINDOW_SHOWN); SDL_SetWindowTitle(_window, "meow :3"); if (!_window) { std::cerr << "Error creating SDL window: " << SDL_GetError() << std::endl; abort(); } _windowSurface = SDL_GetWindowSurface(_window); _fb = SDL_CreateRGBSurfaceWithFormat(0, SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_PIXELFORMAT_ARGB8888); } void Video::exit() { if (_fb) SDL_FreeSurface(_fb); _fb = nullptr; SDL_DestroyWindow(_window); } void Video::SetMode(uint8_t mode) { // Ignored } uint8_t Video::GetMode() { // Fixed return 0x13; } void Video::SetPaletteEntry(uint8_t index, PaletteEntry entry) { SetPaletteEntry(index, &entry); } Video::PaletteEntry Video::GetPaletteEntry(uint8_t index) { PaletteEntry entry; GetPaletteEntry(index, &entry); return entry; } void Video::SetPaletteEntry(uint8_t index, PaletteEntry *entry) { _palette[index] = *entry; } void Video::GetPaletteEntry(uint8_t index, PaletteEntry *entry) { *entry = _palette[index]; } void *Video::GetFB() { return _renderBuffer; } void Video::WaitForVerticalSync() { auto targetTime = _lastUpdate + std::chrono::microseconds(14286); auto currentTime = std::chrono::steady_clock::now(); while (currentTime < targetTime) { currentTime = std::chrono::steady_clock::now(); } _lastUpdate = currentTime; } void Video::UpdateRect(const Rect &rect) { // Merge rect if it overlaps with an existing rect for (auto i = 0; i < _updateRectIndex; i++) { auto &r = _updatedRects[i]; if (r.overlaps(rect)) { r += rect; return; } } // Add a new rect to the list _updatedRects[_updateRectIndex++] = rect; } void Video::Flip() { SDL_LockSurface(_fb); for (auto i = 0; i <= MAX_UPDATE_RECT_INDEX; i++) { auto &rect = _updatedRects[i]; rect.clamp(0, 0, _fb->w, _fb->h); for (auto y = rect.y1; y < rect.y2; y++) { for (auto x = rect.x1; x < rect.x2; x++) { auto &paletteEntry = _palette[_renderBuffer[y * SCREEN_WIDTH + x]]; writePixel(_fb, x, y, paletteEntry.r, paletteEntry.g, paletteEntry.b, 255); } } } SDL_UnlockSurface(_fb); SDL_Rect srcRect{0, 0, SCREEN_WIDTH, SCREEN_HEIGHT}; SDL_Rect dstRect{0, 0, WINDOW_WIDTH, WINDOW_HEIGHT}; SDL_BlitScaled(_fb, &srcRect, _windowSurface, &dstRect); SDL_UpdateWindowSurface(_window); _updateRectIndex = 0; events.poll(); }