commit 75b0fd06d911f82d164fba471862e0cb54a50e5c
parent 5e80946097d29cd435e5ce841cd733b8761df244
Author: neauoire <aliceffekt@gmail.com>
Date: Mon, 8 Feb 2021 15:46:52 -0800
Added SDL layer
Diffstat:
M | build.sh | | | 2 | +- |
M | emulator.c | | | 157 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- |
M | uxn.c | | | 89 | +++++++++++++++++++++++++++++++++++++++---------------------------------------- |
M | uxn.h | | | 7 | ++++--- |
4 files changed, 193 insertions(+), 62 deletions(-)
diff --git a/build.sh b/build.sh
@@ -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
diff --git a/emulator.c b/emulator.c
@@ -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);
}
+void
+domouse(SDL_Event *event)
+{
+ (void)event;
+ printf("mouse\n");
+}
+
+void
+dokey(SDL_Event *event)
+{
+ (void)event;
+ printf("key\n");
+}
+
int
-main(int argc, char *argv[])
+start(Uxn *u)
{
- Uxn cpu;
+ 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);
-
- /* print result */
- echos(&cpu.wst, 0x40, "stack");
- echom(&cpu.ram, 0x40, "ram");
- echof(&cpu);
+ 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");
+
+ start(&u);
+
+ echos(&u.wst, 0x40, "stack");
+ echom(&u.ram, 0x40, "ram");
+ echof(&u);
+
+ quit();
return 0;
}
diff --git a/uxn.c b/uxn.c
@@ -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
+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
-doliteral(Uxn *u, Uint8 instr)
+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);
- return 1;
-}
-
-int
-eval(Uxn *u)
-{
- Uint8 instr = u->ram.dat[u->ram.ptr++];
- if(u->literal > 0)
- return doliteral(u, instr);
- else
- return doopcode(u, instr);
+ devuxn(u);
return 1;
}
int
-load(Uxn *u, char *filepath)
+evaluxn(Uxn *u, Uint16 vec)
{
- FILE *f;
- if(!(f = fopen(filepath, "rb")))
- return error(u, "Missing input.", 0);
- fread(u->ram.dat, sizeof(u->ram.dat), 1, f);
+ 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;
}
-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)
+bootuxn(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); */
diff --git a/uxn.h b/uxn.h
@@ -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);
+\ No newline at end of file