2 SHARP X1 Emulator 'eX1'
3 SHARP X1twin Emulator 'eX1twin'
4 SHARP X1turbo Emulator 'eX1turbo'
6 Origin : X1EMU by KM (kanji rom)
7 X-millenium by Yui (ank16 patch)
8 Author : Takeda.Toshiya
15 #ifdef _X1TURBO_FEATURE
16 #include "../hd46505.h"
21 #define AEN ((zmode1 & 0x80) != 0)
22 #define APEN ((zmode2 & 0x80) != 0)
23 #define APRD ((zmode2 & 0x08) != 0)
28 static const uint16 ANKFONT7f_af[0x21 * 8] = {
29 0x0000, 0x3000, 0x247f, 0x6c24, 0x484c, 0xce4b, 0x0000, 0x0000,
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,
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
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,
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
102 void DISPLAY::initialize()
105 FILEIO* fio = new FILEIO();
108 if(fio->Fopen(emu->bios_path(_T("ANK8.ROM")), FILEIO_READ_BINARY)) {
109 fio->Fread(font, sizeof(font), 1);
111 } else if(fio->Fopen(emu->bios_path(_T("FNT0808.X1")), FILEIO_READ_BINARY)) {
113 fio->Fread(font, sizeof(font), 1);
118 if(fio->Fopen(emu->bios_path(_T("ANK16.ROM")), FILEIO_READ_BINARY)) {
119 fio->Fread(kanji, 0x1000, 1);
121 } else if(fio->Fopen(emu->bios_path(_T("FNT0816.X1")), FILEIO_READ_BINARY)) {
123 fio->Fread(kanji, 0x1000, 1);
126 memcpy(kanji + 0x7f * 16, ANKFONT7f_af, sizeof(ANKFONT7f_af));
127 memcpy(kanji + 0xe0 * 16, ANKFONTe0_ff, sizeof(ANKFONTe0_ff));
130 if(fio->Fopen(emu->bios_path(_T("KANJI.ROM")), FILEIO_READ_BINARY)) {
131 fio->Fread(kanji + 0x1000, 0x4ac00, 1);
133 } else if(fio->Fopen(emu->bios_path(_T("FNT1616.X1")), FILEIO_READ_BINARY)) {
135 fio->Fread(kanji + 0x1000, 0x4ac00, 1);
138 for(int ofs = 0x1000; ofs < 0x4bc00; ofs += 32) {
139 // LRLR.. -> LL..RR..
141 for(int i = 0; i < 16; i++) {
142 buf[i ] = kanji[ofs + i * 2 ];
143 buf[i + 16] = kanji[ofs + i * 2 + 1];
145 memcpy(kanji + ofs, buf, 32);
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
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));
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));
176 memset((void *)text_bak, (void *)0x00, sizeof(text_bak));
177 memset((void *)cg_bak, (void *)0x00, sizeof(cg_bak));
180 register_frame_event(this);
181 register_vline_event(this);
184 void DISPLAY::reset()
186 #ifdef _X1TURBO_FEATURE
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);
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;
203 palette_pc[num + 16] = RGB_COLOR((r * 255) / 15, (g * 255) / 15, (b * 255) / 15);
207 zmode1 = zpriority = zscroll = zmode2 = 0;
210 cur_line = cur_code = 0;
213 kaddr = kofs = kflag = 0;
214 kanji_ptr = &kanji[0];
218 void DISPLAY::write_io8(uint32 addr, uint32 data)
220 switch(addr & 0xff00) {
222 write_kanji(addr, data);
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);
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);
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);
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;
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;
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;
297 #ifdef _X1TURBO_FEATURE
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);
325 // if((mode1 & 1) != (data & 1)) {
326 d_crtc->set_horiz_freq((data & 1) ? 24860 : 15980);
329 // hireso = !((mode1 & 3) == 0 || (mode1 & 3) == 2);
346 vram_a[addr & 0x7ff] = data;
356 vram_a[addr & 0x7ff] = data; // mirror
366 vram_t[addr & 0x7ff] = data;
376 #ifdef _X1TURBO_FEATURE
377 vram_k[addr & 0x7ff] = data;
379 vram_t[addr & 0x7ff] = data; // mirror
385 uint32 DISPLAY::read_io8(uint32 addr)
387 switch(addr & 0xff00) {
389 return read_kanji(addr);
392 if(AEN && APEN && APRD) {
393 return zpal[zpal_num].b;
397 if(AEN && APEN && APRD) {
398 return zpal[zpal_num].r;
402 if(AEN && APEN && APRD) {
403 return zpal[zpal_num].g;
410 return get_cur_font(addr);
413 return pcg_b[cur_code][cur_line];
416 return pcg_r[cur_code][cur_line];
419 return pcg_g[cur_code][cur_line];
432 return ztpal[addr & 7];
454 return vram_a[addr & 0x7ff];
463 return vram_a[addr & 0x7ff]; // mirror
472 return vram_t[addr & 0x7ff];
481 #ifdef _X1TURBO_FEATURE
482 return vram_k[addr & 0x7ff];
484 return vram_t[addr & 0x7ff]; // mirror
490 void DISPLAY::write_signal(int id, uint32 data, uint32 mask)
492 if(id == SIG_DISPLAY_VBLANK) {
495 vblank_clock = current_clock();
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();
505 void DISPLAY::event_frame()
507 cblink = (cblink + 1) & 0x3f;
509 // update crtc parameters
510 ch_height = (regs[9] & 0x1f) + 1;
511 hz_total = regs[0] + 1;
513 vt_disp = regs[6] & 0x7f;
514 st_addr = (regs[12] << 8) | regs[13];
516 #ifdef _X1TURBO_FEATURE
517 int vt_total = ((regs[4] & 0x7f) + 1) * ch_height + (regs[5] & 0x1f);
518 hireso = (vt_total > 400);
522 void DISPLAY::event_vline(int v, int clock)
524 #ifdef _X1TURBO_FEATURE
534 #ifdef _X1TURBO_FEATURE
536 // restart cpu after pcg/cgrom is accessed
537 d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 0);
539 #ifdef _X1TURBO_FEATURE
542 memcpy((void *)text_bak, (void *)text, sizeof(text));
543 memcpy((void *)cg_bak, (void *)cg, sizeof(cg));
548 memcpy((void *)text_bak, (void *)text, sizeof(text));
549 memcpy((void *)cg_bak, (void *)cg, sizeof(cg));
551 #ifdef _X1TURBO_FEATURE
557 void DISPLAY::update_pal()
560 for(int i = 0; i < 8; i++) {
562 pal2[i] = ((pal[0] & bit) ? 1 : 0) | ((pal[1] & bit) ? 2 : 0) | ((pal[2] & bit) ? 4 : 0) | 8;
564 #ifdef _X1TURBO_FEATURE
565 if(mode2 & 0x10) pal2[0] = 8;
566 if(mode2 & 0x20) pal2[1] = 8;
568 for(int c = 0; c < 8; c++) {
569 for(int t = 0; t < 8; t++) {
570 if(priority & (1 << c)) {
573 #ifdef _X1TURBO_FEATURE
574 pri[c][t] = ((mode2 & 8) && (mode2 & 7) == t) ? 0 : t;
585 uint8 DISPLAY::get_cur_font(uint32 addr)
587 #ifdef _X1TURBO_FEATURE
590 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
594 if(!(vram_a[0x7ff] & 0x20)) {
596 } else if(!(vram_a[0x3ff] & 0x20)) {
598 } else if(!(vram_a[0x5ff] & 0x20)) {
600 } else if(!(vram_a[0x1ff] & 0x20)) {
605 uint16 ank = vram_t[vaddr];
606 uint16 knj = vram_k[vaddr];
609 uint32 ofs = adr2knj_x1t((knj << 8) | ank);
613 return kanji[ofs | (addr & 15)];
614 } else if(mode1 & 0x40) {
615 return kanji[(ank << 4) | (addr & 15)];
617 return font[(ank << 3) | ((addr >> 1) & 7)];
622 return font[(cur_code << 3) | (cur_line & 7)];
625 void DISPLAY::get_cur_pcg(uint32 addr)
627 #ifdef _X1TURBO_FEATURE
630 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
634 if(vram_a[0x7ff] & 0x20) {
636 } else if(vram_a[0x3ff] & 0x20) {
638 } else if(vram_a[0x5ff] & 0x20) {
640 } else if(vram_a[0x1ff] & 0x20) {
645 cur_code = vram_t[vaddr];
646 cur_line = (addr >> 1) & 7;
648 if(vram_k[vaddr] & 0x90) {
650 cur_code += addr & 1;
657 void DISPLAY::get_cur_code_line()
659 //#ifdef _X1TURBO_FEATURE
660 // int ht_clock = hireso ? 161 : 250;
664 int clock = passed_clock(vblank_clock);
665 int vt_line = vt_disp * ch_height + (int)(clock / ht_clock);
667 int addr = (hz_total * (clock % ht_clock)) / ht_clock;
668 addr += hz_disp * (int)(vt_line / ch_height);
674 cur_code = vram_t[addr & 0x7ff];
675 cur_line = (vt_line % ch_height) & 7;
678 void DISPLAY::draw_line(int v)
681 memset(text, 0, sizeof(text));
682 memset(cg, 0, sizeof(cg));
683 prev_vert_double = false;
686 if((regs[8] & 0x30) != 0x30) {
687 if((v % ch_height) == 0) {
688 draw_text(v / ch_height);
691 memcpy(&pri_line[v][0][0], &pri[0][0], sizeof(pri));
693 memset(&pri_line[v][0][0], 0, sizeof(pri));
697 void DISPLAY::draw_screen()
699 // copy to real screen
700 #ifdef _X1TURBO_FEATURE
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];
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]]];
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];
721 for(int x = 0; x < 640; x++) {
722 dest[x] = palette_pc[pri_line[y][src_cg[x]][src_text[x]]];
726 emu->screen_skip_line(false);
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];
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]]];
741 if(!config.scan_line) {
742 memcpy(dest1, dest0, 640 * sizeof(scrntype));
744 memset(dest1, 0, 640 * sizeof(scrntype));
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];
755 for(int x = 0; x < 640; x++) {
756 dest0[x] = palette_pc[pri_line[y][src_cg[x]][src_text[x]]];
758 if(!config.scan_line) {
759 memcpy(dest1, dest0, 640 * sizeof(scrntype));
761 memset(dest1, 0, 640 * sizeof(scrntype));
765 emu->screen_skip_line(true);
766 #ifdef _X1TURBO_FEATURE
771 void DISPLAY::draw_text(int y)
773 int width = column40 ? 40 : 80;
774 uint16 src = st_addr + hz_disp * y;
776 bool cur_vert_double = true;
777 uint8 prev_attr = 0, prev_pattern_b[32], prev_pattern_r[32], prev_pattern_g[32];
779 for(int x = 0; x < hz_disp && x < width; x++) {
781 uint8 code = vram_t[src];
782 #ifdef _X1TURBO_FEATURE
783 uint8 knj = vram_k[src];
785 uint8 attr = vram_a[src];
788 uint8 col = attr & 7;
789 bool reverse = ((attr & 8) != 0);
790 bool blink = ((attr & 0x10) && (cblink & 0x20));
791 reverse = (reverse != blink);
794 const uint8 *pattern_b, *pattern_r, *pattern_g;
795 #ifdef _X1TURBO_FEATURE
803 #ifdef _X1TURBO_FEATURE
805 pattern_b = gaiji_b[code >> 1];
806 pattern_r = gaiji_r[code >> 1];
807 pattern_g = gaiji_g[code >> 1];
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;
818 #ifdef _X1TURBO_FEATURE
819 } else if(knj & 0x80) {
820 uint32 ofs = adr2knj_x1t((knj << 8) | code);
824 pattern_b = pattern_r = pattern_g = &kanji[ofs];
825 shift = hireso ? ((ch_height >= 32) ? 1 : 0) : ((ch_height >= 16) ? 0 : -1);
827 } else if(hireso || (mode1 & 4)) {
829 pattern_b = pattern_r = pattern_g = &kanji[code << 4];
830 shift = hireso ? ((ch_height >= 32) ? 1 : 0) : ((ch_height >= 16) ? 0 : -1);
835 pattern_b = pattern_r = pattern_g = &font[code << 3];
838 // check vertical doubled char
840 cur_vert_double = false;
844 for(int l = 0; l < ch_height; l++) {
846 int line = cur_vert_double ? raster + (l >> 1) : l;
847 #ifdef _X1TURBO_FEATURE
850 } else if(shift == -1) {
852 if(cur_vert_double) {
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;
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];
871 b = (!(col & 1)) ? 0xff : ~b;
872 r = (!(col & 2)) ? 0xff : ~r;
873 g = (!(col & 4)) ? 0xff : ~g;
875 b = (!(col & 1)) ? 0 : b;
876 r = (!(col & 2)) ? 0 : r;
877 g = (!(col & 4)) ? 0 : g;
880 int yy = y * ch_height + l;
881 #ifdef _X1TURBO_FEATURE
888 uint8* d = &text[yy][x << 3];
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);
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);
909 if(cur_vert_double && !prev_vert_double) {
910 prev_vert_double = true;
911 raster = ch_height >> 1;
913 prev_vert_double = false;
918 void DISPLAY::draw_cg(int line)
920 int width = column40 ? 40 : 80;
922 int y = line / ch_height;
923 int l = line % ch_height;
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;
933 ofs = (0x400 * (ll & 15)) + (page ? 0xc000 : 0);
935 ofs = (0x800 * (ll & 7)) + (page ? 0xc000 : 0);
938 ofs = 0x800 * (l & 7);
940 int ofs_b = ofs + 0x0000;
941 int ofs_r = ofs + 0x4000;
942 int ofs_g = ofs + 0x8000;
944 for(int x = 0; x < hz_disp && x < width; x++) {
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];
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);
962 // kanji rom (from X1EMU by KM)
964 void DISPLAY::write_kanji(uint32 addr, uint32 data)
968 kaddr = (kaddr & 0xff00) | data;
971 kaddr = (kaddr & 0xff) | (data << 8);
974 // TODO: bit0 L->H: Latch
975 kanji_ptr = &kanji[adr2knj_x1(kaddr & 0xfff0)];
980 uint32 DISPLAY::read_kanji(uint32 addr)
985 uint32 val = kanji_ptr[kofs];
988 kofs = (kofs + 1) & 15;
993 return jis2adr_x1(kaddr << 8) >> 8;
996 uint32 val = kanji_ptr[kofs + 16];
999 kofs = (kofs + 1) & 15;
1009 uint16 DISPLAY::jis2adr_x1(uint16 jis)
1016 adr = 0x4000 + (jh - 0x30) * 0x600;
1018 adr = 0x0100 + (jh - 0x21) * 0x600;
1021 adr += (jl - 0x20) * 0x10;
1026 uint32 DISPLAY::adr2knj_x1(uint16 adr)
1032 jh = 0x21 + jh / 0x600;
1035 jh = 0x30 + jh / 0x600;
1038 adr -= 0x4000 + (jh - 0x30) * 0x600;
1040 adr -= 0x0100 + (jh - 0x21) * 0x600;
1047 jis = (jh << 8) | jl;
1048 return jis2knj(jis);
1051 #ifdef _X1TURBO_FEATURE
1052 uint32 DISPLAY::adr2knj_x1t(uint16 adr)
1065 j2 = rl & 0x1f; // rl4,3,2,1,0
1066 j1 = (rl / 0x20) & 7; // rl7,6,5
1072 case 0: j2 |= 0x20; break;
1073 case 1: j2 |= 0x60; break;
1074 case 2: j2 |= 0x40; break;
1075 default: j1 = j2 = 0; break;
1077 } else if(rh > 0x1c) {
1081 case 0: j2 |= 0x20; break;
1082 case 1: j2 |= 0x60; break;
1083 case 2: j2 |= 0x40; break;
1084 default: j1 = j2 = 0; break;
1087 j1 |= (((rh >> 1) + 7) / 3) * 0x10;
1089 j2 |= ((((rh >> 1) + 1) % 3) + 1) * 0x20;
1092 jis = (j1 << 8) | j2;
1093 return jis2knj(jis);
1097 uint32 DISPLAY::jis2knj(uint16 jis)
1099 uint32 sjis = jis2sjis(jis);
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;
1114 uint16 DISPLAY::jis2sjis(uint16 jis)
1132 c1 = (c1 - 0x20 - 1) / 2 + 0x81;
1136 return (c1 << 8) | c2;
1139 #define STATE_VERSION 2
1141 void DISPLAY::save_state(FILEIO* state_fio)
1143 state_fio->FputUint32(STATE_VERSION);
1144 state_fio->FputInt32(this_device_id);
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);
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);
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);
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);
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);
1195 bool DISPLAY::load_state(FILEIO* state_fio)
1197 if(state_fio->FgetUint32() != STATE_VERSION) {
1200 if(state_fio->FgetInt32() != this_device_id) {
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);
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);
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();
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);
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();