Browse code

ppu: keep track of the vertical region where redraw is supposed to happen

Sigrid Solveig Haflínudóttir authored on 21/09/2021 17:39:00
Showing 3 changed files
... ...
@@ -19,6 +19,14 @@ 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->redraw = 0;
26
+	p->i0 = p->width / PPW + p->height * p->stride;
27
+	p->i1 = 0;
28
+}
29
+
22 30
 static void
23 31
 ppu_clear(Ppu *p)
24 32
 {
... ...
@@ -27,55 +35,55 @@ ppu_clear(Ppu *p)
27 35
 		p->dat[i] = 0;
28 36
 }
29 37
 
30
-unsigned int
38
+void
31 39
 ppu_pixel(Ppu *p, int fg, Uint16 x, Uint16 y, Uint8 color)
32 40
 {
33
-	unsigned int ret, i = x / PPW + y * p->stride, shift = x % PPW * 4;
41
+	unsigned int v, i = x / PPW + y * p->stride, shift = x % PPW * 4;
34 42
 	if(x >= p->width || y >= p->height)
35
-		return 0;
36
-	ret = p->dat[i];
43
+		return;
44
+	v = p->dat[i];
37 45
 	if(fg) shift += 2;
38 46
 	p->dat[i] &= ~(3 << shift);
39 47
 	p->dat[i] |= color << shift;
40
-	return ret ^ p->dat[i];
48
+	if((v ^ p->dat[i]) != 0){
49
+		p->redraw = 1;
50
+		p->i0 = p->i0 < i ? p->i0 : i;
51
+		p->i1 = p->i1 > i ? p->i1 : i;
52
+	}
41 53
 }
42 54
 
43
-unsigned int
55
+void
44 56
 ppu_1bpp(Ppu *p, int fg, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy)
45 57
 {
46 58
 	Uint16 v, h;
47
-	int ret = 0;
48 59
 	for(v = 0; v < 8; v++)
49 60
 		for(h = 0; h < 8; h++) {
50 61
 			Uint8 ch1 = (sprite[v] >> (7 - h)) & 0x1;
51 62
 			if(ch1 || blending[4][color])
52
-				ret |= ppu_pixel(p,
63
+				ppu_pixel(p,
53 64
 					fg,
54 65
 					x + (flipx ? 7 - h : h),
55 66
 					y + (flipy ? 7 - v : v),
56 67
 					blending[ch1][color]);
57 68
 		}
58
-	return ret;
59 69
 }
60 70
 
61
-unsigned int
71
+void
62 72
 ppu_2bpp(Ppu *p, int fg, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy)
63 73
 {
64 74
 	Uint16 v, h;
65
-	int ret = 0;
66 75
 	for(v = 0; v < 8; v++)
67 76
 		for(h = 0; h < 8; h++) {
68 77
 			Uint8 ch1 = ((sprite[v] >> (7 - h)) & 0x1);
69 78
 			Uint8 ch2 = ((sprite[v + 8] >> (7 - h)) & 0x1);
70 79
 			Uint8 ch = ch1 + ch2 * 2;
71 80
 			if(ch || blending[4][color])
72
-				ret |= ppu_pixel(p,
81
+				ppu_pixel(p,
73 82
 					fg,
74 83
 					x + (flipx ? 7 - h : h),
75 84
 					y + (flipy ? 7 - v : v),
76 85
 					blending[ch][color]);
77 86
 		}
78
-	return ret;
79 87
 }
80 88
 
81 89
 /* output */
... ...
@@ -89,5 +97,6 @@ ppu_set_size(Ppu *p, Uint16 width, Uint16 height)
89 97
 	p->dat = realloc(p->dat, p->stride * p->height * sizeof(unsigned int));
90 98
 	if(p->dat == NULL) return 0;
91 99
 	ppu_clear(p);
100
+	ppu_frame(p);
92 101
 	return 1;
93
-}
94 102
\ No newline at end of file
103
+}
... ...
@@ -23,10 +23,12 @@ typedef unsigned int Uint32;
23 23
 
24 24
 typedef struct Ppu {
25 25
 	Uint16 width, height;
26
+	int i0, i1, redraw;
26 27
 	unsigned int *dat, stride;
27 28
 } Ppu;
28 29
 
30
+void ppu_frame(Ppu *p);
29 31
 int ppu_set_size(Ppu *p, Uint16 width, Uint16 height);
