aboutsummaryrefslogtreecommitdiffstats
path: root/src/uxn/devices/ppu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/uxn/devices/ppu.c')
-rw-r--r--src/uxn/devices/ppu.c180
1 files changed, 180 insertions, 0 deletions
diff --git a/src/uxn/devices/ppu.c b/src/uxn/devices/ppu.c
new file mode 100644
index 0000000..b977f97
--- /dev/null
+++ b/src/uxn/devices/ppu.c
@@ -0,0 +1,180 @@
1#include "ppu.h"
2
3/*
4Copyright (c) 2021 Devine Lu Linvega
5Copyright (c) 2021 Andrew Alderwick
6
7Permission to use, copy, modify, and distribute this software for any
8purpose with or without fee is hereby granted, provided that the above
9copyright notice and this permission notice appear in all copies.
10
11THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12WITH REGARD TO THIS SOFTWARE.
13*/
14
15static Uint8 font[][8] = {
16 {0x00, 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c},
17 {0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10},
18 {0x00, 0x7c, 0x82, 0x02, 0x7c, 0x80, 0x80, 0xfe},
19 {0x00, 0x7c, 0x82, 0x02, 0x1c, 0x02, 0x82, 0x7c},
20 {0x00, 0x0c, 0x14, 0x24, 0x44, 0x84, 0xfe, 0x04},
21 {0x00, 0xfe, 0x80, 0x80, 0x7c, 0x02, 0x82, 0x7c},
22 {0x00, 0x7c, 0x82, 0x80, 0xfc, 0x82, 0x82, 0x7c},
23 {0x00, 0x7c, 0x82, 0x02, 0x1e, 0x02, 0x02, 0x02},
24 {0x00, 0x7c, 0x82, 0x82, 0x7c, 0x82, 0x82, 0x7c},
25 {0x00, 0x7c, 0x82, 0x82, 0x7e, 0x02, 0x82, 0x7c},
26 {0x00, 0x7c, 0x82, 0x02, 0x7e, 0x82, 0x82, 0x7e},
27 {0x00, 0xfc, 0x82, 0x82, 0xfc, 0x82, 0x82, 0xfc},
28 {0x00, 0x7c, 0x82, 0x80, 0x80, 0x80, 0x82, 0x7c},
29 {0x00, 0xfc, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfc},
30 {0x00, 0x7c, 0x82, 0x80, 0xf0, 0x80, 0x82, 0x7c},
31 {0x00, 0x7c, 0x82, 0x80, 0xf0, 0x80, 0x80, 0x80}};
32
33Uint8
34readpixel(Uint8 *sprite, Uint8 h, Uint8 v)
35{
36 Uint8 ch1 = ((sprite[v] >> h) & 0x1);
37 Uint8 ch2 = (((sprite[v + 8] >> h) & 0x1) << 1);
38 return ch1 + ch2;
39}
40
41void
42clear(Ppu *p)
43{
44 int i, sz = p->height * p->width, rows = sz / 4;
45 for(i = 0; i < sz; ++i)
46 p->output[i] = p->colors[0];
47 for(i = 0; i < rows; i++) {
48 p->fg[i] = 0;
49 p->bg[i] = 0;
50 }
51}
52
53void
54putcolors(Ppu *p, Uint8 *addr)
55{
56 int i;
57 for(i = 0; i < 4; ++i) {
58 Uint8
59 r = (*(addr + i / 2) >> (!(i % 2) << 2)) & 0x0f,
60 g = (*(addr + 2 + i / 2) >> (!(i % 2) << 2)) & 0x0f,
61 b = (*(addr + 4 + i / 2) >> (!(i % 2) << 2)) & 0x0f;
62 p->colors[i] = rgb15(r,g,b);
63 }
64 // p->colors[0] = COLOR_BLUE;
65 // p->colors[1] = COLOR_WHITE;
66 // p->colors[2] = COLOR_RED;
67 // p->colors[3] = COLOR_CYAN;
68}
69
70void
71putpixel(Ppu *p, Uint8 *layer, Uint16 x, Uint16 y, Uint8 color)
72{
73 Uint16 row = (y % 8) + ((x / 8 + y / 8 * p->hor) * 16), col = 7 - (x % 8);
74 if(x >= p->hor * 8 || y >= p->ver * 8 || row > (p->hor * p->ver * 16) - 8)
75 return;
76 if(color == 0 || color == 2)
77 layer[row] &= ~(1UL << col);
78 else
79 layer[row] |= 1UL << col;
80 if(color == 0 || color == 1)
81 layer[row + 8] &= ~(1UL << col);
82 else
83 layer[row + 8] |= 1UL << col;
84}
85
86void
87puticn(Ppu *p, Uint8 *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy)
88{
89 Uint16 v, h;
90 for(v = 0; v < 8; v++)
91 for(h = 0; h < 8; h++) {
92 Uint8 ch1 = ((sprite[v] >> (7 - h)) & 0x1);
93 if(ch1 == 1 || (color != 0x05 && color != 0x0a && color != 0x0f))
94 putpixel(p,
95 layer,
96 x + (flipx ? 7 - h : h),
97 y + (flipy ? 7 - v : v),
98 ch1 ? color % 4 : color / 4);
99 }
100}
101
102void
103putchr(Ppu *p, Uint8 *layer, Uint16 x, Uint16 y, Uint8 *sprite, Uint8 color, Uint8 flipx, Uint8 flipy)
104{
105 Uint16 v, h;
106 for(v = 0; v < 8; v++)
107 for(h = 0; h < 8; h++) {
108 Uint8 ch1 = ((sprite[v] >> (7 - h)) & 0x1) * color;
109 Uint8 ch2 = ((sprite[v + 8] >> (7 - h)) & 0x1) * color;
110 putpixel(p,
111 layer,
112 x + (flipx ? 7 - h : h),
113 y + (flipy ? 7 - v : v),
114 (((ch1 + ch2 * 2) + color / 4) & 0x3));
115 }
116}
117
118/* output */
119
120void
121drawpixel(Ppu *p, Uint16 x, Uint16 y, Uint8 color)
122{
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];
125}
126
127void
128drawdebugger(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}
145
146void
147drawppu(Ppu *p)
148{
149 Uint16 x, y;
150 for(y = 0; y < p->ver; ++y)
151 for(x = 0; x < p->hor; ++x) {
152 Uint8 v, h;
153 Uint16 key = (y * p->hor + x) * 16;
154 for(v = 0; v < 8; v++)
155 for(h = 0; h < 8; h++) {
156 Uint8 color = readpixel(&p->fg[key], h, v);
157 if(color == 0)
158 color = readpixel(&p->bg[key], h, v);
159 drawpixel(p, x * 8 + p->pad + 7 - h, y * 8 + p->pad + v, color);
160 }
161 }
162}
163
164int
165initppu(Ppu *p, Uint8 hor, Uint8 ver, Uint8 pad)
166{
167 p->hor = hor;
168 p->ver = ver;
169 p->pad = pad;
170 p->width = (8 * p->hor + p->pad * 2);
171 p->height = (8 * p->ver + p->pad * 2);
172 if(!(p->output = malloc(p->width * p->height * sizeof(Uint16))))
173 return 0;
174 if(!(p->bg = malloc(p->width * p->height * sizeof(Uint8) / 4)))
175 return 0;
176 if(!(p->fg = malloc(p->width * p->height * sizeof(Uint8) / 4)))
177 return 0;
178 clear(p);
179 return 1;
180}