Implement overlays

Co-authored-by: Lua MacDougall <lua@foxgirl.dev>
main
Ry 2022-10-23 13:16:40 -07:00
parent 979a8b2cfc
commit 53cbc0d96c
9 changed files with 171 additions and 22 deletions

View File

@ -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

103
src/bus.c 100644
View File

@ -0,0 +1,103 @@
#include <SDL2/SDL.h>
#include <getopt.h>
#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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;
}

4
src/bus.h 100644
View File

@ -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);

View File

@ -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;

View File

@ -8,16 +8,52 @@
#include <stdlib.h>
#include <string.h>
#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);
}

View File

@ -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);

View File

@ -7,6 +7,7 @@
#include <stdlib.h>
#include <string.h>
#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,

View File

@ -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;

View File

@ -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,