30
-unsigned int ppu_pixel(Ppu *p, int fg, Uint16 x, Uint16 y, Uint8 color);
31
-unsigned int ppu_1bpp(Ppu *p, int fg, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy);
32
-unsigned int ppu_2bpp(Ppu *p, int fg, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy);
32
+void ppu_pixel(Ppu *p, int fg, Uint16 x, Uint16 y, Uint8 color);
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);
... ...
@@ -122,17 +122,25 @@ get_pixel(int x, int y)
122 122
 static void
123 123
 redraw(Uxn *u)
124 124
 {
125
-	Uint16 x, y;
125
+	Uint16 x, y, y0 = 0, y1 = ppu.height;
126
+	SDL_Rect up = gRect;
126 127
 	if(devsystem->dat[0xe])
127 128
 		inspect(&ppu, u->wst.dat, u->wst.ptr, u->rst.ptr, u->ram.dat);
128
-	for(y = 0; y < ppu.height; ++y)
129
+	if(ppu.redraw) {
130
+		y0 = ppu.i0 / ppu.stride;
131
+		y1 = ppu.i1 / ppu.stride + 1;
132
+		up.y += y0;
133
+		up.h = y1 - y0;
134
+	}
135
+	for(y = y0; y < y1; ++y)
129 136
 		for(x = 0; x < ppu.width; ++x)
130 137
 			ppu_screen[x + y * ppu.width] = palette[get_pixel(x, y)];
131
-	SDL_UpdateTexture(gTexture, &gRect, ppu_screen, ppu.width * sizeof(Uint32));
138
+	SDL_UpdateTexture(gTexture, &up, ppu_screen + y0 * ppu.width, ppu.width * sizeof(Uint32));
132 139
 	SDL_RenderClear(gRenderer);
133 140
 	SDL_RenderCopy(gRenderer, gTexture, NULL, NULL);
134 141
 	SDL_RenderPresent(gRenderer);
135 142
 	reqdraw = 0;
143
+	ppu_frame(&ppu);
136 144
 }
137 145
 
138 146
 static void
... ...
@@ -353,7 +361,7 @@ screen_talk(Device *d, Uint8 b0, Uint8 w)
353 361
 			Uint16 x = peek16(d->dat, 0x8);
354 362
 			Uint16 y = peek16(d->dat, 0xa);
355 363
 			Uint8 layer = d->dat[0xe] & 0x40;
356
-			reqdraw |= ppu_pixel(&ppu, layer, x, y, d->dat[0xe] & 0x3);
364
+			ppu_pixel(&ppu, layer, x, y, d->dat[0xe] & 0x3);
357 365
 			if(d->dat[0x6] & 0x01) poke16(d->dat, 0x8, x + 1); /* auto x+1 */
358 366
 			if(d->dat[0x6] & 0x02) poke16(d->dat, 0xa, y + 1); /* auto y+1 */
359 367
 			break;
... ...
@@ -364,10 +372,10 @@ screen_talk(Device *d, Uint8 b0, Uint8 w)
364 372
 			Uint8 layer = d->dat[0xf] & 0x40;
365 373
 			Uint8 *addr = &d->mem[peek16(d->dat, 0xc)];
366 374
 			if(d->dat[0xf] & 0x80) {
367
-				reqdraw |= ppu_2bpp(&ppu, layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20);
375
+				ppu_2bpp(&ppu, layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20);
368 376
 				if(d->dat[0x6] & 0x04) poke16(d->dat, 0xc, peek16(d->dat, 0xc) + 16); /* auto addr+16 */
369 377
 			} else {
370
-				reqdraw |= ppu_1bpp(&ppu, layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20);
378
+				ppu_1bpp(&ppu, layer, x, y, addr, d->dat[0xf] & 0xf, d->dat[0xf] & 0x10, d->dat[0xf] & 0x20);
371 379
 				if(d->dat[0x6] & 0x04) poke16(d->dat, 0xc, peek16(d->dat, 0xc) + 8); /* auto addr+8 */
372 380
 			}
373 381
 			if(d->dat[0x6] & 0x01) poke16(d->dat, 0x8, x + 8); /* auto x+8 */
... ...
@@ -529,7 +537,7 @@ run(Uxn *u)
529 537
 			}
530 538
 		}
531 539
 		uxn_eval(u, peek16(devscreen->dat, 0));
532
-		if(reqdraw || devsystem->dat[0xe])
540
+		if(reqdraw || ppu.redraw || devsystem->dat[0xe])
533 541
 			redraw(u);
534 542
 		if(!BENCH) {
535 543
 			elapsed = (SDL_GetPerformanceCounter() - start) / (double)SDL_GetPerformanceFrequency() * 1000.0f;