diff options
Diffstat (limited to 'src/uxn/devices/ppu.c')
-rw-r--r-- | src/uxn/devices/ppu.c | 180 |
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 | /* | ||
4 | Copyright (c) 2021 Devine Lu Linvega | ||
5 | Copyright (c) 2021 Andrew Alderwick | ||
6 | |||
7 | Permission to use, copy, modify, and distribute this software for any | ||
8 | purpose with or without fee is hereby granted, provided that the above | ||
9 | copyright notice and this permission notice appear in all copies. | ||
10 | |||
11 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
12 | WITH REGARD TO THIS SOFTWARE. | ||
13 | */ | ||
14 | |||
15 | static 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 | |||
33 | Uint8 | ||
34 | readpixel(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 | |||
41 | void | ||
42 | clear(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 | |||
53 | void | ||
54 | putcolors(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 | |||
70 | void | ||
71 | putpixel(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 | |||
86 | void | ||
87 | puticn(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 | |||
102 | void | ||
103 | putchr(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 | |||
120 | void | ||
121 | drawpixel(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 | |||
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 | } | ||
145 | |||
146 | void | ||
147 | drawppu(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 | |||
164 | int | ||
165 | initppu(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 | } | ||