OSDN Git Service

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