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 #include "../hd46505.h"
19 #define AEN ((zmode1 & 0x80) != 0)
20 #define C64 ((zmode1 & 0x10) != 0)
21 #define APEN ((zmode2 & 0x80) != 0)
22 #define APRD ((zmode2 & 0x08) != 0)
25 void DISPLAY::initialize()
28 FILEIO* fio = new FILEIO();
31 if(fio->Fopen(create_local_path(_T("ANK8.ROM")), FILEIO_READ_BINARY)) {
32 fio->Fread(font, sizeof(font), 1);
34 } else if(fio->Fopen(create_local_path(_T("FNT0808.X1")), FILEIO_READ_BINARY)) {
36 fio->Fread(font, sizeof(font), 1);
41 if(fio->Fopen(create_local_path(_T("ANK16.ROM")), FILEIO_READ_BINARY)) {
42 fio->Fread(kanji, 0x1000, 1);
44 } else if(fio->Fopen(create_local_path(_T("FNT0816.X1")), FILEIO_READ_BINARY)) {
46 fio->Fread(kanji, 0x1000, 1);
49 memcpy(kanji + 0x7f * 16, ANKFONT7f_9f, sizeof(ANKFONT7f_9f));
50 memcpy(kanji + 0xe0 * 16, ANKFONTe0_ff, sizeof(ANKFONTe0_ff));
53 if(fio->Fopen(create_local_path(_T("KANJI.ROM")), FILEIO_READ_BINARY)) {
54 fio->Fread(kanji + 0x1000, 0x4ac00, 1);
56 } else if(fio->Fopen(create_local_path(_T("FNT1616.X1")), FILEIO_READ_BINARY)) {
58 fio->Fread(kanji + 0x1000, 0x4ac00, 1);
61 for(int ofs = 0x1000; ofs < 0x4bc00; ofs += 32) {
64 for(int i = 0; i < 16; i++) {
65 buf[i ] = kanji[ofs + i * 2 ];
66 buf[i + 16] = kanji[ofs + i * 2 + 1];
68 memcpy(kanji + ofs, buf, 32);
73 for(int i = 0; i < 8; i++) {
74 palette_pc[i ] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0); // text
75 palette_pc[i + 8] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0); // cg
78 for(int i = 0; i < 8; i++) {
79 ztpal[i] = ((i & 1) ? 0x03 : 0) | ((i & 2) ? 0x0c : 0) | ((i & 4) ? 0x30 : 0);
80 zpalette_pc[i ] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0); // text
81 zpalette_pc[i + 8] = RGB_COLOR((i & 2) ? 255 : 0, (i & 4) ? 255 : 0, (i & 1) ? 255 : 0); // digital
83 for(int g = 0; g < 16; g++) {
84 for(int r = 0; r < 16; r++) {
85 for(int b = 0; b < 16; b++) {
86 int num = b + r * 16 + g * 256;
90 zpalette_pc[num + 16] = RGB_COLOR((r * 255) / 15, (g * 255) / 15, (b * 255) / 15);
104 memset(vram_t, 0, sizeof(vram_t));
105 memset(vram_a, 0, sizeof(vram_a));
106 #ifdef _X1TURBO_FEATURE
107 memset(vram_k, 0, sizeof(vram_k));
109 memset(pcg_b, 0, sizeof(pcg_b));
110 memset(pcg_r, 0, sizeof(pcg_r));
111 memset(pcg_g, 0, sizeof(pcg_g));
112 #ifdef _X1TURBO_FEATURE
113 memset(gaiji_b, 0, sizeof(gaiji_b));
114 memset(gaiji_r, 0, sizeof(gaiji_r));
115 memset(gaiji_g, 0, sizeof(gaiji_g));
119 register_frame_event(this);
120 register_vline_event(this);
123 void DISPLAY::reset()
125 #ifdef _X1TURBO_FEATURE
140 cur_line = cur_code = 0;
143 kaddr = kofs = kflag = 0;
144 kanji_ptr = &kanji[0];
147 void DISPLAY::write_io8(uint32_t addr, uint32_t data)
149 switch(addr & 0xff00) {
151 write_kanji(addr, data);
157 int num = get_zpal_num(addr, data);
158 zpal[num].b = data & 0x0f;
159 zpalette_pc[num + 16] = RGB_COLOR((zpal[num].r * 255) / 15, (zpal[num].g * 255) / 15, (zpal[num].b * 255) / 15);
160 } else if(APEN && APRD) {
161 zpal_num = get_zpal_num(addr, data);
174 int num = get_zpal_num(addr, data);
175 zpal[num].r = data & 0x0f;
176 zpalette_pc[num + 16] = RGB_COLOR((zpal[num].r * 255) / 15, (zpal[num].g * 255) / 15, (zpal[num].b * 255) / 15);
177 } else if(APEN && APRD) {
178 // zpal_num = get_zpal_num(addr, data);
191 int num = get_zpal_num(addr, data);
192 zpal[num].g = data & 0x0f;
193 zpalette_pc[num + 16] = RGB_COLOR((zpal[num].r * 255) / 15, (zpal[num].g * 255) / 15, (zpal[num].b * 255) / 15);
194 } else if(APEN && APRD) {
195 // zpal_num = get_zpal_num(addr, data);
210 pcg_b[cur_code][cur_line] = data;
211 #ifdef _X1TURBO_FEATURE
212 gaiji_b[cur_code >> 1][(cur_line << 1) | (cur_code & 1)] = data;
217 pcg_r[cur_code][cur_line] = data;
218 #ifdef _X1TURBO_FEATURE
219 gaiji_r[cur_code >> 1][(cur_line << 1) | (cur_code & 1)] = data;
224 pcg_g[cur_code][cur_line] = data;
225 #ifdef _X1TURBO_FEATURE
226 gaiji_g[cur_code >> 1][(cur_line << 1) | (cur_code & 1)] = data;
229 #ifdef _X1TURBO_FEATURE
245 ztpal[addr & 7] = data;
246 zpalette_pc[addr & 7] = RGB_COLOR((((data >> 2) & 3) * 255) / 3, (((data >> 4) & 3) * 255) / 3, (((data >> 0) & 3) * 255) / 3);
283 // hireso = !((mode1 & 3) == 0 || (mode1 & 3) == 2);
300 vram_a[addr & 0x7ff] = data;
310 vram_a[addr & 0x7ff] = data; // mirror
320 vram_t[addr & 0x7ff] = data;
330 #ifdef _X1TURBO_FEATURE
331 vram_k[addr & 0x7ff] = data;
333 vram_t[addr & 0x7ff] = data; // mirror
339 uint32_t DISPLAY::read_io8(uint32_t addr)
341 switch(addr & 0xff00) {
343 return read_kanji(addr);
346 if(AEN && APEN && APRD) {
347 return zpal[zpal_num].b;
351 if(AEN && APEN && APRD) {
352 return zpal[zpal_num].r;
356 if(AEN && APEN && APRD) {
357 return zpal[zpal_num].g;
364 return get_cur_font(addr);
367 return pcg_b[cur_code][cur_line];
370 return pcg_r[cur_code][cur_line];
373 return pcg_g[cur_code][cur_line];
388 return ztpal[addr & 7];
436 return vram_a[addr & 0x7ff];
445 return vram_a[addr & 0x7ff]; // mirror
454 return vram_t[addr & 0x7ff];
463 #ifdef _X1TURBO_FEATURE
464 return vram_k[addr & 0x7ff];
466 return vram_t[addr & 0x7ff]; // mirror
472 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
474 if(id == SIG_DISPLAY_VBLANK) {
477 vblank_clock = get_current_clock();
479 } else if(id == SIG_DISPLAY_COLUMN40) {
480 column40 = ((data & mask) != 0);
482 } else if(id == SIG_DISPLAY_DETECT_VBLANK) {
483 // hack: cpu detects vblank
484 vblank_clock = get_current_clock();
488 void DISPLAY::event_frame()
490 cblink = (cblink + 1) & 0x3f;
492 // update crtc parameters
493 ch_height = (regs[9] & 0x1f) + 1;
494 hz_total = regs[0] + 1;
496 vt_disp = regs[6] & 0x7f;
497 st_addr = (regs[12] << 8) | regs[13];
499 #ifdef _X1TURBO_FEATURE
500 int vt_total = ((regs[4] & 0x7f) + 1) * ch_height + (regs[5] & 0x1f);
501 hireso = (vt_total > 400);
505 void DISPLAY::event_vline(int v, int clock)
507 #ifdef _X1TURBO_FEATURE
517 #ifdef _X1TURBO_FEATURE
519 // restart cpu after pcg/cgrom is accessed
520 d_cpu->write_signal(SIG_CPU_BUSREQ, 0, 0);
524 void DISPLAY::update_crtc()
526 #ifdef _X1TURBO_FEATURE
528 d_crtc->set_char_clock((mode1 & 1) ? VDP_CLOCK * 1.5 / 32.0 : VDP_CLOCK / 32.0);
530 d_crtc->set_char_clock((mode1 & 1) ? VDP_CLOCK * 1.5 / 16.0 : VDP_CLOCK / 16.0);
534 d_crtc->set_char_clock(VDP_CLOCK / 32.0);
536 d_crtc->set_char_clock(VDP_CLOCK / 16.0);
541 void DISPLAY::update_pal()
544 for(int i = 0; i < 8; i++) {
545 uint8_t bit = 1 << i;
546 pal2[i] = ((pal[0] & bit) ? 1 : 0) | ((pal[1] & bit) ? 2 : 0) | ((pal[2] & bit) ? 4 : 0) | 8;
548 #ifdef _X1TURBO_FEATURE
549 if(mode2 & 0x10) pal2[0] = 8;
550 if(mode2 & 0x20) pal2[1] = 8;
552 for(int c = 0; c < 8; c++) {
553 for(int t = 0; t < 8; t++) {
554 if(priority & (1 << c)) {
557 #ifdef _X1TURBO_FEATURE
558 pri[c][t] = ((mode2 & 8) && (mode2 & 7) == t) ? 0 : t;
569 uint8_t DISPLAY::get_cur_font(uint32_t addr)
571 #ifdef _X1TURBO_FEATURE
574 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
578 if(!(vram_a[0x7ff] & 0x20)) {
580 } else if(!(vram_a[0x3ff] & 0x20)) {
582 } else if(!(vram_a[0x5ff] & 0x20)) {
584 } else if(!(vram_a[0x1ff] & 0x20)) {
589 uint16_t ank = vram_t[vaddr];
590 uint16_t knj = vram_k[vaddr];
593 uint32_t ofs = adr2knj_x1t((knj << 8) | ank);
597 return kanji[ofs | (addr & 15)];
598 } else if(mode1 & 0x40) {
599 return kanji[(ank << 4) | (addr & 15)];
601 return font[(ank << 3) | ((addr >> 1) & 7)];
606 return font[(cur_code << 3) | (cur_line & 7)];
609 void DISPLAY::get_cur_pcg(uint32_t addr)
611 #ifdef _X1TURBO_FEATURE
614 d_cpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
618 if(vram_a[0x7ff] & 0x20) {
620 } else if(vram_a[0x3ff] & 0x20) {
622 } else if(vram_a[0x5ff] & 0x20) {
624 } else if(vram_a[0x1ff] & 0x20) {
629 cur_code = vram_t[vaddr];
630 cur_line = (addr >> 1) & 7;
632 if(vram_k[vaddr] & 0x90) {
634 cur_code += addr & 1;
641 void DISPLAY::get_cur_code_line()
643 //#ifdef _X1TURBO_FEATURE
644 // int ht_clock = hireso ? 161 : 250;
648 int clock = get_passed_clock(vblank_clock);
649 int vt_line = vt_disp * ch_height + (int)(clock / ht_clock);
651 int addr = (hz_total * (clock % ht_clock)) / ht_clock;
652 addr += hz_disp * (int)(vt_line / ch_height);
658 cur_code = vram_t[addr & 0x7ff];
659 cur_line = (vt_line % ch_height) & 7;
662 void DISPLAY::draw_line(int v)
665 memset(text, 0, sizeof(text));
666 memset(cg, 0, sizeof(cg));
668 memset(zcg, 0, sizeof(zcg));
670 prev_vert_double = false;
673 if((regs[8] & 0x30) != 0x30) {
674 if((v % ch_height) == 0) {
675 draw_text(v / ch_height);
678 if(AEN && !hireso && column40) {
683 memcpy(&pri_line[v][0][0], &pri[0][0], sizeof(pri));
685 memset(&pri_line[v][0][0], 0, sizeof(pri));
689 void DISPLAY::draw_screen()
691 // copy to real screen
693 zpalette_pc[8 + 0] = zpalette_pc[16 + 0x000];
694 zpalette_pc[8 + 1] = zpalette_pc[16 + 0x00f];
695 zpalette_pc[8 + 2] = zpalette_pc[16 + 0x0f0];
696 zpalette_pc[8 + 3] = zpalette_pc[16 + 0x0ff];
697 zpalette_pc[8 + 4] = zpalette_pc[16 + 0xf00];
698 zpalette_pc[8 + 5] = zpalette_pc[16 + 0xf0f];
699 zpalette_pc[8 + 6] = zpalette_pc[16 + 0xff0];
700 zpalette_pc[8 + 7] = zpalette_pc[16 + 0xfff];
707 for(int y = 0; y < 400; y++) {
708 scrntype_t* dest = emu->get_screen_buffer(y);
709 uint8_t* src_text = text[y];
710 uint16_t* src_cg0 = zcg[0][y];
712 for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {
713 uint16_t cg00 = src_cg0[x] | (src_cg0[x] >> 2);
715 dest[x2] = dest[x2 + 1] = get_zpriority(src_text[x], cg00, cg00);
720 for(int y = 0; y < 400; y++) {
721 scrntype_t* dest = emu->get_screen_buffer(y);
722 uint8_t* src_text = text[y];
723 uint16_t* src_cg0 = zcg[0][y];
725 for(int x = 0; x < 640; x++) {
726 uint16_t cg00 = src_cg0[x] | (src_cg0[x] >> 2);
728 dest[x] = get_zpriority(src_text[x], cg00, cg00);
732 emu->screen_skip_line(false);
737 for(int y = 0; y < 200; y++) {
738 scrntype_t* dest0 = emu->get_screen_buffer(y * 2 + 0);
739 scrntype_t* dest1 = emu->get_screen_buffer(y * 2 + 1);
740 uint8_t* src_text = text[y];
741 uint16_t* src_cg0 = zcg[0][y];
742 uint16_t* src_cg1 = zcg[1][y];
745 for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {
746 uint16_t cg00 = src_cg0[x] | (src_cg0[x] >> 2);
747 uint16_t cg11 = src_cg1[x] | (src_cg1[x] >> 2);
749 dest0[x2] = dest0[x2 + 1] = get_zpriority(src_text[x], cg00, cg11);
752 for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {
753 uint16_t cg01 = src_cg0[x] | (src_cg1[x] >> 2);
755 dest0[x2] = dest0[x2 + 1] = get_zpriority(src_text[x], cg01, cg01);
758 if(!config.scan_line) {
759 my_memcpy(dest1, dest0, 640 * sizeof(scrntype_t));
761 memset(dest1, 0, 640 * sizeof(scrntype_t));
766 for(int y = 0; y < 200; y++) {
767 scrntype_t* dest0 = emu->get_screen_buffer(y * 2 + 0);
768 scrntype_t* dest1 = emu->get_screen_buffer(y * 2 + 1);
769 uint8_t* src_text = text[y];
770 uint16_t* src_cg0 = zcg[0][y];
772 for(int x = 0; x < 640; x++) {
773 uint16_t cg00 = src_cg0[x] | (src_cg0[x] >> 2);
775 dest0[x] = get_zpriority(src_text[x], cg00, cg00);
777 if(!config.scan_line) {
778 my_memcpy(dest1, dest0, 640 * sizeof(scrntype_t));
780 memset(dest1, 0, 640 * sizeof(scrntype_t));
784 emu->screen_skip_line(true);
788 #ifdef _X1TURBO_FEATURE
793 for(int y = 0; y < 400; y++) {
794 scrntype_t* dest = emu->get_screen_buffer(y);
795 uint8_t* src_text = text[y];
796 uint8_t* src_cg = cg[y];
798 for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {
800 dest[x2] = dest[x2 + 1] = zpalette_pc[pri_line[y][src_cg[x]][src_text[x]]];
802 dest[x2] = dest[x2 + 1] = palette_pc[pri_line[y][src_cg[x]][src_text[x]]];
808 for(int y = 0; y < 400; y++) {
809 scrntype_t* dest = emu->get_screen_buffer(y);
810 uint8_t* src_text = text[y];
811 uint8_t* src_cg = cg[y];
813 for(int x = 0; x < 640; x++) {
815 dest[x] = zpalette_pc[pri_line[y][src_cg[x]][src_text[x]]];
817 dest[x] = palette_pc[pri_line[y][src_cg[x]][src_text[x]]];
822 emu->screen_skip_line(false);
829 for(int y = 0; y < 200; y++) {
830 scrntype_t* dest0 = emu->get_screen_buffer(y * 2 + 0);
831 scrntype_t* dest1 = emu->get_screen_buffer(y * 2 + 1);
832 uint8_t* src_text = text[y];
833 uint8_t* src_cg = cg[y];
835 for(int x = 0, x2 = 0; x < 320; x++, x2 += 2) {
837 dest0[x2] = dest0[x2 + 1] = zpalette_pc[pri_line[y][src_cg[x]][src_text[x]]];
839 dest0[x2] = dest0[x2 + 1] = palette_pc[pri_line[y][src_cg[x]][src_text[x]]];
842 if(!config.scan_line) {
843 my_memcpy(dest1, dest0, 640 * sizeof(scrntype_t));
845 memset(dest1, 0, 640 * sizeof(scrntype_t));
850 for(int y = 0; y < 200; y++) {
851 scrntype_t* dest0 = emu->get_screen_buffer(y * 2 + 0);
852 scrntype_t* dest1 = emu->get_screen_buffer(y * 2 + 1);
853 uint8_t* src_text = text[y];
854 uint8_t* src_cg = cg[y];
856 for(int x = 0; x < 640; x++) {
858 dest0[x] = zpalette_pc[pri_line[y][src_cg[x]][src_text[x]]];
860 dest0[x] = palette_pc[pri_line[y][src_cg[x]][src_text[x]]];
863 if(!config.scan_line) {
864 my_memcpy(dest1, dest0, 640 * sizeof(scrntype_t));
866 memset(dest1, 0, 640 * sizeof(scrntype_t));
870 emu->screen_skip_line(true);
874 void DISPLAY::draw_text(int y)
876 int width = column40 ? 40 : 80;
877 uint16_t src = st_addr + hz_disp * y;
879 bool cur_vert_double = true;
880 uint8_t prev_attr = 0, prev_pattern_b[32], prev_pattern_r[32], prev_pattern_g[32];
882 for(int x = 0; x < hz_disp && x < width; x++) {
884 uint8_t code = vram_t[src];
885 #ifdef _X1TURBO_FEATURE
886 uint8_t knj = vram_k[src];
888 uint8_t attr = vram_a[src];
891 uint8_t col = attr & 7;
892 bool reverse = ((attr & 8) != 0);
893 bool blink = ((attr & 0x10) && (cblink & 0x20));
894 reverse = (reverse != blink);
897 const uint8_t *pattern_b, *pattern_r, *pattern_g;
898 #ifdef _X1TURBO_FEATURE
906 #ifdef _X1TURBO_FEATURE
908 pattern_b = gaiji_b[code >> 1];
909 pattern_r = gaiji_r[code >> 1];
910 pattern_g = gaiji_g[code >> 1];
914 pattern_b = pcg_b[code];
915 pattern_r = pcg_r[code];
916 pattern_g = pcg_g[code];
917 #ifdef _X1TURBO_FEATURE
918 shift = hireso ? 1 : 0;
921 #ifdef _X1TURBO_FEATURE
922 } else if(knj & 0x80) {
923 uint32_t ofs = adr2knj_x1t((knj << 8) | code);
927 pattern_b = pattern_r = pattern_g = &kanji[ofs];
928 shift = hireso ? ((ch_height >= 32) ? 1 : 0) : ((ch_height >= 16) ? 0 : -1);
930 } else if(hireso || (mode1 & 4)) {
932 pattern_b = pattern_r = pattern_g = &kanji[code << 4];
933 shift = hireso ? ((ch_height >= 32) ? 1 : 0) : ((ch_height >= 16) ? 0 : -1);
938 pattern_b = pattern_r = pattern_g = &font[code << 3];
941 // check vertical doubled char
943 cur_vert_double = false;
947 for(int l = 0; l < ch_height; l++) {
949 int line = cur_vert_double ? raster + (l >> 1) : l;
950 #ifdef _X1TURBO_FEATURE
953 } else if(shift == -1) {
955 if(cur_vert_double) {
960 if((x & 1) && (prev_attr & 0x80)) {
961 b = prev_pattern_b[line] << 4;
962 r = prev_pattern_r[line] << 4;
963 g = prev_pattern_g[line] << 4;
964 } else if(line >= max_line) {
965 b = prev_pattern_b[line] = 0;
966 r = prev_pattern_r[line] = 0;
967 g = prev_pattern_g[line] = 0;
969 b = prev_pattern_b[line] = pattern_b[line];
970 r = prev_pattern_r[line] = pattern_r[line];
971 g = prev_pattern_g[line] = pattern_g[line];
974 b = (!(col & 1)) ? 0xff : ~b;
975 r = (!(col & 2)) ? 0xff : ~r;
976 g = (!(col & 4)) ? 0xff : ~g;
978 b = (!(col & 1)) ? 0 : b;
979 r = (!(col & 2)) ? 0 : r;
980 g = (!(col & 4)) ? 0 : g;
983 int yy = y * ch_height + l;
984 #ifdef _X1TURBO_FEATURE
991 uint8_t* d = &text[yy][x << 3];
994 // horizontal doubled char
995 d[ 0] = d[ 1] = ((b & 0x80) >> 7) | ((r & 0x80) >> 6) | ((g & 0x80) >> 5);
996 d[ 2] = d[ 3] = ((b & 0x40) >> 6) | ((r & 0x40) >> 5) | ((g & 0x40) >> 4);
997 d[ 4] = d[ 5] = ((b & 0x20) >> 5) | ((r & 0x20) >> 4) | ((g & 0x20) >> 3);
998 d[ 6] = d[ 7] = ((b & 0x10) >> 4) | ((r & 0x10) >> 3) | ((g & 0x10) >> 2);
1000 d[0] = ((b & 0x80) >> 7) | ((r & 0x80) >> 6) | ((g & 0x80) >> 5);
1001 d[1] = ((b & 0x40) >> 6) | ((r & 0x40) >> 5) | ((g & 0x40) >> 4);
1002 d[2] = ((b & 0x20) >> 5) | ((r & 0x20) >> 4) | ((g & 0x20) >> 3);
1003 d[3] = ((b & 0x10) >> 4) | ((r & 0x10) >> 3) | ((g & 0x10) >> 2);
1004 d[4] = ((b & 0x08) >> 3) | ((r & 0x08) >> 2) | ((g & 0x08) >> 1);
1005 d[5] = ((b & 0x04) >> 2) | ((r & 0x04) >> 1) | ((g & 0x04) >> 0);
1006 d[6] = ((b & 0x02) >> 1) | ((r & 0x02) >> 0) | ((g & 0x02) << 1);
1007 d[7] = ((b & 0x01) >> 0) | ((r & 0x01) << 1) | ((g & 0x01) << 2);
1012 if(cur_vert_double && !prev_vert_double) {
1013 prev_vert_double = true;
1014 raster = ch_height >> 1;
1016 prev_vert_double = false;
1021 void DISPLAY::draw_cg(int line, int plane)
1023 int width = column40 ? 40 : 80;
1025 int y = line / ch_height;
1026 int l = line % ch_height;
1030 int ofs, src = st_addr + hz_disp * y;
1031 #ifdef _X1TURBO_FEATURE
1032 int page = (hireso && !(mode1 & 2)) ? (l & 1) : (mode1 & 8);
1033 int ll = hireso ? (l >> 1) : l;
1036 ofs = (0x400 * (ll & 15));// + (page ? 0xc000 : 0);
1038 ofs = (0x800 * (ll & 7));// + (page ? 0xc000 : 0);
1041 ofs = 0x800 * (l & 7);
1046 HIRESO=0, WIDTH=40, C64=0: 320x200, 4096 PAGE0:(ADDR 000h-3FFh) + PAGE0:(ADDR 400h-7FFh) + PAGE1:(ADDR 000h-3FFh) + PAGE1:(ADDR 400h-7FFh)
1047 HIRESO=0, WIDTH=40, C64=1: 320x200, 64x2 PAGE0:(ADDR 000h-3FFh) + PAGE0:(ADDR 400h-7FFh) / PAGE1:(ADDR 000h-3FFh) + PAGE1:(ADDR 400h-7FFh)
1048 HIRESO=1, WIDTH=40, C64=*: 320x200, 64 PAGE*:(ADDR 000h-3FFh) + PAGE*:(ADDR 400h-7FFh)
1049 HIRESO=0, WIDTH=80, C64=*: 640x200, 64 PAGE0:(ADDR 000h-7FFh) + PAGE1:(ADDR 000h-7FFh)
1050 HIRESO=1, WIDTH=80, C64=*: 640x200, 8 PAGE0:(ADDR 000h-7FFh) + PAGE0:(ADDR 000h-7FFh)
1052 HIRESO=0, WIDTH=40, C64=1: 320x200, 64x2
1054 SCREEN 0 00 00 PAGE0
1055 SCREEM 2 18 08 PAGE1
1056 SCREEN 4 00 10 PAGE0 > PAGE1
1057 SCREEN 6 18 18 PAGE0 < PAGE1
1061 if(C64 && !(zpriority & 0x10)) {
1063 my_memcpy(zcg[plane][1], zcg[plane][0], sizeof(uint16_t) * 640);
1076 int ofs_b0 = ofs + 0x0000;
1077 int ofs_r0 = ofs + 0x4000;
1078 int ofs_g0 = ofs + 0x8000;
1079 int ofs_b1 = column40 ? (ofs_b0 ^ 0x400) : hireso ? ofs_b0 : (ofs_b0 + 0xc000);
1080 int ofs_r1 = column40 ? (ofs_r0 ^ 0x400) : hireso ? ofs_r0 : (ofs_r0 + 0xc000);
1081 int ofs_g1 = column40 ? (ofs_g0 ^ 0x400) : hireso ? ofs_g0 : (ofs_g0 + 0xc000);
1083 for(int x = 0; x < hz_disp && x < width; x++) {
1084 src &= column40 ? 0x3ff : 0x7ff;
1085 uint16_t b0 = vram_ptr[ofs_b0 | src];
1086 uint16_t r0 = vram_ptr[ofs_r0 | src];
1087 uint16_t g0 = vram_ptr[ofs_g0 | src];
1088 uint16_t b1 = vram_ptr[ofs_b1 | src];
1089 uint16_t r1 = vram_ptr[ofs_r1 | src];
1090 uint16_t g1 = vram_ptr[ofs_g1 | src++];
1091 uint16_t* d = &zcg[plane][line][x << 3];
1093 // MSB <- G0,G1,0,0, R0,R1,0,0, B0,B1,0,0 -> LSB
1094 d[0] = ((b0 & 0x80) >> 4) | ((b1 & 0x80) >> 5) | ((r0 & 0x80) >> 0) | ((r1 & 0x80) >> 1) | ((g0 & 0x80) << 4) | ((g1 & 0x80) << 3);
1095 d[1] = ((b0 & 0x40) >> 3) | ((b1 & 0x40) >> 4) | ((r0 & 0x40) << 1) | ((r1 & 0x40) >> 0) | ((g0 & 0x40) << 5) | ((g1 & 0x40) << 4);
1096 d[2] = ((b0 & 0x20) >> 2) | ((b1 & 0x20) >> 3) | ((r0 & 0x20) << 2) | ((r1 & 0x20) << 1) | ((g0 & 0x20) << 6) | ((g1 & 0x20) << 5);
1097 d[3] = ((b0 & 0x10) >> 1) | ((b1 & 0x10) >> 2) | ((r0 & 0x10) << 3) | ((r1 & 0x10) << 2) | ((g0 & 0x10) << 7) | ((g1 & 0x10) << 6);
1098 d[4] = ((b0 & 0x08) >> 0) | ((b1 & 0x08) >> 1) | ((r0 & 0x08) << 4) | ((r1 & 0x08) << 3) | ((g0 & 0x08) << 8) | ((g1 & 0x08) << 7);
1099 d[5] = ((b0 & 0x04) << 1) | ((b1 & 0x04) >> 0) | ((r0 & 0x04) << 5) | ((r1 & 0x04) << 4) | ((g0 & 0x04) << 9) | ((g1 & 0x04) << 8);
1100 d[6] = ((b0 & 0x02) << 2) | ((b1 & 0x02) << 1) | ((r0 & 0x02) << 6) | ((r1 & 0x02) << 5) | ((g0 & 0x02) << 10) | ((g1 & 0x02) << 9);
1101 d[7] = ((b0 & 0x01) << 3) | ((b1 & 0x01) << 2) | ((r0 & 0x01) << 7) | ((r1 & 0x01) << 6) | ((g0 & 0x01) << 11) | ((g1 & 0x01) << 10);
1106 #ifdef _X1TURBO_FEATURE
1111 int ofs_b = ofs + 0x0000;
1112 int ofs_r = ofs + 0x4000;
1113 int ofs_g = ofs + 0x8000;
1115 for(int x = 0; x < hz_disp && x < width; x++) {
1117 uint8_t b = vram_ptr[ofs_b | src];
1118 uint8_t r = vram_ptr[ofs_r | src];
1119 uint8_t g = vram_ptr[ofs_g | src++];
1120 uint8_t* d = &cg[line][x << 3];
1122 d[0] = ((b & 0x80) >> 7) | ((r & 0x80) >> 6) | ((g & 0x80) >> 5);
1123 d[1] = ((b & 0x40) >> 6) | ((r & 0x40) >> 5) | ((g & 0x40) >> 4);
1124 d[2] = ((b & 0x20) >> 5) | ((r & 0x20) >> 4) | ((g & 0x20) >> 3);
1125 d[3] = ((b & 0x10) >> 4) | ((r & 0x10) >> 3) | ((g & 0x10) >> 2);
1126 d[4] = ((b & 0x08) >> 3) | ((r & 0x08) >> 2) | ((g & 0x08) >> 1);
1127 d[5] = ((b & 0x04) >> 2) | ((r & 0x04) >> 1) | ((g & 0x04) >> 0);
1128 d[6] = ((b & 0x02) >> 1) | ((r & 0x02) >> 0) | ((g & 0x02) << 1);
1129 d[7] = ((b & 0x01) >> 0) | ((r & 0x01) << 1) | ((g & 0x01) << 2);
1135 int DISPLAY::get_zpal_num(uint32_t addr, uint32_t data)
1137 int num = ((data >> 4) & 0x0f) | ((addr << 4) & 0xff0);
1139 if(hireso && !column40) {
1144 } else if(!(!hireso && column40 && !C64)) {
1152 scrntype_t DISPLAY::get_zpriority(uint8_t text, uint16_t cg0, uint16_t cg1)
1154 if((mode2 & 8) && (text == (mode2 & 7))) {
1155 int digital = ((cg0 >> 9) & 4) | ((cg0 >> 6) & 2) | ((cg0 >> 3) & 1);
1156 if(!(priority & (1 << digital))) {
1160 uint16_t fore = ((zpriority & 0x18) != 0x18) ? cg0 : cg1;
1161 uint16_t back = ((zpriority & 0x18) != 0x18) ? cg1 : cg0;
1164 switch(zpriority & 0x13) {
1167 disp = text ? text : (fore + 16);
1171 disp = fore ? (fore + 16) : text;
1174 disp = text ? text : fore ? (fore + 16) : (back + 16);
1177 disp = fore ? (fore + 16) : back ? (back + 16) : text;
1180 disp = fore ? (fore + 16) : text ? text : (back + 16);
1182 default: // undefined case :-(
1183 disp = text ? text : fore ? (fore + 16) : (back + 16);
1186 // if((mode2 & 0x10) && disp == (0x000 + 16)) {
1189 // if((mode2 & 0x20) && disp == (0x00f + 16)) {
1192 return zpalette_pc[disp];
1196 // kanji rom (from X1EMU by KM)
1198 void DISPLAY::write_kanji(uint32_t addr, uint32_t data)
1202 kaddr = (kaddr & 0xff00) | data;
1205 kaddr = (kaddr & 0xff) | (data << 8);
1208 // TODO: bit0 L->H: Latch
1209 kanji_ptr = &kanji[adr2knj_x1(kaddr & 0xfff0)];
1214 uint32_t DISPLAY::read_kanji(uint32_t addr)
1218 if(kaddr & 0xff00) {
1219 uint32_t val = kanji_ptr[kofs];
1222 kofs = (kofs + 1) & 15;
1227 return jis2adr_x1(kaddr << 8) >> 8;
1229 if(kaddr & 0xff00) {
1230 uint32_t val = kanji_ptr[kofs + 16];
1233 kofs = (kofs + 1) & 15;
1243 uint16_t DISPLAY::jis2adr_x1(uint16_t jis)
1245 uint16_t jh, jl, adr;
1250 adr = 0x4000 + (jh - 0x30) * 0x600;
1252 adr = 0x0100 + (jh - 0x21) * 0x600;
1255 adr += (jl - 0x20) * 0x10;
1260 uint32_t DISPLAY::adr2knj_x1(uint16_t adr)
1262 uint16_t jh, jl, jis;
1266 jh = 0x21 + jh / 0x600;
1269 jh = 0x30 + jh / 0x600;
1272 adr -= 0x4000 + (jh - 0x30) * 0x600;
1274 adr -= 0x0100 + (jh - 0x21) * 0x600;
1281 jis = (jh << 8) | jl;
1282 return jis2knj(jis);
1285 #ifdef _X1TURBO_FEATURE
1286 uint32_t DISPLAY::adr2knj_x1t(uint16_t adr)
1299 j2 = rl & 0x1f; // rl4,3,2,1,0
1300 j1 = (rl / 0x20) & 7; // rl7,6,5
1306 case 0: j2 |= 0x20; break;
1307 case 1: j2 |= 0x60; break;
1308 case 2: j2 |= 0x40; break;
1309 default: j1 = j2 = 0; break;
1311 } else if(rh > 0x1c) {
1315 case 0: j2 |= 0x20; break;
1316 case 1: j2 |= 0x60; break;
1317 case 2: j2 |= 0x40; break;
1318 default: j1 = j2 = 0; break;
1321 j1 |= (((rh >> 1) + 7) / 3) * 0x10;
1323 j2 |= ((((rh >> 1) + 1) % 3) + 1) * 0x20;
1326 jis = (j1 << 8) | j2;
1327 return jis2knj(jis);
1331 uint32_t DISPLAY::jis2knj(uint16_t jis)
1333 uint32_t sjis = jis2sjis(jis);
1337 } else if(sjis >= 0x8140 && sjis < 0x84c0) {
1338 return 0x01000 + (sjis - 0x8140) * 32;
1339 } else if(sjis >= 0x8890 && sjis < 0xa000) {
1340 return 0x08000 + (sjis - 0x8890) * 32;
1341 } else if(sjis >= 0xe040 && sjis < 0xeab0) {
1342 return 0x36e00 + (sjis - 0xe040) * 32;
1348 uint16_t DISPLAY::jis2sjis(uint16_t jis)
1366 c1 = (c1 - 0x20 - 1) / 2 + 0x81;
1370 return (c1 << 8) | c2;
1373 #define STATE_VERSION 3
1375 void DISPLAY::save_state(FILEIO* state_fio)
1377 state_fio->FputUint32(STATE_VERSION);
1378 state_fio->FputInt32(this_device_id);
1380 state_fio->Fwrite(vram_t, sizeof(vram_t), 1);
1381 state_fio->Fwrite(vram_a, sizeof(vram_a), 1);
1382 #ifdef _X1TURBO_FEATURE
1383 state_fio->Fwrite(vram_k, sizeof(vram_k), 1);
1385 state_fio->Fwrite(pcg_b, sizeof(pcg_b), 1);
1386 state_fio->Fwrite(pcg_r, sizeof(pcg_r), 1);
1387 state_fio->Fwrite(pcg_g, sizeof(pcg_g), 1);
1388 #ifdef _X1TURBO_FEATURE
1389 state_fio->Fwrite(gaiji_b, sizeof(gaiji_b), 1);
1390 state_fio->Fwrite(gaiji_r, sizeof(gaiji_r), 1);
1391 state_fio->Fwrite(gaiji_g, sizeof(gaiji_g), 1);
1393 state_fio->FputUint8(cur_code);
1394 state_fio->FputUint8(cur_line);
1395 state_fio->FputInt32(kaddr);
1396 state_fio->FputInt32(kofs);
1397 state_fio->FputInt32(kflag);
1398 state_fio->FputInt32((int)(kanji_ptr - &kanji[0]));
1399 state_fio->Fwrite(pal, sizeof(pal), 1);
1400 state_fio->FputUint8(priority);
1401 state_fio->Fwrite(pri, sizeof(pri), 1);
1402 state_fio->FputBool(column40);
1403 #ifdef _X1TURBO_FEATURE
1404 state_fio->FputUint8(mode1);
1405 state_fio->FputUint8(mode2);
1406 state_fio->FputBool(hireso);
1409 state_fio->FputUint8(zmode1);
1410 state_fio->FputUint8(zpriority);
1411 state_fio->FputUint8(zadjust);
1412 state_fio->FputUint8(zmosaic);
1413 state_fio->FputUint8(zchromakey);
1414 state_fio->FputUint8(zscroll);
1415 state_fio->FputUint8(zmode2);
1416 state_fio->Fwrite(ztpal, sizeof(ztpal), 1);
1417 state_fio->Fwrite(zpal, sizeof(zpal), 1);
1418 state_fio->FputInt32(zpal_num);
1419 state_fio->Fwrite(zpalette_pc, sizeof(zpalette_pc), 1);
1421 state_fio->FputBool(prev_vert_double);
1422 state_fio->FputInt32(raster);
1423 state_fio->FputInt32(cblink);
1424 state_fio->FputInt32(ch_height);
1425 state_fio->FputInt32(hz_total);
1426 state_fio->FputInt32(hz_disp);
1427 state_fio->FputInt32(vt_disp);
1428 state_fio->FputInt32(st_addr);
1429 state_fio->FputUint32(vblank_clock);
1432 bool DISPLAY::load_state(FILEIO* state_fio)
1434 if(state_fio->FgetUint32() != STATE_VERSION) {
1437 if(state_fio->FgetInt32() != this_device_id) {
1440 state_fio->Fread(vram_t, sizeof(vram_t), 1);
1441 state_fio->Fread(vram_a, sizeof(vram_a), 1);
1442 #ifdef _X1TURBO_FEATURE
1443 state_fio->Fread(vram_k, sizeof(vram_k), 1);
1445 state_fio->Fread(pcg_b, sizeof(pcg_b), 1);
1446 state_fio->Fread(pcg_r, sizeof(pcg_r), 1);
1447 state_fio->Fread(pcg_g, sizeof(pcg_g), 1);
1448 #ifdef _X1TURBO_FEATURE
1449 state_fio->Fread(gaiji_b, sizeof(gaiji_b), 1);
1450 state_fio->Fread(gaiji_r, sizeof(gaiji_r), 1);
1451 state_fio->Fread(gaiji_g, sizeof(gaiji_g), 1);
1453 cur_code = state_fio->FgetUint8();
1454 cur_line = state_fio->FgetUint8();
1455 kaddr = state_fio->FgetInt32();
1456 kofs = state_fio->FgetInt32();
1457 kflag = state_fio->FgetInt32();
1458 kanji_ptr = &kanji[0] + state_fio->FgetInt32();
1459 state_fio->Fread(pal, sizeof(pal), 1);
1460 priority = state_fio->FgetUint8();
1461 state_fio->Fread(pri, sizeof(pri), 1);
1462 column40 = state_fio->FgetBool();
1463 #ifdef _X1TURBO_FEATURE
1464 mode1 = state_fio->FgetUint8();
1465 mode2 = state_fio->FgetUint8();
1466 hireso = state_fio->FgetBool();
1469 zmode1 = state_fio->FgetUint8();
1470 zpriority = state_fio->FgetUint8();
1471 zadjust = state_fio->FgetUint8();
1472 zmosaic = state_fio->FgetUint8();
1473 zchromakey = state_fio->FgetUint8();
1474 zscroll = state_fio->FgetUint8();
1475 zmode2 = state_fio->FgetUint8();
1476 state_fio->Fread(ztpal, sizeof(ztpal), 1);
1477 state_fio->Fread(zpal, sizeof(zpal), 1);
1478 zpal_num = state_fio->FgetInt32();
1479 state_fio->Fread(zpalette_pc, sizeof(zpalette_pc), 1);
1481 prev_vert_double = state_fio->FgetBool();
1482 raster = state_fio->FgetInt32();
1483 cblink = state_fio->FgetInt32();
1484 ch_height = state_fio->FgetInt32();
1485 hz_total = state_fio->FgetInt32();
1486 hz_disp = state_fio->FgetInt32();
1487 vt_disp = state_fio->FgetInt32();
1488 st_addr = state_fio->FgetInt32();
1489 vblank_clock = state_fio->FgetUint32();