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
|
||||
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
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;
|
||||
|
||||
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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue
Block a user