Browse code

Split talk functions into dei and deo; make deo functions void

Andrew Alderwick authored on 04/11/2021 16:38:32
Showing 5 changed files
... ...
@@ -30,11 +30,11 @@ See etc/mkuxn-fast.moon for instructions.
30 30
 /* clang-format off */
31 31
 static void   poke8(Uint8 *m, Uint16 a, Uint8 b) { m[a] = b; }
32 32
 static Uint8  peek8(Uint8 *m, Uint16 a) { return m[a]; }
33
-static int    devw8(Device *d, Uint8 a, Uint8 b) { d->dat[a & 0xf] = b; return d->talk(d, a & 0x0f, 1); }
34
-static Uint8  devr8(Device *d, Uint8 a) { d->talk(d, a & 0x0f, 0); return d->dat[a & 0xf];  }
33
+static void   devw8(Device *d, Uint8 a, Uint8 b) { d->dat[a & 0xf] = b; d->deo(d, a & 0x0f); }
34
+static Uint8  devr8(Device *d, Uint8 a) { return d->dei(d, a & 0x0f); }
35 35
 void   poke16(Uint8 *m, Uint16 a, Uint16 b) { poke8(m, a, b >> 8); poke8(m, a + 1, b); }
36 36
 Uint16 peek16(Uint8 *m, Uint16 a) { return (peek8(m, a) << 8) + peek8(m, a + 1); }
37
-static int    devw16(Device *d, Uint8 a, Uint16 b) { return devw8(d, a, b >> 8) && devw8(d, a + 1, b); }
37
+static void   devw16(Device *d, Uint8 a, Uint16 b) { devw8(d, a, b >> 8); devw8(d, a + 1, b); }
38 38
 
39 39
 /* clang-format on */
40 40
 
... ...
@@ -366,8 +366,7 @@ uxn_eval(Uxn *u, Uint16 vec)
366 366
 		case 0x17: /* DEO */
