commit a34ceda
neauoire
·
2022-03-27 02:58:48 +0000 UTC
parent 51542bc
Starting controller
8 files changed,
+266,
-192
M
build.sh
+3,
-3
1@@ -9,10 +9,10 @@ echo "Building.."
2 mkdir -p bin
3
4 # Build(debug)
5-gcc -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 src/uxn.c src/devices/system.c src/devices/screen.c src/uxn11.c -o bin/uxn11 -lX11
6+gcc -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 src/uxn.c src/devices/system.c src/devices/screen.c src/devices/controller.c src/uxn11.c -o bin/uxn11 -lX11
7
8 # Build(release)
9-# gcc src/uxn.c src/devices/system.c src/devices/screen.c src/uxn11.c -o bin/uxn11 -lX11
10+# gcc src/uxn.c src/devices/system.c src/devices/screen.c src/devices/controller.c src/uxn11.c -o bin/uxn11 -lX11
11
12 echo "Running.."
13-bin/uxn11 etc/screen.rom
14+bin/uxn11 etc/controller.rom
+0,
-0
+52,
-0
1@@ -0,0 +1,52 @@
2+#include "../uxn.h"
3+#include "controller.h"
4+
5+/*
6+Copyright (c) 2021 Devine Lu Linvega
7+Copyright (c) 2021 Andrew Alderwick
8+
9+Permission to use, copy, modify, and distribute this software for any
10+purpose with or without fee is hereby granted, provided that the above
11+copyright notice and this permission notice appear in all copies.
12+
13+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14+WITH REGARD TO THIS SOFTWARE.
15+*/
16+
17+void
18+controller_down(Device *d, Uint8 mask)
19+{
20+ if(mask) {
21+ d->dat[2] |= mask;
22+ uxn_eval(d->u, GETVECTOR(d));
23+ }
24+}
25+
26+void
27+controller_up(Device *d, Uint8 mask)
28+{
29+ if(mask) {
30+ d->dat[2] &= (~mask);
31+ uxn_eval(d->u, GETVECTOR(d));
32+ }
33+}
34+
35+void
36+controller_key(Device *d, Uint8 key)
37+{
38+ if(key) {
39+ d->dat[3] = key;
40+ uxn_eval(d->u, GETVECTOR(d));
41+ d->dat[3] = 0x00;
42+ }
43+}
44+
45+void
46+controller_special(Device *d, Uint8 key)
47+{
48+ if(key) {
49+ d->dat[4] = key;
50+ uxn_eval(d->u, GETVECTOR(d));
51+ d->dat[4] = 0x00;
52+ }
53+}
+16,
-0
1@@ -0,0 +1,16 @@
2+/*
3+Copyright (c) 2021 Devine Lu Linvega
4+Copyright (c) 2021 Andrew Alderwick
5+
6+Permission to use, copy, modify, and distribute this software for any
7+purpose with or without fee is hereby granted, provided that the above
8+copyright notice and this permission notice appear in all copies.
9+
10+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11+WITH REGARD TO THIS SOFTWARE.
12+*/
13+
14+void controller_down(Device *d, Uint8 mask);
15+void controller_up(Device *d, Uint8 mask);
16+void controller_key(Device *d, Uint8 key);
17+void controller_special(Device *d, Uint8 key);
+0,
-150
1@@ -1,150 +0,0 @@
2-#include "ppu.h"
3-
4-/*
5-Copyright (c) 2021 Devine Lu Linvega
6-Copyright (c) 2021 Andrew Alderwick
7-
8-Permission to use, copy, modify, and distribute this software for any
9-purpose with or without fee is hereby granted, provided that the above
10-copyright notice and this permission notice appear in all copies.
11-
12-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13-WITH REGARD TO THIS SOFTWARE.
14-*/
15-
16-static Uint8 blending[5][16] = {
17- {0, 0, 0, 0, 1, 0, 1, 1, 2, 2, 0, 2, 3, 3, 3, 0},
18- {0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3},
19- {1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1, 1, 2, 3, 1},
20- {2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2},
21- {1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0}};
22-
23-static Uint8 font[][8] = {
24- {0x00, 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c},
25- {0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10},
26- {0x00, 0x7c, 0x82, 0x02, 0x7c, 0x80, 0x80, 0xfe},
27- {0x00, 0x7c, 0x82, 0x02, 0x1c, 0x02, 0x82, 0x7c},
28- {0x00, 0x0c, 0x14, 0x24, 0x44, 0x84, 0xfe, 0x04},
29- {0x00, 0xfe, 0x80, 0x80, 0x7c, 0x02, 0x82, 0x7c},
30- {0x00, 0x7c, 0x82, 0x80, 0xfc, 0x82, 0x82, 0x7c},
31- {0x00, 0x7c, 0x82, 0x02, 0x1e, 0x02, 0x02, 0x02},
32- {0x00, 0x7c, 0x82, 0x82, 0x7c, 0x82, 0x82, 0x7c},
33- {0x00, 0x7c, 0x82, 0x82, 0x7e, 0x02, 0x82, 0x7c},
34- {0x00, 0x7c, 0x82, 0x02, 0x7e, 0x82, 0x82, 0x7e},
35- {0x00, 0xfc, 0x82, 0x82, 0xfc, 0x82, 0x82, 0xfc},
36- {0x00, 0x7c, 0x82, 0x80, 0x80, 0x80, 0x82, 0x7c},
37- {0x00, 0xfc, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfc},
38- {0x00, 0x7c, 0x82, 0x80, 0xf0, 0x80, 0x82, 0x7c},
39- {0x00, 0x7c, 0x82, 0x80, 0xf0, 0x80, 0x80, 0x80}};
40-
41-void
42-ppu_palette(Ppu *p, Uint8 *addr)
43-{
44- int i, shift;
45- for(i = 0, shift = 4; i < 4; ++i, shift ^= 4) {
46- Uint8
47- r = (addr[0 + i / 2] >> shift) & 0x0f,
48- g = (addr[2 + i / 2] >> shift) & 0x0f,
49- b = (addr[4 + i / 2] >> shift) & 0x0f;
50- p->palette[i] = 0x0f000000 | r << 16 | g << 8 | b;
51- p->palette[i] |= p->palette[i] << 4;
52- }
53- p->fg.changed = p->bg.changed = 1;
54-}
55-
56-void
57-ppu_resize(Ppu *p, Uint16 width, Uint16 height)
58-{
59- Uint8
60- *bg = realloc(p->bg.pixels, width * height),
61- *fg = realloc(p->fg.pixels, width * height);
62- if(bg) p->bg.pixels = bg;
63- if(fg) p->fg.pixels = fg;
64- if(bg && fg) {
65- p->width = width;
66- p->height = height;
67- ppu_clear(p, &p->bg);
68- ppu_clear(p, &p->fg);
69- }
70-}
71-
72-void
73-ppu_clear(Ppu *p, Layer *layer)
74-{
75- Uint32 i, size = p->width * p->height;
76- for(i = 0; i < size; ++i)
77- layer->pixels[i] = 0x00;
78- layer->changed = 1;
79-}
80-
81-#pragma weak ppu_redraw
82-void
83-ppu_redraw(Ppu *p, Uint32 *screen)
84-{
85- Uint32 i, size = p->width * p->height, palette[16];
86- for(i = 0; i < 16; ++i)
87- palette[i] = p->palette[(i >> 2) ? (i >> 2) : (i & 3)];
88- for(i = 0; i < size; ++i)
89- screen[i] = palette[p->fg.pixels[i] << 2 | p->bg.pixels[i]];
90- p->fg.changed = p->bg.changed = 0;
91-}
92-
93-void
94-ppu_write(Ppu *p, Layer *layer, Uint16 x, Uint16 y, Uint8 color)
95-{
96- if(x < p->width && y < p->height) {
97- Uint32 i = x + y * p->width;
98- Uint8 prev = layer->pixels[i];
99- if(color != prev) {
100- layer->pixels[i] = color;
101- layer->changed = 1;
102- }
103- }
104-}
105-
106-void
107-ppu_blit(Ppu *p, Layer *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy, Uint8 twobpp)
108-{
109- int v, h, opaque = blending[4][color];
110- for(v = 0; v < 8; ++v) {
111- Uint16 c = sprite[v] | (twobpp ? sprite[v + 8] : 0) << 8;
112- for(h = 7; h >= 0; --h, c >>= 1) {
113- Uint8 ch = (c & 1) | ((c >> 7) & 2);
114- if(opaque || ch)
115- ppu_write(p,
116- layer,
117- x + (flipx ? 7 - h : h),
118- y + (flipy ? 7 - v : v),
119- blending[ch][color]);
120- }
121- }
122-}
123-
124-void
125-ppu_debug(Ppu *p, Uint8 *stack, Uint8 wptr, Uint8 rptr, Uint8 *memory)
126-{
127- Uint8 i, x, y, b;
128- for(i = 0; i < 0x20; ++i) {
129- x = ((i % 8) * 3 + 1) * 8, y = (i / 8 + 1) * 8, b = stack[i];
130- /* working stack */
131- ppu_blit(p, &p->fg, x, y, font[(b >> 4) & 0xf], 1 + (wptr == i) * 0x7, 0, 0, 0);
132- ppu_blit(p, &p->fg, x + 8, y, font[b & 0xf], 1 + (wptr == i) * 0x7, 0, 0, 0);
133- y = 0x28 + (i / 8 + 1) * 8;
134- b = memory[i];
135- /* return stack */
136- ppu_blit(p, &p->fg, x, y, font[(b >> 4) & 0xf], 3, 0, 0, 0);
137- ppu_blit(p, &p->fg, x + 8, y, font[b & 0xf], 3, 0, 0, 0);
138- }
139- /* return pointer */
140- ppu_blit(p, &p->fg, 0x8, y + 0x10, font[(rptr >> 4) & 0xf], 0x2, 0, 0, 0);
141- ppu_blit(p, &p->fg, 0x10, y + 0x10, font[rptr & 0xf], 0x2, 0, 0, 0);
142- /* guides */
143- for(x = 0; x < 0x10; ++x) {
144- ppu_write(p, &p->fg, x, p->height / 2, 2);
145- ppu_write(p, &p->fg, p->width - x, p->height / 2, 2);
146- ppu_write(p, &p->fg, p->width / 2, p->height - x, 2);
147- ppu_write(p, &p->fg, p->width / 2, x, 2);
148- ppu_write(p, &p->fg, p->width / 2 - 0x10 / 2 + x, p->height / 2, 2);
149- ppu_write(p, &p->fg, p->width / 2, p->height / 2 - 0x10 / 2 + x, 2);
150- }
151-}
+0,
-37
1@@ -1,37 +0,0 @@
2-#include <stdlib.h>
3-
4-/*
5-Copyright (c) 2021 Devine Lu Linvega
6-Copyright (c) 2021 Andrew Alderwick
7-
8-Permission to use, copy, modify, and distribute this software for any
9-purpose with or without fee is hereby granted, provided that the above
10-copyright notice and this permission notice appear in all copies.
11-
12-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13-WITH REGARD TO THIS SOFTWARE.
14-*/
15-
16-typedef unsigned char Uint8;
17-typedef unsigned short Uint16;
18-typedef unsigned int Uint32;
19-
20-typedef struct Layer {
21- Uint8 *pixels;
22- Uint8 changed;
23-} Layer;
24-
25-typedef struct Ppu {
26- Uint32 palette[4];
27- Uint16 width, height;
28- Layer fg, bg;
29-} Ppu;
30-
31-void ppu_palette(Ppu *p, Uint8 *addr);
32-void ppu_resize(Ppu *p, Uint16 width, Uint16 height);
33-void ppu_clear(Ppu *p, Layer *layer);
34-void ppu_redraw(Ppu *p, Uint32 *screen);
35-
36-void ppu_write(Ppu *p, Layer *layer, Uint16 x, Uint16 y, Uint8 color);
37-void ppu_blit(Ppu *p, Layer *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy, Uint8 twobpp);
38-void ppu_debug(Ppu *p, Uint8 *stack, Uint8 wptr, Uint8 rptr, Uint8 *memory);
+47,
-2
1@@ -12,6 +12,9 @@
2 #include "uxn.h"
3 #include "devices/system.h"
4 #include "devices/screen.h"
5+#include "devices/controller.h"
6+
7+static Device *devctrl;
8
9 static int
10 error(char *msg, const char *err)
11@@ -64,6 +67,18 @@ load(Uxn *u, char *filepath)
12 return 1;
13 }
14
15+/* /usr/include/X11/keysymdef.h */
16+
17+#define XK_Left 0xff51
18+#define XK_Up 0xff52
19+#define XK_Right 0xff53
20+#define XK_Down 0xff54
21+
22+#define XK_Home 0xff50
23+#define XK_Shift 0xffe1
24+#define XK_Control 0xffe3
25+#define XK_Alt 0xffe9
26+
27 void
28 processEvent(Display *display, Window window, XImage *ximage, int width, int height)
29 {
30@@ -73,6 +88,28 @@ processEvent(Display *display, Window window, XImage *ximage, int width, int hei
31 case Expose:
32 XPutImage(display, window, DefaultGC(display, 0), ximage, 0, 0, 0, 0, width, height);
33 break;
34+ case KeyPress: {
35+ XKeyPressedEvent *e = (XKeyPressedEvent *)&ev;
36+ if(e->keycode == XKeysymToKeycode(display, XK_Up)) controller_down(devctrl, 0x10);
37+ if(e->keycode == XKeysymToKeycode(display, XK_Down)) controller_down(devctrl, 0x20);
38+ if(e->keycode == XKeysymToKeycode(display, XK_Left)) controller_down(devctrl, 0x40);
39+ if(e->keycode == XKeysymToKeycode(display, XK_Right)) controller_down(devctrl, 0x80);
40+ if(e->keycode == XKeysymToKeycode(display, XK_Control)) controller_down(devctrl, 0x01);
41+ if(e->keycode == XKeysymToKeycode(display, XK_Alt)) controller_down(devctrl, 0x02);
42+ if(e->keycode == XKeysymToKeycode(display, XK_Shift)) controller_down(devctrl, 0x04);
43+ if(e->keycode == XKeysymToKeycode(display, XK_Home)) controller_down(devctrl, 0x08);
44+ } break;
45+ case KeyRelease: {
46+ XKeyPressedEvent *e = (XKeyPressedEvent *)&ev;
47+ if(e->keycode == XKeysymToKeycode(display, XK_Up)) controller_up(devctrl, 0x10);
48+ if(e->keycode == XKeysymToKeycode(display, XK_Down)) controller_up(devctrl, 0x20);
49+ if(e->keycode == XKeysymToKeycode(display, XK_Left)) controller_up(devctrl, 0x40);
50+ if(e->keycode == XKeysymToKeycode(display, XK_Right)) controller_up(devctrl, 0x80);
51+ if(e->keycode == XKeysymToKeycode(display, XK_Control)) controller_up(devctrl, 0x01);
52+ if(e->keycode == XKeysymToKeycode(display, XK_Alt)) controller_up(devctrl, 0x02);
53+ if(e->keycode == XKeysymToKeycode(display, XK_Shift)) controller_up(devctrl, 0x04);
54+ if(e->keycode == XKeysymToKeycode(display, XK_Home)) controller_up(devctrl, 0x08);
55+ } break;
56 case ButtonPress:
57 exit(0);
58 }
59@@ -91,7 +128,7 @@ start(Uxn *u)
60 /* empty */ uxn_port(u, 0x5, nil_dei, nil_deo);
61 /* empty */ uxn_port(u, 0x6, nil_dei, nil_deo);
62 /* empty */ uxn_port(u, 0x7, nil_dei, nil_deo);
63- /* empty */ uxn_port(u, 0x8, nil_dei, nil_deo);
64+ /* control */ devctrl = uxn_port(u, 0x8, nil_dei, nil_deo);
65 /* empty */ uxn_port(u, 0x9, nil_dei, nil_deo);
66 /* file */ uxn_port(u, 0xa, nil_dei, nil_deo);
67 /* datetime */ uxn_port(u, 0xb, nil_dei, nil_deo);
68@@ -102,6 +139,11 @@ start(Uxn *u)
69 return 1;
70 }
71
72+void
73+redraw(void)
74+{
75+}
76+
77 int
78 main(int argc, char **argv)
79 {
80@@ -132,10 +174,13 @@ main(int argc, char **argv)
81
82 ximage = XCreateImage(display, visual, DefaultDepth(display, DefaultScreen(display)), ZPixmap, 0, (char *)uxn_screen.pixels, uxn_screen.width, uxn_screen.height, 32, 0);
83
84- XSelectInput(display, window, ButtonPressMask | ExposureMask);
85+ XSelectInput(display, window, ButtonPressMask | ExposureMask | KeyPressMask | KeyReleaseMask);
86 XMapWindow(display, window);
87 while(1) {
88 processEvent(display, window, ximage, uxn_screen.width, uxn_screen.height);
89+
90+ if(uxn_screen.fg.changed || uxn_screen.bg.changed)
91+ redraw();
92 }
93 return 0;
94 }
+148,
-0
1@@ -0,0 +1,148 @@
2+#include <stdio.h>
3+#include <stdlib.h>
4+
5+#include "uxn.h"
6+#include "devices/system.h"
7+#include "devices/file.h"
8+#include "devices/datetime.h"
9+
10+/*
11+Copyright (c) 2021 Devine Lu Linvega
12+
13+Permission to use, copy, modify, and distribute this software for any
14+purpose with or without fee is hereby granted, provided that the above
15+copyright notice and this permission notice appear in all copies.
16+
17+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
18+WITH REGARD TO THIS SOFTWARE.
19+*/
20+
21+static Device *devfile0;
22+
23+static int
24+error(char *msg, const char *err)
25+{
26+ fprintf(stderr, "Error %s: %s\n", msg, err);
27+ return 0;
28+}
29+
30+void
31+system_deo_special(Device *d, Uint8 port)
32+{
33+ (void)d;
34+ (void)port;
35+}
36+
37+static void
38+console_deo(Device *d, Uint8 port)
39+{
40+ FILE *fd = port == 0x8 ? stdout : port == 0x9 ? stderr
41+ : 0;
42+ if(fd) {
43+ fputc(d->dat[port], fd);
44+ fflush(fd);
45+ }
46+}
47+
48+static void
49+file_deo(Device *d, Uint8 port)
50+{
51+ file_i_deo(d - devfile0, d, port);
52+}
53+
54+static Uint8
55+file_dei(Device *d, Uint8 port)
56+{
57+ return file_i_dei(d - devfile0, d, port);
58+}
59+
60+static Uint8
61+nil_dei(Device *d, Uint8 port)
62+{
63+ return d->dat[port];
64+}
65+
66+static void
67+nil_deo(Device *d, Uint8 port)
68+{
69+ (void)d;
70+ (void)port;
71+}
72+
73+static int
74+console_input(Uxn *u, char c)
75+{
76+ Device *d = &u->dev[1];
77+ d->dat[0x2] = c;
78+ return uxn_eval(u, GETVECTOR(d));
79+}
80+
81+static void
82+run(Uxn *u)
83+{
84+ Device *d = &u->dev[0];
85+ while(!d->dat[0xf]) {
86+ int c = fgetc(stdin);
87+ if(c != EOF)
88+ console_input(u, (Uint8)c);
89+ }
90+}
91+
92+static int
93+load(Uxn *u, char *filepath)
94+{
95+ FILE *f;
96+ int r;
97+ if(!(f = fopen(filepath, "rb"))) return 0;
98+ r = fread(u->ram + PAGE_PROGRAM, 1, 0x10000 - PAGE_PROGRAM, f);
99+ fclose(f);
100+ if(r < 1) return 0;
101+ fprintf(stderr, "Loaded %s\n", filepath);
102+ return 1;
103+}
104+
105+static int
106+start(Uxn *u)
107+{
108+ if(!uxn_boot(u, (Uint8 *)calloc(0x10000, sizeof(Uint8))))
109+ return error("Boot", "Failed");
110+ /* system */ uxn_port(u, 0x0, system_dei, system_deo);
111+ /* console */ uxn_port(u, 0x1, nil_dei, console_deo);
112+ /* empty */ uxn_port(u, 0x2, nil_dei, nil_deo);
113+ /* empty */ uxn_port(u, 0x3, nil_dei, nil_deo);
114+ /* empty */ uxn_port(u, 0x4, nil_dei, nil_deo);
115+ /* empty */ uxn_port(u, 0x5, nil_dei, nil_deo);
116+ /* empty */ uxn_port(u, 0x6, nil_dei, nil_deo);
117+ /* empty */ uxn_port(u, 0x7, nil_dei, nil_deo);
118+ /* empty */ uxn_port(u, 0x8, nil_dei, nil_deo);
119+ /* empty */ uxn_port(u, 0x9, nil_dei, nil_deo);
120+ /* file0 */ devfile0 = uxn_port(u, 0xa, file_dei, file_deo);
121+ /* file1 */ uxn_port(u, 0xb, file_dei, file_deo);
122+ /* datetime */ uxn_port(u, 0xc, datetime_dei, nil_deo);
123+ /* empty */ uxn_port(u, 0xd, nil_dei, nil_deo);
124+ /* empty */ uxn_port(u, 0xe, nil_dei, nil_deo);
125+ /* empty */ uxn_port(u, 0xf, nil_dei, nil_deo);
126+ return 1;
127+}
128+
129+int
130+main(int argc, char **argv)
131+{
132+ Uxn u;
133+ int i;
134+ if(argc < 2)
135+ return error("Usage", "uxncli game.rom args");
136+ if(!start(&u))
137+ return error("Start", "Failed");
138+ if(!load(&u, argv[1]))
139+ return error("Load", "Failed");
140+ if(!uxn_eval(&u, PAGE_PROGRAM))
141+ return error("Init", "Failed");
142+ for(i = 2; i < argc; i++) {
143+ char *p = argv[i];
144+ while(*p) console_input(&u, *p++);
145+ console_input(&u, '\n');
146+ }
147+ run(&u);
148+ return 0;
149+}