| ... | ... |
@@ -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; |