dosgame1/system/sdl/Video.cpp

125 lines
2.7 KiB
C++

#include <iostream>
#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<Uint32*>(static_cast<Uint8*>(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);
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();
}