Added SDL layer

This commit is contained in:
neauoire 2021-02-08 15:46:52 -08:00
parent 5e80946097
commit 75b0fd06d9
4 changed files with 192 additions and 62 deletions

View File

@ -15,7 +15,7 @@ clang-format -i emulator.c
clang-format -i uxn.h
clang-format -i uxn.c
rm -f ./uxn
cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined uxn.c emulator.c -o bin/emulator
cc -std=c89 -DDEBUG -Wall -Wno-unknown-pragmas -Wpedantic -Wshadow -Wextra -Werror=implicit-int -Werror=incompatible-pointer-types -Werror=int-conversion -Wvla -g -Og -fsanitize=address -fsanitize=undefined uxn.c emulator.c -L/usr/local/lib -lSDL2 -o bin/emulator
# run
./bin/emulator bin/boot.rom

View File

@ -1,5 +1,5 @@
#include <SDL2/SDL.h>
#include <stdio.h>
#include "uxn.h"
/*
Copyright (c) 2021 Devine Lu Linvega
@ -12,6 +12,90 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
*/
#include "uxn.h"
#define HOR 32
#define VER 16
#define PAD 2
#define SZ (HOR * VER * 16)
typedef unsigned char Uint8;
int WIDTH = 8 * HOR + 8 * PAD * 2;
int HEIGHT = 8 * (VER + 2) + 8 * PAD * 2;
int FPS = 30, GUIDES = 1, BIGPIXEL = 0, ZOOM = 2;
Uint32 theme[] = {
0x000000,
0xFFFFFF,
0x72DEC2,
0x666666,
0x222222};
SDL_Window *gWindow;
SDL_Renderer *gRenderer;
SDL_Texture *gTexture;
Uint32 *pixels;
int
error(char *msg, const char *err)
{
printf("Error %s: %s\n", msg, err);
return 0;
}
void
clear(Uint32 *dst)
{
int v, h;
for(v = 0; v < HEIGHT; v++)
for(h = 0; h < WIDTH; h++)
dst[v * WIDTH + h] = theme[0];
}
void
redraw(Uint32 *dst)
{
SDL_UpdateTexture(gTexture, NULL, dst, WIDTH * sizeof(Uint32));
SDL_RenderClear(gRenderer);
SDL_RenderCopy(gRenderer, gTexture, NULL, NULL);
SDL_RenderPresent(gRenderer);
}
void
quit(void)
{
free(pixels);
SDL_DestroyTexture(gTexture);
gTexture = NULL;
SDL_DestroyRenderer(gRenderer);
gRenderer = NULL;
SDL_DestroyWindow(gWindow);
gWindow = NULL;
SDL_Quit();
exit(0);
}
int
init(void)
{
if(SDL_Init(SDL_INIT_VIDEO) < 0)
return error("Init", SDL_GetError());
gWindow = SDL_CreateWindow("Uxn", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH * ZOOM, HEIGHT * ZOOM, SDL_WINDOW_SHOWN);
if(gWindow == NULL)
return error("Window", SDL_GetError());
gRenderer = SDL_CreateRenderer(gWindow, -1, 0);
if(gRenderer == NULL)
return error("Renderer", SDL_GetError());
gTexture = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, WIDTH, HEIGHT);
if(gTexture == NULL)
return error("Texture", SDL_GetError());
if(!(pixels = (Uint32 *)malloc(WIDTH * HEIGHT * sizeof(Uint32))))
return error("Pixels", "Failed to allocate memory");
clear(pixels);
return 1;
}
void
echos(Stack8 *s, Uint8 len, char *name)
{
@ -49,21 +133,68 @@ echof(Uxn *c)
getflag(&c->status, FLAG_COND) != 0);
}
int
main(int argc, char *argv[])
void
domouse(SDL_Event *event)
{
Uxn cpu;
(void)event;
printf("mouse\n");
}
void
dokey(SDL_Event *event)
{
(void)event;
printf("key\n");
}
int
start(Uxn *u)
{
int ticknext = 0;
evaluxn(u, u->vreset);
while(1) {
int tick = SDL_GetTicks();
SDL_Event event;
if(tick < ticknext)
SDL_Delay(ticknext - tick);
ticknext = tick + (1000 / FPS);
evaluxn(u, u->vframe);
while(SDL_PollEvent(&event) != 0) {
switch(event.type) {
case SDL_QUIT: quit(); break;
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEMOTION: domouse(&event); break;
case SDL_KEYDOWN: dokey(&event); break;
case SDL_WINDOWEVENT:
if(event.window.event == SDL_WINDOWEVENT_EXPOSED)
redraw(pixels);
break;
}
}
}
}
int
main(int argc, char **argv)
{
Uxn u;
if(argc < 2)
return error(&cpu, "No input.", 0);
if(!load(&cpu, argv[1]))
return error(&cpu, "Load error", 0);
if(!boot(&cpu))
return error(&cpu, "Boot error", 0);
return error("Input", "Missing");
if(!bootuxn(&u))
return error("Boot", "Failed");
if(!loaduxn(&u, argv[1]))
return error("Load", "Failed");
if(!init())
return error("Init", "Failed");
/* print result */
echos(&cpu.wst, 0x40, "stack");
echom(&cpu.ram, 0x40, "ram");
echof(&cpu);
start(&u);
echos(&u.wst, 0x40, "stack");
echom(&u.ram, 0x40, "ram");
echof(&u);
quit();
return 0;
}

