Browse code

Added screen example

neauoire authored on 10/02/2021 19:06:36
Showing 7 changed files
... ...
@@ -31,15 +31,13 @@ A [stack-based VM](https://wiki.xxiivv.com/site/uxn.html), written in ANSI C.
31 31
 ( hello world )
32 32
 
33 33
 ;iterator
34
-:dev1r FFF0
35
-:dev1w FFF1
36 34
 
37 35
 |0100 @RESET
38 36
 
39
-@word1 "hello_word ( len: 0x0b )
37
+@word1 "hello_world ( len: 0x0b )
40 38
 
41 39
 @loop
42
-	,dev1w STR ( write to stdout )
40
+	,00 IOW ( write to device#0 )
43 41
 	,incr JSR ( increment itr )
44 42
 	,word1 ,strlen JSR ( get strlen )
45 43
 	NEQ ,loop ROT JSR? ( loop != strlen )
... ...
@@ -64,25 +62,11 @@ BRK
64 62
 
65 63
 ## TODOs
66 64
 
67
-### Assembler
68
-
69
-- Implement shorthand operators
70
-- Signed operations
71
-
72
-### CPU
73
-
74
-- Signed operations
75
-- Catch overflow/underflow
76
-- A Three-Way Decision Routine(http://www.6502.org/tutorials/compare_instructions.html)
77
-- Draw pixel to screen
78
-- Redo overflow/underflow mappping
79
-- Detect mouse click
80
-- SDL Layer Emulator
81
-- Build PPU
82
-
83
-### Devices
84
-
85
-- Devices each have an input byte, an output byte and two request bytes.
65
+- Implement signed flag to operators.
66
+- On-screen debugger.
67
+- 16b mode for str/ldr
68
+- Auto-advance ldr?
69
+- Getting rid of IOR/IOW would be nice..
86 70
 
87 71
 ## Refs
88 72
 
... ...
@@ -59,7 +59,7 @@ void
59 59
 putpixel(Uint32 *dst, int x, int y, int color)
60 60
 {
61 61
 	if(x >= 0 && x < WIDTH - 8 && y >= 0 && y < HEIGHT - 8)
62
-		dst[(y + PAD * 8) * WIDTH + (x + PAD * 8)] = theme[color];
62
+		dst[y * WIDTH + x] = theme[color];
63 63
 }
64 64
 
65 65
 void
... ...
@@ -145,14 +145,18 @@ echof(Uxn *c)
145 145
 void
146 146
 domouse(SDL_Event *event)
147 147
 {
148
-	devmouse->mem[0] = event->motion.x / ZOOM - PAD * 8;
149
-	devmouse->mem[1] = event->motion.y / ZOOM - PAD * 8;
148
+	int x = event->motion.x / ZOOM;
149
+	int y = event->motion.y / ZOOM;
150
+	devmouse->mem[0] = (x >> 8) & 0xff;
151
+	devmouse->mem[1] = x & 0xff;
152
+	devmouse->mem[2] = (y >> 8) & 0xff;
153
+	devmouse->mem[3] = y & 0xff;
150 154
 	switch(event->type) {
151 155
 	case SDL_MOUSEBUTTONUP:
152
-		devmouse->mem[2] = 0;
156
+		devmouse->mem[4] = 0;
153 157
 		break;
154 158
 	case SDL_MOUSEBUTTONDOWN:
155
-		devmouse->mem[2] = event->button.button == SDL_BUTTON_LEFT;
159
+		devmouse->mem[4] = event->button.button == SDL_BUTTON_LEFT;
156 160
 	}
157 161
 }
158 162
 
... ...
@@ -186,9 +190,7 @@ consolew(Device *d, Uint8 b)
186 190
 Uint8
187 191
 screenr(Device *d, Uint8 b)
188 192
 {
189
-	(void)b;
190
-	(void)d;
191
-	return 0;
193
+	return d->mem[b];
192 194
 }
193 195
 
194 196
 Uint8
... ...
@@ -197,8 +199,8 @@ screenw(Device *d, Uint8 b)
197 199
 	d->mem[d->len++] = b;
198 200
 	if(d->len > 5) {
199 201
 		putpixel(pixels,
200
-			(d->mem[0] << 8) + d->mem[1],
201 202
 			(d->mem[2] << 8) + d->mem[3],
203
+			(d->mem[0] << 8) + d->mem[1],
202 204
 			d->mem[4]);
203 205
 		if(d->mem[5])
204 206
 			redraw(pixels);
... ...
@@ -244,6 +246,11 @@ start(Uxn *u)
244 246
 {
245 247
 	int ticknext = 0;
246 248
 	evaluxn(u, u->vreset);
249
+
250
+	echos(&u->wst, 0x40, "stack");
251
+	echom(&u->ram, 0x40, "ram");
252
+	echof(u);
253
+
247 254
 	while(1) {
248 255
 		int tick = SDL_GetTicks();
249 256
 		SDL_Event event;
... ...
@@ -286,6 +293,11 @@ main(int argc, char **argv)
286 293
 	devmouse = portuxn(&u, "mouse", mouser, mousew);
287 294
 	devkey = portuxn(&u, "key", keyr, keyw);
288 295
 
296
+	devscreen->mem[0] = (WIDTH >> 8) & 0xff;
297
+	devscreen->mem[1] = WIDTH & 0xff;
298
+	devscreen->mem[2] = (HEIGHT >> 8) & 0xff;
299
+	devscreen->mem[3] = HEIGHT & 0xff;
300
+
289 301
 	start(&u);
290 302
 
291 303
 	echos(&u.wst, 0x40, "stack");
... ...
@@ -1,46 +1,40 @@
1
-( draw pixel )
1
+( mouse )
2 2
 
3
-|0100 @RESET
3
+:dev/r fff8 ( std read port )
4
+:dev/w fff9 ( std write port )
5
+
6
+|0100 @RESET 
4 7
 	
5
-	( draw 3 pixels )
6
-	,00 ,01 ,0000 ,0000 ,putpixel JSR
7
-	,00 ,02 ,0001 ,0001 ,putpixel JSR
8
-	,01 ,03 ,0002 ,0002 ,putpixel JSR
8
+	,02 ,dev/r STR ( set dev/read mouse#02 )
9
+	,01 ,dev/w STR ( set dev/write screen#01 )
9 10
 
10 11
 BRK
11 12
 
12
-|c000 @FRAME 
13
-	
13
+|c000 @FRAME
14
+
14 15
 	( get mouse button, or break )
15
-	,02 ,02 IOR
16
+	,04 IOR
16 17
 	,01 NEQ
17 18
 	BRK?
18
-
19
-	( print A to console on click )
20
-	,02 ,02 IOR
21
-	,41 ADD 
22
-	,putbyte JSR
23
-
19
+		
24 20
 	( paint a white pixel )
25 21
 	,01 ,01 
26 22
 	,getmouse JSR
27 23
 	,putpixel JSR
28
-BRK 
29 24
 
30
-@putpixel 
31
-	SWP ,01 IOW ,01 IOW ( y )
32
-	SWP ,01 IOW ,01 IOW ( x )
33
-	,01 IOW ( color )
34
-	,01 IOW ( redraw )
35
-	RTS
25
+BRK
36 26
 
37
-@getmouse ( push y,x to stack )
38
-	,00 ,01 ,02 IOR ( grab y )
39
-	,00 ,00 ,02 IOR ( grab x )
27
+@getmouse
28
+	,00 IOR^ ( get mouse x )
29
+	,02 IOR^ ( get mouse y )
40 30
 	RTS
41 31
 
42
-@putbyte ( print to console )
43
-	,00 IOW RTS 
32
+@putpixel 
33
+	IOW^ ( y short )
34
+	IOW^ ( x short )
35
+	IOW ( color byte )
36
+	IOW ( redraw byte )
37
+	RTS
44 38
 
45 39
 |d000 @ERROR BRK 
46 40
 |FFFA .RESET .FRAME .ERROR
47 41
new file mode 100644
... ...
@@ -0,0 +1,38 @@
1
+( screen )
2
+
3
+:dev/r fff8 ( std read port )
4
+:dev/w fff9 ( std write port )
5
+;width0
6
+;width1
7
+;height0
8
+;height1
9
+
10
+|0100 @RESET 
11
+	
12
+	( set read/write to dev/screen )
13
+	,01 DUP ,dev/r STR ,dev/w STR 
14
+
15
+	( load screen size )
16
+	,00 IOR^ ,width0 STR^
17
+	,02 IOR^ ,height0 STR^
18
+
19
+	( draw pixel at screen center )
20
+
21
+	,0101 
22
+	,width0 LDR^ ,0002 DIV^ 
23
+	,height0 LDR^ ,0002 DIV^ 
24
+	,putpixel JSR
25
+
26
+BRK
27
+
28
+|c000 @FRAME BRK
29
+
30
+@putpixel 
31
+	IOW^ ( y short )
32
+	IOW^ ( x short )
33
+	IOW ( color byte )
34
+	IOW ( redraw byte )
35
+	RTS
36
+
37
+|d000 @ERROR BRK 
38
+|FFFA .RESET .FRAME .ERROR
... ...
@@ -1,13 +1,45 @@
1 1
 ( my default test file )
2 2
 
3
-;iterator
3
+:dev/r fff8 ( std read port )
4
+:dev/w fff9 ( std write port )
4 5
 
5 6
 |0100 @RESET 
7
+	
8
+	,02 ,dev/r STR ( set dev/read mouse#02 )
9
+	,01 ,dev/w STR ( set dev/write screen#01 )
6 10
 
7
-	,1234
11
+	,00 ,01 ,0001 ,0000 ,putpixel JSR
12
+	,00 ,01 ,0000 ,0001 ,putpixel JSR
13
+	,00 ,01 ,0002 ,0001 ,putpixel JSR
14
+	,01 ,02 ,0001 ,0002 ,putpixel JSR
8 15
 
9 16
 BRK
10 17
 
11
-|c000 @FRAME BRK
18
+|c000 @FRAME
19
+
20
+	( get mouse button, or break )
21
+	,04 IOR
22
+	,01 NEQ
23
+	BRK?
24
+		
25
+	( paint a white pixel )
26
+	,01 ,01 
27
+	,getmouse JSR
28
+	,putpixel JSR
29
+
30
+BRK
31
+
32
+@getmouse
33
+	,02 IOR^ ( get mouse y )
34
+	,00 IOR^ ( get mouse x )
35
+	RTS
36
+
37
+@putpixel 
38
+	IOW^ ( y short )
39
+	IOW^ ( x short )
40
+	IOW ( color byte )
41
+	IOW ( redraw byte )
42
+	RTS
43
+
12 44
 |d000 @ERROR BRK 
13 45
 |FFFA .RESET .FRAME .ERROR
... ...
@@ -19,13 +19,13 @@ WITH REGARD TO THIS SOFTWARE.
19 19
 
20 20
 void   setflag(Uint8 *st, char flag, int b) { if(b) *st |= flag; else *st &= (~flag); }
21 21
 int    getflag(Uint8 *st, char flag) { return *st & flag; }
22
-Uint16 bytes2short(Uint8 a, Uint8 b) { return (a << 8) + b; }
23 22
 void   wspush8(Uxn *u, Uint8 b) { u->wst.dat[u->wst.ptr++] = b; }
24 23
 Uint8  wspop8(Uxn *u) { return u->wst.dat[--u->wst.ptr]; }
25 24
 Uint8  wspeek8(Uxn *u, Uint8 o) { return u->wst.dat[u->wst.ptr - o]; }
25
+Uint8  mempeek8(Uxn *u, Uint16 s) { return u->ram.dat[s]; }
26 26
 void   wspush16(Uxn *u, Uint16 s) { wspush8(u,s >> 8); wspush8(u,s & 0xff); }
27 27
 Uint16 wspop16(Uxn *u) { return wspop8(u) + (wspop8(u) << 8); }
28
-Uint16 wspeek16(Uxn *u, Uint8 o) { return bytes2short(u->wst.dat[u->wst.ptr - o], u->wst.dat[u->wst.ptr - o + 1]); }
28
+Uint16 wspeek16(Uxn *u, Uint8 o) { return (u->wst.dat[u->wst.ptr - o] << 8) + u->wst.dat[u->wst.ptr - o + 1]; }
29 29
 void   rspush16(Uxn *u, Uint16 a) { u->rst.dat[u->rst.ptr++] = a; }
30 30
 Uint16 mempeek16(Uxn *u, Uint16 s) { return (u->ram.dat[s] << 8) + (u->ram.dat[s + 1] & 0xff); }
31 31
 
... ...
@@ -34,8 +34,8 @@ void op_brk(Uxn *u) { setflag(&u->status,FLAG_HALT, 1); }
34 34
 void op_li1(Uxn *u) { u->literal += 1; }
35 35
 void op_lix(Uxn *u) { u->literal += u->ram.dat[u->ram.ptr++]; }
36 36
 void op_nop(Uxn *u) { printf("NOP"); (void)u; }
37
-void op_ior(Uxn *u) { Uint8 devid = wspop8(u); Uint16 devop = wspop8(u); Device *dev = &u->dev[devid]; if(devid < u->devices) wspush8(u, dev->rfn(dev,devop)); }
38
-void op_iow(Uxn *u) { Uint8 devid = wspop8(u); Uint16 devop = wspop8(u); Device *dev = &u->dev[devid]; if(devid < u->devices) dev->wfn(dev,devop); }
37
+void op_ior(Uxn *u) { Device *dev = &u->dev[mempeek8(u, u->devr)]; if(dev) wspush8(u, dev->read(dev, wspop8(u))); }
38
+void op_iow(Uxn *u) { Uint8 a = wspop8(u); Device *dev = &u->dev[mempeek8(u, u->devw)]; if(dev) dev->write(dev, a); }
39 39
 void op_ldr(Uxn *u) { Uint16 a = wspop16(u); wspush8(u, u->ram.dat[a]); }
40 40
 void op_str(Uxn *u) { Uint16 a = wspop16(u); Uint8 b = wspop8(u); u->ram.dat[a] = b; }
41 41
 /* Logic */
... ...
@@ -60,6 +60,11 @@ void op_equ(Uxn *u) { Uint8 a = wspop8(u), b = wspop8(u); wspush8(u, b == a); }
60 60
 void op_neq(Uxn *u) { Uint8 a = wspop8(u), b = wspop8(u); wspush8(u, b != a); }
61 61
 void op_gth(Uxn *u) { Uint8 a = wspop8(u), b = wspop8(u); wspush8(u, b > a); }
62 62
 void op_lth(Uxn *u) { Uint8 a = wspop8(u), b = wspop8(u); wspush8(u, b < a); }
63
+/* --- */
64
+void op_ior16(Uxn *u) { Uint8 a = wspop8(u); Device *dev = &u->dev[mempeek8(u, u->devr)]; if(dev) wspush16(u, (dev->read(dev, a) << 8) + dev->read(dev, a + 1)); }
65
+void op_iow16(Uxn *u) { Uint8 a = wspop8(u); Uint8 b = wspop8(u); Device *dev = &u->dev[mempeek8(u, u->devw)]; if(dev) { dev->write(dev, b); dev->write(dev, a); } }
66
+void op_ldr16(Uxn *u) { Uint16 a = wspop16(u); wspush16(u, (u->ram.dat[a] << 8) + u->ram.dat[a + 1]); }
67
+void op_str16(Uxn *u) { Uint16 a = wspop16(u); Uint16 b = wspop16(u); u->ram.dat[a] = b >> 8; u->ram.dat[a + 1] = b & 0xff; }
63 68
 /* Stack(16-bits) */
64 69
 void op_pop16(Uxn *u) { wspop16(u); }
65 70
 void op_dup16(Uxn *u) { wspush16(u, wspeek16(u, 2)); }
... ...
@@ -84,15 +89,21 @@ void (*ops[])(Uxn *u) = {
84 89
 	op_jmp, op_jsr, op_nop, op_rts, op_nop, op_nop, op_nop, op_nop, 
85 90
 	op_pop, op_dup, op_swp, op_ovr, op_rot, op_and, op_ora, op_rol,
86 91
 	op_add, op_sub, op_mul, op_div, op_equ, op_neq, op_gth, op_lth,
92
+	/* 16-bit */
93
+	op_brk, op_nop, op_li1, op_lix, op_ior16, op_iow16, op_ldr16, op_str16, 
94
+	op_jmp, op_jsr, op_nop, op_rts, op_nop, op_nop, op_nop, op_nop, 
87 95
 	op_pop16, op_dup16, op_swp16, op_ovr16, op_rot16, op_and16, op_ora16, op_rol16,
88 96
 	op_add16, op_sub16, op_mul16, op_div16, op_equ16, op_neq16, op_gth16, op_lth16
89 97
 };
90 98
 
91 99
 Uint8 opr[][2] = { 
92
-	{0,0}, {0,0}, {0,0}, {0,0}, {2,1}, {2,0}, {2,1}, {3,0},
100
+	{0,0}, {0,0}, {0,0}, {0,0}, {1,1}, {1,0}, {2,1}, {3,0},
93 101
 	{2,0}, {2,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0},
94 102
 	{1,0}, {1,2}, {2,2}, {3,3}, {3,3}, {2,1}, {2,1}, {2,1},
95 103
 	{2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1}, {2,1},
104
+	/* 16-bit */
105
+	{0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, /* TODO */
106
+	{0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, /* TODO */
96 107
 	{0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, /* TODO */
97 108
 	{0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}, {0,0}  /* TODO */
98 109
 };
... ...
@@ -124,7 +135,7 @@ opcuxn(Uxn *u, Uint8 instr)
124 135
 	setflag(&u->status, FLAG_SIGN, (instr >> 6) & 1); /* usused */
125 136
 	setflag(&u->status, FLAG_COND, (instr >> 7) & 1);
126 137
 	if(getflag(&u->status, FLAG_SHORT))
127
-		op += 16;
138
+		op += 32;
128 139
 	if(u->wst.ptr < opr[op][0])
129 140
 		return haltuxn(u, "Stack underflow", op);
130 141
 	if(u->wst.ptr + opr[op][1] - opr[op][0] >= 255)
... ...
@@ -174,6 +185,8 @@ loaduxn(Uxn *u, char *filepath)
174 185
 	if(!(f = fopen(filepath, "rb")))
175 186
 		return haltuxn(u, "Missing input.", 0);
176 187
 	fread(u->ram.dat, sizeof(u->ram.dat), 1, f);
188
+	u->devr = 0xfff8;
189
+	u->devw = 0xfff9;
177 190
 	u->vreset = mempeek16(u, 0xfffa);
178 191
 	u->vframe = mempeek16(u, 0xfffc);
179 192
 	u->verror = mempeek16(u, 0xfffe);
... ...
@@ -188,11 +201,11 @@ loaduxn(Uxn *u, char *filepath)
188 201
 /* to start: evaluxn(u, u->vreset); */
189 202
 
190 203
 Device *
191
-portuxn(Uxn *u, char *name, Uint8 (*onread)(Device *, Uint8), Uint8 (*onwrite)(Device *, Uint8))
204
+portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Uint8), Uint8 (*wfn)(Device *, Uint8))
192 205
 {
193 206
 	Device *d = &u->dev[u->devices++];
194
-	d->rfn = onread;
195
-	d->wfn = onwrite;
207
+	d->read = rfn;
208
+	d->write = wfn;
196 209
 	d->len = 0;
197 210
 	printf("Device#%d: %s \n", u->devices, name);
198 211
 	return d;
... ...
@@ -36,13 +36,13 @@ typedef struct {
36 36
 
37 37
 typedef struct Device {
38 38
 	Uint8 len, mem[8];
39
-	Uint8 (*rfn)(struct Device *, Uint8);
40
-	Uint8 (*wfn)(struct Device *, Uint8);
39
+	Uint8 (*read)(struct Device *, Uint8);
40
+	Uint8 (*write)(struct Device *, Uint8);
41 41
 } Device;
42 42
 
43 43
 typedef struct {
44 44
 	Uint8 literal, status, devices;
45
-	Uint16 counter, vreset, vframe, verror;
45
+	Uint16 counter, devr, devw, vreset, vframe, verror;
46 46
 	Stack8 wst;
47 47
 	Stack16 rst;
48 48
 	Memory ram;
... ...
@@ -54,4 +54,4 @@ int getflag(Uint8 *status, char flag);
54 54
 int loaduxn(Uxn *c, char *filepath);
55 55
 int bootuxn(Uxn *c);
56 56
 int evaluxn(Uxn *u, Uint16 vec);
57
-Device *portuxn(Uxn *u, char *name, Uint8 (*onread)(Device *, Uint8), Uint8 (*onwrite)(Device *, Uint8));
57
+Device *portuxn(Uxn *u, char *name, Uint8 (*rfn)(Device *, Uint8), Uint8 (*wfn)(Device *, Uint8));