... | ... |
@@ -19,48 +19,49 @@ static Uint8 blending[5][16] = { |
19 | 19 |
{2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2, 2, 3, 1, 2}, |
20 | 20 |
{1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0}}; |
21 | 21 |
|
22 |
-void |
|
23 |
-ppu_frame(Ppu *p) |
|
24 |
-{ |
|
25 |
- p->reqdraw = 0; |
|
26 |
- p->i0 = p->width / PPW + p->height * p->stride; |
|
27 |
- p->i1 = 0; |
|
28 |
-} |
|
29 |
- |
|
30 | 22 |
static void |
31 | 23 |
ppu_clear(Ppu *p) |
32 | 24 |
{ |
33 |
- unsigned int i; |
|
34 |
- for(i = 0; i < p->stride * p->height; ++i) |
|
35 |
- p->dat[i] = 0; |
|
25 |
+ int x, y; |
|
26 |
+ for(y = 0; y < p->height; ++y) { |
|
27 |
+ for(x = 0; x < p->width; ++x) { |
|
28 |
+ ppu_write(p, p->bg, x, y, 0); |
|
29 |
+ ppu_write(p, p->fg, x, y, 0); |
|
30 |
+ } |
|
31 |
+ } |
|
36 | 32 |
} |
37 | 33 |
|
38 | 34 |
Uint8 |
39 | 35 |
ppu_read(Ppu *p, Uint16 x, Uint16 y) |
40 | 36 |
{ |
41 |
- unsigned int i = x / PPW + y * p->stride, shift = x % PPW * 4; |
|
42 |
- return (p->dat[i] >> shift) & 0xf; |
|
37 |
+ int ch1, ch2, r = (y % 8) + ((x / 8 + y / 8 * p->width / 8) * 16); |
|
38 |
+ ch1 = (p->fg[r] >> (7 - x % 8)) & 1; |
|
39 |
+ ch2 = (p->fg[r + 8] >> (7 - x % 8)) & 1; |
|
40 |
+ if(!ch1 && !ch2) { |
|
41 |
+ ch1 = (p->bg[r] >> (7 - x % 8)) & 1; |
|
42 |
+ ch2 = (p->bg[r + 8] >> (7 - x % 8)) & 1; |
|
43 |
+ } |
|
44 |
+ return ch1 + (ch2 << 1); |
|
43 | 45 |
} |
44 | 46 |
|
45 | 47 |
void |
46 |
-ppu_write(Ppu *p, int fg, Uint16 x, Uint16 y, Uint8 color) |
|
48 |
+ppu_write(Ppu *p, Uint8 *layer, Uint16 x, Uint16 y, Uint8 color) |
|
47 | 49 |
{ |
48 |
- unsigned int v, i = x / PPW + y * p->stride, shift = x % PPW * 4; |
|
50 |
+ int row = (y % 8) + ((x / 8 + y / 8 * p->width / 8) * 16), col = x % 8; |
|
49 | 51 |
if(x >= p->width || y >= p->height) |
50 | 52 |
return; |
51 |
- v = p->dat[i]; |
|
52 |
- if(fg) shift += 2; |
|
53 |
- p->dat[i] &= ~(3 << shift); |
|
54 |
- p->dat[i] |= color << shift; |
|
55 |
- if((v ^ p->dat[i]) != 0) { |
|
56 |
- p->reqdraw = 1; |
|
57 |
- p->i0 = p->i0 < i ? p->i0 : i; |
|
58 |
- p->i1 = p->i1 > i ? p->i1 : i; |
|
59 |
- } |
|
53 |
+ if(color == 0 || color == 2) |
|
54 |
+ layer[row] &= ~(1UL << (7 - col)); |
|
55 |
+ else |
|
56 |
+ layer[row] |= 1UL << (7 - col); |
|
57 |
+ if(color == 0 || color == 1) |
|
58 |
+ layer[row + 8] &= ~(1UL << (7 - col)); |
|
59 |
+ else |
|
60 |
+ layer[row + 8] |= 1UL << (7 - col); |
|
60 | 61 |
} |
61 | 62 |
|
62 | 63 |
void |
63 |
-ppu_1bpp(Ppu *p, int fg, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy) |
|
64 |
+ppu_1bpp(Ppu *p, Uint8 *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy) |
|
64 | 65 |
{ |
65 | 66 |
Uint16 v, h; |
66 | 67 |
for(v = 0; v < 8; v++) |
... | ... |
@@ -68,7 +69,7 @@ ppu_1bpp(Ppu *p, int fg, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 f |
68 | 69 |
Uint8 ch1 = (sprite[v] >> (7 - h)) & 0x1; |
69 | 70 |
if(ch1 || blending[4][color]) |
70 | 71 |
ppu_write(p, |
71 |
- fg, |
|
72 |
+ layer, |
|
72 | 73 |
x + (flipx ? 7 - h : h), |
73 | 74 |
y + (flipy ? 7 - v : v), |
74 | 75 |
blending[ch1][color]); |
... | ... |
@@ -76,7 +77,7 @@ ppu_1bpp(Ppu *p, int fg, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 f |
76 | 77 |
} |
77 | 78 |
|
78 | 79 |
void |
79 |
-ppu_2bpp(Ppu *p, int fg, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy) |
|
80 |
+ppu_2bpp(Ppu *p, Uint8 *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy) |
|
80 | 81 |
{ |
81 | 82 |
Uint16 v, h; |
82 | 83 |
for(v = 0; v < 8; v++) |
... | ... |
@@ -86,7 +87,7 @@ ppu_2bpp(Ppu *p, int fg, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 f |
86 | 87 |
Uint8 ch = ch1 + ch2 * 2; |
87 | 88 |
if(ch || blending[4][color]) |
88 | 89 |
ppu_write(p, |
89 |
- fg, |
|
90 |
+ layer, |
|
90 | 91 |
x + (flipx ? 7 - h : h), |
91 | 92 |
y + (flipy ? 7 - v : v), |
92 | 93 |
blending[ch][color]); |
... | ... |
@@ -98,12 +99,12 @@ ppu_2bpp(Ppu *p, int fg, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 f |
98 | 99 |
int |
99 | 100 |
ppu_set_size(Ppu *p, Uint16 width, Uint16 height) |
100 | 101 |
{ |
102 |
+ ppu_clear(p); |
|
101 | 103 |
p->width = width; |
102 |
- p->stride = (width + PPW - 1) / PPW; |
|
103 | 104 |
p->height = height; |
104 |
- p->dat = realloc(p->dat, p->stride * p->height * sizeof(unsigned int)); |
|
105 |
- if(p->dat == NULL) return 0; |
|
105 |
+ p->pixels = realloc(p->bg, p->width / 4 * p->height * sizeof(Uint8) * 2); |
|
106 |
+ p->bg = p->pixels; |
|
107 |
+ p->fg = p->pixels + (p->width / 4 * p->height * sizeof(Uint8)); |
|
106 | 108 |
ppu_clear(p); |
107 |
- ppu_frame(p); |
|
108 |
- return 1; |
|
109 |
+ return p->bg && p->fg; |
|
109 | 110 |
} |
... | ... |
@@ -22,14 +22,14 @@ typedef unsigned short Uint16; |
22 | 22 |
typedef unsigned int Uint32; |
23 | 23 |
|
24 | 24 |
typedef struct Ppu { |
25 |
- Uint8 reqdraw; |
|
25 |
+ Uint8 *bg, *fg, *pixels, reqdraw; |
|
26 | 26 |
Uint16 width, height; |
27 |
- unsigned int i0, i1, *dat, stride; |
|
28 | 27 |
} Ppu; |
29 | 28 |
|
30 | 29 |
Uint8 ppu_read(Ppu *p, Uint16 x, Uint16 y); |
31 |
-void ppu_write(Ppu *p, int fg, Uint16 x, Uint16 y, Uint8 color); |
|
30 |
+void ppu_write(Ppu *p, Uint8 *layer, Uint16 x, Uint16 y, Uint8 color); |
|
32 | 31 |
void ppu_frame(Ppu *p); |
33 |
-void ppu_1bpp(Ppu *p, int fg, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy); |
|
34 |
-void ppu_2bpp(Ppu *p, int fg, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy); |
|
32 |
+ |
|
33 |
+void ppu_1bpp(Ppu *p, Uint8 *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy); |
|
34 |
+void ppu_2bpp(Ppu *p, Uint8 *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy); |
|
35 | 35 |
int ppu_set_size(Ppu *p, Uint16 width, Uint16 height); |
... | ... |
@@ -37,7 +37,7 @@ static SDL_Rect gRect; |
37 | 37 |
static Ppu ppu; |
38 | 38 |
static Apu apu[POLYPHONY]; |
39 | 39 |
static Device *devsystem, *devscreen, *devmouse, *devctrl, *devaudio0, *devconsole; |
40 |
-static Uint8 zoom = 1, reqdraw = 0; |
|
40 |
+static Uint8 zoom = 1; |
|
41 | 41 |
static Uint32 *ppu_screen, stdin_event, audio0_event, palette[16]; |
42 | 42 |
|
43 | 43 |
static Uint8 font[][8] = { |
... | ... |
@@ -118,14 +118,14 @@ set_palette(Uint8 *addr) |
118 | 118 |
} |
119 | 119 |
for(i = 4; i < 16; ++i) |
120 | 120 |
palette[i] = palette[i / 4]; |
121 |
- reqdraw = 1; |
|
121 |
+ ppu.reqdraw = 1; |
|
122 | 122 |
} |
123 | 123 |
|
124 | 124 |
static void |
125 | 125 |
set_inspect(Uint8 flag) |
126 | 126 |
{ |
127 | 127 |
devsystem->dat[0xe] = flag; |
128 |
- reqdraw = 1; |
|
128 |
+ ppu.reqdraw = 1; |
|
129 | 129 |
} |
130 | 130 |
|
131 | 131 |
static void |
... | ... |
@@ -144,7 +144,7 @@ set_zoom(Uint8 scale) |
144 | 144 |
if(scale == zoom || !gWindow) |
145 | 145 |
return; |
146 | 146 |
set_window_size(gWindow, (ppu.width + PAD * 2) * zoom, (ppu.height + PAD * 2) * zoom); |
147 |
- reqdraw = 1; |
|
147 |
+ ppu.reqdraw = 1; |
|
148 | 148 |
} |
149 | 149 |
|
150 | 150 |
static int |
... | ... |
@@ -165,7 +165,7 @@ set_size(Uint16 width, Uint16 height, int is_resize) |
165 | 165 |
return error("sdl_texture", SDL_GetError()); |
166 | 166 |
if(is_resize) |
167 | 167 |
set_window_size(gWindow, (ppu.width + PAD * 2) * zoom, (ppu.height + PAD * 2) * zoom); |
168 |
- reqdraw = 1; |
|
168 |
+ ppu.reqdraw = 1; |
|
169 | 169 |
return 1; |
170 | 170 |
} |
171 | 171 |
|
... | ... |
@@ -190,51 +190,46 @@ static void |
190 | 190 |
draw_inspect(Ppu *p, Uint8 *stack, Uint8 wptr, Uint8 rptr, Uint8 *memory) |
191 | 191 |
{ |
192 | 192 |
Uint8 i, x, y, b; |
193 |
- for(i = 0; i < 0x20; ++i) { /* stack */ |
|
193 |
+ |
|
194 |
+ for(i = 0; i < 0x20; ++i) { |
|
194 | 195 |
x = ((i % 8) * 3 + 1) * 8, y = (i / 8 + 1) * 8, b = stack[i]; |
195 |
- ppu_1bpp(p, 1, x, y, font[(b >> 4) & 0xf], 1 + (wptr == i) * 0x7, 0, 0); |
|
196 |
- ppu_1bpp(p, 1, x + 8, y, font[b & 0xf], 1 + (wptr == i) * 0x7, 0, 0); |
|
196 |
+ /* working stack */ |
|
197 |
+ ppu_1bpp(p, ppu.fg, x, y, font[(b >> 4) & 0xf], 1 + (wptr == i) * 0x7, 0, 0); |
|
198 |
+ ppu_1bpp(p, ppu.fg, x + 8, y, font[b & 0xf], 1 + (wptr == i) * 0x7, 0, 0); |
|
199 |
+ y = 0x28 + (i / 8 + 1) * 8; |
|
200 |
+ b = memory[i]; |
|
201 |
+ /* return stack */ |
|
202 |
+ ppu_1bpp(p, ppu.fg, x, y, font[(b >> 4) & 0xf], 3, 0, 0); |
|
203 |
+ ppu_1bpp(p, ppu.fg, x + 8, y, font[b & 0xf], 3, 0, 0); |
|
197 | 204 |
} |
198 | 205 |
/* return pointer */ |
199 |
- ppu_1bpp(p, 1, 0x8, y + 0x10, font[(rptr >> 4) & 0xf], 0x2, 0, 0); |
|
200 |
- ppu_1bpp(p, 1, 0x10, y + 0x10, font[rptr & 0xf], 0x2, 0, 0); |
|
201 |
- for(i = 0; i < 0x20; ++i) { /* memory */ |
|
202 |
- x = ((i % 8) * 3 + 1) * 8, y = 0x38 + (i / 8 + 1) * 8, b = memory[i]; |
|
203 |
- ppu_1bpp(p, 1, x, y, font[(b >> 4) & 0xf], 3, 0, 0); |
|
204 |
- ppu_1bpp(p, 1, x + 8, y, font[b & 0xf], 3, 0, 0); |
|
205 |
- } |
|
206 |
- for(x = 0; x < 0x10; ++x) { /* guides */ |
|
207 |
- ppu_write(p, 1, x, p->height / 2, 2); |
|
208 |
- ppu_write(p, 1, p->width - x, p->height / 2, 2); |
|
209 |
- ppu_write(p, 1, p->width / 2, p->height - x, 2); |
|
210 |
- ppu_write(p, 1, p->width / 2, x, 2); |
|
211 |
- ppu_write(p, 1, p->width / 2 - 0x10 / 2 + x, p->height / 2, 2); |
|
212 |
- ppu_write(p, 1, p->width / 2, p->height / 2 - 0x10 / 2 + x, 2); |
|
206 |
+ ppu_1bpp(p, ppu.fg, 0x8, y + 0x10, font[(rptr >> 4) & 0xf], 0x2, 0, 0); |
|
207 |
+ ppu_1bpp(p, ppu.fg, 0x10, y + 0x10, font[rptr & 0xf], 0x2, 0, 0); |
|
208 |
+ /* guides */ |
|
209 |
+ for(x = 0; x < 0x10; ++x) { |
|
210 |
+ ppu_write(p, ppu.fg, x, p->height / 2, 2); |
|
211 |
+ ppu_write(p, ppu.fg, p->width - x, p->height / 2, 2); |
|
212 |
+ ppu_write(p, ppu.fg, p->width / 2, p->height - x, 2); |
|
213 |
+ ppu_write(p, ppu.fg, p->width / 2, x, 2); |
|
214 |
+ ppu_write(p, ppu.fg, p->width / 2 - 0x10 / 2 + x, p->height / 2, 2); |
|
215 |
+ ppu_write(p, ppu.fg, p->width / 2, p->height / 2 - 0x10 / 2 + x, 2); |
|
213 | 216 |
} |
214 | 217 |
} |
215 | 218 |
|
216 | 219 |
static void |
217 | 220 |
redraw(Uxn *u) |
218 | 221 |
{ |
219 |
- Uint16 x, y, y0 = 0, y1 = ppu.height; |
|
220 |
- SDL_Rect up = gRect; |
|
222 |
+ Uint16 x, y; |
|
221 | 223 |
if(devsystem->dat[0xe]) |
222 | 224 |
draw_inspect(&ppu, u->wst.dat, u->wst.ptr, u->rst.ptr, u->ram.dat); |
223 |
- if(!reqdraw && ppu.reqdraw) { |
|
224 |
- y0 = ppu.i0 / ppu.stride; |
|
225 |
- y1 = ppu.i1 / ppu.stride + 1; |
|
226 |
- up.y += y0; |
|
227 |
- up.h = y1 - y0; |
|
228 |
- } |
|
229 |
- for(y = y0; y < y1; ++y) |
|
225 |
+ for(y = 0; y < ppu.height; ++y) |
|
230 | 226 |
for(x = 0; x < ppu.width; ++x) |
231 | 227 |
ppu_screen[x + y * ppu.width] = palette[ppu_read(&ppu, x, y)]; |
232 |
- SDL_UpdateTexture(gTexture, &up, ppu_screen + y0 * ppu.width, ppu.width * sizeof(Uint32)); |
|
228 |
+ SDL_UpdateTexture(gTexture, &gRect, ppu_screen, ppu.width * sizeof(Uint32)); |
|
233 | 229 |
SDL_RenderClear(gRenderer); |
234 | 230 |
SDL_RenderCopy(gRenderer, gTexture, NULL, NULL); |
235 | 231 |
SDL_RenderPresent(gRenderer); |
236 |
- reqdraw = 0; |
|
237 |
- ppu_frame(&ppu); |
|
232 |
+ ppu.reqdraw = 0; |
|
238 | 233 |
} |
239 | 234 |
|
240 | 235 |
static void |
... | ... |
@@ -395,7 +390,7 @@ screen_talk(Device *d, Uint8 b0, Uint8 w) |
395 | 390 |
Uint16 x = peek16(d->dat, 0x8); |
396 | 391 |
Uint16 y = peek16(d->dat, 0xa); |
397 | 392 |
Uint8 layer = d->dat[0xe] & 0x40; |
398 |
- ppu_write(&ppu, layer, x, y, d->dat[0xe] & 0x3); |
|
393 |
+ ppu_write(&ppu, layer ? ppu.fg : ppu.bg, x, y, d->dat[0xe] & 0x3); |
|
399 | 394 |
if(d->dat[0x6] & 0x01) poke16(d->dat, 0x8, x + 1); /* auto x+1 */ |
400 | 395 |
if(d->dat[0x6] & 0x02) poke16(d->dat, 0xa, y + 1); /* auto y+1 */ |
401 | 396 |
break; |
... | ... |
@@ -406,14 +401,15 @@ screen_talk(Device *d, Uint8 b0, Uint8 w) |
406 | 401 |
Uint8 layer = d->dat[0xf] & 0x40; |
407 | 402 |
Uint8 *addr = &d->mem[peek16(d->dat, 0xc)]; |
408 | 403 |
if(d->dat[0xf] & 0x80) { |
409 |
- ppu_2bpp(&ppu, layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20); |
|
404 |
+ ppu_2bpp(&ppu, layer ? ppu.fg : ppu.bg, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20); |
|
410 | 405 |
if(d->dat[0x6] & 0x04) poke16(d->dat, 0xc, peek16(d->dat, 0xc) + 16); /* auto addr+16 */ |
411 | 406 |
} else { |
412 |
- ppu_1bpp(&ppu, layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20); |
|
407 |
+ ppu_1bpp(&ppu, layer ? ppu.fg : ppu.bg, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20); |
|
413 | 408 |
if(d->dat[0x6] & 0x04) poke16(d->dat, 0xc, peek16(d->dat, 0xc) + 8); /* auto addr+8 */ |
414 | 409 |
} |
415 | 410 |
if(d->dat[0x6] & 0x01) poke16(d->dat, 0x8, x + 8); /* auto x+8 */ |
416 | 411 |
if(d->dat[0x6] & 0x02) poke16(d->dat, 0xa, y + 8); /* auto y+8 */ |
412 |
+ ppu.reqdraw = 1; |
|
417 | 413 |
break; |
418 | 414 |
} |
419 | 415 |
} |
... | ... |
@@ -546,7 +542,7 @@ run(Uxn *u) |
546 | 542 |
} |
547 | 543 |
} |
548 | 544 |
uxn_eval(u, devscreen->vector); |
549 |
- if(reqdraw || ppu.reqdraw || devsystem->dat[0xe]) |
|
545 |
+ if(ppu.reqdraw || devsystem->dat[0xe]) |
|
550 | 546 |
redraw(u); |
551 | 547 |
if(!BENCH) { |
552 | 548 |
elapsed = (SDL_GetPerformanceCounter() - start) / (double)SDL_GetPerformanceFrequency() * 1000.0f; |