OSDN Git Service

[VM][General] Merge upstream 2016-03-01. (Pahse 1).
[csp-qt/common_source_project-fm7.git] / source / src / vm / mz2500 / crtc.cpp
1 /*
2         SHARP MZ-2500 Emulator 'EmuZ-2500'
3
4         Author : Takeda.Toshiya
5         Date   : 2006.12.03 -
6
7         [ crtc ]
8 */
9
10 #include "crtc.h"
11 #include "interrupt.h"
12 #include "memory.h"
13 #include "../i8255.h"
14
15 #define EVENT_HSYNC     0
16 #define EVENT_BLINK     256
17
18 #define SCRN_640x400    1
19 #define SCRN_640x200    2
20 #define SCRN_320x200    3
21
22 void CRTC::initialize()
23 {
24         // config
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);
28         
29         // thanks Mr.Sato (http://x1center.org/)
30         if(monitor_200line) {
31                 frames_per_sec = 60.99;
32                 lines_per_frame = 262;
33                 chars_per_line = 112;
34         } else {
35                 frames_per_sec = 55.49;
36                 lines_per_frame = 448;
37                 chars_per_line = 108;
38         }
39         set_frames_per_sec(frames_per_sec);
40         set_lines_per_frame(lines_per_frame);
41         
42         // set 16/4096 palette
43         for(int i = 0; i < 16; i++) {
44                 uint8_t r, g, b, r8, g8, b8;
45                 if((i & 0x0f) == 8) {
46                         // gray
47                         r = r8 = 152;
48                         g = g8 = 152;
49                         b = b8 = 152;
50                 } else {
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;
57                 }
58                 
59                 if(monitor_digital) {
60                         palette16[i] = RGB_COLOR(r8, g8, b8);
61                 } else {
62                         palette16[i] = RGB_COLOR(r, g, b);
63                 }
64                 palette4096r[i] = r;
65                 palette4096g[i] = g;
66                 palette4096b[i] = b;
67                 palette4096[i] = RGB_COLOR(r, g, b);
68         }
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);
71         }
72         for(int i = 0; i < 16; i++) {
73                 for(int j = 1; j < 8; j++) {
74                         priority16[i][j] = j + 16;
75                 }
76                 priority16[i][0] = i; // transparent black
77                 priority16[i][8] = 0 + 16; // non transparent black
78         }
79         prev16 = 0xff;
80         update16 = true;
81         
82         // set 256 palette
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));
87         }
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));
90         }
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));
95         }
96         for(int i = 0; i < 256; i++) {
97                 for(int j = 1; j < 16 + 64; j++) {
98                         priority256[i][j] = j + 256;
99                 }
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)
103         }
104         prev256 = -1;
105         update256 = true;
106         
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);
115                         }
116                 }
117         }
118         
119         // initialize crtc
120         memset(textreg, 0, sizeof(textreg));
121         memset(cgreg, 0, sizeof(cgreg));
122         
123         cgreg_num = 0x80;
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);
131         
132         for(int i = 0; i < 16; i++) {
133                 palette_reg[i] = i;
134         }
135         scrn_size = SCRN_320x200;
136         font_size = true;
137         column_size = false;
138         cg_mask = 0x0f;
139         cg_mask256 = 0;
140         cg_mask256_init = false;
141         clear_flag = 0;
142         pal_select = false;
143         screen_mask = false;
144         blink = false;
145         latch[0] = latch[1] = latch[2] = latch[3] = 0;
146         hblank = vblank = false;
147         map_init = trans_init = true;
148         
149         // register events
150         register_vline_event(this);
151         register_event(this, EVENT_BLINK, 500000, true, NULL);
152 }
153
154 void CRTC::write_data8(uint32_t addr, uint32_t data)
155 {
156         // read modify write
157         if(cgreg[0x0e] == 0x03) {
158                 // for Yukara K2
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;
161                 
162                 // 4 colors
163                 if((cgreg[5] & 0xc0) == 0x00) {
164                         // REPLACE
165                         if(addr & 0x4000) {
166                                 addr &= 0x3fff;
167                                 if(cgreg[5] & 1) {
168                                         vram_b1[addr] &= ~cgreg[6];
169                                         vram_b1[addr] |= (cgreg[4] & 1) ? (data & cgreg[0] & cgreg[6]) : 0;
170                                 }
171                                 if(cgreg[5] & 2) {
172                                         vram_r1[addr] &= ~cgreg[6];
173                                         vram_r1[addr] |= (cgreg[4] & 2) ? (data & cgreg[1] & cgreg[6]) : 0;
174                                 }
175                         } else {
176                                 addr &= 0x3fff;
177                                 if(cgreg[5] & 1) {
178                                         vram_b[addr] &= ~cgreg[6];
179                                         vram_b[addr] |= (cgreg[4] & 1) ? (data & cgreg[0] & cgreg[6]) : 0;
180                                 }
181                                 if(cgreg[5] & 2) {
182                                         vram_r[addr] &= ~cgreg[6];
183                                         vram_r[addr] |= (cgreg[4] & 2) ? (data & cgreg[1] & cgreg[6]) : 0;
184                                 }
185                         }
186                 } else if((cgreg[5] & 0xc0) == 0x40) {
187                         // PSET
188                         if(addr & 0x4000) {
189                                 addr &= 0x3fff;
190                                 if(cgreg[5] & 1) {
191                                         vram_b1[addr] &= ~data;
192                                         vram_b1[addr] |= (cgreg[4] & 1) ? (data & cgreg[0]) : 0;
193                                 }
194                                 if(cgreg[5] & 2) {
195                                         vram_r1[addr] &= ~data;
196                                         vram_r1[addr] |= (cgreg[4] & 2) ? (data & cgreg[1]) : 0;
197                                 }
198                         } else {
199                                 addr &= 0x3fff;
200                                 if(cgreg[5] & 1) {
201                                         vram_b[addr] &= ~data;
202                                         vram_b[addr] |= (cgreg[4] & 1) ? (data & cgreg[0]) : 0;
203                                 }
204                                 if(cgreg[5] & 2) {
205                                         vram_r[addr] &= ~data;
206                                         vram_r[addr] |= (cgreg[4] & 2) ? (data & cgreg[1]) : 0;
207                                 }
208                         }
209                 }
210         } else {
211                 addr &= 0x7fff;
212                 if((cgreg[5] & 0xc0) == 0x00) {
213                         // REPLACE
214                         if(cgreg[5] & 1) {
215                                 vram_b[addr] &= ~cgreg[6];
216                                 vram_b[addr] |= (cgreg[4] & 1) ? (data & cgreg[0] & cgreg[6]) : 0;
217                         }
218                         if(cgreg[5] & 2) {
219                                 vram_r[addr] &= ~cgreg[6];
220                                 vram_r[addr] |= (cgreg[4] & 2) ? (data & cgreg[1] & cgreg[6]) : 0;
221                         }
222                         if(cgreg[5] & 4) {
223                                 vram_g[addr] &= ~cgreg[6];
224                                 vram_g[addr] |= (cgreg[4] & 4) ? (data & cgreg[2] & cgreg[6]) : 0;
225                         }
226                         if(cgreg[5] & 8) {
227                                 vram_i[addr] &= ~cgreg[6];
228                                 vram_i[addr] |= (cgreg[4] & 8) ? (data & cgreg[3] & cgreg[6]) : 0;
229                         }
230                 } else if((cgreg[5] & 0xc0) == 0x40) {
231                         // PSET
232                         if(cgreg[5] & 1) {
233                                 vram_b[addr] &= ~data;
234                                 vram_b[addr] |= (cgreg[4] & 1) ? (data & cgreg[0]) : 0;
235                         }
236                         if(cgreg[5] & 2) {
237                                 vram_r[addr] &= ~data;
238                                 vram_r[addr] |= (cgreg[4] & 2) ? (data & cgreg[1]) : 0;
239                         }
240                         if(cgreg[5] & 4) {
241                                 vram_g[addr] &= ~data;
242                                 vram_g[addr] |= (cgreg[4] & 4) ? (data & cgreg[2]) : 0;
243                         }
244                         if(cgreg[5] & 8) {
245                                 vram_i[addr] &= ~data;
246                                 vram_i[addr] |= (cgreg[4] & 8) ? (data & cgreg[3]) : 0;
247                         }
248                 }
249         }
250 }
251
252 uint32_t CRTC::read_data8(uint32_t addr)
253 {
254         // read modify write
255         uint8_t b, r, g, i, pl;
256         
257         if(cgreg[0x0e] == 0x03) {
258                 // 4 colors
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];
261                 g = latch[2] = 0;
262                 i = latch[3] = 0;
263                 pl = cgreg[7] & 1;
264         } else {
265                 addr &= 0x7fff;
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];
270                 pl = cgreg[7] & 3;
271         }
272         
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;
283                 return val;
284         } else {
285                 return latch[pl];
286         }
287 }
288
289 void CRTC::write_io8(uint32_t addr, uint32_t data)
290 {
291         uint8_t haddr = (addr >> 8) & 0xff;
292         uint8_t num, r, g, b, prev;
293         
294         switch(addr & 0xff) {
295         case 0xae:
296                 // 4096 palette reg
297                 num = (haddr & 0x1f) >> 1;
298                 r = palette4096r[num];
299                 g = palette4096g[num];
300                 b = palette4096b[num];
301                 if(haddr & 1) {
302                         g = (data & 0x0f) << 4;
303                 } else {
304                         r = data & 0xf0;
305                         b = (data & 0x0f) << 4;
306                 }
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);
312                         update16 = true;
313                 }
314                 // never change palette 0
315                 //palette4096[0] = 0;
316                 break;
317         case 0xbc:
318                 // cgreg num
319                 cgreg_num = data;
320                 break;
321         case 0xbd:
322                 // cgreg
323                 prev = cgreg[cgreg_num & 0x1f];
324                 cgreg[cgreg_num & 0x1f] = data;
325                 
326                 switch(cgreg_num & 0x1f) {
327                 // clear screen
328                 case 0x05:
329                         if((data & 0xc0) == 0x80) {
330                                 uint16_t st, sz;
331                                 switch(cgreg[0x0e]) {
332                                 case 0x03: case 0x14: case 0x15: case 0x17: case 0x1d:
333                                         // clear 0x0000 - 0x4000
334                                         st = 0x0000;
335                                         sz = 0x4000;
336                                         break;
337                                 case 0x94: case 0x95: case 0x97: case 0x9d:
338                                         // clear 0x4000 - 0x7fff
339                                         st = 0x4000;
340                                         sz = 0x4000;
341                                         break;
342                                 default:
343                                         // clear 0x0000 - 0x7fff
344                                         st = 0x0000;
345                                         sz = 0x8000;
346                                 }
347                                 if(cgreg[5] & 0x01) {
348                                         memset(vram_b + st, 0, sz);
349                                 }
350                                 if(cgreg[5] & 0x02) {
351                                         memset(vram_r + st, 0, sz);
352                                 }
353                                 if(cgreg[5] & 0x04) {
354                                         memset(vram_g + st, 0, sz);
355                                 }
356                                 if(cgreg[5] & 0x08) {
357                                         memset(vram_i + st, 0, sz);
358                                 }
359                                 clear_flag = 1;
360                         }
361                         break;
362                 // view range
363                 case 0x08:
364                         cgreg[0x09] = 0;
365                 case 0x09:
366                         GDEVS = (cgreg[0x08] | ((cgreg[0x09] & 1) << 8));
367                         break;
368                 case 0x0a:
369                         cgreg[0x0b] = 0;
370                 case 0x0b:
371                         GDEVE = (cgreg[0x0a] | ((cgreg[0x0b] & 1) << 8));
372                         break;
373                 case 0x0c:
374                         GDEHS = cgreg[0x0c] & 0x7f;
375                         GDEHSC = (int)(CPU_CLOCKS * GDEHS / frames_per_sec / lines_per_frame / chars_per_line + 0.5);
376                         break;
377                 case 0x0d:
378                         GDEHE = cgreg[0x0d] & 0x7f;
379                         GDEHEC = (int)(CPU_CLOCKS * (GDEHE + 3) / frames_per_sec / lines_per_frame / chars_per_line + 0.5);
380                         break;
381                 // screen size
382                 case 0x0e:
383                         switch(data) {
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;
387                                 break;
388                         case 0x17: case 0x97:
389                                 map_init |= (scrn_size != SCRN_640x200);
390                                 scrn_size = SCRN_640x200;
391                                 break;
392                         case 0x03: case 0x93:
393                                 map_init |= (scrn_size != SCRN_640x400);
394                                 scrn_size = SCRN_640x400;
395                                 break;
396                         }
397                         break;
398                 // scroll
399                 case 0x0f:
400                         map_init |= ((prev & 0x07) != (uint8_t)(data & 0x07));
401                         break;
402                 case 0x10: case 0x12: case 0x14: case 0x16:
403                         map_init |= (prev != (uint8_t)(data & 0xff));
404                         break;
405                 case 0x11: case 0x13: case 0x15:
406                         map_init |= ((prev & 0x7f) != (uint8_t)(data & 0x7f));
407                         break;
408                 case 0x17:
409                         map_init |= ((prev & 0x01) != (uint8_t)(data & 0x01));
410                         break;
411                 // screen mask
412                 case 0x18:
413                         cg_mask256_init |= (prev != (uint8_t)(data & 0xff));
414                         break;
415                 }
416                 // inc cgreg num
417                 if(cgreg_num & 0x80) {
418                         cgreg_num = (cgreg_num & 0xfc) | ((cgreg_num + 1) & 0x03);
419                 }
420                 break;
421         case 0xf4:
422                 // textreg num
423                 textreg_num = data;
424                 break;
425         case 0xf5:
426                 // text/palette reg
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);
441                                         }
442                                         update256 = true;
443                                 }
444                         }
445                         textreg[textreg_num] = data;
446                         
447                         // kugyokuden 400line patch
448                         if(get_cpu_pc(0) == 0xc27e && !monitor_200line) {
449                                 if(textreg[3] == 0x26 && textreg[5] == 0xee) {
450                                         textreg[3] = 0x11;
451                                         textreg[5] = 0xd9;
452                                 }
453                         }
454                 } else if(0x80 <= textreg_num && textreg_num < 0x90) {
455                         int c = textreg_num & 0x0f;
456                         int p = data & 0x10;
457                         
458                         prev = palette_reg[c];
459                         palette_reg[c] = data;
460                         
461                         if((prev & 0x0f) != (uint8_t)(data & 0x0f)) {
462                                 update16 = true;
463                         }
464                         if((prev & 0x10) != (uint8_t)(data & 0x10)) {
465                                 // update priority
466                                 for(int i = 1; i < 8; i++) {
467                                         priority16[c][i] = p ? c : (i + 16);
468                                 }
469                                 priority16[c][0] = c; // transparent black
470                                 priority16[c][8] = p ? c : (0 + 16); // non transparent black
471                                 update16 = true;
472                         }
473                         if((prev & 0x1f) != (uint8_t)(data & 0x1f)) {
474                                 // update priority (256 colors)
475                                 int c16 = c << 4;
476                                 int col16 = (data & 0x0f) << 4;
477                                 
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);
481                                         }
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)
485                                 }
486                                 update256 = true;
487                         }
488                 }
489                 break;
490         case 0xf6:
491                 // cg mask reg
492                 prev = cg_mask;
493                 cg_mask = (data & 7) | ((data & 1) ? 8 : 0);
494                 if(prev != cg_mask) {
495                         cg_mask256_init = true;
496                         update16 = true;
497                 }
498                 break;
499         case 0xf7:
500                 // font size reg
501                 font_size = ((data & 1) != 0);
502                 break;
503         }
504 }
505
506 uint32_t CRTC::read_io8(uint32_t addr)
507 {
508         switch(addr & 0xff) {
509         case 0xbc:
510                 // read plane b
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;
517                         
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;
526                         return val;
527                 } else {
528                         return latch[0];
529                 }
530         case 0xbd:
531                 // read plane r
532                 if(cgreg[7] & 0x10) {
533                         return (vblank ? 0 : 0x80) | clear_flag;
534                 } else {
535                         return latch[1];
536                 }
537         case 0xbe:
538                 // read plane g
539                 return latch[2];
540         case 0xbf:
541                 // read plane i
542                 return latch[3];
543         case 0xf4: case 0xf5: case 0xf6: case 0xf7:
544                 // get blank state
545                 return (vblank ? 0 : 1) | (hblank ? 0 : 2);
546         }
547         return 0xff;
548 }
549
550 void CRTC::write_signal(int id, uint32_t data, uint32_t mask)
551 {
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
558         }
559 }
560
561 void CRTC::event_callback(int event_id, int err)
562 {
563         if(event_id & EVENT_BLINK) {
564                 blink = !blink;
565         } else {
566                 set_hsync(event_id);
567         }
568 }
569
570 void CRTC::event_vline(int v, int clock)
571 {
572         bool next = !(GDEVS <= v && v < GDEVE); // vblank = true
573         if(vblank != next) {
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);
577                 vblank = next;
578         }
579         // complete clear screen
580         if(v == (monitor_200line ? 200 : 400)) {
581                 clear_flag = 0;
582         }
583         // register hsync events
584         if(!GDEHS) {
585                 set_hsync(0);
586         } else if(GDEHS < chars_per_line) {
587                 register_event_by_clock(this, GDEHS, GDEHSC, false, NULL);
588         }
589         if(!GDEHE) {
590                 set_hsync(0);
591         } else if(GDEHE < chars_per_line) {
592                 register_event_by_clock(this, GDEHE, GDEHEC, false, NULL);
593         }
594 }
595
596 void CRTC::set_hsync(int h)
597 {
598         bool next = !(GDEHS <= h && h < GDEHE); // hblank = true
599         if(hblank != next) {
600                 d_mem->write_signal(SIG_MEMORY_HBLANK, next ? 1 : 0, 1);
601                 hblank = next;
602         }
603 }
604
605 void CRTC::update_config()
606 {
607         //monitor_200line = ((config.monitor_type & 2) != 0);
608         scan_tmp = (monitor_200line && config.scan_line);
609         monitor_tmp = ((config.monitor_type & 1) != 0);
610 }
611
612 // ----------------------------------------------------------------------------
613 // draw screen
614 // ----------------------------------------------------------------------------
615
616 void CRTC::draw_screen()
617 {
618         // update config
619         scan_line = scan_tmp;
620         
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) {
627                                 // gray
628                                 r = r8 = 152;
629                                 g = g8 = 152;
630                                 b = b8 = 152;
631                         } else {
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;
638                         }
639                         
640                         if(monitor_digital) {
641                                 palette16[i] = RGB_COLOR(r8, g8, b8);
642                         } else {
643                                 palette16[i] = RGB_COLOR(r, g, b);
644                         }
645                 }
646                 update16 = true;
647         }
648         
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) {
652                 prev16 = back16;
653                 update16 = true;
654         }
655         if(update16) {
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)];
661                 }
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]];
666                         }
667                 }
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];
671                 palette16txt[8] = 0;
672                 memcpy(palette4096txt, &palette4096tmp[16], sizeof(scrntype_t) * 8);
673                 palette4096txt[0] = palette4096[palette_reg[back16] & 0x0f];
674                 palette4096txt[8] = 0;
675                 update16 = false;
676         }
677         
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) {
681                 prev256 = back256;
682                 update256 = true;
683         }
684         if(update256) {
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]];
689                         }
690                 }
691                 memcpy(palette256txt, &palette256[256], sizeof(scrntype_t) * (16 + 64));
692                 palette256txt[0] = back256;
693                 palette256txt[8] = 0;
694                 update256 = false;
695         }
696         
697         // draw cg screen
698         memset(cg, 0, sizeof(cg));
699         draw_cg();
700         
701         // draw text screen
702         memset(text, 0, sizeof(text));
703         draw_text();
704         
705         // view port
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;
710         
711         // mix screens
712         if(screen_mask) {
713                 // screen is masked
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);
717                 }
718         } else if(cgreg[0x0e] == 0x1d || cgreg[0x0e] == 0x9d) {
719                 // 256 colors
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]];
725                         }
726                 }
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]];
732                         }
733                         for(int x = hs; x < he && x < 640; x++) {
734                                 dest[x] = palette256pri[src_cg[x]][src_text[x]];
735                         }
736                         for(int x = he; x < 640; x++) {
737                                 dest[x] = palette256txt[src_text[x]];
738                         }
739                 }
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]];
745                         }
746                 }
747         } else if(!pal_select) {
748                 // 16 colors
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]];
754                         }
755                 }
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]];
761                         }
762                         for(int x = hs; x < he && x < 640; x++) {
763                                 dest[x] = palette16pri[src_cg[x]][src_text[x]];
764                         }
765                         for(int x = he; x < 640; x++) {
766                                 dest[x] = palette16txt[src_text[x]];
767                         }
768                 }
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]];
774                         }
775                 }
776         } else {
777                 // 4096 colors
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]];
783                         }
784                 }
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]];
790                         }
791                         for(int x = hs; x < he && x < 640; x++) {
792                                 dest[x] = palette4096pri[src_cg[x]][src_text[x]];
793                         }
794                         for(int x = he; x < 640; x++) {
795                                 dest[x] = palette4096txt[src_text[x]];
796                         }
797                 }
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]];
803                         }
804                 }
805         }
806         emu->screen_skip_line(monitor_200line);
807 }
808
809 // ----------------------------------------------------------------------------
810 // draw text screen
811 // ----------------------------------------------------------------------------
812
813 void CRTC::draw_text()
814 {
815         // extract text optimization matrix
816         if(trans_init) {
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;
829                         }
830                 }
831                 trans_init = false;
832         }
833         
834         // draw text
835         if(column_size) {
836                 draw_80column_screen();
837         } else {
838                 draw_40column_screen();
839         }
840         
841         // display period
842         int SL, EL, SC, EC;
843         if(monitor_200line) {
844                 // 200 lines
845                 SL = (textreg[3] - 38) << 1;
846                 EL = (textreg[5] - 38) << 1;
847                 if(column_size) {
848                         // 80 column
849                         SC = (textreg[7] & 0x7f) - 11;
850                         EC = (textreg[8] & 0x7f) - 11;
851                 } else {
852                         // 40 column
853                         SC = (textreg[7] & 0x7f) - 10;
854                         EC = (textreg[8] & 0x7f) - 10;
855                 }
856         } else {
857                 // 400 lines
858                 SL = (textreg[3] - 17) << 1;
859                 EL = (textreg[5] - 17) << 1;
860                 if(column_size) {
861                         // 80 colums
862                         SC = (textreg[7] & 0x7f) - 9;
863                         EC = (textreg[8] & 0x7f) - 9;
864                 } else {
865                         // 40 column
866                         SC = (textreg[7] & 0x7f) - 8;
867                         EC = (textreg[8] & 0x7f) - 8;
868                 }
869         }
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;
874         
875         if(EL >= SL) {
876                 for(int y = 0; y < SL; y++) {
877                         memset(text + 640 * y, trans_color, 640);
878                 }
879                 for(int y = EL; y < 400; y++) {
880                         memset(text + 640 * y, trans_color, 640);
881                 }
882         } else {
883                 for(int y = EL; y < SL; y++) {
884                         memset(text + 640 * y, trans_color, 640);
885                 }
886         }
887         if(EC >= SC) {
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);
891                 }
892         } else {
893                 for(int y = 0; y < 400; y++) {
894                         memset(text + 640 * y + (EC << 3), trans_color, (SC - EC) << 3);
895                 }
896         }
897 }
898
899 void CRTC::draw_80column_screen()
900 {
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;
905         
906         // 80x20(25)
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);
911                         dest += 8;
912                 }
913         }
914 }
915
916 void CRTC::draw_40column_screen()
917 {
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;
923         
924         switch(textreg[0] & 0x0c) {
925         case 0x00:
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);
933                                 dest1 += 16;
934                                 dest2 += 16;
935                         }
936                 }
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;
941                         uint8_t col;
942                         for(int x = 0; x < 640; x++) {
943                                 if((text[src1] & 8) && (text[src2] & 8)) {
944                                         col = 8; // non transparent black
945                                 } else {
946                                         col = (((text[src1] & 7) << 3) | (text[src2] & 7)) + 16;
947                                 }
948                                 text[dest++] = col;
949                                 src1++;
950                                 src2++;
951                         }
952                 }
953                 break;
954         case 0x04:
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);
960                                 dest += 16;
961                         }
962                 }
963                 break;
964         case 0x08:
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);
970                                 dest += 16;
971                         }
972                 }
973                 break;
974         case 0x0c:
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);
980                                 dest += 16;
981                         }
982                 }
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);
987                                 dest += 16;
988                         }
989                 }
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));
997                         }
998                 }
999                 break;
1000         }
1001 }
1002
1003 void CRTC::draw_80column_font(uint16_t src, int dest, int y)
1004 {
1005         // draw char (80 column)
1006         uint8_t* pattern1;
1007         uint8_t* pattern2;
1008         uint8_t* pattern3;
1009         
1010         uint32_t code;
1011         uint8_t sel, col, pat1, pat2, pat3;
1012         uint8_t t1 = tvram1[src], t2 = tvram2[src], attr = attrib[src];
1013         
1014         // select char type
1015         sel = (t2 & 0xc0) | (attr & 0x38);
1016         switch(sel) {
1017         case 0x00: case 0x40:
1018                 pattern1 = pcg0;
1019                 break;
1020         case 0x80:
1021                 pattern1 = kanji1;
1022                 break;
1023         case 0xc0:
1024                 pattern1 = kanji2;
1025                 break;
1026         case 0x10: case 0x50: case 0x90: case 0xd0:
1027                 pattern1 = pcg1;
1028                 break;
1029         case 0x20: case 0x60: case 0xa0: case 0xe0:
1030                 pattern1 = pcg2;
1031                 break;
1032         case 0x30: case 0x70: case 0xb0: case 0xf0:
1033                 pattern1 = pcg3;
1034                 break;
1035         default:
1036                 pattern1 = pcg1;
1037                 pattern2 = pcg2;
1038                 pattern3 = pcg3;
1039                 break;
1040         }
1041         if(sel & 8) {
1042                 // PCG1 + PCG2 + PCG3 8colors
1043                 
1044                 // generate addr
1045                 code = font_size ? t1 << 3 : (t1 & 0xfe) << 3;
1046                 // draw
1047                 if(font_size) {
1048                         for(int i = 0; i < 8; i++) {
1049                                 // check end line of screen
1050                                 if(!(y++ < 480)) {
1051                                         break;
1052                                 }
1053                                 if((attr & 0x80) && blink) {
1054                                         // blink
1055                                         uint8_t val = (attr & 0x40) ? 7 : trans_color;
1056                                         if(dest >= 0) {
1057                                                 memset(text + dest, val, 8);
1058                                         }
1059                                         dest += 640;
1060                                         // check end line of screen
1061                                         if(!(y++ < 480)) {
1062                                                 break;
1063                                         }
1064                                         if(dest >= 0 && !scan_line) {
1065                                                 memset(text + dest, val, 8);
1066                                         }
1067                                         dest += 640;
1068                                 } else {
1069                                         if(attr & 0x40) {
1070                                                 pat1 = ~pattern1[code + i];
1071                                                 pat2 = ~pattern2[code + i];
1072                                                 pat3 = ~pattern3[code + i];
1073                                         } else {
1074                                                 pat1 = pattern1[code + i];
1075                                                 pat2 = pattern2[code + i];
1076                                                 pat3 = pattern3[code + i];
1077                                         }
1078                                         if(dest >= 0) {
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;
1088                                         }
1089                                         dest += 640;
1090                                         // check end line of screen
1091                                         if(!(y++ < 480)) {
1092                                                 break;
1093                                         }
1094                                         if(dest >= 0 && !scan_line) {
1095                                                 if(dest >= 640) {
1096                                                         memcpy(text + dest, text + dest - 640, 8);
1097                                                 } else {
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;
1107                                                 }
1108                                         }
1109                                         dest += 640;
1110                                 }
1111                         }
1112                 } else {
1113                         for(int i = 0; i < 16; i++) {
1114                                 // check end line of screen
1115                                 if(!(y++ < 480)) {
1116                                         break;
1117                                 }
1118                                 if(dest >= 0) {
1119                                         if((attr & 0x80) && blink) {
1120                                                 if(attr & 0x40) {
1121                                                         memset(text + dest, 7, 8);
1122                                                 } else {
1123                                                         memset(text + dest, trans_color, 8);
1124                                                 }
1125                                         } else {
1126                                                 if(attr & 0x40) {
1127                                                         pat1 = ~pattern1[code + i];
1128                                                         pat2 = ~pattern2[code + i];
1129                                                         pat3 = ~pattern3[code + i];
1130                                                 } else {
1131                                                         pat1 = pattern1[code + i];
1132                                                         pat2 = pattern2[code + i];
1133                                                         pat3 = pattern3[code + i];
1134                                                 }
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;
1144                                         }
1145                                 }
1146                                 dest += 640;
1147                         }
1148                 }
1149         } else {
1150                 // monochrome
1151                 
1152                 // generate addr
1153                 if(font_size) {
1154                         if(sel == 0x80 || sel == 0xc0) {
1155                                 code = ((t2 & 0x3f) << 11) | (t1 << 3);
1156                         } else {
1157                                 code = t1 << 3;
1158                         }
1159                 } else {
1160                         if(sel == 0x80 || sel == 0xc0) {
1161                                 code = ((t2 & 0x3f) << 11) | ((t1 & 0xfe) << 3);
1162                         } else {
1163                                 code = (t1 & 0xfe) << 3;
1164                         }
1165                 }
1166                 // color
1167                 col = attr & 0x07;
1168                 // draw
1169                 if(font_size) {
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
1174                                 if(!(y++ < 480)) {
1175                                         break;
1176                                 }
1177                                 // reverse, blink
1178                                 if(attr & 0x40) {
1179                                         pat1 = ((attr & 0x80) && blink) ? 0xff : ~pattern1[code + i];
1180                                 } else {
1181                                         pat1 = ((attr & 0x80) && blink) ? 0x00 : pattern1[code + i];
1182                                 }
1183                                 if(dest >= 0) {
1184                                         memcpy(&text[dest], text_matrix[pat1][col], 8);
1185                                 }
1186                                 dest += 640;
1187                                 // check end line of screen
1188                                 if(!(y++ < 480)) {
1189                                         break;
1190                                 }
1191                                 if(dest >= 0 && !scan_line) {
1192                                         memcpy(&text[dest], text_matrix[pat1][col], 8);
1193                                 }
1194                                 dest += 640;
1195                         }
1196                 } else {
1197                         for(int i = 0; i < 16; i++) {
1198                                 // check end line of screen
1199                                 if(!(y++ < 480)) {
1200                                         break;
1201                                 }
1202                                 if(dest >= 0) {
1203                                         // reverse, blink
1204                                         if(attr & 0x40) {
1205                                                 pat1 = ((attr & 0x80) && blink) ? 0xff : ~pattern1[code + i];
1206                                         } else {
1207                                                 pat1 = ((attr & 0x80) && blink) ? 0x00 : pattern1[code + i];
1208                                         }
1209                                         memcpy(&text[dest], text_matrix[pat1][col], 8);
1210                                 }
1211                                 dest += 640;
1212                         }
1213                 }
1214         }
1215 }
1216
1217 void CRTC::draw_40column_font(uint16_t src, int dest, int y)
1218 {
1219         // draw char (40 column)
1220         uint8_t* pattern1;
1221         uint8_t* pattern2;
1222         uint8_t* pattern3;
1223         
1224         uint32_t code;
1225         uint8_t sel, col, pat1, pat2, pat3;
1226         uint8_t t1 = tvram1[src], t2 = tvram2[src], attr = attrib[src];
1227         
1228         // select char type
1229         sel = (t2 & 0xc0) | (attr & 0x38);
1230         switch(sel) {
1231         case 0x00: case 0x40:
1232                 pattern1 = pcg0;
1233                 break;
1234         case 0x80:
1235                 pattern1 = kanji1;
1236                 break;
1237         case 0xc0:
1238                 pattern1 = kanji2;
1239                 break;
1240         case 0x10: case 0x50: case 0x90: case 0xd0:
1241                 pattern1 = pcg1;
1242                 break;
1243         case 0x20: case 0x60: case 0xa0: case 0xe0:
1244                 pattern1 = pcg2;
1245                 break;
1246         case 0x30: case 0x70: case 0xb0: case 0xf0:
1247                 pattern1 = pcg3;
1248                 break;
1249         default:
1250                 pattern1 = pcg1;
1251                 pattern2 = pcg2;
1252                 pattern3 = pcg3;
1253                 break;
1254         }
1255         if(sel & 0x08) {
1256                 // PCG1 + PCG2 + PCG3 8colors
1257                 
1258                 // generate addr
1259                 code = font_size ? t1 << 3 : (t1 & 0xfe) << 3;
1260                 // draw
1261                 if(font_size) {
1262                         for(int i = 0; i < 8; i++) {
1263                                 // check end line of screen
1264                                 if(!(y++ < 480)) {
1265                                         break;
1266                                 }
1267                                 if((attr & 0x80) && blink) {
1268                                         // blink
1269                                         uint8_t val = (attr & 0x40) ? 7 : trans_color;
1270                                         if(dest >= 0) {
1271                                                 memset(text + dest, val, 16);
1272                                         }
1273                                         dest += 640;
1274                                         // check end line of screen
1275                                         if(!(y++ < 480)) {
1276                                                 break;
1277                                         }
1278                                         if(dest >= 0 && !scan_line) {
1279                                                 memset(text + dest, val, 16);
1280                                         }
1281                                         dest += 640;
1282                                 } else {
1283                                         if(attr & 0x40) {
1284                                                 pat1 = ~pattern1[code + i];
1285                                                 pat2 = ~pattern2[code + i];
1286                                                 pat3 = ~pattern3[code + i];
1287                                         } else {
1288                                                 pat1 = pattern1[code + i];
1289                                                 pat2 = pattern2[code + i];
1290                                                 pat3 = pattern3[code + i];
1291                                         }
1292                                         if(dest >= 0) {
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;
1302                                         }
1303                                         dest += 640;
1304                                         // check end line of screen
1305                                         if(!(y++ < 480)) {
1306                                                 break;
1307                                         }
1308                                         if(dest >= 0 && !scan_line) {
1309                                                 if(dest >= 640) {
1310                                                         memcpy(text + dest, text + dest - 640, 16);
1311                                                 } else {
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;
1321                                                 }
1322                                         }
1323                                         dest += 640;
1324                                 }
1325                         }
1326                 } else {
1327                         for(int i = 0; i < 16; i++) {
1328                                 // check end line of screen
1329                                 if(!(y++ < 480)) {
1330                                         break;
1331                                 }
1332                                 if(dest >= 0) {
1333                                         if((attr & 0x80) && blink) {
1334                                                 if(attr & 0x40) {
1335                                                         memset(text + dest, 7, 16);
1336                                                 } else {
1337                                                         memset(text + dest, trans_color, 16);
1338                                                 }
1339                                         } else {
1340                                                 if(attr & 0x40) {
1341                                                         pat1 = ~pattern1[code + i];
1342                                                         pat2 = ~pattern2[code + i];
1343                                                         pat3 = ~pattern3[code + i];
1344                                                 } else {
1345                                                         pat1 = pattern1[code + i];
1346                                                         pat2 = pattern2[code + i];
1347                                                         pat3 = pattern3[code + i];
1348                                                 }
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;
1358                                         }
1359                                 }
1360                                 dest += 640;
1361                         }
1362                 }
1363         } else {
1364                 // monochrome
1365                 
1366                 // generate addr
1367                 if(font_size) {
1368                         if(sel == 0x80 || sel == 0xc0) {
1369                                 code = ((t2 & 0x3f) << 11) | (t1 << 3);
1370                         } else {
1371                                 code = t1 << 3;
1372                         }
1373                 } else {
1374                         if(sel == 0x80 || sel == 0xc0) {
1375                                 code = ((t2 & 0x3f) << 11) | ((t1 & 0xfe) << 3);
1376                         } else {
1377                                 code = (t1 & 0xfe) << 3;
1378                         }
1379                 }
1380                 // color
1381                 col = attr & 0x07;
1382                 // draw
1383                 if(font_size) {
1384                         for(int i = 0; i < 8; i++) {
1385                                 // check end line of screen
1386                                 if(!(y++ < 480)) {
1387                                         break;
1388                                 }
1389                                 // reverse, blink
1390                                 if(attr & 0x40) {
1391                                         pat1 = ((attr & 0x80) && blink) ? 0xff : ~pattern1[code + i];
1392                                 } else {
1393                                         pat1 = ((attr & 0x80) && blink) ? 0x00 : pattern1[code + i];
1394                                 }
1395                                 if(dest >= 0) {
1396                                         memcpy(&text[dest], text_matrixw[pat1][col], 16);
1397                                 }
1398                                 dest += 640;
1399                                 // check end line of screen
1400                                 if(!(y++ < 480)) {
1401                                         break;
1402                                 }
1403                                 if(dest >= 0 && !scan_line) {
1404                                         memcpy(&text[dest], text_matrixw[pat1][col], 16);
1405                                 }
1406                                 dest += 640;
1407                         }
1408                 } else {
1409                         for(int i = 0; i < 16; i++) {
1410                                 // check end line of screen
1411                                 if(!(y++ < 480)) {
1412                                         break;
1413                                 }
1414                                 if(dest >= 0) {
1415                                         // reverse, blink
1416                                         if(attr & 0x40) {
1417                                                 pat1 = ((attr & 0x80) && blink) ? 0xff : ~pattern1[code + i];
1418                                         } else {
1419                                                 pat1 = ((attr & 0x80) && blink) ? 0x00 : pattern1[code + i];
1420                                         }
1421                                         memcpy(&text[dest], text_matrixw[pat1][col], 16);
1422                                 }
1423                                 dest += 640;
1424                         }
1425                 }
1426         }
1427 }
1428
1429 // ----------------------------------------------------------------------------
1430 // drive cg screen
1431 // ----------------------------------------------------------------------------
1432
1433 void CRTC::draw_cg()
1434 {
1435         // draw cg screen
1436         switch(cgreg[0x0e]) {
1437         case 0x03:
1438                 draw_640x400x4screen();
1439                 break;
1440         case 0x14:
1441                 draw_320x200x16screen(0);
1442                 draw_320x200x16screen(1);
1443                 break;
1444         case 0x15:
1445                 draw_320x200x16screen(1);
1446                 draw_320x200x16screen(0);
1447                 break;
1448         case 0x17:
1449                 draw_640x200x16screen(0);
1450                 break;
1451         case 0x1d:
1452                 draw_320x200x256screen(0);
1453                 break;
1454         case 0x93:
1455                 draw_640x400x16screen();
1456                 break;
1457         case 0x94:
1458                 draw_320x200x16screen(2);
1459                 draw_320x200x16screen(3);
1460                 break;
1461         case 0x95:
1462                 draw_320x200x16screen(3);
1463                 draw_320x200x16screen(2);
1464                 break;
1465         case 0x97:
1466                 draw_640x200x16screen(1);
1467                 break;
1468         case 0x9d:
1469                 draw_320x200x256screen(1);
1470                 break;
1471         }
1472         
1473         // fill scan line
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);
1477                 }
1478         }
1479 }
1480
1481 void CRTC::draw_320x200x16screen(uint8_t pl)
1482 {
1483         uint8_t B, R, G, I, col;
1484         uint32_t dest = 0;
1485         
1486         if(map_init) {
1487                 create_addr_map(40, 200);
1488         }
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];
1493                         dest += 16;
1494                         
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;
1500                         } else {
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;
1505                         }
1506                         
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;
1515                 }
1516                 dest += 640;
1517         }
1518 }
1519
1520 void CRTC::draw_320x200x256screen(uint8_t pl)
1521 {
1522         uint8_t B0, B1, R0, R1, G0, G1, I0, I1;
1523         uint32_t dest = 0;
1524         
1525         if(map_init) {
1526                 create_addr_map(40, 200);
1527         }
1528         if(cg_mask256_init) {
1529                 cg_mask256 = cgreg[0x18];
1530                 if(!(cg_mask & 1)) {
1531                         cg_mask256 &= ~(0x11 | 0x88);
1532                 }
1533                 if(!(cg_mask & 2)) {
1534                         cg_mask256 &= ~0x22;
1535                 }
1536                 if(!(cg_mask & 4)) {
1537                         cg_mask256 &= ~0x44;
1538                 }
1539                 cg_mask256_init = false;
1540         }
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];
1546                         dest += 16;
1547                         
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;
1556                         
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];
1565                 }
1566                 dest += 640;
1567         }
1568 }
1569
1570 void CRTC::draw_640x200x16screen(uint8_t pl)
1571 {
1572         uint8_t B, R, G, I;
1573         uint32_t dest = 0;
1574         
1575         if(map_init) {
1576                 create_addr_map(80, 200);
1577         }
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];
1582                         dest += 8;
1583                         
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;
1588                         
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];
1597                 }
1598                 dest += 640;
1599         }
1600 }
1601
1602 void CRTC::draw_640x400x4screen()
1603 {
1604         uint8_t B, R;
1605         uint32_t dest = 0;
1606         // for Yukara K2
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;
1609         
1610         if(map_init) {
1611                 create_addr_map(80, 400);
1612         }
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];
1617                         dest += 8;
1618                         
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;
1621                         
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];
1630                 }
1631         }
1632 }
1633
1634 void CRTC::draw_640x400x16screen()
1635 {
1636         uint8_t B, R, G, I;
1637         uint32_t dest = 0;
1638         
1639         if(map_init) {
1640                 create_addr_map(80, 400);
1641         }
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];
1646                         dest += 8;
1647                         
1648                         B = vram_b[src];
1649                         R = vram_r[src];
1650                         G = vram_g[src];
1651                         I = vram_i[src];
1652                         
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];
1661                 }
1662         }
1663 }
1664
1665 void CRTC::create_addr_map(int xmax, int ymax)
1666 {
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);
1672         
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);
1678                 }
1679         }
1680         for(int y = SLN1; y < ymax; y++) {
1681                 for(int x = 0; x < xmax; x++) {
1682                         map_hdsc[y][x] = 0;
1683                         map_addr[y][x] = (SAD2++) & 0x7fff;
1684                 }
1685         }
1686         map_init = false;
1687 }
1688
1689 #define STATE_VERSION   1
1690
1691 void CRTC::save_state(FILEIO* state_fio)
1692 {
1693         state_fio->FputUint32(STATE_VERSION);
1694         state_fio->FputInt32(this_device_id);
1695         
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);
1750 }
1751
1752 bool CRTC::load_state(FILEIO* state_fio)
1753 {
1754         if(state_fio->FgetUint32() != STATE_VERSION) {
1755                 return false;
1756         }
1757         if(state_fio->FgetInt32() != this_device_id) {
1758                 return false;
1759         }
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();
1814         return true;
1815 }
1816