OSDN Git Service

bcf265fcf8ee69b1bfbcf942845ac8b0e1a7cf78
[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         emu->set_vm_screen_lines(ve);
712
713         // mix screens
714         emu->set_vm_screen_lines(ve);
715         
716         if(screen_mask) {
717                 // screen is masked
718                 for(int y = 0; y < 400; y++) {
719                         scrntype_t *dest = emu->get_screen_buffer(y);
720                         memset(dest, 0, sizeof(scrntype_t) * 640);
721                 }
722         } else if(cgreg[0x0e] == 0x1d || cgreg[0x0e] == 0x9d) {
723                 // 256 colors
724                 for(int y = 0; y < vs && y < 400; y++) {
725                         scrntype_t *dest = emu->get_screen_buffer(y);
726                         uint8_t *src_text = &text[640 * y];
727                         for(int x = 0; x < 640; x++) {
728                                 dest[x] = palette256txt[src_text[x]];
729                         }
730                 }
731                 for(int y = vs; y < ve && y < 400; y++) {
732                         scrntype_t *dest = emu->get_screen_buffer(y);
733                         uint8_t *src_cg = &cg[640 * y], *src_text = &text[640 * y];
734                         for(int x = 0; x < hs && x < 640; x++) {
735                                 dest[x] = palette256txt[src_text[x]];
736                         }
737                         for(int x = hs; x < he && x < 640; x++) {
738                                 dest[x] = palette256pri[src_cg[x]][src_text[x]];
739                         }
740                         for(int x = he; x < 640; x++) {
741                                 dest[x] = palette256txt[src_text[x]];
742                         }
743                 }
744                 for(int y = ve; y < 400; y++) {
745                         scrntype_t *dest = emu->get_screen_buffer(y);
746                         uint8_t *src_text = &text[640 * y];
747                         for(int x = 0; x < 640; x++) {
748                                 dest[x] = palette256txt[src_text[x]];
749                         }
750                 }
751         } else if(!pal_select) {
752                 // 16 colors
753                 for(int y = 0; y < vs && y < 400; y++) {
754                         scrntype_t *dest = emu->get_screen_buffer(y);
755                         uint8_t *src_cg = &cg[640 * y], *src_text = &text[640 * y];
756                         for(int x = 0; x < 640; x++) {
757                                 dest[x] = palette16txt[src_text[x]];
758                         }
759                 }
760                 for(int y = vs; y < ve && y < 400; y++) {
761                         scrntype_t *dest = emu->get_screen_buffer(y);
762                         uint8_t *src_cg = &cg[640 * y], *src_text = &text[640 * y];
763                         for(int x = 0; x < hs && x < 640; x++) {
764                                 dest[x] = palette16txt[src_text[x]];
765                         }
766                         for(int x = hs; x < he && x < 640; x++) {
767                                 dest[x] = palette16pri[src_cg[x]][src_text[x]];
768                         }
769                         for(int x = he; x < 640; x++) {
770                                 dest[x] = palette16txt[src_text[x]];
771                         }
772                 }
773                 for(int y = ve; y < 400; y++) {
774                         scrntype_t *dest = emu->get_screen_buffer(y);
775                         uint8_t *src_cg = &cg[640 * y], *src_text = &text[640 * y];
776                         for(int x = 0; x < 640; x++) {
777                                 dest[x] = palette16txt[src_text[x]];
778                         }
779                 }
780         } else {
781                 // 4096 colors
782                 for(int y = 0; y < vs && y < 400; y++) {
783                         scrntype_t *dest = emu->get_screen_buffer(y);
784                         uint8_t *src_cg = &cg[640 * y], *src_text = &text[640 * y];
785                         for(int x = 0; x < 640; x++) {
786                                 dest[x] = palette4096txt[src_text[x]];
787                         }
788                 }
789                 for(int y = vs; y < ve && y < 400; y++) {
790                         scrntype_t *dest = emu->get_screen_buffer(y);
791                         uint8_t *src_cg = &cg[640 * y], *src_text = &text[640 * y];
792                         for(int x = 0; x < hs && x < 640; x++) {
793                                 dest[x] = palette4096txt[src_text[x]];
794                         }
795                         for(int x = hs; x < he && x < 640; x++) {
796                                 dest[x] = palette4096pri[src_cg[x]][src_text[x]];
797                         }
798                         for(int x = he; x < 640; x++) {
799                                 dest[x] = palette4096txt[src_text[x]];
800                         }
801                 }
802                 for(int y = ve; y < 400; y++) {
803                         scrntype_t *dest = emu->get_screen_buffer(y);
804                         uint8_t *src_cg = &cg[640 * y], *src_text = &text[640 * y];
805                         for(int x = 0; x < 640; x++) {
806                                 dest[x] = palette4096txt[src_text[x]];
807                         }
808                 }
809         }
810         emu->screen_skip_line(monitor_200line);
811 }
812
813 // ----------------------------------------------------------------------------
814 // draw text screen
815 // ----------------------------------------------------------------------------
816
817 void CRTC::draw_text()
818 {
819         // extract text optimization matrix
820         if(trans_init) {
821                 trans_color = (textreg[0] & 2) ? 8 : 0;
822                 for(int pat = 0; pat < 256; pat++) {
823                         for(int col = 0; col < 8; col++) {
824                                 int fore_color = col ? col : 8;
825                                 text_matrix[pat][col][0] = text_matrixw[pat][col][ 0] = text_matrixw[pat][col][ 1] = (pat & 0x80) ? fore_color : trans_color;
826                                 text_matrix[pat][col][1] = text_matrixw[pat][col][ 2] = text_matrixw[pat][col][ 3] = (pat & 0x40) ? fore_color : trans_color;
827                                 text_matrix[pat][col][2] = text_matrixw[pat][col][ 4] = text_matrixw[pat][col][ 5] = (pat & 0x20) ? fore_color : trans_color;
828                                 text_matrix[pat][col][3] = text_matrixw[pat][col][ 6] = text_matrixw[pat][col][ 7] = (pat & 0x10) ? fore_color : trans_color;
829                                 text_matrix[pat][col][4] = text_matrixw[pat][col][ 8] = text_matrixw[pat][col][ 9] = (pat & 0x08) ? fore_color : trans_color;
830                                 text_matrix[pat][col][5] = text_matrixw[pat][col][10] = text_matrixw[pat][col][11] = (pat & 0x04) ? fore_color : trans_color;
831                                 text_matrix[pat][col][6] = text_matrixw[pat][col][12] = text_matrixw[pat][col][13] = (pat & 0x02) ? fore_color : trans_color;
832                                 text_matrix[pat][col][7] = text_matrixw[pat][col][14] = text_matrixw[pat][col][15] = (pat & 0x01) ? fore_color : trans_color;
833                         }
834                 }
835                 trans_init = false;
836         }
837         
838         // draw text
839         if(column_size) {
840                 draw_80column_screen();
841         } else {
842                 draw_40column_screen();
843         }
844         
845         // display period
846         int SL, EL, SC, EC;
847         if(monitor_200line) {
848                 // 200 lines
849                 SL = (textreg[3] - 38) << 1;
850                 EL = (textreg[5] - 38) << 1;
851                 if(column_size) {
852                         // 80 column
853                         SC = (textreg[7] & 0x7f) - 11;
854                         EC = (textreg[8] & 0x7f) - 11;
855                 } else {
856                         // 40 column
857                         SC = (textreg[7] & 0x7f) - 10;
858                         EC = (textreg[8] & 0x7f) - 10;
859                 }
860         } else {
861                 // 400 lines
862                 SL = (textreg[3] - 17) << 1;
863                 EL = (textreg[5] - 17) << 1;
864                 if(column_size) {
865                         // 80 colums
866                         SC = (textreg[7] & 0x7f) - 9;
867                         EC = (textreg[8] & 0x7f) - 9;
868                 } else {
869                         // 40 column
870                         SC = (textreg[7] & 0x7f) - 8;
871                         EC = (textreg[8] & 0x7f) - 8;
872                 }
873         }
874         SL = (SL < 0) ? 0 : (SL > 400) ? 400 : SL;
875         EL = (EL < 0) ? 0 : (EL > 400) ? 400 : EL;
876         SC = (SC < 0) ? 0 : (SC > 80) ? 80 : SC;
877         EC = (EC < 0) ? 0 : (EC > 80) ? 80 : EC;
878         
879         if(EL >= SL) {
880                 for(int y = 0; y < SL; y++) {
881                         memset(text + 640 * y, trans_color, 640);
882                 }
883                 for(int y = EL; y < 400; y++) {
884                         memset(text + 640 * y, trans_color, 640);
885                 }
886         } else {
887                 for(int y = EL; y < SL; y++) {
888                         memset(text + 640 * y, trans_color, 640);
889                 }
890         }
891         if(EC >= SC) {
892                 for(int y = 0; y < 400; y++) {
893                         memset(text + 640 * y, trans_color, SC << 3);
894                         memset(text + 640 * y + (EC << 3), trans_color, (80 - EC) << 3);
895                 }
896         } else {
897                 for(int y = 0; y < 400; y++) {
898                         memset(text + 640 * y + (EC << 3), trans_color, (SC - EC) << 3);
899                 }
900         }
901 }
902
903 void CRTC::draw_80column_screen()
904 {
905         uint16_t src = textreg[1] | ((textreg[2] & 0x07) << 8);
906         uint8_t line = (textreg[0] & 0x10) ? 2 : 0;
907         uint8_t height = (textreg[0] & 0x10) ? 20 : 16;
908         uint8_t vd = (textreg[9] & 0x0f) << 1;
909         
910         // 80x20(25)
911         for(int y = line; y < 416; y += height) {
912                 int dest = (y - vd) * 640;
913                 for(int x = 0; x < 80; x++) {
914                         draw_80column_font((src++) & 0x7ff, dest, y - vd);
915                         dest += 8;
916                 }
917         }
918 }
919
920 void CRTC::draw_40column_screen()
921 {
922         uint16_t src1 = textreg[1] | ((textreg[2] & 0x07) << 8);
923         uint16_t src2 = src1 + 0x400;
924         uint8_t line = (textreg[0] & 0x10) ? 2 : 0;
925         uint8_t height = (textreg[0] & 0x10) ? 20 : 16;
926         uint8_t vd = (textreg[9] & 0x0f) << 1;
927         
928         switch(textreg[0] & 0x0c) {
929         case 0x00:
930                 // 40x20(25), 64colors
931                 for(int y = line; y < 416; y += height) {
932                         int dest1 = (y - vd) * 640;
933                         int dest2 = (y - vd) * 640 + 640 * 480;
934                         for(int x = 0; x < 40; x++) {
935                                 draw_40column_font((src1++) & 0x7ff, dest1, y - vd);
936                                 draw_40column_font((src2++) & 0x7ff, dest2, y - vd);
937                                 dest1 += 16;
938                                 dest2 += 16;
939                         }
940                 }
941                 for(int y = 0; y < 400; y++) {
942                         uint32_t src1 = 640 * y;
943                         uint32_t src2 = 640 * y + 640 * 480;
944                         uint32_t dest = 640 * y;
945                         uint8_t col;
946                         for(int x = 0; x < 640; x++) {
947                                 if((text[src1] & 8) && (text[src2] & 8)) {
948                                         col = 8; // non transparent black
949                                 } else {
950                                         col = (((text[src1] & 7) << 3) | (text[src2] & 7)) + 16;
951                                 }
952                                 text[dest++] = col;
953                                 src1++;
954                                 src2++;
955                         }
956                 }
957                 break;
958         case 0x04:
959                 // 40x20(25), No.1 Screen
960                 for(int y = line; y < 416; y += height) {
961                         int dest = (y - vd) * 640;
962                         for(int x = 0; x < 40; x++) {
963                                 draw_40column_font((src1++) & 0x7ff, dest, y - vd);
964                                 dest += 16;
965                         }
966                 }
967                 break;
968         case 0x08:
969                 // 40x20(25), No.2 Screen
970                 for(int y = line; y < 416; y += height) {
971                         int dest = (y - vd) * 640;
972                         for(int x = 0; x < 40; x++) {
973                                 draw_40column_font((src2++) & 0x7ff, dest, y - vd);
974                                 dest += 16;
975                         }
976                 }
977                 break;
978         case 0x0c:
979                 // 40x20(25), No.1 + No.2 Screens (No.1 > No.2)
980                 for(int y = line; y < 416; y += height) {
981                         int dest = (y - vd) * 640;
982                         for(int x = 0; x < 40; x++) {
983                                 draw_40column_font((src1++) & 0x7ff, dest, y - vd);
984                                 dest += 16;
985                         }
986                 }
987                 for(int y = line; y < 416; y += height) {
988                         int dest = (y - vd) * 640 + 640 * 480;
989                         for(int x = 0; x < 40; x++) {
990                                 draw_40column_font((src2++) & 0x7ff, dest, y - vd);
991                                 dest += 16;
992                         }
993                 }
994                 for(int y = line; y < 400; y++) {
995                         int dest = (y - vd) * 640;
996                         uint8_t* tsrc1 = &text[dest];
997                         uint8_t* tsrc2 = &text[dest + 640 * 480];
998                         uint8_t* tdest = &text[dest];
999                         for(int x = 0; x < 640; x++) {
1000                                 tdest[x] = (tsrc1[x] & 7) ? tsrc1[x] : (tsrc2[x] & 7) ? tsrc2[x] : ((tsrc1[x] & 8) | (tsrc2[x] & 8));
1001                         }
1002                 }
1003                 break;
1004         }
1005 }
1006
1007 void CRTC::draw_80column_font(uint16_t src, int dest, int y)
1008 {
1009         // draw char (80 column)
1010         uint8_t* pattern1;
1011         uint8_t* pattern2;
1012         uint8_t* pattern3;
1013         
1014         uint32_t code;
1015         uint8_t sel, col, pat1, pat2, pat3;
1016         uint8_t t1 = tvram1[src], t2 = tvram2[src], attr = attrib[src];
1017         
1018         // select char type
1019         sel = (t2 & 0xc0) | (attr & 0x38);
1020         switch(sel) {
1021         case 0x00: case 0x40:
1022                 pattern1 = pcg0;
1023                 break;
1024         case 0x80:
1025                 pattern1 = kanji1;
1026                 break;
1027         case 0xc0:
1028                 pattern1 = kanji2;
1029                 break;
1030         case 0x10: case 0x50: case 0x90: case 0xd0:
1031                 pattern1 = pcg1;
1032                 break;
1033         case 0x20: case 0x60: case 0xa0: case 0xe0:
1034                 pattern1 = pcg2;
1035                 break;
1036         case 0x30: case 0x70: case 0xb0: case 0xf0:
1037                 pattern1 = pcg3;
1038                 break;
1039         default:
1040                 pattern1 = pcg1;
1041                 pattern2 = pcg2;
1042                 pattern3 = pcg3;
1043                 break;
1044         }
1045         if(sel & 8) {
1046                 // PCG1 + PCG2 + PCG3 8colors
1047                 
1048                 // generate addr
1049                 code = font_size ? t1 << 3 : (t1 & 0xfe) << 3;
1050                 // draw
1051                 if(font_size) {
1052                         for(int i = 0; i < 8; i++) {
1053                                 // check end line of screen
1054                                 if(!(y++ < 480)) {
1055                                         break;
1056                                 }
1057                                 if((attr & 0x80) && blink) {
1058                                         // blink
1059                                         uint8_t val = (attr & 0x40) ? 7 : trans_color;
1060                                         if(dest >= 0) {
1061                                                 memset(text + dest, val, 8);
1062                                         }
1063                                         dest += 640;
1064                                         // check end line of screen
1065                                         if(!(y++ < 480)) {
1066                                                 break;
1067                                         }
1068                                         if(dest >= 0 && !scan_line) {
1069                                                 memset(text + dest, val, 8);
1070                                         }
1071                                         dest += 640;
1072                                 } else {
1073                                         if(attr & 0x40) {
1074                                                 pat1 = ~pattern1[code + i];
1075                                                 pat2 = ~pattern2[code + i];
1076                                                 pat3 = ~pattern3[code + i];
1077                                         } else {
1078                                                 pat1 = pattern1[code + i];
1079                                                 pat2 = pattern2[code + i];
1080                                                 pat3 = pattern3[code + i];
1081                                         }
1082                                         if(dest >= 0) {
1083                                                 uint8_t* tdest = &text[dest];
1084                                                 col = ((pat1 & 0x80) >> 7) | ((pat2 & 0x80) >> 6) | ((pat3 & 0x80) >> 5); tdest[0] = col ? col : trans_color;
1085                                                 col = ((pat1 & 0x40) >> 6) | ((pat2 & 0x40) >> 5) | ((pat3 & 0x40) >> 4); tdest[1] = col ? col : trans_color;
1086                                                 col = ((pat1 & 0x20) >> 5) | ((pat2 & 0x20) >> 4) | ((pat3 & 0x20) >> 3); tdest[2] = col ? col : trans_color;
1087                                                 col = ((pat1 & 0x10) >> 4) | ((pat2 & 0x10) >> 3) | ((pat3 & 0x10) >> 2); tdest[3] = col ? col : trans_color;
1088                                                 col = ((pat1 & 0x08) >> 3) | ((pat2 & 0x08) >> 2) | ((pat3 & 0x08) >> 1); tdest[4] = col ? col : trans_color;
1089                                                 col = ((pat1 & 0x04) >> 2) | ((pat2 & 0x04) >> 1) | ((pat3 & 0x04)     ); tdest[5] = col ? col : trans_color;
1090                                                 col = ((pat1 & 0x02) >> 1) | ((pat2 & 0x02)     ) | ((pat3 & 0x02) << 1); tdest[6] = col ? col : trans_color;
1091                                                 col = ((pat1 & 0x01)     ) | ((pat2 & 0x01) << 1) | ((pat3 & 0x01) << 2); tdest[7] = col ? col : trans_color;
1092                                         }
1093                                         dest += 640;
1094                                         // check end line of screen
1095                                         if(!(y++ < 480)) {
1096                                                 break;
1097                                         }
1098                                         if(dest >= 0 && !scan_line) {
1099                                                 if(dest >= 640) {
1100                                                         memcpy(text + dest, text + dest - 640, 8);
1101                                                 } else {
1102                                                         uint8_t* tdest = &text[dest];
1103                                                         col = ((pat1 & 0x80) >> 7) | ((pat2 & 0x80) >> 6) | ((pat3 & 0x80) >> 5); tdest[0] = col ? col : trans_color;
1104                                                         col = ((pat1 & 0x40) >> 6) | ((pat2 & 0x40) >> 5) | ((pat3 & 0x40) >> 4); tdest[1] = col ? col : trans_color;
1105                                                         col = ((pat1 & 0x20) >> 5) | ((pat2 & 0x20) >> 4) | ((pat3 & 0x20) >> 3); tdest[2] = col ? col : trans_color;
1106                                                         col = ((pat1 & 0x10) >> 4) | ((pat2 & 0x10) >> 3) | ((pat3 & 0x10) >> 2); tdest[3] = col ? col : trans_color;
1107                                                         col = ((pat1 & 0x08) >> 3) | ((pat2 & 0x08) >> 2) | ((pat3 & 0x08) >> 1); tdest[4] = col ? col : trans_color;
1108                                                         col = ((pat1 & 0x04) >> 2) | ((pat2 & 0x04) >> 1) | ((pat3 & 0x04)     ); tdest[5] = col ? col : trans_color;
1109                                                         col = ((pat1 & 0x02) >> 1) | ((pat2 & 0x02)     ) | ((pat3 & 0x02) << 1); tdest[6] = col ? col : trans_color;
1110                                                         col = ((pat1 & 0x01)     ) | ((pat2 & 0x01) << 1) | ((pat3 & 0x01) << 2); tdest[7] = col ? col : trans_color;
1111                                                 }
1112                                         }
1113                                         dest += 640;
1114                                 }
1115                         }
1116                 } else {
1117                         for(int i = 0; i < 16; i++) {
1118                                 // check end line of screen
1119                                 if(!(y++ < 480)) {
1120                                         break;
1121                                 }
1122                                 if(dest >= 0) {
1123                                         if((attr & 0x80) && blink) {
1124                                                 if(attr & 0x40) {
1125                                                         memset(text + dest, 7, 8);
1126                                                 } else {
1127                                                         memset(text + dest, trans_color, 8);
1128                                                 }
1129                                         } else {
1130                                                 if(attr & 0x40) {
1131                                                         pat1 = ~pattern1[code + i];
1132                                                         pat2 = ~pattern2[code + i];
1133                                                         pat3 = ~pattern3[code + i];
1134                                                 } else {
1135                                                         pat1 = pattern1[code + i];
1136                                                         pat2 = pattern2[code + i];
1137                                                         pat3 = pattern3[code + i];
1138                                                 }
1139                                                 uint8_t* tdest = &text[dest];
1140                                                 col = ((pat1 & 0x80) >> 7) | ((pat2 & 0x80) >> 6) | ((pat3 & 0x80) >> 5); tdest[0] = col ? col : trans_color;
1141                                                 col = ((pat1 & 0x40) >> 6) | ((pat2 & 0x40) >> 5) | ((pat3 & 0x40) >> 4); tdest[1] = col ? col : trans_color;
1142                                                 col = ((pat1 & 0x20) >> 5) | ((pat2 & 0x20) >> 4) | ((pat3 & 0x20) >> 3); tdest[2] = col ? col : trans_color;
1143                                                 col = ((pat1 & 0x10) >> 4) | ((pat2 & 0x10) >> 3) | ((pat3 & 0x10) >> 2); tdest[3] = col ? col : trans_color;
1144                                                 col = ((pat1 & 0x08) >> 3) | ((pat2 & 0x08) >> 2) | ((pat3 & 0x08) >> 1); tdest[4] = col ? col : trans_color;
1145                                                 col = ((pat1 & 0x04) >> 2) | ((pat2 & 0x04) >> 1) | ((pat3 & 0x04)     ); tdest[5] = col ? col : trans_color;
1146                                                 col = ((pat1 & 0x02) >> 1) | ((pat2 & 0x02)     ) | ((pat3 & 0x02) << 1); tdest[6] = col ? col : trans_color;
1147                                                 col = ((pat1 & 0x01)     ) | ((pat2 & 0x01) << 1) | ((pat3 & 0x01) << 2); tdest[7] = col ? col : trans_color;
1148                                         }
1149                                 }
1150                                 dest += 640;
1151                         }
1152                 }
1153         } else {
1154                 // monochrome
1155                 
1156                 // generate addr
1157                 if(font_size) {
1158                         if(sel == 0x80 || sel == 0xc0) {
1159                                 code = ((t2 & 0x3f) << 11) | (t1 << 3);
1160                         } else {
1161                                 code = t1 << 3;
1162                         }
1163                 } else {
1164                         if(sel == 0x80 || sel == 0xc0) {
1165                                 code = ((t2 & 0x3f) << 11) | ((t1 & 0xfe) << 3);
1166                         } else {
1167                                 code = (t1 & 0xfe) << 3;
1168                         }
1169                 }
1170                 // color
1171                 col = attr & 0x07;
1172                 // draw
1173                 if(font_size) {
1174                         uint32_t dest1 = dest;
1175                         uint32_t dest2 = (dest >= 640 * 399) ? dest - 640 * 399 : dest + 640;
1176                         for(int i = 0; i < 8; i++) {
1177                                 // check end line of screen
1178                                 if(!(y++ < 480)) {
1179                                         break;
1180                                 }
1181                                 // reverse, blink
1182                                 if(attr & 0x40) {
1183                                         pat1 = ((attr & 0x80) && blink) ? 0xff : ~pattern1[code + i];
1184                                 } else {
1185                                         pat1 = ((attr & 0x80) && blink) ? 0x00 : pattern1[code + i];
1186                                 }
1187                                 if(dest >= 0) {
1188                                         memcpy(&text[dest], text_matrix[pat1][col], 8);
1189                                 }
1190                                 dest += 640;
1191                                 // check end line of screen
1192                                 if(!(y++ < 480)) {
1193                                         break;
1194                                 }
1195                                 if(dest >= 0 && !scan_line) {
1196                                         memcpy(&text[dest], text_matrix[pat1][col], 8);
1197                                 }
1198                                 dest += 640;
1199                         }
1200                 } else {
1201                         for(int i = 0; i < 16; i++) {
1202                                 // check end line of screen
1203                                 if(!(y++ < 480)) {
1204                                         break;
1205                                 }
1206                                 if(dest >= 0) {
1207                                         // reverse, blink
1208                                         if(attr & 0x40) {
1209                                                 pat1 = ((attr & 0x80) && blink) ? 0xff : ~pattern1[code + i];
1210                                         } else {
1211                                                 pat1 = ((attr & 0x80) && blink) ? 0x00 : pattern1[code + i];
1212                                         }
1213                                         memcpy(&text[dest], text_matrix[pat1][col], 8);
1214                                 }
1215                                 dest += 640;
1216                         }
1217                 }
1218         }
1219 }
1220
1221 void CRTC::draw_40column_font(uint16_t src, int dest, int y)
1222 {
1223         // draw char (40 column)
1224         uint8_t* pattern1;
1225         uint8_t* pattern2;
1226         uint8_t* pattern3;
1227         
1228         uint32_t code;
1229         uint8_t sel, col, pat1, pat2, pat3;
1230         uint8_t t1 = tvram1[src], t2 = tvram2[src], attr = attrib[src];
1231         
1232         // select char type
1233         sel = (t2 & 0xc0) | (attr & 0x38);
1234         switch(sel) {
1235         case 0x00: case 0x40:
1236                 pattern1 = pcg0;
1237                 break;
1238         case 0x80:
1239                 pattern1 = kanji1;
1240                 break;
1241         case 0xc0:
1242                 pattern1 = kanji2;
1243                 break;
1244         case 0x10: case 0x50: case 0x90: case 0xd0:
1245                 pattern1 = pcg1;
1246                 break;
1247         case 0x20: case 0x60: case 0xa0: case 0xe0:
1248                 pattern1 = pcg2;
1249                 break;
1250         case 0x30: case 0x70: case 0xb0: case 0xf0:
1251                 pattern1 = pcg3;
1252                 break;
1253         default:
1254                 pattern1 = pcg1;
1255                 pattern2 = pcg2;
1256                 pattern3 = pcg3;
1257                 break;
1258         }
1259         if(sel & 0x08) {
1260                 // PCG1 + PCG2 + PCG3 8colors
1261                 
1262                 // generate addr
1263                 code = font_size ? t1 << 3 : (t1 & 0xfe) << 3;
1264                 // draw
1265                 if(font_size) {
1266                         for(int i = 0; i < 8; i++) {
1267                                 // check end line of screen
1268                                 if(!(y++ < 480)) {
1269                                         break;
1270                                 }
1271                                 if((attr & 0x80) && blink) {
1272                                         // blink
1273                                         uint8_t val = (attr & 0x40) ? 7 : trans_color;
1274                                         if(dest >= 0) {
1275                                                 memset(text + dest, val, 16);
1276                                         }
1277                                         dest += 640;
1278                                         // check end line of screen
1279                                         if(!(y++ < 480)) {
1280                                                 break;
1281                                         }
1282                                         if(dest >= 0 && !scan_line) {
1283                                                 memset(text + dest, val, 16);
1284                                         }
1285                                         dest += 640;
1286                                 } else {
1287                                         if(attr & 0x40) {
1288                                                 pat1 = ~pattern1[code + i];
1289                                                 pat2 = ~pattern2[code + i];
1290                                                 pat3 = ~pattern3[code + i];
1291                                         } else {
1292                                                 pat1 = pattern1[code + i];
1293                                                 pat2 = pattern2[code + i];
1294                                                 pat3 = pattern3[code + i];
1295                                         }
1296                                         if(dest >= 0) {
1297                                                 uint8_t* tdest = &text[dest];
1298                                                 col = ((pat1 & 0x80) >> 7) | ((pat2 & 0x80) >> 6) | ((pat3 & 0x80) >> 5); tdest[ 0] = tdest[ 1] = col ? col : trans_color;
1299                                                 col = ((pat1 & 0x40) >> 6) | ((pat2 & 0x40) >> 5) | ((pat3 & 0x40) >> 4); tdest[ 2] = tdest[ 3] = col ? col : trans_color;
1300                                                 col = ((pat1 & 0x20) >> 5) | ((pat2 & 0x20) >> 4) | ((pat3 & 0x20) >> 3); tdest[ 4] = tdest[ 5] = col ? col : trans_color;
1301                                                 col = ((pat1 & 0x10) >> 4) | ((pat2 & 0x10) >> 3) | ((pat3 & 0x10) >> 2); tdest[ 6] = tdest[ 7] = col ? col : trans_color;
1302                                                 col = ((pat1 & 0x08) >> 3) | ((pat2 & 0x08) >> 2) | ((pat3 & 0x08) >> 1); tdest[ 8] = tdest[ 9] = col ? col : trans_color;
1303                                                 col = ((pat1 & 0x04) >> 2) | ((pat2 & 0x04) >> 1) | ((pat3 & 0x04)     ); tdest[10] = tdest[11] = col ? col : trans_color;
1304                                                 col = ((pat1 & 0x02) >> 1) | ((pat2 & 0x02)     ) | ((pat3 & 0x02) << 1); tdest[12] = tdest[13] = col ? col : trans_color;
1305                                                 col = ((pat1 & 0x01)     ) | ((pat2 & 0x01) << 1) | ((pat3 & 0x01) << 2); tdest[14] = tdest[15] = col ? col : trans_color;
1306                                         }
1307                                         dest += 640;
1308                                         // check end line of screen
1309                                         if(!(y++ < 480)) {
1310                                                 break;
1311                                         }
1312                                         if(dest >= 0 && !scan_line) {
1313                                                 if(dest >= 640) {
1314                                                         memcpy(text + dest, text + dest - 640, 16);
1315                                                 } else {
1316                                                         uint8_t* tdest = &text[dest];
1317                                                         col = ((pat1 & 0x80) >> 7) | ((pat2 & 0x80) >> 6) | ((pat3 & 0x80) >> 5); tdest[ 0] = tdest[ 1] = col ? col : trans_color;
1318                                                         col = ((pat1 & 0x40) >> 6) | ((pat2 & 0x40) >> 5) | ((pat3 & 0x40) >> 4); tdest[ 2] = tdest[ 3] = col ? col : trans_color;
1319                                                         col = ((pat1 & 0x20) >> 5) | ((pat2 & 0x20) >> 4) | ((pat3 & 0x20) >> 3); tdest[ 4] = tdest[ 5] = col ? col : trans_color;
1320                                                         col = ((pat1 & 0x10) >> 4) | ((pat2 & 0x10) >> 3) | ((pat3 & 0x10) >> 2); tdest[ 6] = tdest[ 7] = col ? col : trans_color;
1321                                                         col = ((pat1 & 0x08) >> 3) | ((pat2 & 0x08) >> 2) | ((pat3 & 0x08) >> 1); tdest[ 8] = tdest[ 9] = col ? col : trans_color;
1322                                                         col = ((pat1 & 0x04) >> 2) | ((pat2 & 0x04) >> 1) | ((pat3 & 0x04)     ); tdest[10] = tdest[11] = col ? col : trans_color;
1323                                                         col = ((pat1 & 0x02) >> 1) | ((pat2 & 0x02)     ) | ((pat3 & 0x02) << 1); tdest[12] = tdest[13] = col ? col : trans_color;
1324                                                         col = ((pat1 & 0x01)     ) | ((pat2 & 0x01) << 1) | ((pat3 & 0x01) << 2); tdest[14] = tdest[15] = col ? col : trans_color;
1325                                                 }
1326                                         }
1327                                         dest += 640;
1328                                 }
1329                         }
1330                 } else {
1331                         for(int i = 0; i < 16; i++) {
1332                                 // check end line of screen
1333                                 if(!(y++ < 480)) {
1334                                         break;
1335                                 }
1336                                 if(dest >= 0) {
1337                                         if((attr & 0x80) && blink) {
1338                                                 if(attr & 0x40) {
1339                                                         memset(text + dest, 7, 16);
1340                                                 } else {
1341                                                         memset(text + dest, trans_color, 16);
1342                                                 }
1343                                         } else {
1344                                                 if(attr & 0x40) {
1345                                                         pat1 = ~pattern1[code + i];
1346                                                         pat2 = ~pattern2[code + i];
1347                                                         pat3 = ~pattern3[code + i];
1348                                                 } else {
1349                                                         pat1 = pattern1[code + i];
1350                                                         pat2 = pattern2[code + i];
1351                                                         pat3 = pattern3[code + i];
1352                                                 }
1353                                                 uint8_t* tdest = &text[dest];
1354                                                 col = ((pat1 & 0x80) >> 7) | ((pat2 & 0x80) >> 6) | ((pat3 & 0x80) >> 5); tdest[ 0] = tdest[ 1] = col ? col : trans_color;
1355                                                 col = ((pat1 & 0x40) >> 6) | ((pat2 & 0x40) >> 5) | ((pat3 & 0x40) >> 4); tdest[ 2] = tdest[ 3] = col ? col : trans_color;
1356                                                 col = ((pat1 & 0x20) >> 5) | ((pat2 & 0x20) >> 4) | ((pat3 & 0x20) >> 3); tdest[ 4] = tdest[ 5] = col ? col : trans_color;
1357                                                 col = ((pat1 & 0x10) >> 4) | ((pat2 & 0x10) >> 3) | ((pat3 & 0x10) >> 2); tdest[ 6] = tdest[ 7] = col ? col : trans_color;
1358                                                 col = ((pat1 & 0x08) >> 3) | ((pat2 & 0x08) >> 2) | ((pat3 & 0x08) >> 1); tdest[ 8] = tdest[ 9] = col ? col : trans_color;
1359                                                 col = ((pat1 & 0x04) >> 2) | ((pat2 & 0x04) >> 1) | ((pat3 & 0x04)     ); tdest[10] = tdest[11] = col ? col : trans_color;
1360                                                 col = ((pat1 & 0x02) >> 1) | ((pat2 & 0x02)     ) | ((pat3 & 0x02) << 1); tdest[12] = tdest[13] = col ? col : trans_color;
1361                                                 col = ((pat1 & 0x01)     ) | ((pat2 & 0x01) << 1) | ((pat3 & 0x01) << 2); tdest[14] = tdest[15] = col ? col : trans_color;
1362                                         }
1363                                 }
1364                                 dest += 640;
1365                         }
1366                 }
1367         } else {
1368                 // monochrome
1369                 
1370                 // generate addr
1371                 if(font_size) {
1372                         if(sel == 0x80 || sel == 0xc0) {
1373                                 code = ((t2 & 0x3f) << 11) | (t1 << 3);
1374                         } else {
1375                                 code = t1 << 3;
1376                         }
1377                 } else {
1378                         if(sel == 0x80 || sel == 0xc0) {
1379                                 code = ((t2 & 0x3f) << 11) | ((t1 & 0xfe) << 3);
1380                         } else {
1381                                 code = (t1 & 0xfe) << 3;
1382                         }
1383                 }
1384                 // color
1385                 col = attr & 0x07;
1386                 // draw
1387                 if(font_size) {
1388                         for(int i = 0; i < 8; i++) {
1389                                 // check end line of screen
1390                                 if(!(y++ < 480)) {
1391                                         break;
1392                                 }
1393                                 // reverse, blink
1394                                 if(attr & 0x40) {
1395                                         pat1 = ((attr & 0x80) && blink) ? 0xff : ~pattern1[code + i];
1396                                 } else {
1397                                         pat1 = ((attr & 0x80) && blink) ? 0x00 : pattern1[code + i];
1398                                 }
1399                                 if(dest >= 0) {
1400                                         memcpy(&text[dest], text_matrixw[pat1][col], 16);
1401                                 }
1402                                 dest += 640;
1403                                 // check end line of screen
1404                                 if(!(y++ < 480)) {
1405                                         break;
1406                                 }
1407                                 if(dest >= 0 && !scan_line) {
1408                                         memcpy(&text[dest], text_matrixw[pat1][col], 16);
1409                                 }
1410                                 dest += 640;
1411                         }
1412                 } else {
1413                         for(int i = 0; i < 16; i++) {
1414                                 // check end line of screen
1415                                 if(!(y++ < 480)) {
1416                                         break;
1417                                 }
1418                                 if(dest >= 0) {
1419                                         // reverse, blink
1420                                         if(attr & 0x40) {
1421                                                 pat1 = ((attr & 0x80) && blink) ? 0xff : ~pattern1[code + i];
1422                                         } else {
1423                                                 pat1 = ((attr & 0x80) && blink) ? 0x00 : pattern1[code + i];
1424                                         }
1425                                         memcpy(&text[dest], text_matrixw[pat1][col], 16);
1426                                 }
1427                                 dest += 640;
1428                         }
1429                 }
1430         }
1431 }
1432
1433 // ----------------------------------------------------------------------------
1434 // drive cg screen
1435 // ----------------------------------------------------------------------------
1436
1437 void CRTC::draw_cg()
1438 {
1439         // draw cg screen
1440         switch(cgreg[0x0e]) {
1441         case 0x03:
1442                 draw_640x400x4screen();
1443                 break;
1444         case 0x14:
1445                 draw_320x200x16screen(0);
1446                 draw_320x200x16screen(1);
1447                 break;
1448         case 0x15:
1449                 draw_320x200x16screen(1);
1450                 draw_320x200x16screen(0);
1451                 break;
1452         case 0x17:
1453                 draw_640x200x16screen(0);
1454                 break;
1455         case 0x1d:
1456                 draw_320x200x256screen(0);
1457                 break;
1458         case 0x93:
1459                 draw_640x400x16screen();
1460                 break;
1461         case 0x94:
1462                 draw_320x200x16screen(2);
1463                 draw_320x200x16screen(3);
1464                 break;
1465         case 0x95:
1466                 draw_320x200x16screen(3);
1467                 draw_320x200x16screen(2);
1468                 break;
1469         case 0x97:
1470                 draw_640x200x16screen(1);
1471                 break;
1472         case 0x9d:
1473                 draw_320x200x256screen(1);
1474                 break;
1475         }
1476         
1477         // fill scan line
1478         if(!scan_line && !(cgreg[0x0e] == 0x03 || cgreg[0x0e] == 0x93)) {
1479                 for(int y = 0; y < 400; y += 2) {
1480                         memcpy(cg + (y + 1) * 640, cg + y * 640, 640);
1481                 }
1482         }
1483 }
1484
1485 void CRTC::draw_320x200x16screen(uint8_t pl)
1486 {
1487         uint8_t B, R, G, I, col;
1488         uint32_t dest = 0;
1489         
1490         if(map_init) {
1491                 create_addr_map(40, 200);
1492         }
1493         for(int y = 0; y < 200; y++) {
1494                 for(int x = 0; x < 40; x++) {
1495                         uint16_t src = (map_addr[y][x] + (0x2000 * pl)) & 0x7fff;
1496                         uint32_t dest2 = dest + map_hdsc[y][x];
1497                         dest += 16;
1498                         
1499                         if(pl == 0 || pl == 2) {
1500                                 B = (cgreg[0x18] & 0x01) ? vram_b[src] : 0;
1501                                 R = (cgreg[0x18] & 0x02) ? vram_r[src] : 0;
1502                                 G = (cgreg[0x18] & 0x04) ? vram_g[src] : 0;
1503                                 I = (cgreg[0x18] & 0x08) ? vram_i[src] : 0;
1504                         } else {
1505                                 B = (cgreg[0x18] & 0x10) ? vram_b[src] : 0;
1506                                 R = (cgreg[0x18] & 0x20) ? vram_r[src] : 0;
1507                                 G = (cgreg[0x18] & 0x40) ? vram_g[src] : 0;
1508                                 I = (cgreg[0x18] & 0x80) ? vram_i[src] : 0;
1509                         }
1510                         
1511                         col = cg_matrix0[B][R][0] | cg_matrix1[G][I][0]; if(col) cg[dest2     ] = cg[dest2 +  1] = col;
1512                         col = cg_matrix0[B][R][1] | cg_matrix1[G][I][1]; if(col) cg[dest2 +  2] = cg[dest2 +  3] = col;
1513                         col = cg_matrix0[B][R][2] | cg_matrix1[G][I][2]; if(col) cg[dest2 +  4] = cg[dest2 +  5] = col;
1514                         col = cg_matrix0[B][R][3] | cg_matrix1[G][I][3]; if(col) cg[dest2 +  6] = cg[dest2 +  7] = col;
1515                         col = cg_matrix0[B][R][4] | cg_matrix1[G][I][4]; if(col) cg[dest2 +  8] = cg[dest2 +  9] = col;
1516                         col = cg_matrix0[B][R][5] | cg_matrix1[G][I][5]; if(col) cg[dest2 + 10] = cg[dest2 + 11] = col;
1517                         col = cg_matrix0[B][R][6] | cg_matrix1[G][I][6]; if(col) cg[dest2 + 12] = cg[dest2 + 13] = col;
1518                         col = cg_matrix0[B][R][7] | cg_matrix1[G][I][7]; if(col) cg[dest2 + 14] = cg[dest2 + 15] = col;
1519                 }
1520                 dest += 640;
1521         }
1522 }
1523
1524 void CRTC::draw_320x200x256screen(uint8_t pl)
1525 {
1526         uint8_t B0, B1, R0, R1, G0, G1, I0, I1;
1527         uint32_t dest = 0;
1528         
1529         if(map_init) {
1530                 create_addr_map(40, 200);
1531         }
1532         if(cg_mask256_init) {
1533                 cg_mask256 = cgreg[0x18];
1534                 if(!(cg_mask & 1)) {
1535                         cg_mask256 &= ~(0x11 | 0x88);
1536                 }
1537                 if(!(cg_mask & 2)) {
1538                         cg_mask256 &= ~0x22;
1539                 }
1540                 if(!(cg_mask & 4)) {
1541                         cg_mask256 &= ~0x44;
1542                 }
1543                 cg_mask256_init = false;
1544         }
1545         for(int y = 0; y < 200; y++) {
1546                 for(int x = 0; x < 40; x++) {
1547                         uint16_t src1 = (map_addr[y][x] + (0x4000 * pl)) & 0x7fff;
1548                         uint16_t src2 = (src1 + 0x2000) & 0x7fff;
1549                         uint32_t dest2 = dest + map_hdsc[y][x];
1550                         dest += 16;
1551                         
1552                         B1 = (cg_mask256 & 0x01) ? vram_b[src1] : 0;
1553                         B0 = (cg_mask256 & 0x10) ? vram_b[src2] : 0;
1554                         R1 = (cg_mask256 & 0x02) ? vram_r[src1] : 0;
1555                         R0 = (cg_mask256 & 0x20) ? vram_r[src2] : 0;
1556                         G1 = (cg_mask256 & 0x04) ? vram_g[src1] : 0;
1557                         G0 = (cg_mask256 & 0x40) ? vram_g[src2] : 0;
1558                         I1 = (cg_mask256 & 0x08) ? vram_i[src1] : 0;
1559                         I0 = (cg_mask256 & 0x80) ? vram_i[src2] : 0;
1560                         
1561                         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];
1562                         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];
1563                         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];
1564                         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];
1565                         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];
1566                         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];
1567                         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];
1568                         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];
1569                 }
1570                 dest += 640;
1571         }
1572 }
1573
1574 void CRTC::draw_640x200x16screen(uint8_t pl)
1575 {
1576         uint8_t B, R, G, I;
1577         uint32_t dest = 0;
1578         
1579         if(map_init) {
1580                 create_addr_map(80, 200);
1581         }
1582         for(int y = 0; y < 200; y++) {
1583                 for(int x = 0; x < 80; x++) {
1584                         uint16_t src = (map_addr[y][x] + (0x4000 * pl)) & 0x7fff;
1585                         uint32_t dest2 = dest + map_hdsc[y][x];
1586                         dest += 8;
1587                         
1588                         B = (cgreg[0x18] & 0x01) ? vram_b[src] : 0;
1589                         R = (cgreg[0x18] & 0x02) ? vram_r[src] : 0;
1590                         G = (cgreg[0x18] & 0x04) ? vram_g[src] : 0;
1591                         I = (cgreg[0x18] & 0x08) ? vram_i[src] : 0;
1592                         
1593                         cg[dest2    ] = cg_matrix0[B][R][0] | cg_matrix1[G][I][0];
1594                         cg[dest2 + 1] = cg_matrix0[B][R][1] | cg_matrix1[G][I][1];
1595                         cg[dest2 + 2] = cg_matrix0[B][R][2] | cg_matrix1[G][I][2];
1596                         cg[dest2 + 3] = cg_matrix0[B][R][3] | cg_matrix1[G][I][3];
1597                         cg[dest2 + 4] = cg_matrix0[B][R][4] | cg_matrix1[G][I][4];
1598                         cg[dest2 + 5] = cg_matrix0[B][R][5] | cg_matrix1[G][I][5];
1599                         cg[dest2 + 6] = cg_matrix0[B][R][6] | cg_matrix1[G][I][6];
1600                         cg[dest2 + 7] = cg_matrix0[B][R][7] | cg_matrix1[G][I][7];
1601                 }
1602                 dest += 640;
1603         }
1604 }
1605
1606 void CRTC::draw_640x400x4screen()
1607 {
1608         uint8_t B, R;
1609         uint32_t dest = 0;
1610         // for Yukara K2
1611         uint8_t *vram_b1 = ((cgreg[0x18] & 3) == 1) ? vram_b + 0x4000 : vram_g;
1612         uint8_t *vram_r1 = ((cgreg[0x18] & 3) == 1) ? vram_r + 0x4000 : vram_i;
1613         
1614         if(map_init) {
1615                 create_addr_map(80, 400);
1616         }
1617         for(int y = 0; y < 400; y++) {
1618                 for(int x = 0; x < 80; x++) {
1619                         uint16_t src = map_addr[y][x];
1620                         uint32_t dest2 = dest + map_hdsc[y][x];
1621                         dest += 8;
1622                         
1623                         B = (cgreg[0x18] & 0x01) ? ((src & 0x4000) ? vram_b1[src & 0x3fff] : vram_b[src]) : 0;
1624                         R = (cgreg[0x18] & 0x02) ? ((src & 0x4000) ? vram_r1[src & 0x3fff] : vram_r[src]) : 0;
1625                         
1626                         cg[dest2    ] = cg_matrix0[B][R][0];
1627                         cg[dest2 + 1] = cg_matrix0[B][R][1];
1628                         cg[dest2 + 2] = cg_matrix0[B][R][2];
1629                         cg[dest2 + 3] = cg_matrix0[B][R][3];
1630                         cg[dest2 + 4] = cg_matrix0[B][R][4];
1631                         cg[dest2 + 5] = cg_matrix0[B][R][5];
1632                         cg[dest2 + 6] = cg_matrix0[B][R][6];
1633                         cg[dest2 + 7] = cg_matrix0[B][R][7];
1634                 }
1635         }
1636 }
1637
1638 void CRTC::draw_640x400x16screen()
1639 {
1640         uint8_t B, R, G, I;
1641         uint32_t dest = 0;
1642         
1643         if(map_init) {
1644                 create_addr_map(80, 400);
1645         }
1646         for(int y = 0; y < 400; y++) {
1647                 for(int x = 0; x < 80; x++) {
1648                         uint16_t src = map_addr[y][x];
1649                         uint32_t dest2 = dest + map_hdsc[y][x];
1650                         dest += 8;
1651                         
1652                         B = vram_b[src];
1653                         R = vram_r[src];
1654                         G = vram_g[src];
1655                         I = vram_i[src];
1656                         
1657                         cg[dest2    ] = cg_matrix0[B][R][0] | cg_matrix1[G][I][0];
1658                         cg[dest2 + 1] = cg_matrix0[B][R][1] | cg_matrix1[G][I][1];
1659                         cg[dest2 + 2] = cg_matrix0[B][R][2] | cg_matrix1[G][I][2];
1660                         cg[dest2 + 3] = cg_matrix0[B][R][3] | cg_matrix1[G][I][3];
1661                         cg[dest2 + 4] = cg_matrix0[B][R][4] | cg_matrix1[G][I][4];
1662                         cg[dest2 + 5] = cg_matrix0[B][R][5] | cg_matrix1[G][I][5];
1663                         cg[dest2 + 6] = cg_matrix0[B][R][6] | cg_matrix1[G][I][6];
1664                         cg[dest2 + 7] = cg_matrix0[B][R][7] | cg_matrix1[G][I][7];
1665                 }
1666         }
1667 }
1668
1669 void CRTC::create_addr_map(int xmax, int ymax)
1670 {
1671         uint8_t HDSC = cgreg[0x0f] & 0x07;
1672         uint16_t SAD0 = cgreg[0x10] | ((cgreg[0x11] & 0x7f) << 8);
1673         uint16_t SAD1 = cgreg[0x12] | ((cgreg[0x13] & 0x7f) << 8);
1674         uint16_t SAD2 = cgreg[0x14] | ((cgreg[0x15] & 0x7f) << 8);
1675         uint16_t SLN1 = cgreg[0x16] | ((cgreg[0x17] & 0x01) << 8);
1676         
1677         for(int y = 0; y < SLN1 && y < ymax; y++) {
1678                 for(int x = 0; x < xmax; x++) {
1679                         map_hdsc[y][x] = HDSC;
1680                         map_addr[y][x] = SAD0;
1681                         SAD0 = (SAD0 == SAD1) ? 0 : ((SAD0 + 1) & 0x7fff);
1682                 }
1683         }
1684         for(int y = SLN1; y < ymax; y++) {
1685                 for(int x = 0; x < xmax; x++) {
1686                         map_hdsc[y][x] = 0;
1687                         map_addr[y][x] = (SAD2++) & 0x7fff;
1688                 }
1689         }
1690         map_init = false;
1691 }
1692
1693 #define STATE_VERSION   1
1694
1695 #include "../../statesub.h"
1696
1697 void CRTC::decl_state()
1698 {
1699         enter_decl_state(STATE_VERSION);
1700
1701         DECL_STATE_ENTRY_BOOL(scan_line);
1702         DECL_STATE_ENTRY_BOOL(scan_tmp);
1703         DECL_STATE_ENTRY_BOOL(monitor_200line);
1704         DECL_STATE_ENTRY_BOOL(monitor_digital);
1705         DECL_STATE_ENTRY_BOOL(monitor_tmp);
1706         DECL_STATE_ENTRY_UINT8(textreg_num);
1707         DECL_STATE_ENTRY_1D_ARRAY(textreg, sizeof(textreg));
1708         DECL_STATE_ENTRY_UINT8(cgreg_num);
1709         DECL_STATE_ENTRY_1D_ARRAY(cgreg, sizeof(cgreg));
1710         DECL_STATE_ENTRY_UINT8(scrn_size);
1711         DECL_STATE_ENTRY_UINT8(cg_mask);
1712         DECL_STATE_ENTRY_UINT8(cg_mask256);
1713         DECL_STATE_ENTRY_BOOL(cg_mask256_init);
1714         DECL_STATE_ENTRY_BOOL(font_size);
1715         DECL_STATE_ENTRY_BOOL(column_size);
1716         DECL_STATE_ENTRY_1D_ARRAY(latch, sizeof(latch));
1717         DECL_STATE_ENTRY_UINT16(GDEVS);
1718         DECL_STATE_ENTRY_UINT16(GDEVE);
1719         DECL_STATE_ENTRY_UINT8(GDEHS);
1720         DECL_STATE_ENTRY_UINT8(GDEHE);
1721         DECL_STATE_ENTRY_INT32(GDEHSC);
1722         DECL_STATE_ENTRY_INT32(GDEHEC);
1723         DECL_STATE_ENTRY_BOOL(hblank);
1724         DECL_STATE_ENTRY_BOOL(vblank);
1725         DECL_STATE_ENTRY_BOOL(blink);
1726         DECL_STATE_ENTRY_UINT8(clear_flag);
1727         DECL_STATE_ENTRY_1D_ARRAY(palette_reg, sizeof(palette_reg));
1728         DECL_STATE_ENTRY_BOOL(pal_select);
1729         DECL_STATE_ENTRY_BOOL(screen_mask);
1730         DECL_STATE_ENTRY_2D_ARRAY(priority16, 16, 9);
1731         // ToDo: scrntype_t
1732         DECL_STATE_ENTRY_SCRNTYPE_T_1D_ARRAY(palette16, sizeof(palette16) / sizeof(scrntype_t));
1733         DECL_STATE_ENTRY_SCRNTYPE_T_1D_ARRAY(palette4096, sizeof(palette4096) / sizeof(scrntype_t));
1734         DECL_STATE_ENTRY_1D_ARRAY(palette4096r, sizeof(palette4096r));
1735         DECL_STATE_ENTRY_1D_ARRAY(palette4096g, sizeof(palette4096g));
1736         DECL_STATE_ENTRY_1D_ARRAY(palette4096b, sizeof(palette4096b));
1737         DECL_STATE_ENTRY_SCRNTYPE_T_1D_ARRAY(palette16txt, sizeof(palette16txt) / sizeof(scrntype_t));
1738         DECL_STATE_ENTRY_SCRNTYPE_T_1D_ARRAY(palette4096txt, sizeof(palette4096txt) / sizeof(scrntype_t));
1739         DECL_STATE_ENTRY_SCRNTYPE_T_2D_ARRAY(palette16pri, 16, 9);
1740         DECL_STATE_ENTRY_SCRNTYPE_T_2D_ARRAY(palette4096pri, 16, 9);
1741         DECL_STATE_ENTRY_UINT8(prev16);
1742         DECL_STATE_ENTRY_BOOL(update16);
1743         DECL_STATE_ENTRY_2D_ARRAY(priority256, 256, 16+64);
1744         DECL_STATE_ENTRY_SCRNTYPE_T_1D_ARRAY(palette256, sizeof(palette256) / sizeof(scrntype_t));
1745         DECL_STATE_ENTRY_SCRNTYPE_T_1D_ARRAY(palette256txt, sizeof(palette256txt) / sizeof(scrntype_t));
1746         DECL_STATE_ENTRY_SCRNTYPE_T_2D_ARRAY(palette256pri, 256, 16+64);
1747         DECL_STATE_ENTRY_SCRNTYPE_T(prev256);
1748         DECL_STATE_ENTRY_BOOL(update256);
1749         DECL_STATE_ENTRY_2D_ARRAY(map_addr, 400, 80);
1750         DECL_STATE_ENTRY_2D_ARRAY(map_hdsc, 400, 80);
1751         DECL_STATE_ENTRY_3D_ARRAY(text_matrix, 256, 8, 8);
1752         DECL_STATE_ENTRY_3D_ARRAY(text_matrixw, 256, 8, 8);
1753         DECL_STATE_ENTRY_UINT8(trans_color);
1754         DECL_STATE_ENTRY_BOOL(map_init);
1755         DECL_STATE_ENTRY_BOOL(trans_init);
1756         leave_decl_state();
1757 }
1758
1759 void CRTC::save_state(FILEIO* state_fio)
1760 {
1761         if(state_entry != NULL) {
1762                 state_entry->save_state(state_fio);
1763         }
1764 //      state_fio->FputUint32(STATE_VERSION);
1765 //      state_fio->FputInt32(this_device_id);
1766         
1767 //      state_fio->FputBool(scan_line);
1768 //      state_fio->FputBool(scan_tmp);
1769 //      state_fio->FputBool(monitor_200line);
1770 //      state_fio->FputBool(monitor_digital);
1771 //      state_fio->FputBool(monitor_tmp);
1772 //      state_fio->FputUint8(textreg_num);
1773 //      state_fio->Fwrite(textreg, sizeof(textreg), 1);
1774 //      state_fio->FputUint8(cgreg_num);
1775 //      state_fio->Fwrite(cgreg, sizeof(cgreg), 1);
1776 //      state_fio->FputUint8(scrn_size);
1777 //      state_fio->FputUint8(cg_mask);
1778 //      state_fio->FputUint8(cg_mask256);
1779 //      state_fio->FputBool(cg_mask256_init);
1780 //      state_fio->FputBool(font_size);
1781 //      state_fio->FputBool(column_size);
1782 //      state_fio->Fwrite(latch, sizeof(latch), 1);
1783 //      state_fio->FputUint16(GDEVS);
1784 //      state_fio->FputUint16(GDEVE);
1785 //      state_fio->FputUint8(GDEHS);
1786 //      state_fio->FputUint8(GDEHE);
1787 //      state_fio->FputInt32(GDEHSC);
1788 //      state_fio->FputInt32(GDEHEC);
1789 //      state_fio->FputBool(hblank);
1790 //      state_fio->FputBool(vblank);
1791 //      state_fio->FputBool(blink);
1792 //      state_fio->FputUint8(clear_flag);
1793 //      state_fio->Fwrite(palette_reg, sizeof(palette_reg), 1);
1794 //      state_fio->FputBool(pal_select);
1795 //      state_fio->FputBool(screen_mask);
1796 //      state_fio->Fwrite(priority16, sizeof(priority16), 1);
1797 //      state_fio->Fwrite(palette16, sizeof(palette16), 1);
1798 //      state_fio->Fwrite(palette4096, sizeof(palette4096), 1);
1799 //      state_fio->Fwrite(palette4096r, sizeof(palette4096r), 1);
1800 //      state_fio->Fwrite(palette4096g, sizeof(palette4096g), 1);
1801 //      state_fio->Fwrite(palette4096b, sizeof(palette4096b), 1);
1802 //      state_fio->Fwrite(palette16txt, sizeof(palette16txt), 1);
1803 //      state_fio->Fwrite(palette4096txt, sizeof(palette4096txt), 1);
1804 //      state_fio->Fwrite(palette16pri, sizeof(palette16pri), 1);
1805 //      state_fio->Fwrite(palette4096pri, sizeof(palette4096pri), 1);
1806 //      state_fio->FputUint8(prev16);
1807 //      state_fio->FputBool(update16);
1808 //      state_fio->Fwrite(priority256, sizeof(priority256), 1);
1809 //      state_fio->Fwrite(palette256, sizeof(palette256), 1);
1810 //      state_fio->Fwrite(palette256txt, sizeof(palette256txt), 1);
1811 //      state_fio->Fwrite(palette256pri, sizeof(palette256pri), 1);
1812 //      state_fio->FputUint32((uint32_t)prev256);
1813 //      state_fio->FputBool(update256);
1814 //      state_fio->Fwrite(map_addr, sizeof(map_addr), 1);
1815 //      state_fio->Fwrite(map_hdsc, sizeof(map_hdsc), 1);
1816 //      state_fio->Fwrite(text_matrix, sizeof(text_matrix), 1);
1817 //      state_fio->Fwrite(text_matrixw, sizeof(text_matrixw), 1);
1818 //      state_fio->FputUint8(trans_color);
1819 //      state_fio->FputBool(map_init);
1820 //      state_fio->FputBool(trans_init);
1821 }
1822
1823 bool CRTC::load_state(FILEIO* state_fio)
1824 {
1825         bool mb = false;
1826         if(state_entry != NULL) {
1827                 mb = state_entry->load_state(state_fio);
1828         }
1829         if(!mb) {
1830                 return false;
1831         }
1832 //      if(state_fio->FgetUint32() != STATE_VERSION) {
1833 //              return false;
1834 //      }
1835 //      if(state_fio->FgetInt32() != this_device_id) {
1836 //              return false;
1837 //      }
1838 //      scan_line = state_fio->FgetBool();
1839 //      scan_tmp = state_fio->FgetBool();
1840 //      monitor_200line = state_fio->FgetBool();
1841 //      monitor_digital = state_fio->FgetBool();
1842 //      monitor_tmp = state_fio->FgetBool();
1843 //      textreg_num = state_fio->FgetUint8();
1844 //      state_fio->Fread(textreg, sizeof(textreg), 1);
1845 //      cgreg_num = state_fio->FgetUint8();
1846 //      state_fio->Fread(cgreg, sizeof(cgreg), 1);
1847 //      scrn_size = state_fio->FgetUint8();
1848 //      cg_mask = state_fio->FgetUint8();
1849 //      cg_mask256 = state_fio->FgetUint8();
1850 //      cg_mask256_init = state_fio->FgetBool();
1851 //      font_size = state_fio->FgetBool();
1852 //      column_size = state_fio->FgetBool();
1853 //      state_fio->Fread(latch, sizeof(latch), 1);
1854 //      GDEVS = state_fio->FgetUint16();
1855 //      GDEVE = state_fio->FgetUint16();
1856 //      GDEHS = state_fio->FgetUint8();
1857 //      GDEHE = state_fio->FgetUint8();
1858 //      GDEHSC = state_fio->FgetInt32();
1859 //      GDEHEC = state_fio->FgetInt32();
1860 //      hblank = state_fio->FgetBool();
1861 //      vblank = state_fio->FgetBool();
1862 //      blink = state_fio->FgetBool();
1863 //      clear_flag = state_fio->FgetUint8();
1864 //      state_fio->Fread(palette_reg, sizeof(palette_reg), 1);
1865 //      pal_select = state_fio->FgetBool();
1866 //      screen_mask = state_fio->FgetBool();
1867 //      state_fio->Fread(priority16, sizeof(priority16), 1);
1868 //      state_fio->Fread(palette16, sizeof(palette16), 1);
1869 //      state_fio->Fread(palette4096, sizeof(palette4096), 1);
1870 //      state_fio->Fread(palette4096r, sizeof(palette4096r), 1);
1871 //      state_fio->Fread(palette4096g, sizeof(palette4096g), 1);
1872 //      state_fio->Fread(palette4096b, sizeof(palette4096b), 1);
1873 //      state_fio->Fread(palette16txt, sizeof(palette16txt), 1);
1874 //      state_fio->Fread(palette4096txt, sizeof(palette4096txt), 1);
1875 //      state_fio->Fread(palette16pri, sizeof(palette16pri), 1);
1876 //      state_fio->Fread(palette4096pri, sizeof(palette4096pri), 1);
1877 //      prev16 = state_fio->FgetUint8();
1878 //      update16 = state_fio->FgetBool();
1879 //      state_fio->Fread(priority256, sizeof(priority256), 1);
1880 //      state_fio->Fread(palette256, sizeof(palette256), 1);
1881 //      state_fio->Fread(palette256txt, sizeof(palette256txt), 1);
1882 //      state_fio->Fread(palette256pri, sizeof(palette256pri), 1);
1883 //      prev256 = (scrntype_t)state_fio->FgetUint32();
1884 //      update256 = state_fio->FgetBool();
1885 //      state_fio->Fread(map_addr, sizeof(map_addr), 1);
1886 //      state_fio->Fread(map_hdsc, sizeof(map_hdsc), 1);
1887 //      state_fio->Fread(text_matrix, sizeof(text_matrix), 1);
1888 //      state_fio->Fread(text_matrixw, sizeof(text_matrixw), 1);
1889 //      trans_color = state_fio->FgetUint8();
1890 //      map_init = state_fio->FgetBool();
1891 //      trans_init = state_fio->FgetBool();
1892         return true;
1893 }
1894