OSDN Git Service

[UI][VM][EMU][Qt][WIP] Apply upstream's OSD class.I don't test to build yet X-)
[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
6         Origin : X1EMU by KM (kanji rom)
7                  X-millenium by Yui (ank16 patch)
8         Author : Takeda.Toshiya
9         Date   : 2009.03.14-
10
11         [ display ]
12 */
13
14 #include "display.h"
15 #ifdef _X1TURBO_FEATURE
16 #include "../hd46505.h"
17 #endif
18 #include "../i8255.h"
19
20 #ifdef _X1TURBOZ
21 #define AEN     ((zmode1 & 0x80) != 0)
22 #define APEN    ((zmode2 & 0x80) != 0)
23 #define APRD    ((zmode2 & 0x08) != 0)
24 #endif
25
26 // from X-millenium
27
28 static const uint16 ANKFONT7f_af[0x21 * 8] = {
29         0x0000, 0x3000, 0x247f, 0x6c24, 0x484c, 0xce4b, 0x0000, 0x0000,
30
31         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff,
32         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff,
33         0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff,
34         0x0000, 0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff,
35         0x0000, 0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
36         0x0000, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
37         0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
38         0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
39         0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080, 0x8080,
40         0xc0c0, 0xc0c0, 0xc0c0, 0xc0c0, 0xc0c0, 0xc0c0, 0xc0c0, 0xc0c0,
41         0xe0e0, 0xe0e0, 0xe0e0, 0xe0e0, 0xe0e0, 0xe0e0, 0xe0e0, 0xe0e0,
42         0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0,
43         0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8, 0xf8f8,
44         0xfcfc, 0xfcfc, 0xfcfc, 0xfcfc, 0xfcfc, 0xfcfc, 0xfcfc, 0xfcfc,
45         0xfefe, 0xfefe, 0xfefe, 0xfefe, 0xfefe, 0xfefe, 0xfefe, 0xfefe,
46         0x0101, 0x0202, 0x0404, 0x0808, 0x1010, 0x2020, 0x4040, 0x8080,
47
48         0x0000, 0x0000, 0x0000, 0x0000, 0x00ff, 0x0000, 0x0000, 0x0000,
49         0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010, 0x1010,
50         0x1010, 0x1010, 0x1010, 0x1010, 0x00ff, 0x0000, 0x0000, 0x0000,
51         0x0000, 0x0000, 0x0000, 0x0000, 0x10ff, 0x1010, 0x1010, 0x1010,
52         0x1010, 0x1010, 0x1010, 0x1010, 0x10f0, 0x1010, 0x1010, 0x1010,
53         0x1010, 0x1010, 0x1010, 0x1010, 0x101f, 0x1010, 0x1010, 0x1010,
54         0x1010, 0x1010, 0x1010, 0x1010, 0x10ff, 0x1010, 0x1010, 0x1010,
55         0x0000, 0x0000, 0x0000, 0x0000, 0x10f0, 0x1010, 0x1010, 0x1010,
56         0x1010, 0x1010, 0x1010, 0x1010, 0x00f0, 0x0000, 0x0000, 0x0000,
57         0x1010, 0x1010, 0x1010, 0x1010, 0x001f, 0x0000, 0x0000, 0x0000,
58         0x0000, 0x0000, 0x0000, 0x0000, 0x101f, 0x1010, 0x1010, 0x1010,
59         0x0000, 0x0000, 0x0000, 0x0000, 0x4080, 0x2020, 0x1010, 0x1010,
60         0x1010, 0x1010, 0x0810, 0x0408, 0x0003, 0x0000, 0x0000, 0x0000,
61         0x1010, 0x1010, 0x2010, 0x4020, 0x0080, 0x0000, 0x0000, 0x0000,
62         0x0000, 0x0000, 0x0000, 0x0000, 0x0403, 0x0808, 0x1010, 0x1010,
63         0x8080, 0x4040, 0x2020, 0x1010, 0x0808, 0x0404, 0x0202, 0x0101
64 };
65
66 static const uint16 ANKFONTe0_ff[0x20 * 8] = {
67         0x0000, 0x7e3c, 0xffff, 0xdbdb, 0xffff, 0xe7db, 0x7eff, 0x003c,
68         0x0000, 0x423c, 0x8181, 0xa5a5, 0x8181, 0x99a5, 0x4281, 0x003c,
69         0x0000, 0x3810, 0x7c7c, 0xfefe, 0xfefe, 0x106c, 0x7c38, 0x0000,
70         0x0000, 0x6c00, 0xfefe, 0xfefe, 0xfefe, 0x7c7c, 0x1038, 0x0000,
71         0x0000, 0x1010, 0x3838, 0x7c7c, 0x7cfe, 0x387c, 0x1038, 0x0010,
72         0x0000, 0x3810, 0x7c7c, 0x5438, 0xfefe, 0x6cfe, 0x7c10, 0x0000,
73         0x0101, 0x0303, 0x0707, 0x0f0f, 0x1f1f, 0x3f3f, 0x7f7f, 0xffff,
74         0x8080, 0xc0c0, 0xe0e0, 0xf0f0, 0xf8f8, 0xfcfc, 0xfefe, 0xffff,
75         0x8181, 0x4242, 0x2424, 0x1818, 0x1818, 0x2424, 0x4242, 0x8181,
76         0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0, 0x0000, 0x0000, 0x0000, 0x0000,
77         0x0000, 0x0000, 0x0000, 0x0000, 0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0,
78         0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0x0000, 0x0000, 0x0000, 0x0000,
79         0x0000, 0x0000, 0x0000, 0x0000, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f,
80         0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f, 0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0,
81         0xf0f0, 0xf0f0, 0xf0f0, 0xf0f0, 0x0f0f, 0x0f0f, 0x0f0f, 0x0f0f,
82         0x81ff, 0x8181, 0x8181, 0x8181, 0x8181, 0x8181, 0x8181, 0xff81,
83
84         0x55aa, 0x55aa, 0x55aa, 0x55aa, 0x55aa, 0x55aa, 0x55aa, 0x55aa,
85         0x1000, 0x1010, 0xf01e, 0x1010, 0x1010, 0x1010, 0x7e10, 0x00c0,
86         0x1000, 0x2418, 0x7c42, 0x1090, 0x781c, 0x5410, 0xfe54, 0x0000,
87         0x1000, 0x1010, 0xfe10, 0x1010, 0x3030, 0x565c, 0x9090, 0x0010,
88         0x1000, 0x1210, 0xf412, 0x3034, 0x5030, 0x9654, 0x1090, 0x0000,
89         0x0800, 0x8808, 0x5292, 0x1454, 0x2020, 0x5020, 0x465c, 0x0040,
90         0x0000, 0xe23c, 0x8282, 0x82fa, 0x7a82, 0x4242, 0x0044, 0x0000,
91         0x0000, 0x443c, 0x8242, 0xf282, 0x8282, 0x8282, 0x3844, 0x0000,
92         0x0800, 0x5e18, 0xa468, 0xe4be, 0xbea4, 0xb2a2, 0x0a5a, 0x0002,
93         0x0000, 0x2628, 0x4042, 0xe23c, 0x2222, 0x4222, 0x4442, 0x0004,
94         0x0800, 0x0808, 0xda7a, 0x5454, 0x46e4, 0xe442, 0x08c4, 0x0000,
95         0x0000, 0x7e40, 0x8848, 0x28be, 0x2828, 0x3e28, 0x08e8, 0x0008,
96         0x0000, 0x723c, 0x9252, 0x9292, 0x8292, 0x84fc, 0x8484, 0x0000,
97         0x0000, 0x1010, 0x2010, 0x2020, 0x6040, 0x8c50, 0x8286, 0x0000,
98         0x0000, 0x4040, 0x784e, 0x88c0, 0x388e, 0x0848, 0x7e08, 0x0000,
99         0x0000, 0x7c00, 0x0000, 0x0000, 0x10fe, 0x1010, 0x1010, 0x0010
100 };
101
102 void DISPLAY::initialize()
103 {
104         // load rom images
105         FILEIO* fio = new FILEIO();
106         
107         // ank8 (8x8)
108         if(fio->Fopen(emu->bios_path(_T("ANK8.ROM")), FILEIO_READ_BINARY)) {
109                 fio->Fread(font, sizeof(font), 1);
110                 fio->Fclose();
111         } else if(fio->Fopen(emu->bios_path(_T("FNT0808.X1")), FILEIO_READ_BINARY)) {
112                 // xmillenium rom
113                 fio->Fread(font, sizeof(font), 1);
114                 fio->Fclose();
115         }
116         
117         // ank16 (8x16)
118         if(fio->Fopen(emu->bios_path(_T("ANK16.ROM")), FILEIO_READ_BINARY)) {
119                 fio->Fread(kanji, 0x1000, 1);
120                 fio->Fclose();
121         } else if(fio->Fopen(emu->bios_path(_T("FNT0816.X1")), FILEIO_READ_BINARY)) {
122                 // xmillenium rom
123                 fio->Fread(kanji, 0x1000, 1);
124                 fio->Fclose();
125         }
126         memcpy(kanji + 0x7f * 16, ANKFONT7f_af, sizeof(ANKFONT7f_af));
127         memcpy(kanji + 0xe0 * 16, ANKFONTe0_ff, sizeof(ANKFONTe0_ff));
128         
129         // kanji (16x16)
130         if(fio->Fopen(emu->bios_path(_T("KANJI.ROM")), FILEIO_READ_BINARY)) {
131                 fio->Fread(kanji + 0x1000, 0x4ac00, 1);
132                 fio->Fclose();
133         } else if(fio->Fopen(emu->bios_path(_T("FNT1616.X1")), FILEIO_READ_BINARY)) {
134                 // xmillenium rom
135                 fio->Fread(kanji + 0x1000, 0x4ac00, 1);
136                 fio->Fclose();
137         }
138         for(int ofs = 0x1000; ofs < 0x4bc00; ofs += 32) {
139                 // LRLR.. -> LL..RR..
140                 uint8 buf[32];
141                 for(int i = 0; i < 16; i++) {
142                         buf[i     ] = kanji[ofs + i * 2    ];
143                         buf[i + 16] = kanji[ofs + i * 2 + 1];
144                 }
145                 memcpy(kanji + ofs, buf, 32);
146         }
147         delete fio;
148         
149         // create pc palette
150         for(int i = 0; i < 8; i++) {
151                 palette_pc[i    ] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0); // text
152                 palette_pc[i + 8] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0); // cg
153         }
154         
155         // initialize regs
156         pal[0] = 0xaa;
157         pal[1] = 0xcc;
158         pal[2] = 0xf0;
159         priority = 0;
160         update_pal();
161         column40 = true;
162         
163         memset(vram_t, 0, sizeof(vram_t));
164         memset(vram_a, 0, sizeof(vram_a));
165 #ifdef _X1TURBO_FEATURE
166         memset(vram_k, 0, sizeof(vram_k));
167 #endif
168         memset(pcg_b, 0, sizeof(pcg_b));
169         memset(pcg_r, 0, sizeof(pcg_r));
170         memset(pcg_g, 0, sizeof(pcg_g));
171 #ifdef _X1TURBO_FEATURE
172         memset(gaiji_b, 0, sizeof(gaiji_b));
173         memset(gaiji_r, 0, sizeof(gaiji_r));
174         memset(gaiji_g, 0, sizeof(gaiji_g));
175 #endif
176         memset((void *)text_bak, (void *)0x00, sizeof(text_bak)); 
177         memset((void *)cg_bak,   (void *)0x00, sizeof(cg_bak)); 
178         
179         // register event
180         register_frame_event(this);
181         register_vline_event(this);
182 }
183
184 void DISPLAY::reset()
185 {
186 #ifdef _X1TURBO_FEATURE
187         mode1 = 0;//3;
188         mode2 = 0;
189         hireso = true;
190 #endif
191 #ifdef _X1TURBOZ
192         for(int i = 0; i < 8; i++) {
193                 palette_pc[i    ] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0); // text
194                 ztpal[i] = ((i & 1) ? 0x03 : 0) | ((i & 2) ? 3 : 0x0c) | ((i & 4) ? 0x30 : 0);
195         }
196         for(int g = 0; g < 16; g++) {
197                 for(int r = 0; r < 16; r++) {
198                         for(int b = 0; b < 16; b++) {
199                                 int num = b + r * 16 + g * 256;
200                                 zpal[num].b = b;
201                                 zpal[num].r = r;
202                                 zpal[num].g = g;
203                                 palette_pc[num + 16] = RGB_COLOR((r * 255) / 15, (g * 255) / 15, (b * 255) / 15);
204                         }
205                 }
206         }
207         zmode1 = zpriority = zscroll = zmode2 = 0;
208         zpal_num = 0;
209 #endif
210         cur_line = cur_code = 0;
211         vblank_clock = 0;
212         
213         kaddr = kofs = kflag = 0;
214         kanji_ptr = &kanji[0];
215 }
216
217
218 void DISPLAY::write_io8(uint32 addr, uint32 data)
219 {
220         switch(addr & 0xff00) {
221         case 0x0e00:
222                 write_kanji(addr, data);
223                 break;
224         case 0x1000:
225 #ifdef _X1TURBOZ
226                 if(AEN && APEN && !APRD) {
227                         int num = ((data >> 4) & 0x0f) | ((addr << 4) & 0xff0);
228                         zpal[num].b = data & 0x0f;
229                         palette_pc[num + 16] = RGB_COLOR((zpal[num].r * 255) / 15, (zpal[num].g * 255) / 15, (zpal[num].b * 255) / 15);
230                 } else if(AEN && APEN && APRD) {
231                         zpal_num = ((data >> 4) & 0x0f) | ((addr << 4) & 0xff0);
232                 } else if(!AEN) {
233 #endif
234                         pal[0] = data;
235                         update_pal();
236 #ifdef _X1TURBOZ
237                 }
238 #endif
239                 break;
240         case 0x1100:
241 #ifdef _X1TURBOZ
242                 if(AEN && APEN && !APRD) {
243                         int num = ((data >> 4) & 0x0f) | ((addr << 4) & 0xff0);
244                         zpal[num].r = data & 0x0f;
245                         palette_pc[num + 16] = RGB_COLOR((zpal[num].r * 255) / 15, (zpal[num].g * 255) / 15, (zpal[num].b * 255) / 15);
246 //              } else if(AEN && APEN && APRD) {
247 //                      zpal_num = ((data >> 4) & 0x0f) | ((addr << 4) & 0xff0);
248                 } else if(!AEN) {
249 #endif
250                         pal[1] = data;
251                         update_pal();
252 #ifdef _X1TURBOZ
253                 }
254 #endif
255                 break;
256         case 0x1200:
257 #ifdef _X1TURBOZ
258                 if(AEN && APEN && !APRD) {
259                         int num = ((data >> 4) & 0x0f) | ((addr << 4) & 0xff0);
260                         zpal[num].g = data & 0x0f;
261                         palette_pc[num + 16] = RGB_COLOR((zpal[num].r * 255) / 15, (zpal[num].g * 255) / 15, (zpal[num].b * 255) / 15);
262 //              } else if(AEN && APEN && APRD) {
263 //                      zpal_num = ((data >> 4) & 0x0f) | ((addr << 4) & 0xff0);
264                 } else if(!AEN) {
265 #endif
266                         pal[2] = data;
267                         update_pal();
268 #ifdef _X1TURBOZ
269                 }
270 #endif
271                 break;
272         case 0x1300:
273                 priority = data;
274                 update_pal();
275                 break;
276         case 0x1500:
277                 get_cur_pcg(addr);
278                 pcg_b[cur_code][cur_line] = data;
279 #ifdef _X1TURBO_FEATURE
280                 gaiji_b[cur_code >> 1][(cur_line << 1) | (cur_code & 1)] = data;
281 #endif
282                 break;
283         case 0x1600:
284                 get_cur_pcg(addr);
285                 pcg_r[cur_code][cur_line] = data;
286 #ifdef _X1TURBO_FEATURE
287                 gaiji_r[cur_code >> 1][(cur_line << 1) | (cur_code & 1)] = data;
288 #endif
289                 break;
290         case 0x1700:
291                 get_cur_pcg(addr);
292                 pcg_g[cur_code][cur_line] = data;
293 #ifdef _X1TURBO_FEATURE
294                 gaiji_g[cur_code >> 1][(cur_line << 1) | (cur_code & 1)] = data;
295 #endif
296                 break;
297 #ifdef _X1TURBO_FEATURE
298         case 0x1f00:
299                 switch(addr) {
300 #ifdef _X1TURBOZ
301                 case 0x1fb0:
302                         zmode1 = data;
303                         break;
304                 case 0x1fb1:
305                 case 0x1fb2:
306                 case 0x1fb3:
307                 case 0x1fb4:
308                 case 0x1fb5:
309                 case 0x1fb6:
310                 case 0x1fb7:
311                         ztpal[addr & 7] = data;
312                         palette_pc[addr & 7] = RGB_COLOR((((data >> 2) & 3) * 255) / 3, (((data >> 4) & 3) * 255) / 3, (((data >> 0) & 3) * 255) / 3);
313                         break;
314                 case 0x1fc0:
315                         zpriority = data;
316                         break;
317                 case 0x1fc4:
318                         zscroll = data;
319                         break;
320                 case 0x1fc5:
321                         zmode2 = data;
322                         break;
323 #endif
324                 case 0x1fd0:
325 //                      if((mode1 & 1) != (data & 1)) {
326                                 d_crtc->set_horiz_freq((data & 1) ? 24860 : 15980);
327 //                      }
328                         mode1 = data;
329 //                      hireso = !((mode1 & 3) == 0 || (mode1 & 3) == 2);
330                         break;
331                 case 0x1fe0:
332                         mode2 = data;
333                         update_pal();
334                         break;
335                 }
336                 break;
337 #endif
338         case 0x2000:
339         case 0x2100:
340         case 0x2200:
341         case 0x2300:
342         case 0x2400:
343         case 0x2500:
344         case 0x2600:
345         case 0x2700:
346                 vram_a[addr & 0x7ff] = data;
347                 break;
348         case 0x2800:
349         case 0x2900:
350         case 0x2a00:
351         case 0x2b00:
352         case 0x2c00:
353         case 0x2d00:
354         case 0x2e00:
355         case 0x2f00:
356                 vram_a[addr & 0x7ff] = data; // mirror
357                 break;
358         case 0x3000:
359         case 0x3100:
360         case 0x3200:
361         case 0x3300:
362         case 0x3400:
363         case 0x3500:
364         case 0x3600:
365         case 0x3700:
366                 vram_t[addr & 0x7ff] = data;
367                 break;
368         case 0x3800:
369         case 0x3900:
370         case 0x3a00:
371         case 0x3b00:
372         case 0x3c00:
373         case 0x3d00:
374         case 0x3e00:
375         case 0x3f00:
376 #ifdef _X1TURBO_FEATURE
377                 vram_k[addr & 0x7ff] = data;
378 #else
379                 vram_t[addr & 0x7ff] = data; // mirror
380 #endif
381                 break;
382         }
383 }
384
385 uint32 DISPLAY::read_io8(uint32 addr)
386 {
387         switch(addr & 0xff00) {
388         case 0x0e00:
389                 return read_kanji(addr);
390 #ifdef _X1TURBOZ
391         case 0x1000:
392                 if(AEN && APEN && APRD) {
393                         return zpal[zpal_num].b;
394                 }
395                 break;
396         case 0x1100:
397                 if(AEN && APEN && APRD) {
398                         return zpal[zpal_num].r;
399                 }
400                 break;
401         case 0x1200:
402                 if(AEN && APEN && APRD) {
403                         return zpal[zpal_num].g;
404                 }
405                 break;
406 #endif
407 //      case 0x1300:
408 //              return priority;
409         case 0x1400:
410                 return get_cur_font(addr);
411         case 0x1500:
412                 get_cur_pcg(addr);
413                 return pcg_b[cur_code][cur_line];
414         case 0x1600:
415                 get_cur_pcg(addr);
416                 return pcg_r[cur_code][cur_line];
417         case 0x1700:
418                 get_cur_pcg(addr);
419                 return pcg_g[cur_code][cur_line];
420 #ifdef _X1TURBOZ
421         case 0x1f00:
422                 switch(addr) {
423                 case 0x1fb0:
424                         return zmode1;
425                 case 0x1fb1:
426                 case 0x1fb2:
427                 case 0x1fb3:
428                 case 0x1fb4:
429                 case 0x1fb5:
430                 case 0x1fb6:
431                 case 0x1fb7:
432                         return ztpal[addr & 7];
433                 case 0x1fc0:
434                         return zpriority;
435                 case 0x1fc4:
436                         return zscroll;
437                 case 0x1fc5:
438                         return zmode2;
439                 case 0x1fd0:
440                         return mode1;
441                 case 0x1fe0:
442                         return mode2;
443                 }
444                 break;
445 #endif
446         case 0x2000:
447         case 0x2100:
448         case 0x2200:
449         case 0x2300:
450         case 0x2400:
451         case 0x2500:
452         case 0x2600:
453         case 0x2700:
454                 return vram_a[addr & 0x7ff];
455         case 0x2800:
456         case 0x2900:
457         case 0x2a00:
458         case 0x2b00:
459         case 0x2c00:
460         case 0x2d00:
461         case 0x2e00:
462         case 0x2f00:
463                 return vram_a[addr & 0x7ff]; // mirror
464         case 0x3000:
465         case 0x3100:
466         case 0x3200:
467         case 0x3300:
468         case 0x3400:
469         case 0x3500:
470         case 0x3600:
471         case 0x3700:
472                 return vram_t[addr & 0x7ff];
473         case 0x3800:
474         case 0x3900:
475         case 0x3a00:
476         case 0x3b00:
477         case 0x3c00:
478         case 0x3d00:
479         case 0x3e00:
480         case 0x3f00:
481 #ifdef _X1TURBO_FEATURE
482                 return vram_k[addr & 0x7ff];
483 #else
484                 return vram_t[addr & 0x7ff]; // mirror
485 #endif
486         }
487         return 0xff;
488 }
489
490 void DISPLAY::write_signal(int id, uint32 data, uint32 mask)
491 {
492         if(id == SIG_DISPLAY_VBLANK) {
493                 if(!(data & mask)) {
494                         // enter vblank
495                         vblank_clock = current_clock();
496                 }
497         } else if(id == SIG_DISPLAY_COLUMN40) {
498                 column40 = ((data & mask) != 0);
499         } else if(id == SIG_DISPLAY_DETECT_VBLANK) {
500                 // hack: cpu detects vblank
501                 vblank_clock = current_clock();
502         }
503 }
504
505 void DISPLAY::event_frame()
506 {
507         cblink = (cblink + 1) & 0x3f;
508         
509         // update crtc parameters
510         ch_height = (regs[9] & 0x1f) + 1;
511         hz_total = regs[0] + 1;
512         hz_disp = regs[1];
513         vt_disp = regs[6] & 0x7f;
514         st_addr = (regs[12] << 8) | regs[13];
515         
516 #ifdef _X1TURBO_FEATURE
517         int vt_total = ((regs[4] & 0x7f) + 1) * ch_height + (regs[5] & 0x1f);
518         hireso = (vt_total > 400);
519 #endif
520 }
521
522 void DISPLAY::event_vline(int v, int clock)
523 {
524 #ifdef _X1TURBO_FEATURE
525         if(hireso) {
526                 if(v < 400) {
527                         draw_line(v);
528                 }
529         } else {
530 #endif
531                 if(v < 200) {
532                         draw_line(v);
533                 }
534 #ifdef _X1TURBO_FEATURE
535         }
536         // restart cpu after pcg/cgrom is accessed
537         d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 0);
538 #endif
539 #ifdef _X1TURBO_FEATURE
540         if(hireso) {
541                 if(v == 400) {
542                         memcpy((void *)text_bak, (void *)text, sizeof(text)); 
543                         memcpy((void *)cg_bak,   (void *)cg, sizeof(cg)); 
544                 }
545         } else {
546 #endif
547                 if(v == 200) {
548                         memcpy((void *)text_bak, (void *)text, sizeof(text)); 
549                         memcpy((void *)cg_bak,   (void *)cg, sizeof(cg)); 
550                 }
551 #ifdef _X1TURBO_FEATURE
552         }
553 #endif
554         
555 }
556
557 void DISPLAY::update_pal()
558 {
559         uint8 pal2[8];
560         for(int i = 0; i < 8; i++) {
561                 uint8 bit = 1 << i;
562                 pal2[i] = ((pal[0] & bit) ? 1 : 0) | ((pal[1] & bit) ? 2 : 0) | ((pal[2] & bit) ? 4 : 0) | 8;
563         }
564 #ifdef _X1TURBO_FEATURE
565         if(mode2 & 0x10) pal2[0] = 8;
566         if(mode2 & 0x20) pal2[1] = 8;
567 #endif
568         for(int c = 0; c < 8; c++) {
569                 for(int t = 0; t < 8; t++) {
570                         if(priority & (1 << c)) {
571                                 pri[c][t] = pal2[c];
572                         } else if(t) {
573 #ifdef _X1TURBO_FEATURE
574                                 pri[c][t] = ((mode2 & 8) && (mode2 & 7) == t) ? 0 : t;
575 #else
576                                 pri[c][t] = t;
577 #endif
578                         } else {
579                                 pri[c][t] = pal2[c];
580                         }
581                 }
582         }
583 }
584
585 uint8 DISPLAY::get_cur_font(uint32 addr)
586 {
587 #ifdef _X1TURBO_FEATURE
588         if(mode1 & 0x20) {
589                 // wait next raster
590                 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
591                 
592                 // from X1EMU
593                 uint16 vaddr;
594                 if(!(vram_a[0x7ff] & 0x20)) {
595                         vaddr = 0x7ff;
596                 } else if(!(vram_a[0x3ff] & 0x20)) {
597                         vaddr = 0x3ff;
598                 } else if(!(vram_a[0x5ff] & 0x20)) {
599                         vaddr = 0x5ff;
600                 } else if(!(vram_a[0x1ff] & 0x20)) {
601                         vaddr = 0x1ff;
602                 } else {
603                         vaddr = 0x3ff;
604                 }
605                 uint16 ank = vram_t[vaddr];
606                 uint16 knj = vram_k[vaddr];
607                 
608                 if(knj & 0x80) {
609                         uint32 ofs = adr2knj_x1t((knj << 8) | ank);
610                         if(knj & 0x40) {
611                                 ofs += 16; // right
612                         }
613                         return kanji[ofs | (addr & 15)];
614                 } else if(mode1 & 0x40) {
615                         return kanji[(ank << 4) | (addr & 15)];
616                 } else {
617                         return font[(ank << 3) | ((addr >> 1) & 7)];
618                 }
619         }
620 #endif
621         get_cur_code_line();
622         return font[(cur_code << 3) | (cur_line & 7)];
623 }
624
625 void DISPLAY::get_cur_pcg(uint32 addr)
626 {
627 #ifdef _X1TURBO_FEATURE
628         if(mode1 & 0x20) {
629                 // wait next raster
630                 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
631                 
632                 // from X1EMU
633                 uint16 vaddr;
634                 if(vram_a[0x7ff] & 0x20) {
635                         vaddr = 0x7ff;
636                 } else if(vram_a[0x3ff] & 0x20) {
637                         vaddr = 0x3ff;
638                 } else if(vram_a[0x5ff] & 0x20) {
639                         vaddr = 0x5ff;
640                 } else if(vram_a[0x1ff] & 0x20) {
641                         vaddr = 0x1ff;
642                 } else {
643                         vaddr = 0x3ff;
644                 }
645                 cur_code = vram_t[vaddr];
646                 cur_line = (addr >> 1) & 7;
647                 
648                 if(vram_k[vaddr] & 0x90) {
649                         cur_code &= 0xfe;
650                         cur_code += addr & 1;
651                 }
652         } else
653 #endif
654         get_cur_code_line();
655 }
656
657 void DISPLAY::get_cur_code_line()
658 {
659 //#ifdef _X1TURBO_FEATURE
660 //      int ht_clock = hireso ? 161 : 250;
661 //#else
662         #define ht_clock 250
663 //#endif
664         int clock = passed_clock(vblank_clock);
665         int vt_line = vt_disp * ch_height + (int)(clock / ht_clock);
666         
667         int addr = (hz_total * (clock % ht_clock)) / ht_clock;
668         addr += hz_disp * (int)(vt_line / ch_height);
669         if(addr > 0x7ff) {
670                 addr = 0x7ff;
671         }
672         addr += st_addr;
673         
674         cur_code = vram_t[addr & 0x7ff];
675         cur_line = (vt_line % ch_height) & 7;
676 }
677
678 void DISPLAY::draw_line(int v)
679 {
680         if(v == 0) {
681                 memset(text, 0, sizeof(text));
682                 memset(cg, 0, sizeof(cg));
683                 prev_vert_double = false;
684                 raster = 0;
685         }
686         if((regs[8] & 0x30) != 0x30) {
687                 if((v % ch_height) == 0) {
688                         draw_text(v / ch_height);
689                 }
690                 draw_cg(v);
691                 memcpy(&pri_line[v][0][0], &pri[0][0], sizeof(pri));
692         } else {
693                 memset(&pri_line[v][0][0], 0, sizeof(pri));
694         }
695 }
696
697 void DISPLAY::draw_screen()
698 {
699         // copy to real screen
700 #ifdef _X1TURBO_FEATURE
701         if(hireso) {
702                 // 400 lines
703                 if(column40) {
704                         // 40 columns
705                         for(int y = 0; y < 400; y++) {
706                                 scrntype* dest = emu->screen_buffer(y);
707                                 uint8* src_text = text_bak[y];
708                                 uint8* src_cg = cg_bak[y];
709                                 
710                                 for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {
711                                         dest[x2] = dest[x2 + 1] = palette_pc[pri_line[y][src_cg[x]][src_text[x]]];
712                                 }
713                         }
714                 } else {
715                         // 80 columns
716                         for(int y = 0; y < 400; y++) {
717                                 scrntype* dest = emu->screen_buffer(y);
718                                 uint8* src_text = text_bak[y];
719                                 uint8* src_cg = cg_bak[y];
720                                 
721                                 for(int x = 0; x < 640; x++) {
722                                         dest[x] = palette_pc[pri_line[y][src_cg[x]][src_text[x]]];
723                                 }
724                         }
725                 }
726                 emu->screen_skip_line(false);
727         } else {
728 #endif
729                 // 200 lines
730                 if(column40) {
731                         // 40 columns
732                         for(int y = 0; y < 200; y++) {
733                                 scrntype* dest0 = emu->screen_buffer(y * 2 + 0);
734                                 scrntype* dest1 = emu->screen_buffer(y * 2 + 1);
735                                 uint8* src_text = text_bak[y];
736                                 uint8* src_cg = cg_bak[y];
737                                 
738                                 for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {
739                                         dest0[x2] = dest0[x2 + 1] = palette_pc[pri_line[y][src_cg[x]][src_text[x]]];
740                                 }
741                                 if(!config.scan_line) {
742                                         memcpy(dest1, dest0, 640 * sizeof(scrntype));
743                                 } else {
744                                         memset(dest1, 0, 640 * sizeof(scrntype));
745                                 }
746                         }
747                 } else {
748                         // 80 columns
749                         for(int y = 0; y < 200; y++) {
750                                 scrntype* dest0 = emu->screen_buffer(y * 2 + 0);
751                                 scrntype* dest1 = emu->screen_buffer(y * 2 + 1);
752                                 uint8* src_text = text_bak[y];
753                                 uint8* src_cg = cg_bak[y];
754                                 
755                                 for(int x = 0; x < 640; x++) {
756                                         dest0[x] = palette_pc[pri_line[y][src_cg[x]][src_text[x]]];
757                                 }
758                                 if(!config.scan_line) {
759                                         memcpy(dest1, dest0, 640 * sizeof(scrntype));
760                                 } else {
761                                         memset(dest1, 0, 640 * sizeof(scrntype));
762                                 }
763                         }
764                 }
765                 emu->screen_skip_line(true);
766 #ifdef _X1TURBO_FEATURE
767         }
768 #endif
769 }
770
771 void DISPLAY::draw_text(int y)
772 {
773         int width = column40 ? 40 : 80;
774         uint16 src = st_addr + hz_disp * y;
775         
776         bool cur_vert_double = true;
777         uint8 prev_attr = 0, prev_pattern_b[32], prev_pattern_r[32], prev_pattern_g[32];
778         
779         for(int x = 0; x < hz_disp && x < width; x++) {
780                 src &= 0x7ff;
781                 uint8 code = vram_t[src];
782 #ifdef _X1TURBO_FEATURE
783                 uint8 knj = vram_k[src];
784 #endif
785                 uint8 attr = vram_a[src];
786                 src++;
787                 
788                 uint8 col = attr & 7;
789                 bool reverse = ((attr & 8) != 0);
790                 bool blink = ((attr & 0x10) && (cblink & 0x20));
791                 reverse = (reverse != blink);
792                 
793                 // select pcg or ank
794                 const uint8 *pattern_b, *pattern_r, *pattern_g;
795 #ifdef _X1TURBO_FEATURE
796                 int shift = 0;
797                 int max_line = 8;
798 #else
799                 #define max_line 8
800 #endif
801                 if(attr & 0x20) {
802                         // pcg
803 #ifdef _X1TURBO_FEATURE
804                         if(knj & 0x90) {
805                                 pattern_b = gaiji_b[code >> 1];
806                                 pattern_r = gaiji_r[code >> 1];
807                                 pattern_g = gaiji_g[code >> 1];
808                                 max_line = 16;
809                         } else {
810 #endif
811                                 pattern_b = pcg_b[code];
812                                 pattern_r = pcg_r[code];
813                                 pattern_g = pcg_g[code];
814 #ifdef _X1TURBO_FEATURE
815                                 shift = hireso ? 1 : 0;
816                         }
817 #endif
818 #ifdef _X1TURBO_FEATURE
819                 } else if(knj & 0x80) {
820                         uint32 ofs = adr2knj_x1t((knj << 8) | code);
821                         if(knj & 0x40) {
822                                 ofs += 16; // right
823                         }
824                         pattern_b = pattern_r = pattern_g = &kanji[ofs];
825                         shift = hireso ? ((ch_height >= 32) ? 1 : 0) : ((ch_height >= 16) ? 0 : -1);
826                         max_line = 16;
827                 } else if(hireso || (mode1 & 4)) {
828                         // ank 8x16 or kanji
829                         pattern_b = pattern_r = pattern_g = &kanji[code << 4];
830                         shift = hireso ? ((ch_height >= 32) ? 1 : 0) : ((ch_height >= 16) ? 0 : -1);
831                         max_line = 16;
832 #endif
833                 } else {
834                         // ank 8x8
835                         pattern_b = pattern_r = pattern_g = &font[code << 3];
836                 }
837                 
838                 // check vertical doubled char
839                 if(!(attr & 0x40)) {
840                         cur_vert_double = false;
841                 }
842                 
843                 // render character
844                 for(int l = 0; l < ch_height; l++) {
845                         uint8 b, r, g;
846                         int line = cur_vert_double ? raster + (l >> 1) : l;
847 #ifdef _X1TURBO_FEATURE
848                         if(shift == 1) {
849                                 line >>= 1;
850                         } else if(shift == -1) {
851                                 line <<= 1;
852                                 if(cur_vert_double) {
853                                         line |= l & 1;
854                                 }
855                         }
856 #endif
857                         if((x & 1) && (prev_attr & 0x80)) {
858                                 b = prev_pattern_b[line] << 4;
859                                 r = prev_pattern_r[line] << 4;
860                                 g = prev_pattern_g[line] << 4;
861                         } else if(line >= max_line) {
862                                 b = prev_pattern_b[line] = 0;
863                                 r = prev_pattern_r[line] = 0;
864                                 g = prev_pattern_g[line] = 0;
865                         } else {
866                                 b = prev_pattern_b[line] = pattern_b[line];
867                                 r = prev_pattern_r[line] = pattern_r[line];
868                                 g = prev_pattern_g[line] = pattern_g[line];
869                         }
870                         if(reverse) {
871                                 b = (!(col & 1)) ? 0xff : ~b;
872                                 r = (!(col & 2)) ? 0xff : ~r;
873                                 g = (!(col & 4)) ? 0xff : ~g;
874                         } else {
875                                 b = (!(col & 1)) ? 0 : b;
876                                 r = (!(col & 2)) ? 0 : r;
877                                 g = (!(col & 4)) ? 0 : g;
878                         }
879                         
880                         int yy = y * ch_height + l;
881 #ifdef _X1TURBO_FEATURE
882                         if(yy >= 400) {
883 #else
884                         if(yy >= 200) {
885 #endif
886                                 break;
887                         }
888                         uint8* d = &text[yy][x << 3];
889                         
890                         if(attr & 0x80) {
891                                 // horizontal doubled char
892                                 d[ 0] = d[ 1] = ((b & 0x80) >> 7) | ((r & 0x80) >> 6) | ((g & 0x80) >> 5);
893                                 d[ 2] = d[ 3] = ((b & 0x40) >> 6) | ((r & 0x40) >> 5) | ((g & 0x40) >> 4);
894                                 d[ 4] = d[ 5] = ((b & 0x20) >> 5) | ((r & 0x20) >> 4) | ((g & 0x20) >> 3);
895                                 d[ 6] = d[ 7] = ((b & 0x10) >> 4) | ((r & 0x10) >> 3) | ((g & 0x10) >> 2);
896                         } else {
897                                 d[0] = ((b & 0x80) >> 7) | ((r & 0x80) >> 6) | ((g & 0x80) >> 5);
898                                 d[1] = ((b & 0x40) >> 6) | ((r & 0x40) >> 5) | ((g & 0x40) >> 4);
899                                 d[2] = ((b & 0x20) >> 5) | ((r & 0x20) >> 4) | ((g & 0x20) >> 3);
900                                 d[3] = ((b & 0x10) >> 4) | ((r & 0x10) >> 3) | ((g & 0x10) >> 2);
901                                 d[4] = ((b & 0x08) >> 3) | ((r & 0x08) >> 2) | ((g & 0x08) >> 1);
902                                 d[5] = ((b & 0x04) >> 2) | ((r & 0x04) >> 1) | ((g & 0x04) >> 0);
903                                 d[6] = ((b & 0x02) >> 1) | ((r & 0x02) >> 0) | ((g & 0x02) << 1);
904                                 d[7] = ((b & 0x01) >> 0) | ((r & 0x01) << 1) | ((g & 0x01) << 2);
905                         }
906                 }
907                 prev_attr = attr;
908         }
909         if(cur_vert_double && !prev_vert_double) {
910                 prev_vert_double = true;
911                 raster = ch_height >> 1;
912         } else {
913                 prev_vert_double = false;
914                 raster = 0;
915         }
916 }
917
918 void DISPLAY::draw_cg(int line)
919 {
920         int width = column40 ? 40 : 80;
921         
922         int y = line / ch_height;
923         int l = line % ch_height;
924         if(y >= vt_disp) {
925                 return;
926         }
927         int ofs, src = st_addr + hz_disp * y;
928 #ifdef _X1TURBO_FEATURE
929         int page = (hireso && !(mode1 & 2)) ? (l & 1) : (mode1 & 8);
930         int ll = hireso ? (l >> 1) : l;
931         
932         if(mode1 & 4) {
933                 ofs = (0x400 * (ll & 15)) + (page ? 0xc000 : 0);
934         } else {
935                 ofs = (0x800 * (ll & 7)) + (page ? 0xc000 : 0);
936         }
937 #else
938         ofs = 0x800 * (l & 7);
939 #endif
940         int ofs_b = ofs + 0x0000;
941         int ofs_r = ofs + 0x4000;
942         int ofs_g = ofs + 0x8000;
943         
944         for(int x = 0; x < hz_disp && x < width; x++) {
945                 src &= 0x7ff;
946                 uint8 b = vram_ptr[ofs_b | src];
947                 uint8 r = vram_ptr[ofs_r | src];
948                 uint8 g = vram_ptr[ofs_g | src++];
949                 uint8* d = &cg[line][x << 3];
950                 
951                 d[0] = ((b & 0x80) >> 7) | ((r & 0x80) >> 6) | ((g & 0x80) >> 5);
952                 d[1] = ((b & 0x40) >> 6) | ((r & 0x40) >> 5) | ((g & 0x40) >> 4);
953                 d[2] = ((b & 0x20) >> 5) | ((r & 0x20) >> 4) | ((g & 0x20) >> 3);
954                 d[3] = ((b & 0x10) >> 4) | ((r & 0x10) >> 3) | ((g & 0x10) >> 2);
955                 d[4] = ((b & 0x08) >> 3) | ((r & 0x08) >> 2) | ((g & 0x08) >> 1);
956                 d[5] = ((b & 0x04) >> 2) | ((r & 0x04) >> 1) | ((g & 0x04) >> 0);
957                 d[6] = ((b & 0x02) >> 1) | ((r & 0x02) >> 0) | ((g & 0x02) << 1);
958                 d[7] = ((b & 0x01) >> 0) | ((r & 0x01) << 1) | ((g & 0x01) << 2);
959         }
960 }
961
962 // kanji rom (from X1EMU by KM)
963
964 void DISPLAY::write_kanji(uint32 addr, uint32 data)
965 {
966         switch(addr) {
967         case 0xe80:
968                 kaddr = (kaddr & 0xff00) | data;
969                 break;
970         case 0xe81:
971                 kaddr = (kaddr & 0xff) | (data << 8);
972                 break;
973         case 0xe82:
974                 // TODO: bit0 L->H: Latch
975                 kanji_ptr = &kanji[adr2knj_x1(kaddr & 0xfff0)];
976                 break;
977         }
978 }
979
980 uint32 DISPLAY::read_kanji(uint32 addr)
981 {
982         switch(addr) {
983         case 0xe80:
984                 if(kaddr & 0xff00) {
985                         uint32 val = kanji_ptr[kofs];
986                         kflag |= 1;
987                         if(kflag == 3) {
988                                 kofs = (kofs + 1) & 15;
989                                 kflag = 0;
990                         }
991                         return val;
992                 }
993                 return jis2adr_x1(kaddr << 8) >> 8;
994         case 0xe81:
995                 if(kaddr & 0xff00) {
996                         uint32 val = kanji_ptr[kofs + 16];
997                         kflag |= 2;
998                         if(kflag == 3) {
999                                 kofs = (kofs + 1) & 15;
1000                                 kflag = 0;
1001                         }
1002                         return val;
1003                 }
1004                 return 0;
1005         }
1006         return 0xff;
1007 }
1008
1009 uint16 DISPLAY::jis2adr_x1(uint16 jis)
1010 {
1011         uint16 jh, jl, adr;
1012         
1013         jh = jis >> 8;
1014         jl = jis & 0xff;
1015         if(jh > 0x28) {
1016                 adr = 0x4000 + (jh - 0x30) * 0x600;
1017         } else {
1018                 adr = 0x0100 + (jh - 0x21) * 0x600;
1019         }
1020         if(jl >= 0x20) {
1021                 adr += (jl - 0x20) * 0x10;
1022         }
1023         return adr;
1024 }
1025
1026 uint32 DISPLAY::adr2knj_x1(uint16 adr)
1027 {
1028         uint16 jh, jl, jis;
1029         
1030         if(adr < 0x4000) {
1031                 jh = adr - 0x0100;
1032                 jh = 0x21 + jh / 0x600;
1033         } else {
1034                 jh = adr - 0x4000;
1035                 jh = 0x30 + jh / 0x600;
1036         }
1037         if(jh > 0x28) {
1038                 adr -= 0x4000 + (jh - 0x30) * 0x600;
1039         } else {
1040                 adr -= 0x0100 + (jh - 0x21) * 0x600;
1041         }
1042         jl = 0x20;
1043         if(adr) {
1044                 jl += adr / 0x10;
1045         }
1046         
1047         jis = (jh << 8) | jl;
1048         return jis2knj(jis);
1049 }
1050
1051 #ifdef _X1TURBO_FEATURE
1052 uint32 DISPLAY::adr2knj_x1t(uint16 adr)
1053 {
1054         uint16 j1, j2;
1055         uint16 rl, rh;
1056         uint16 jis;
1057         
1058         rh = adr >> 8;
1059         rl = adr & 0xff;
1060         
1061         rh &= 0x1f;
1062         if(!rl && !rh) {
1063                 return jis2knj(0);
1064         }
1065         j2 = rl & 0x1f;         // rl4,3,2,1,0
1066         j1 = (rl / 0x20) & 7;   // rl7,6,5
1067         
1068         if(rh < 0x04) {
1069                 // 2121-277e
1070                 j1 |= 0x20;
1071                 switch(rh & 3) {
1072                 case 0: j2 |= 0x20; break;
1073                 case 1: j2 |= 0x60; break;
1074                 case 2: j2 |= 0x40; break;
1075                 default: j1 = j2 = 0; break;
1076                 }
1077         } else if(rh > 0x1c) {
1078                 // 7021-777e
1079                 j1 |= 0x70;
1080                 switch(rh & 3) {
1081                 case 0: j2 |= 0x20; break;
1082                 case 1: j2 |= 0x60; break;
1083                 case 2: j2 |= 0x40; break;
1084                 default: j1 = j2 = 0; break;
1085                 }
1086         } else {
1087                 j1 |= (((rh >> 1) + 7) / 3) * 0x10;
1088                 j1 |= (rh & 1) * 8;
1089                 j2 |= ((((rh >> 1) + 1) % 3) + 1) * 0x20;
1090         }
1091         
1092         jis = (j1 << 8) | j2;
1093         return jis2knj(jis);
1094 }
1095 #endif
1096
1097 uint32 DISPLAY::jis2knj(uint16 jis)
1098 {
1099         uint32 sjis = jis2sjis(jis);
1100         
1101         if(sjis < 0x100) {
1102                 return sjis * 16;
1103         } else if(sjis >= 0x8140 && sjis < 0x84c0) {
1104                 return 0x01000 + (sjis - 0x8140) * 32;
1105         } else if(sjis >= 0x8890 && sjis < 0xa000) {
1106                 return 0x08000 + (sjis - 0x8890) * 32;
1107         } else if(sjis >= 0xe040 && sjis < 0xeab0) {
1108                 return 0x36e00 + (sjis - 0xe040) * 32;
1109         } else {
1110                 return 0;
1111         }
1112 }
1113
1114 uint16 DISPLAY::jis2sjis(uint16 jis)
1115 {
1116         uint16 c1, c2;
1117         
1118         if(!jis) {
1119                 return 0;
1120         }
1121         c1 = jis >> 8;
1122         c2 = jis & 0xff;
1123         
1124         if(c1 & 1) {
1125                 c2 += 0x1f;
1126                 if(c2 >= 0x7f) {
1127                         c2++;
1128                 }
1129         } else {
1130                 c2 += 0x7e;
1131         }
1132         c1 = (c1 - 0x20 - 1) / 2 + 0x81;
1133         if(c1 >= 0xa0) {
1134                 c1 += 0x40;
1135         }
1136         return (c1 << 8) | c2;
1137 }
1138
1139 #define STATE_VERSION   2
1140
1141 void DISPLAY::save_state(FILEIO* state_fio)
1142 {
1143         state_fio->FputUint32(STATE_VERSION);
1144         state_fio->FputInt32(this_device_id);
1145         
1146         state_fio->Fwrite(vram_t, sizeof(vram_t), 1);
1147         state_fio->Fwrite(vram_a, sizeof(vram_a), 1);
1148 #ifdef _X1TURBO_FEATURE
1149         state_fio->Fwrite(vram_k, sizeof(vram_k), 1);
1150 #endif
1151         state_fio->Fwrite(pcg_b, sizeof(pcg_b), 1);
1152         state_fio->Fwrite(pcg_r, sizeof(pcg_r), 1);
1153         state_fio->Fwrite(pcg_g, sizeof(pcg_g), 1);
1154 #ifdef _X1TURBO_FEATURE
1155         state_fio->Fwrite(gaiji_b, sizeof(gaiji_b), 1);
1156         state_fio->Fwrite(gaiji_r, sizeof(gaiji_r), 1);
1157         state_fio->Fwrite(gaiji_g, sizeof(gaiji_g), 1);
1158 #endif
1159         state_fio->FputUint8(cur_code);
1160         state_fio->FputUint8(cur_line);
1161         state_fio->FputInt32(kaddr);
1162         state_fio->FputInt32(kofs);
1163         state_fio->FputInt32(kflag);
1164         state_fio->FputInt32((int)(kanji_ptr - &kanji[0]));
1165         state_fio->Fwrite(pal, sizeof(pal), 1);
1166         state_fio->FputUint8(priority);
1167         state_fio->Fwrite(pri, sizeof(pri), 1);
1168         state_fio->FputBool(column40);
1169 #ifdef _X1TURBO_FEATURE
1170         state_fio->FputUint8(mode1);
1171         state_fio->FputUint8(mode2);
1172         state_fio->FputBool(hireso);
1173 #endif
1174 #ifdef _X1TURBOZ
1175         state_fio->FputUint8(zmode1);
1176         state_fio->FputUint8(zpriority);
1177         state_fio->FputUint8(zscroll);
1178         state_fio->FputUint8(zmode2);
1179         state_fio->Fwrite(ztpal, sizeof(ztpal), 1);
1180         state_fio->Fwrite(zpal, sizeof(zpal), 1);
1181         state_fio->FputInt32(zpal_num);
1182         state_fio->Fwrite(palette_pc, sizeof(palette_pc), 1);
1183 #endif
1184         state_fio->FputBool(prev_vert_double);
1185         state_fio->FputInt32(raster);
1186         state_fio->FputInt32(cblink);
1187         state_fio->FputInt32(ch_height);
1188         state_fio->FputInt32(hz_total);
1189         state_fio->FputInt32(hz_disp);
1190         state_fio->FputInt32(vt_disp);
1191         state_fio->FputInt32(st_addr);
1192         state_fio->FputUint32(vblank_clock);
1193 }
1194
1195 bool DISPLAY::load_state(FILEIO* state_fio)
1196 {
1197         if(state_fio->FgetUint32() != STATE_VERSION) {
1198                 return false;
1199         }
1200         if(state_fio->FgetInt32() != this_device_id) {
1201                 return false;
1202         }
1203         state_fio->Fread(vram_t, sizeof(vram_t), 1);
1204         state_fio->Fread(vram_a, sizeof(vram_a), 1);
1205 #ifdef _X1TURBO_FEATURE
1206         state_fio->Fread(vram_k, sizeof(vram_k), 1);
1207 #endif
1208         state_fio->Fread(pcg_b, sizeof(pcg_b), 1);
1209         state_fio->Fread(pcg_r, sizeof(pcg_r), 1);
1210         state_fio->Fread(pcg_g, sizeof(pcg_g), 1);
1211 #ifdef _X1TURBO_FEATURE
1212         state_fio->Fread(gaiji_b, sizeof(gaiji_b), 1);
1213         state_fio->Fread(gaiji_r, sizeof(gaiji_r), 1);
1214         state_fio->Fread(gaiji_g, sizeof(gaiji_g), 1);
1215 #endif
1216         cur_code = state_fio->FgetUint8();
1217         cur_line = state_fio->FgetUint8();
1218         kaddr = state_fio->FgetInt32();
1219         kofs = state_fio->FgetInt32();
1220         kflag = state_fio->FgetInt32();
1221         kanji_ptr = &kanji[0] + state_fio->FgetInt32();
1222         state_fio->Fread(pal, sizeof(pal), 1);
1223         priority = state_fio->FgetUint8();
1224         state_fio->Fread(pri, sizeof(pri), 1);
1225         column40 = state_fio->FgetBool();
1226 #ifdef _X1TURBO_FEATURE
1227         mode1 = state_fio->FgetUint8();
1228         mode2 = state_fio->FgetUint8();
1229         hireso = state_fio->FgetBool();
1230 #endif
1231 #ifdef _X1TURBOZ
1232         zmode1 = state_fio->FgetUint8();
1233         zpriority = state_fio->FgetUint8();
1234         zscroll = state_fio->FgetUint8();
1235         zmode2 = state_fio->FgetUint8();
1236         state_fio->Fread(ztpal, sizeof(ztpal), 1);
1237         state_fio->Fread(zpal, sizeof(zpal), 1);
1238         zpal_num = state_fio->FgetInt32();
1239         state_fio->Fread(palette_pc, sizeof(palette_pc), 1);
1240 #endif
1241         prev_vert_double = state_fio->FgetBool();
1242         raster = state_fio->FgetInt32();
1243         cblink = state_fio->FgetInt32();
1244         ch_height = state_fio->FgetInt32();
1245         hz_total = state_fio->FgetInt32();
1246         hz_disp = state_fio->FgetInt32();
1247         vt_disp = state_fio->FgetInt32();
1248         st_addr = state_fio->FgetInt32();
1249         vblank_clock = state_fio->FgetUint32();
1250         return true;
1251 }
1252