1 /*
2 * viciivsid-draw.c - Rendering for the MOS6569 (VIC-II) emulation.
3 *
4 * Written by
5 * Andreas Boose <viceteam@t-online.de>
6 * Ettore Perazzoli <ettore@comm2000.it>
7 *
8 * This file is part of VICE, the Versatile Commodore Emulator.
9 * See README for copyright notice.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 * 02111-1307 USA.
25 *
26 */
27
28 #include "vice.h"
29
30 #include <string.h>
31
32 #include "raster-cache-fill.h"
33 #include "raster-cache-fill-1fff.h"
34 #include "raster-cache-fill-39ff.h"
35 #include "raster-cache-text-ext.h"
36 #include "raster-cache-text-std.h"
37 #include "raster-cache.h"
38 #include "raster-modes.h"
39 #include "raster.h"
40 #include "types.h"
41 #include "vicii-draw.h"
42 #include "viciitypes.h"
43 #include "viewport.h"
44
45
46 #define GFX_MSK_LEFTBORDER_SIZE ((VICII_MAX_SPRITE_WIDTH - VICII_RASTER_X(0) \
47 + vicii.screen_leftborderwidth ) / 8 + 1)
48
49 /* The following tables are used to speed up the drawing. We do not use
50 multi-dimensional arrays as we can optimize better this way... */
51
52 /* foreground(4) | background(4) | nibble(4) -> 4 pixels. */
53 static uint32_t hr_table[16 * 16 * 16];
54
55 /* mc flag(1) | idx(2) | byte(8) -> index into double-pixel table. */
56 static uint8_t mc_table[3 * 256];
57 static uint8_t mcmsktable[256];
58
59
60 /* These functions draw the background from `start_pixel' to `end_pixel'. */
61
draw_std_background(unsigned int start_pixel,unsigned int end_pixel)62 static void draw_std_background(unsigned int start_pixel,
63 unsigned int end_pixel)
64 {
65 uint8_t background_color;
66 unsigned int gfxstart, gfxend;
67
68 background_color = (uint8_t)vicii.raster.background_color;
69
70 if (VICII_IS_ILLEGAL_MODE(vicii.raster.video_mode)) {
71 background_color = 0;
72 }
73
74 gfxstart = vicii.raster.geometry->gfx_position.x + vicii.raster.xsmooth;
75 gfxend = gfxstart + vicii.raster.geometry->gfx_size.width;
76
77 if (start_pixel < gfxstart) {
78 if (end_pixel < gfxstart) {
79 memset(vicii.raster.draw_buffer_ptr + start_pixel,
80 vicii.raster.xsmooth_color,
81 end_pixel - start_pixel + 1);
82 } else {
83 if (end_pixel < gfxend) {
84 memset(vicii.raster.draw_buffer_ptr + start_pixel,
85 vicii.raster.xsmooth_color,
86 gfxstart - start_pixel);
87 memset(vicii.raster.draw_buffer_ptr + gfxstart,
88 background_color,
89 end_pixel - gfxstart + 1);
90 } else {
91 memset(vicii.raster.draw_buffer_ptr + start_pixel,
92 vicii.raster.xsmooth_color,
93 gfxstart - start_pixel);
94 memset(vicii.raster.draw_buffer_ptr + gfxstart,
95 background_color,
96 gfxend - gfxstart);
97 memset(vicii.raster.draw_buffer_ptr + gfxend,
98 vicii.raster.xsmooth_color,
99 end_pixel - gfxend + 1);
100 }
101 }
102 } else {
103 if (start_pixel < gfxend) {
104 if (end_pixel < gfxend) {
105 memset(vicii.raster.draw_buffer_ptr + start_pixel,
106 background_color,
107 end_pixel - start_pixel + 1);
108 } else {
109 memset(vicii.raster.draw_buffer_ptr + start_pixel,
110 background_color,
111 gfxend - start_pixel);
112 memset(vicii.raster.draw_buffer_ptr + gfxend,
113 vicii.raster.xsmooth_color,
114 end_pixel - gfxend + 1);
115 }
116 } else {
117 memset(vicii.raster.draw_buffer_ptr + start_pixel,
118 vicii.raster.xsmooth_color,
119 end_pixel - start_pixel + 1);
120 }
121 }
122
123 if (vicii.raster.xsmooth_shift_right) {
124 int pos;
125
126 pos = (start_pixel - vicii.raster.geometry->gfx_position.x) / 8;
127
128 if (pos >= 0 && pos < VICII_SCREEN_TEXTCOLS) {
129 if (vicii.raster.video_mode == VICII_HIRES_BITMAP_MODE) {
130 background_color = vicii.vbuf[pos] & 0xf;
131 }
132 if (vicii.raster.video_mode == VICII_EXTENDED_TEXT_MODE) {
133 int bg_idx;
134
135 bg_idx = vicii.vbuf[pos] >> 6;
136
137 if (bg_idx > 0) {
138 background_color = vicii.ext_background_color[bg_idx - 1];
139 }
140 }
141 if (VICII_IS_ILLEGAL_MODE(vicii.raster.video_mode)) {
142 background_color = 0;
143 }
144 memset(vicii.raster.draw_buffer_ptr + start_pixel + 8,
145 background_color, vicii.raster.xsmooth_shift_right);
146 }
147 vicii.raster.xsmooth_shift_right = 0;
148 }
149 }
150
draw_idle_std_background(unsigned int start_pixel,unsigned int end_pixel)151 static void draw_idle_std_background(unsigned int start_pixel,
152 unsigned int end_pixel)
153 {
154 memset(vicii.raster.draw_buffer_ptr + start_pixel,
155 vicii.raster.idle_background_color,
156 end_pixel - start_pixel + 1);
157 }
158
159 /* If unaligned 32-bit access is not allowed, the graphics is stored in a
160 temporary aligned buffer, and later copied to the real frame buffer. This
161 is ugly, but should be hopefully faster than accessing 8 bits at a time
162 anyway. */
163
164 #ifndef ALLOW_UNALIGNED_ACCESS
165 static uint32_t _aligned_line_buffer[VICII_SCREEN_XPIX / 2 + 1];
166 static uint8_t *const aligned_line_buffer = (uint8_t *)_aligned_line_buffer;
167 #endif
168
169
170 /* Pointer to the start of the graphics area on the frame buffer. */
171 #define GFX_PTR() \
172 (vicii.raster.draw_buffer_ptr \
173 + (vicii.screen_leftborderwidth + vicii.raster.xsmooth))
174
175 #ifdef ALLOW_UNALIGNED_ACCESS
176 #define ALIGN_DRAW_FUNC(name, xs, xe, gfx_msk_ptr) \
177 name(GFX_PTR(), (xs), (xe), (gfx_msk_ptr))
178 #else
179 #define ALIGN_DRAW_FUNC(name, xs, xe, gfx_msk_ptr) \
180 do { \
181 name(aligned_line_buffer, (xs), (xe), (gfx_msk_ptr)); \
182 memcpy(GFX_PTR() + (xs) * 8, \
183 aligned_line_buffer + (xs) * 8, \
184 ((xe) - (xs) + 1) * 8); \
185 } while (0)
186 #endif
187
188
189 /* Standard text mode. */
190
get_std_text(raster_cache_t * cache,unsigned int * xs,unsigned int * xe,int rr)191 static int get_std_text(raster_cache_t *cache, unsigned int *xs,
192 unsigned int *xe, int rr)
193 {
194 int r;
195
196 if (cache->background_data[0] != vicii.raster.background_color
197 || cache->chargen_ptr != vicii.chargen_ptr) {
198 cache->background_data[0] = vicii.raster.background_color;
199 cache->chargen_ptr = vicii.chargen_ptr;
200 rr = 1;
201 }
202
203 r = raster_cache_data_fill_text(cache->foreground_data,
204 vicii.vbuf,
205 vicii.chargen_ptr + vicii.raster.ycounter,
206 VICII_SCREEN_TEXTCOLS,
207 xs, xe,
208 rr);
209
210 r |= raster_cache_data_fill(cache->color_data_1,
211 vicii.cbuf,
212 VICII_SCREEN_TEXTCOLS,
213 xs, xe,
214 rr);
215 return r;
216 }
217
_draw_std_text(uint8_t * p,unsigned int xs,unsigned int xe,uint8_t * gfx_msk_ptr)218 inline static void _draw_std_text(uint8_t *p, unsigned int xs, unsigned int xe,
219 uint8_t *gfx_msk_ptr)
220 {
221 uint32_t *table_ptr;
222 uint8_t *char_ptr, *msk_ptr;
223 unsigned int i;
224
225 table_ptr = hr_table + (vicii.raster.background_color << 4);
226 char_ptr = vicii.chargen_ptr + vicii.raster.ycounter;
227 msk_ptr = gfx_msk_ptr + GFX_MSK_LEFTBORDER_SIZE;
228
229 for (i = xs; i <= xe; i++) {
230 uint32_t *ptr = table_ptr + (vicii.cbuf[i] << 8);
231 int d = msk_ptr[i] = char_ptr[vicii.vbuf[i] * 8];
232
233 *((uint32_t *)p + i * 2) = ptr[d >> 4];
234 *((uint32_t *)p + i * 2 + 1) = ptr[d & 0xf];
235 }
236 }
237
_draw_std_text_cached(uint8_t * p,unsigned int xs,unsigned int xe,raster_cache_t * cache)238 inline static void _draw_std_text_cached(uint8_t *p, unsigned int xs,
239 unsigned int xe,
240 raster_cache_t *cache)
241 {
242 uint32_t *table_ptr;
243 uint8_t *msk_ptr, *foreground_data, *color_data;
244 unsigned int i;
245
246 table_ptr = hr_table + (cache->background_data[0] << 4);
247 msk_ptr = cache->gfx_msk + GFX_MSK_LEFTBORDER_SIZE;
248 foreground_data = cache->foreground_data;
249 color_data = cache->color_data_1;
250
251 for (i = xs; i <= xe; i++) {
252 uint32_t *ptr = table_ptr + (color_data[i] << 8);
253 int d = msk_ptr[i] = foreground_data[i];
254
255 *((uint32_t *)p + i * 2) = ptr[d >> 4];
256 *((uint32_t *)p + i * 2 + 1) = ptr[d & 0xf];
257 }
258 }
259
draw_std_text_cached(raster_cache_t * cache,unsigned int xs,unsigned int xe)260 static void draw_std_text_cached(raster_cache_t *cache, unsigned int xs,
261 unsigned int xe)
262 {
263 ALIGN_DRAW_FUNC(_draw_std_text_cached, xs, xe, cache);
264 }
265
draw_std_text(void)266 static void draw_std_text(void)
267 {
268 ALIGN_DRAW_FUNC(_draw_std_text, 0, VICII_SCREEN_TEXTCOLS - 1,
269 vicii.raster.gfx_msk);
270 }
271
272 #define DRAW_STD_TEXT_BYTE(p, b, f) \
273 do { \
274 if ((b) & 0x80) { \
275 *(p) = (f); \
276 } \
277 if ((b) & 0x40) { \
278 *((p) + 1) = (f); \
279 } \
280 if ((b) & 0x20) { \
281 *((p) + 2) = (f); \
282 } \
283 if ((b) & 0x10) { \
284 *((p) + 3) = (f); \
285 } \
286 if ((b) & 0x08) { \
287 *((p) + 4) = (f); \
288 } \
289 if ((b) & 0x04) { \
290 *((p) + 5) = (f); \
291 } \
292 if ((b) & 0x02) { \
293 *((p) + 6) = (f); \
294 } \
295 if ((b) & 0x01) { \
296 *((p) + 7) = (f); \
297 } \
298 } while (0)
299
draw_std_text_foreground(unsigned int start_char,unsigned int end_char)300 static void draw_std_text_foreground(unsigned int start_char, unsigned int end_char)
301 {
302 unsigned int i;
303 uint8_t *char_ptr, *msk_ptr, *p;
304
305 char_ptr = vicii.chargen_ptr + vicii.raster.ycounter;
306 msk_ptr = vicii.raster.gfx_msk + GFX_MSK_LEFTBORDER_SIZE;
307 p = GFX_PTR() + 8 * start_char;
308
309 for (i = start_char; i <= end_char; i++, p += 8) {
310 uint8_t b, f;
311
312 b = char_ptr[vicii.vbuf[i - vicii.buf_offset] * 8];
313
314 if (vicii.raster.last_video_mode == VICII_EXTENDED_TEXT_MODE) {
315 b = char_ptr[(vicii.vbuf[i - vicii.buf_offset] & 0x3f) * 8];
316 }
317
318 if (vicii.raster.last_video_mode == VICII_HIRES_BITMAP_MODE) {
319 unsigned int j = ((vicii.memptr << 3) + vicii.raster.ycounter + i * 8) & 0x1fff;
320 if (j & 0x1000) {
321 b = vicii.bitmap_high_ptr[j & 0xfff];
322 } else {
323 b = vicii.bitmap_low_ptr[j];
324 }
325 }
326
327 f = vicii.cbuf[i - vicii.buf_offset];
328
329 if (vicii.raster.xsmooth_shift_left > 0) {
330 b = (b >> vicii.raster.xsmooth_shift_left) << vicii.raster.xsmooth_shift_left;
331 }
332
333 msk_ptr[i] = b;
334 DRAW_STD_TEXT_BYTE(p, b, f);
335 }
336 }
337
338 /* Hires Bitmap mode. */
339
get_hires_bitmap(raster_cache_t * cache,unsigned int * xs,unsigned int * xe,int rr)340 static int get_hires_bitmap(raster_cache_t *cache, unsigned int *xs, unsigned int *xe, int rr)
341 {
342 int r;
343
344 r = raster_cache_data_fill(cache->background_data,
345 vicii.vbuf,
346 VICII_SCREEN_TEXTCOLS,
347 xs, xe,
348 rr);
349 r |= raster_cache_data_fill_1fff(cache->foreground_data,
350 vicii.bitmap_low_ptr,
351 vicii.bitmap_high_ptr,
352 vicii.memptr * 8 + vicii.raster.ycounter,
353 VICII_SCREEN_TEXTCOLS,
354 xs, xe,
355 rr);
356 return r;
357 }
358
_draw_hires_bitmap(uint8_t * p,unsigned int xs,unsigned int xe,uint8_t * gfx_msk_ptr)359 inline static void _draw_hires_bitmap(uint8_t *p, unsigned int xs,
360 unsigned int xe, uint8_t *gfx_msk_ptr)
361 {
362 uint8_t *bmptr_low, *bmptr_high, *msk_ptr;
363 uint8_t bmval;
364 unsigned int i, j;
365
366 bmptr_low = vicii.bitmap_low_ptr;
367 bmptr_high = vicii.bitmap_high_ptr;
368 msk_ptr = gfx_msk_ptr + GFX_MSK_LEFTBORDER_SIZE;
369
370 for (j = ((vicii.memptr << 3) + vicii.raster.ycounter + xs * 8) & 0x1fff, i = xs;
371 i <= xe; i++, j = (j + 8) & 0x1fff) {
372 uint32_t *ptr = hr_table + (vicii.vbuf[i] << 4);
373 int d;
374
375 if (j & 0x1000) {
376 bmval = bmptr_high[j & 0xfff];
377 } else {
378 bmval = bmptr_low[j];
379 }
380
381 d = msk_ptr[i] = bmval;
382 *((uint32_t *)p + i * 2) = ptr[d >> 4];
383 *((uint32_t *)p + i * 2 + 1) = ptr[d & 0xf];
384 }
385 }
386
_draw_hires_bitmap_cached(uint8_t * p,unsigned int xs,unsigned int xe,raster_cache_t * cache)387 inline static void _draw_hires_bitmap_cached(uint8_t *p, unsigned int xs,
388 unsigned int xe,
389 raster_cache_t *cache)
390 {
391 uint8_t *foreground_data, *background_data, *msk_ptr;
392 unsigned int i;
393
394 foreground_data = cache->foreground_data;
395 background_data = cache->background_data;
396 msk_ptr = cache->gfx_msk + GFX_MSK_LEFTBORDER_SIZE;
397
398 for (i = xs; i <= xe; i++) {
399 uint32_t *ptr = hr_table + (background_data[i] << 4);
400 int d;
401
402 d = msk_ptr[i] = foreground_data[i];
403 *((uint32_t *)p + i * 2) = ptr[d >> 4];
404 *((uint32_t *)p + i * 2 + 1) = ptr[d & 0xf];
405 }
406 }
407
draw_hires_bitmap(void)408 static void draw_hires_bitmap(void)
409 {
410 ALIGN_DRAW_FUNC(_draw_hires_bitmap, 0, VICII_SCREEN_TEXTCOLS - 1,
411 vicii.raster.gfx_msk);
412 }
413
draw_hires_bitmap_cached(raster_cache_t * cache,unsigned int xs,unsigned int xe)414 static void draw_hires_bitmap_cached(raster_cache_t *cache, unsigned int xs,
415 unsigned int xe)
416 {
417 ALIGN_DRAW_FUNC(_draw_hires_bitmap_cached, xs, xe, cache);
418 }
419
_draw_hires_bitmap_foreground(uint8_t * p,unsigned int xs,unsigned int xe,uint8_t * gfx_msk_ptr)420 inline static void _draw_hires_bitmap_foreground(uint8_t *p, unsigned int xs,
421 unsigned int xe,
422 uint8_t *gfx_msk_ptr)
423 {
424 uint8_t *bmptr_low, *bmptr_high, *msk_ptr;
425 uint8_t bmval;
426 unsigned int i, j;
427
428 bmptr_low = vicii.bitmap_low_ptr;
429 bmptr_high = vicii.bitmap_high_ptr;
430 msk_ptr = gfx_msk_ptr + GFX_MSK_LEFTBORDER_SIZE;
431
432 for (j = ((vicii.memptr << 3) + vicii.raster.ycounter + xs * 8) & 0x1fff, i = xs;
433 i <= xe; i++, j = (j + 8) & 0x1fff) {
434 uint32_t *ptr = hr_table + (vicii.vbuf[i - vicii.buf_offset] << 4);
435 int d;
436
437 if (vicii.raster.last_video_mode == VICII_ILLEGAL_BITMAP_MODE_1) {
438 j &= 0x19ff;
439 }
440
441 if (j & 0x1000) {
442 bmval = bmptr_high[j & 0xfff];
443 } else {
444 bmval = bmptr_low[j];
445 }
446
447 if (vicii.raster.last_video_mode == VICII_NORMAL_TEXT_MODE) {
448 uint8_t *char_ptr = vicii.chargen_ptr + vicii.raster.ycounter;
449 bmval = char_ptr[vicii.vbuf[i - vicii.buf_offset] * 8];
450 }
451
452 d = msk_ptr[i] = bmval;
453
454 *((uint32_t *)p + i * 2) = ptr[d >> 4];
455 *((uint32_t *)p + i * 2 + 1) = ptr[d & 0xf];
456 }
457 }
458
draw_hires_bitmap_foreground(unsigned int start_char,unsigned int end_char)459 static void draw_hires_bitmap_foreground(unsigned int start_char,
460 unsigned int end_char)
461 {
462 ALIGN_DRAW_FUNC(_draw_hires_bitmap_foreground, start_char, end_char,
463 vicii.raster.gfx_msk);
464 }
465
466 /* Multicolor text mode. */
467
get_mc_text(raster_cache_t * cache,unsigned int * xs,unsigned int * xe,int rr)468 static int get_mc_text(raster_cache_t *cache, unsigned int *xs,
469 unsigned int *xe, int rr)
470 {
471 int r;
472
473 if (cache->background_data[0] != vicii.raster.background_color
474 || cache->color_data_1[0] != vicii.ext_background_color[0]
475 || cache->color_data_1[1] != vicii.ext_background_color[1]
476 || cache->chargen_ptr != vicii.chargen_ptr) {
477 cache->background_data[0] = vicii.raster.background_color;
478 cache->color_data_1[0] = vicii.ext_background_color[0];
479 cache->color_data_1[1] = vicii.ext_background_color[1];
480 cache->chargen_ptr = vicii.chargen_ptr;
481 rr = 1;
482 }
483
484 r = raster_cache_data_fill_text(cache->foreground_data,
485 vicii.vbuf,
486 vicii.chargen_ptr + vicii.raster.ycounter,
487 VICII_SCREEN_TEXTCOLS,
488 xs, xe,
489 rr);
490 r |= raster_cache_data_fill(cache->color_data_3,
491 vicii.cbuf,
492 VICII_SCREEN_TEXTCOLS,
493 xs, xe,
494 rr);
495 return r;
496 }
497
_draw_mc_text(uint8_t * p,unsigned int xs,unsigned int xe,uint8_t * gfx_msk_ptr)498 inline static void _draw_mc_text(uint8_t *p, unsigned int xs, unsigned int xe,
499 uint8_t *gfx_msk_ptr)
500 {
501 uint8_t c[8];
502 uint32_t *table_ptr;
503 uint8_t *char_ptr, *msk_ptr;
504 uint16_t *ptmp;
505 unsigned int i;
506
507 table_ptr = hr_table + (vicii.raster.background_color << 4);
508 char_ptr = vicii.chargen_ptr + vicii.raster.ycounter;
509 msk_ptr = gfx_msk_ptr + GFX_MSK_LEFTBORDER_SIZE;
510
511 c[1] = c[0] = vicii.raster.background_color;
512 c[3] = c[2] = vicii.ext_background_color[0];
513 c[5] = c[4] = vicii.ext_background_color[1];
514
515 ptmp = (uint16_t *)(p + xs * 8);
516
517 for (i = xs; i <= xe; i++) {
518 if (vicii.cbuf[i] & 0x8) {
519 unsigned int d;
520
521 c[7] = c[6] = vicii.cbuf[i] & 0x7;
522
523 d = char_ptr[vicii.vbuf[i] * 8];
524
525 msk_ptr[i] = mcmsktable[d];
526
527 ptmp[0] = ((uint16_t *)c)[mc_table[d]];
528 ptmp[1] = ((uint16_t *)c)[mc_table[0x100 + d]];
529 ptmp[2] = ((uint16_t *)c)[mc_table[0x200 + d]];
530 ptmp[3] = ((uint16_t *)c)[d & 3];
531 ptmp += 4;
532 } else {
533 uint32_t *ptr = table_ptr + (vicii.cbuf[i] << 8);
534 int d = msk_ptr[i] = char_ptr[vicii.vbuf[i] * 8];
535
536 *((uint32_t *)ptmp) = ptr[d >> 4];
537 *((uint32_t *)(ptmp + 2)) = ptr[d & 0xf];
538 ptmp += 4;
539 }
540 }
541 }
542
_draw_mc_text_cached(uint8_t * p,unsigned int xs,unsigned int xe,raster_cache_t * cache)543 inline static void _draw_mc_text_cached(uint8_t *p, unsigned int xs, unsigned int xe, raster_cache_t *cache)
544 {
545 uint8_t c[8];
546 uint32_t *table_ptr;
547 uint8_t *foreground_data, *color_data_3, *msk_ptr;
548 uint16_t *ptmp;
549 unsigned int i;
550
551 foreground_data = cache->foreground_data;
552 color_data_3 = cache->color_data_3;
553 table_ptr = hr_table + (cache->background_data[0] << 4);
554 msk_ptr = cache->gfx_msk + GFX_MSK_LEFTBORDER_SIZE;
555
556 c[1] = c[0] = cache->background_data[0];
557 c[3] = c[2] = cache->color_data_1[0];
558 c[5] = c[4] = cache->color_data_1[1];
559
560 ptmp = (uint16_t *)(p + xs * 8);
561
562 for (i = xs; i <= xe; i++) {
563 if (color_data_3[i] & 0x8) {
564 unsigned int d;
565
566 c[7] = c[6] = color_data_3[i] & 0x7;
567
568 d = foreground_data[i];
569
570 msk_ptr[i] = mcmsktable[d];
571
572 ptmp[0] = ((uint16_t *)c)[mc_table[d]];
573 ptmp[1] = ((uint16_t *)c)[mc_table[0x100 + d]];
574 ptmp[2] = ((uint16_t *)c)[mc_table[0x200 + d]];
575 ptmp[3] = ((uint16_t *)c)[d & 3];
576 ptmp += 4;
577 } else {
578 uint32_t *ptr = table_ptr + (color_data_3[i] << 8);
579 int d = msk_ptr[i] = foreground_data[i];
580
581 *((uint32_t *)ptmp) = ptr[d >> 4];
582 *((uint32_t *)(ptmp + 2)) = ptr[d & 0xf];
583 ptmp += 4;
584 }
585 }
586 }
587
draw_mc_text(void)588 static void draw_mc_text(void)
589 {
590 ALIGN_DRAW_FUNC(_draw_mc_text, 0, VICII_SCREEN_TEXTCOLS - 1,
591 vicii.raster.gfx_msk);
592 }
593
draw_mc_text_cached(raster_cache_t * cache,unsigned int xs,unsigned int xe)594 static void draw_mc_text_cached(raster_cache_t *cache, unsigned int xs,
595 unsigned int xe)
596 {
597 ALIGN_DRAW_FUNC(_draw_mc_text_cached, xs, xe, cache);
598 }
599
600 /* FIXME: aligned/unaligned versions. */
601 #define DRAW_MC_BYTE(p, b, f1, f2, f3) \
602 do { \
603 if ((b) & 0x80) { \
604 if ((b) & 0x40) { \
605 *(p) = *((p) + 1) = (f3); \
606 } else { \
607 *(p) = *((p) + 1) = (f2); \
608 } \
609 } else if ((b) & 0x40) { \
610 *(p) = *((p) + 1) = (f1); \
611 } \
612 \
613 if ((b) & 0x20) { \
614 if ((b) & 0x10) { \
615 *((p) + 2) = *((p) + 3) = (f3); \
616 } else { \
617 *((p) + 2) = *((p) + 3) = (f2); \
618 } \
619 } else if ((b) & 0x10) { \
620 *((p) + 2) = *((p) + 3) = (f1); \
621 } \
622 \
623 if ((b) & 0x08) { \
624 if ((b) & 0x04) { \
625 *((p) + 4) = *((p) + 5) = (f3); \
626 } else { \
627 *((p) + 4) = *((p) + 5) = (f2); \
628 } \
629 } else if ((b) & 0x04) { \
630 *((p) + 4) = *((p) + 5) = (f1); \
631 } \
632 \
633 if ((b) & 0x02) { \
634 if ((b) & 0x01) { \
635 *((p) + 6) = *((p) + 7) = (f3); \
636 } else { \
637 *((p) + 6) = *((p) + 7) = (f2); \
638 } \
639 } else if ((b) & 0x01) { \
640 *((p) + 6) = *((p) + 7) = (f1); \
641 } \
642 } while (0)
643
draw_mc_text_foreground(unsigned int start_char,unsigned int end_char)644 static void draw_mc_text_foreground(unsigned int start_char, unsigned int end_char)
645 {
646 uint8_t *char_ptr, *msk_ptr;
647 uint8_t c1, c2;
648 uint8_t *p;
649 unsigned int i;
650
651 char_ptr = vicii.chargen_ptr + vicii.raster.ycounter;
652 msk_ptr = vicii.raster.gfx_msk + GFX_MSK_LEFTBORDER_SIZE;
653 c1 = vicii.ext_background_color[0];
654 c2 = vicii.ext_background_color[1];
655 p = GFX_PTR() + 8 * start_char;
656
657 for (i = start_char; i <= end_char; i++, p += 8) {
658 uint8_t b, c;
659
660 c = vicii.cbuf[i - vicii.buf_offset];
661 if (vicii.raster.last_video_mode == VICII_MULTICOLOR_BITMAP_MODE) {
662 unsigned int j = ((vicii.memptr << 3) + vicii.raster.ycounter + i * 8) & 0x1fff;
663 if (j & 0x1000) {
664 b = vicii.bitmap_high_ptr[j & 0xfff];
665 } else {
666 b = vicii.bitmap_low_ptr[j];
667 }
668 } else {
669 b = char_ptr[vicii.vbuf[i - vicii.buf_offset] * 8];
670 }
671
672 if (c & 0x8) {
673 uint8_t c3;
674 uint8_t orig_background = *p;
675
676 c3 = c & 0x7;
677 DRAW_MC_BYTE(p, b, c1, c2, c3);
678 msk_ptr[i] = mcmsktable[b];
679
680 if (vicii.raster.xsmooth_shift_left > 0) {
681 int j;
682
683 for (j = 0; j < vicii.raster.xsmooth_shift_left; j++) {
684 p[7 - j] = orig_background;
685 }
686
687 msk_ptr[i] = (uint8_t)((mcmsktable[b]
688 >> vicii.raster.xsmooth_shift_left)
689 << vicii.raster.xsmooth_shift_left);
690 }
691 } else {
692 uint8_t c3;
693
694 if (vicii.raster.xsmooth_shift_left > 0) {
695 b = (b >> vicii.raster.xsmooth_shift_left) << vicii.raster.xsmooth_shift_left;
696 }
697
698 c3 = c;
699 DRAW_STD_TEXT_BYTE(p, b, c3);
700 msk_ptr[i] = b;
701 }
702 }
703 }
704
705 /* Multicolor Bitmap Mode. */
706
get_mc_bitmap(raster_cache_t * cache,unsigned int * xs,unsigned int * xe,int rr)707 static int get_mc_bitmap(raster_cache_t *cache, unsigned int *xs,
708 unsigned int *xe, int rr)
709 {
710 int r;
711
712 if (cache->background_data[0] != vicii.raster.background_color) {
713 cache->background_data[0] = vicii.raster.background_color;
714 rr = 1;
715 }
716
717 r = raster_cache_data_fill(cache->color_data_1,
718 vicii.vbuf,
719 VICII_SCREEN_TEXTCOLS,
720 xs, xe,
721 rr);
722 r |= raster_cache_data_fill(cache->color_data_3,
723 vicii.cbuf,
724 VICII_SCREEN_TEXTCOLS,
725 xs, xe,
726 rr);
727 r |= raster_cache_data_fill_1fff(cache->foreground_data,
728 vicii.bitmap_low_ptr,
729 vicii.bitmap_high_ptr,
730 8 * vicii.memptr + vicii.raster.ycounter,
731 VICII_SCREEN_TEXTCOLS,
732 xs, xe,
733 rr);
734 return r;
735 }
736
_draw_mc_bitmap(uint8_t * p,unsigned int xs,unsigned int xe,uint8_t * gfx_msk_ptr)737 inline static void _draw_mc_bitmap(uint8_t *p, unsigned int xs, unsigned int xe,
738 uint8_t *gfx_msk_ptr)
739 {
740 uint8_t *colptr, *bmptr_low, *bmptr_high, *msk_ptr, *ptmp;
741 uint8_t c[4];
742 unsigned int i, j;
743
744 colptr = vicii.cbuf;
745 bmptr_low = vicii.bitmap_low_ptr;
746 bmptr_high = vicii.bitmap_high_ptr;
747 msk_ptr = gfx_msk_ptr + GFX_MSK_LEFTBORDER_SIZE;
748
749 c[0] = vicii.raster.background_color;
750
751 ptmp = p + xs * 8;
752
753 for (j = ((vicii.memptr << 3) + vicii.raster.ycounter + xs * 8) & 0x1fff,
754 i = xs; i <= xe; i++, j = (j + 8) & 0x1fff) {
755 unsigned int d;
756
757 if (j & 0x1000) {
758 d = bmptr_high[j & 0xfff];
759 } else {
760 d = bmptr_low[j];
761 }
762
763 msk_ptr[i] = mcmsktable[d];
764
765 c[1] = vicii.vbuf[i] >> 4;
766 c[2] = vicii.vbuf[i] & 0xf;
767 c[3] = colptr[i];
768
769 ptmp[1] = ptmp[0] = c[mc_table[d]];
770 ptmp[3] = ptmp[2] = c[mc_table[0x100 + d]];
771 ptmp[5] = ptmp[4] = c[mc_table[0x200 + d]];
772 ptmp[7] = ptmp[6] = c[d & 3];
773 ptmp += 8;
774 }
775 }
776
_draw_mc_bitmap_cached(uint8_t * p,unsigned int xs,unsigned int xe,raster_cache_t * cache)777 inline static void _draw_mc_bitmap_cached(uint8_t *p, unsigned int xs,
778 unsigned int xe,
779 raster_cache_t *cache)
780 {
781 uint8_t *foreground_data, *color_data_1, *color_data_3;
782 uint8_t *msk_ptr, *ptmp;
783 uint8_t c[4];
784 unsigned int i;
785
786 foreground_data = cache->foreground_data;
787 color_data_1 = cache->color_data_1;
788 color_data_3 = cache->color_data_3;
789 msk_ptr = cache->gfx_msk + GFX_MSK_LEFTBORDER_SIZE;
790
791 c[0] = cache->background_data[0];
792
793 ptmp = p + xs * 8;
794
795 for (i = xs; i <= xe; i++) {
796 unsigned int d;
797
798 d = foreground_data[i];
799
800 msk_ptr[i] = mcmsktable[d];
801
802 c[1] = color_data_1[i] >> 4;
803 c[2] = color_data_1[i] & 0xf;
804 c[3] = color_data_3[i];
805
806 ptmp[1] = ptmp[0] = c[mc_table[d]];
807 ptmp[3] = ptmp[2] = c[mc_table[0x100 + d]];
808 ptmp[5] = ptmp[4] = c[mc_table[0x200 + d]];
809 ptmp[7] = ptmp[6] = c[d & 3];
810 ptmp += 8;
811 }
812 }
813
draw_mc_bitmap(void)814 static void draw_mc_bitmap(void)
815 {
816 _draw_mc_bitmap(GFX_PTR(), 0, VICII_SCREEN_TEXTCOLS - 1,
817 vicii.raster.gfx_msk);
818 }
819
draw_mc_bitmap_cached(raster_cache_t * cache,unsigned int xs,unsigned int xe)820 static void draw_mc_bitmap_cached(raster_cache_t *cache, unsigned int xs,
821 unsigned int xe)
822 {
823 _draw_mc_bitmap_cached(GFX_PTR(), xs, xe, cache);
824 }
825
draw_mc_bitmap_foreground(unsigned int start_char,unsigned int end_char)826 static void draw_mc_bitmap_foreground(unsigned int start_char,
827 unsigned int end_char)
828 {
829 uint8_t *p, *bmptr_low, *bmptr_high, *msk_ptr;
830 unsigned int i, j;
831
832 p = GFX_PTR() + 8 * start_char;
833 bmptr_low = vicii.bitmap_low_ptr;
834 bmptr_high = vicii.bitmap_high_ptr;
835 msk_ptr = vicii.raster.gfx_msk + GFX_MSK_LEFTBORDER_SIZE;
836
837 for (j = ((vicii.memptr << 3) + vicii.raster.ycounter + 8 * start_char) & 0x1fff,
838 i = start_char; i <= end_char; j = (j + 8) & 0x1fff, i++, p += 8) {
839 uint8_t c1, c2, c3;
840 uint8_t b;
841 uint8_t orig_background = *p;
842
843 c1 = vicii.vbuf[i - vicii.buf_offset] >> 4;
844 c2 = vicii.vbuf[i - vicii.buf_offset] & 0xf;
845 c3 = vicii.cbuf[i - vicii.buf_offset];
846
847 if (vicii.raster.last_video_mode == VICII_ILLEGAL_BITMAP_MODE_2) {
848 j &= 0x19ff;
849 }
850
851 if (j & 0x1000) {
852 b = bmptr_high[j & 0xfff];
853 } else {
854 b = bmptr_low[j];
855 }
856
857 if (vicii.raster.last_video_mode == VICII_MULTICOLOR_TEXT_MODE
858 || vicii.raster.last_video_mode == VICII_ILLEGAL_TEXT_MODE) {
859 uint8_t *char_ptr = vicii.chargen_ptr + vicii.raster.ycounter;
860 b = char_ptr[vicii.vbuf[i - vicii.buf_offset] * 8];
861 }
862
863 msk_ptr[i] = mcmsktable[b];
864 DRAW_MC_BYTE(p, b, c1, c2, c3);
865
866 if (vicii.raster.xsmooth_shift_left > 0) {
867 int k;
868
869 for (k = 0; k < vicii.raster.xsmooth_shift_left; k++) {
870 p[7 - k] = orig_background;
871 }
872
873 msk_ptr[i] = (uint8_t)((mcmsktable[b]
874 >> vicii.raster.xsmooth_shift_left)
875 << vicii.raster.xsmooth_shift_left);
876 }
877 }
878 }
879
880 /* Extended Text Mode. */
881
get_ext_text(raster_cache_t * cache,unsigned int * xs,unsigned int * xe,int rr)882 static int get_ext_text(raster_cache_t *cache, unsigned int *xs,
883 unsigned int *xe, int rr)
884 {
885 int r;
886
887 if (cache->color_data_2[0] != vicii.raster.background_color
888 || cache->color_data_2[1] != vicii.ext_background_color[0]
889 || cache->color_data_2[2] != vicii.ext_background_color[1]
890 || cache->color_data_2[3] != vicii.ext_background_color[2]
891 || cache->chargen_ptr != vicii.chargen_ptr) {
892 cache->color_data_2[0] = vicii.raster.background_color;
893 cache->color_data_2[1] = vicii.ext_background_color[0];
894 cache->color_data_2[2] = vicii.ext_background_color[1];
895 cache->color_data_2[3] = vicii.ext_background_color[2];
896 cache->chargen_ptr = vicii.chargen_ptr;
897 rr = 1;
898 }
899
900 r = raster_cache_data_fill_text_ext(cache->foreground_data,
901 cache->color_data_3,
902 vicii.vbuf,
903 vicii.chargen_ptr,
904 8,
905 VICII_SCREEN_TEXTCOLS,
906 vicii.raster.ycounter,
907 xs, xe,
908 rr);
909
910 r |= raster_cache_data_fill(cache->color_data_1,
911 vicii.cbuf,
912 VICII_SCREEN_TEXTCOLS,
913 xs, xe,
914 rr);
915 return r;
916 }
917
_draw_ext_text(uint8_t * p,unsigned int xs,unsigned int xe,uint8_t * gfx_msk_ptr)918 inline static void _draw_ext_text(uint8_t *p, unsigned int xs, unsigned int xe,
919 uint8_t *gfx_msk_ptr)
920 {
921 uint8_t *char_ptr, *msk_ptr;
922 unsigned int i;
923
924 char_ptr = vicii.chargen_ptr + vicii.raster.ycounter;
925 msk_ptr = gfx_msk_ptr + GFX_MSK_LEFTBORDER_SIZE;
926
927 for (i = xs; i <= xe; i++) {
928 uint32_t *ptr;
929 int bg_idx;
930 int d;
931
932 ptr = hr_table + (vicii.cbuf[i] << 8);
933 bg_idx = vicii.vbuf[i] >> 6;
934 d = char_ptr[(vicii.vbuf[i] & 0x3f) * 8];
935
936 if (bg_idx == 0) {
937 ptr += vicii.raster.background_color << 4;
938 } else {
939 ptr += vicii.ext_background_color[bg_idx - 1] << 4;
940 }
941
942 msk_ptr[i] = d;
943 *((uint32_t *)p + 2 * i) = ptr[d >> 4];
944 *((uint32_t *)p + 2 * i + 1) = ptr[d & 0xf];
945 }
946 }
947
_draw_ext_text_cached(uint8_t * p,unsigned int xs,unsigned int xe,raster_cache_t * cache)948 inline static void _draw_ext_text_cached(uint8_t *p, unsigned int xs,
949 unsigned int xe,
950 raster_cache_t *cache)
951 {
952 uint8_t *foreground_data, *color_data_1, *color_data_2, *color_data_3;
953 uint8_t *msk_ptr;
954 unsigned int i;
955
956 foreground_data = cache->foreground_data;
957 color_data_1 = cache->color_data_1;
958 color_data_2 = cache->color_data_2;
959 color_data_3 = cache->color_data_3;
960 msk_ptr = cache->gfx_msk + GFX_MSK_LEFTBORDER_SIZE;
961
962 for (i = xs; i <= xe; i++) {
963 uint32_t *ptr;
964 int d;
965
966 ptr = hr_table + (color_data_1[i] << 8);
967 d = foreground_data[i];
968
969 ptr += color_data_2[color_data_3[i]] << 4;
970
971 msk_ptr[i] = d;
972 *((uint32_t *)p + 2 * i) = ptr[d >> 4];
973 *((uint32_t *)p + 2 * i + 1) = ptr[d & 0xf];
974 }
975 }
976
draw_ext_text(void)977 static void draw_ext_text(void)
978 {
979 ALIGN_DRAW_FUNC(_draw_ext_text, 0, VICII_SCREEN_TEXTCOLS - 1,
980 vicii.raster.gfx_msk);
981 }
982
draw_ext_text_cached(raster_cache_t * cache,unsigned int xs,unsigned int xe)983 static void draw_ext_text_cached(raster_cache_t *cache, unsigned int xs,
984 unsigned int xe)
985 {
986 ALIGN_DRAW_FUNC(_draw_ext_text_cached, xs, xe, cache);
987 }
988
draw_ext_text_foreground(unsigned int start_char,unsigned int end_char)989 static void draw_ext_text_foreground(unsigned int start_char,
990 unsigned int end_char)
991 {
992 unsigned int i;
993 uint8_t *char_ptr, *msk_ptr, *p;
994
995 char_ptr = vicii.chargen_ptr + vicii.raster.ycounter;
996 msk_ptr = vicii.raster.gfx_msk + GFX_MSK_LEFTBORDER_SIZE;
997 p = GFX_PTR() + 8 * start_char;
998
999 for (i = start_char; i <= end_char; i++, p += 8) {
1000 uint8_t b, f;
1001 int bg_idx;
1002
1003 b = char_ptr[(vicii.vbuf[i - vicii.buf_offset] & 0x3f) * 8];
1004
1005 if (vicii.raster.last_video_mode == VICII_ILLEGAL_BITMAP_MODE_1) {
1006 unsigned int j = ((vicii.memptr << 3) + vicii.raster.ycounter + i * 8) & 0x19ff;
1007 if (j & 0x1000) {
1008 b = vicii.bitmap_high_ptr[j & 0xfff];
1009 } else {
1010 b = vicii.bitmap_low_ptr[j];
1011 }
1012 }
1013
1014 f = vicii.cbuf[i - vicii.buf_offset];
1015 bg_idx = vicii.vbuf[i - vicii.buf_offset] >> 6;
1016
1017 if (vicii.raster.xsmooth_shift_left > 0) {
1018 b = (b >> vicii.raster.xsmooth_shift_left) << vicii.raster.xsmooth_shift_left;
1019 }
1020
1021 if (bg_idx > 0) {
1022 p[7] = p[6] = p[5] = p[4] = p[3] = p[2] = p[1] = p[0] = vicii.ext_background_color[bg_idx - 1];
1023 }
1024
1025 msk_ptr[i] = b;
1026 DRAW_STD_TEXT_BYTE(p, b, f);
1027 }
1028 }
1029
1030 /* Illegal text mode. */
1031
get_illegal_text(raster_cache_t * cache,unsigned int * xs,unsigned int * xe,int rr)1032 static int get_illegal_text(raster_cache_t *cache, unsigned int *xs,
1033 unsigned int *xe, int rr)
1034 {
1035 int r;
1036
1037 if (cache->chargen_ptr != vicii.chargen_ptr) {
1038 cache->chargen_ptr = vicii.chargen_ptr;
1039 rr = 1;
1040 }
1041
1042 r = raster_cache_data_fill_text_ext(cache->foreground_data,
1043 cache->color_data_3,
1044 vicii.vbuf,
1045 vicii.chargen_ptr,
1046 8,
1047 VICII_SCREEN_TEXTCOLS,
1048 vicii.raster.ycounter,
1049 xs, xe,
1050 rr);
1051
1052 r |= raster_cache_data_fill(cache->color_data_1,
1053 vicii.cbuf,
1054 VICII_SCREEN_TEXTCOLS,
1055 xs, xe,
1056 rr);
1057 return r;
1058 }
1059
_draw_illegal_text(uint8_t * p,unsigned int xs,unsigned int xe,uint8_t * gfx_msk_ptr)1060 inline static void _draw_illegal_text(uint8_t *p, unsigned int xs,
1061 unsigned int xe, uint8_t *gfx_msk_ptr)
1062 {
1063 uint8_t *char_ptr, *msk_ptr;
1064 unsigned int i;
1065
1066 char_ptr = vicii.chargen_ptr + vicii.raster.ycounter;
1067 msk_ptr = gfx_msk_ptr + GFX_MSK_LEFTBORDER_SIZE;
1068
1069 memset(p + 8 * xs, 0, (xe - xs + 1) * 8);
1070
1071 for (i = xs; i <= xe; i++) {
1072 unsigned int d;
1073
1074 d = char_ptr[(vicii.vbuf[i] & 0x3f) * 8];
1075
1076 msk_ptr[i] = (vicii.cbuf[i] & 0x8) ? mcmsktable[d] : d;
1077 }
1078 }
1079
_draw_illegal_text_cached(uint8_t * p,unsigned int xs,unsigned int xe,raster_cache_t * cache)1080 inline static void _draw_illegal_text_cached(uint8_t *p, unsigned int xs,
1081 unsigned int xe,
1082 raster_cache_t *cache)
1083 {
1084 uint8_t *foreground_data, *color_data_1, *msk_ptr;
1085 unsigned int i;
1086
1087 foreground_data = cache->foreground_data;
1088 color_data_1 = cache->color_data_1;
1089 msk_ptr = cache->gfx_msk + GFX_MSK_LEFTBORDER_SIZE;
1090
1091 memset(p + 8 * xs, 0, (xe - xs + 1) * 8);
1092
1093 for (i = xs; i <= xe; i++) {
1094 unsigned int d;
1095
1096 d = foreground_data[i];
1097
1098 msk_ptr[i] = (color_data_1[i] & 0x8) ? mcmsktable[d] : d;
1099 }
1100 }
1101
draw_illegal_text(void)1102 static void draw_illegal_text(void)
1103 {
1104 _draw_illegal_text(GFX_PTR(), 0, VICII_SCREEN_TEXTCOLS - 1,
1105 vicii.raster.gfx_msk);
1106 }
1107
draw_illegal_text_cached(raster_cache_t * cache,unsigned int xs,unsigned int xe)1108 static void draw_illegal_text_cached(raster_cache_t *cache, unsigned int xs,
1109 unsigned int xe)
1110 {
1111 _draw_illegal_text_cached(GFX_PTR(), xs, xe, cache);
1112 }
1113
draw_illegal_text_foreground(unsigned int start_char,unsigned int end_char)1114 static void draw_illegal_text_foreground(unsigned int start_char,
1115 unsigned int end_char)
1116 {
1117 uint8_t *char_ptr, *msk_ptr, *p;
1118 unsigned int i;
1119
1120 char_ptr = vicii.chargen_ptr + vicii.raster.ycounter;
1121 msk_ptr = vicii.raster.gfx_msk + GFX_MSK_LEFTBORDER_SIZE;
1122 p = GFX_PTR() + 8 * start_char;
1123
1124 memset(p, 0, (end_char - start_char + 1) * 8);
1125
1126 for (i = start_char; i <= end_char; i++) {
1127 unsigned int d;
1128
1129 d = char_ptr[(vicii.vbuf[i - vicii.buf_offset] & 0x3f) * 8];
1130
1131 msk_ptr[i] = (vicii.cbuf[i - vicii.buf_offset] & 0x8) ? mcmsktable[d] : d;
1132 }
1133 }
1134
1135 /* Illegal bitmap mode 1. */
1136
get_illegal_bitmap_mode1(raster_cache_t * cache,unsigned int * xs,unsigned int * xe,int rr)1137 static int get_illegal_bitmap_mode1(raster_cache_t *cache, unsigned int *xs,
1138 unsigned int *xe, int rr)
1139 {
1140 int r;
1141
1142 r = raster_cache_data_fill(cache->background_data,
1143 vicii.vbuf,
1144 VICII_SCREEN_TEXTCOLS,
1145 xs, xe,
1146 rr);
1147 r |= raster_cache_data_fill_39ff(cache->foreground_data,
1148 vicii.bitmap_low_ptr,
1149 vicii.bitmap_high_ptr,
1150 vicii.memptr * 8
1151 + vicii.raster.ycounter,
1152 VICII_SCREEN_TEXTCOLS,
1153 8,
1154 xs, xe,
1155 rr);
1156 return r;
1157 }
1158
_draw_illegal_bitmap_mode1(uint8_t * p,unsigned int xs,unsigned int xe,uint8_t * gfx_msk_ptr)1159 inline static void _draw_illegal_bitmap_mode1(uint8_t *p, unsigned int xs,
1160 unsigned int xe,
1161 uint8_t *gfx_msk_ptr)
1162 {
1163 uint8_t *bmptr_low, *bmptr_high, *msk_ptr;
1164 uint8_t bmval;
1165 unsigned int i, j;
1166
1167 bmptr_low = vicii.bitmap_low_ptr;
1168 bmptr_high = vicii.bitmap_high_ptr;
1169 msk_ptr = gfx_msk_ptr + GFX_MSK_LEFTBORDER_SIZE;
1170
1171 memset(p + 8 * xs, 0, (xe - xs + 1) * 8);
1172
1173 for (j = ((vicii.memptr << 3) + vicii.raster.ycounter + xs * 8) & 0x1fff, i = xs;
1174 i <= xe; i++, j = (j + 8) & 0x1fff) {
1175 if (j & 0x1000) {
1176 bmval = bmptr_low[j & 0x9ff];
1177 } else {
1178 bmval = bmptr_high[j & 0x9ff];
1179 }
1180
1181 msk_ptr[i] = bmval;
1182 }
1183 }
1184
_draw_illegal_bitmap_mode1_cached(uint8_t * p,unsigned int xs,unsigned int xe,raster_cache_t * cache)1185 inline static void _draw_illegal_bitmap_mode1_cached(uint8_t *p, unsigned int xs,
1186 unsigned int xe,
1187 raster_cache_t *cache)
1188 {
1189 uint8_t *foreground_data, *msk_ptr;
1190
1191 foreground_data = cache->foreground_data;
1192 msk_ptr = cache->gfx_msk + GFX_MSK_LEFTBORDER_SIZE;
1193
1194 memset(p + 8 * xs, 0, (xe - xs + 1) * 8);
1195 memcpy(msk_ptr + xs, foreground_data + xs, xe - xs + 1);
1196 }
1197
draw_illegal_bitmap_mode1(void)1198 static void draw_illegal_bitmap_mode1(void)
1199 {
1200 _draw_illegal_bitmap_mode1(GFX_PTR(), 0, VICII_SCREEN_TEXTCOLS - 1,
1201 vicii.raster.gfx_msk);
1202 }
1203
draw_illegal_bitmap_mode1_cached(raster_cache_t * cache,unsigned int xs,unsigned int xe)1204 static void draw_illegal_bitmap_mode1_cached(raster_cache_t *cache,
1205 unsigned int xs, unsigned int xe)
1206 {
1207 _draw_illegal_bitmap_mode1_cached(GFX_PTR(), xs, xe, cache);
1208 }
1209
draw_illegal_bitmap_mode1_foreground(unsigned int start_char,unsigned int end_char)1210 static void draw_illegal_bitmap_mode1_foreground(unsigned int start_char,
1211 unsigned int end_char)
1212 {
1213 _draw_illegal_bitmap_mode1(GFX_PTR(), start_char, end_char,
1214 vicii.raster.gfx_msk);
1215 }
1216
1217 /* Illegal bitmap mode 2. */
1218
get_illegal_bitmap_mode2(raster_cache_t * cache,unsigned int * xs,unsigned int * xe,int rr)1219 static int get_illegal_bitmap_mode2(raster_cache_t *cache, unsigned int *xs,
1220 unsigned int *xe, int rr)
1221 {
1222 int r;
1223
1224 r = raster_cache_data_fill(cache->color_data_1,
1225 vicii.vbuf,
1226 VICII_SCREEN_TEXTCOLS,
1227 xs, xe,
1228 rr);
1229 r |= raster_cache_data_fill(cache->color_data_3,
1230 vicii.cbuf,
1231 VICII_SCREEN_TEXTCOLS,
1232 xs, xe,
1233 rr);
1234 r |= raster_cache_data_fill_39ff(cache->foreground_data,
1235 vicii.bitmap_low_ptr,
1236 vicii.bitmap_high_ptr,
1237 vicii.memptr * 8
1238 + vicii.raster.ycounter,
1239 VICII_SCREEN_TEXTCOLS,
1240 8,
1241 xs, xe,
1242 rr);
1243 return r;
1244 }
1245
_draw_illegal_bitmap_mode2(uint8_t * p,unsigned int xs,unsigned int xe,uint8_t * gfx_msk_ptr)1246 inline static void _draw_illegal_bitmap_mode2(uint8_t *p, unsigned int xs,
1247 unsigned int xe,
1248 uint8_t *gfx_msk_ptr)
1249 {
1250 uint8_t *bmptr_low, *bmptr_high, *msk_ptr;
1251 uint8_t bmval;
1252 unsigned int i, j;
1253
1254 bmptr_low = vicii.bitmap_low_ptr;
1255 bmptr_high = vicii.bitmap_high_ptr;
1256 msk_ptr = gfx_msk_ptr + GFX_MSK_LEFTBORDER_SIZE;
1257
1258 memset(p + 8 * xs, 0, (xe - xs + 1) * 8);
1259
1260 for (j = ((vicii.memptr << 3) + vicii.raster.ycounter + xs * 8) & 0x1fff, i = xs;
1261 i <= xe; i++, j = (j + 8) & 0x1fff) {
1262 if (j & 0x1000) {
1263 bmval = bmptr_high[j & 0x9ff];
1264 } else {
1265 bmval = bmptr_low[j & 0x9ff];
1266 }
1267
1268 msk_ptr[i] = mcmsktable[bmval];
1269 }
1270 }
1271
_draw_illegal_bitmap_mode2_cached(uint8_t * p,unsigned int xs,unsigned int xe,raster_cache_t * cache)1272 inline static void _draw_illegal_bitmap_mode2_cached(uint8_t *p, unsigned int xs,
1273 unsigned int xe,
1274 raster_cache_t *cache)
1275 {
1276 uint8_t *foreground_data, *msk_ptr;
1277 unsigned int i;
1278
1279 foreground_data = cache->foreground_data;
1280 msk_ptr = cache->gfx_msk + GFX_MSK_LEFTBORDER_SIZE;
1281
1282 memset(p + 8 * xs, 0, (xe - xs + 1) * 8);
1283
1284 for (i = xs; i <= xe; i++) {
1285 msk_ptr[i] = mcmsktable[foreground_data[i]];
1286 }
1287 }
1288
draw_illegal_bitmap_mode2(void)1289 static void draw_illegal_bitmap_mode2(void)
1290 {
1291 _draw_illegal_bitmap_mode2(GFX_PTR(), 0, VICII_SCREEN_TEXTCOLS - 1,
1292 vicii.raster.gfx_msk);
1293 }
1294
draw_illegal_bitmap_mode2_cached(raster_cache_t * cache,unsigned int xs,unsigned int xe)1295 static void draw_illegal_bitmap_mode2_cached(raster_cache_t *cache,
1296 unsigned int xs, unsigned int xe)
1297 {
1298 _draw_illegal_bitmap_mode2_cached(GFX_PTR(), xs, xe, cache);
1299 }
1300
draw_illegal_bitmap_mode2_foreground(unsigned int start_char,unsigned int end_char)1301 static void draw_illegal_bitmap_mode2_foreground(unsigned int start_char,
1302 unsigned int end_char)
1303 {
1304 _draw_illegal_bitmap_mode2(GFX_PTR(), start_char, end_char,
1305 vicii.raster.gfx_msk);
1306 }
1307
1308 /* Idle state. */
1309
get_idle(raster_cache_t * cache,unsigned int * xs,unsigned int * xe,int rr)1310 static int get_idle(raster_cache_t *cache, unsigned int *xs, unsigned int *xe,
1311 int rr)
1312 {
1313 if (rr
1314 || cache->foreground_data[0] != vicii.idle_data
1315 || cache->color_data_1[0] != vicii.raster.background_color
1316 || cache->color_data_1[1] != vicii.raster.idle_background_color
1317 || cache->color_data_1[2] != vicii.raster.video_mode) {
1318 cache->foreground_data[0] = (uint8_t)vicii.idle_data;
1319 cache->color_data_1[0] = vicii.raster.background_color;
1320 cache->color_data_1[1] = vicii.raster.idle_background_color;
1321 cache->color_data_1[2] = vicii.raster.video_mode;
1322 *xs = 0;
1323 *xe = VICII_SCREEN_TEXTCOLS - 1;
1324 return 1;
1325 } else {
1326 return 0;
1327 }
1328 }
1329
_draw_idle(uint8_t * p,unsigned int xs,unsigned int xe,uint8_t * gfx_msk_ptr)1330 inline static void _draw_idle(uint8_t *p, unsigned int xs, unsigned int xe,
1331 uint8_t *gfx_msk_ptr)
1332 {
1333 uint8_t *msk_ptr;
1334 uint8_t d = 0;
1335 unsigned int i;
1336
1337 if (!vicii.raster.blank_enabled) {
1338 d = (uint8_t)vicii.idle_data;
1339 }
1340
1341 msk_ptr = gfx_msk_ptr + GFX_MSK_LEFTBORDER_SIZE;
1342
1343 if (VICII_IS_TEXT_MODE(vicii.raster.video_mode)) {
1344 /* The foreground color is always black (0). */
1345 unsigned int offs;
1346 uint32_t c1, c2;
1347
1348 offs = vicii.raster.idle_background_color << 4;
1349 c1 = hr_table[offs + (d >> 4)];
1350 c2 = hr_table[offs + (d & 0xf)];
1351
1352 for (i = xs * 8; i <= xe * 8; i += 8) {
1353 *((uint32_t *)(p + i)) = c1;
1354 *((uint32_t *)(p + i + 4)) = c2;
1355 }
1356 memset(msk_ptr + xs, d, xe + 1 - xs);
1357 } else {
1358 if (vicii.raster.video_mode == VICII_MULTICOLOR_BITMAP_MODE) {
1359 /* FIXME: Could be optimized */
1360 uint8_t *ptmp;
1361 uint8_t c[4];
1362
1363 c[0] = vicii.raster.background_color;
1364 c[1] = 0;
1365 c[2] = 0;
1366 c[3] = 0;
1367
1368 ptmp = p + xs * 8;
1369
1370 for (i = xs; i <= xe; i++) {
1371 msk_ptr[i] = mcmsktable[d];
1372
1373 ptmp[1] = ptmp[0] = c[mc_table[d]];
1374 ptmp[3] = ptmp[2] = c[mc_table[0x100 + d]];
1375 ptmp[5] = ptmp[4] = c[mc_table[0x200 + d]];
1376 ptmp[7] = ptmp[6] = c[d & 3];
1377 ptmp += 8;
1378 }
1379 } else {
1380 memset(p + xs * 8, 0, (xe + 1 - xs) * 8);
1381 if (vicii.raster.video_mode == VICII_ILLEGAL_BITMAP_MODE_2) {
1382 memset(msk_ptr + xs, mcmsktable[d], xe + 1 - xs);
1383 } else {
1384 memset(msk_ptr + xs, d, xe + 1 - xs);
1385 }
1386 }
1387 }
1388 }
1389
draw_idle(void)1390 static void draw_idle(void)
1391 {
1392 ALIGN_DRAW_FUNC(_draw_idle, 0, VICII_SCREEN_TEXTCOLS - 1,
1393 vicii.raster.gfx_msk);
1394 }
1395
draw_idle_cached(raster_cache_t * cache,unsigned int xs,unsigned int xe)1396 static void draw_idle_cached(raster_cache_t *cache, unsigned int xs,
1397 unsigned int xe)
1398 {
1399 ALIGN_DRAW_FUNC(_draw_idle, xs, xe, cache->gfx_msk);
1400 }
1401
draw_idle_foreground(unsigned int start_char,unsigned int end_char)1402 static void draw_idle_foreground(unsigned int start_char,
1403 unsigned int end_char)
1404 {
1405 uint8_t *p, *msk_ptr;
1406 uint8_t d = 0;
1407 unsigned int i;
1408
1409 p = GFX_PTR();
1410 msk_ptr = vicii.raster.gfx_msk + GFX_MSK_LEFTBORDER_SIZE;
1411 if (!vicii.raster.blank_enabled) {
1412 d = (uint8_t)vicii.idle_data;
1413 }
1414
1415 if (vicii.raster.xsmooth_shift_left > 0) {
1416 d = (d >> vicii.raster.xsmooth_shift_left) << vicii.raster.xsmooth_shift_left;
1417 }
1418
1419 for (i = start_char; i <= end_char; i++) {
1420 DRAW_STD_TEXT_BYTE(p + i * 8, d, 0);
1421 msk_ptr[i] = d;
1422 }
1423 }
1424
setup_modes(void)1425 static void setup_modes(void)
1426 {
1427 raster_modes_set(vicii.raster.modes, VICII_NORMAL_TEXT_MODE,
1428 get_std_text,
1429 draw_std_text_cached,
1430 draw_std_text,
1431 draw_std_background,
1432 draw_std_text_foreground);
1433
1434 raster_modes_set(vicii.raster.modes, VICII_MULTICOLOR_TEXT_MODE,
1435 get_mc_text,
1436 draw_mc_text_cached,
1437 draw_mc_text,
1438 draw_std_background,
1439 draw_mc_text_foreground);
1440
1441 raster_modes_set(vicii.raster.modes, VICII_HIRES_BITMAP_MODE,
1442 get_hires_bitmap,
1443 draw_hires_bitmap_cached,
1444 draw_hires_bitmap,
1445 draw_std_background,
1446 draw_hires_bitmap_foreground);
1447
1448 raster_modes_set(vicii.raster.modes, VICII_MULTICOLOR_BITMAP_MODE,
1449 get_mc_bitmap,
1450 draw_mc_bitmap_cached,
1451 draw_mc_bitmap,
1452 draw_std_background,
1453 draw_mc_bitmap_foreground);
1454
1455 raster_modes_set(vicii.raster.modes, VICII_EXTENDED_TEXT_MODE,
1456 get_ext_text,
1457 draw_ext_text_cached,
1458 draw_ext_text,
1459 draw_std_background,
1460 draw_ext_text_foreground);
1461
1462 raster_modes_set(vicii.raster.modes, VICII_IDLE_MODE,
1463 get_idle,
1464 draw_idle_cached,
1465 draw_idle,
1466 draw_idle_std_background,
1467 draw_idle_foreground);
1468
1469 raster_modes_set(vicii.raster.modes, VICII_ILLEGAL_TEXT_MODE,
1470 get_illegal_text,
1471 draw_illegal_text_cached,
1472 draw_illegal_text,
1473 draw_std_background,
1474 draw_illegal_text_foreground);
1475
1476 raster_modes_set(vicii.raster.modes, VICII_ILLEGAL_BITMAP_MODE_1,
1477 get_illegal_bitmap_mode1,
1478 draw_illegal_bitmap_mode1_cached,
1479 draw_illegal_bitmap_mode1,
1480 draw_std_background,
1481 draw_illegal_bitmap_mode1_foreground);
1482
1483 raster_modes_set(vicii.raster.modes, VICII_ILLEGAL_BITMAP_MODE_2,
1484 get_illegal_bitmap_mode2,
1485 draw_illegal_bitmap_mode2_cached,
1486 draw_illegal_bitmap_mode2,
1487 draw_std_background,
1488 draw_illegal_bitmap_mode2_foreground);
1489 }
1490
1491 /* Initialize the drawing tables. */
init_drawing_tables(void)1492 static void init_drawing_tables(void)
1493 {
1494 uint32_t i;
1495 unsigned int f, b;
1496
1497 for (i = 0; i <= 0xf; i++) {
1498 for (f = 0; f <= 0xf; f++) {
1499 for (b = 0; b <= 0xf; b++) {
1500 uint8_t fp, bp;
1501 uint8_t *p;
1502 int offset;
1503
1504 fp = f;
1505 bp = b;
1506 offset = (f << 8) | (b << 4);
1507 p = (uint8_t *)(hr_table + offset + i);
1508
1509 p[0] = i & 0x8 ? fp : bp;
1510 p[1] = i & 0x4 ? fp : bp;
1511 p[2] = i & 0x2 ? fp : bp;
1512 p[3] = i & 0x1 ? fp : bp;
1513 }
1514 }
1515 }
1516
1517 for (i = 0; i <= 0xff; i++) {
1518 mc_table[i] = (uint8_t)(i >> 6);
1519 mc_table[i + 0x100] = (uint8_t)((i >> 4) & 0x3);
1520 mc_table[i + 0x200] = (uint8_t)((i >> 2) & 0x3);
1521 mcmsktable[i] = (uint8_t)((i & 0xaa) | ((i & 0xaa) >> 1));
1522 }
1523 }
1524
vicii_draw_init(void)1525 void vicii_draw_init(void)
1526 {
1527 init_drawing_tables();
1528
1529 setup_modes();
1530 }
1531