... | ... |
@@ -15,7 +15,7 @@ clang-format -i emulator.c |
15 | 15 |
clang-format -i uxn.h |
16 | 16 |
clang-format -i uxn.c |
17 | 17 |
rm -f ./uxn |
18 |
-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 |
|
18 |
+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 |
|
19 | 19 |
|
20 | 20 |
# run |
21 | 21 |
./bin/emulator bin/boot.rom |
... | ... |
@@ -1,5 +1,5 @@ |
1 |
+#include <SDL2/SDL.h> |
|
1 | 2 |
#include <stdio.h> |
2 |
-#include "uxn.h" |
|
3 | 3 |
|
4 | 4 |
/* |
5 | 5 |
Copyright (c) 2021 Devine Lu Linvega |
... | ... |
@@ -12,6 +12,90 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
12 | 12 |
WITH REGARD TO THIS SOFTWARE. |
13 | 13 |
*/ |
14 | 14 |
|
15 |
+#include "uxn.h" |
|
16 |
+ |
|
17 |
+#define HOR 32 |
|
18 |
+#define VER 16 |
|
19 |
+#define PAD 2 |
|
20 |
+#define SZ (HOR * VER * 16) |
|
21 |
+ |
|
22 |
+typedef unsigned char Uint8; |
|
23 |
+ |
|
24 |
+int WIDTH = 8 * HOR + 8 * PAD * 2; |
|
25 |
+int HEIGHT = 8 * (VER + 2) + 8 * PAD * 2; |
|
26 |
+int FPS = 30, GUIDES = 1, BIGPIXEL = 0, ZOOM = 2; |
|
27 |
+ |
|
28 |
+Uint32 theme[] = { |
|
29 |
+ 0x000000, |
|
30 |
+ 0xFFFFFF, |
|
31 |
+ 0x72DEC2, |
|
32 |
+ 0x666666, |
|
33 |
+ 0x222222}; |
|
34 |
+ |
|
35 |
+SDL_Window *gWindow; |
|
36 |
+SDL_Renderer *gRenderer; |
|
37 |
+SDL_Texture *gTexture; |
|
38 |
+Uint32 *pixels; |
|
39 |
+ |
|
40 |
+int |
|
41 |
+error(char *msg, const char *err) |
|
42 |
+{ |
|
43 |
+ printf("Error %s: %s\n", msg, err); |
|
44 |
+ return 0; |
|
45 |
+} |
|
46 |
+ |
|
47 |
+void |
|
48 |
+clear(Uint32 *dst) |
|
49 |
+{ |
|
50 |
+ int v, h; |
|
51 |
+ for(v = 0; v < HEIGHT; v++) |
|
52 |
+ for(h = 0; h < WIDTH; h++) |
|
53 |
+ dst[v * WIDTH + h] = theme[0]; |
|
54 |
+} |
|
55 |
+ |
|
56 |
+void |
|
57 |
+redraw(Uint32 *dst) |
|
58 |
+{ |
|
59 |
+ SDL_UpdateTexture(gTexture, NULL, dst, WIDTH * sizeof(Uint32)); |
|
60 |
+ SDL_RenderClear(gRenderer); |
|
61 |
+ SDL_RenderCopy(gRenderer, gTexture, NULL, NULL); |
|
62 |
+ SDL_RenderPresent(gRenderer); |
|
63 |
+} |
|
64 |
+ |
|
65 |
+void |
|
66 |
+quit(void) |
|
67 |
+{ |
|
68 |
+ free(pixels); |
|
69 |
+ SDL_DestroyTexture(gTexture); |
|
70 |
+ gTexture = NULL; |
|
71 |
+ SDL_DestroyRenderer(gRenderer); |
|
72 |
+ gRenderer = NULL; |
|
73 |
+ SDL_DestroyWindow(gWindow); |
|
74 |
+ gWindow = NULL; |
|
75 |
+ SDL_Quit(); |
|
76 |
+ exit(0); |
|
77 |
+} |
|
78 |
+ |
|
79 |
+int |
|
80 |
+init(void) |
|
81 |
+{ |
|
82 |
+ if(SDL_Init(SDL_INIT_VIDEO) < 0) |
|
83 |
+ return error("Init", SDL_GetError()); |
|
84 |
+ gWindow = SDL_CreateWindow("Uxn", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, WIDTH * ZOOM, HEIGHT * ZOOM, SDL_WINDOW_SHOWN); |
|
85 |
+ if(gWindow == NULL) |
|
86 |
+ return error("Window", SDL_GetError()); |
|
87 |
+ gRenderer = SDL_CreateRenderer(gWindow, -1, 0); |
|
88 |
+ if(gRenderer == NULL) |
|
89 |
+ return error("Renderer", SDL_GetError()); |
|
90 |
+ gTexture = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, WIDTH, HEIGHT); |
|
91 |
+ if(gTexture == NULL) |
|
92 |
+ return error("Texture", SDL_GetError()); |
|
93 |
+ if(!(pixels = (Uint32 *)malloc(WIDTH * HEIGHT * sizeof(Uint32)))) |
|
94 |
+ return error("Pixels", "Failed to allocate memory"); |
|
95 |
+ clear(pixels); |
|
96 |
+ return 1; |
|
97 |
+} |
|
98 |
+ |
|
15 | 99 |
void |
16 | 100 |
echos(Stack8 *s, Uint8 len, char *name) |
17 | 101 |
{ |
... | ... |
@@ -49,21 +133,68 @@ echof(Uxn *c) |
49 | 133 |
getflag(&c->status, FLAG_COND) != 0); |
50 | 134 |
} |
51 | 135 |
|
136 |
+void |
|
137 |
+domouse(SDL_Event *event) |
|
138 |
+{ |
|
139 |
+ (void)event; |
|
140 |
+ printf("mouse\n"); |
|
141 |
+} |
|
142 |
+ |
|
143 |
+void |
|
144 |
+dokey(SDL_Event *event) |
|
145 |
+{ |
|
146 |
+ (void)event; |
|
147 |
+ printf("key\n"); |
|
148 |
+} |
|
149 |
+ |
|
52 | 150 |
int |
53 |
-main(int argc, char *argv[]) |
|
151 |
+start(Uxn *u) |
|
54 | 152 |
{ |
55 |
- Uxn cpu; |
|
153 |
+ int ticknext = 0; |
|
154 |
+ evaluxn(u, u->vreset); |
|
155 |
+ while(1) { |
|
156 |
+ int tick = SDL_GetTicks(); |
|
157 |
+ SDL_Event event; |
|
158 |
+ if(tick < ticknext) |
|
159 |
+ SDL_Delay(ticknext - tick); |
|
160 |
+ ticknext = tick + (1000 / FPS); |
|
161 |
+ evaluxn(u, u->vframe); |
|
162 |
+ while(SDL_PollEvent(&event) != 0) { |
|
163 |
+ switch(event.type) { |
|
164 |
+ case SDL_QUIT: quit(); break; |
|
165 |
+ case SDL_MOUSEBUTTONUP: |
|
166 |
+ case SDL_MOUSEBUTTONDOWN: |
|
167 |
+ case SDL_MOUSEMOTION: domouse(&event); break; |
|
168 |
+ case SDL_KEYDOWN: dokey(&event); break; |
|
169 |
+ case SDL_WINDOWEVENT: |
|
170 |
+ if(event.window.event == SDL_WINDOWEVENT_EXPOSED) |
|
171 |
+ redraw(pixels); |
|
172 |
+ break; |
|
173 |
+ } |
|
174 |
+ } |
|
175 |
+ } |
|
176 |
+} |
|
177 |
+ |
|
178 |
+int |
|
179 |
+main(int argc, char **argv) |
|
180 |
+{ |
|
181 |
+ Uxn u; |
|
56 | 182 |
|
57 | 183 |
if(argc < 2) |
58 |
- return error(&cpu, "No input.", 0); |
|
59 |
- if(!load(&cpu, argv[1])) |
|
60 |
- return error(&cpu, "Load error", 0); |
|
61 |
- if(!boot(&cpu)) |
|
62 |
- return error(&cpu, "Boot error", 0); |
|
63 |
- |
|
64 |
- /* print result */ |
|
65 |
- echos(&cpu.wst, 0x40, "stack"); |
|
66 |
- echom(&cpu.ram, 0x40, "ram"); |
|
67 |
- echof(&cpu); |
|
184 |
+ return error("Input", "Missing"); |
|
185 |
+ if(!bootuxn(&u)) |
|
186 |
+ return error("Boot", "Failed"); |
|
187 |
+ if(!loaduxn(&u, argv[1])) |
|
188 |
+ return error("Load", "Failed"); |
|
189 |
+ if(!init()) |
|
190 |
+ return error("Init", "Failed"); |
|
191 |
+ |
|
192 |
+ start(&u); |
|
193 |
+ |
|
194 |
+ echos(&u.wst, 0x40, "stack"); |
|
195 |
+ echom(&u.ram, 0x40, "ram"); |
|
196 |
+ echof(&u); |
|
197 |
+ |
|
198 |
+ quit(); |
|
68 | 199 |
return 0; |
69 | 200 |
} |
... | ... |
@@ -97,24 +97,44 @@ Uint8 opr[][2] = { |
97 | 97 |
/* clang-format on */ |
98 | 98 |
|
99 | 99 |
int |
100 |
-error(Uxn *u, char *name, int id) |
|
100 |
+haltuxn(Uxn *u, char *name, int id) |
|
101 | 101 |
{ |
102 | 102 |
printf("Error: %s#%04x, at 0x%04x\n", name, id, u->counter); |
103 | 103 |
return 0; |
104 | 104 |
} |
105 | 105 |
|
106 |
+void |
|
107 |
+inituxn(Uxn *u) |
|
108 |
+{ |
|
109 |
+ size_t i; |
|
110 |
+ char *cptr = (char *)u; |
|
111 |
+ for(i = 0; i < sizeof u; i++) |
|
112 |
+ cptr[i] = 0; |
|
113 |
+} |
|
114 |
+ |
|
115 |
+int |
|
116 |
+loaduxn(Uxn *u, char *filepath) |
|
117 |
+{ |
|
118 |
+ FILE *f; |
|
119 |
+ if(!(f = fopen(filepath, "rb"))) |
|
120 |
+ return haltuxn(u, "Missing input.", 0); |
|
121 |
+ fread(u->ram.dat, sizeof(u->ram.dat), 1, f); |
|
122 |
+ printf("Uxn Loaded: %s\n", filepath); |
|
123 |
+ return 1; |
|
124 |
+} |
|
125 |
+ |
|
106 | 126 |
int |
107 |
-doliteral(Uxn *u, Uint8 instr) |
|
127 |
+lituxn(Uxn *u, Uint8 instr) |
|
108 | 128 |
{ |
109 | 129 |
if(u->wst.ptr >= 255) |
110 |
- return error(u, "Stack overflow", instr); |
|
130 |
+ return haltuxn(u, "Stack overflow", instr); |
|
111 | 131 |
wspush8(u, instr); |
112 | 132 |
u->literal--; |
113 | 133 |
return 1; |
114 | 134 |
} |
115 | 135 |
|
116 | 136 |
int |
117 |
-dodevices(Uxn *u) /* experimental */ |
|
137 |
+devuxn(Uxn *u) /* experimental */ |
|
118 | 138 |
{ |
119 | 139 |
if(u->ram.dat[0xfff1]) { |
120 | 140 |
printf("%c", u->ram.dat[0xfff1]); |
... | ... |
@@ -124,7 +144,7 @@ dodevices(Uxn *u) /* experimental */ |
124 | 144 |
} |
125 | 145 |
|
126 | 146 |
int |
127 |
-doopcode(Uxn *u, Uint8 instr) |
|
147 |
+opcuxn(Uxn *u, Uint8 instr) |
|
128 | 148 |
{ |
129 | 149 |
Uint8 op = instr & 0x1f; |
130 | 150 |
setflag(&u->status, FLAG_SHORT, (instr >> 5) & 1); |
... | ... |
@@ -133,61 +153,40 @@ doopcode(Uxn *u, Uint8 instr) |
133 | 153 |
if(getflag(&u->status, FLAG_SHORT)) |
134 | 154 |
op += 16; |
135 | 155 |
if(u->wst.ptr < opr[op][0]) |
136 |
- return error(u, "Stack underflow", op); |
|
156 |
+ return haltuxn(u, "Stack underflow", op); |
|
137 | 157 |
if(u->wst.ptr + opr[op][1] - opr[op][0] >= 255) |
138 |
- return error(u, "Stack overflow", instr); |
|
158 |
+ return haltuxn(u, "Stack overflow", instr); |
|
139 | 159 |
if(!getflag(&u->status, FLAG_COND) || (getflag(&u->status, FLAG_COND) && wspop8(u))) |
140 | 160 |
(*ops[op])(u); |
141 |
- dodevices(u); |
|
142 |
- return 1; |
|
143 |
-} |
|
144 |
- |
|
145 |
-int |
|
146 |
-eval(Uxn *u) |
|
147 |
-{ |
|
148 |
- Uint8 instr = u->ram.dat[u->ram.ptr++]; |
|
149 |
- if(u->literal > 0) |
|
150 |
- return doliteral(u, instr); |
|
151 |
- else |
|
152 |
- return doopcode(u, instr); |
|
161 |
+ devuxn(u); |
|
153 | 162 |
return 1; |
154 | 163 |
} |
155 | 164 |
|
156 | 165 |
int |
157 |
-load(Uxn *u, char *filepath) |
|
166 |
+evaluxn(Uxn *u, Uint16 vec) |
|
158 | 167 |
{ |
159 |
- FILE *f; |
|
160 |
- if(!(f = fopen(filepath, "rb"))) |
|
161 |
- return error(u, "Missing input.", 0); |
|
162 |
- fread(u->ram.dat, sizeof(u->ram.dat), 1, f); |
|
168 |
+ u->ram.ptr = vec; |
|
169 |
+ setflag(&u->status, FLAG_HALT, 0); |
|
170 |
+ while(!(u->status & FLAG_HALT)) { |
|
171 |
+ Uint8 instr = u->ram.dat[u->ram.ptr++]; |
|
172 |
+ u->counter++; |
|
173 |
+ if(u->literal > 0) |
|
174 |
+ return lituxn(u, instr); |
|
175 |
+ else |
|
176 |
+ return opcuxn(u, instr); |
|
177 |
+ } |
|
163 | 178 |
return 1; |
164 | 179 |
} |
165 | 180 |
|
166 |
-void |
|
167 |
-reset(Uxn *u) |
|
168 |
-{ |
|
169 |
- size_t i; |
|
170 |
- char *cptr = (char *)u; |
|
171 |
- for(i = 0; i < sizeof u; i++) |
|
172 |
- cptr[i] = 0; |
|
173 |
-} |
|
174 |
- |
|
175 | 181 |
int |
176 |
-boot(Uxn *u) |
|
182 |
+bootuxn(Uxn *u) |
|
177 | 183 |
{ |
178 |
- reset(u); |
|
184 |
+ inituxn(u); |
|
179 | 185 |
u->vreset = mempeek16(u, 0xfffa); |
180 | 186 |
u->vframe = mempeek16(u, 0xfffc); |
181 | 187 |
u->verror = mempeek16(u, 0xfffe); |
182 |
- /* eval reset */ |
|
183 |
- u->ram.ptr = u->vreset; |
|
184 |
- setflag(&u->status, FLAG_HALT, 0); |
|
185 |
- while(!(u->status & FLAG_HALT) && eval(u)) |
|
186 |
- u->counter++; |
|
187 |
- /* eval frame */ |
|
188 |
- u->ram.ptr = u->vframe; |
|
189 |
- setflag(&u->status, FLAG_HALT, 0); |
|
190 |
- while(!(u->status & FLAG_HALT) && eval(u)) |
|
191 |
- u->counter++; |
|
188 |
+ printf("Uxn Ready.\n"); |
|
192 | 189 |
return 1; |
193 | 190 |
} |
191 |
+ |
|
192 |
+/* to start: evaluxn(u, u->vreset); */ |
... | ... |
@@ -44,6 +44,6 @@ typedef struct { |
44 | 44 |
|
45 | 45 |
void setflag(Uint8 *status, char flag, int b); |
46 | 46 |
int getflag(Uint8 *status, char flag); |
47 |
-int error(Uxn *c, char *name, int id); |
|
48 |
-int load(Uxn *c, char *filepath); |
|
49 |
-int boot(Uxn *c); |
|
47 |
+int loaduxn(Uxn *c, char *filepath); |
|
48 |
+int bootuxn(Uxn *c); |
|
49 |
+int evaluxn(Uxn *u, Uint16 vec); |
|
50 | 50 |
\ No newline at end of file |