diff options
author | Bad Diode <bd@badd10de.dev> | 2021-05-18 18:18:18 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-05-18 18:18:18 +0200 |
commit | ec5b9644db2ff26cc6f0cc3d84854b714a25eff9 (patch) | |
tree | e6806bbe0bc84a20d11f620c0425ab58aba12b42 /src | |
parent | 0c7265cf0de9d4ec95d28c5e103c00a63f4a1697 (diff) | |
download | uxngba-ec5b9644db2ff26cc6f0cc3d84854b714a25eff9.tar.gz uxngba-ec5b9644db2ff26cc6f0cc3d84854b714a25eff9.zip |
Draw directly to the FRAMEBUFFER
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 118 | ||||
-rw-r--r-- | src/uxn/devices/ppu.c | 21 | ||||
-rw-r--r-- | src/uxn/uxn.c | 46 |
3 files changed, 63 insertions, 122 deletions
@@ -21,14 +21,14 @@ static Device *devscreen; | |||
21 | 21 | ||
22 | void | 22 | void |
23 | nil_talk(Device *d, Uint8 b0, Uint8 w) { | 23 | nil_talk(Device *d, Uint8 b0, Uint8 w) { |
24 | (void)d; | 24 | (void)d; |
25 | (void)b0; | 25 | (void)b0; |
26 | (void)w; | 26 | (void)w; |
27 | } | 27 | } |
28 | 28 | ||
29 | void | 29 | void |
30 | console_talk(Device *d, u8 b0, u8 w) { | 30 | console_talk(Device *d, u8 b0, u8 w) { |
31 | if(!w) { | 31 | if(!w) { |
32 | return; | 32 | return; |
33 | } | 33 | } |
34 | switch(b0) { | 34 | switch(b0) { |
@@ -42,77 +42,70 @@ console_talk(Device *d, u8 b0, u8 w) { | |||
42 | void | 42 | void |
43 | system_talk(Device *d, Uint8 b0, Uint8 w) | 43 | system_talk(Device *d, Uint8 b0, Uint8 w) |
44 | { | 44 | { |
45 | if(!w) { | 45 | if(!w) { |
46 | d->dat[0x2] = d->u->wst.ptr; | 46 | d->dat[0x2] = d->u->wst.ptr; |
47 | d->dat[0x3] = d->u->rst.ptr; | 47 | d->dat[0x3] = d->u->rst.ptr; |
48 | } else { | 48 | } else { |
49 | putcolors(&ppu, &d->dat[0x8]); | 49 | putcolors(&ppu, &d->dat[0x8]); |
50 | reqdraw = 1; | 50 | reqdraw = 1; |
51 | } | 51 | } |
52 | (void)b0; | 52 | (void)b0; |
53 | } | 53 | } |
54 | 54 | ||
55 | void | 55 | void |
56 | screen_talk(Device *d, Uint8 b0, Uint8 w) { | 56 | screen_talk(Device *d, Uint8 b0, Uint8 w) { |
57 | if(w && b0 == 0xe) { | 57 | if(w && b0 == 0xe) { |
58 | Uint16 x = mempeek16(d->dat, 0x8); | 58 | Uint16 x = mempeek16(d->dat, 0x8); |
59 | Uint16 y = mempeek16(d->dat, 0xa); | 59 | Uint16 y = mempeek16(d->dat, 0xa); |
60 | Uint8 *addr = &d->mem[mempeek16(d->dat, 0xc)]; | 60 | Uint8 *addr = &d->mem[mempeek16(d->dat, 0xc)]; |
61 | Uint8 *layer = d->dat[0xe] >> 4 & 0x1 ? ppu.fg : ppu.bg; | 61 | Uint8 *layer = d->dat[0xe] >> 4 & 0x1 ? ppu.fg : ppu.bg; |
62 | Uint8 mode = d->dat[0xe] >> 5; | 62 | Uint8 mode = d->dat[0xe] >> 5; |
63 | if(!mode) { | 63 | if(!mode) { |
64 | putpixel(&ppu, layer, x, y, d->dat[0xe] & 0x3); | 64 | putpixel(&ppu, layer, x, y, d->dat[0xe] & 0x3); |
65 | } else if(mode-- & 0x1) { | 65 | } else if(mode-- & 0x1) { |
66 | puticn(&ppu, layer, x, y, addr, d->dat[0xe] & 0xf, mode & 0x2, mode & 0x4); | 66 | puticn(&ppu, layer, x, y, addr, d->dat[0xe] & 0xf, mode & 0x2, mode & 0x4); |
67 | } else { | 67 | } else { |
68 | putchr(&ppu, layer, x, y, addr, d->dat[0xe] & 0xf, mode & 0x2, mode & 0x4); | 68 | putchr(&ppu, layer, x, y, addr, d->dat[0xe] & 0xf, mode & 0x2, mode & 0x4); |
69 | } | 69 | } |
70 | reqdraw = 1; | 70 | reqdraw = 1; |
71 | } | 71 | } |
72 | } | 72 | } |
73 | 73 | ||
74 | void | 74 | void |
75 | redraw(Uint16 *dst, Uxn *u) { | 75 | redraw(Uint16 *dst, Uxn *u) { |
76 | // TODO: The screen will flicker but using Mode4 for double buffering would | 76 | // TODO: The screen will flicker but using Mode4 for double buffering would |
77 | // be way too slow. | 77 | // be way too slow. |
78 | drawppu(&ppu); | 78 | drawppu(&ppu); |
79 | clear_screen_m3(); | 79 | reqdraw = 0; |
80 | // Copy ppu data to framebuffer. | ||
81 | for (size_t j = 0; j < ppu.height; ++j) { | ||
82 | for (size_t i = 0; i < ppu.width; ++i) { | ||
83 | FRAMEBUFFER[j][i] = ppu.output[i + j * ppu.width]; | ||
84 | } | ||
85 | } | ||
86 | reqdraw = 0; | ||
87 | } | 80 | } |
88 | 81 | ||
89 | void | 82 | void |
90 | init_uxn(Uxn *u) { | 83 | init_uxn(Uxn *u) { |
91 | // Initialize PPU. | 84 | // Initialize PPU. |
92 | initppu(&ppu, 30, 20, 0); | 85 | initppu(&ppu, 30, 20, 0); |
93 | 86 | ||
94 | // Copy rom to VM. | 87 | // Copy rom to VM. |
95 | memcpy(u->ram.dat + PAGE_PROGRAM, uxn_rom, sizeof(uxn_rom)); | 88 | memcpy(u->ram.dat + PAGE_PROGRAM, uxn_rom, sizeof(uxn_rom)); |
96 | 89 | ||
97 | // Prepare devices. | 90 | // Prepare devices. |
98 | portuxn(u, 0x0, "system", system_talk); | 91 | portuxn(u, 0x0, "system", system_talk); |
99 | portuxn(u, 0x1, "console", console_talk); | 92 | portuxn(u, 0x1, "console", console_talk); |
100 | devscreen = portuxn(u, 0x2, "screen", screen_talk); | 93 | devscreen = portuxn(u, 0x2, "screen", screen_talk); |
101 | portuxn(u, 0x3, "---", nil_talk); | 94 | portuxn(u, 0x3, "---", nil_talk); |
102 | portuxn(u, 0x4, "---", nil_talk); | 95 | portuxn(u, 0x4, "---", nil_talk); |
103 | portuxn(u, 0x5, "---", nil_talk); | 96 | portuxn(u, 0x5, "---", nil_talk); |
104 | portuxn(u, 0x6, "---", nil_talk); | 97 | portuxn(u, 0x6, "---", nil_talk); |
105 | portuxn(u, 0x7, "---", nil_talk); | 98 | portuxn(u, 0x7, "---", nil_talk); |
106 | portuxn(u, 0x8, "---", nil_talk); | 99 | portuxn(u, 0x8, "---", nil_talk); |
107 | portuxn(u, 0x9, "---", nil_talk); | 100 | portuxn(u, 0x9, "---", nil_talk); |
108 | portuxn(u, 0xa, "---", nil_talk); | 101 | portuxn(u, 0xa, "---", nil_talk); |
109 | portuxn(u, 0xb, "---", nil_talk); | 102 | portuxn(u, 0xb, "---", nil_talk); |
110 | portuxn(u, 0xc, "---", nil_talk); | 103 | portuxn(u, 0xc, "---", nil_talk); |
111 | portuxn(u, 0xd, "---", nil_talk); | 104 | portuxn(u, 0xd, "---", nil_talk); |
112 | portuxn(u, 0xe, "---", nil_talk); | 105 | portuxn(u, 0xe, "---", nil_talk); |
113 | portuxn(u, 0xf, "---", nil_talk); | 106 | portuxn(u, 0xf, "---", nil_talk); |
114 | mempoke16(devscreen->dat, 2, ppu.hor * 8); | 107 | mempoke16(devscreen->dat, 2, ppu.hor * 8); |
115 | mempoke16(devscreen->dat, 4, ppu.ver * 8); | 108 | mempoke16(devscreen->dat, 4, ppu.ver * 8); |
116 | } | 109 | } |
117 | 110 | ||
118 | int main(void) { | 111 | int main(void) { |
@@ -126,7 +119,7 @@ int main(void) { | |||
126 | .data = small_font, | 119 | .data = small_font, |
127 | .char_width = 4, | 120 | .char_width = 4, |
128 | .char_height = 8, | 121 | .char_height = 8, |
129 | .color = COLOR_BLUE, | 122 | .color = COLOR_WHITE, |
130 | .char_map = small_font_map, | 123 | .char_map = small_font_map, |
131 | }); | 124 | }); |
132 | 125 | ||
@@ -137,17 +130,24 @@ int main(void) { | |||
137 | // Initialize VM. | 130 | // Initialize VM. |
138 | Uxn u = {0}; | 131 | Uxn u = {0}; |
139 | init_uxn(&u); | 132 | init_uxn(&u); |
140 | evaluxn(&u, 0x0100); | 133 | evaluxn(&u, 0x0100); |
141 | 134 | ||
142 | // Main loop. | 135 | // Main loop. |
143 | int frame_counter = 0; | 136 | int frame_counter = 0; |
144 | while(true) { | 137 | while(true) { |
145 | bios_vblank_wait(); | 138 | bios_vblank_wait(); |
146 | poll_keys(); | 139 | poll_keys(); |
147 | evaluxn(&u, mempeek16(devscreen->dat, 0)); | 140 | profile_start(); |
148 | if(reqdraw) { | 141 | evaluxn(&u, mempeek16(devscreen->dat, 0)); |
149 | redraw(ppu.output, &u); | 142 | int eval_cycles = profile_stop(); |
143 | profile_start(); | ||
144 | if(reqdraw) { | ||
145 | redraw(ppu.output, &u); | ||
150 | } | 146 | } |
147 | int redraw_cycles = profile_stop(); | ||
148 | txt_position(0, 0); | ||
149 | txt_printf("EVAL: %d\n", eval_cycles); | ||
150 | txt_printf("REDRAW: %d\n", redraw_cycles); | ||
151 | frame_counter++; | 151 | frame_counter++; |
152 | }; | 152 | }; |
153 | 153 | ||
diff --git a/src/uxn/devices/ppu.c b/src/uxn/devices/ppu.c index b977f97..06d84bf 100644 --- a/src/uxn/devices/ppu.c +++ b/src/uxn/devices/ppu.c | |||
@@ -121,26 +121,7 @@ void | |||
121 | drawpixel(Ppu *p, Uint16 x, Uint16 y, Uint8 color) | 121 | drawpixel(Ppu *p, Uint16 x, Uint16 y, Uint8 color) |
122 | { | 122 | { |
123 | if(x >= p->pad && x <= p->width - p->pad - 1 && y >= p->pad && y <= p->height - p->pad - 1) | 123 | if(x >= p->pad && x <= p->width - p->pad - 1 && y >= p->pad && y <= p->height - p->pad - 1) |
124 | p->output[y * p->width + x] = p->colors[color]; | 124 | FRAMEBUFFER[y][x] = p->colors[color]; |
125 | } | ||
126 | |||
127 | void | ||
128 | drawdebugger(Ppu *p, Uint8 *stack, Uint8 ptr) | ||
129 | { | ||
130 | Uint8 i, x, y, b; | ||
131 | for(i = 0; i < 0x20; ++i) { /* memory */ | ||
132 | x = ((i % 8) * 3 + 1) * 8, y = (i / 8 + 1) * 8, b = stack[i]; | ||
133 | puticn(p, p->bg, x, y, font[(b >> 4) & 0xf], 1 + (ptr == i) * 0x7, 0, 0); | ||
134 | puticn(p, p->bg, x + 8, y, font[b & 0xf], 1 + (ptr == i) * 0x7, 0, 0); | ||
135 | } | ||
136 | for(x = 0; x < 0x20; ++x) { | ||
137 | drawpixel(p, x, p->height / 2, 2); | ||
138 | drawpixel(p, p->width - x, p->height / 2, 2); | ||
139 | drawpixel(p, p->width / 2, p->height - x, 2); | ||
140 | drawpixel(p, p->width / 2, x, 2); | ||
141 | drawpixel(p, p->width / 2 - 16 + x, p->height / 2, 2); | ||
142 | drawpixel(p, p->width / 2, p->height / 2 - 16 + x, 2); | ||
143 | } | ||
144 | } | 125 | } |
145 | 126 | ||
146 | void | 127 | void |
diff --git a/src/uxn/uxn.c b/src/uxn/uxn.c index 796a980..08b3b9b 100644 --- a/src/uxn/uxn.c +++ b/src/uxn/uxn.c | |||
@@ -116,14 +116,6 @@ void (*ops[])(Uxn *u) = { | |||
116 | 116 | ||
117 | #pragma mark - Core | 117 | #pragma mark - Core |
118 | 118 | ||
119 | int | ||
120 | haltuxn(Uxn *u, char *name, int id) | ||
121 | { | ||
122 | txt_printf("Halted: %s#%04x, at 0x%04x\n", name, id, u->ram.ptr); | ||
123 | u->ram.ptr = 0; | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | void | 119 | void |
128 | opcuxn(Uxn *u, Uint8 instr) | 120 | opcuxn(Uxn *u, Uint8 instr) |
129 | { | 121 | { |
@@ -140,46 +132,14 @@ opcuxn(Uxn *u, Uint8 instr) | |||
140 | } | 132 | } |
141 | 133 | ||
142 | int | 134 | int |
143 | stepuxn(Uxn *u, Uint8 instr) | ||
144 | { | ||
145 | opcuxn(u, instr); | ||
146 | if(u->wst.error) | ||
147 | return haltuxn(u, u->wst.error == 1 ? "Working-stack underflow" : "Working-stack overflow", instr); | ||
148 | if(u->rst.error) | ||
149 | return haltuxn(u, u->rst.error == 1 ? "Return-stack underflow" : "Return-stack overflow", instr); | ||
150 | return 1; | ||
151 | } | ||
152 | |||
153 | int | ||
154 | evaluxn(Uxn *u, Uint16 vec) | 135 | evaluxn(Uxn *u, Uint16 vec) |
155 | { | 136 | { |
156 | u->ram.ptr = vec; | 137 | u->ram.ptr = vec; |
157 | u->wst.error = 0; | 138 | u->wst.error = 0; |
158 | u->rst.error = 0; | 139 | u->rst.error = 0; |
159 | while(u->ram.ptr) | 140 | while(u->ram.ptr) { |
160 | if(!stepuxn(u, u->ram.dat[u->ram.ptr++])) | 141 | opcuxn(u, u->ram.dat[u->ram.ptr++]); |
161 | return 0; | 142 | } |
162 | return 1; | ||
163 | } | ||
164 | |||
165 | int | ||
166 | bootuxn(Uxn *u) | ||
167 | { | ||
168 | size_t i; | ||
169 | char *cptr = (char *)u; | ||
170 | for(i = 0; i < sizeof(*u); i++) | ||
171 | cptr[i] = 0; | ||
172 | return 1; | ||
173 | } | ||
174 | |||
175 | int | ||
176 | loaduxn(Uxn *u, char *filepath) | ||
177 | { | ||
178 | FILE *f; | ||
179 | if(!(f = fopen(filepath, "rb"))) | ||
180 | return haltuxn(u, "Missing input rom.", 0); | ||
181 | fread(u->ram.dat + PAGE_PROGRAM, sizeof(u->ram.dat) - PAGE_PROGRAM, 1, f); | ||
182 | txt_printf("Uxn loaded[%s].\n", filepath); | ||
183 | return 1; | 143 | return 1; |
184 | } | 144 | } |
185 | 145 | ||