diff --git a/Makefile b/Makefile index cef464a..9cb7b1a 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,9 @@ SDL2_CONFIG = sdl2-config -CFLAGS = -g -Ofast -std=c99 `$(SDL2_CONFIG) --cflags --libs` +CFLAGS = -g -Ofast -std=c99 -Wall -Wextra `$(SDL2_CONFIG) --cflags --libs` TARGET=fox32 CFILES = src/main.c \ + src/bus.c \ src/cpu.c \ src/framebuffer.c \ src/screen.c diff --git a/src/bus.c b/src/bus.c new file mode 100644 index 0000000..208b3ec --- /dev/null +++ b/src/bus.c @@ -0,0 +1,103 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bus.h" +#include "cpu.h" +#include "framebuffer.h" + +extern fox32_vm_t vm; + +int bus_io_read(void *user, uint32_t *value, uint32_t port) { + (void) user; + switch (port) { + case 0x80000000 ... 0x8000031F: { // overlay port + uint8_t overlay_number = (port & 0x000000FF); + uint8_t setting = (port & 0x0000FF00) >> 8; + switch (setting) { + case 0x00: { + // overlay position + uint32_t x = overlay_get(overlay_number)->x; + uint32_t y = overlay_get(overlay_number)->y; + *value = (y << 16) | x; + break; + }; + case 0x01: { + // overlay size + uint32_t width = overlay_get(overlay_number)->width; + uint32_t height = overlay_get(overlay_number)->height; + *value = (height << 16) | width; + break; + }; + case 0x02: { + // overlay framebuffer pointer + *value = overlay_get(overlay_number)->pointer; + break; + }; + case 0x03: { + // overlay enable status + *value = overlay_get(overlay_number)->enabled ? 1 : 0; + break; + }; + } + + break; + }; + } + + return 0; +} + +int bus_io_write(void *user, uint32_t value, uint32_t port) { + (void) user; + switch (port) { + case 0x00000000: { // terminal output port + putchar((int) value); + fflush(stdout); + break; + }; + + case 0x80000000 ... 0x8000031F: { // overlay port + uint8_t overlay_number = (port & 0x000000FF); + uint8_t setting = (port & 0x0000FF00) >> 8; + switch (setting) { + case 0x00: { + // overlay position + uint32_t x = value & 0x0000FFFF; + uint32_t y = (value & 0xFFFF0000) >> 16; + overlay_get(overlay_number)->x = x; + overlay_get(overlay_number)->y = y; + break; + }; + case 0x01: { + // overlay size + uint32_t width = value & 0x0000FFFF; + uint32_t height = (value & 0xFFFF0000) >> 16; + overlay_get(overlay_number)->width = width; + overlay_get(overlay_number)->height = height; + break; + }; + case 0x02: { + // overlay framebuffer pointer + overlay_get(overlay_number)->pointer = value; + break; + }; + case 0x03: { + // overlay enable status + overlay_get(overlay_number)->enabled = value != 0; + break; + }; + } + + break; + }; + } + + return 0; +} diff --git a/src/bus.h b/src/bus.h new file mode 100644 index 0000000..e50261f --- /dev/null +++ b/src/bus.h @@ -0,0 +1,4 @@ +#pragma once + +int bus_io_read(void *user, uint32_t *value, uint32_t port); +int bus_io_write(void *user, uint32_t value, uint32_t port); diff --git a/src/cpu.c b/src/cpu.c index 0256a46..fbe297b 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -34,16 +34,14 @@ typedef fox32_io_read_t io_read_t; typedef fox32_io_write_t io_write_t; static int io_read_default_impl(void *user, uint32_t *value, uint32_t port) { - //return (void) user, (void) value, (int) port; - return 0; + return (void) user, (void) value, (int) port; } static int io_write_default_impl(void *user, uint32_t value, uint32_t port) { if (port == 0) { putchar((int) value); fflush(stdout); } - //return (void) user, (int) port; - return 0; + return (void) user, (int) port; } static io_read_t *const io_read_default = io_read_default_impl; diff --git a/src/framebuffer.c b/src/framebuffer.c index 7bb7096..f29d9a2 100644 --- a/src/framebuffer.c +++ b/src/framebuffer.c @@ -8,16 +8,52 @@ #include #include +#include "bus.h" #include "cpu.h" #include "framebuffer.h" #include "screen.h" -uint32_t PixelBuffer[FRAMEBUFFER_WIDTH * FRAMEBUFFER_HEIGHT]; - extern fox32_vm_t vm; -void FramebufferDraw(struct Screen *screen) { - SDL_Texture *texture = ScreenGetTexture(screen); - memcpy(PixelBuffer, &vm.memory_ram[0x02000000], FRAMEBUFFER_WIDTH * FRAMEBUFFER_HEIGHT * 4); - SDL_UpdateTexture(texture, NULL, PixelBuffer, FRAMEBUFFER_WIDTH * 4); +static uint8_t framebuffer[FRAMEBUFFER_WIDTH * FRAMEBUFFER_HEIGHT * 4]; +static overlay_t overlays[32]; + +overlay_t *overlay_get(uint32_t index) { + if (index >= 32) abort(); + return &overlays[index]; +} + +void draw_framebuffer(struct Screen *screen) { + SDL_Texture *texture = ScreenGetTexture(screen); + + memcpy(framebuffer, &vm.memory_ram[0x02000000], FRAMEBUFFER_WIDTH * FRAMEBUFFER_HEIGHT * 4); + + for (size_t i = 0; i < 32; i++) { + overlay_t *overlay = &overlays[i]; + if (!overlay->enabled) continue; + + size_t pointer = overlay->pointer; + + size_t height = overlay->height; + size_t width = overlay->width; + + size_t ymin = overlay->y, ymax = ymin + height; + size_t xmin = overlay->x, xmax = xmin + width; + ymax = ymax < FRAMEBUFFER_HEIGHT ? ymax : FRAMEBUFFER_HEIGHT; + xmax = xmax < FRAMEBUFFER_WIDTH ? xmax : FRAMEBUFFER_WIDTH; + if (ymin >= ymax) continue; + if (xmin >= xmax) continue; + + for (size_t y = ymin; y < ymax; y++) { + for (size_t x = xmin; x < xmax; x++) { + size_t index_dst = (x + y * FRAMEBUFFER_WIDTH) * 4; + size_t index_src = ((x - xmin) + (y - ymin) * width) * 4 + pointer; + if (vm.memory_ram[index_src] > 0) { + memcpy(&framebuffer[index_dst], &vm.memory_ram[index_src], 4); + } + } + } + } + + SDL_UpdateTexture(texture, NULL, framebuffer, FRAMEBUFFER_WIDTH * 4); } diff --git a/src/framebuffer.h b/src/framebuffer.h index 9eeb41b..9a38d42 100644 --- a/src/framebuffer.h +++ b/src/framebuffer.h @@ -7,4 +7,13 @@ #define VSYNC_INTERRUPT_VECTOR 0xFF -void FramebufferDraw(struct Screen *screen); +void draw_framebuffer(struct Screen *screen); + +typedef struct { + uint32_t pointer; + uint32_t x, y; + uint32_t width, height; + bool enabled; +} overlay_t; + +overlay_t *overlay_get(uint32_t index); diff --git a/src/main.c b/src/main.c index 87b85e7..245189a 100644 --- a/src/main.c +++ b/src/main.c @@ -7,6 +7,7 @@ #include #include +#include "bus.h" #include "cpu.h" #include "framebuffer.h" #include "screen.h" @@ -33,6 +34,8 @@ int main(int argc, char *argv[]) { } fox32_init(&vm); + vm.io_read = bus_io_read; + vm.io_write = bus_io_write; vm.halted = false; //vm.debug = true; @@ -40,8 +43,7 @@ int main(int argc, char *argv[]) { ScreenCreate( FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT, - "fox32 framebuffer", - FramebufferDraw, + draw_framebuffer, 0, 0, 0, diff --git a/src/screen.c b/src/screen.c index fb9db48..24372ec 100644 --- a/src/screen.c +++ b/src/screen.c @@ -180,8 +180,8 @@ struct SDL_Texture *ScreenGetTexture(struct Screen *screen) { return screen->Texture; } -struct Screen ScreenCreate( - int w, int h, char *title, +void ScreenCreate( + int w, int h, ScreenDrawF draw, ScreenKeyPressedF keypressed, ScreenKeyReleasedF keyreleased, @@ -198,7 +198,6 @@ struct Screen ScreenCreate( MainScreen.Width = w; MainScreen.Height = h; - MainScreen.Title = title; MainScreen.Draw = draw; MainScreen.KeyPressed = keypressed; diff --git a/src/screen.h b/src/screen.h index 4b3933e..2eb4328 100644 --- a/src/screen.h +++ b/src/screen.h @@ -14,9 +14,6 @@ typedef void (*ScreenMouseMovedF)(struct Screen *screen, int dx, int dy); struct Screen { int Width; int Height; - void *Context1; - void *Context2; - char *Title; SDL_Texture *Texture; ScreenDrawF Draw; @@ -35,8 +32,8 @@ int ScreenProcessEvents(); struct SDL_Texture *ScreenGetTexture(struct Screen *screen); -struct Screen ScreenCreate( - int w, int h, char *title, +void ScreenCreate( + int w, int h, ScreenDrawF draw, ScreenKeyPressedF keypressed, ScreenKeyReleasedF keyreleased,