18 #include <type_traits>
22 template <
class Pixel>
25 : vdp(vdp_), vram(vdp.getVRAM()), palFg(palFg_), palBg(palBg_)
29 template <
class Pixel>
33 assert(modeBase < 0x0C);
36 template <
class Pixel>
41 case 0: renderGraphic1(linePtr, line);
break;
42 case 1: renderText1 (linePtr, line);
break;
43 case 2: renderMulti (linePtr, line);
break;
44 case 3: renderBogus (linePtr);
break;
45 case 4: renderGraphic2(linePtr, line);
break;
46 case 5: renderText1Q (linePtr, line);
break;
47 case 6: renderMultiQ (linePtr, line);
break;
48 case 7: renderBogus (linePtr);
break;
50 case 8: renderGraphic2(linePtr, line);
break;
51 case 9: renderText2 (linePtr, line);
break;
52 case 10: renderBogus (linePtr);
break;
53 case 11: renderBogus (linePtr);
break;
58 template <
class Pixel>
60 Pixel* __restrict pixelPtr,
int line) __restrict
62 Pixel fg = palFg[vdp.getForegroundColor()];
63 Pixel bg = palFg[vdp.getBackgroundColor()];
66 const byte* patternArea = vram.patternTable.getReadArea(0, 256 * 8);
67 patternArea += (line + vdp.getVerticalScroll()) & 7;
72 unsigned nameStart = (line / 8) * 40;
73 unsigned nameEnd = nameStart + 40;
74 for (
unsigned name = nameStart; name < nameEnd; ++name) {
75 unsigned charcode = vram.nameTable.readNP((name + 0xC00) | (-1 << 12));
76 unsigned pattern = patternArea[charcode * 8];
77 pixelPtr[0] = (pattern & 0x80) ? fg : bg;
78 pixelPtr[1] = (pattern & 0x40) ? fg : bg;
79 pixelPtr[2] = (pattern & 0x20) ? fg : bg;
80 pixelPtr[3] = (pattern & 0x10) ? fg : bg;
81 pixelPtr[4] = (pattern & 0x08) ? fg : bg;
82 pixelPtr[5] = (pattern & 0x04) ? fg : bg;
87 template <
class Pixel>
88 void CharacterConverter<Pixel>::renderText1Q(
89 Pixel* __restrict pixelPtr,
int line) __restrict
91 Pixel fg = palFg[vdp.getForegroundColor()];
92 Pixel bg = palFg[vdp.getBackgroundColor()];
94 unsigned patternBaseLine = (-1 << 13) | ((line + vdp.getVerticalScroll()) & 7);
99 unsigned nameStart = (line / 8) * 40;
100 unsigned nameEnd = nameStart + 40;
101 unsigned patternQuarter = (line & 0xC0) << 2;
102 for (
unsigned name = nameStart; name < nameEnd; ++name) {
103 unsigned charcode = vram.nameTable.readNP((name + 0xC00) | (-1 << 12));
104 unsigned patternNr = patternQuarter | charcode;
105 unsigned pattern = vram.patternTable.readNP(
106 patternBaseLine | (patternNr * 8));
107 pixelPtr[0] = (pattern & 0x80) ? fg : bg;
108 pixelPtr[1] = (pattern & 0x40) ? fg : bg;
109 pixelPtr[2] = (pattern & 0x20) ? fg : bg;
110 pixelPtr[3] = (pattern & 0x10) ? fg : bg;
111 pixelPtr[4] = (pattern & 0x08) ? fg : bg;
112 pixelPtr[5] = (pattern & 0x04) ? fg : bg;
117 template <
class Pixel>
118 void CharacterConverter<Pixel>::renderText2(
119 Pixel* __restrict pixelPtr,
int line) __restrict
121 Pixel plainFg = palFg[vdp.getForegroundColor()];
122 Pixel plainBg = palFg[vdp.getBackgroundColor()];
123 Pixel blinkFg, blinkBg;
124 if (vdp.getBlinkState()) {
125 int fg = vdp.getBlinkForegroundColor();
126 blinkFg = palBg[fg ? fg : vdp.getBlinkBackgroundColor()];
127 blinkBg = palBg[vdp.getBlinkBackgroundColor()];
134 const byte* patternArea = vram.patternTable.getReadArea(0, 256 * 8);
135 patternArea += (line + vdp.getVerticalScroll()) & 7;
137 unsigned colorStart = (line / 8) * (80 / 8);
138 unsigned nameStart = (line / 8) * 80;
139 for (
unsigned i = 0; i < (80 / 8); ++i) {
140 unsigned colorPattern = vram.colorTable.readNP(
141 (colorStart + i) | (-1 << 9));
142 const byte* nameArea = vram.nameTable.getReadArea(
143 (nameStart + 8 * i) | (-1 << 12), 8);
145 Pixel fg0 = (colorPattern & 0x80) ? blinkFg : plainFg;
146 Pixel bg0 = (colorPattern & 0x80) ? blinkBg : plainBg;
147 unsigned pattern0 = patternArea[nameArea[0] * 8];
148 pixelPtr[ 0] = (pattern0 & 0x80) ? fg0 : bg0;
149 pixelPtr[ 1] = (pattern0 & 0x40) ? fg0 : bg0;
150 pixelPtr[ 2] = (pattern0 & 0x20) ? fg0 : bg0;
151 pixelPtr[ 3] = (pattern0 & 0x10) ? fg0 : bg0;
152 pixelPtr[ 4] = (pattern0 & 0x08) ? fg0 : bg0;
153 pixelPtr[ 5] = (pattern0 & 0x04) ? fg0 : bg0;
155 Pixel fg1 = (colorPattern & 0x40) ? blinkFg : plainFg;
156 Pixel bg1 = (colorPattern & 0x40) ? blinkBg : plainBg;
157 unsigned pattern1 = patternArea[nameArea[1] * 8];
158 pixelPtr[ 6] = (pattern1 & 0x80) ? fg1 : bg1;
159 pixelPtr[ 7] = (pattern1 & 0x40) ? fg1 : bg1;
160 pixelPtr[ 8] = (pattern1 & 0x20) ? fg1 : bg1;
161 pixelPtr[ 9] = (pattern1 & 0x10) ? fg1 : bg1;
162 pixelPtr[10] = (pattern1 & 0x08) ? fg1 : bg1;
163 pixelPtr[11] = (pattern1 & 0x04) ? fg1 : bg1;
165 Pixel fg2 = (colorPattern & 0x20) ? blinkFg : plainFg;
166 Pixel bg2 = (colorPattern & 0x20) ? blinkBg : plainBg;
167 unsigned pattern2 = patternArea[nameArea[2] * 8];
168 pixelPtr[12] = (pattern2 & 0x80) ? fg2 : bg2;
169 pixelPtr[13] = (pattern2 & 0x40) ? fg2 : bg2;
170 pixelPtr[14] = (pattern2 & 0x20) ? fg2 : bg2;
171 pixelPtr[15] = (pattern2 & 0x10) ? fg2 : bg2;
172 pixelPtr[16] = (pattern2 & 0x08) ? fg2 : bg2;
173 pixelPtr[17] = (pattern2 & 0x04) ? fg2 : bg2;
175 Pixel fg3 = (colorPattern & 0x10) ? blinkFg : plainFg;
176 Pixel bg3 = (colorPattern & 0x10) ? blinkBg : plainBg;
177 unsigned pattern3 = patternArea[nameArea[3] * 8];
178 pixelPtr[18] = (pattern3 & 0x80) ? fg3 : bg3;
179 pixelPtr[19] = (pattern3 & 0x40) ? fg3 : bg3;
180 pixelPtr[20] = (pattern3 & 0x20) ? fg3 : bg3;
181 pixelPtr[21] = (pattern3 & 0x10) ? fg3 : bg3;
182 pixelPtr[22] = (pattern3 & 0x08) ? fg3 : bg3;
183 pixelPtr[23] = (pattern3 & 0x04) ? fg3 : bg3;
185 Pixel fg4 = (colorPattern & 0x08) ? blinkFg : plainFg;
186 Pixel bg4 = (colorPattern & 0x08) ? blinkBg : plainBg;
187 unsigned pattern4 = patternArea[nameArea[4] * 8];
188 pixelPtr[24] = (pattern4 & 0x80) ? fg4 : bg4;
189 pixelPtr[25] = (pattern4 & 0x40) ? fg4 : bg4;
190 pixelPtr[26] = (pattern4 & 0x20) ? fg4 : bg4;
191 pixelPtr[27] = (pattern4 & 0x10) ? fg4 : bg4;
192 pixelPtr[28] = (pattern4 & 0x08) ? fg4 : bg4;
193 pixelPtr[29] = (pattern4 & 0x04) ? fg4 : bg4;
195 Pixel fg5 = (colorPattern & 0x04) ? blinkFg : plainFg;
196 Pixel bg5 = (colorPattern & 0x04) ? blinkBg : plainBg;
197 unsigned pattern5 = patternArea[nameArea[5] * 8];
198 pixelPtr[30] = (pattern5 & 0x80) ? fg5 : bg5;
199 pixelPtr[31] = (pattern5 & 0x40) ? fg5 : bg5;
200 pixelPtr[32] = (pattern5 & 0x20) ? fg5 : bg5;
201 pixelPtr[33] = (pattern5 & 0x10) ? fg5 : bg5;
202 pixelPtr[34] = (pattern5 & 0x08) ? fg5 : bg5;
203 pixelPtr[35] = (pattern5 & 0x04) ? fg5 : bg5;
205 Pixel fg6 = (colorPattern & 0x02) ? blinkFg : plainFg;
206 Pixel bg6 = (colorPattern & 0x02) ? blinkBg : plainBg;
207 unsigned pattern6 = patternArea[nameArea[6] * 8];
208 pixelPtr[36] = (pattern6 & 0x80) ? fg6 : bg6;
209 pixelPtr[37] = (pattern6 & 0x40) ? fg6 : bg6;
210 pixelPtr[38] = (pattern6 & 0x20) ? fg6 : bg6;
211 pixelPtr[39] = (pattern6 & 0x10) ? fg6 : bg6;
212 pixelPtr[40] = (pattern6 & 0x08) ? fg6 : bg6;
213 pixelPtr[41] = (pattern6 & 0x04) ? fg6 : bg6;
215 Pixel fg7 = (colorPattern & 0x01) ? blinkFg : plainFg;
216 Pixel bg7 = (colorPattern & 0x01) ? blinkBg : plainBg;
217 unsigned pattern7 = patternArea[nameArea[7] * 8];
218 pixelPtr[42] = (pattern7 & 0x80) ? fg7 : bg7;
219 pixelPtr[43] = (pattern7 & 0x40) ? fg7 : bg7;
220 pixelPtr[44] = (pattern7 & 0x20) ? fg7 : bg7;
221 pixelPtr[45] = (pattern7 & 0x10) ? fg7 : bg7;
222 pixelPtr[46] = (pattern7 & 0x08) ? fg7 : bg7;
223 pixelPtr[47] = (pattern7 & 0x04) ? fg7 : bg7;
229 template <
class Pixel>
230 const byte* CharacterConverter<Pixel>::getNamePtr(
int line,
int scroll)
234 return vram.nameTable.getReadArea(
235 ((line / 8) * 32) | ((scroll & 0x20) ? 0x8000 : 0), 32);
237 template <
class Pixel>
238 void CharacterConverter<Pixel>::renderGraphic1(
239 Pixel* __restrict pixelPtr,
int line) __restrict
241 const byte* patternArea = vram.patternTable.getReadArea(0, 256 * 8);
242 patternArea += line & 7;
243 const byte* colorArea = vram.colorTable.getReadArea(0, 256 / 8);
245 int scroll = vdp.getHorizontalScrollHigh();
246 const byte* namePtr = getNamePtr(line, scroll);
247 for (
unsigned n = 0; n < 32; ++n) {
248 unsigned charcode = namePtr[scroll & 0x1F];
249 unsigned color = colorArea[charcode / 8];
250 Pixel fg = palFg[color >> 4];
251 Pixel bg = palFg[color & 0x0F];
253 unsigned pattern = patternArea[charcode * 8];
254 pixelPtr[0] = (pattern & 0x80) ? fg : bg;
255 pixelPtr[1] = (pattern & 0x40) ? fg : bg;
256 pixelPtr[2] = (pattern & 0x20) ? fg : bg;
257 pixelPtr[3] = (pattern & 0x10) ? fg : bg;
258 pixelPtr[4] = (pattern & 0x08) ? fg : bg;
259 pixelPtr[5] = (pattern & 0x04) ? fg : bg;
260 pixelPtr[6] = (pattern & 0x02) ? fg : bg;
261 pixelPtr[7] = (pattern & 0x01) ? fg : bg;
263 if (!(++scroll & 0x1F)) namePtr = getNamePtr(line, scroll);
267 template <
class Pixel>
268 void CharacterConverter<Pixel>::renderGraphic2(
269 Pixel* __restrict pixelPtr,
int line) __restrict
273 sizeof(
Pixel) == 2 && (reinterpret_cast<uintptr_t>(pixelPtr) & 3);
274 if (misAligned) pixelPtr--;
275 unsigned partial = *pixelPtr;
277 int quarter = ((line / 8) * 32) & ~0xFF;
278 int baseLine = (-1 << 13) | (quarter * 8) | (line & 7);
281 const byte* patternArea = vram.patternTable.getReadArea(quarter * 8, 8 * 256);
282 patternArea += line & 7;
284 int scroll = vdp.getHorizontalScrollHigh();
285 const byte* namePtr = getNamePtr(line, scroll);
287 for (
unsigned n = 0; n < 32; ++n) {
288 unsigned charCode8 = namePtr[scroll & 0x1F] * 8;
289 unsigned pattern = patternArea[charCode8];
290 unsigned index = charCode8 | baseLine;
291 unsigned color = vram.colorTable.readNP(index);
292 Pixel fg = palFg[color >> 4];
293 Pixel bg = palFg[color & 0x0F];
295 if (
sizeof(
Pixel) == 2) {
299 "tst %[PAT],#128\n\t"
301 "orreq r0,r0,%[BG], lsl #16\n\t"
302 "orrne r0,r0,%[FG], lsl #16\n\t"
309 "orreq r1,r1,%[BG], lsl #16\n\t"
310 "orrne r1,r1,%[FG], lsl #16\n\t"
317 "orreq r2,r2,%[BG], lsl #16\n\t"
318 "orrne r2,r2,%[FG], lsl #16\n\t"
325 "orreq r3,r3,%[BG], lsl #16\n\t"
326 "orrne r3,r3,%[FG], lsl #16\n\t"
329 "moveq %[PART],%[BG]\n\t"
330 "movne %[PART],%[FG]\n\t"
331 "stmia %[OUT]!,{r0-r3}\n\t"
332 : [OUT]
"=r" (pixelPtr)
333 , [PART]
"=r" (partial)
336 , [PAT]
"r" (pattern)
337 , [FG]
"r" (
unsigned(fg))
338 , [BG]
"r" (
unsigned(bg))
339 :
"r0",
"r1",
"r2",
"r3",
"memory"
343 "tst %[PAT],#128\n\t"
349 "orreq r0,r0,%[BG], lsl #16\n\t"
350 "orrne r0,r0,%[FG], lsl #16\n\t"
357 "orreq r1,r1,%[BG], lsl #16\n\t"
358 "orrne r1,r1,%[FG], lsl #16\n\t"
365 "orreq r2,r2,%[BG], lsl #16\n\t"
366 "orrne r2,r2,%[FG], lsl #16\n\t"
373 "orreq r3,r3,%[BG], lsl #16\n\t"
374 "orrne r3,r3,%[FG], lsl #16\n\t"
375 "stmia %[OUT]!,{r0-r3}\n\t"
377 : [OUT]
"=r" (pixelPtr)
379 , [PAT]
"r" (pattern)
380 , [FG]
"r" (
unsigned(fg))
381 , [BG]
"r" (
unsigned(bg))
382 :
"r0",
"r1",
"r2",
"r3",
"memory"
387 pixelPtr[0] = (pattern & 0x80) ? fg : bg;
388 pixelPtr[1] = (pattern & 0x40) ? fg : bg;
389 pixelPtr[2] = (pattern & 0x20) ? fg : bg;
390 pixelPtr[3] = (pattern & 0x10) ? fg : bg;
391 pixelPtr[4] = (pattern & 0x08) ? fg : bg;
392 pixelPtr[5] = (pattern & 0x04) ? fg : bg;
393 pixelPtr[6] = (pattern & 0x02) ? fg : bg;
394 pixelPtr[7] = (pattern & 0x01) ? fg : bg;
399 if (!(++scroll & 0x1F)) namePtr = getNamePtr(line, scroll);
403 *pixelPtr =
static_cast<Pixel>(partial);
408 template <
class Pixel>
409 void CharacterConverter<Pixel>::renderMultiHelper(
410 Pixel* __restrict pixelPtr,
int line,
411 int mask,
int patternQuarter) __restrict
413 unsigned baseLine = mask | ((line / 4) & 7);
414 unsigned scroll = vdp.getHorizontalScrollHigh();
415 const byte* namePtr = getNamePtr(line, scroll);
416 for (
unsigned n = 0; n < 32; ++n) {
417 unsigned patternNr = patternQuarter | namePtr[scroll & 0x1F];
418 unsigned color = vram.patternTable.readNP((patternNr * 8) | baseLine);
419 Pixel cl = palFg[color >> 4];
420 Pixel cr = palFg[color & 0x0F];
421 pixelPtr[0] = cl; pixelPtr[1] = cl;
422 pixelPtr[2] = cl; pixelPtr[3] = cl;
423 pixelPtr[4] = cr; pixelPtr[5] = cr;
424 pixelPtr[6] = cr; pixelPtr[7] = cr;
426 if (!(++scroll & 0x1F)) namePtr = getNamePtr(line, scroll);
429 template <
class Pixel>
430 void CharacterConverter<Pixel>::renderMulti(
431 Pixel* __restrict pixelPtr,
int line) __restrict
433 int mask = (-1 << 11);
434 renderMultiHelper(pixelPtr, line, mask, 0);
437 template <
class Pixel>
438 void CharacterConverter<Pixel>::renderMultiQ(
439 Pixel* __restrict pixelPtr,
int line) __restrict
441 int mask = (-1 << 13);
442 int patternQuarter = (line * 4) & ~0xFF;
443 renderMultiHelper(pixelPtr, line, mask, patternQuarter);
446 template <
class Pixel>
447 void CharacterConverter<Pixel>::renderBogus(
448 Pixel* __restrict pixelPtr) __restrict
450 Pixel fg = palFg[vdp.getForegroundColor()];
451 Pixel bg = palFg[vdp.getBackgroundColor()];
452 for (
int n = 8; n--; ) *pixelPtr++ = bg;
453 for (
int c = 20; c--; ) {
454 for (
int n = 4; n--; ) *pixelPtr++ = fg;
455 for (
int n = 2; n--; ) *pixelPtr++ = bg;
457 for (
int n = 8; n--; ) *pixelPtr++ = bg;
462 template class CharacterConverter<word>;
464 #if HAVE_32BPP || COMPONENT_GL
465 template class CharacterConverter<unsigned>;