2 SHARP MZ-2500 Emulator 'EmuZ-2500'
4 Author : Takeda.Toshiya
11 #include "interrupt.h"
16 #define EVENT_BLINK 256
18 #define SCRN_640x400 1
19 #define SCRN_640x200 2
20 #define SCRN_320x200 3
22 void CRTC::initialize()
25 monitor_200line = ((config.monitor_type & 2) != 0);
26 scan_line = scan_tmp = (monitor_200line && config.scan_line);
27 monitor_digital = monitor_tmp = ((config.monitor_type & 1) != 0);
29 // thanks Mr.Sato (http://x1center.org/)
31 frames_per_sec = 60.99;
32 lines_per_frame = 262;
35 frames_per_sec = 55.49;
36 lines_per_frame = 448;
39 set_frames_per_sec(frames_per_sec);
40 set_lines_per_frame(lines_per_frame);
42 // set 16/4096 palette
43 for(int i = 0; i < 16; i++) {
44 uint8_t r, g, b, r8, g8, b8;
51 r = ((i & 0x0a) == 0x0a) ? 255 : ((i & 0x0a) == 2) ? 127 : 0;
52 g = ((i & 0x0c) == 0x0c) ? 255 : ((i & 0x0c) == 4) ? 127 : 0;
53 b = ((i & 0x09) == 0x09) ? 255 : ((i & 0x09) == 1) ? 127 : 0;
54 r8 = (i & 2) ? 255 : 0;
55 g8 = (i & 4) ? 255 : 0;
56 b8 = (i & 1) ? 255 : 0;
60 palette16[i] = RGB_COLOR(r8, g8, b8);
62 palette16[i] = RGB_COLOR(r, g, b);
67 palette4096[i] = RGB_COLOR(r, g, b);
69 for(int i = 0; i < 8; i++) {
70 palette16[i + 16] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0);
72 for(int i = 0; i < 16; i++) {
73 for(int j = 1; j < 8; j++) {
74 priority16[i][j] = j + 16;
76 priority16[i][0] = i; // transparent black
77 priority16[i][8] = 0 + 16; // non transparent black
83 for(int i = 0; i < 256; i++) {
84 palette256[i] = RGB_COLOR(((i & 0x20) ? 128 : 0) | ((i & 2) ? 64 : 0) | ((i & 0x80) ? 32 : 0),
85 ((i & 0x40) ? 128 : 0) | ((i & 4) ? 64 : 0) | ((i & 0x80) ? 32 : 0),
86 ((i & 0x10) ? 128 : 0) | ((i & 1) ? 64 : 0) | ((i & 0x80) ? 32 : 0));
88 for(int i = 0; i < 8; i++) {
89 palette256[i + 256] = RGB_COLOR(((i & 2) ? 255 : 0), ((i & 4) ? 255 : 0), ((i & 1) ? 255 : 0));
91 for(int i = 0; i < 64; i++) {
92 palette256[i + 256 + 16] = RGB_COLOR(((i & 2) ? 64 : 0) | ((i & 0x10) ? 128 : 0),
93 ((i & 4) ? 64 : 0) | ((i & 0x20) ? 128 : 0),
94 ((i & 1) ? 64 : 0) | ((i & 0x08) ? 128 : 0));
96 for(int i = 0; i < 256; i++) {
97 for(int j = 1; j < 16 + 64; j++) {
98 priority256[i][j] = j + 256;
100 priority256[i][0] = i; // transparent black
101 priority256[i][8] = 0 + 256; // non transparent black
102 priority256[i][16] = i; // transparent black (64 colors)
107 // extract cg optimization matrix
108 for(int p1 = 0; p1 < 256; p1++) {
109 for(int p2 = 0; p2 < 256; p2++) {
110 for(int i = 0; i < 8; i++) {
111 cg_matrix0[p1][p2][i] = (p1 & (1 << i) ? 0x01 : 0) | (p2 & (1 << i) ? 0x02 : 0);
112 cg_matrix1[p1][p2][i] = (p1 & (1 << i) ? 0x04 : 0) | (p2 & (1 << i) ? 0x08 : 0);
113 cg_matrix2[p1][p2][i] = (p1 & (1 << i) ? 0x10 : 0) | (p2 & (1 << i) ? 0x20 : 0);
114 cg_matrix3[p1][p2][i] = (p1 & (1 << i) ? 0x40 : 0) | (p2 & (1 << i) ? 0x80 : 0);
120 memset(textreg, 0, sizeof(textreg));
121 memset(cgreg, 0, sizeof(cgreg));
124 cgreg[0x00] = cgreg[0x01] = cgreg[0x02] = cgreg[0x03] = cgreg[0x06] = 0xff;
125 GDEVS = 0; cgreg[0x08] = 0x00; cgreg[0x09] = 0x00;
126 GDEVE = monitor_200line ? 200 : 400; cgreg[0x0a] = GDEVE & 0xff; cgreg[0x0b] = GDEVE >> 8;
127 GDEHS = 0; cgreg[0x0c] = 0x00;
128 GDEHSC = (int)(CPU_CLOCKS * GDEHS / frames_per_sec / lines_per_frame / chars_per_line + 0.5);
129 GDEHE = 80; cgreg[0x0d] = GDEHE;
130 GDEHEC = (int)(CPU_CLOCKS * (GDEHE + 3) / frames_per_sec / lines_per_frame / chars_per_line + 0.5);
132 for(int i = 0; i < 16; i++) {
135 scrn_size = SCRN_320x200;
140 cg_mask256_init = false;
145 latch[0] = latch[1] = latch[2] = latch[3] = 0;
146 hblank = vblank = false;
147 map_init = trans_init = true;
150 register_vline_event(this);
151 register_event(this, EVENT_BLINK, 500000, true, NULL);
154 void CRTC::write_data8(uint32_t addr, uint32_t data)
157 if(cgreg[0x0e] == 0x03) {
159 uint8_t *vram_b1 = ((cgreg[0x18] & 3) == 1) ? vram_b + 0x4000 : vram_g;
160 uint8_t *vram_r1 = ((cgreg[0x18] & 3) == 1) ? vram_r + 0x4000 : vram_i;
163 if((cgreg[5] & 0xc0) == 0x00) {
168 vram_b1[addr] &= ~cgreg[6];
169 vram_b1[addr] |= (cgreg[4] & 1) ? (data & cgreg[0] & cgreg[6]) : 0;
172 vram_r1[addr] &= ~cgreg[6];
173 vram_r1[addr] |= (cgreg[4] & 2) ? (data & cgreg[1] & cgreg[6]) : 0;
178 vram_b[addr] &= ~cgreg[6];
179 vram_b[addr] |= (cgreg[4] & 1) ? (data & cgreg[0] & cgreg[6]) : 0;
182 vram_r[addr] &= ~cgreg[6];
183 vram_r[addr] |= (cgreg[4] & 2) ? (data & cgreg[1] & cgreg[6]) : 0;
186 } else if((cgreg[5] & 0xc0) == 0x40) {
191 vram_b1[addr] &= ~data;
192 vram_b1[addr] |= (cgreg[4] & 1) ? (data & cgreg[0]) : 0;
195 vram_r1[addr] &= ~data;
196 vram_r1[addr] |= (cgreg[4] & 2) ? (data & cgreg[1]) : 0;
201 vram_b[addr] &= ~data;
202 vram_b[addr] |= (cgreg[4] & 1) ? (data & cgreg[0]) : 0;
205 vram_r[addr] &= ~data;
206 vram_r[addr] |= (cgreg[4] & 2) ? (data & cgreg[1]) : 0;
212 if((cgreg[5] & 0xc0) == 0x00) {
215 vram_b[addr] &= ~cgreg[6];
216 vram_b[addr] |= (cgreg[4] & 1) ? (data & cgreg[0] & cgreg[6]) : 0;
219 vram_r[addr] &= ~cgreg[6];
220 vram_r[addr] |= (cgreg[4] & 2) ? (data & cgreg[1] & cgreg[6]) : 0;
223 vram_g[addr] &= ~cgreg[6];
224 vram_g[addr] |= (cgreg[4] & 4) ? (data & cgreg[2] & cgreg[6]) : 0;
227 vram_i[addr] &= ~cgreg[6];
228 vram_i[addr] |= (cgreg[4] & 8) ? (data & cgreg[3] & cgreg[6]) : 0;
230 } else if((cgreg[5] & 0xc0) == 0x40) {
233 vram_b[addr] &= ~data;
234 vram_b[addr] |= (cgreg[4] & 1) ? (data & cgreg[0]) : 0;
237 vram_r[addr] &= ~data;
238 vram_r[addr] |= (cgreg[4] & 2) ? (data & cgreg[1]) : 0;
241 vram_g[addr] &= ~data;
242 vram_g[addr] |= (cgreg[4] & 4) ? (data & cgreg[2]) : 0;
245 vram_i[addr] &= ~data;
246 vram_i[addr] |= (cgreg[4] & 8) ? (data & cgreg[3]) : 0;
252 uint32_t CRTC::read_data8(uint32_t addr)
255 uint8_t b, r, g, i, pl;
257 if(cgreg[0x0e] == 0x03) {
259 b = latch[0] = (addr & 0x4000) ? vram_g[addr & 0x3fff] : vram_b[addr & 0x3fff];
260 r = latch[1] = (addr & 0x4000) ? vram_i[addr & 0x3fff] : vram_r[addr & 0x3fff];
266 b = latch[0] = vram_b[addr];
267 r = latch[1] = vram_r[addr];
268 g = latch[2] = vram_g[addr];
269 i = latch[3] = vram_i[addr];
273 if(cgreg[7] & 0x10) {
274 uint8_t compare = cgreg[7] & 0x0f;
275 uint8_t val = (compare == (((b & 0x80) >> 7) | ((r & 0x80) >> 6) | ((g & 0x80) >> 5) | ((i & 0x80) >> 4))) ? 0x80 : 0;
276 val |= (compare == (((b & 0x40) >> 6) | ((r & 0x40) >> 5) | ((g & 0x40) >> 4) | ((i & 0x40) >> 3))) ? 0x40 : 0;
277 val |= (compare == (((b & 0x20) >> 5) | ((r & 0x20) >> 4) | ((g & 0x20) >> 3) | ((i & 0x20) >> 2))) ? 0x20 : 0;
278 val |= (compare == (((b & 0x10) >> 4) | ((r & 0x10) >> 3) | ((g & 0x10) >> 2) | ((i & 0x10) >> 1))) ? 0x10 : 0;
279 val |= (compare == (((b & 0x08) >> 3) | ((r & 0x08) >> 2) | ((g & 0x08) >> 1) | ((i & 0x08) >> 0))) ? 0x08 : 0;
280 val |= (compare == (((b & 0x04) >> 2) | ((r & 0x04) >> 1) | ((g & 0x04) >> 0) | ((i & 0x04) << 1))) ? 0x04 : 0;
281 val |= (compare == (((b & 0x02) >> 1) | ((r & 0x02) >> 0) | ((g & 0x02) << 1) | ((i & 0x02) << 2))) ? 0x02 : 0;
282 val |= (compare == (((b & 0x01) >> 0) | ((r & 0x01) << 1) | ((g & 0x01) << 2) | ((i & 0x01) << 3))) ? 0x01 : 0;
289 void CRTC::write_io8(uint32_t addr, uint32_t data)
291 uint8_t haddr = (addr >> 8) & 0xff;
292 uint8_t num, r, g, b, prev;
294 switch(addr & 0xff) {
297 num = (haddr & 0x1f) >> 1;
298 r = palette4096r[num];
299 g = palette4096g[num];
300 b = palette4096b[num];
302 g = (data & 0x0f) << 4;
305 b = (data & 0x0f) << 4;
307 if(palette4096r[num] != r || palette4096g[num] != g || palette4096b[num] != b) {
308 palette4096r[num] = r;
309 palette4096g[num] = g;
310 palette4096b[num] = b;
311 palette4096[num] = RGB_COLOR(r, g, b);
314 // never change palette 0
315 //palette4096[0] = 0;
323 prev = cgreg[cgreg_num & 0x1f];
324 cgreg[cgreg_num & 0x1f] = data;
326 switch(cgreg_num & 0x1f) {
329 if((data & 0xc0) == 0x80) {
331 switch(cgreg[0x0e]) {
332 case 0x03: case 0x14: case 0x15: case 0x17: case 0x1d:
333 // clear 0x0000 - 0x4000
337 case 0x94: case 0x95: case 0x97: case 0x9d:
338 // clear 0x4000 - 0x7fff
343 // clear 0x0000 - 0x7fff
347 if(cgreg[5] & 0x01) {
348 memset(vram_b + st, 0, sz);
350 if(cgreg[5] & 0x02) {
351 memset(vram_r + st, 0, sz);
353 if(cgreg[5] & 0x04) {
354 memset(vram_g + st, 0, sz);
356 if(cgreg[5] & 0x08) {
357 memset(vram_i + st, 0, sz);
366 GDEVS = (cgreg[0x08] | ((cgreg[0x09] & 1) << 8));
371 GDEVE = (cgreg[0x0a] | ((cgreg[0x0b] & 1) << 8));
374 GDEHS = cgreg[0x0c] & 0x7f;
375 GDEHSC = (int)(CPU_CLOCKS * GDEHS / frames_per_sec / lines_per_frame / chars_per_line + 0.5);
378 GDEHE = cgreg[0x0d] & 0x7f;
379 GDEHEC = (int)(CPU_CLOCKS * (GDEHE + 3) / frames_per_sec / lines_per_frame / chars_per_line + 0.5);
384 case 0x15: case 0x14: case 0x1d: case 0x95: case 0x94: case 0x9d:
385 map_init |= (scrn_size != SCRN_320x200);
386 scrn_size = SCRN_320x200;
388 case 0x17: case 0x97:
389 map_init |= (scrn_size != SCRN_640x200);
390 scrn_size = SCRN_640x200;
392 case 0x03: case 0x93:
393 map_init |= (scrn_size != SCRN_640x400);
394 scrn_size = SCRN_640x400;
400 map_init |= ((prev & 0x07) != (uint8_t)(data & 0x07));
402 case 0x10: case 0x12: case 0x14: case 0x16:
403 map_init |= (prev != (uint8_t)(data & 0xff));
405 case 0x11: case 0x13: case 0x15:
406 map_init |= ((prev & 0x7f) != (uint8_t)(data & 0x7f));
409 map_init |= ((prev & 0x01) != (uint8_t)(data & 0x01));
413 cg_mask256_init |= (prev != (uint8_t)(data & 0xff));
417 if(cgreg_num & 0x80) {
418 cgreg_num = (cgreg_num & 0xfc) | ((cgreg_num + 1) & 0x03);
427 if(textreg_num < 0x10) {
428 if(textreg_num == 0) {
429 trans_init |= ((textreg[0] & 2) != (uint8_t)(data & 2));
430 } else if(textreg_num == 0x0a) {
431 // update 256 colors palette
432 if((textreg[0x0a] & 0x3f) != (uint8_t)(data & 0x3f)) {
433 for(int i = 0; i < 256; i++) {
434 uint8_t b0 = (data & 0x03) >> 0;
435 uint8_t r0 = (data & 0x0c) >> 2;
436 uint8_t g0 = (data & 0x30) >> 4;
437 uint16_t b = ((i & 0x10) ? 128 : 0) | ((i & 1) ? 64 : 0) | ((b0 == 0 && (i & 0x80)) || (b0 == 1 && (i & 8)) || (b0 == 2) ? 32 : 0);
438 uint16_t r = ((i & 0x20) ? 128 : 0) | ((i & 2) ? 64 : 0) | ((r0 == 0 && (i & 0x80)) || (r0 == 1 && (i & 8)) || (r0 == 2) ? 32 : 0);
439 uint16_t g = ((i & 0x40) ? 128 : 0) | ((i & 4) ? 64 : 0) | ((g0 == 0 && (i & 0x80)) || (g0 == 1 && (i & 8)) || (g0 == 2) ? 32 : 0);
440 palette256[i] = RGB_COLOR(r, g, b);
445 textreg[textreg_num] = data;
447 // kugyokuden 400line patch
448 if(get_cpu_pc(0) == 0xc27e && !monitor_200line) {
449 if(textreg[3] == 0x26 && textreg[5] == 0xee) {
454 } else if(0x80 <= textreg_num && textreg_num < 0x90) {
455 int c = textreg_num & 0x0f;
458 prev = palette_reg[c];
459 palette_reg[c] = data;
461 if((prev & 0x0f) != (uint8_t)(data & 0x0f)) {
464 if((prev & 0x10) != (uint8_t)(data & 0x10)) {
466 for(int i = 1; i < 8; i++) {
467 priority16[c][i] = p ? c : (i + 16);
469 priority16[c][0] = c; // transparent black
470 priority16[c][8] = p ? c : (0 + 16); // non transparent black
473 if((prev & 0x1f) != (uint8_t)(data & 0x1f)) {
474 // update priority (256 colors)
476 int col16 = (data & 0x0f) << 4;
478 for(int i = 0; i < 16; i++) {
479 for(int j = 1; j < 16 + 64; j++) {
480 priority256[c16 | i][j] = p ? (col16 | i) : (j + 256);
482 priority256[c16 | i][0] = col16 | i; // transparent black
483 priority256[c16 | i][8] = p ? (col16 | i) : (0 + 256); // non transparent black
484 priority256[c16 | i][16] = col16 | i; // transparent black (64 colors)
493 cg_mask = (data & 7) | ((data & 1) ? 8 : 0);
494 if(prev != cg_mask) {
495 cg_mask256_init = true;
501 font_size = ((data & 1) != 0);
506 uint32_t CRTC::read_io8(uint32_t addr)
508 switch(addr & 0xff) {
511 if(cgreg[7] & 0x10) {
512 uint8_t b = latch[0];
513 uint8_t r = latch[1];
514 uint8_t g = latch[2];
515 uint8_t i = latch[3];
516 uint8_t compare = cgreg[7] & 0x0f;
518 uint8_t val = (compare == (((b & 0x80) >> 7) | ((r & 0x80) >> 6) | ((g & 0x80) >> 5) | ((i & 0x80) >> 4))) ? 0x80 : 0;
519 val |= (compare == (((b & 0x40) >> 6) | ((r & 0x40) >> 5) | ((g & 0x40) >> 4) | ((i & 0x40) >> 3))) ? 0x40 : 0;
520 val |= (compare == (((b & 0x20) >> 5) | ((r & 0x20) >> 4) | ((g & 0x20) >> 3) | ((i & 0x20) >> 2))) ? 0x20 : 0;
521 val |= (compare == (((b & 0x10) >> 4) | ((r & 0x10) >> 3) | ((g & 0x10) >> 2) | ((i & 0x10) >> 1))) ? 0x10 : 0;
522 val |= (compare == (((b & 0x08) >> 3) | ((r & 0x08) >> 2) | ((g & 0x08) >> 1) | ((i & 0x08) >> 0))) ? 0x08 : 0;
523 val |= (compare == (((b & 0x04) >> 2) | ((r & 0x04) >> 1) | ((g & 0x04) >> 0) | ((i & 0x04) << 1))) ? 0x04 : 0;
524 val |= (compare == (((b & 0x02) >> 1) | ((r & 0x02) >> 0) | ((g & 0x02) << 1) | ((i & 0x02) << 2))) ? 0x02 : 0;
525 val |= (compare == (((b & 0x01) >> 0) | ((r & 0x01) << 1) | ((g & 0x01) << 2) | ((i & 0x01) << 3))) ? 0x01 : 0;
532 if(cgreg[7] & 0x10) {
533 return (vblank ? 0 : 0x80) | clear_flag;
543 case 0xf4: case 0xf5: case 0xf6: case 0xf7:
545 return (vblank ? 0 : 1) | (hblank ? 0 : 2);
550 void CRTC::write_signal(int id, uint32_t data, uint32_t mask)
552 if(id == SIG_CRTC_COLUMN_SIZE) {
553 column_size = ((data & mask) != 0); // from z80pio port a
554 } else if(id == SIG_CRTC_PALLETE) {
555 pal_select = ((data & mask) == 0); // from ym2203 port a
556 } else if(id == SIG_CRTC_MASK) {
557 screen_mask = ((data & mask) != 0); // from i8255 port c
561 void CRTC::event_callback(int event_id, int err)
563 if(event_id & EVENT_BLINK) {
570 void CRTC::event_vline(int v, int clock)
572 bool next = !(GDEVS <= v && v < GDEVE); // vblank = true
574 d_pio->write_signal(SIG_I8255_PORT_B, next ? 0 : 1, 1);
575 d_int->write_signal(SIG_INTERRUPT_CRTC, next ? 1 : 0, 1);
576 d_mem->write_signal(SIG_MEMORY_VBLANK, next ? 1 : 0, 1);
579 // complete clear screen
580 if(v == (monitor_200line ? 200 : 400)) {
583 // register hsync events
586 } else if(GDEHS < chars_per_line) {
587 register_event_by_clock(this, GDEHS, GDEHSC, false, NULL);
591 } else if(GDEHE < chars_per_line) {
592 register_event_by_clock(this, GDEHE, GDEHEC, false, NULL);
596 void CRTC::set_hsync(int h)
598 bool next = !(GDEHS <= h && h < GDEHE); // hblank = true
600 d_mem->write_signal(SIG_MEMORY_HBLANK, next ? 1 : 0, 1);
605 void CRTC::update_config()
607 //monitor_200line = ((config.monitor_type & 2) != 0);
608 scan_tmp = (monitor_200line && config.scan_line);
609 monitor_tmp = ((config.monitor_type & 1) != 0);
612 // ----------------------------------------------------------------------------
614 // ----------------------------------------------------------------------------
616 void CRTC::draw_screen()
619 scan_line = scan_tmp;
621 if(monitor_digital != monitor_tmp) {
622 monitor_digital = monitor_tmp;
623 // set 16 colors palette
624 for(int i = 0; i < 16; i++) {
625 uint8_t r, g, b, r8, g8, b8;
626 if((i & 0x0f) == 0x08) {
632 r = ((i & 0x0a) == 0x0a) ? 255 : ((i & 0x0a) == 0x02) ? 127 : 0;
633 g = ((i & 0x0c) == 0x0c) ? 255 : ((i & 0x0c) == 0x04) ? 127 : 0;
634 b = ((i & 0x09) == 0x09) ? 255 : ((i & 0x09) == 0x01) ? 127 : 0;
635 r8 = (i & 0x02) ? 255 : 0;
636 g8 = (i & 0x04) ? 255 : 0;
637 b8 = (i & 0x01) ? 255 : 0;
640 if(monitor_digital) {
641 palette16[i] = RGB_COLOR(r8, g8, b8);
643 palette16[i] = RGB_COLOR(r, g, b);
649 // update 16/4096 palette
650 uint8_t back16 = ((textreg[0x0b] & 4) >> 2) | ((textreg[0x0b] & 0x20) >> 4) | ((textreg[0x0c] & 1) << 2) | ((textreg[0x0b] & 1) << 3);
651 if(back16 != prev16) {
656 scrntype_t palette16tmp[16 + 8], palette4096tmp[16 + 8];
657 for(int i = 0; i < 16 + 8; i++) {
658 palette16tmp[i] = palette16[(i & 16) ? i : (palette_reg[i] & 0x0f) ? (palette_reg[i] & cg_mask) : (back16 & cg_mask)];
659 uint8_t col = (i == 16) ? 0 : (i & 16) ? (i & 0x0f) + 8 : i;
660 palette4096tmp[i] = palette4096[(palette_reg[col] & 0x0f) ? (palette_reg[col] & cg_mask) : (back16 & cg_mask)];
662 for(int i = 0; i < 16; i++) {
663 for(int j = 0; j < 9; j++) {
664 palette16pri[i][j] = palette16tmp[priority16[i][j]];
665 palette4096pri[i][j] = palette4096tmp[priority16[i][j]];
668 memcpy(palette16txt, &palette16tmp[16], sizeof(scrntype_t) * 8);
669 // palette16txt[0] = (back16 == 0 && (palette_reg[0] & 0x0f)== 2) ? 0 : palette16[palette_reg[back16] & 0x0f]; // tower of doruaga
670 palette16txt[0] = palette16[palette_reg[back16] & 0x0f];
672 memcpy(palette4096txt, &palette4096tmp[16], sizeof(scrntype_t) * 8);
673 palette4096txt[0] = palette4096[palette_reg[back16] & 0x0f];
674 palette4096txt[8] = 0;
678 // update 256 palette
679 scrntype_t back256 = RGB_COLOR((textreg[0x0b] & 0x38) << 2, ((textreg[0x0b] & 0xc0) >> 1) | ((textreg[0x0c] & 1) << 7), (textreg[0x0b] & 7) << 5);
680 if(back256 != prev256) {
685 palette256[0] = back256;
686 for(int i = 0; i < 256; i++) {
687 for(int j = 0; j < 16 + 64; j++) {
688 palette256pri[i][j] = palette256[priority256[i][j]];
691 memcpy(palette256txt, &palette256[256], sizeof(scrntype_t) * (16 + 64));
692 palette256txt[0] = back256;
693 palette256txt[8] = 0;
698 memset(cg, 0, sizeof(cg));
702 memset(text, 0, sizeof(text));
706 int vs = (GDEVS <= GDEVE) ? GDEVS * (scrn_size == SCRN_640x400 ? 1 : 2) : 0;
707 int ve = (GDEVS <= GDEVE) ? GDEVE * (scrn_size == SCRN_640x400 ? 1 : 2) : 400;
708 int hs = (GDEHS <= GDEHE && GDEHS < 80) ? (GDEHS << 3) : 0;
709 int he = (GDEHS <= GDEHE && GDEHE < 80) ? (GDEHE << 3) : 640;
714 for(int y = 0; y < 400; y++) {
715 scrntype_t *dest = emu->get_screen_buffer(y);
716 memset(dest, 0, sizeof(scrntype_t) * 640);
718 } else if(cgreg[0x0e] == 0x1d || cgreg[0x0e] == 0x9d) {
720 for(int y = 0; y < vs && y < 400; y++) {
721 scrntype_t *dest = emu->get_screen_buffer(y);
722 uint8_t *src_text = &text[640 * y];
723 for(int x = 0; x < 640; x++) {
724 dest[x] = palette256txt[src_text[x]];
727 for(int y = vs; y < ve && y < 400; y++) {
728 scrntype_t *dest = emu->get_screen_buffer(y);
729 uint8_t *src_cg = &cg[640 * y], *src_text = &text[640 * y];
730 for(int x = 0; x < hs && x < 640; x++) {
731 dest[x] = palette256txt[src_text[x]];
733 for(int x = hs; x < he && x < 640; x++) {
734 dest[x] = palette256pri[src_cg[x]][src_text[x]];
736 for(int x = he; x < 640; x++) {
737 dest[x] = palette256txt[src_text[x]];
740 for(int y = ve; y < 400; y++) {
741 scrntype_t *dest = emu->get_screen_buffer(y);
742 uint8_t *src_text = &text[640 * y];
743 for(int x = 0; x < 640; x++) {
744 dest[x] = palette256txt[src_text[x]];
747 } else if(!pal_select) {
749 for(int y = 0; y < vs && y < 400; y++) {
750 scrntype_t *dest = emu->get_screen_buffer(y);
751 uint8_t *src_cg = &cg[640 * y], *src_text = &text[640 * y];
752 for(int x = 0; x < 640; x++) {
753 dest[x] = palette16txt[src_text[x]];
756 for(int y = vs; y < ve && y < 400; y++) {
757 scrntype_t *dest = emu->get_screen_buffer(y);
758 uint8_t *src_cg = &cg[640 * y], *src_text = &text[640 * y];
759 for(int x = 0; x < hs && x < 640; x++) {
760 dest[x] = palette16txt[src_text[x]];
762 for(int x = hs; x < he && x < 640; x++) {
763 dest[x] = palette16pri[src_cg[x]][src_text[x]];
765 for(int x = he; x < 640; x++) {
766 dest[x] = palette16txt[src_text[x]];
769 for(int y = ve; y < 400; y++) {
770 scrntype_t *dest = emu->get_screen_buffer(y);
771 uint8_t *src_cg = &cg[640 * y], *src_text = &text[640 * y];
772 for(int x = 0; x < 640; x++) {
773 dest[x] = palette16txt[src_text[x]];
778 for(int y = 0; y < vs && y < 400; y++) {
779 scrntype_t *dest = emu->get_screen_buffer(y);
780 uint8_t *src_cg = &cg[640 * y], *src_text = &text[640 * y];
781 for(int x = 0; x < 640; x++) {
782 dest[x] = palette4096txt[src_text[x]];
785 for(int y = vs; y < ve && y < 400; y++) {
786 scrntype_t *dest = emu->get_screen_buffer(y);
787 uint8_t *src_cg = &cg[640 * y], *src_text = &text[640 * y];
788 for(int x = 0; x < hs && x < 640; x++) {
789 dest[x] = palette4096txt[src_text[x]];
791 for(int x = hs; x < he && x < 640; x++) {
792 dest[x] = palette4096pri[src_cg[x]][src_text[x]];
794 for(int x = he; x < 640; x++) {
795 dest[x] = palette4096txt[src_text[x]];
798 for(int y = ve; y < 400; y++) {
799 scrntype_t *dest = emu->get_screen_buffer(y);
800 uint8_t *src_cg = &cg[640 * y], *src_text = &text[640 * y];
801 for(int x = 0; x < 640; x++) {
802 dest[x] = palette4096txt[src_text[x]];
806 emu->screen_skip_line(monitor_200line);
809 // ----------------------------------------------------------------------------
811 // ----------------------------------------------------------------------------
813 void CRTC::draw_text()
815 // extract text optimization matrix
817 trans_color = (textreg[0] & 2) ? 8 : 0;
818 for(int pat = 0; pat < 256; pat++) {
819 for(int col = 0; col < 8; col++) {
820 int fore_color = col ? col : 8;
821 text_matrix[pat][col][0] = text_matrixw[pat][col][ 0] = text_matrixw[pat][col][ 1] = (pat & 0x80) ? fore_color : trans_color;
822 text_matrix[pat][col][1] = text_matrixw[pat][col][ 2] = text_matrixw[pat][col][ 3] = (pat & 0x40) ? fore_color : trans_color;
823 text_matrix[pat][col][2] = text_matrixw[pat][col][ 4] = text_matrixw[pat][col][ 5] = (pat & 0x20) ? fore_color : trans_color;
824 text_matrix[pat][col][3] = text_matrixw[pat][col][ 6] = text_matrixw[pat][col][ 7] = (pat & 0x10) ? fore_color : trans_color;
825 text_matrix[pat][col][4] = text_matrixw[pat][col][ 8] = text_matrixw[pat][col][ 9] = (pat & 0x08) ? fore_color : trans_color;
826 text_matrix[pat][col][5] = text_matrixw[pat][col][10] = text_matrixw[pat][col][11] = (pat & 0x04) ? fore_color : trans_color;
827 text_matrix[pat][col][6] = text_matrixw[pat][col][12] = text_matrixw[pat][col][13] = (pat & 0x02) ? fore_color : trans_color;
828 text_matrix[pat][col][7] = text_matrixw[pat][col][14] = text_matrixw[pat][col][15] = (pat & 0x01) ? fore_color : trans_color;
836 draw_80column_screen();
838 draw_40column_screen();
843 if(monitor_200line) {
845 SL = (textreg[3] - 38) << 1;
846 EL = (textreg[5] - 38) << 1;
849 SC = (textreg[7] & 0x7f) - 11;
850 EC = (textreg[8] & 0x7f) - 11;
853 SC = (textreg[7] & 0x7f) - 10;
854 EC = (textreg[8] & 0x7f) - 10;
858 SL = (textreg[3] - 17) << 1;
859 EL = (textreg[5] - 17) << 1;
862 SC = (textreg[7] & 0x7f) - 9;
863 EC = (textreg[8] & 0x7f) - 9;
866 SC = (textreg[7] & 0x7f) - 8;
867 EC = (textreg[8] & 0x7f) - 8;
870 SL = (SL < 0) ? 0 : (SL > 400) ? 400 : SL;
871 EL = (EL < 0) ? 0 : (EL > 400) ? 400 : EL;
872 SC = (SC < 0) ? 0 : (SC > 80) ? 80 : SC;
873 EC = (EC < 0) ? 0 : (EC > 80) ? 80 : EC;
876 for(int y = 0; y < SL; y++) {
877 memset(text + 640 * y, trans_color, 640);
879 for(int y = EL; y < 400; y++) {
880 memset(text + 640 * y, trans_color, 640);
883 for(int y = EL; y < SL; y++) {
884 memset(text + 640 * y, trans_color, 640);
888 for(int y = 0; y < 400; y++) {
889 memset(text + 640 * y, trans_color, SC << 3);
890 memset(text + 640 * y + (EC << 3), trans_color, (80 - EC) << 3);
893 for(int y = 0; y < 400; y++) {
894 memset(text + 640 * y + (EC << 3), trans_color, (SC - EC) << 3);
899 void CRTC::draw_80column_screen()
901 uint16_t src = textreg[1] | ((textreg[2] & 0x07) << 8);
902 uint8_t line = (textreg[0] & 0x10) ? 2 : 0;
903 uint8_t height = (textreg[0] & 0x10) ? 20 : 16;
904 uint8_t vd = (textreg[9] & 0x0f) << 1;
907 for(int y = line; y < 416; y += height) {
908 int dest = (y - vd) * 640;
909 for(int x = 0; x < 80; x++) {
910 draw_80column_font((src++) & 0x7ff, dest, y - vd);
916 void CRTC::draw_40column_screen()
918 uint16_t src1 = textreg[1] | ((textreg[2] & 0x07) << 8);
919 uint16_t src2 = src1 + 0x400;
920 uint8_t line = (textreg[0] & 0x10) ? 2 : 0;
921 uint8_t height = (textreg[0] & 0x10) ? 20 : 16;
922 uint8_t vd = (textreg[9] & 0x0f) << 1;
924 switch(textreg[0] & 0x0c) {
926 // 40x20(25), 64colors
927 for(int y = line; y < 416; y += height) {
928 int dest1 = (y - vd) * 640;
929 int dest2 = (y - vd) * 640 + 640 * 480;
930 for(int x = 0; x < 40; x++) {
931 draw_40column_font((src1++) & 0x7ff, dest1, y - vd);
932 draw_40column_font((src2++) & 0x7ff, dest2, y - vd);
937 for(int y = 0; y < 400; y++) {
938 uint32_t src1 = 640 * y;
939 uint32_t src2 = 640 * y + 640 * 480;
940 uint32_t dest = 640 * y;
942 for(int x = 0; x < 640; x++) {
943 if((text[src1] & 8) && (text[src2] & 8)) {
944 col = 8; // non transparent black
946 col = (((text[src1] & 7) << 3) | (text[src2] & 7)) + 16;
955 // 40x20(25), No.1 Screen
956 for(int y = line; y < 416; y += height) {
957 int dest = (y - vd) * 640;
958 for(int x = 0; x < 40; x++) {
959 draw_40column_font((src1++) & 0x7ff, dest, y - vd);
965 // 40x20(25), No.2 Screen
966 for(int y = line; y < 416; y += height) {
967 int dest = (y - vd) * 640;
968 for(int x = 0; x < 40; x++) {
969 draw_40column_font((src2++) & 0x7ff, dest, y - vd);
975 // 40x20(25), No.1 + No.2 Screens (No.1 > No.2)
976 for(int y = line; y < 416; y += height) {
977 int dest = (y - vd) * 640;
978 for(int x = 0; x < 40; x++) {
979 draw_40column_font((src1++) & 0x7ff, dest, y - vd);
983 for(int y = line; y < 416; y += height) {
984 int dest = (y - vd) * 640 + 640 * 480;
985 for(int x = 0; x < 40; x++) {
986 draw_40column_font((src2++) & 0x7ff, dest, y - vd);
990 for(int y = line; y < 400; y++) {
991 int dest = (y - vd) * 640;
992 uint8_t* tsrc1 = &text[dest];
993 uint8_t* tsrc2 = &text[dest + 640 * 480];
994 uint8_t* tdest = &text[dest];
995 for(int x = 0; x < 640; x++) {
996 tdest[x] = (tsrc1[x] & 7) ? tsrc1[x] : (tsrc2[x] & 7) ? tsrc2[x] : ((tsrc1[x] & 8) | (tsrc2[x] & 8));
1003 void CRTC::draw_80column_font(uint16_t src, int dest, int y)
1005 // draw char (80 column)
1011 uint8_t sel, col, pat1, pat2, pat3;
1012 uint8_t t1 = tvram1[src], t2 = tvram2[src], attr = attrib[src];
1015 sel = (t2 & 0xc0) | (attr & 0x38);
1017 case 0x00: case 0x40:
1026 case 0x10: case 0x50: case 0x90: case 0xd0:
1029 case 0x20: case 0x60: case 0xa0: case 0xe0:
1032 case 0x30: case 0x70: case 0xb0: case 0xf0:
1042 // PCG1 + PCG2 + PCG3 8colors
1045 code = font_size ? t1 << 3 : (t1 & 0xfe) << 3;
1048 for(int i = 0; i < 8; i++) {
1049 // check end line of screen
1053 if((attr & 0x80) && blink) {
1055 uint8_t val = (attr & 0x40) ? 7 : trans_color;
1057 memset(text + dest, val, 8);
1060 // check end line of screen
1064 if(dest >= 0 && !scan_line) {
1065 memset(text + dest, val, 8);
1070 pat1 = ~pattern1[code + i];
1071 pat2 = ~pattern2[code + i];
1072 pat3 = ~pattern3[code + i];
1074 pat1 = pattern1[code + i];
1075 pat2 = pattern2[code + i];
1076 pat3 = pattern3[code + i];
1079 uint8_t* tdest = &text[dest];
1080 col = ((pat1 & 0x80) >> 7) | ((pat2 & 0x80) >> 6) | ((pat3 & 0x80) >> 5); tdest[0] = col ? col : trans_color;
1081 col = ((pat1 & 0x40) >> 6) | ((pat2 & 0x40) >> 5) | ((pat3 & 0x40) >> 4); tdest[1] = col ? col : trans_color;
1082 col = ((pat1 & 0x20) >> 5) | ((pat2 & 0x20) >> 4) | ((pat3 & 0x20) >> 3); tdest[2] = col ? col : trans_color;
1083 col = ((pat1 & 0x10) >> 4) | ((pat2 & 0x10) >> 3) | ((pat3 & 0x10) >> 2); tdest[3] = col ? col : trans_color;
1084 col = ((pat1 & 0x08) >> 3) | ((pat2 & 0x08) >> 2) | ((pat3 & 0x08) >> 1); tdest[4] = col ? col : trans_color;
1085 col = ((pat1 & 0x04) >> 2) | ((pat2 & 0x04) >> 1) | ((pat3 & 0x04) ); tdest[5] = col ? col : trans_color;
1086 col = ((pat1 & 0x02) >> 1) | ((pat2 & 0x02) ) | ((pat3 & 0x02) << 1); tdest[6] = col ? col : trans_color;
1087 col = ((pat1 & 0x01) ) | ((pat2 & 0x01) << 1) | ((pat3 & 0x01) << 2); tdest[7] = col ? col : trans_color;
1090 // check end line of screen
1094 if(dest >= 0 && !scan_line) {
1096 memcpy(text + dest, text + dest - 640, 8);
1098 uint8_t* tdest = &text[dest];
1099 col = ((pat1 & 0x80) >> 7) | ((pat2 & 0x80) >> 6) | ((pat3 & 0x80) >> 5); tdest[0] = col ? col : trans_color;
1100 col = ((pat1 & 0x40) >> 6) | ((pat2 & 0x40) >> 5) | ((pat3 & 0x40) >> 4); tdest[1] = col ? col : trans_color;
1101 col = ((pat1 & 0x20) >> 5) | ((pat2 & 0x20) >> 4) | ((pat3 & 0x20) >> 3); tdest[2] = col ? col : trans_color;
1102 col = ((pat1 & 0x10) >> 4) | ((pat2 & 0x10) >> 3) | ((pat3 & 0x10) >> 2); tdest[3] = col ? col : trans_color;
1103 col = ((pat1 & 0x08) >> 3) | ((pat2 & 0x08) >> 2) | ((pat3 & 0x08) >> 1); tdest[4] = col ? col : trans_color;
1104 col = ((pat1 & 0x04) >> 2) | ((pat2 & 0x04) >> 1) | ((pat3 & 0x04) ); tdest[5] = col ? col : trans_color;
1105 col = ((pat1 & 0x02) >> 1) | ((pat2 & 0x02) ) | ((pat3 & 0x02) << 1); tdest[6] = col ? col : trans_color;
1106 col = ((pat1 & 0x01) ) | ((pat2 & 0x01) << 1) | ((pat3 & 0x01) << 2); tdest[7] = col ? col : trans_color;
1113 for(int i = 0; i < 16; i++) {
1114 // check end line of screen
1119 if((attr & 0x80) && blink) {
1121 memset(text + dest, 7, 8);
1123 memset(text + dest, trans_color, 8);
1127 pat1 = ~pattern1[code + i];
1128 pat2 = ~pattern2[code + i];
1129 pat3 = ~pattern3[code + i];
1131 pat1 = pattern1[code + i];
1132 pat2 = pattern2[code + i];
1133 pat3 = pattern3[code + i];
1135 uint8_t* tdest = &text[dest];
1136 col = ((pat1 & 0x80) >> 7) | ((pat2 & 0x80) >> 6) | ((pat3 & 0x80) >> 5); tdest[0] = col ? col : trans_color;
1137 col = ((pat1 & 0x40) >> 6) | ((pat2 & 0x40) >> 5) | ((pat3 & 0x40) >> 4); tdest[1] = col ? col : trans_color;
1138 col = ((pat1 & 0x20) >> 5) | ((pat2 & 0x20) >> 4) | ((pat3 & 0x20) >> 3); tdest[2] = col ? col : trans_color;
1139 col = ((pat1 & 0x10) >> 4) | ((pat2 & 0x10) >> 3) | ((pat3 & 0x10) >> 2); tdest[3] = col ? col : trans_color;
1140 col = ((pat1 & 0x08) >> 3) | ((pat2 & 0x08) >> 2) | ((pat3 & 0x08) >> 1); tdest[4] = col ? col : trans_color;
1141 col = ((pat1 & 0x04) >> 2) | ((pat2 & 0x04) >> 1) | ((pat3 & 0x04) ); tdest[5] = col ? col : trans_color;
1142 col = ((pat1 & 0x02) >> 1) | ((pat2 & 0x02) ) | ((pat3 & 0x02) << 1); tdest[6] = col ? col : trans_color;
1143 col = ((pat1 & 0x01) ) | ((pat2 & 0x01) << 1) | ((pat3 & 0x01) << 2); tdest[7] = col ? col : trans_color;
1154 if(sel == 0x80 || sel == 0xc0) {
1155 code = ((t2 & 0x3f) << 11) | (t1 << 3);
1160 if(sel == 0x80 || sel == 0xc0) {
1161 code = ((t2 & 0x3f) << 11) | ((t1 & 0xfe) << 3);
1163 code = (t1 & 0xfe) << 3;
1170 uint32_t dest1 = dest;
1171 uint32_t dest2 = (dest >= 640 * 399) ? dest - 640 * 399 : dest + 640;
1172 for(int i = 0; i < 8; i++) {
1173 // check end line of screen
1179 pat1 = ((attr & 0x80) && blink) ? 0xff : ~pattern1[code + i];
1181 pat1 = ((attr & 0x80) && blink) ? 0x00 : pattern1[code + i];
1184 memcpy(&text[dest], text_matrix[pat1][col], 8);
1187 // check end line of screen
1191 if(dest >= 0 && !scan_line) {
1192 memcpy(&text[dest], text_matrix[pat1][col], 8);
1197 for(int i = 0; i < 16; i++) {
1198 // check end line of screen
1205 pat1 = ((attr & 0x80) && blink) ? 0xff : ~pattern1[code + i];
1207 pat1 = ((attr & 0x80) && blink) ? 0x00 : pattern1[code + i];
1209 memcpy(&text[dest], text_matrix[pat1][col], 8);
1217 void CRTC::draw_40column_font(uint16_t src, int dest, int y)
1219 // draw char (40 column)
1225 uint8_t sel, col, pat1, pat2, pat3;
1226 uint8_t t1 = tvram1[src], t2 = tvram2[src], attr = attrib[src];
1229 sel = (t2 & 0xc0) | (attr & 0x38);
1231 case 0x00: case 0x40:
1240 case 0x10: case 0x50: case 0x90: case 0xd0:
1243 case 0x20: case 0x60: case 0xa0: case 0xe0:
1246 case 0x30: case 0x70: case 0xb0: case 0xf0:
1256 // PCG1 + PCG2 + PCG3 8colors
1259 code = font_size ? t1 << 3 : (t1 & 0xfe) << 3;
1262 for(int i = 0; i < 8; i++) {
1263 // check end line of screen
1267 if((attr & 0x80) && blink) {
1269 uint8_t val = (attr & 0x40) ? 7 : trans_color;
1271 memset(text + dest, val, 16);
1274 // check end line of screen
1278 if(dest >= 0 && !scan_line) {
1279 memset(text + dest, val, 16);
1284 pat1 = ~pattern1[code + i];
1285 pat2 = ~pattern2[code + i];
1286 pat3 = ~pattern3[code + i];
1288 pat1 = pattern1[code + i];
1289 pat2 = pattern2[code + i];
1290 pat3 = pattern3[code + i];
1293 uint8_t* tdest = &text[dest];
1294 col = ((pat1 & 0x80) >> 7) | ((pat2 & 0x80) >> 6) | ((pat3 & 0x80) >> 5); tdest[ 0] = tdest[ 1] = col ? col : trans_color;
1295 col = ((pat1 & 0x40) >> 6) | ((pat2 & 0x40) >> 5) | ((pat3 & 0x40) >> 4); tdest[ 2] = tdest[ 3] = col ? col : trans_color;
1296 col = ((pat1 & 0x20) >> 5) | ((pat2 & 0x20) >> 4) | ((pat3 & 0x20) >> 3); tdest[ 4] = tdest[ 5] = col ? col : trans_color;
1297 col = ((pat1 & 0x10) >> 4) | ((pat2 & 0x10) >> 3) | ((pat3 & 0x10) >> 2); tdest[ 6] = tdest[ 7] = col ? col : trans_color;
1298 col = ((pat1 & 0x08) >> 3) | ((pat2 & 0x08) >> 2) | ((pat3 & 0x08) >> 1); tdest[ 8] = tdest[ 9] = col ? col : trans_color;
1299 col = ((pat1 & 0x04) >> 2) | ((pat2 & 0x04) >> 1) | ((pat3 & 0x04) ); tdest[10] = tdest[11] = col ? col : trans_color;
1300 col = ((pat1 & 0x02) >> 1) | ((pat2 & 0x02) ) | ((pat3 & 0x02) << 1); tdest[12] = tdest[13] = col ? col : trans_color;
1301 col = ((pat1 & 0x01) ) | ((pat2 & 0x01) << 1) | ((pat3 & 0x01) << 2); tdest[14] = tdest[15] = col ? col : trans_color;
1304 // check end line of screen
1308 if(dest >= 0 && !scan_line) {
1310 memcpy(text + dest, text + dest - 640, 16);
1312 uint8_t* tdest = &text[dest];
1313 col = ((pat1 & 0x80) >> 7) | ((pat2 & 0x80) >> 6) | ((pat3 & 0x80) >> 5); tdest[ 0] = tdest[ 1] = col ? col : trans_color;
1314 col = ((pat1 & 0x40) >> 6) | ((pat2 & 0x40) >> 5) | ((pat3 & 0x40) >> 4); tdest[ 2] = tdest[ 3] = col ? col : trans_color;
1315 col = ((pat1 & 0x20) >> 5) | ((pat2 & 0x20) >> 4) | ((pat3 & 0x20) >> 3); tdest[ 4] = tdest[ 5] = col ? col : trans_color;
1316 col = ((pat1 & 0x10) >> 4) | ((pat2 & 0x10) >> 3) | ((pat3 & 0x10) >> 2); tdest[ 6] = tdest[ 7] = col ? col : trans_color;
1317 col = ((pat1 & 0x08) >> 3) | ((pat2 & 0x08) >> 2) | ((pat3 & 0x08) >> 1); tdest[ 8] = tdest[ 9] = col ? col : trans_color;
1318 col = ((pat1 & 0x04) >> 2) | ((pat2 & 0x04) >> 1) | ((pat3 & 0x04) ); tdest[10] = tdest[11] = col ? col : trans_color;
1319 col = ((pat1 & 0x02) >> 1) | ((pat2 & 0x02) ) | ((pat3 & 0x02) << 1); tdest[12] = tdest[13] = col ? col : trans_color;
1320 col = ((pat1 & 0x01) ) | ((pat2 & 0x01) << 1) | ((pat3 & 0x01) << 2); tdest[14] = tdest[15] = col ? col : trans_color;
1327 for(int i = 0; i < 16; i++) {
1328 // check end line of screen
1333 if((attr & 0x80) && blink) {
1335 memset(text + dest, 7, 16);
1337 memset(text + dest, trans_color, 16);
1341 pat1 = ~pattern1[code + i];
1342 pat2 = ~pattern2[code + i];
1343 pat3 = ~pattern3[code + i];
1345 pat1 = pattern1[code + i];
1346 pat2 = pattern2[code + i];
1347 pat3 = pattern3[code + i];
1349 uint8_t* tdest = &text[dest];
1350 col = ((pat1 & 0x80) >> 7) | ((pat2 & 0x80) >> 6) | ((pat3 & 0x80) >> 5); tdest[ 0] = tdest[ 1] = col ? col : trans_color;
1351 col = ((pat1 & 0x40) >> 6) | ((pat2 & 0x40) >> 5) | ((pat3 & 0x40) >> 4); tdest[ 2] = tdest[ 3] = col ? col : trans_color;
1352 col = ((pat1 & 0x20) >> 5) | ((pat2 & 0x20) >> 4) | ((pat3 & 0x20) >> 3); tdest[ 4] = tdest[ 5] = col ? col : trans_color;
1353 col = ((pat1 & 0x10) >> 4) | ((pat2 & 0x10) >> 3) | ((pat3 & 0x10) >> 2); tdest[ 6] = tdest[ 7] = col ? col : trans_color;
1354 col = ((pat1 & 0x08) >> 3) | ((pat2 & 0x08) >> 2) | ((pat3 & 0x08) >> 1); tdest[ 8] = tdest[ 9] = col ? col : trans_color;
1355 col = ((pat1 & 0x04) >> 2) | ((pat2 & 0x04) >> 1) | ((pat3 & 0x04) ); tdest[10] = tdest[11] = col ? col : trans_color;
1356 col = ((pat1 & 0x02) >> 1) | ((pat2 & 0x02) ) | ((pat3 & 0x02) << 1); tdest[12] = tdest[13] = col ? col : trans_color;
1357 col = ((pat1 & 0x01) ) | ((pat2 & 0x01) << 1) | ((pat3 & 0x01) << 2); tdest[14] = tdest[15] = col ? col : trans_color;
1368 if(sel == 0x80 || sel == 0xc0) {
1369 code = ((t2 & 0x3f) << 11) | (t1 << 3);
1374 if(sel == 0x80 || sel == 0xc0) {
1375 code = ((t2 & 0x3f) << 11) | ((t1 & 0xfe) << 3);
1377 code = (t1 & 0xfe) << 3;
1384 for(int i = 0; i < 8; i++) {
1385 // check end line of screen
1391 pat1 = ((attr & 0x80) && blink) ? 0xff : ~pattern1[code + i];
1393 pat1 = ((attr & 0x80) && blink) ? 0x00 : pattern1[code + i];
1396 memcpy(&text[dest], text_matrixw[pat1][col], 16);
1399 // check end line of screen
1403 if(dest >= 0 && !scan_line) {
1404 memcpy(&text[dest], text_matrixw[pat1][col], 16);
1409 for(int i = 0; i < 16; i++) {
1410 // check end line of screen
1417 pat1 = ((attr & 0x80) && blink) ? 0xff : ~pattern1[code + i];
1419 pat1 = ((attr & 0x80) && blink) ? 0x00 : pattern1[code + i];
1421 memcpy(&text[dest], text_matrixw[pat1][col], 16);
1429 // ----------------------------------------------------------------------------
1431 // ----------------------------------------------------------------------------
1433 void CRTC::draw_cg()
1436 switch(cgreg[0x0e]) {
1438 draw_640x400x4screen();
1441 draw_320x200x16screen(0);
1442 draw_320x200x16screen(1);
1445 draw_320x200x16screen(1);
1446 draw_320x200x16screen(0);
1449 draw_640x200x16screen(0);
1452 draw_320x200x256screen(0);
1455 draw_640x400x16screen();
1458 draw_320x200x16screen(2);
1459 draw_320x200x16screen(3);
1462 draw_320x200x16screen(3);
1463 draw_320x200x16screen(2);
1466 draw_640x200x16screen(1);
1469 draw_320x200x256screen(1);
1474 if(!scan_line && !(cgreg[0x0e] == 0x03 || cgreg[0x0e] == 0x93)) {
1475 for(int y = 0; y < 400; y += 2) {
1476 memcpy(cg + (y + 1) * 640, cg + y * 640, 640);
1481 void CRTC::draw_320x200x16screen(uint8_t pl)
1483 uint8_t B, R, G, I, col;
1487 create_addr_map(40, 200);
1489 for(int y = 0; y < 200; y++) {
1490 for(int x = 0; x < 40; x++) {
1491 uint16_t src = (map_addr[y][x] + (0x2000 * pl)) & 0x7fff;
1492 uint32_t dest2 = dest + map_hdsc[y][x];
1495 if(pl == 0 || pl == 2) {
1496 B = (cgreg[0x18] & 0x01) ? vram_b[src] : 0;
1497 R = (cgreg[0x18] & 0x02) ? vram_r[src] : 0;
1498 G = (cgreg[0x18] & 0x04) ? vram_g[src] : 0;
1499 I = (cgreg[0x18] & 0x08) ? vram_i[src] : 0;
1501 B = (cgreg[0x18] & 0x10) ? vram_b[src] : 0;
1502 R = (cgreg[0x18] & 0x20) ? vram_r[src] : 0;
1503 G = (cgreg[0x18] & 0x40) ? vram_g[src] : 0;
1504 I = (cgreg[0x18] & 0x80) ? vram_i[src] : 0;
1507 col = cg_matrix0[B][R][0] | cg_matrix1[G][I][0]; if(col) cg[dest2 ] = cg[dest2 + 1] = col;
1508 col = cg_matrix0[B][R][1] | cg_matrix1[G][I][1]; if(col) cg[dest2 + 2] = cg[dest2 + 3] = col;
1509 col = cg_matrix0[B][R][2] | cg_matrix1[G][I][2]; if(col) cg[dest2 + 4] = cg[dest2 + 5] = col;
1510 col = cg_matrix0[B][R][3] | cg_matrix1[G][I][3]; if(col) cg[dest2 + 6] = cg[dest2 + 7] = col;
1511 col = cg_matrix0[B][R][4] | cg_matrix1[G][I][4]; if(col) cg[dest2 + 8] = cg[dest2 + 9] = col;
1512 col = cg_matrix0[B][R][5] | cg_matrix1[G][I][5]; if(col) cg[dest2 + 10] = cg[dest2 + 11] = col;
1513 col = cg_matrix0[B][R][6] | cg_matrix1[G][I][6]; if(col) cg[dest2 + 12] = cg[dest2 + 13] = col;
1514 col = cg_matrix0[B][R][7] | cg_matrix1[G][I][7]; if(col) cg[dest2 + 14] = cg[dest2 + 15] = col;
1520 void CRTC::draw_320x200x256screen(uint8_t pl)
1522 uint8_t B0, B1, R0, R1, G0, G1, I0, I1;
1526 create_addr_map(40, 200);
1528 if(cg_mask256_init) {
1529 cg_mask256 = cgreg[0x18];
1530 if(!(cg_mask & 1)) {
1531 cg_mask256 &= ~(0x11 | 0x88);
1533 if(!(cg_mask & 2)) {
1534 cg_mask256 &= ~0x22;
1536 if(!(cg_mask & 4)) {
1537 cg_mask256 &= ~0x44;
1539 cg_mask256_init = false;
1541 for(int y = 0; y < 200; y++) {
1542 for(int x = 0; x < 40; x++) {
1543 uint16_t src1 = (map_addr[y][x] + (0x4000 * pl)) & 0x7fff;
1544 uint16_t src2 = (src1 + 0x2000) & 0x7fff;
1545 uint32_t dest2 = dest + map_hdsc[y][x];
1548 B1 = (cg_mask256 & 0x01) ? vram_b[src1] : 0;
1549 B0 = (cg_mask256 & 0x10) ? vram_b[src2] : 0;
1550 R1 = (cg_mask256 & 0x02) ? vram_r[src1] : 0;
1551 R0 = (cg_mask256 & 0x20) ? vram_r[src2] : 0;
1552 G1 = (cg_mask256 & 0x04) ? vram_g[src1] : 0;
1553 G0 = (cg_mask256 & 0x40) ? vram_g[src2] : 0;
1554 I1 = (cg_mask256 & 0x08) ? vram_i[src1] : 0;
1555 I0 = (cg_mask256 & 0x80) ? vram_i[src2] : 0;
1557 cg[dest2 ] = cg[dest2 + 1] = cg_matrix0[B0][R0][0] | cg_matrix1[G0][I0][0] | cg_matrix2[B1][R1][0] | cg_matrix3[G1][I1][0];
1558 cg[dest2 + 2] = cg[dest2 + 3] = cg_matrix0[B0][R0][1] | cg_matrix1[G0][I0][1] | cg_matrix2[B1][R1][1] | cg_matrix3[G1][I1][1];
1559 cg[dest2 + 4] = cg[dest2 + 5] = cg_matrix0[B0][R0][2] | cg_matrix1[G0][I0][2] | cg_matrix2[B1][R1][2] | cg_matrix3[G1][I1][2];
1560 cg[dest2 + 6] = cg[dest2 + 7] = cg_matrix0[B0][R0][3] | cg_matrix1[G0][I0][3] | cg_matrix2[B1][R1][3] | cg_matrix3[G1][I1][3];
1561 cg[dest2 + 8] = cg[dest2 + 9] = cg_matrix0[B0][R0][4] | cg_matrix1[G0][I0][4] | cg_matrix2[B1][R1][4] | cg_matrix3[G1][I1][4];
1562 cg[dest2 + 10] = cg[dest2 + 11] = cg_matrix0[B0][R0][5] | cg_matrix1[G0][I0][5] | cg_matrix2[B1][R1][5] | cg_matrix3[G1][I1][5];
1563 cg[dest2 + 12] = cg[dest2 + 13] = cg_matrix0[B0][R0][6] | cg_matrix1[G0][I0][6] | cg_matrix2[B1][R1][6] | cg_matrix3[G1][I1][6];
1564 cg[dest2 + 14] = cg[dest2 + 15] = cg_matrix0[B0][R0][7] | cg_matrix1[G0][I0][7] | cg_matrix2[B1][R1][7] | cg_matrix3[G1][I1][7];
1570 void CRTC::draw_640x200x16screen(uint8_t pl)
1576 create_addr_map(80, 200);
1578 for(int y = 0; y < 200; y++) {
1579 for(int x = 0; x < 80; x++) {
1580 uint16_t src = (map_addr[y][x] + (0x4000 * pl)) & 0x7fff;
1581 uint32_t dest2 = dest + map_hdsc[y][x];
1584 B = (cgreg[0x18] & 0x01) ? vram_b[src] : 0;
1585 R = (cgreg[0x18] & 0x02) ? vram_r[src] : 0;
1586 G = (cgreg[0x18] & 0x04) ? vram_g[src] : 0;
1587 I = (cgreg[0x18] & 0x08) ? vram_i[src] : 0;
1589 cg[dest2 ] = cg_matrix0[B][R][0] | cg_matrix1[G][I][0];
1590 cg[dest2 + 1] = cg_matrix0[B][R][1] | cg_matrix1[G][I][1];
1591 cg[dest2 + 2] = cg_matrix0[B][R][2] | cg_matrix1[G][I][2];
1592 cg[dest2 + 3] = cg_matrix0[B][R][3] | cg_matrix1[G][I][3];
1593 cg[dest2 + 4] = cg_matrix0[B][R][4] | cg_matrix1[G][I][4];
1594 cg[dest2 + 5] = cg_matrix0[B][R][5] | cg_matrix1[G][I][5];
1595 cg[dest2 + 6] = cg_matrix0[B][R][6] | cg_matrix1[G][I][6];
1596 cg[dest2 + 7] = cg_matrix0[B][R][7] | cg_matrix1[G][I][7];
1602 void CRTC::draw_640x400x4screen()
1607 uint8_t *vram_b1 = ((cgreg[0x18] & 3) == 1) ? vram_b + 0x4000 : vram_g;
1608 uint8_t *vram_r1 = ((cgreg[0x18] & 3) == 1) ? vram_r + 0x4000 : vram_i;
1611 create_addr_map(80, 400);
1613 for(int y = 0; y < 400; y++) {
1614 for(int x = 0; x < 80; x++) {
1615 uint16_t src = map_addr[y][x];
1616 uint32_t dest2 = dest + map_hdsc[y][x];
1619 B = (cgreg[0x18] & 0x01) ? ((src & 0x4000) ? vram_b1[src & 0x3fff] : vram_b[src]) : 0;
1620 R = (cgreg[0x18] & 0x02) ? ((src & 0x4000) ? vram_r1[src & 0x3fff] : vram_r[src]) : 0;
1622 cg[dest2 ] = cg_matrix0[B][R][0];
1623 cg[dest2 + 1] = cg_matrix0[B][R][1];
1624 cg[dest2 + 2] = cg_matrix0[B][R][2];
1625 cg[dest2 + 3] = cg_matrix0[B][R][3];
1626 cg[dest2 + 4] = cg_matrix0[B][R][4];
1627 cg[dest2 + 5] = cg_matrix0[B][R][5];
1628 cg[dest2 + 6] = cg_matrix0[B][R][6];
1629 cg[dest2 + 7] = cg_matrix0[B][R][7];
1634 void CRTC::draw_640x400x16screen()
1640 create_addr_map(80, 400);
1642 for(int y = 0; y < 400; y++) {
1643 for(int x = 0; x < 80; x++) {
1644 uint16_t src = map_addr[y][x];
1645 uint32_t dest2 = dest + map_hdsc[y][x];
1653 cg[dest2 ] = cg_matrix0[B][R][0] | cg_matrix1[G][I][0];
1654 cg[dest2 + 1] = cg_matrix0[B][R][1] | cg_matrix1[G][I][1];
1655 cg[dest2 + 2] = cg_matrix0[B][R][2] | cg_matrix1[G][I][2];
1656 cg[dest2 + 3] = cg_matrix0[B][R][3] | cg_matrix1[G][I][3];
1657 cg[dest2 + 4] = cg_matrix0[B][R][4] | cg_matrix1[G][I][4];
1658 cg[dest2 + 5] = cg_matrix0[B][R][5] | cg_matrix1[G][I][5];
1659 cg[dest2 + 6] = cg_matrix0[B][R][6] | cg_matrix1[G][I][6];
1660 cg[dest2 + 7] = cg_matrix0[B][R][7] | cg_matrix1[G][I][7];
1665 void CRTC::create_addr_map(int xmax, int ymax)
1667 uint8_t HDSC = cgreg[0x0f] & 0x07;
1668 uint16_t SAD0 = cgreg[0x10] | ((cgreg[0x11] & 0x7f) << 8);
1669 uint16_t SAD1 = cgreg[0x12] | ((cgreg[0x13] & 0x7f) << 8);
1670 uint16_t SAD2 = cgreg[0x14] | ((cgreg[0x15] & 0x7f) << 8);
1671 uint16_t SLN1 = cgreg[0x16] | ((cgreg[0x17] & 0x01) << 8);
1673 for(int y = 0; y < SLN1 && y < ymax; y++) {
1674 for(int x = 0; x < xmax; x++) {
1675 map_hdsc[y][x] = HDSC;
1676 map_addr[y][x] = SAD0;
1677 SAD0 = (SAD0 == SAD1) ? 0 : ((SAD0 + 1) & 0x7fff);
1680 for(int y = SLN1; y < ymax; y++) {
1681 for(int x = 0; x < xmax; x++) {
1683 map_addr[y][x] = (SAD2++) & 0x7fff;
1689 #define STATE_VERSION 1
1691 void CRTC::save_state(FILEIO* state_fio)
1693 state_fio->FputUint32(STATE_VERSION);
1694 state_fio->FputInt32(this_device_id);
1696 state_fio->FputBool(scan_line);
1697 state_fio->FputBool(scan_tmp);
1698 state_fio->FputBool(monitor_200line);
1699 state_fio->FputBool(monitor_digital);
1700 state_fio->FputBool(monitor_tmp);
1701 state_fio->FputUint8(textreg_num);
1702 state_fio->Fwrite(textreg, sizeof(textreg), 1);
1703 state_fio->FputUint8(cgreg_num);
1704 state_fio->Fwrite(cgreg, sizeof(cgreg), 1);
1705 state_fio->FputUint8(scrn_size);
1706 state_fio->FputUint8(cg_mask);
1707 state_fio->FputUint8(cg_mask256);
1708 state_fio->FputBool(cg_mask256_init);
1709 state_fio->FputBool(font_size);
1710 state_fio->FputBool(column_size);
1711 state_fio->Fwrite(latch, sizeof(latch), 1);
1712 state_fio->FputUint16(GDEVS);
1713 state_fio->FputUint16(GDEVE);
1714 state_fio->FputUint8(GDEHS);
1715 state_fio->FputUint8(GDEHE);
1716 state_fio->FputInt32(GDEHSC);
1717 state_fio->FputInt32(GDEHEC);
1718 state_fio->FputBool(hblank);
1719 state_fio->FputBool(vblank);
1720 state_fio->FputBool(blink);
1721 state_fio->FputUint8(clear_flag);
1722 state_fio->Fwrite(palette_reg, sizeof(palette_reg), 1);
1723 state_fio->FputBool(pal_select);
1724 state_fio->FputBool(screen_mask);
1725 state_fio->Fwrite(priority16, sizeof(priority16), 1);
1726 state_fio->Fwrite(palette16, sizeof(palette16), 1);
1727 state_fio->Fwrite(palette4096, sizeof(palette4096), 1);
1728 state_fio->Fwrite(palette4096r, sizeof(palette4096r), 1);
1729 state_fio->Fwrite(palette4096g, sizeof(palette4096g), 1);
1730 state_fio->Fwrite(palette4096b, sizeof(palette4096b), 1);
1731 state_fio->Fwrite(palette16txt, sizeof(palette16txt), 1);
1732 state_fio->Fwrite(palette4096txt, sizeof(palette4096txt), 1);
1733 state_fio->Fwrite(palette16pri, sizeof(palette16pri), 1);
1734 state_fio->Fwrite(palette4096pri, sizeof(palette4096pri), 1);
1735 state_fio->FputUint8(prev16);
1736 state_fio->FputBool(update16);
1737 state_fio->Fwrite(priority256, sizeof(priority256), 1);
1738 state_fio->Fwrite(palette256, sizeof(palette256), 1);
1739 state_fio->Fwrite(palette256txt, sizeof(palette256txt), 1);
1740 state_fio->Fwrite(palette256pri, sizeof(palette256pri), 1);
1741 state_fio->FputUint32((uint32_t)prev256);
1742 state_fio->FputBool(update256);
1743 state_fio->Fwrite(map_addr, sizeof(map_addr), 1);
1744 state_fio->Fwrite(map_hdsc, sizeof(map_hdsc), 1);
1745 state_fio->Fwrite(text_matrix, sizeof(text_matrix), 1);
1746 state_fio->Fwrite(text_matrixw, sizeof(text_matrixw), 1);
1747 state_fio->FputUint8(trans_color);
1748 state_fio->FputBool(map_init);
1749 state_fio->FputBool(trans_init);
1752 bool CRTC::load_state(FILEIO* state_fio)
1754 if(state_fio->FgetUint32() != STATE_VERSION) {
1757 if(state_fio->FgetInt32() != this_device_id) {
1760 scan_line = state_fio->FgetBool();
1761 scan_tmp = state_fio->FgetBool();
1762 monitor_200line = state_fio->FgetBool();
1763 monitor_digital = state_fio->FgetBool();
1764 monitor_tmp = state_fio->FgetBool();
1765 textreg_num = state_fio->FgetUint8();
1766 state_fio->Fread(textreg, sizeof(textreg), 1);
1767 cgreg_num = state_fio->FgetUint8();
1768 state_fio->Fread(cgreg, sizeof(cgreg), 1);
1769 scrn_size = state_fio->FgetUint8();
1770 cg_mask = state_fio->FgetUint8();
1771 cg_mask256 = state_fio->FgetUint8();
1772 cg_mask256_init = state_fio->FgetBool();
1773 font_size = state_fio->FgetBool();
1774 column_size = state_fio->FgetBool();
1775 state_fio->Fread(latch, sizeof(latch), 1);
1776 GDEVS = state_fio->FgetUint16();
1777 GDEVE = state_fio->FgetUint16();
1778 GDEHS = state_fio->FgetUint8();
1779 GDEHE = state_fio->FgetUint8();
1780 GDEHSC = state_fio->FgetInt32();
1781 GDEHEC = state_fio->FgetInt32();
1782 hblank = state_fio->FgetBool();
1783 vblank = state_fio->FgetBool();
1784 blink = state_fio->FgetBool();
1785 clear_flag = state_fio->FgetUint8();
1786 state_fio->Fread(palette_reg, sizeof(palette_reg), 1);
1787 pal_select = state_fio->FgetBool();
1788 screen_mask = state_fio->FgetBool();
1789 state_fio->Fread(priority16, sizeof(priority16), 1);
1790 state_fio->Fread(palette16, sizeof(palette16), 1);
1791 state_fio->Fread(palette4096, sizeof(palette4096), 1);
1792 state_fio->Fread(palette4096r, sizeof(palette4096r), 1);
1793 state_fio->Fread(palette4096g, sizeof(palette4096g), 1);
1794 state_fio->Fread(palette4096b, sizeof(palette4096b), 1);
1795 state_fio->Fread(palette16txt, sizeof(palette16txt), 1);
1796 state_fio->Fread(palette4096txt, sizeof(palette4096txt), 1);
1797 state_fio->Fread(palette16pri, sizeof(palette16pri), 1);
1798 state_fio->Fread(palette4096pri, sizeof(palette4096pri), 1);
1799 prev16 = state_fio->FgetUint8();
1800 update16 = state_fio->FgetBool();
1801 state_fio->Fread(priority256, sizeof(priority256), 1);
1802 state_fio->Fread(palette256, sizeof(palette256), 1);
1803 state_fio->Fread(palette256txt, sizeof(palette256txt), 1);
1804 state_fio->Fread(palette256pri, sizeof(palette256pri), 1);
1805 prev256 = (scrntype_t)state_fio->FgetUint32();
1806 update256 = state_fio->FgetBool();
1807 state_fio->Fread(map_addr, sizeof(map_addr), 1);
1808 state_fio->Fread(map_hdsc, sizeof(map_hdsc), 1);
1809 state_fio->Fread(text_matrix, sizeof(text_matrix), 1);
1810 state_fio->Fread(text_matrixw, sizeof(text_matrixw), 1);
1811 trans_color = state_fio->FgetUint8();
1812 map_init = state_fio->FgetBool();
1813 trans_init = state_fio->FgetBool();