Implement overlays
Co-authored-by: Lua MacDougall <lua@foxgirl.dev>
This commit is contained in:
parent
979a8b2cfc
commit
53cbc0d96c
3
Makefile
3
Makefile
|
@ -1,8 +1,9 @@
|
||||||
SDL2_CONFIG = sdl2-config
|
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
|
TARGET=fox32
|
||||||
|
|
||||||
CFILES = src/main.c \
|
CFILES = src/main.c \
|
||||||
|
src/bus.c \
|
||||||
src/cpu.c \
|
src/cpu.c \
|
||||||
src/framebuffer.c \
|
src/framebuffer.c \
|
||||||
src/screen.c
|
src/screen.c
|
||||||
|
|
103
src/bus.c
Normal file
103
src/bus.c
Normal 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
Normal file
4
src/bus.h
Normal 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);
|
|
@ -34,16 +34,14 @@ typedef fox32_io_read_t io_read_t;
|
||||||
typedef fox32_io_write_t io_write_t;
|
typedef fox32_io_write_t io_write_t;
|
||||||
|
|
||||||
static int io_read_default_impl(void *user, uint32_t *value, uint32_t port) {
|
static int io_read_default_impl(void *user, uint32_t *value, uint32_t port) {
|
||||||
//return (void) user, (void) value, (int) port;
|
return (void) user, (void) value, (int) port;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
static int io_write_default_impl(void *user, uint32_t value, uint32_t port) {
|
static int io_write_default_impl(void *user, uint32_t value, uint32_t port) {
|
||||||
if (port == 0) {
|
if (port == 0) {
|
||||||
putchar((int) value);
|
putchar((int) value);
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
//return (void) user, (int) port;
|
return (void) user, (int) port;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static io_read_t *const io_read_default = io_read_default_impl;
|
static io_read_t *const io_read_default = io_read_default_impl;
|
||||||
|
|
|
@ -8,16 +8,52 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "bus.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "framebuffer.h"
|
#include "framebuffer.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
|
||||||
uint32_t PixelBuffer[FRAMEBUFFER_WIDTH * FRAMEBUFFER_HEIGHT];
|
|
||||||
|
|
||||||
extern fox32_vm_t vm;
|
extern fox32_vm_t vm;
|
||||||
|
|
||||||
void FramebufferDraw(struct Screen *screen) {
|
static uint8_t framebuffer[FRAMEBUFFER_WIDTH * FRAMEBUFFER_HEIGHT * 4];
|
||||||
SDL_Texture *texture = ScreenGetTexture(screen);
|
static overlay_t overlays[32];
|
||||||
memcpy(PixelBuffer, &vm.memory_ram[0x02000000], FRAMEBUFFER_WIDTH * FRAMEBUFFER_HEIGHT * 4);
|
|
||||||
SDL_UpdateTexture(texture, NULL, PixelBuffer, FRAMEBUFFER_WIDTH * 4);
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,4 +7,13 @@
|
||||||
|
|
||||||
#define VSYNC_INTERRUPT_VECTOR 0xFF
|
#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);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "bus.h"
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "framebuffer.h"
|
#include "framebuffer.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
@ -33,6 +34,8 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fox32_init(&vm);
|
fox32_init(&vm);
|
||||||
|
vm.io_read = bus_io_read;
|
||||||
|
vm.io_write = bus_io_write;
|
||||||
vm.halted = false;
|
vm.halted = false;
|
||||||
//vm.debug = true;
|
//vm.debug = true;
|
||||||
|
|
||||||
|
@ -40,8 +43,7 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
ScreenCreate(
|
ScreenCreate(
|
||||||
FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT,
|
FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT,
|
||||||
"fox32 framebuffer",
|
draw_framebuffer,
|
||||||
FramebufferDraw,
|
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
|
|
@ -180,8 +180,8 @@ struct SDL_Texture *ScreenGetTexture(struct Screen *screen) {
|
||||||
return screen->Texture;
|
return screen->Texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Screen ScreenCreate(
|
void ScreenCreate(
|
||||||
int w, int h, char *title,
|
int w, int h,
|
||||||
ScreenDrawF draw,
|
ScreenDrawF draw,
|
||||||
ScreenKeyPressedF keypressed,
|
ScreenKeyPressedF keypressed,
|
||||||
ScreenKeyReleasedF keyreleased,
|
ScreenKeyReleasedF keyreleased,
|
||||||
|
@ -198,7 +198,6 @@ struct Screen ScreenCreate(
|
||||||
|
|
||||||
MainScreen.Width = w;
|
MainScreen.Width = w;
|
||||||
MainScreen.Height = h;
|
MainScreen.Height = h;
|
||||||
MainScreen.Title = title;
|
|
||||||
|
|
||||||
MainScreen.Draw = draw;
|
MainScreen.Draw = draw;
|
||||||
MainScreen.KeyPressed = keypressed;
|
MainScreen.KeyPressed = keypressed;
|
||||||
|
|
|
@ -14,9 +14,6 @@ typedef void (*ScreenMouseMovedF)(struct Screen *screen, int dx, int dy);
|
||||||
struct Screen {
|
struct Screen {
|
||||||
int Width;
|
int Width;
|
||||||
int Height;
|
int Height;
|
||||||
void *Context1;
|
|
||||||
void *Context2;
|
|
||||||
char *Title;
|
|
||||||
SDL_Texture *Texture;
|
SDL_Texture *Texture;
|
||||||
|
|
||||||
ScreenDrawF Draw;
|
ScreenDrawF Draw;
|
||||||
|
@ -35,8 +32,8 @@ int ScreenProcessEvents();
|
||||||
|
|
||||||
struct SDL_Texture *ScreenGetTexture(struct Screen *screen);
|
struct SDL_Texture *ScreenGetTexture(struct Screen *screen);
|
||||||
|
|
||||||
struct Screen ScreenCreate(
|
void ScreenCreate(
|
||||||
int w, int h, char *title,
|
int w, int h,
|
||||||
ScreenDrawF draw,
|
ScreenDrawF draw,
|
||||||
ScreenKeyPressedF keypressed,
|
ScreenKeyPressedF keypressed,
|
||||||
ScreenKeyReleasedF keyreleased,
|
ScreenKeyReleasedF keyreleased,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user