89
uxn.c
View File

@ -97,24 +97,44 @@ Uint8 opr[][2] = {
/* clang-format on */
int
error(Uxn *u, char *name, int id)
haltuxn(Uxn *u, char *name, int id)
{
printf("Error: %s#%04x, at 0x%04x\n", name, id, u->counter);
return 0;
}
void
inituxn(Uxn *u)
{
size_t i;
char *cptr = (char *)u;
for(i = 0; i < sizeof u; i++)
cptr[i] = 0;
}
int
doliteral(Uxn *u, Uint8 instr)
loaduxn(Uxn *u, char *filepath)
{
FILE *f;
if(!(f = fopen(filepath, "rb")))
return haltuxn(u, "Missing input.", 0);
fread(u->ram.dat, sizeof(u->ram.dat), 1, f);
printf("Uxn Loaded: %s\n", filepath);
return 1;
}
int
lituxn(Uxn *u, Uint8 instr)
{
if(u->wst.ptr >= 255)
return error(u, "Stack overflow", instr);
return haltuxn(u, "Stack overflow", instr);
wspush8(u, instr);
u->literal--;
return 1;
}
int
dodevices(Uxn *u) /* experimental */
devuxn(Uxn *u) /* experimental */
{
if(u->ram.dat[0xfff1]) {
printf("%c", u->ram.dat[0xfff1]);
@ -124,7 +144,7 @@ dodevices(Uxn *u) /* experimental */
}
int
doopcode(Uxn *u, Uint8 instr)
opcuxn(Uxn *u, Uint8 instr)
{
Uint8 op = instr & 0x1f;
setflag(&u->status, FLAG_SHORT, (instr >> 5) & 1);
@ -133,61 +153,40 @@ doopcode(Uxn *u, Uint8 instr)
if(getflag(&u->status, FLAG_SHORT))
op += 16;
if(u->wst.ptr < opr[op][0])
return error(u, "Stack underflow", op);
return haltuxn(u, "Stack underflow", op);
if(u->wst.ptr + opr[op][1] - opr[op][0] >= 255)
return error(u, "Stack overflow", instr);
return haltuxn(u, "Stack overflow", instr);
if(!getflag(&u->status, FLAG_COND) || (getflag(&u->status, FLAG_COND) && wspop8(u)))
(*ops[op])(u);
dodevices(u);
devuxn(u);
return 1;
}
int
eval(Uxn *u)
evaluxn(Uxn *u, Uint16 vec)
{
Uint8 instr = u->ram.dat[u->ram.ptr++];
if(u->literal > 0)
return doliteral(u, instr);
else
return doopcode(u, instr);
u->ram.ptr = vec;
setflag(&u->status, FLAG_HALT, 0);
while(!(u->status & FLAG_HALT)) {
Uint8 instr = u->ram.dat[u->ram.ptr++];
u->counter++;
if(u->literal > 0)
return lituxn(u, instr);
else
return opcuxn(u, instr);
}
return 1;
}
int
load(Uxn *u, char *filepath)
bootuxn(Uxn *u)
{
FILE *f;
if(!(f = fopen(filepath, "rb")))
return error(u, "Missing input.", 0);
fread(u->ram.dat, sizeof(u->ram.dat), 1, f);
return 1;
}
void
reset(Uxn *u)
{
size_t i;
char *cptr = (char *)u;
for(i = 0; i < sizeof u; i++)
cptr[i] = 0;
}
int
boot(Uxn *u)
{
reset(u);
inituxn(u);
u->vreset = mempeek16(u, 0xfffa);
u->vframe = mempeek16(u, 0xfffc);
u->verror = mempeek16(u, 0xfffe);
/* eval reset */
u->ram.ptr = u->vreset;
setflag(&u->status, FLAG_HALT, 0);
while(!(u->status & FLAG_HALT) && eval(u))
u->counter++;
/* eval frame */
u->ram.ptr = u->vframe;
setflag(&u->status, FLAG_HALT, 0);
while(!(u->status & FLAG_HALT) && eval(u))
u->counter++;
printf("Uxn Ready.\n");
return 1;
}
/* to start: evaluxn(u, u->vreset); */

6
uxn.h
View File

@ -44,6 +44,6 @@ typedef struct {
void setflag(Uint8 *status, char flag, int b);
int getflag(Uint8 *status, char flag);
int error(Uxn *c, char *name, int id);
int load(Uxn *c, char *filepath);
int boot(Uxn *c);
int loaduxn(Uxn *c, char *filepath);
int bootuxn(Uxn *c);
int evaluxn(Uxn *u, Uint16 vec);