OSDN Git Service

[VM][STATE][PC9801][X1] Apply new state framework to PC9801 series and X1 series.
[csp-qt/common_source_project-fm7.git] / source / src / vm / x1 / display.cpp
1 /*
2         SHARP X1 Emulator 'eX1'
3         SHARP X1twin Emulator 'eX1twin'
4         SHARP X1turbo Emulator 'eX1turbo'
5         SHARP X1turboZ Emulator 'eX1turboZ'
6
7         Origin : X1EMU by KM (kanji rom)
8                  X-millenium by Yui (ank16 patch)
9         Author : Takeda.Toshiya
10         Date   : 2009.03.14-
11
12   [ display ]
13 */
14
15 #include "display.h"
16 #include "../hd46505.h"
17 #include "../i8255.h"
18
19 #ifdef _X1TURBO_FEATURE
20 #define EVENT_AFTER_BLANK       0
21 #endif
22
23 #ifdef _X1TURBOZ
24 #define AEN     ((zmode1 & 0x80) != 0)
25 #define C64     ((zmode1 & 0x10) != 0)
26 #define APEN    ((zmode2 & 0x80) != 0)
27 #define APRD    ((zmode2 & 0x08) != 0)
28 #endif
29
30 void DISPLAY::initialize()
31 {
32         // load rom images
33         FILEIO* fio = new FILEIO();
34         
35         // ank8 (8x8)
36         if(fio->Fopen(create_local_path(_T("ANK8.ROM")), FILEIO_READ_BINARY)) {
37                 fio->Fread(font, sizeof(font), 1);
38                 fio->Fclose();
39         } else if(fio->Fopen(create_local_path(_T("FNT0808.X1")), FILEIO_READ_BINARY)) {
40                 // xmillenium rom
41                 fio->Fread(font, sizeof(font), 1);
42                 fio->Fclose();
43         }
44         
45         // ank16 (8x16)
46         if(fio->Fopen(create_local_path(_T("ANK16.ROM")), FILEIO_READ_BINARY)) {
47                 fio->Fread(kanji, 0x1000, 1);
48                 fio->Fclose();
49         } else if(fio->Fopen(create_local_path(_T("FNT0816.X1")), FILEIO_READ_BINARY)) {
50                 // xmillenium rom
51                 fio->Fread(kanji, 0x1000, 1);
52                 fio->Fclose();
53         }
54         memcpy(kanji + 0x7f * 16, ANKFONT7f_9f, sizeof(ANKFONT7f_9f));
55         memcpy(kanji + 0xe0 * 16, ANKFONTe0_ff, sizeof(ANKFONTe0_ff));
56         
57         // kanji (16x16)
58         if(fio->Fopen(create_local_path(_T("KANJI.ROM")), FILEIO_READ_BINARY)) {
59                 fio->Fread(kanji + 0x1000, 0x4ac00, 1);
60                 fio->Fclose();
61         } else if(fio->Fopen(create_local_path(_T("FNT1616.X1")), FILEIO_READ_BINARY)) {
62                 // xmillenium rom
63                 fio->Fread(kanji + 0x1000, 0x4ac00, 1);
64                 fio->Fclose();
65         }
66         for(int ofs = 0x1000; ofs < 0x4bc00; ofs += 32) {
67                 // LRLR.. -> LL..RR..
68                 uint8_t buf[32];
69                 for(int i = 0; i < 16; i++) {
70                         buf[i     ] = kanji[ofs + i * 2    ];
71                         buf[i + 16] = kanji[ofs + i * 2 + 1];
72                 }
73                 memcpy(kanji + ofs, buf, 32);
74         }
75         delete fio;
76         
77         // create pc palette
78         for(int i = 0; i < 8; i++) {
79                 palette_pc[i    ] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0); // text
80                 palette_pc[i + 8] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0); // cg
81         }
82 #ifdef _X1TURBOZ
83         for(int i = 0; i < 8; i++) {
84                 ztpal[i] = ((i & 1) ? 0x03 : 0) | ((i & 2) ? 0x0c : 0) | ((i & 4) ? 0x30 : 0);
85                 zpalette_pc[i    ] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0);        // text
86                 zpalette_pc[i + 8] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0);        // digital
87         }
88         for(int g = 0; g < 16; g++) {
89                 for(int r = 0; r < 16; r++) {
90                         for(int b = 0; b < 16; b++) {
91                                 int num = b + r * 16 + g * 256;
92                                 zpal[num].b = b;
93                                 zpal[num].r = r;
94                                 zpal[num].g = g;
95                                 zpalette_pc[num + 16] = RGB_COLOR((r * 255) / 15, (g * 255) / 15, (b * 255) / 15);
96                         }
97                 }
98         }
99 #endif
100         
101         // initialize regs
102         pal[0] = 0xaa;
103         pal[1] = 0xcc;
104         pal[2] = 0xf0;
105         priority = 0;
106         update_pal();
107         column40 = true;
108         
109         memset(vram_t, 0, sizeof(vram_t));
110         memset(vram_a, 0, sizeof(vram_a));
111 #ifdef _X1TURBO_FEATURE
112         memset(vram_k, 0, sizeof(vram_k));
113 #endif
114         memset(pcg_b, 0, sizeof(pcg_b));
115         memset(pcg_r, 0, sizeof(pcg_r));
116         memset(pcg_g, 0, sizeof(pcg_g));
117 #ifdef _X1TURBO_FEATURE
118         memset(gaiji_b, 0, sizeof(gaiji_b));
119         memset(gaiji_r, 0, sizeof(gaiji_r));
120         memset(gaiji_g, 0, sizeof(gaiji_g));
121 #endif
122         
123         // register event
124         register_frame_event(this);
125         register_vline_event(this);
126
127         // Copy images to draw buffers.
128         my_memcpy(dr_text, text, sizeof(dr_text));
129         my_memcpy(dr_cg, cg, sizeof(dr_cg));
130         my_memcpy(dr_pri_line, pri_line, sizeof(dr_pri_line));
131         my_memcpy(dr_palette_pc, palette_pc, sizeof(dr_palette_pc));
132         dr_priority = priority;
133 #ifdef _X1TURBOZ
134         dr_zpriority = zpriority;
135         my_memcpy(dr_zcg, zcg, sizeof(dr_zcg));
136         my_memcpy(dr_aen_line, aen_line, sizeof(dr_aen_line));
137         my_memcpy(dr_zpalette_pc, zpalette_pc, sizeof(zpalette_pc));
138         zpalette_pc[8 + 0] = zpalette_pc[16 + 0x000];
139         zpalette_pc[8 + 1] = zpalette_pc[16 + 0x00f];
140         zpalette_pc[8 + 2] = zpalette_pc[16 + 0x0f0];
141         zpalette_pc[8 + 3] = zpalette_pc[16 + 0x0ff];
142         zpalette_pc[8 + 4] = zpalette_pc[16 + 0xf00];
143         zpalette_pc[8 + 5] = zpalette_pc[16 + 0xf0f];
144         zpalette_pc[8 + 6] = zpalette_pc[16 + 0xff0];
145         zpalette_pc[8 + 7] = zpalette_pc[16 + 0xfff];
146 #endif  
147 }
148
149 void DISPLAY::reset()
150 {
151 #ifdef _X1TURBO_FEATURE
152         mode1 = 0;//3;
153         mode2 = 0;
154         hireso = true;
155 #endif
156 #ifdef _X1TURBOZ
157         zmode1 = 0;
158         zpriority = 0;
159         zadjust = 0;
160         zmosaic = 0;
161         zchromakey = 0;
162         zscroll = 0;
163         zmode2 = 0;
164         zpal_num = 0;
165 #endif
166         cur_line = cur_code = 0;
167         vblank_clock = 0;
168         cur_vline = 0;
169         cur_blank = true;
170         
171         kaddr = kofs = kflag = 0;
172         kanji_ptr = &kanji[0];
173
174         // Copy images to draw buffers.
175         my_memcpy(dr_text, text, sizeof(dr_text));
176         my_memcpy(dr_cg, cg, sizeof(dr_cg));
177         my_memcpy(dr_pri_line, pri_line, sizeof(dr_pri_line));
178         my_memcpy(dr_palette_pc, palette_pc, sizeof(dr_palette_pc));
179         dr_priority = priority;
180 #ifdef _X1TURBOZ
181         dr_zpriority = zpriority;
182         my_memcpy(dr_zcg, zcg, sizeof(dr_zcg));
183         my_memcpy(dr_aen_line, aen_line, sizeof(dr_aen_line));
184         my_memcpy(dr_zpalette_pc, zpalette_pc, sizeof(zpalette_pc));
185         zpalette_pc[8 + 0] = zpalette_pc[16 + 0x000];
186         zpalette_pc[8 + 1] = zpalette_pc[16 + 0x00f];
187         zpalette_pc[8 + 2] = zpalette_pc[16 + 0x0f0];
188         zpalette_pc[8 + 3] = zpalette_pc[16 + 0x0ff];
189         zpalette_pc[8 + 4] = zpalette_pc[16 + 0xf00];
190         zpalette_pc[8 + 5] = zpalette_pc[16 + 0xf0f];
191         zpalette_pc[8 + 6] = zpalette_pc[16 + 0xff0];
192         zpalette_pc[8 + 7] = zpalette_pc[16 + 0xfff];
193 #endif  
194 }
195
196 void DISPLAY::write_io8(uint32_t addr, uint32_t data)
197 {
198         switch(addr & 0xff00) {
199         case 0x0e00:
200                 write_kanji(addr, data);
201                 break;
202         case 0x1000:
203 #ifdef _X1TURBOZ
204                 if(AEN) {
205                         if(APEN && !APRD) {
206                                 if(!cur_blank) {
207                                         // wait next blank
208                                         d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
209                                 }
210                                 int num = get_zpal_num(addr, data);
211                                 zpal[num].b = data & 0x0f;
212                                 zpalette_pc[num + 16] = RGB_COLOR((zpal[num].r * 255) / 15, (zpal[num].g * 255) / 15, (zpal[num].b * 255) / 15);
213                         } else if(APEN && APRD) {
214                                 zpal_num = get_zpal_num(addr, data);
215                         }
216                 } else
217 #endif
218                 {
219                         pal[0] = data;
220                         update_pal();
221                 }
222                 break;
223         case 0x1100:
224 #ifdef _X1TURBOZ
225                 if(AEN) {
226                         if(APEN && !APRD) {
227                                 if(!cur_blank) {
228                                         // wait next blank
229                                         d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
230                                 }
231                                 int num = get_zpal_num(addr, data);
232                                 zpal[num].r = data & 0x0f;
233                                 zpalette_pc[num + 16] = RGB_COLOR((zpal[num].r * 255) / 15, (zpal[num].g * 255) / 15, (zpal[num].b * 255) / 15);
234                         } else if(APEN && APRD) {
235 //                              zpal_num = get_zpal_num(addr, data);
236                         }
237                 } else
238 #endif
239                 {
240                         pal[1] = data;
241                         update_pal();
242                 }
243                 break;
244         case 0x1200:
245 #ifdef _X1TURBOZ
246                 if(AEN) {
247                         if(APEN && !APRD) {
248                                 if(!cur_blank) {
249                                         // wait next blank
250                                         d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
251                                 }
252                                 int num = get_zpal_num(addr, data);
253                                 zpal[num].g = data & 0x0f;
254                                 zpalette_pc[num + 16] = RGB_COLOR((zpal[num].r * 255) / 15, (zpal[num].g * 255) / 15, (zpal[num].b * 255) / 15);
255                         } else if(APEN && APRD) {
256 //                              zpal_num = get_zpal_num(addr, data);
257                         }
258                 } else
259 #endif
260                 {
261                         pal[2] = data;
262                         update_pal();
263                 }
264                 break;
265         case 0x1300:
266                 priority = data;
267                 update_pal();
268                 break;
269         case 0x1500:
270                 get_cur_pcg(addr);
271                 pcg_b[cur_code][cur_line] = data;
272 #ifdef _X1TURBO_FEATURE
273                 gaiji_b[cur_code >> 1][(cur_line << 1) | (cur_code & 1)] = data;
274 #endif
275                 break;
276         case 0x1600:
277                 get_cur_pcg(addr);
278                 pcg_r[cur_code][cur_line] = data;
279 #ifdef _X1TURBO_FEATURE
280                 gaiji_r[cur_code >> 1][(cur_line << 1) | (cur_code & 1)] = data;
281 #endif
282                 break;
283         case 0x1700:
284                 get_cur_pcg(addr);
285                 pcg_g[cur_code][cur_line] = data;
286 #ifdef _X1TURBO_FEATURE
287                 gaiji_g[cur_code >> 1][(cur_line << 1) | (cur_code & 1)] = data;
288 #endif
289                 break;
290 #ifdef _X1TURBO_FEATURE
291         case 0x1f00:
292                 switch(addr) {
293 #ifdef _X1TURBOZ
294                 case 0x1fb0:
295                         zmode1 = data;
296                         break;
297 //              case 0x1fb8:
298                 case 0x1fb9:
299                 case 0x1fba:
300                 case 0x1fbb:
301                 case 0x1fbc:
302                 case 0x1fbd:
303                 case 0x1fbe:
304                 case 0x1fbf:
305                         if(AEN) {
306                                 ztpal[addr & 7] = data;
307                                 zpalette_pc[addr & 7] = RGB_COLOR((((data >> 2) & 3) * 255) / 3, (((data >> 4) & 3) * 255) / 3, (((data >> 0) & 3) * 255) / 3);
308                         }
309                         break;
310                 case 0x1fc0:
311                         if(AEN) {
312                                 zpriority = data;
313                         }
314                         break;
315                 case 0x1fc1:
316                         if(AEN) {
317                                 zadjust = data;
318                         }
319                         break;
320                 case 0x1fc2:
321                         if(AEN) {
322                                 zmosaic = data;
323                         }
324                         break;
325                 case 0x1fc3:
326                         if(AEN) {
327                                 zchromakey = data;
328                         }
329                         break;
330                 case 0x1fc4:
331                         if(AEN) {
332                                 zscroll = data;
333                         }
334                         break;
335                 case 0x1fc5:
336                         if(AEN) {
337                                 zmode2 = data;
338                         }
339                         break;
340 #endif
341                 case 0x1fd0:
342                         mode1 = data;
343                         update_crtc();
344 //                      hireso = !((mode1 & 3) == 0 || (mode1 & 3) == 2);
345                         break;
346                 case 0x1fe0:
347                         mode2 = data;
348                         update_pal();
349                         break;
350                 }
351                 break;
352 #endif
353         case 0x2000:
354         case 0x2100:
355         case 0x2200:
356         case 0x2300:
357         case 0x2400:
358         case 0x2500:
359         case 0x2600:
360         case 0x2700:
361                 vram_a[addr & 0x7ff] = data;
362                 break;
363         case 0x2800:
364         case 0x2900:
365         case 0x2a00:
366         case 0x2b00:
367         case 0x2c00:
368         case 0x2d00:
369         case 0x2e00:
370         case 0x2f00:
371                 vram_a[addr & 0x7ff] = data; // mirror
372                 break;
373         case 0x3000:
374         case 0x3100:
375         case 0x3200:
376         case 0x3300:
377         case 0x3400:
378         case 0x3500:
379         case 0x3600:
380         case 0x3700:
381                 vram_t[addr & 0x7ff] = data;
382                 break;
383         case 0x3800:
384         case 0x3900:
385         case 0x3a00:
386         case 0x3b00:
387         case 0x3c00:
388         case 0x3d00:
389         case 0x3e00:
390         case 0x3f00:
391 #ifdef _X1TURBO_FEATURE
392                 vram_k[addr & 0x7ff] = data;
393 #else
394                 vram_t[addr & 0x7ff] = data; // mirror
395 #endif
396                 break;
397         }
398 }
399
400 uint32_t DISPLAY::read_io8(uint32_t addr)
401 {
402         switch(addr & 0xff00) {
403         case 0x0e00:
404                 return read_kanji(addr);
405 #ifdef _X1TURBOZ
406         case 0x1000:
407                 if(AEN && APEN && APRD) {
408                         return zpal[zpal_num].b;
409                 }
410                 break;
411         case 0x1100:
412                 if(AEN && APEN && APRD) {
413                         return zpal[zpal_num].r;
414                 }
415                 break;
416         case 0x1200:
417                 if(AEN && APEN && APRD) {
418                         return zpal[zpal_num].g;
419                 }
420                 break;
421 #endif
422 //      case 0x1300:
423 //              return priority;
424         case 0x1400:
425                 return get_cur_font(addr);
426         case 0x1500:
427                 get_cur_pcg(addr);
428                 return pcg_b[cur_code][cur_line];
429         case 0x1600:
430                 get_cur_pcg(addr);
431                 return pcg_r[cur_code][cur_line];
432         case 0x1700:
433                 get_cur_pcg(addr);
434                 return pcg_g[cur_code][cur_line];
435 #ifdef _X1TURBOZ
436         case 0x1f00:
437                 switch(addr) {
438                 case 0x1fb0:
439                         return zmode1;
440 //              case 0x1fb8:
441                 case 0x1fb9:
442                 case 0x1fba:
443                 case 0x1fbb:
444                 case 0x1fbc:
445                 case 0x1fbd:
446                 case 0x1fbe:
447                 case 0x1fbf:
448                         if(AEN) {
449                                 return ztpal[addr & 7];
450                         }
451                         break;
452                 case 0x1fc0:
453                         if(AEN) {
454                                 return zpriority;
455                         }
456                         break;
457                 case 0x1fc1:
458                         if(AEN) {
459                                 return zadjust;
460                         }
461                         break;
462                 case 0x1fc2:
463                         if(AEN) {
464                                 return zmosaic;
465                         }
466                         break;
467                 case 0x1fc3:
468                         if(AEN) {
469                                 return zchromakey;
470                         }
471                         break;
472                 case 0x1fc4:
473                         if(AEN) {
474                                 return zscroll;
475                         }
476                         break;
477                 case 0x1fc5:
478                         if(AEN) {
479                                 return zmode2;
480                         }
481                         break;
482                 case 0x1fd0:
483                         return mode1;
484                 case 0x1fe0:
485                         return mode2;
486                 }
487                 break;
488 #endif
489         case 0x2000:
490         case 0x2100:
491         case 0x2200:
492         case 0x2300:
493         case 0x2400:
494         case 0x2500:
495         case 0x2600:
496         case 0x2700:
497                 return vram_a[addr & 0x7ff];
498         case 0x2800:
499         case 0x2900:
500         case 0x2a00:
501         case 0x2b00:
502         case 0x2c00:
503         case 0x2d00:
504         case 0x2e00:
505         case 0x2f00:
506                 return vram_a[addr & 0x7ff]; // mirror
507         case 0x3000:
508         case 0x3100:
509         case 0x3200:
510         case 0x3300:
511         case 0x3400:
512         case 0x3500:
513         case 0x3600:
514         case 0x3700:
515                 return vram_t[addr & 0x7ff];
516         case 0x3800:
517         case 0x3900:
518         case 0x3a00:
519         case 0x3b00:
520         case 0x3c00:
521         case 0x3d00:
522         case 0x3e00:
523         case 0x3f00:
524 #ifdef _X1TURBO_FEATURE
525                 return vram_k[addr & 0x7ff];
526 #else
527                 return vram_t[addr & 0x7ff]; // mirror
528 #endif
529         }
530         return 0xff;
531 }
532
533 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
534 {
535         if(id == SIG_DISPLAY_VBLANK) {
536                 if(!(data & mask)) {
537                         // enter vblank
538                         vblank_clock = get_current_clock();
539                 }
540         } else if(id == SIG_DISPLAY_COLUMN40) {
541                 column40 = ((data & mask) != 0);
542                 update_crtc();
543         } else if(id == SIG_DISPLAY_DETECT_VBLANK) {
544                 // hack: cpu detects vblank
545                 vblank_clock = get_current_clock();
546         } else if(id == SIG_DISPLAY_DISP) {
547                 bool prev = cur_blank;
548                 cur_blank = ((data & mask) == 0); // blank = not disp
549                 if(!prev && cur_blank) {
550                         // draw line at start of hblank
551 #ifdef _X1TURBO_FEATURE
552                         if(hireso) {
553                                 if(cur_vline < 400) {
554                                         draw_line(cur_vline);
555                                 }
556                         } else {
557 #endif
558                                 if(cur_vline < 200) {
559                                         draw_line(cur_vline);
560                                 }
561 #ifdef _X1TURBO_FEATURE
562                         }
563                         // restart cpu after pcg/cgrom/zpal is accessed
564 //                      d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 0);
565                         register_event_by_clock(this, EVENT_AFTER_BLANK, 24, false, NULL);
566 #endif
567                 }
568         }
569 }
570
571 void DISPLAY::event_frame()
572 {
573         cblink = (cblink + 1) & 0x3f;
574         
575         // update crtc parameters
576         ch_height = (regs[9] & 0x1f) + 1;
577         hz_total = regs[0] + 1;
578         hz_disp = regs[1];
579         vt_disp = regs[6] & 0x7f;
580         st_addr = (regs[12] << 8) | regs[13];
581         
582 #ifdef _X1TURBO_FEATURE
583         int vt_total = ((regs[4] & 0x7f) + 1) * ch_height + (regs[5] & 0x1f);
584         hireso = (vt_total > 400);
585 #endif
586         int vlen;
587 #ifdef _X1TURBO_FEATURE
588         vlen = (hireso) ? 400 : 200;
589 #else
590         vlen = 200;
591 #endif
592         if(vlen > 0) {
593                 // Copy images to draw buffers.
594                 my_memcpy(dr_text, text, sizeof(uint8_t) * vlen * (640 + 8));
595                 my_memcpy(dr_cg, cg, sizeof(uint8_t) * vlen * 640);
596                 my_memcpy(dr_pri_line, pri_line, sizeof(uint8_t) * vlen * 8 * 8);
597         }
598         my_memcpy(dr_palette_pc, palette_pc, sizeof(dr_palette_pc));
599         dr_priority = priority;
600         // initialize draw screen
601         memset(text, 0, sizeof(text));
602         memset(cg, 0, sizeof(cg));
603         memset(pri_line, 0, sizeof(pri_line));
604 #ifdef _X1TURBOZ
605         if(vlen > 0) {
606         // Copy images to draw buffers.
607                 my_memcpy(&(dr_zcg[0][0][0]), &(zcg[0][0][0]), sizeof(uint8_t) * vlen * 640);
608                 //my_memcpy(dr_aen_line, aen_line, sizeof(bool) * vlen);
609         }
610         my_memcpy(dr_aen_line, aen_line, sizeof(aen_line));
611         dr_zpriority = zpriority;
612         my_memcpy(dr_zpalette_pc, zpalette_pc, sizeof(zpalette_pc));
613         zpalette_pc[8 + 0] = zpalette_pc[16 + 0x000];
614         zpalette_pc[8 + 1] = zpalette_pc[16 + 0x00f];
615         zpalette_pc[8 + 2] = zpalette_pc[16 + 0x0f0];
616         zpalette_pc[8 + 3] = zpalette_pc[16 + 0x0ff];
617         zpalette_pc[8 + 4] = zpalette_pc[16 + 0xf00];
618         zpalette_pc[8 + 5] = zpalette_pc[16 + 0xf0f];
619         zpalette_pc[8 + 6] = zpalette_pc[16 + 0xff0];
620         zpalette_pc[8 + 7] = zpalette_pc[16 + 0xfff];
621         
622         memset(zcg, 0, sizeof(zcg));
623         memset(aen_line, 0, sizeof(aen_line));
624 #endif
625         prev_vert_double = false;
626         raster = 0;
627 }
628
629 void DISPLAY::event_vline(int v, int clock)
630 {
631         cur_vline = v;
632
633 #if 0
634         // Copy images to draw buffers.
635         int vlimit;
636 #ifdef _X1TURBO_FEATURE
637         vlimit = (hireso) ? 400 : 200;
638 #else
639         vlimit = 200;
640 #endif
641         if((v > vlimit) || (v < 0)) return;
642         
643         if(v == vlimit) {
644                 my_memcpy(dr_palette_pc, palette_pc, sizeof(palette_pc));
645 #ifdef _X1TURBOZ
646                 my_memcpy(dr_zpalette_pc, zpalette_pc, sizeof(zpalette_pc));
647 #endif
648                 // Copy images to draw buffers.
649                 //my_memcpy(&(dr_text[v][0]), &(text[v][0]), sizeof(uint8_t) * (640 + 8));
650                 //my_memcpy(&(dr_cg[v][0]), &(cg[v][0]), sizeof(uint8_t) * 640);
651                 //my_memcpy(&(dr_pri_line[v][0][0]), &(pri_line[v][0][0]), sizeof(uint8_t) * 8 * 8);
652 #ifdef _X1TURBOZ
653                 //my_memcpy(&(dr_zcg[0][v][0]), &(zcg[0][v][0]), sizeof(uint8_t) * 640);
654                 //my_memcpy(&(dr_zcg[1][v][0]), &(zcg[1][v][0]), sizeof(uint8_t) * 640);
655                 //dr_aen_line[v] = aen_line[v];
656 #endif
657         } else if(v == 0) {
658                 return;
659         }
660         // Copy images to draw buffers.
661         my_memcpy(&(dr_text[v - 1][0]), &(text[v - 1][0]), sizeof(uint8_t) * (640 + 8));
662         my_memcpy(&(dr_cg[v - 1][0]), &(cg[v -1 ][0]), sizeof(uint8_t) * 640);
663         my_memcpy(&(dr_pri_line[v - 1][0][0]), &(pri_line[v - 1][0][0]), sizeof(uint8_t) * 8 * 8);
664         dr_priority = priority;
665 #ifdef _X1TURBOZ
666         my_memcpy(&(dr_zcg[0][v - 1 ][0]), &(zcg[0][v - 1][0]), sizeof(uint8_t) * 640);
667         my_memcpy(&(dr_zcg[1][v - 1][0]), &(zcg[1][v - 1][0]), sizeof(uint8_t) * 640);
668         dr_zpriority = zpriority;
669         dr_aen_line[v - 1] = aen_line[v - 1];
670 #endif
671 #endif
672 }
673
674 #ifdef _X1TURBO_FEATURE
675 void DISPLAY::event_callback(int event_id, int err)
676 {
677         if(event_id == EVENT_AFTER_BLANK) {
678                 // restart cpu after pcg/cgrom/zpal is accessed
679                 d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 0);
680         }
681 }
682 #endif
683
684 void DISPLAY::update_crtc()
685 {
686 #ifdef _X1TURBO_FEATURE
687         if (column40) {
688                 d_crtc->set_char_clock((mode1 & 1) ? VDP_CLOCK * 1.5 / 32.0 : VDP_CLOCK / 32.0);
689         } else {
690                 d_crtc->set_char_clock((mode1 & 1) ? VDP_CLOCK * 1.5 / 16.0 : VDP_CLOCK / 16.0);
691         }
692 #else
693         if (column40) {
694                 d_crtc->set_char_clock(VDP_CLOCK / 32.0);
695         } else {
696                 d_crtc->set_char_clock(VDP_CLOCK / 16.0);
697         }
698 #endif
699 }
700
701 void DISPLAY::update_pal()
702 {
703         uint8_t pal2[8];
704         for(int i = 0; i < 8; i++) {
705                 uint8_t bit = 1 << i;
706                 pal2[i] = ((pal[0] & bit) ? 1 : 0) | ((pal[1] & bit) ? 2 : 0) | ((pal[2] & bit) ? 4 : 0) | 8;
707         }
708 #ifdef _X1TURBO_FEATURE
709         if(mode2 & 0x10) pal2[0] = 8;
710         if(mode2 & 0x20) pal2[1] = 8;
711 #endif
712         for(int c = 0; c < 8; c++) {
713                 for(int t = 0; t < 8; t++) {
714                         if(priority & (1 << c)) {
715                                 pri[c][t] = pal2[c];
716                         } else if(t) {
717 #ifdef _X1TURBO_FEATURE
718                                 pri[c][t] = ((mode2 & 8) && (mode2 & 7) == t) ? 0 : t;
719 #else
720                                 pri[c][t] = t;
721 #endif
722                         } else {
723                                 pri[c][t] = pal2[c];
724                         }
725                 }
726         }
727 }
728
729 uint8_t DISPLAY::get_cur_font(uint32_t addr)
730 {
731 #ifdef _X1TURBO_FEATURE
732         if(mode1 & 0x20) {
733                 // wait next blank
734                 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
735                 
736                 // from X1EMU
737                 uint16_t vaddr;
738                 if(!(vram_a[0x7ff] & 0x20)) {
739                         vaddr = 0x7ff;
740                 } else if(!(vram_a[0x3ff] & 0x20)) {
741                         vaddr = 0x3ff;
742                 } else if(!(vram_a[0x5ff] & 0x20)) {
743                         vaddr = 0x5ff;
744                 } else if(!(vram_a[0x1ff] & 0x20)) {
745                         vaddr = 0x1ff;
746                 } else {
747                         vaddr = 0x3ff;
748                 }
749                 uint16_t ank = vram_t[vaddr];
750                 uint16_t knj = vram_k[vaddr];
751                 
752                 if(knj & 0x80) {
753                         uint32_t ofs = adr2knj_x1t((knj << 8) | ank);
754                         if(knj & 0x40) {
755                                 ofs += 16; // right
756                         }
757                         return kanji[ofs | (addr & 15)];
758                 } else if(mode1 & 0x40) {
759                         return kanji[(ank << 4) | (addr & 15)];
760                 } else {
761                         return font[(ank << 3) | ((addr >> 1) & 7)];
762                 }
763         }
764 #endif
765         get_cur_code_line();
766         return font[(cur_code << 3) | (cur_line & 7)];
767 }
768
769 void DISPLAY::get_cur_pcg(uint32_t addr)
770 {
771 #ifdef _X1TURBO_FEATURE
772         if(mode1 & 0x20) {
773                 // wait next blank
774                 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
775                 
776                 // from X1EMU
777                 uint16_t vaddr;
778                 if(vram_a[0x7ff] & 0x20) {
779                         vaddr = 0x7ff;
780                 } else if(vram_a[0x3ff] & 0x20) {
781                         vaddr = 0x3ff;
782                 } else if(vram_a[0x5ff] & 0x20) {
783                         vaddr = 0x5ff;
784                 } else if(vram_a[0x1ff] & 0x20) {
785                         vaddr = 0x1ff;
786                 } else {
787                         vaddr = 0x3ff;
788                 }
789                 cur_code = vram_t[vaddr];
790                 cur_line = (addr >> 1) & 7;
791                 
792                 if(vram_k[vaddr] & 0x90) {
793                         cur_code &= 0xfe;
794                         cur_code += addr & 1;
795                 }
796         } else
797 #endif
798                 get_cur_code_line();
799 }
800
801 void DISPLAY::get_cur_code_line()
802 {
803 //#ifdef _X1TURBO_FEATURE
804 //      int ht_clock = hireso ? 161 : 250;
805 //#else
806 #define ht_clock 250
807 //#endif
808         int clock = get_passed_clock(vblank_clock);
809         int vt_line = vt_disp * ch_height + (int)(clock / ht_clock);
810         
811         int addr = (hz_total * (clock % ht_clock)) / ht_clock;
812         addr += hz_disp * (int)(vt_line / ch_height);
813         if(addr > 0x7ff) {
814                 addr = 0x7ff;
815         }
816         addr += st_addr;
817         
818         cur_code = vram_t[addr & 0x7ff];
819         cur_line = (vt_line % ch_height) & 7;
820 }
821
822 void DISPLAY::draw_line(int v)
823 {
824         if((regs[8] & 0x30) != 0x30) {
825                 if((v % ch_height) == 0) {
826                         draw_text(v / ch_height);
827                 }
828 #ifdef _X1TURBOZ
829                 if(AEN && !hireso && column40) {
830                         draw_cg(v, 1);
831                 }
832 #endif
833                 draw_cg(v, 0);
834                 memcpy(&pri_line[v][0][0], &pri[0][0], sizeof(pri));
835 //      } else {
836 //              memset(&pri_line[v][0][0], 0, sizeof(pri));
837         }
838 #ifdef _X1TURBOZ
839         aen_line[v] = AEN;
840 #endif
841 }
842
843 void DISPLAY::draw_screen()
844 {
845         // copy to real screen
846 #ifdef _X1TURBOZ
847         dr_zpalette_pc[8 + 0] = dr_zpalette_pc[16 + 0x000];
848         dr_zpalette_pc[8 + 1] = dr_zpalette_pc[16 + 0x00f];
849         dr_zpalette_pc[8 + 2] = dr_zpalette_pc[16 + 0x0f0];
850         dr_zpalette_pc[8 + 3] = dr_zpalette_pc[16 + 0x0ff];
851         dr_zpalette_pc[8 + 4] = dr_zpalette_pc[16 + 0xf00];
852         dr_zpalette_pc[8 + 5] = dr_zpalette_pc[16 + 0xf0f];
853         dr_zpalette_pc[8 + 6] = dr_zpalette_pc[16 + 0xff0];
854         dr_zpalette_pc[8 + 7] = dr_zpalette_pc[16 + 0xfff];
855 #endif
856 #ifdef _X1TURBO_FEATURE
857         if(hireso) {
858                 // 400 lines
859                 emu->set_vm_screen_lines(400);
860                 if(column40) {
861                         // 40 columns
862                         for(int y = 0; y < 400; y++) {
863                                 scrntype_t* dest = emu->get_screen_buffer(y);
864                                 uint8_t* src_text = dr_text[y];
865 #ifdef _X1TURBOZ
866                                 if(dr_aen_line[y]) {
867                                         uint16_t* src_cg0 = dr_zcg[0][y];
868                                         
869                                         for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {
870                                                 uint16_t cg00 = src_cg0[x] | (src_cg0[x] >> 2);
871                                                 
872                                                 dest[x2] = dest[x2 + 1] = get_zpriority(src_text[x], cg00, cg00);
873                                         }
874                                 } else {
875 #endif
876                                         uint8_t* src_cg = dr_cg[y];
877                                         
878                                         for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {
879 #ifdef _X1TURBOZ
880                                                 dest[x2] = dest[x2 + 1] = dr_zpalette_pc[dr_pri_line[y][src_cg[x]][src_text[x]]];
881 #else
882                                                 dest[x2] = dest[x2 + 1] =  dr_palette_pc[dr_pri_line[y][src_cg[x]][src_text[x]]];
883 #endif
884                                         }
885 #ifdef _X1TURBOZ
886                                 }
887 #endif
888                         }
889                 } else {
890                         // 80 columns
891                         for(int y = 0; y < 400; y++) {
892                                 scrntype_t* dest = emu->get_screen_buffer(y);
893                                 uint8_t* src_text = dr_text[y];
894 #ifdef _X1TURBOZ
895                                 if(dr_aen_line[y]) {
896                                         uint16_t* src_cg0 = dr_zcg[0][y];
897                                         
898                                         for(int x = 0; x < 640; x++) {
899                                                 uint16_t cg00 = src_cg0[x] | (src_cg0[x] >> 2);
900                                                 
901                                                 dest[x] = get_zpriority(src_text[x], cg00, cg00);
902                                         }
903                                 } else {
904 #endif
905                                         uint8_t* src_cg = dr_cg[y];
906                                         
907                                         for(int x = 0; x < 640; x++) {
908 #ifdef _X1TURBOZ
909                                                 dest[x] = dr_zpalette_pc[dr_pri_line[y][src_cg[x]][src_text[x]]];
910 #else
911                                                 dest[x] =  dr_palette_pc[dr_pri_line[y][src_cg[x]][src_text[x]]];
912 #endif
913                                         }
914 #ifdef _X1TURBOZ
915                                 }
916 #endif
917                         }
918                 }
919                 emu->screen_skip_line(false);
920         } else {
921 #endif
922                 emu->set_vm_screen_lines(200);
923                 // 200 lines
924                 emu->set_vm_screen_lines(200);
925                 
926                 if(column40) {
927                         // 40 columns
928                         for(int y = 0; y < 200; y++) {
929                                 scrntype_t* dest0 = emu->get_screen_buffer(y * 2 + 0);
930                                 scrntype_t* dest1 = emu->get_screen_buffer(y * 2 + 1);
931                                 uint8_t* src_text = dr_text[y];
932 #ifdef _X1TURBOZ
933                                 if(dr_aen_line[y]) {
934                                         uint16_t* src_cg0 = dr_zcg[0][y];
935                                         uint16_t* src_cg1 = dr_zcg[1][y];
936                                         
937                                         if(C64) {
938                                                 for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {
939                                                         uint16_t cg00 = src_cg0[x] | (src_cg0[x] >> 2);
940                                                         uint16_t cg11 = src_cg1[x] | (src_cg1[x] >> 2);
941                                                         
942                                                         dest0[x2] = dest0[x2 + 1] = get_zpriority(src_text[x], cg00, cg11);
943                                                 }
944                                         } else {
945                                                 for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {
946                                                         uint16_t cg01 = src_cg0[x] | (src_cg1[x] >> 2);
947                                                         
948                                                         dest0[x2] = dest0[x2 + 1] = get_zpriority(src_text[x], cg01, cg01);
949                                                 }
950                                         }
951                                 } else {
952 #endif
953                                         scrntype_t* dest = emu->get_screen_buffer(y);
954                                         uint8_t* src_cg = dr_cg[y];
955                                 
956                                         for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {
957 #ifdef _X1TURBOZ
958                                                 dest0[x2] = dest0[x2 + 1] = dr_zpalette_pc[dr_pri_line[y][src_cg[x]][src_text[x]]];
959 #else
960                                                 dest0[x2] = dest0[x2 + 1] =  dr_palette_pc[dr_pri_line[y][src_cg[x]][src_text[x]]];
961 #endif
962                                         }
963 #ifdef _X1TURBOZ
964                                 }
965 #endif
966                                 if(!config.scan_line) {
967                                         my_memcpy(dest1, dest0, 640 * sizeof(scrntype_t));
968                                 } else {
969                                         memset(dest1, 0, 640 * sizeof(scrntype_t));
970                                 }
971                         }
972                 } else {
973                         // 80 columns
974                         for(int y = 0; y < 200; y++) {
975                                 scrntype_t* dest0 = emu->get_screen_buffer(y * 2 + 0);
976                                 scrntype_t* dest1 = emu->get_screen_buffer(y * 2 + 1);
977                                 uint8_t* src_text = dr_text[y];
978 #ifdef _X1TURBOZ
979                                 if(aen_line[y]) {
980                                         uint16_t* src_cg0 = dr_zcg[0][y];
981                                         
982                                         for(int x = 0; x < 640; x++) {
983                                                 uint16_t cg00 = src_cg0[x] | (src_cg0[x] >> 2);
984                                                 
985                                                 dest0[x] = get_zpriority(src_text[x], cg00, cg00);
986                                         }
987                                 } else {
988 #endif
989                                         uint8_t* src_cg = dr_cg[y];
990                                         
991                                         for(int x = 0; x < 640; x++) {
992 #ifdef _X1TURBOZ
993                                                 dest0[x] = dr_zpalette_pc[dr_pri_line[y][src_cg[x]][src_text[x]]];
994 #else
995                                                 dest0[x] =  dr_palette_pc[dr_pri_line[y][src_cg[x]][src_text[x]]];
996 #endif
997                                         }
998 #ifdef _X1TURBOZ
999                                 }
1000 #endif
1001                                 if(!config.scan_line) {
1002                                         my_memcpy(dest1, dest0, 640 * sizeof(scrntype_t));
1003                                 } else {
1004                                         memset(dest1, 0, 640 * sizeof(scrntype_t));
1005                                 }
1006                         }
1007                 }
1008                 emu->screen_skip_line(true);
1009 #ifdef _X1TURBO_FEATURE
1010         }
1011 #endif
1012
1013 }
1014
1015 void DISPLAY::draw_text(int y)
1016 {
1017         int width = column40 ? 40 : 80;
1018         uint16_t src = st_addr + hz_disp * y;
1019         
1020         bool cur_vert_double = true;
1021         uint8_t prev_attr = 0, prev_pattern_b[32], prev_pattern_r[32], prev_pattern_g[32];
1022         
1023         for(int x = 0; x < hz_disp && x < width; x++) {
1024                 src &= 0x7ff;
1025                 uint8_t code = vram_t[src];
1026 #ifdef _X1TURBO_FEATURE
1027                 uint8_t knj = vram_k[src];
1028 #endif
1029                 uint8_t attr = vram_a[src];
1030                 src++;
1031                 
1032                 uint8_t col = attr & 7;
1033                 bool reverse = ((attr & 8) != 0);
1034                 bool blink = ((attr & 0x10) && (cblink & 0x20));
1035                 reverse = (reverse != blink);
1036                 
1037                 // select pcg or ank
1038                 const uint8_t *pattern_b, *pattern_r, *pattern_g;
1039 #ifdef _X1TURBO_FEATURE
1040                 int shift = 0;
1041                 int max_line = 8;
1042 #else
1043 #define max_line 8
1044 #endif
1045                 if(attr & 0x20) {
1046                         // pcg
1047 #ifdef _X1TURBO_FEATURE
1048                         if(knj & 0x90) {
1049                                 pattern_b = gaiji_b[code >> 1];
1050                                 pattern_r = gaiji_r[code >> 1];
1051                                 pattern_g = gaiji_g[code >> 1];
1052                                 max_line = 16;
1053                         } else {
1054 #endif
1055                                 pattern_b = pcg_b[code];
1056                                 pattern_r = pcg_r[code];
1057                                 pattern_g = pcg_g[code];
1058 #ifdef _X1TURBO_FEATURE
1059                                 shift = hireso ? 1 : 0;
1060                         }
1061 #endif
1062 #ifdef _X1TURBO_FEATURE
1063                 } else if(knj & 0x80) {
1064                         uint32_t ofs = adr2knj_x1t((knj << 8) | code);
1065                         if(knj & 0x40) {
1066                                 ofs += 16; // right
1067                         }
1068                         pattern_b = pattern_r = pattern_g = &kanji[ofs];
1069                         shift = hireso ? ((ch_height >= 32) ? 1 : 0) : ((ch_height >= 16) ? 0 : -1);
1070                         max_line = 16;
1071                 } else if(hireso || (mode1 & 4)) {
1072                         // ank 8x16 or kanji
1073                         pattern_b = pattern_r = pattern_g = &kanji[code << 4];
1074                         shift = hireso ? ((ch_height >= 32) ? 1 : 0) : ((ch_height >= 16) ? 0 : -1);
1075                         max_line = 16;
1076 #endif
1077                 } else {
1078                         // ank 8x8
1079                         pattern_b = pattern_r = pattern_g = &font[code << 3];
1080                 }
1081                 
1082                 // check vertical doubled char
1083                 if(!(attr & 0x40)) {
1084                         cur_vert_double = false;
1085                 }
1086                 
1087                 // render character
1088                 for(int l = 0; l < ch_height; l++) {
1089                         uint8_t b, r, g;
1090                         int line = cur_vert_double ? raster + (l >> 1) : l;
1091 #ifdef _X1TURBO_FEATURE
1092                         if(shift == 1) {
1093                                 line >>= 1;
1094                         } else if(shift == -1) {
1095                                 line <<= 1;
1096                                 if(cur_vert_double) {
1097                                         line |= l & 1;
1098                                 }
1099                         }
1100 #endif
1101                         if((x & 1) && (prev_attr & 0x80)) {
1102                                 b = prev_pattern_b[line] << 4;
1103                                 r = prev_pattern_r[line] << 4;
1104                                 g = prev_pattern_g[line] << 4;
1105                         } else if(line >= max_line) {
1106                                 b = prev_pattern_b[line] = 0;
1107                                 r = prev_pattern_r[line] = 0;
1108                                 g = prev_pattern_g[line] = 0;
1109                         } else {
1110                                 b = prev_pattern_b[line] = pattern_b[line];
1111                                 r = prev_pattern_r[line] = pattern_r[line];
1112                                 g = prev_pattern_g[line] = pattern_g[line];
1113                         }
1114                         if(reverse) {
1115                                 b = (!(col & 1)) ? 0xff : ~b;
1116                                 r = (!(col & 2)) ? 0xff : ~r;
1117                                 g = (!(col & 4)) ? 0xff : ~g;
1118                         } else {
1119                                 b = (!(col & 1)) ? 0 : b;
1120                                 r = (!(col & 2)) ? 0 : r;
1121                                 g = (!(col & 4)) ? 0 : g;
1122                         }
1123                         
1124                         int yy = y * ch_height + l;
1125 #ifdef _X1TURBO_FEATURE
1126                         if(yy >= 400) {
1127 #else
1128                         if(yy >= 200) {
1129 #endif
1130                                 break;
1131                         }
1132                         uint8_t* d = &text[yy][x << 3];
1133                 
1134                         if(attr & 0x80) {
1135                                 // horizontal doubled char
1136                                 d[ 0] = d[ 1] = ((b & 0x80) >> 7) | ((r & 0x80) >> 6) | ((g & 0x80) >> 5);
1137                                 d[ 2] = d[ 3] = ((b & 0x40) >> 6) | ((r & 0x40) >> 5) | ((g & 0x40) >> 4);
1138                                 d[ 4] = d[ 5] = ((b & 0x20) >> 5) | ((r & 0x20) >> 4) | ((g & 0x20) >> 3);
1139                                 d[ 6] = d[ 7] = ((b & 0x10) >> 4) | ((r & 0x10) >> 3) | ((g & 0x10) >> 2);
1140                         } else {
1141                                 d[0] = ((b & 0x80) >> 7) | ((r & 0x80) >> 6) | ((g & 0x80) >> 5);
1142                                 d[1] = ((b & 0x40) >> 6) | ((r & 0x40) >> 5) | ((g & 0x40) >> 4);
1143                                 d[2] = ((b & 0x20) >> 5) | ((r & 0x20) >> 4) | ((g & 0x20) >> 3);
1144                                 d[3] = ((b & 0x10) >> 4) | ((r & 0x10) >> 3) | ((g & 0x10) >> 2);
1145                                 d[4] = ((b & 0x08) >> 3) | ((r & 0x08) >> 2) | ((g & 0x08) >> 1);
1146                                 d[5] = ((b & 0x04) >> 2) | ((r & 0x04) >> 1) | ((g & 0x04) >> 0);
1147                                 d[6] = ((b & 0x02) >> 1) | ((r & 0x02) >> 0) | ((g & 0x02) << 1);
1148                                 d[7] = ((b & 0x01) >> 0) | ((r & 0x01) << 1) | ((g & 0x01) << 2);
1149                         }
1150                         prev_attr = attr;
1151                 }
1152         }
1153         if(cur_vert_double && !prev_vert_double) {
1154                 prev_vert_double = true;
1155                 raster = ch_height >> 1;
1156         } else {
1157                 prev_vert_double = false;
1158                 raster = 0;
1159         }
1160 }
1161
1162 void DISPLAY::draw_cg(int line, int plane)
1163 {
1164         int width = column40 ? 40 : 80;
1165         
1166         int y = line / ch_height;
1167         int l = line % ch_height;
1168         if(y >= vt_disp) {
1169                 return;
1170         }
1171         int ofs, src = st_addr + hz_disp * y;
1172 #ifdef _X1TURBO_FEATURE
1173         int page = (hireso && !(mode1 & 2)) ? (l & 1) : (mode1 & 8);
1174         int ll = hireso ? (l >> 1) : l;
1175         
1176         if(mode1 & 4) {
1177                 ofs = (0x400 * (ll & 15));// + (page ? 0xc000 : 0);
1178         } else {
1179                 ofs = (0x800 * (ll &  7));// + (page ? 0xc000 : 0);
1180         }
1181 #else
1182         ofs = 0x800 * (l & 7);
1183 #endif
1184 #ifdef _X1TURBOZ
1185         if(AEN) {
1186 /*
1187   HIRESO=0, WIDTH=40, C64=0: 320x200, 4096      PAGE0:(ADDR 000h-3FFh) + PAGE0:(ADDR 400h-7FFh) + PAGE1:(ADDR 000h-3FFh) + PAGE1:(ADDR 400h-7FFh)
1188   HIRESO=0, WIDTH=40, C64=1: 320x200, 64x2      PAGE0:(ADDR 000h-3FFh) + PAGE0:(ADDR 400h-7FFh) / PAGE1:(ADDR 000h-3FFh) + PAGE1:(ADDR 400h-7FFh)
1189   HIRESO=1, WIDTH=40, C64=*: 320x200, 64                PAGE*:(ADDR 000h-3FFh) + PAGE*:(ADDR 400h-7FFh)
1190   HIRESO=0, WIDTH=80, C64=*: 640x200, 64                PAGE0:(ADDR 000h-7FFh) + PAGE1:(ADDR 000h-7FFh)
1191   HIRESO=1, WIDTH=80, C64=*: 640x200, 8         PAGE0:(ADDR 000h-7FFh) + PAGE0:(ADDR 000h-7FFh)
1192
1193   HIRESO=0, WIDTH=40, C64=1: 320x200, 64x2
1194   mode1 zpriority       
1195   SCREEN 0      00      00              PAGE0
1196   SCREEM 2      18      08              PAGE1
1197   SCREEN 4      00      10              PAGE0 > PAGE1
1198   SCREEN 6      18      18              PAGE0 < PAGE1
1199 */
1200                 if(!hireso) {
1201                         if(column40) {
1202                                 if(C64 && !(zpriority & 0x10)) {
1203                                         if(plane) {
1204                                                 my_memcpy(zcg[plane][1], zcg[plane][0], sizeof(uint16_t) * 640);
1205                                                 return;
1206                                         }
1207                                 } else {
1208                                         page = plane;
1209                                 }
1210                         } else {
1211                                 page = 0;
1212                         }
1213                 }
1214                 if(page) {
1215                         ofs += 0xc000;
1216                 }
1217                 int ofs_b0 = ofs + 0x0000;
1218                 int ofs_r0 = ofs + 0x4000;
1219                 int ofs_g0 = ofs + 0x8000;
1220                 int ofs_b1 = column40 ? (ofs_b0 ^ 0x400) : hireso ? ofs_b0 : (ofs_b0 + 0xc000);
1221                 int ofs_r1 = column40 ? (ofs_r0 ^ 0x400) : hireso ? ofs_r0 : (ofs_r0 + 0xc000);
1222                 int ofs_g1 = column40 ? (ofs_g0 ^ 0x400) : hireso ? ofs_g0 : (ofs_g0 + 0xc000);
1223                 
1224                 for(int x = 0; x < hz_disp && x < width; x++) {
1225                         src &= column40 ? 0x3ff : 0x7ff;
1226                         uint16_t b0 = vram_ptr[ofs_b0 | src];
1227                         uint16_t r0 = vram_ptr[ofs_r0 | src];
1228                         uint16_t g0 = vram_ptr[ofs_g0 | src];
1229                         uint16_t b1 = vram_ptr[ofs_b1 | src];
1230                         uint16_t r1 = vram_ptr[ofs_r1 | src];
1231                         uint16_t g1 = vram_ptr[ofs_g1 | src++];
1232                         uint16_t* d = &zcg[plane][line][x << 3];
1233                         
1234                         // MSB <- G0,G1,0,0, R0,R1,0,0, B0,B1,0,0 -> LSB
1235                         d[0] = ((b0 & 0x80) >> 4) | ((b1 & 0x80) >> 5) | ((r0 & 0x80) >> 0) | ((r1 & 0x80) >> 1) | ((g0 & 0x80) <<  4) | ((g1 & 0x80) <<  3);
1236                         d[1] = ((b0 & 0x40) >> 3) | ((b1 & 0x40) >> 4) | ((r0 & 0x40) << 1) | ((r1 & 0x40) >> 0) | ((g0 & 0x40) <<  5) | ((g1 & 0x40) <<  4);
1237                         d[2] = ((b0 & 0x20) >> 2) | ((b1 & 0x20) >> 3) | ((r0 & 0x20) << 2) | ((r1 & 0x20) << 1) | ((g0 & 0x20) <<  6) | ((g1 & 0x20) <<  5);
1238                         d[3] = ((b0 & 0x10) >> 1) | ((b1 & 0x10) >> 2) | ((r0 & 0x10) << 3) | ((r1 & 0x10) << 2) | ((g0 & 0x10) <<  7) | ((g1 & 0x10) <<  6);
1239                         d[4] = ((b0 & 0x08) >> 0) | ((b1 & 0x08) >> 1) | ((r0 & 0x08) << 4) | ((r1 & 0x08) << 3) | ((g0 & 0x08) <<  8) | ((g1 & 0x08) <<  7);
1240                         d[5] = ((b0 & 0x04) << 1) | ((b1 & 0x04) >> 0) | ((r0 & 0x04) << 5) | ((r1 & 0x04) << 4) | ((g0 & 0x04) <<  9) | ((g1 & 0x04) <<  8);
1241                         d[6] = ((b0 & 0x02) << 2) | ((b1 & 0x02) << 1) | ((r0 & 0x02) << 6) | ((r1 & 0x02) << 5) | ((g0 & 0x02) << 10) | ((g1 & 0x02) <<  9);
1242                         d[7] = ((b0 & 0x01) << 3) | ((b1 & 0x01) << 2) | ((r0 & 0x01) << 7) | ((r1 & 0x01) << 6) | ((g0 & 0x01) << 11) | ((g1 & 0x01) << 10);
1243                 }
1244         } else
1245 #endif
1246         {
1247 #ifdef _X1TURBO_FEATURE
1248                 if(page) {
1249                         ofs += 0xc000;
1250                 }
1251 #endif
1252                 int ofs_b = ofs + 0x0000;
1253                 int ofs_r = ofs + 0x4000;
1254                 int ofs_g = ofs + 0x8000;
1255                 
1256                 for(int x = 0; x < hz_disp && x < width; x++) {
1257                         src &= 0x7ff;
1258                         uint8_t b = vram_ptr[ofs_b | src];
1259                         uint8_t r = vram_ptr[ofs_r | src];
1260                         uint8_t g = vram_ptr[ofs_g | src++];
1261                         uint8_t* d = &cg[line][x << 3];
1262                         
1263                         d[0] = ((b & 0x80) >> 7) | ((r & 0x80) >> 6) | ((g & 0x80) >> 5);
1264                         d[1] = ((b & 0x40) >> 6) | ((r & 0x40) >> 5) | ((g & 0x40) >> 4);
1265                         d[2] = ((b & 0x20) >> 5) | ((r & 0x20) >> 4) | ((g & 0x20) >> 3);
1266                         d[3] = ((b & 0x10) >> 4) | ((r & 0x10) >> 3) | ((g & 0x10) >> 2);
1267                         d[4] = ((b & 0x08) >> 3) | ((r & 0x08) >> 2) | ((g & 0x08) >> 1);
1268                         d[5] = ((b & 0x04) >> 2) | ((r & 0x04) >> 1) | ((g & 0x04) >> 0);
1269                         d[6] = ((b & 0x02) >> 1) | ((r & 0x02) >> 0) | ((g & 0x02) << 1);
1270                         d[7] = ((b & 0x01) >> 0) | ((r & 0x01) << 1) | ((g & 0x01) << 2);
1271                 }
1272         }
1273 }
1274
1275 #ifdef _X1TURBOZ
1276 int DISPLAY::get_zpal_num(uint32_t addr, uint32_t data)
1277 {
1278         int num = ((data >> 4) & 0x0f) | ((addr << 4) & 0xff0);
1279         
1280         if(hireso && !column40) {
1281                 // 8 colors
1282                 num &= 0x888;
1283                 num |= num >> 1;
1284                 num |= num >> 2;
1285         } else if(!(!hireso && column40 && !C64)) {
1286                 // 64 colors
1287                 num &= 0xccc;
1288                 num |= num >> 2;
1289         }
1290         return num;
1291 }
1292
1293 scrntype_t DISPLAY::get_zpriority(uint8_t text, uint16_t cg0, uint16_t cg1)
1294 {
1295         if((mode2 & 8) && (text == (mode2 & 7))) {
1296                 int digital = ((cg0 >> 9) & 4) | ((cg0 >> 6) & 2) | ((cg0 >> 3) & 1);
1297                 if(!(dr_priority & (1 << digital))) {
1298                         return 0;
1299                 }
1300         }
1301         uint16_t fore = ((dr_zpriority & 0x18) != 0x18) ? cg0 : cg1;
1302         uint16_t back = ((dr_zpriority & 0x18) != 0x18) ? cg1 : cg0;
1303         uint16_t disp;
1304         
1305         switch(dr_zpriority & 0x13) {
1306         case 0x00:
1307         case 0x02:
1308                 disp = text ? text : (fore + 16);
1309                 break;
1310         case 0x01:
1311         case 0x03:
1312                 disp = fore ? (fore + 16) : text;
1313                 break;
1314         case 0x10:
1315                 disp = text ? text : fore ? (fore + 16) : (back + 16);
1316                 break;
1317         case 0x11:
1318                 disp = fore ? (fore + 16) : back ? (back + 16) : text;
1319                 break;
1320         case 0x12:
1321                 disp = fore ? (fore + 16) : text ? text : (back + 16);
1322                 break;
1323         default: // undefined case :-(
1324                 disp = text ? text : fore ? (fore + 16) : (back + 16);
1325                 break;
1326         }
1327 //      if((mode2 & 0x10) && disp == (0x000 + 16)) {
1328 //              return 0;
1329 //      }
1330 //      if((mode2 & 0x20) && disp == (0x00f + 16)) {
1331 //              return 0;
1332 //      }
1333         return dr_zpalette_pc[disp];
1334 }
1335 #endif
1336
1337 // kanji rom (from X1EMU by KM)
1338
1339 void DISPLAY::write_kanji(uint32_t addr, uint32_t data)
1340 {
1341         switch(addr) {
1342         case 0xe80:
1343                 kaddr = (kaddr & 0xff00) | data;
1344                 break;
1345         case 0xe81:
1346                 kaddr = (kaddr & 0xff) | (data << 8);
1347                 break;
1348         case 0xe82:
1349                 // TODO: bit0 L->H: Latch
1350                 kanji_ptr = &kanji[adr2knj_x1(kaddr & 0xfff0)];
1351                 break;
1352         }
1353 }
1354
1355 uint32_t DISPLAY::read_kanji(uint32_t addr)
1356 {
1357         switch(addr) {
1358         case 0xe80:
1359                 if(kaddr & 0xff00) {
1360                         uint32_t val = kanji_ptr[kofs];
1361                         kflag |= 1;
1362                         if(kflag == 3) {
1363                                 kofs = (kofs + 1) & 15;
1364                                 kflag = 0;
1365                         }
1366                         return val;
1367                 }
1368                 return jis2adr_x1(kaddr << 8) >> 8;
1369         case 0xe81:
1370                 if(kaddr & 0xff00) {
1371                         uint32_t val = kanji_ptr[kofs + 16];
1372                         kflag |= 2;
1373                         if(kflag == 3) {
1374                                 kofs = (kofs + 1) & 15;
1375                                 kflag = 0;
1376                         }
1377                         return val;
1378                 }
1379                 return 0;
1380         }
1381         return 0xff;
1382 }
1383
1384 uint16_t DISPLAY::jis2adr_x1(uint16_t jis)
1385 {
1386         uint16_t jh, jl, adr;
1387         
1388         jh = jis >> 8;
1389         jl = jis & 0xff;
1390         if(jh > 0x28) {
1391                 adr = 0x4000 + (jh - 0x30) * 0x600;
1392         } else {
1393                 adr = 0x0100 + (jh - 0x21) * 0x600;
1394         }
1395         if(jl >= 0x20) {
1396                 adr += (jl - 0x20) * 0x10;
1397         }
1398         return adr;
1399 }
1400
1401 uint32_t DISPLAY::adr2knj_x1(uint16_t adr)
1402 {
1403         uint16_t jh, jl, jis;
1404         
1405         if(adr < 0x4000) {
1406                 jh = adr - 0x0100;
1407                 jh = 0x21 + jh / 0x600;
1408         } else {
1409                 jh = adr - 0x4000;
1410                 jh = 0x30 + jh / 0x600;
1411         }
1412         if(jh > 0x28) {
1413                 adr -= 0x4000 + (jh - 0x30) * 0x600;
1414         } else {
1415                 adr -= 0x0100 + (jh - 0x21) * 0x600;
1416         }
1417         jl = 0x20;
1418         if(adr) {
1419                 jl += adr / 0x10;
1420         }
1421         
1422         jis = (jh << 8) | jl;
1423         return jis2knj(jis);
1424 }
1425
1426 #ifdef _X1TURBO_FEATURE
1427 uint32_t DISPLAY::adr2knj_x1t(uint16_t adr)
1428 {
1429         uint16_t j1, j2;
1430         uint16_t rl, rh;
1431         uint16_t jis;
1432         
1433         rh = adr >> 8;
1434         rl = adr & 0xff;
1435         
1436         rh &= 0x1f;
1437         if(!rl && !rh) {
1438                 return jis2knj(0);
1439         }
1440         j2 = rl & 0x1f;         // rl4,3,2,1,0
1441         j1 = (rl / 0x20) & 7;   // rl7,6,5
1442         
1443         if(rh < 0x04) {
1444                 // 2121-277e
1445                 j1 |= 0x20;
1446                 switch(rh & 3) {
1447                 case 0: j2 |= 0x20; break;
1448                 case 1: j2 |= 0x60; break;
1449                 case 2: j2 |= 0x40; break;
1450                 default: j1 = j2 = 0; break;
1451                 }
1452         } else if(rh > 0x1c) {
1453                 // 7021-777e
1454                 j1 |= 0x70;
1455                 switch(rh & 3) {
1456                 case 0: j2 |= 0x20; break;
1457                 case 1: j2 |= 0x60; break;
1458                 case 2: j2 |= 0x40; break;
1459                 default: j1 = j2 = 0; break;
1460                 }
1461         } else {
1462                 j1 |= (((rh >> 1) + 7) / 3) * 0x10;
1463                 j1 |= (rh & 1) * 8;
1464                 j2 |= ((((rh >> 1) + 1) % 3) + 1) * 0x20;
1465         }
1466         
1467         jis = (j1 << 8) | j2;
1468         return jis2knj(jis);
1469 }
1470 #endif
1471
1472 uint32_t DISPLAY::jis2knj(uint16_t jis)
1473 {
1474         uint32_t sjis = jis2sjis(jis);
1475         
1476         if(sjis < 0x100) {
1477                 return sjis * 16;
1478         } else if(sjis >= 0x8140 && sjis < 0x84c0) {
1479                 return 0x01000 + (sjis - 0x8140) * 32;
1480         } else if(sjis >= 0x8890 && sjis < 0xa000) {
1481                 return 0x08000 + (sjis - 0x8890) * 32;
1482         } else if(sjis >= 0xe040 && sjis < 0xeab0) {
1483                 return 0x36e00 + (sjis - 0xe040) * 32;
1484         } else {
1485                 return 0;
1486         }
1487 }
1488
1489 uint16_t DISPLAY::jis2sjis(uint16_t jis)
1490 {
1491         uint16_t c1, c2;
1492         
1493         if(!jis) {
1494                 return 0;
1495         }
1496         c1 = jis >> 8;
1497         c2 = jis & 0xff;
1498         
1499         if(c1 & 1) {
1500                 c2 += 0x1f;
1501                 if(c2 >= 0x7f) {
1502                         c2++;
1503                 }
1504         } else {
1505                 c2 += 0x7e;
1506         }
1507         c1 = (c1 - 0x20 - 1) / 2 + 0x81;
1508         if(c1 >= 0xa0) {
1509                 c1 += 0x40;
1510         }
1511         return (c1 << 8) | c2;
1512 }
1513
1514 #define STATE_VERSION   4
1515
1516 #include "../statesub.h"
1517
1518 void DISPLAY::decl_state()
1519 {
1520         enter_decl_state(STATE_VERSION);
1521         
1522         DECL_STATE_ENTRY_1D_ARRAY(vram_t, sizeof(vram_t));
1523         DECL_STATE_ENTRY_1D_ARRAY(vram_a, sizeof(vram_a));
1524 #ifdef _X1TURBO_FEATURE
1525         DECL_STATE_ENTRY_1D_ARRAY(vram_k, sizeof(vram_k));
1526 #endif
1527         DECL_STATE_ENTRY_2D_ARRAY(pcg_b, 256, 8);
1528         DECL_STATE_ENTRY_2D_ARRAY(pcg_r, 256, 8);
1529         DECL_STATE_ENTRY_2D_ARRAY(pcg_g, 256, 8);
1530 #ifdef _X1TURBO_FEATURE
1531         DECL_STATE_ENTRY_2D_ARRAY(gaiji_b, 128, 16);
1532         DECL_STATE_ENTRY_2D_ARRAY(gaiji_r, 128, 16);
1533         DECL_STATE_ENTRY_2D_ARRAY(gaiji_g, 128, 16);
1534 #endif
1535         DECL_STATE_ENTRY_UINT8(cur_code);
1536         DECL_STATE_ENTRY_UINT8(cur_line);
1537         DECL_STATE_ENTRY_INT32(kaddr);
1538         DECL_STATE_ENTRY_INT32(kofs);
1539         DECL_STATE_ENTRY_INT32(kflag);
1540         DECL_STATE_ENTRY_INT32(tmp_kanji_ptr); // (int)(kanji_ptr - &kanji[0]);
1541         DECL_STATE_ENTRY_1D_ARRAY(pal, sizeof(pal));
1542         DECL_STATE_ENTRY_UINT8(priority);
1543         DECL_STATE_ENTRY_2D_ARRAY(pri, 8, 8);
1544         DECL_STATE_ENTRY_BOOL(column40);
1545 #ifdef _X1TURBO_FEATURE
1546         DECL_STATE_ENTRY_UINT8(mode1);
1547         DECL_STATE_ENTRY_UINT8(mode2);
1548         DECL_STATE_ENTRY_BOOL(hireso);
1549 #endif
1550 #ifdef _X1TURBOZ
1551         DECL_STATE_ENTRY_UINT8(zmode1);
1552         DECL_STATE_ENTRY_UINT8(zpriority);
1553         DECL_STATE_ENTRY_UINT8(zadjust);
1554         DECL_STATE_ENTRY_UINT8(zmosaic);
1555         DECL_STATE_ENTRY_UINT8(zchromakey);
1556         DECL_STATE_ENTRY_UINT8(zscroll);
1557         DECL_STATE_ENTRY_UINT8(zmode2);
1558         DECL_STATE_ENTRY_1D_ARRAY(ztpal, sizeof(ztpal));
1559
1560         DECL_STATE_ENTRY_UINT8_STRIDE((zpal[0].b), sizeof(zpal) / sizeof(zpal[0]) ,sizeof(zpal[0]));
1561         DECL_STATE_ENTRY_UINT8_STRIDE((zpal[0].r), sizeof(zpal) / sizeof(zpal[0]) ,sizeof(zpal[0]));
1562         DECL_STATE_ENTRY_UINT8_STRIDE((zpal[0].g), sizeof(zpal) / sizeof(zpal[0]) ,sizeof(zpal[0]));
1563         DECL_STATE_ENTRY_INT32(zpal_num);
1564         
1565         DECL_STATE_ENTRY_1D_ARRAY(zpalette_pc, sizeof(zpalette_pc) / sizeof(scrntype_t)); // ToDo: Generic value.
1566 #endif
1567         DECL_STATE_ENTRY_BOOL(prev_vert_double);
1568         DECL_STATE_ENTRY_INT32(raster);
1569         DECL_STATE_ENTRY_INT32(cblink);
1570         DECL_STATE_ENTRY_INT32(ch_height);
1571         DECL_STATE_ENTRY_INT32(hz_total);
1572         DECL_STATE_ENTRY_INT32(hz_disp);
1573         DECL_STATE_ENTRY_INT32(vt_disp);
1574         DECL_STATE_ENTRY_INT32(st_addr);
1575         DECL_STATE_ENTRY_UINT32(vblank_clock);
1576         DECL_STATE_ENTRY_BOOL(cur_blank);
1577         
1578         leave_decl_state();
1579 }
1580 void DISPLAY::save_state(FILEIO* state_fio)
1581 {
1582         tmp_kanji_ptr = (int)(kanji_ptr - &kanji[0]);
1583         
1584         if(state_entry != NULL) {
1585                 state_entry->save_state(state_fio);
1586         }
1587 //      state_fio->FputUint32(STATE_VERSION);
1588 //      state_fio->FputInt32(this_device_id);
1589         
1590 //      state_fio->Fwrite(vram_t, sizeof(vram_t), 1);
1591 //      state_fio->Fwrite(vram_a, sizeof(vram_a), 1);
1592 //#ifdef _X1TURBO_FEATURE
1593 //      state_fio->Fwrite(vram_k, sizeof(vram_k), 1);
1594 //#endif
1595 //      state_fio->Fwrite(pcg_b, sizeof(pcg_b), 1);
1596 //      state_fio->Fwrite(pcg_r, sizeof(pcg_r), 1);
1597 //      state_fio->Fwrite(pcg_g, sizeof(pcg_g), 1);
1598 //#ifdef _X1TURBO_FEATURE
1599 //      state_fio->Fwrite(gaiji_b, sizeof(gaiji_b), 1);
1600 //      state_fio->Fwrite(gaiji_r, sizeof(gaiji_r), 1);
1601 //      state_fio->Fwrite(gaiji_g, sizeof(gaiji_g), 1);
1602 //#endif
1603 //      state_fio->FputUint8(cur_code);
1604 //      state_fio->FputUint8(cur_line);
1605 //      state_fio->FputInt32(kaddr);
1606 //      state_fio->FputInt32(kofs);
1607 //      state_fio->FputInt32(kflag);
1608
1609 //      state_fio->FputInt32((int)(kanji_ptr - &kanji[0]));
1610 //      state_fio->Fwrite(pal, sizeof(pal), 1);
1611 //      state_fio->FputUint8(priority);
1612 //      state_fio->Fwrite(pri, sizeof(pri), 1);
1613 //      state_fio->FputBool(column40);
1614 //#ifdef _X1TURBO_FEATURE
1615 //      state_fio->FputUint8(mode1);
1616 //      state_fio->FputUint8(mode2);
1617 //      state_fio->FputBool(hireso);
1618 //#endif
1619 //#ifdef _X1TURBOZ
1620 //      state_fio->FputUint8(zmode1);
1621 //      state_fio->FputUint8(zpriority);
1622 //      state_fio->FputUint8(zadjust);
1623 //      state_fio->FputUint8(zmosaic);
1624 //      state_fio->FputUint8(zchromakey);
1625 //      state_fio->FputUint8(zscroll);
1626 //      state_fio->FputUint8(zmode2);
1627 //      state_fio->Fwrite(ztpal, sizeof(ztpal), 1);
1628 //      state_fio->Fwrite(zpal, sizeof(zpal), 1);
1629 //      state_fio->FputInt32(zpal_num);
1630 //      state_fio->Fwrite(zpalette_pc, sizeof(zpalette_pc), 1);
1631 //#endif
1632 //      state_fio->FputBool(prev_vert_double);
1633 //      state_fio->FputInt32(raster);
1634 //      state_fio->FputInt32(cblink);
1635 //      state_fio->FputInt32(ch_height);
1636 //      state_fio->FputInt32(hz_total);
1637 //      state_fio->FputInt32(hz_disp);
1638 //      state_fio->FputInt32(vt_disp);
1639 //      state_fio->FputInt32(st_addr);
1640 //      state_fio->FputUint32(vblank_clock);
1641 //      state_fio->FputBool(cur_blank);
1642 }
1643
1644 bool DISPLAY::load_state(FILEIO* state_fio)
1645 {
1646         bool mb = false;
1647         if(state_entry != NULL) {
1648                 mb = state_entry->load_state(state_fio);
1649         }
1650         if(!mb) return false;
1651 //      if(state_fio->FgetUint32() != STATE_VERSION) {
1652 //              return false;
1653 //      }
1654 //      if(state_fio->FgetInt32() != this_device_id) {
1655 //              return false;
1656 //      }
1657 //      state_fio->Fread(vram_t, sizeof(vram_t), 1);
1658 //      state_fio->Fread(vram_a, sizeof(vram_a), 1);
1659 //#ifdef _X1TURBO_FEATURE
1660 //      state_fio->Fread(vram_k, sizeof(vram_k), 1);
1661 //#endif
1662 //      state_fio->Fread(pcg_b, sizeof(pcg_b), 1);
1663 //      state_fio->Fread(pcg_r, sizeof(pcg_r), 1);
1664 //      state_fio->Fread(pcg_g, sizeof(pcg_g), 1);
1665 //#ifdef _X1TURBO_FEATURE
1666 //      state_fio->Fread(gaiji_b, sizeof(gaiji_b), 1);
1667 //      state_fio->Fread(gaiji_r, sizeof(gaiji_r), 1);
1668 //      state_fio->Fread(gaiji_g, sizeof(gaiji_g), 1);
1669 //#endif
1670 //      cur_code = state_fio->FgetUint8();
1671 //      cur_line = state_fio->FgetUint8();
1672 //      kaddr = state_fio->FgetInt32();
1673 //      kofs = state_fio->FgetInt32();
1674 //      kflag = state_fio->FgetInt32();
1675 //      kanji_ptr = &kanji[0] + state_fio->FgetInt32();
1676 //      state_fio->Fread(pal, sizeof(pal), 1);
1677 //      priority = state_fio->FgetUint8();
1678 //      state_fio->Fread(pri, sizeof(pri), 1);
1679 //      column40 = state_fio->FgetBool();
1680 //#ifdef _X1TURBO_FEATURE
1681 //      mode1 = state_fio->FgetUint8();
1682 //      mode2 = state_fio->FgetUint8();
1683 //      hireso = state_fio->FgetBool();
1684 //#endif
1685 //#ifdef _X1TURBOZ
1686 //      zmode1 = state_fio->FgetUint8();
1687 //      zpriority = state_fio->FgetUint8();
1688 //      zadjust = state_fio->FgetUint8();
1689 //      zmosaic = state_fio->FgetUint8();
1690 //      zchromakey = state_fio->FgetUint8();
1691 //      zscroll = state_fio->FgetUint8();
1692 //      zmode2 = state_fio->FgetUint8();
1693 //      state_fio->Fread(ztpal, sizeof(ztpal), 1);
1694 //      state_fio->Fread(zpal, sizeof(zpal), 1);
1695 //      zpal_num = state_fio->FgetInt32();
1696 //      state_fio->Fread(zpalette_pc, sizeof(zpalette_pc), 1);
1697 //#endif
1698 //      prev_vert_double = state_fio->FgetBool();
1699 //      raster = state_fio->FgetInt32();
1700 //      cblink = state_fio->FgetInt32();
1701 //      ch_height = state_fio->FgetInt32();
1702 //      hz_total = state_fio->FgetInt32();
1703 //      hz_disp = state_fio->FgetInt32();
1704 //      vt_disp = state_fio->FgetInt32();
1705 //      st_addr = state_fio->FgetInt32();
1706 //      vblank_clock = state_fio->FgetUint32();
1707 //      cur_blank = state_fio->FgetBool();
1708         
1709         kanji_ptr = &kanji[0] + tmp_kanji_ptr;
1710         // post process
1711         // Copy images to draw buffers.
1712         my_memcpy(dr_text, text, sizeof(dr_text));
1713         my_memcpy(dr_cg, cg, sizeof(dr_cg));
1714         my_memcpy(dr_pri_line, pri_line, sizeof(dr_pri_line));
1715         my_memcpy(dr_palette_pc, palette_pc, sizeof(dr_palette_pc));
1716         dr_priority = priority;
1717 #ifdef _X1TURBOZ
1718         dr_zpriority = zpriority;
1719         my_memcpy(dr_zcg, zcg, sizeof(dr_zcg));
1720         my_memcpy(dr_aen_line, aen_line, sizeof(dr_aen_line));
1721         my_memcpy(dr_zpalette_pc, zpalette_pc, sizeof(zpalette_pc));
1722         zpalette_pc[8 + 0] = zpalette_pc[16 + 0x000];
1723         zpalette_pc[8 + 1] = zpalette_pc[16 + 0x00f];
1724         zpalette_pc[8 + 2] = zpalette_pc[16 + 0x0f0];
1725         zpalette_pc[8 + 3] = zpalette_pc[16 + 0x0ff];
1726         zpalette_pc[8 + 4] = zpalette_pc[16 + 0xf00];
1727         zpalette_pc[8 + 5] = zpalette_pc[16 + 0xf0f];
1728         zpalette_pc[8 + 6] = zpalette_pc[16 + 0xff0];
1729         zpalette_pc[8 + 7] = zpalette_pc[16 + 0xfff];
1730 #endif  
1731
1732         update_crtc(); // force update timing
1733         
1734         return true;
1735 }
1736