Implement paletted framebuffer (320x200 for now)

This commit is contained in:
Konstantin Nazarov 2024-12-22 02:18:02 +00:00
parent 557d5dfa75
commit 844ad3b073
Signed by: knazarov
GPG key ID: 4CFE0A42FA409C22
3 changed files with 33 additions and 12 deletions

View file

@ -2,6 +2,7 @@
typedef unsigned long long uint64_t; typedef unsigned long long uint64_t;
typedef unsigned long uint32_t; typedef unsigned long uint32_t;
typedef unsigned char uint8_t;
#define MTIME_BASE 0x0200BFF8 #define MTIME_BASE 0x0200BFF8
volatile uint32_t* mtime_upper = (uint32_t*)(MTIME_BASE+4); volatile uint32_t* mtime_upper = (uint32_t*)(MTIME_BASE+4);
@ -36,10 +37,10 @@ int fib(int n) {
void draw() { void draw() {
for (int k = 0; k < 200; k++) { for (int k = 0; k < 200; k++) {
for (int i = 0; i< 640; i++) { for (int i = 0; i< 320; i++) {
for (int j = 0; j < 480; j++) { for (int j = 0; j < 200; j++) {
uint32_t color = i*(j + k); uint8_t color = i*(j + k);
uint32_t* addr = (uint32_t*)(FRAMEBUFFER_BASE + ((j*640) + i) *4); uint8_t* addr = (uint8_t*)(FRAMEBUFFER_BASE + (j*320) + i);
*addr = color; *addr = color;
} }
} }

View file

@ -9,12 +9,21 @@ SDL_Window* window = nullptr;
SDL_Renderer* renderer = nullptr; SDL_Renderer* renderer = nullptr;
SDL_Texture* texture = nullptr; SDL_Texture* texture = nullptr;
Framebuffer::Framebuffer() : Device(FRAMEBUFFER_ADDR, 640 * 480 * 4) { #define FB_WIDTH 320
#define FB_HEIGHT 200
#define FB_SCALE 2
#define FB_OFFSET 0x10000
Framebuffer::Framebuffer()
: Device(FRAMEBUFFER_ADDR, FB_WIDTH * FB_HEIGHT + FB_OFFSET),
width(FB_WIDTH),
height(FB_HEIGHT),
buf(FB_WIDTH * FB_HEIGHT, 0) {
if (SDL_Init(SDL_INIT_VIDEO) < 0) { if (SDL_Init(SDL_INIT_VIDEO) < 0) {
throw std::runtime_error("Failed to initialize SDL"); throw std::runtime_error("Failed to initialize SDL");
} }
window = SDL_CreateWindow("rve Framebuffer", SDL_WINDOWPOS_CENTERED, window = SDL_CreateWindow("rve Framebuffer", SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, 640, 480, 0); SDL_WINDOWPOS_CENTERED, width, height, 0);
if (!window) { if (!window) {
throw std::runtime_error("Failed to create SDL window"); throw std::runtime_error("Failed to create SDL window");
} }
@ -33,7 +42,7 @@ Framebuffer::Framebuffer() : Device(FRAMEBUFFER_ADDR, 640 * 480 * 4) {
throw std::runtime_error("Failed to create SDL renderer"); throw std::runtime_error("Failed to create SDL renderer");
} }
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING, 640, 480); SDL_TEXTUREACCESS_STREAMING, width, height);
if (!texture) { if (!texture) {
throw std::runtime_error("Failed to create SDL texture"); throw std::runtime_error("Failed to create SDL texture");
} }
@ -44,8 +53,15 @@ Framebuffer::Framebuffer() : Device(FRAMEBUFFER_ADDR, 640 * 480 * 4) {
} }
void Framebuffer::draw() { void Framebuffer::draw() {
SDL_UpdateTexture(texture, nullptr, &mem[0], for (size_t i = 0; i < width * height; i++) {
640 * 4); // Update the SDL texture uint8_t color = mem[i + FB_OFFSET];
uint32_t cmap = ((uint32_t*)&mem[0])[color];
buf[i] = cmap;
}
SDL_UpdateTexture(texture, nullptr, &buf[0],
width * 4); // Update the SDL texture
SDL_RenderClear(renderer); SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, nullptr, nullptr); SDL_RenderCopy(renderer, texture, nullptr, nullptr);
SDL_RenderPresent(renderer); SDL_RenderPresent(renderer);
@ -54,7 +70,7 @@ void Framebuffer::draw() {
void Framebuffer::write_mem_u8(uint8_t* src, size_t addr) { void Framebuffer::write_mem_u8(uint8_t* src, size_t addr) {
Device::write_mem_u8(src, addr); Device::write_mem_u8(src, addr);
if (addr + 1 == base() + (640 * 480) * 4) { if (addr + 1 == base() + width * height + FB_OFFSET) {
// draw to the screen when the last byte is written // draw to the screen when the last byte is written
draw(); draw();
} }
@ -63,7 +79,7 @@ void Framebuffer::write_mem_u8(uint8_t* src, size_t addr) {
void Framebuffer::write_mem_u16(uint16_t* src, size_t addr) { void Framebuffer::write_mem_u16(uint16_t* src, size_t addr) {
Device::write_mem_u16(src, addr); Device::write_mem_u16(src, addr);
if (addr + 2 == base() + (640 * 480) * 4) { if (addr + 2 == base() + width * height + FB_OFFSET) {
// draw to the screen when the last byte is written // draw to the screen when the last byte is written
draw(); draw();
} }
@ -72,7 +88,7 @@ void Framebuffer::write_mem_u16(uint16_t* src, size_t addr) {
void Framebuffer::write_mem_u32(uint32_t* src, size_t addr) { void Framebuffer::write_mem_u32(uint32_t* src, size_t addr) {
Device::write_mem_u32(src, addr); Device::write_mem_u32(src, addr);
if (addr + 4 == base() + (640 * 480) * 4) { if (addr + 4 == base() + width * height + FB_OFFSET) {
// draw to the screen when the last byte is written // draw to the screen when the last byte is written
draw(); draw();
} }

View file

@ -114,6 +114,10 @@ class Framebuffer final : public Device {
protected: protected:
void draw(); void draw();
size_t width;
size_t height;
std::vector<uint32_t> buf;
}; };
class VM { class VM {