367 367
 			{
368 368
 				Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
369
-				if(!devw8(&u->dev[a >> 4], a, b))
370
-					return 1;
369
+				devw8(&u->dev[a >> 4], a, b);
371 370
 #ifndef NO_STACK_CHECKS
372 371
 				if(__builtin_expect(u->wst.ptr < 2, 0)) {
373 372
 					u->wst.error = 1;
... ...
@@ -828,8 +827,7 @@ uxn_eval(Uxn *u, Uint16 vec)
828 827
 			{
829 828
 				Uint8 a = u->wst.dat[u->wst.ptr - 1];
830 829
 				Uint16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8));
831
-				if(!devw16(&u->dev[a >> 4], a, b))
832
-					return 1;
830
+				devw16(&u->dev[a >> 4], a, b);
833 831
 #ifndef NO_STACK_CHECKS
834 832
 				if(__builtin_expect(u->wst.ptr < 3, 0)) {
835 833
 					u->wst.error = 1;
... ...
@@ -1272,8 +1270,7 @@ uxn_eval(Uxn *u, Uint16 vec)
1272 1270
 		case 0x57: /* DEOr */
1273 1271
 			{
1274 1272
 				Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
1275
-				if(!devw8(&u->dev[a >> 4], a, b))
1276
-					return 1;
1273
+				devw8(&u->dev[a >> 4], a, b);
1277 1274
 #ifndef NO_STACK_CHECKS
1278 1275
 				if(__builtin_expect(u->rst.ptr < 2, 0)) {
1279 1276
 					u->rst.error = 1;
... ...
@@ -1734,8 +1731,7 @@ uxn_eval(Uxn *u, Uint16 vec)
1734 1731
 			{
1735 1732
 				Uint8 a = u->rst.dat[u->rst.ptr - 1];
1736 1733
 				Uint16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8));
1737
-				if(!devw16(&u->dev[a >> 4], a, b))
1738
-					return 1;
1734
+				devw16(&u->dev[a >> 4], a, b);
1739 1735
 #ifndef NO_STACK_CHECKS
1740 1736
 				if(__builtin_expect(u->rst.ptr < 3, 0)) {
1741 1737
 					u->rst.error = 1;
... ...
@@ -2235,8 +2231,7 @@ uxn_eval(Uxn *u, Uint16 vec)
2235 2231
 		case 0x97: /* DEOk */
2236 2232
 			{
2237 2233
 				Uint8 a = u->wst.dat[u->wst.ptr - 1], b = u->wst.dat[u->wst.ptr - 2];
2238
-				if(!devw8(&u->dev[a >> 4], a, b))
2239
-					return 1;
2234
+				devw8(&u->dev[a >> 4], a, b);
2240 2235
 #ifndef NO_STACK_CHECKS
2241 2236
 				if(__builtin_expect(u->wst.ptr < 2, 0)) {
2242 2237
 					u->wst.error = 1;
... ...
@@ -2776,8 +2771,7 @@ uxn_eval(Uxn *u, Uint16 vec)
2776 2771
 			{
2777 2772
 				Uint8 a = u->wst.dat[u->wst.ptr - 1];
2778 2773
 				Uint16 b = (u->wst.dat[u->wst.ptr - 2] | (u->wst.dat[u->wst.ptr - 3] << 8));
2779
-				if(!devw16(&u->dev[a >> 4], a, b))
2780
-					return 1;
2774
+				devw16(&u->dev[a >> 4], a, b);
2781 2775
 #ifndef NO_STACK_CHECKS
2782 2776
 				if(__builtin_expect(u->wst.ptr < 3, 0)) {
2783 2777
 					u->wst.error = 1;
... ...
@@ -3309,8 +3303,7 @@ uxn_eval(Uxn *u, Uint16 vec)
3309 3303
 		case 0xd7: /* DEOkr */
3310 3304
 			{
3311 3305
 				Uint8 a = u->rst.dat[u->rst.ptr - 1], b = u->rst.dat[u->rst.ptr - 2];
3312
-				if(!devw8(&u->dev[a >> 4], a, b))
3313
-					return 1;
3306
+				devw8(&u->dev[a >> 4], a, b);
3314 3307
 #ifndef NO_STACK_CHECKS
3315 3308
 				if(__builtin_expect(u->rst.ptr < 2, 0)) {
3316 3309
 					u->rst.error = 1;
... ...
@@ -3850,8 +3843,7 @@ uxn_eval(Uxn *u, Uint16 vec)
3850 3843
 			{
3851 3844
 				Uint8 a = u->rst.dat[u->rst.ptr - 1];
3852 3845
 				Uint16 b = (u->rst.dat[u->rst.ptr - 2] | (u->rst.dat[u->rst.ptr - 3] << 8));
3853
-				if(!devw16(&u->dev[a >> 4], a, b))
3854
-					return 1;
3846
+				devw16(&u->dev[a >> 4], a, b);
3855 3847
 #ifndef NO_STACK_CHECKS
3856 3848
 				if(__builtin_expect(u->rst.ptr < 3, 0)) {
3857 3849
 					u->rst.error = 1;
... ...
@@ -4036,12 +4028,13 @@ uxn_boot(Uxn *u)
4036 4028
 }
4037 4029
 
4038 4030
 Device *
4039
-uxn_port(Uxn *u, Uint8 id, int (*talkfn)(Device *d, Uint8 b0, Uint8 w))
4031
+uxn_port(Uxn *u, Uint8 id, Uint8 (*deifn)(Device *d, Uint8 b0), void (*deofn)(Device *d, Uint8 b0))
4040 4032
 {
4041 4033
 	Device *d = &u->dev[id];
4042 4034
 	d->addr = id * 0x10;
4043 4035
 	d->u = u;
4044 4036
 	d->mem = u->ram.dat;
4045
-	d->talk = talkfn;
4037
+	d->dei = deifn;
4038
+	d->deo = deofn;
4046 4039
 	return d;
4047 4040
 }
... ...
@@ -26,7 +26,7 @@ static Uint16 (*pop8)(Stack *s);
26 26
 static Uint16 (*pop)(Stack *s);
27 27
 static void   (*poke)(Uint8 *m, Uint16 a, Uint16 b);
28 28
 static Uint16 (*peek)(Uint8 *m, Uint16 a);
29
-static int    (*devw)(Device *d, Uint8 a, Uint16 b);
29
+static void   (*devw)(Device *d, Uint8 a, Uint16 b);
30 30
 static Uint16 (*devr)(Device *d, Uint8 a);
31 31
 static void   (*warp)(Uxn *u, Uint16 a);
32 32
 static void   (*pull)(Uxn *u);
... ...
@@ -36,8 +36,8 @@ static Uint16 pop8k(Stack *s) { if(s->kptr == 0) { s->error = 1; return 0; } ret
36 36
 static Uint16 pop8d(Stack *s) { if(s->ptr == 0) { s->error = 1; return 0; } return s->dat[--s->ptr]; }
37 37
 static void   poke8(Uint8 *m, Uint16 a, Uint16 b) { m[a] = b; }
38 38
 static Uint16 peek8(Uint8 *m, Uint16 a) { return m[a]; }
39
-static int    devw8(Device *d, Uint8 a, Uint16 b) { d->dat[a & 0xf] = b; return d->talk(d, a & 0x0f, 1); }
40
-static Uint16 devr8(Device *d, Uint8 a) { d->talk(d, a & 0x0f, 0); return d->dat[a & 0xf];  }
39
+static void   devw8(Device *d, Uint8 a, Uint16 b) { d->dat[a & 0xf] = b; d->deo(d, a & 0x0f); }
40
+static Uint16 devr8(Device *d, Uint8 a) { return d->dei(d, a & 0x0f); }
41 41
 static void   warp8(Uxn *u, Uint16 a){ u->ram.ptr += (Sint8)a; }
42 42
 static void   pull8(Uxn *u){ push8(u->src, peek8(u->ram.dat, u->ram.ptr++)); }
43 43
 /* short mode */
... ...
@@ -45,7 +45,7 @@ static void   push16(Stack *s, Uint16 a) { push8(s, a >> 8); push8(s, a); }
45 45
 static Uint16 pop16(Stack *s) { Uint8 a = pop8(s), b = pop8(s); return a + (b << 8); }
46 46
 	   void   poke16(Uint8 *m, Uint16 a, Uint16 b) { poke8(m, a, b >> 8); poke8(m, a + 1, b); }
47 47
 	   Uint16 peek16(Uint8 *m, Uint16 a) { return (peek8(m, a) << 8) + peek8(m, a + 1); }
48
-static int    devw16(Device *d, Uint8 a, Uint16 b) { return devw8(d, a, b >> 8) && devw8(d, a + 1, b); }
48
+static void   devw16(Device *d, Uint8 a, Uint16 b) { devw8(d, a, b >> 8); devw8(d, a + 1, b); }
49 49
 static Uint16 devr16(Device *d, Uint8 a) { return (devr8(d, a) << 8) + devr8(d, a + 1); }
50 50
 static void   warp16(Uxn *u, Uint16 a){ u->ram.ptr = a; }
51 51
 static void   pull16(Uxn *u){ push16(u->src, peek16(u->ram.dat, u->ram.ptr++)); u->ram.ptr++; }
... ...
@@ -116,7 +116,7 @@ uxn_eval(Uxn *u, Uint16 vec)
116 116
 			case 0x14: /* LDA */ a = pop16(u->src); push(u->src, peek(u->ram.dat, a)); break;
117 117
 			case 0x15: /* STA */ a = pop16(u->src); b = pop(u->src); poke(u->ram.dat, a, b); break;
118 118
 			case 0x16: /* DEI */ a = pop8(u->src); push(u->src, devr(&u->dev[a >> 4], a)); break;
119
-			case 0x17: /* DEO */ a = pop8(u->src); b = pop(u->src); if (!devw(&u->dev[a >> 4], a, b)) return 1; break;
119
+			case 0x17: /* DEO */ a = pop8(u->src); b = pop(u->src); devw(&u->dev[a >> 4], a, b); break;
120 120
 			/* Arithmetic */
121 121
 			case 0x18: /* ADD */ a = pop(u->src), b = pop(u->src); push(u->src, b + a); break;
122 122
 			case 0x19: /* SUB */ a = pop(u->src), b = pop(u->src); push(u->src, b - a); break;
... ...
@@ -146,12 +146,13 @@ uxn_boot(Uxn *u)
146 146
 }
147 147
 
148 148
 Device *
149
-uxn_port(Uxn *u, Uint8 id, int (*talkfn)(Device *d, Uint8 b0, Uint8 w))
149
+uxn_port(Uxn *u, Uint8 id, Uint8 (*deifn)(Device *d, Uint8 b0), void (*deofn)(Device *d, Uint8 b0))
150 150
 {
151 151
 	Device *d = &u->dev[id];
152 152
 	d->addr = id * 0x10;
153 153
 	d->u = u;
154 154
 	d->mem = u->ram.dat;
155
-	d->talk = talkfn;
155
+	d->dei = deifn;
156
+	d->deo = deofn;
156 157
 	return d;
157 158
 }
... ...
@@ -30,7 +30,8 @@ typedef struct Device {
30 30
 	struct Uxn *u;
31 31
 	Uint8 addr, dat[16], *mem;
32 32
 	Uint16 vector;
33
-	int (*talk)(struct Device *d, Uint8, Uint8);
33
+	Uint8 (*dei)(struct Device *d, Uint8);
34
+	void (*deo)(struct Device *d, Uint8);
34 35
 } Device;
35 36
 
36 37
 typedef struct Uxn {
... ...
@@ -47,4 +48,4 @@ Uint16 peek16(Uint8 *m, Uint16 a);
47 48
 int uxn_boot(Uxn *c);
48 49
 int uxn_eval(Uxn *u, Uint16 vec);
49 50
 int uxn_halt(Uxn *u, Uint8 error, char *name, int id);
50
-Device *uxn_port(Uxn *u, Uint8 id, int (*talkfn)(Device *, Uint8, Uint8));
51
+Device *uxn_port(Uxn *u, Uint8 id, Uint8 (*deifn)(Device *, Uint8), void (*deofn)(Device *, Uint8));
... ...
@@ -43,43 +43,43 @@ inspect(Stack *s, char *name)
43 43
 
44 44
 #pragma mark - Devices
45 45
 
46
-static int
47
-system_talk(Device *d, Uint8 b0, Uint8 w)
46
+static Uint8
47
+system_dei(Device *d, Uint8 b0)
48 48
 {
49
-	if(!w) { /* read */
50
-		switch(b0) {
51
-		case 0x2: d->dat[0x2] = d->u->wst.ptr; break;
52
-		case 0x3: d->dat[0x3] = d->u->rst.ptr; break;
53
-		}
54
-	} else { /* write */
55
-		switch(b0) {
56
-		case 0x2: d->u->wst.ptr = d->dat[0x2]; break;
57
-		case 0x3: d->u->rst.ptr = d->dat[0x3]; break;
58
-		case 0xe:
59
-			inspect(&d->u->wst, "Working-stack");
60
-			inspect(&d->u->rst, "Return-stack");
61
-			break;
62
-		case 0xf: return 0;
63
-		}
49
+	switch(b0) {
50
+	case 0x2: return d->u->wst.ptr;
51
+	case 0x3: return d->u->rst.ptr;
52
+	default: return d->dat[b0];
64 53
 	}
65
-	return 1;
66 54
 }
67 55
 
68
-static int
69
-console_talk(Device *d, Uint8 b0, Uint8 w)
56
+static void
57
+system_deo(Device *d, Uint8 b0)
58
+{
59
+	switch(b0) {
60
+	case 0x2: d->u->wst.ptr = d->dat[b0]; break;
61
+	case 0x3: d->u->rst.ptr = d->dat[b0]; break;
62
+	case 0xe:
63
+		inspect(&d->u->wst, "Working-stack");
64
+		inspect(&d->u->rst, "Return-stack");
65
+		break;
66
+	}
67
+}
68
+
69
+static void
70
+console_deo(Device *d, Uint8 b0)
70 71
 {
71 72
 	if(b0 == 0x1)
72 73
 		d->vector = peek16(d->dat, 0x0);
73
-	if(w && b0 > 0x7)
74
+	if(b0 > 0x7)
74 75
 		write(b0 - 0x7, (char *)&d->dat[b0], 1);
75
-	return 1;
76 76
 }
77 77
 
78
-static int
79
-file_talk(Device *d, Uint8 b0, Uint8 w)
78
+static void
79
+file_deo(Device *d, Uint8 b0)
80 80
 {
81 81
 	Uint8 read = b0 == 0xd;
82
-	if(w && (read || b0 == 0xf)) {
82
+	if(read || b0 == 0xf) {
83 83
 		char *name = (char *)&d->mem[peek16(d->dat, 0x8)];
84 84
 		Uint16 result = 0, length = peek16(d->dat, 0xa);
85 85
 		long offset = (peek16(d->dat, 0x4) << 16) + peek16(d->dat, 0x6);
... ...
@@ -92,36 +92,39 @@ file_talk(Device *d, Uint8 b0, Uint8 w)
92 92
 		}
93 93
 		poke16(d->dat, 0x2, result);
94 94
 	}
95
-	return 1;
96 95
 }
97 96
 
98
-static int
99
-datetime_talk(Device *d, Uint8 b0, Uint8 w)
97
+static Uint8
98
+datetime_dei(Device *d, Uint8 b0)
100 99
 {
101 100
 	time_t seconds = time(NULL);
102 101
 	struct tm *t = localtime(&seconds);
103
-	t->tm_year += 1900;
104
-	poke16(d->dat, 0x0, t->tm_year);
105
-	d->dat[0x2] = t->tm_mon;
106
-	d->dat[0x3] = t->tm_mday;
107
-	d->dat[0x4] = t->tm_hour;
108
-	d->dat[0x5] = t->tm_min;
109
-	d->dat[0x6] = t->tm_sec;
110
-	d->dat[0x7] = t->tm_wday;
111
-	poke16(d->dat, 0x08, t->tm_yday);
112
-	d->dat[0xa] = t->tm_isdst;
113
-	(void)b0;
114
-	(void)w;
115
-	return 1;
102
+	switch(b0) {
103
+	case 0x0: return (t->tm_year + 1900) >> 8;
104
+	case 0x1: return (t->tm_year + 1900);
105
+	case 0x2: return t->tm_mon;
106
+	case 0x3: return t->tm_mday;
107
+	case 0x4: return t->tm_hour;
108
+	case 0x5: return t->tm_min;
109
+	case 0x6: return t->tm_sec;
110
+	case 0x7: return t->tm_wday;
111
+	case 0x8: return t->tm_yday >> 8;
112
+	case 0x9: return t->tm_yday;
113
+	case 0xa: return t->tm_isdst;
114
+	default: return d->dat[b0];
115
+	}
116 116
 }
117 117
 
118
-static int
119
-nil_talk(Device *d, Uint8 b0, Uint8 w)
118
+static Uint8
119
+nil_dei(Device *d, Uint8 b0)
120 120
 {
121
-	(void)d;
122
-	(void)b0;
123
-	(void)w;
124
-	return 1;
121
+	return d->dat[b0];
122
+}
123
+
124
+static void
125
+nil_deo(Device *d, Uint8 b0)
126
+{
127
+	if(b0 == 0x1) d->vector = peek16(d->dat, 0x0);
125 128
 }
126 129
 
127 130
 #pragma mark - Generics
... ...
@@ -173,22 +176,22 @@ main(int argc, char **argv)
173 176
 	if(!uxn_boot(&u))
174 177
 		return error("Boot", "Failed");
175 178
 
176
-	/* system   */ devsystem = uxn_port(&u, 0x0, system_talk);
177
-	/* console  */ devconsole = uxn_port(&u, 0x1, console_talk);
178
-	/* empty    */ uxn_port(&u, 0x2, nil_talk);
179
-	/* empty    */ uxn_port(&u, 0x3, nil_talk);
180
-	/* empty    */ uxn_port(&u, 0x4, nil_talk);
181
-	/* empty    */ uxn_port(&u, 0x5, nil_talk);
182
-	/* empty    */ uxn_port(&u, 0x6, nil_talk);
183
-	/* empty    */ uxn_port(&u, 0x7, nil_talk);
184
-	/* empty    */ uxn_port(&u, 0x8, nil_talk);
185
-	/* empty    */ uxn_port(&u, 0x9, nil_talk);
186
-	/* file     */ uxn_port(&u, 0xa, file_talk);
187
-	/* datetime */ uxn_port(&u, 0xb, datetime_talk);
188
-	/* empty    */ uxn_port(&u, 0xc, nil_talk);
189
-	/* empty    */ uxn_port(&u, 0xd, nil_talk);
190
-	/* empty    */ uxn_port(&u, 0xe, nil_talk);
191
-	/* empty    */ uxn_port(&u, 0xf, nil_talk);
179
+	/* system   */ devsystem = uxn_port(&u, 0x0, system_dei, system_deo);
180
+	/* console  */ devconsole = uxn_port(&u, 0x1, nil_dei, console_deo);
181
+	/* empty    */ uxn_port(&u, 0x2, nil_dei, nil_deo);
182
+	/* empty    */ uxn_port(&u, 0x3, nil_dei, nil_deo);
183
+	/* empty    */ uxn_port(&u, 0x4, nil_dei, nil_deo);
184
+	/* empty    */ uxn_port(&u, 0x5, nil_dei, nil_deo);
185
+	/* empty    */ uxn_port(&u, 0x6, nil_dei, nil_deo);
186
+	/* empty    */ uxn_port(&u, 0x7, nil_dei, nil_deo);
187
+	/* empty    */ uxn_port(&u, 0x8, nil_dei, nil_deo);
188
+	/* empty    */ uxn_port(&u, 0x9, nil_dei, nil_deo);
189
+	/* file     */ uxn_port(&u, 0xa, nil_dei, file_deo);
190
+	/* datetime */ uxn_port(&u, 0xb, datetime_dei, nil_deo);
191
+	/* empty    */ uxn_port(&u, 0xc, nil_dei, nil_deo);
192
+	/* empty    */ uxn_port(&u, 0xd, nil_dei, nil_deo);
193
+	/* empty    */ uxn_port(&u, 0xe, nil_dei, nil_deo);
194
+	/* empty    */ uxn_port(&u, 0xf, nil_dei, nil_deo);
192 195
 
193 196
 	for(i = 1; i < argc; ++i) {
194 197
 		if(!loaded++) {
... ...
@@ -289,87 +289,89 @@ doctrl(SDL_Event *event, int z)
289 289
 
290 290
 #pragma mark - Devices
291 291
 
292
-static int
293
-system_talk(Device *d, Uint8 b0, Uint8 w)
292
+static Uint8
293
+system_dei(Device *d, Uint8 b0)
294 294
 {
295
-	if(!w) { /* read */
296
-		switch(b0) {
297
-		case 0x2: d->dat[0x2] = d->u->wst.ptr; break;
298
-		case 0x3: d->dat[0x3] = d->u->rst.ptr; break;
299
-		}
300
-	} else { /* write */
301
-		switch(b0) {
302
-		case 0x2: d->u->wst.ptr = d->dat[0x2]; break;
303
-		case 0x3: d->u->rst.ptr = d->dat[0x3]; break;
304
-		case 0xf: return 0;
305
-		}
306
-		if(b0 > 0x7 && b0 < 0xe)
307
-			set_palette(&d->dat[0x8]);
295
+	switch(b0) {
296
+	case 0x2: return d->u->wst.ptr;
297
+	case 0x3: return d->u->rst.ptr;
298
+	default: return d->dat[b0];
308 299
 	}
309
-	return 1;
310 300
 }
311 301
 
312
-static int
313
-console_talk(Device *d, Uint8 b0, Uint8 w)
302
+static void
303
+system_deo(Device *d, Uint8 b0)
314 304
 {
315
-	if(w) {
316
-		if(b0 == 0x1)
317
-			d->vector = peek16(d->dat, 0x0);
318
-		if(b0 > 0x7)
319
-			write(b0 - 0x7, (char *)&d->dat[b0], 1);
305
+	switch(b0) {
306
+	case 0x2: d->u->wst.ptr = d->dat[b0]; break;
307
+	case 0x3: d->u->rst.ptr = d->dat[b0]; break;
320 308
 	}
321
-	return 1;
309
+	if(b0 > 0x7 && b0 < 0xe)
310
+		set_palette(&d->dat[0x8]);
322 311
 }
323 312
 
324
-static int
325
-screen_talk(Device *d, Uint8 b0, Uint8 w)
313
+static void
314
+console_deo(Device *d, Uint8 b0)
326 315
 {
327
-	if(!w) switch(b0) {
328
-		case 0x2: d->dat[0x2] = ppu.width >> 8; break;
329
-		case 0x3: d->dat[0x3] = ppu.width; break;
330
-		case 0x4: d->dat[0x4] = ppu.height >> 8; break;
331
-		case 0x5: d->dat[0x5] = ppu.height; break;
332
-		}
333
-	else
334
-		switch(b0) {
335
-		case 0x1: d->vector = peek16(d->dat, 0x0); break;
336
-		case 0x5:
337
-			if(!FIXED_SIZE) return set_size(peek16(d->dat, 0x2), peek16(d->dat, 0x4), 1);
338
-			break;
339
-		case 0xe: {
340
-			Uint16 x = peek16(d->dat, 0x8);
341
-			Uint16 y = peek16(d->dat, 0xa);
342
-			Uint8 layer = d->dat[0xe] & 0x40;
343
-			ppu_write(&ppu, !!layer, x, y, d->dat[0xe] & 0x3);
344
-			if(d->dat[0x6] & 0x01) poke16(d->dat, 0x8, x + 1); /* auto x+1 */
345
-			if(d->dat[0x6] & 0x02) poke16(d->dat, 0xa, y + 1); /* auto y+1 */
346
-			break;
347
-		}
348
-		case 0xf: {
349
-			Uint16 x = peek16(d->dat, 0x8);
350
-			Uint16 y = peek16(d->dat, 0xa);
351
-			Uint8 layer = d->dat[0xf] & 0x40;
352
-			Uint8 *addr = &d->mem[peek16(d->dat, 0xc)];
353
-			if(d->dat[0xf] & 0x80) {
354
-				ppu_2bpp(&ppu, !!layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20);
355
-				if(d->dat[0x6] & 0x04) poke16(d->dat, 0xc, peek16(d->dat, 0xc) + 16); /* auto addr+16 */
356
-			} else {
357
-				ppu_1bpp(&ppu, !!layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20);
358
-				if(d->dat[0x6] & 0x04) poke16(d->dat, 0xc, peek16(d->dat, 0xc) + 8); /* auto addr+8 */
359
-			}
360
-			if(d->dat[0x6] & 0x01) poke16(d->dat, 0x8, x + 8); /* auto x+8 */
361
-			if(d->dat[0x6] & 0x02) poke16(d->dat, 0xa, y + 8); /* auto y+8 */
362
-			break;
363
-		}
316
+	if(b0 == 0x1)
317
+		d->vector = peek16(d->dat, 0x0);
318
+	if(b0 > 0x7)
319
+		write(b0 - 0x7, (char *)&d->dat[b0], 1);
320
+}
321
+
322
+static Uint8
323
+screen_dei(Device *d, Uint8 b0)
324
+{
325
+	switch(b0) {
326
+	case 0x2: return ppu.width >> 8;
327
+	case 0x3: return ppu.width;
328
+	case 0x4: return ppu.height >> 8;
329
+	case 0x5: return ppu.height;
330
+	default: return d->dat[b0];
331
+	}
332
+}
333
+
334
+static void
335
+screen_deo(Device *d, Uint8 b0)
336
+{
337
+	switch(b0) {
338
+	case 0x1: d->vector = peek16(d->dat, 0x0); break;
339
+	case 0x5:
340
+		if(!FIXED_SIZE) set_size(peek16(d->dat, 0x2), peek16(d->dat, 0x4), 1);
341
+		break;
342
+	case 0xe: {
343
+		Uint16 x = peek16(d->dat, 0x8);
344
+		Uint16 y = peek16(d->dat, 0xa);
345
+		Uint8 layer = d->dat[0xe] & 0x40;
346
+		ppu_write(&ppu, !!layer, x, y, d->dat[0xe] & 0x3);
347
+		if(d->dat[0x6] & 0x01) poke16(d->dat, 0x8, x + 1); /* auto x+1 */
348
+		if(d->dat[0x6] & 0x02) poke16(d->dat, 0xa, y + 1); /* auto y+1 */
349
+		break;
350
+	}
351
+	case 0xf: {
352
+		Uint16 x = peek16(d->dat, 0x8);
353
+		Uint16 y = peek16(d->dat, 0xa);
354
+		Uint8 layer = d->dat[0xf] & 0x40;
355
+		Uint8 *addr = &d->mem[peek16(d->dat, 0xc)];
356
+		if(d->dat[0xf] & 0x80) {
357
+			ppu_2bpp(&ppu, !!layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20);
358
+			if(d->dat[0x6] & 0x04) poke16(d->dat, 0xc, peek16(d->dat, 0xc) + 16); /* auto addr+16 */
359
+		} else {
360
+			ppu_1bpp(&ppu, !!layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20);
361
+			if(d->dat[0x6] & 0x04) poke16(d->dat, 0xc, peek16(d->dat, 0xc) + 8); /* auto addr+8 */
364 362
 		}
365
-	return 1;
363
+		if(d->dat[0x6] & 0x01) poke16(d->dat, 0x8, x + 8); /* auto x+8 */
364
+		if(d->dat[0x6] & 0x02) poke16(d->dat, 0xa, y + 8); /* auto y+8 */
365
+		break;
366
+	}
367
+	}
366 368
 }
367 369
 
368
-static int
369
-file_talk(Device *d, Uint8 b0, Uint8 w)
370
+static void
371
+file_deo(Device *d, Uint8 b0)
370 372
 {
371 373
 	Uint8 read = b0 == 0xd;
372
-	if(w && (read || b0 == 0xf)) {
374
+	if(read || b0 == 0xf) {
373 375
 		char *name = (char *)&d->mem[peek16(d->dat, 0x8)];
374 376
 		Uint16 result = 0, length = peek16(d->dat, 0xa);
375 377
 		long offset = (peek16(d->dat, 0x4) << 16) + peek16(d->dat, 0x6);
... ...
@@ -382,20 +384,26 @@ file_talk(Device *d, Uint8 b0, Uint8 w)
382 384
 		}
383 385
 		poke16(d->dat, 0x2, result);
384 386
 	}
385
-	return 1;
386 387
 }
387 388
 
388
-static int
389
-audio_talk(Device *d, Uint8 b0, Uint8 w)
389
+static Uint8
390
+audio_dei(Device *d, Uint8 b0)
390 391
 {
391 392
 	Apu *c = &apu[d - devaudio0];
392
-	if(!audio_id) return 1;
393
-	if(!w) {
394
-		if(b0 == 0x2)
395
-			poke16(d->dat, 0x2, c->i);
396
-		else if(b0 == 0x4)
397
-			d->dat[0x4] = apu_get_vu(c);
398
-	} else if(b0 == 0xf) {
393
+	if(!audio_id) return d->dat[b0];
394
+	switch(b0) {
395
+	case 0x4: return apu_get_vu(c);
396
+	case 0x2: poke16(d->dat, 0x2, c->i); /* fall through */
397
+	default: return d->dat[b0];
398
+	}
399
+}
400
+
401
+static void
402
+audio_deo(Device *d, Uint8 b0)
403
+{
404
+	Apu *c = &apu[d - devaudio0];
405
+	if(!audio_id) return;
406
+	if(b0 == 0xf) {
399 407
 		SDL_LockAudioDevice(audio_id);
400 408
 		c->len = peek16(d->dat, 0xa);
401 409
 		c->addr = &d->mem[peek16(d->dat, 0xc)];
... ...
@@ -406,38 +414,39 @@ audio_talk(Device *d, Uint8 b0, Uint8 w)
406 414
 		SDL_UnlockAudioDevice(audio_id);
407 415
 		SDL_PauseAudioDevice(audio_id, 0);
408 416
 	}
409
-	return 1;
410 417
 }
411 418
 
412
-static int
413
-datetime_talk(Device *d, Uint8 b0, Uint8 w)
419
+static Uint8
420
+datetime_dei(Device *d, Uint8 b0)
414 421
 {
415 422
 	time_t seconds = time(NULL);
416 423
 	struct tm *t = localtime(&seconds);
417
-	t->tm_year += 1900;
418
-	poke16(d->dat, 0x0, t->tm_year);
419
-	d->dat[0x2] = t->tm_mon;
420
-	d->dat[0x3] = t->tm_mday;
421
-	d->dat[0x4] = t->tm_hour;
422
-	d->dat[0x5] = t->tm_min;
423
-	d->dat[0x6] = t->tm_sec;
424
-	d->dat[0x7] = t->tm_wday;
425
-	poke16(d->dat, 0x08, t->tm_yday);
426
-	d->dat[0xa] = t->tm_isdst;
427
-	(void)b0;
428
-	(void)w;
429
-	return 1;
424
+	switch(b0) {
425
+	case 0x0: return (t->tm_year + 1900) >> 8;
426
+	case 0x1: return (t->tm_year + 1900);
427
+	case 0x2: return t->tm_mon;
428
+	case 0x3: return t->tm_mday;
429
+	case 0x4: return t->tm_hour;
430
+	case 0x5: return t->tm_min;
431
+	case 0x6: return t->tm_sec;
432
+	case 0x7: return t->tm_wday;
433
+	case 0x8: return t->tm_yday >> 8;
434
+	case 0x9: return t->tm_yday;
435
+	case 0xa: return t->tm_isdst;
436
+	default: return d->dat[b0];
437
+	}
430 438
 }
431 439
 
432
-static int
433
-nil_talk(Device *d, Uint8 b0, Uint8 w)
440
+static Uint8
441
+nil_dei(Device *d, Uint8 b0)
434 442
 {
435
-	if(w && b0 == 0x1)
436
-		d->vector = peek16(d->dat, 0x0);
437
-	(void)d;
438
-	(void)b0;
439
-	(void)w;
440
-	return 1;
443
+	return d->dat[b0];
444
+}
445
+
446
+static void
447
+nil_deo(Device *d, Uint8 b0)
448
+{
449
+	if(b0 == 0x1) d->vector = peek16(d->dat, 0x0);
441 450
 }
442 451
 
443 452
 static const char *errors[] = {"underflow", "overflow", "division by zero"};
... ...
@@ -526,22 +535,22 @@ main(int argc, char **argv)
526 535
 	if(!uxn_boot(&u))
527 536
 		return error("Boot", "Failed to start uxn.");
528 537
 
529
-	/* system   */ devsystem = uxn_port(&u, 0x0, system_talk);
530
-	/* console  */ devconsole = uxn_port(&u, 0x1, console_talk);
531
-	/* screen   */ devscreen = uxn_port(&u, 0x2, screen_talk);
532
-	/* audio0   */ devaudio0 = uxn_port(&u, 0x3, audio_talk);
533
-	/* audio1   */ uxn_port(&u, 0x4, audio_talk);
534
-	/* audio2   */ uxn_port(&u, 0x5, audio_talk);
535
-	/* audio3   */ uxn_port(&u, 0x6, audio_talk);
536
-	/* unused   */ uxn_port(&u, 0x7, nil_talk);
537
-	/* control  */ devctrl = uxn_port(&u, 0x8, nil_talk);
538
-	/* mouse    */ devmouse = uxn_port(&u, 0x9, nil_talk);
539
-	/* file     */ uxn_port(&u, 0xa, file_talk);
540
-	/* datetime */ uxn_port(&u, 0xb, datetime_talk);
541
-	/* unused   */ uxn_port(&u, 0xc, nil_talk);
542
-	/* unused   */ uxn_port(&u, 0xd, nil_talk);
543
-	/* unused   */ uxn_port(&u, 0xe, nil_talk);
544
-	/* unused   */ uxn_port(&u, 0xf, nil_talk);
538
+	/* system   */ devsystem = uxn_port(&u, 0x0, system_dei, system_deo);
539
+	/* console  */ devconsole = uxn_port(&u, 0x1, nil_dei, console_deo);
540
+	/* screen   */ devscreen = uxn_port(&u, 0x2, screen_dei, screen_deo);
541
+	/* audio0   */ devaudio0 = uxn_port(&u, 0x3, audio_dei, audio_deo);
542
+	/* audio1   */ uxn_port(&u, 0x4, audio_dei, audio_deo);
543
+	/* audio2   */ uxn_port(&u, 0x5, audio_dei, audio_deo);
544
+	/* audio3   */ uxn_port(&u, 0x6, audio_dei, audio_deo);
545
+	/* unused   */ uxn_port(&u, 0x7, nil_dei, nil_deo);
546
+	/* control  */ devctrl = uxn_port(&u, 0x8, nil_dei, nil_deo);
547
+	/* mouse    */ devmouse = uxn_port(&u, 0x9, nil_dei, nil_deo);
548
+	/* file     */ uxn_port(&u, 0xa, nil_dei, file_deo);
549
+	/* datetime */ uxn_port(&u, 0xb, datetime_dei, nil_deo);
550
+	/* unused   */ uxn_port(&u, 0xc, nil_dei, nil_deo);
551
+	/* unused   */ uxn_port(&u, 0xd, nil_dei, nil_deo);
552
+	/* unused   */ uxn_port(&u, 0xe, nil_dei, nil_deo);
553
+	/* unused   */ uxn_port(&u, 0xf, nil_dei, nil_deo);
545 554
 
546 555
 	/* set default zoom */
547 556
 	if(SDL_GetCurrentDisplayMode(0, &DM) == 0)