2 * Common source code project -> FM-7 -> Display
3 * (C) 2015 K.Ohta <whatisthis.sowhat _at_ gmail.com>
5 * Feb 10, 2015 : Initial.
10 #include "../../fileio.h"
11 #include "fm7_display.h"
12 #if defined(_FM77AV_VARIANTS)
13 # include "mb61vh010.h"
16 DISPLAY::DISPLAY(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
23 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
26 #elif defined(_FM77_VARIANTS)
29 #if defined(_FM77AV_VARIANTS)
35 for(int i = 0; i < 256; i++) {
36 uint16_t n = (uint16_t)i;
37 for(int j = 0; j < 8; j++) {
38 bit_trans_table_0[i][j] = n & 0x80;
39 bit_trans_table_1[i][j] = ((n & 0x80) != 0) ? 0x40 : 0;
40 bit_trans_table_2[i][j] = ((n & 0x80) != 0) ? 0x20 : 0;
41 bit_trans_table_3[i][j] = ((n & 0x80) != 0) ? 0x10 : 0;
42 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
43 bit_trans_table_4[i][j] = ((n & 0x80) != 0) ? 0x08 : 0;
44 bit_trans_table_5[i][j] = ((n & 0x80) != 0) ? 0x04 : 0;
51 set_device_name(_T("DISPLAY SUBSYSTEM"));
59 void DISPLAY::reset_cpuonly()
63 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
64 mainio->write_signal(SIG_FM7_SUB_HALT, 0x00, 0xff);
67 palette_changed = true;
68 multimode_accessmask = 0;
69 multimode_dispmask = 0;
71 //cancel_request = false;
72 switch(config.cpu_type){
83 for(i = 0; i < 2; i++) {
84 offset_changed[i] = true;
85 tmp_offset_point[i].d = 0;
88 vram_wrote_shadow = true;
89 for(i = 0; i < 411; i++) vram_wrote_table[i] = true;
90 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
91 write_access_page = 0;
92 for(i = 0; i < 411; i++) vram_wrote_pages[i] = write_access_page;
96 #if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
102 if(hblank_event_id >= 0) cancel_event(this, hblank_event_id);
103 if(hdisp_event_id >= 0) cancel_event(this, hdisp_event_id);
104 if(vsync_event_id >= 0) cancel_event(this, vsync_event_id);
105 if(vstart_event_id >= 0) cancel_event(this, vstart_event_id);
106 hblank_event_id = -1;
109 vstart_event_id = -1;
110 if(display_mode == DISPLAY_MODE_8_400L) {
111 usec = 0.33 * 1000.0;
113 usec = 0.51 * 1000.0;
116 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
117 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
118 mainio->write_signal(SIG_DISPLAY_VSYNC, 0xff, 0xff);
120 #if defined(_FM77AV_VARIANTS)
122 offset_point_bank1 = 0;
124 display_page_bak = 0;
126 subcpu_resetreq = false;
127 subrom_bank_using = subrom_bank;
132 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
134 vram_display_block = 0;
135 vram_active_block = 0;
137 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
142 window_opened = false;
147 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
148 alu->write_signal(SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
149 alu->write_signal(SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400: 200, 0xffff);
150 alu->write_signal(SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xffffffff : 0, 0xffffffff);
152 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
153 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
154 alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
156 alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
157 alu->write_signal(SIG_ALU_PLANES, 3, 3);
160 for(i = 0; i < 8; i++) set_dpalette(i, i);
161 do_firq(!firq_mask && key_firq_req);
163 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
165 kanjiaddr.d = 0x00000000;
166 # if defined(_FM77L4)
168 stat_400linecard = false;
173 frame_skip_count_draw = 3;
174 frame_skip_count_transfer = 3;
175 need_transfer_line = true;
179 void DISPLAY::reset()
182 memset(io_w_latch, 0xff, sizeof(io_w_latch));
184 vram_accessflag = true;
185 display_mode = DISPLAY_MODE_8_200L;
187 screen_update_flag = true;
190 cancel_request = false;
191 #if defined(_FM77AV_VARIANTS)
193 apalette_index.d = 0;
194 for(i = 0; i < 4096; i++) {
195 analog_palette_r[i] = i & 0x0f0;
196 analog_palette_g[i] = (i & 0xf00) >> 4;
197 analog_palette_b[i] = (i & 0x00f) << 4;
202 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
209 #elif defined(_FM77L4)
212 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
213 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
214 key_firq_req = false; //firq_mask = true;
218 #if defined(_FM77AV_VARIANTS)
219 power_on_reset = false;
220 for(i = 0; i < 411; i++) vram_wrote_table[i] = false;
224 for(i = 0; i < 8; i++) set_dpalette(i, i);
225 multimode_accessmask = 0x00;
226 multimode_dispmask = 0x00;
231 if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
232 register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
233 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
237 void DISPLAY::update_config()
241 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
247 * Vram accessing functions moved to vram.cpp .
250 void DISPLAY::do_irq(bool flag)
252 subcpu->write_signal(SIG_CPU_IRQ, flag ? 1: 0, 1);
255 void DISPLAY::do_firq(bool flag)
257 subcpu->write_signal(SIG_CPU_FIRQ, flag ? 1: 0, 1);
260 void DISPLAY::do_nmi(bool flag)
262 #if defined(_FM77AV_VARIANTS)
263 if(!nmi_enable) flag = false;
265 subcpu->write_signal(SIG_CPU_NMI, flag ? 1 : 0, 1);
268 void DISPLAY::set_multimode(uint8_t val)
271 multimode_accessmask = val & 0x07;
272 multimode_dispmask = (val & 0x70) >> 4;
274 # if defined(_FM77AV_VARIANTS)
275 alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
280 uint8_t DISPLAY::get_multimode(void)
286 val = multimode_accessmask & 0x07;
287 val |= ((multimode_dispmask << 4) & 0x70);
293 uint8_t DISPLAY::get_cpuaccessmask(void)
295 return multimode_accessmask & 0x07;
298 void DISPLAY::set_dpalette(uint32_t addr, uint8_t val)
302 dpalette_data[addr] = val | 0xf8; //0b11111000;
303 b = ((val & 0x01) != 0x00)? 255 : 0x00;
304 r = ((val & 0x02) != 0x00)? 255 : 0x00;
305 g = ((val & 0x04) != 0x00)? 255 : 0x00;
307 dpalette_pixel[addr] = RGB_COLOR(r, g, b);
308 palette_changed = true;
311 uint8_t DISPLAY::get_dpalette(uint32_t addr)
319 data = dpalette_data[addr];
324 void DISPLAY::halt_subcpu(void)
326 subcpu->write_signal(SIG_CPU_BUSREQ, 0x01, 0x01);
329 void DISPLAY::go_subcpu(void)
331 subcpu->write_signal(SIG_CPU_BUSREQ, 0x00, 0x01);
334 void DISPLAY::enter_display(void)
338 subclock = SUBCLOCK_NORMAL;
340 subclock = SUBCLOCK_SLOW;
342 if(!is_cyclesteal && vram_accessflag) {
343 subclock = subclock / 3;
345 if(prev_clock != subclock) p_vm->set_cpu_clock(subcpu, subclock);
346 prev_clock = subclock;
349 void DISPLAY::leave_display(void)
353 void DISPLAY::halt_subsystem(void)
359 void DISPLAY::restart_subsystem(void)
362 #if defined(_FM77AV_VARIANTS)
363 if(subcpu_resetreq) {
364 firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
366 power_on_reset = true;
367 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
369 do_firq(!firq_mask && key_firq_req);
376 void DISPLAY::set_crtflag(void)
383 void DISPLAY::reset_crtflag(void)
390 uint8_t DISPLAY::acknowledge_irq(void)
392 cancel_request = false;
398 uint8_t DISPLAY::beep(void)
400 mainio->write_signal(FM7_MAINIO_BEEP, 0x01, 0x01);
401 return 0xff; // True?
406 uint8_t DISPLAY::attention_irq(void)
408 mainio->write_signal(FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
413 void DISPLAY::set_cyclesteal(uint8_t val)
416 # if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
420 is_cyclesteal = true;
422 is_cyclesteal = false;
430 uint8_t DISPLAY::set_vramaccess(void)
432 vram_accessflag = true;
437 void DISPLAY::reset_vramaccess(void)
439 vram_accessflag = false;
443 uint8_t DISPLAY::reset_subbusy(void)
450 void DISPLAY::set_subbusy(void)
456 #if defined(_FM77AV_VARIANTS)
458 void DISPLAY::alu_write_cmdreg(uint32_t val)
460 alu->write_data8(ALU_CMDREG, val);
461 if((val & 0x80) != 0) {
469 void DISPLAY::alu_write_logical_color(uint8_t val)
471 uint32_t data = (uint32_t)val;
472 alu->write_data8(ALU_LOGICAL_COLOR, data);
476 void DISPLAY::alu_write_mask_reg(uint8_t val)
478 uint32_t data = (uint32_t)val;
479 alu->write_data8(ALU_WRITE_MASKREG, data);
483 void DISPLAY::alu_write_cmpdata_reg(int addr, uint8_t val)
485 uint32_t data = (uint32_t)val;
487 alu->write_data8(ALU_CMPDATA_REG + addr, data);
491 void DISPLAY::alu_write_disable_reg(uint8_t val)
493 uint32_t data = (uint32_t)val;
494 alu->write_data8(ALU_BANK_DISABLE, data);
498 void DISPLAY::alu_write_tilepaint_data(uint32_t addr, uint8_t val)
500 uint32_t data = (uint32_t)val;
503 alu->write_data8(ALU_TILEPAINT_B, data);
506 alu->write_data8(ALU_TILEPAINT_R, data);
509 alu->write_data8(ALU_TILEPAINT_G, data);
512 //alu->write_data8(ALU_TILEPAINT_L, 0xff);
518 void DISPLAY::alu_write_offsetreg_hi(uint8_t val)
520 alu->write_data8(ALU_OFFSET_REG_HIGH, val & 0x7f);
524 void DISPLAY::alu_write_offsetreg_lo(uint8_t val)
526 alu->write_data8(ALU_OFFSET_REG_LO, val);
530 void DISPLAY::alu_write_linepattern_hi(uint8_t val)
532 alu->write_data8(ALU_LINEPATTERN_REG_HIGH, val);
536 void DISPLAY::alu_write_linepattern_lo(uint8_t val)
538 alu->write_data8(ALU_LINEPATTERN_REG_LO, val);
542 void DISPLAY::alu_write_line_position(int addr, uint8_t val)
544 uint32_t data = (uint32_t)val;
547 alu->write_data8(ALU_LINEPOS_START_X_HIGH, data & 0x03);
550 alu->write_data8(ALU_LINEPOS_START_X_LOW, data);
553 alu->write_data8(ALU_LINEPOS_START_Y_HIGH, data & 0x01);
556 alu->write_data8(ALU_LINEPOS_START_Y_LOW, data);
559 alu->write_data8(ALU_LINEPOS_END_X_HIGH, data & 0x03);
562 alu->write_data8(ALU_LINEPOS_END_X_LOW, data);
565 alu->write_data8(ALU_LINEPOS_END_Y_HIGH, data & 0x01);
568 alu->write_data8(ALU_LINEPOS_END_Y_LOW, data);
574 uint8_t DISPLAY::get_miscreg(void)
579 if(!hblank) ret |= 0x80;
580 if(vsync) ret |= 0x04;
581 if(alu->read_signal(SIG_ALU_BUSYSTAT) == 0) ret |= 0x10;
582 if(power_on_reset) ret |= 0x01;
587 void DISPLAY::set_miscreg(uint8_t val)
589 int old_display_page = display_page;
591 nmi_enable = ((val & 0x80) == 0) ? true : false;
592 if(!nmi_enable) do_nmi(false);
594 if((val & 0x40) == 0) {
599 if(display_page != old_display_page) {
602 active_page = ((val & 0x20) == 0) ? 0 : 1;
603 if((val & 0x04) == 0) {
608 cgrom_bank = val & 0x03;
612 void DISPLAY::set_monitor_bank(uint8_t var)
614 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
615 if((var & 0x04) != 0){
621 subrom_bank = var & 0x03;
624 subcpu_resetreq = false;
625 power_on_reset = true;
626 firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
628 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
630 do_firq(!firq_mask && key_firq_req);
632 subcpu_resetreq = true;
638 void DISPLAY::set_apalette_index_hi(uint8_t val)
640 apalette_index.b.h = val & 0x0f;
644 void DISPLAY::set_apalette_index_lo(uint8_t val)
646 apalette_index.b.l = val;
649 void DISPLAY::calc_apalette(uint16_t idx)
653 g = analog_palette_g[idx];
654 r = analog_palette_r[idx];
655 b = analog_palette_b[idx];
656 if(g != 0) g |= 0x0f;
657 if(r != 0) r |= 0x0f;
658 if(b != 0) b |= 0x0f;
659 analog_palette_pixel[idx] = RGB_COLOR(r, g, b);
663 void DISPLAY::set_apalette_b(uint8_t val)
667 index = apalette_index.w.l;
668 tmp = (val & 0x0f) << 4;
669 if(analog_palette_b[index] != tmp) {
670 analog_palette_b[index] = tmp;
671 calc_apalette(index);
672 palette_changed = true;
677 void DISPLAY::set_apalette_r(uint8_t val)
681 index = apalette_index.w.l;
682 tmp = (val & 0x0f) << 4;
683 if(analog_palette_r[index] != tmp) {
684 analog_palette_r[index] = tmp;
685 calc_apalette(index);
686 palette_changed = true;
691 void DISPLAY::set_apalette_g(uint8_t val)
695 index = apalette_index.w.l;
696 tmp = (val & 0x0f) << 4;
697 if(analog_palette_g[index] != tmp) {
698 analog_palette_g[index] = tmp;
699 calc_apalette(index);
700 palette_changed = true;
704 #endif // _FM77AV_VARIANTS
707 void DISPLAY::copy_vram_blank_area(void)
711 void DISPLAY::copy_vram_per_line(void)
720 uint32_t src_offset_d1;
721 uint32_t src_offset_d2;
722 uint32_t src_offset_d;
727 uint32_t addr_d1, addr_d2;
730 //int dline = (int)displine - 1;
731 int dline = (int)displine;
733 if(dline < 0) return;
734 if(display_mode == DISPLAY_MODE_8_400L) {
735 if(dline >= 400) return;
737 if(dline >= 200) return;
739 #if defined(_FM77AV_VARIANTS)
740 yoff_d1 = offset_point;
741 yoff_d2 = offset_point_bank1;
742 if(display_mode == DISPLAY_MODE_4096) {
743 src_offset = dline * 40;
744 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
747 addr_d1 = (src_offset + yoff_d1) & 0x1fff;
748 addr_d2 = (src_offset + yoff_d2) & 0x1fff;
749 bytes_d1 = 0x2000 - addr_d1;
750 bytes_d2 = 0x2000 - addr_d2;
752 for(k = 0; k < pages; k++) {
753 for(i = 0; i < 3; i++) {
754 for(j = 0; j < 2; j++) {
755 uint32_t _addr_base = src_base + src_offset + poff;
757 memcpy(&gvram_shadow[_addr_base],
758 &gvram[addr_d1 + src_base + poff],
760 memcpy(&gvram_shadow[_addr_base + bytes_d1],
761 &gvram[src_base + poff],
764 memcpy(&gvram_shadow[_addr_base],
765 &gvram[addr_d1 + src_base + poff],
768 _addr_base += 0xc000;
770 memcpy(&gvram_shadow[_addr_base],
771 &gvram[addr_d2 + src_base + poff + 0xc000],
773 memcpy(&gvram_shadow[_addr_base + bytes_d2],
774 &gvram[src_base + poff + 0xc000],
777 memcpy(&gvram_shadow[_addr_base],
778 &gvram[addr_d2 + src_base + poff + 0xc000],
783 src_base = (i + 1) * 0x4000;
787 vram_draw_table[dline] = true;
788 vram_wrote_table[dline] = false;
790 # if defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV40)
791 else if(display_mode == DISPLAY_MODE_256k) {
792 src_offset = dline * 40;
794 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
796 #elif defined(_FM77AV40)
801 src_offset_d1 = (src_offset + yoff_d1) & 0x1fff;
802 src_offset_d2 = (src_offset + yoff_d2) & 0x1fff;
803 bytes_d1 = 0x2000 - ((src_offset + yoff_d1) & 0x1fff);
804 bytes_d2 = 0x2000 - ((src_offset + yoff_d2) & 0x1fff);
805 for(k = 0; k < pages; k++) {
806 for(i = 0; i < 3; i++) {
807 for(j = 0; j < 2; j++) {
809 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
810 src_offset_d = src_offset_d1;
813 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
814 src_offset_d = src_offset_d2;
818 memcpy(&gvram_shadow[src_offset + src_base],
819 &gvram[src_offset_d + src_base],
821 memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
825 memcpy(&gvram_shadow[src_offset + src_base],
826 &gvram[src_offset_d + src_base],
832 vram_draw_table[dline] = true;
833 vram_wrote_table[dline] = false;
835 else if(display_mode == DISPLAY_MODE_8_400L) {
836 src_offset = dline * 80;
837 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
839 # elif defined(_FM77AV40)
842 if(display_page_bak == 1) { // Is this dirty?
847 yoff_d = (yoff_d << 1) & 0x7fff;
848 src_offset_d = (src_offset + yoff_d) & 0x7fff;
849 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
850 for(i = 0; i < pages; i++) {
851 for(j = 0; j < 3; j++) {
852 src_base = i * 0x18000 + j * 0x8000;
854 memcpy(&gvram_shadow[src_offset + src_base],
855 &gvram[src_offset_d + src_base],
857 memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
861 memcpy(&gvram_shadow[src_offset + src_base + poff],
862 &gvram[src_offset_d + src_base],
867 vram_draw_table[dline] = true;
868 vram_wrote_table[dline] = false;
872 src_offset = dline * 80;
873 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
875 #elif defined(_FM77AV40)
877 #elif defined(_FM77AV_VARIANTS)
883 src_offset_d1 = (src_offset + yoff_d1) & 0x3fff;
884 src_offset_d2 = (src_offset + yoff_d2) & 0x3fff;
885 bytes_d1 = 0x4000 - ((src_offset + yoff_d1) & 0x3fff);
886 bytes_d2 = 0x4000 - ((src_offset + yoff_d2) & 0x3fff);
887 for(i = 0; i < pages; i++) {
889 src_offset_d = src_offset_d1;
892 src_offset_d = src_offset_d2;
896 for(j = 0; j < 3; j++) {
898 memcpy(&gvram_shadow[src_offset + src_base + poff],
899 &gvram[src_offset_d + src_base + poff],
901 memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
902 &gvram[src_base + poff],
905 memcpy(&gvram_shadow[src_offset + src_base + poff],
906 &gvram[src_offset_d + src_base + poff],
913 vram_draw_table[dline] = true;
914 vram_wrote_table[dline] = false;
918 src_offset = dline * 80;
921 yoff_d = offset_point;
922 src_offset_d = (src_offset + yoff_d) & 0x3fff;
923 bytes_d = 0x4000 - ((src_offset + yoff_d) & 0x3fff);
924 for(j = 0; j < 3; j++) {
925 src_base = j * 0x4000;
927 memcpy(&gvram_shadow[src_offset + src_base + poff],
928 &gvram[src_offset_d + src_base + poff],
930 memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
931 &gvram[src_base + poff],
934 memcpy(&gvram_shadow[src_offset + src_base + poff],
935 &gvram[src_offset_d + src_base + poff],
939 vram_draw_table[dline] = true;
940 vram_wrote_table[dline] = false;
946 void DISPLAY::copy_vram_all()
948 #if defined(_FM77AV_VARIANTS)
949 uint32_t yoff_d1 = offset_point;
950 uint32_t yoff_d2 = offset_point_bank1;
951 uint32_t src_offset_1, src_offset_2;
953 if(display_mode == DISPLAY_MODE_4096) {
954 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
959 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
960 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
961 for(int k = 0; k < pages; k++) {
962 for(int i = 0; i < 3; i++) {
963 for(int j = 0; j < 2; j++) {
964 src_offset_1 = i * 0x4000 + j * 0x2000;
965 src_offset_2 = src_offset_1 + 0xc000;
966 memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
967 memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
968 memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
969 memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
975 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
976 else if(display_mode == DISPLAY_MODE_256k) {
977 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
978 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
979 for(int i = 0; i < 3; i++) {
980 for(int j = 0; j < 2; j++) {
981 src_offset_1 = i * 0x4000 + j * 0x2000;
982 src_offset_2 = src_offset_1 + 0xc000;
983 memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
984 memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
985 memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
986 memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
990 for(int i = 0; i < 3; i++) {
991 for(int j = 0; j < 2; j++) {
992 src_offset_1 = i * 0x4000 + j * 0x2000;
993 memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
994 memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
997 } else if(display_mode == DISPLAY_MODE_8_400L) {
998 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1006 if(display_page_bak == 1) { // Is this dirty?
1011 yoff_d = (yoff_d << 1) & 0x7fff;
1012 bytes_d = 0x8000 - yoff_d;
1013 for(int k = 0; k < pages; k++) {
1014 for(int i = 0; i < 3; i++) {
1015 src_offset_1 = i * 0x8000;
1016 memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + yoff_d + poff], bytes_d);
1017 memcpy(&gvram_shadow[src_offset_1 + bytes_d + poff], &gvram[src_offset_1 + poff], 0x8000 - bytes_d);
1024 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1026 #elif defined(_FM77AV40)
1031 uint32_t bytes_d1 = 0x4000 - (yoff_d1 & 0x3fff);
1032 uint32_t bytes_d2 = 0x4000 - (yoff_d2 & 0x3fff);
1033 uint32_t yoff_d, bytes_d;
1034 for(int k = 0; k < pages; k++) {
1035 yoff_d = ((k & 1) == 0) ? (yoff_d1 & 0x3fff) : (yoff_d2 & 0x3fff);
1036 bytes_d = ((k & 1) == 0) ? bytes_d1 : bytes_d2;
1037 for(int j = 0; j < 3; j++) {
1038 src_offset_1 = k * 0xc000 + j * 0x4000;
1039 memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1040 memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1046 uint32_t yoff_d = offset_point & 0x3fff;
1047 uint32_t bytes_d = 0x4000 - (offset_point & 0x3fff);
1048 uint32_t src_offset_1;
1049 for(int j = 0; j < 3; j++) {
1050 src_offset_1 = j * 0x4000;
1051 memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1052 memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1058 // Timing values from XM7 . Thanks Ryu.
1059 void DISPLAY::event_callback(int event_id, int err)
1064 case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
1065 #if defined(_FM77AV_VARIANTS)
1075 case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
1078 #if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1079 case EVENT_FM7SUB_HDISP:
1082 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x02, 0xff);
1084 if(display_mode == DISPLAY_MODE_8_400L) {
1085 register_event(this, EVENT_FM7SUB_HDISP, 30.0 + 11.0, true, &hdisp_event_id);
1086 register_event(this, EVENT_FM7SUB_HBLANK, 30.0, false, &hblank_event_id); // NEXT CYCLE_
1088 register_event(this, EVENT_FM7SUB_HDISP, 39.5 + 24.0, true, &hdisp_event_id);
1089 register_event(this, EVENT_FM7SUB_HBLANK, 39.5, false, &hblank_event_id); // NEXT CYCLE_
1092 if(display_mode == DISPLAY_MODE_8_400L) {
1093 if(displine < 400) f = true;
1095 if(displine < 200) f = true;
1098 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
1099 if((vram_wrote_table[displine] || vram_wrote) && need_transfer_line/*|| vram_wrote */) copy_vram_per_line();
1107 case EVENT_FM7SUB_HBLANK:
1109 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1112 if(display_mode == DISPLAY_MODE_8_400L) {
1117 register_event(this, EVENT_FM7SUB_HBLANK, usec, true, &hblank_event_id); // NEXT CYCLE_
1120 if(display_mode == DISPLAY_MODE_8_400L) {
1121 if((displine < 400)) f = true;
1123 if((displine < 200)) f = true;
1125 if(!f && (hdisp_event_id >= 0)) {
1126 cancel_event(this, hdisp_event_id);
1127 cancel_event(this, hblank_event_id);
1128 hdisp_event_id = -1;
1129 hblank_event_id = -1;
1133 case EVENT_FM7SUB_VSTART: // Call first.
1138 display_page_bak = display_page;
1139 // Parameter from XM7/VM/display.c , thanks, Ryu.
1140 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1141 mainio->write_signal(SIG_DISPLAY_VSYNC, 0x00, 0xff);
1142 if(vblank_count != 0) {
1143 if(display_mode == DISPLAY_MODE_8_400L) {
1144 usec = (0.98 + 16.4) * 1000.0;
1146 usec = (1.91 + 12.7) * 1000.0;
1148 register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
1150 if(display_mode == DISPLAY_MODE_8_400L) {
1151 usec = 930.0; // 939.0
1153 usec = 1840.0; // 1846.5
1155 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
1159 if(display_mode == DISPLAY_MODE_8_400L) {
1160 usec = 0.34 * 1000.0;
1162 usec = 1.52 * 1000.0;
1164 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1169 case EVENT_FM7SUB_VSYNC:
1173 write_access_page = (write_access_page + 1) & 1;
1175 if(display_mode == DISPLAY_MODE_8_400L) {
1176 usec = 0.33 * 1000.0;
1178 usec = 0.51 * 1000.0;
1180 mainio->write_signal(SIG_DISPLAY_VSYNC, 0x01, 0xff);
1181 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1182 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1183 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) {
1186 if(need_transfer_line) {
1188 if(display_mode == DISPLAY_MODE_8_400L) lines = 400;
1189 for(int yy = 0; yy < lines; yy++) {
1190 if(vram_wrote_table[yy]) {
1191 vram_wrote_table[yy] = false;
1197 if(need_transfer_line) ff = true;
1200 for(int yy = 0; yy < 400; yy++) vram_draw_table[yy] = true;
1202 vram_wrote_shadow = true;
1203 screen_update_flag = true;
1207 if(need_transfer_line) {
1209 for(int yy = 0; yy < 400; yy++) {
1210 if(!vram_draw_table[yy]) {
1212 copy_vram_per_line();
1219 for(int yy = 0; yy < 400; yy++) {
1220 if(vram_draw_table[yy]) {
1221 vram_wrote_shadow = true;
1222 screen_update_flag = true;
1226 //vram_wrote = false;
1228 frame_skip_count_transfer++;
1230 uint32_t factor = ((config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28) & 3;
1231 if((frame_skip_count_transfer > factor) /* || (vram_wrote) */) {
1232 frame_skip_count_transfer = 0;
1233 need_transfer_line = true;
1235 need_transfer_line = false;
1240 case EVENT_FM7SUB_CLR_BUSY:
1243 case EVENT_FM7SUB_CLR_CRTFLAG:
1249 void DISPLAY::event_frame()
1251 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1254 if(need_transfer_line && vram_wrote) {
1255 for(yy = 0; yy < 400; yy++) {
1256 if(!vram_draw_table[yy]) {
1258 copy_vram_per_line();
1265 for(yy = 0; yy < 400; yy++) {
1266 if(vram_draw_table[yy]) {
1272 screen_update_flag = true;
1273 vram_wrote_shadow = true;
1277 frame_skip_count_transfer++;
1279 uint32_t factor = (config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28;
1280 if(frame_skip_count_transfer > factor) {
1281 frame_skip_count_transfer = 0;
1282 need_transfer_line = true;
1284 need_transfer_line = false;
1286 //vram_wrote = false;
1293 void DISPLAY::event_vline(int v, int clock)
1295 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1296 if(need_transfer_line == false) return;
1298 if(vram_wrote_table[displine] || vram_wrote) {
1299 copy_vram_per_line();
1306 uint32_t DISPLAY::read_signal(int id)
1308 uint32_t retval = 0;
1310 case SIG_FM7_SUB_HALT:
1311 case SIG_DISPLAY_HALT:
1312 retval = (halt_flag) ? 0xffffffff : 0;
1314 case SIG_DISPLAY_BUSY:
1315 retval = (sub_busy) ? 0x80 : 0;
1317 case SIG_DISPLAY_MULTIPAGE:
1318 retval = multimode_accessmask;
1320 case SIG_DISPLAY_PLANES:
1323 #if defined(_FM77AV_VARIANTS)
1324 case SIG_DISPLAY_VSYNC:
1325 retval = (vsync) ? 0x01 : 0x00;
1327 case SIG_DISPLAY_DISPLAY:
1328 retval = (!hblank) ? 0x02: 0x00;
1330 case SIG_FM7_SUB_BANK: // Main: FD13
1331 retval = subrom_bank & 0x03;
1332 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1333 if(monitor_ram) retval |= 0x04;
1337 #if defined(_FM77AV_VARIANTS)
1338 case SIG_DISPLAY_MODE320:
1339 retval = (mode320) ? 0x40: 0x00;
1342 case SIG_DISPLAY_Y_HEIGHT:
1343 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1344 retval = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
1349 case SIG_DISPLAY_X_WIDTH:
1350 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1351 retval = (mode320 || mode256k) ? 320 : 640;
1352 #elif defined(_FM77AV_VARIANTS)
1353 retval = (mode320) ? 320 : 640;
1364 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
1366 bool flag = ((data & mask) != 0);
1369 case SIG_FM7_SUB_HALT:
1374 //mainio->write_signal(SIG_FM7_SUB_HALT, data, mask);
1376 case SIG_DISPLAY_HALT:
1380 restart_subsystem();
1383 case SIG_FM7_SUB_CANCEL:
1385 cancel_request = true;
1389 case SIG_DISPLAY_CLOCK:
1393 #if defined(_FM77AV_VARIANTS)
1394 case SIG_FM7_SUB_BANK: // Main: FD13
1395 set_monitor_bank(data & 0xff);
1398 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1399 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1400 //printf("Wrote $FD04: %02x\n", data);
1402 int oldmode = display_mode;
1404 kanjisub = ((data & 0x20) == 0) ? true : false;
1405 mode256k = (((data & 0x10) != 0) && ((data & 0x08) != 0) ) ? true : false;
1406 mode400line = ((data & 0x08) == 0) ? true : false;
1407 ram_protect = ((data & 0x04) == 0) ? true : false;
1408 if(mode400line && !mode320) {
1409 display_mode = DISPLAY_MODE_8_400L;
1410 } else if(mode256k) {
1411 display_mode = DISPLAY_MODE_256k;
1413 display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1415 if(oldmode != display_mode) {
1417 if(mode320 || mode256k) {
1418 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1419 for(y = 0; y < 200; y++) {
1420 pp = emu->get_screen_buffer(y);
1421 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1423 } else if(display_mode == DISPLAY_MODE_8_400L) {
1424 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1425 for(y = 0; y < 400; y++) {
1426 pp = emu->get_screen_buffer(y);
1427 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1430 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1431 for(y = 0; y < 200; y++) {
1432 pp = emu->get_screen_buffer(y);
1433 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1437 alu->write_signal(SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
1438 alu->write_signal(SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200, 0xffff);
1439 alu->write_signal(SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xff : 0x00, 0xff);
1440 frame_skip_count_draw = 3;
1441 frame_skip_count_transfer = 3;
1444 #elif defined(_FM77_VARIANTS)
1446 int oldmode = display_mode;
1447 kanjisub = ((data & 0x20) == 0) ? true : false;
1448 # if defined(_FM77L4)
1449 stat_400linecard = ((data & 0x20) != 0) ? true : false;
1450 mode400line = ((data & 0x08) != 0) ? false : true;
1451 if(mode400line && stat_400linecard) {
1452 display_mode = DISPLAY_MODE_8_400L_TEXT;
1453 } else if(stat_400linecard) {
1454 display_mode = DISPLAY_MODE_8_200L_TEXT;
1456 display_mode = DISPLAY_MODE_8_200L;
1462 #if defined(_FM77AV_VARIANTS)
1463 case SIG_DISPLAY_MODE320: // FD12 bit 6
1464 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1466 //printf("Wrote $FD12: %02x\n", data);
1467 int oldmode = display_mode;
1469 if(!mode320 && !mode256k) {
1470 //display_mode = (mode400line) ? DISPLAY_MODE_8_400L : DISPLAY_MODE_8_200L;
1471 display_mode = DISPLAY_MODE_8_200L;
1473 display_mode = (mode256k) ? DISPLAY_MODE_256k : DISPLAY_MODE_4096;
1475 if(oldmode != display_mode) {
1477 if(mode320 || mode256k) {
1478 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1479 for(y = 0; y < 200; y++) {
1480 pp = emu->get_screen_buffer(y);
1481 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1483 } else { // 200 lines, 8 colors.
1484 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1485 for(y = 0; y < 200; y++) {
1486 pp = emu->get_screen_buffer(y);
1487 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1491 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
1492 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
1493 alu->write_signal(SIG_ALU_400LINE, 0x00, 0xff);
1494 //frame_skip_count = 3;
1502 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1503 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 320 * sizeof(scrntype_t));
1505 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1506 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
1509 display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1510 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
1511 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
1512 alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
1517 case SIG_DISPLAY_MULTIPAGE:
1518 set_multimode(data);
1520 case SIG_FM7_SUB_KEY_MASK:
1521 if(firq_mask == flag) {
1522 do_firq(!flag && key_firq_req);
1526 case SIG_FM7_SUB_KEY_FIRQ:
1527 do_firq(flag & !(firq_mask));
1528 key_firq_req = flag;
1530 case SIG_FM7_SUB_USE_CLR:
1532 clr_count = data & 0x03;
1543 * Vram accessing functions moved to vram.cpp .
1546 uint32_t DISPLAY::read_mmio(uint32_t addr)
1548 uint32_t retval = 0xff;
1550 if(addr < 0xd400) return 0xff;
1552 #if !defined(_FM77AV_VARIANTS)
1553 raddr = (addr - 0xd400) & 0x000f;
1554 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
1555 raddr = (addr - 0xd400) & 0x003f;
1556 #else // FM77AV40EX || FM77AV40SX
1557 raddr = (addr - 0xd400) & 0x00ff;
1560 case 0x00: // Read keyboard
1561 retval = (keyboard->read_data8(0x00) != 0) ? 0xff : 0x7f;
1563 case 0x01: // Read keyboard
1564 retval = keyboard->read_data8(0x01) & 0xff;
1566 case 0x02: // Acknowledge
1575 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1576 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
1578 if(!kanjisub) return 0xff;
1579 # if !defined(_FM77_VARIANTS)
1581 return (uint8_t)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1584 if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1587 if(!kanjisub) return 0xff;
1588 # if !defined(_FM77_VARIANTS)
1590 return (uint8_t)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1593 if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1600 retval = set_vramaccess();
1606 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
1608 #if defined(_FM77AV_VARIANTS)
1611 retval = alu->read_data8(ALU_CMDREG);
1614 retval = alu->read_data8(ALU_LOGICAL_COLOR);
1617 retval = alu->read_data8(ALU_WRITE_MASKREG);
1620 retval = alu->read_data8(ALU_CMP_STATUS_REG);
1623 retval = alu->read_data8(ALU_BANK_DISABLE);
1625 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1626 case 0x2f: // VRAM BANK
1627 retval = 0xfc | (vram_bank & 0x03);
1632 retval = get_miscreg();
1636 retval = keyboard->read_data8(0x31);
1639 retval = keyboard->read_data8(0x32);
1645 return (uint8_t)retval;
1648 uint32_t DISPLAY::read_vram_data8(uint32_t addr)
1651 uint32_t page_offset = 0;
1652 uint32_t page_mask = 0x3fff;
1653 uint32_t color = (addr >> 14) & 0x03;
1656 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1657 if(display_mode == DISPLAY_MODE_8_400L) {
1658 color = vram_bank & 0x03;
1659 if(color > 2) color = 0;
1661 color = (addr >> 14) & 0x03;
1665 if((multimode_accessmask & (1 << color)) != 0) return 0xff;
1667 #if defined(_FM77AV_VARIANTS)
1668 if (active_page != 0) {
1669 offset = offset_point_bank1;
1671 offset = offset_point;
1674 offset = offset_point;
1677 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1678 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1679 if(vram_active_block != 0) page_offset = 0x18000;
1681 if(display_mode == DISPLAY_MODE_8_400L) {
1682 if(addr >= 0x8000) return 0xff;
1683 color = vram_bank & 0x03;
1684 if(color > 2) color = 0;
1686 pagemod = 0x8000 * color;
1687 return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
1690 #if defined(_FM77AV40)
1692 page_offset = 0xc000 * (vram_bank & 0x03);
1694 page_offset = 0; // right?
1697 page_offset = 0xc000 * (vram_bank & 0x03);
1700 pagemod = addr & 0xe000;
1704 pagemod = addr & 0xe000;
1706 pagemod = addr & 0xc000;
1708 if(active_page != 0) {
1709 page_offset += 0xc000;
1712 return gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1714 #elif defined(_FM77AV_VARIANTS)
1716 if(active_page != 0) {
1717 page_offset += 0xc000;
1721 pagemod = addr & 0xe000;
1723 pagemod = addr & 0xc000;
1725 return gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1727 #elif defined(_FM77L4) //_FM77L4
1729 if(display_mode == DISPLAY_MODE_8_400L) {
1730 return (uint32_t)read_vram_l4_400l(addr, offset);
1732 pagemod = addr & 0xc000;
1733 return gvram[((addr + offset) & 0x3fff) | pagemod];
1737 #else // Others (77/7/8)
1738 pagemod = addr & 0xc000;
1739 return gvram[((addr + offset) & 0x3fff) | pagemod];
1743 void DISPLAY::write_dma_data8(uint32_t addr, uint32_t data)
1745 uint32_t raddr = (addr & 0xffff) >> 7;
1746 if(write_dma_func_table[raddr] != NULL) {
1747 (this->*write_dma_func_table[raddr])(addr, (uint8_t) data);
1751 void DISPLAY::write_vram_data8(uint32_t addr, uint8_t data)
1754 uint32_t page_offset = 0;
1755 uint32_t page_mask = 0x3fff;
1756 uint32_t color = (addr >> 14) & 0x03;
1760 #if defined(_FM77AV_VARIANTS)
1761 if (active_page != 0) {
1762 offset = offset_point_bank1;
1764 offset = offset_point;
1767 offset = offset_point;
1770 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1771 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1772 if(vram_active_block != 0) page_offset = 0x18000;
1774 if(display_mode == DISPLAY_MODE_8_400L) {
1775 if(addr >= 0x8000) {
1778 color = vram_bank & 0x03;
1779 if(color > 2) color = 0;
1781 pagemod = 0x8000 * color;
1782 // Reduce data transfer.
1783 tdata = gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
1785 gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset] = data;
1786 vram_wrote_table[(addr & 0x7fff) / 80] = true;
1788 } else if(display_mode == DISPLAY_MODE_256k) {
1789 #if defined(_FM77AV40)
1791 page_offset = 0xc000 * (vram_bank & 0x03);
1793 page_offset = 0; // right?
1796 page_offset = 0xc000 * (vram_bank & 0x03);
1799 pagemod = addr & 0xe000;
1800 tdata = gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1802 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1803 vram_wrote_table[(addr & page_mask) / 40] = true;
1806 } else if(display_mode == DISPLAY_MODE_4096) {
1807 if(active_page != 0) {
1808 page_offset += 0xc000;
1811 pagemod = addr & 0xe000;
1812 tdata = gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1814 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1815 vram_wrote_table[(addr & page_mask) / 40] = true;
1818 if(active_page != 0) {
1819 page_offset += 0xc000;
1822 pagemod = addr & 0xc000;
1823 tdata = gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1825 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1826 vram_wrote_table[(addr & page_mask) / 80] = true;
1829 #elif defined(_FM77AV_VARIANTS)
1830 if(display_mode == DISPLAY_MODE_4096) {
1831 if(active_page != 0) {
1832 page_offset = 0xc000;
1835 pagemod = addr & 0xe000;
1836 tdata = gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1838 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1839 vram_wrote_table[(addr & page_mask) / 40] = true;
1842 if(active_page != 0) {
1843 page_offset = 0xc000;
1846 pagemod = addr & 0xc000;
1847 tdata = gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1849 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1850 vram_wrote_table[(addr & page_mask) / 80] = true;
1853 #elif defined(_FM77L4) //_FM77L4
1855 if(display_mode == DISPLAY_MODE_8_400L) {
1856 write_vram_l4_400l(addr, data, offset);
1858 pagemod = addr & 0xc000;
1859 tdata = gvram[((addr + offset) & 0x3fff) | pagemod];
1861 gvram[((addr + offset) & 0x3fff) | pagemod] = data;
1862 vram_wrote_table[(addr & 0x3fff) / 80] = true;
1866 #else // Others (77/7/8)
1867 pagemod = addr & 0xc000;
1868 tdata = gvram[((addr + offset) & 0x3fff) | pagemod];
1870 gvram[((addr + offset) & 0x3fff) | pagemod] = data;
1871 vram_wrote_table[(addr & 0x3fff) / 80] = true;
1876 uint32_t DISPLAY::read_cpu_vram_data8(uint32_t addr)
1879 #if defined(_FM77AV_VARIANTS)
1881 alu->read_data8(addr + ALU_WRITE_PROXY);
1884 return read_vram_data8(addr);
1887 uint32_t DISPLAY::read_dma_vram_data8(uint32_t addr)
1889 return read_vram_data8(addr);
1892 void DISPLAY::init_read_table(void)
1895 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
1896 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cpu_vram_data8;
1897 read_dma_func_table[_at >> 7] = &DISPLAY::read_dma_vram_data8;
1899 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
1900 read_cpu_func_table[_at >> 7] = &DISPLAY::read_console_ram;
1901 read_dma_func_table[_at >> 7] = &DISPLAY::read_console_ram;
1903 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
1904 read_cpu_func_table[_at >> 7] = &DISPLAY::read_work_ram;
1905 read_dma_func_table[_at >> 7] = &DISPLAY::read_work_ram;
1907 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
1908 read_cpu_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
1909 read_dma_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
1911 #if defined(_FM77AV_VARIANTS)
1912 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
1913 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
1914 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
1916 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
1917 read_cpu_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
1918 read_dma_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
1921 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
1922 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
1923 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
1926 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
1927 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cgrom;
1928 read_dma_func_table[_at >> 7] = &DISPLAY::read_cgrom;
1930 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
1931 read_cpu_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
1932 read_dma_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
1936 uint32_t DISPLAY::read_console_ram(uint32_t addr)
1938 uint32_t raddr = addr & 0xfff;
1939 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1941 if(console_ram_bank >= 1) {
1942 return submem_console_av40[((console_ram_bank - 1) << 12) + raddr];
1946 return console_ram[raddr];
1949 uint32_t DISPLAY::read_work_ram(uint32_t addr)
1951 addr = addr & 0x3ff;
1952 return work_ram[addr];
1956 uint32_t DISPLAY::read_shared_ram(uint32_t addr)
1958 addr = addr - 0xd380;
1959 return shared_ram[addr];
1962 #if defined(_FM77AV_VARIANTS)
1963 uint32_t DISPLAY::read_hidden_ram(uint32_t addr)
1965 if(addr >= 0xd500) {
1966 return submem_hidden[addr - 0xd500];
1971 uint32_t DISPLAY::read_cgrom(uint32_t addr)
1973 #if defined(_FM77AV_VARIANTS)
1974 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
1976 return submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)]; //FIXME
1979 return subsys_cg[(addr - 0xd800) + cgrom_bank * 0x800];
1981 return subsys_c[addr - 0xd800];
1985 uint32_t DISPLAY::read_subsys_monitor(uint32_t addr)
1987 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
1989 return subsys_ram[addr - 0xe000];
1992 #if defined(_FM77AV_VARIANTS)
1993 switch(subrom_bank_using & 3) {
1995 return subsys_c[addr - 0xd800];
1998 return subsys_a[addr - 0xe000];
2001 return subsys_b[addr - 0xe000];
2004 return subsys_cg[addr - 0xe000];
2008 return subsys_c[addr - 0xd800];
2012 uint32_t DISPLAY::read_dma_data8(uint32_t addr)
2014 uint32_t raddr = (addr & 0xffff) >> 7;
2015 if(read_dma_func_table[raddr] != NULL) {
2016 return (this->*read_dma_func_table[raddr])(addr);
2021 uint32_t DISPLAY::read_data8(uint32_t addr)
2023 uint32_t raddr = addr;
2025 if(addr < 0x10000) {
2026 raddr = (addr & 0xffff) >> 7;
2027 if(read_cpu_func_table[raddr] != NULL) {
2028 return (this->*read_cpu_func_table[raddr])(addr);
2033 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2034 return dpalette_data[addr - FM7_SUBMEM_OFFSET_DPALETTE];
2037 #if defined(_FM77AV_VARIANTS)
2039 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2040 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2041 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2042 if(display_mode == DISPLAY_MODE_8_400L) {
2043 uint32_t page_offset = 0;
2044 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2045 if(vram_active_block != 0) page_offset = 0x18000;
2047 uint32_t color = (addr & 0x0c000) >> 14;
2048 color = (addr & 0x18000) >> 15;
2049 if(color > 2) color = 0;
2051 if (active_page != 0) {
2052 offset = offset_point_bank1 << 1;
2054 offset = offset_point << 1;
2056 if(color > 2) color = 0;
2057 uint32_t pagemod = 0x8000 * color;
2058 return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
2061 return read_vram_data8(addr);
2068 * Vram accessing functions moved to vram.cpp .
2071 void DISPLAY::write_mmio(uint32_t addr, uint8_t data)
2075 if(addr < 0xd400) return;
2077 #if !defined(_FM77AV_VARIANTS)
2078 addr = (addr - 0xd400) & 0x000f;
2079 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2080 addr = (addr - 0xd400) & 0x003f;
2081 #else // FM77AV40EX || FM77AV40SX
2082 addr = (addr - 0xd400) & 0x00ff;
2084 io_w_latch[addr] = (uint8_t)data;
2086 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4)
2089 set_cyclesteal((uint8_t)data);
2092 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2093 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2096 if(!kanjisub) return;
2097 kanjiaddr.w.h = 0x0000;
2098 kanjiaddr.b.h = (uint8_t) data;
2101 if(!kanjisub) return;
2102 kanjiaddr.w.h = 0x0000;
2103 kanjiaddr.b.l = (uint8_t)data;
2116 if(clr_count <= 0) {
2118 } else { // Read once when using clr_foo() to set busy flag.
2121 usec = (1000.0 * 1000.0) / 2000000.0;
2123 usec = (1000.0 * 1000.0) / 999000.0;
2125 if(!is_cyclesteal && vram_accessflag) usec = usec * 3.0;
2126 usec = (double)clr_count * usec;
2127 register_event(this, EVENT_FM7SUB_CLR_BUSY, usec, false, NULL); // NEXT CYCLE_
2134 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
2139 rval = (uint8_t)data;
2140 if(offset_changed[active_page]) {
2141 #if defined(_FM77AV_VARIANTS)
2142 if(active_page != 0) {
2143 tmp_offset_point[active_page].d = offset_point_bank1;
2145 tmp_offset_point[active_page].d = offset_point;
2148 tmp_offset_point[active_page].d = offset_point;
2151 tmp_offset_point[active_page].w.h = 0x0000;
2153 tmp_offset_point[active_page].b.h = rval;
2155 tmp_offset_point[active_page].b.l = rval;
2157 offset_changed[active_page] = !offset_changed[active_page];
2158 if(offset_changed[active_page]) {
2160 #if defined(_FM77AV_VARIANTS)
2161 if(active_page != 0) {
2163 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fff;
2165 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fe0;
2169 offset_point = tmp_offset_point[active_page].d & 0x007fff;
2171 offset_point = tmp_offset_point[active_page].d & 0x007fe0;
2175 offset_point = tmp_offset_point[active_page].d & 0x7fe0;
2179 #if defined(_FM77AV_VARIANTS)
2182 alu_write_cmdreg(data);
2185 alu_write_logical_color(data);
2188 alu_write_mask_reg(data);
2191 alu_write_disable_reg(data);
2194 alu_write_offsetreg_hi(data);
2197 alu_write_offsetreg_lo(data);
2200 alu_write_linepattern_hi(data);
2203 alu_write_linepattern_lo(data);
2205 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2207 console_ram_bank = (data & 0x18) >> 3;
2208 if(console_ram_bank > 2) console_ram_bank = 0;
2209 cgram_bank = data & 0x07;
2210 kanji_level2 = ((data & 0x80) == 0) ? false : true;
2212 case 0x2f: // VRAM BANK
2213 vram_bank = data & 0x03;
2214 if(vram_bank > 2) vram_bank = 0;
2224 keyboard->write_data8(0x31, data);
2226 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2228 vram_active_block = data & 0x01;
2229 if(vram_display_block != (((data & 0x10) != 0) ? 1 : 0)) vram_wrote = true;
2230 vram_display_block = ((data & 0x10) != 0) ? 1 : 0;
2235 tmpvar.d = window_xbegin * 8;
2238 tmpvar.b.h = data & 0x03;
2240 tmpvar.b.l = data & 0xf8;
2242 if(mode320 || mode256k) {
2243 if(tmpvar.d > 320) tmpvar.d = 320;
2245 if(tmpvar.d > 640) tmpvar.d = 640;
2247 window_xbegin = tmpvar.d / 8;
2252 tmpvar.d = window_xend * 8;
2255 tmpvar.b.h = data & 0x03;
2257 tmpvar.b.l = data & 0xf8;
2259 if(mode320 || mode256k) {
2260 if(tmpvar.d > 320) tmpvar.d = 320;
2262 if(tmpvar.d > 640) tmpvar.d = 640;
2264 window_xend = tmpvar.d / 8;
2269 tmpvar.d = window_low;
2272 tmpvar.b.h = data & 0x03;
2274 tmpvar.b.l = data & 0xff;
2276 if(display_mode == DISPLAY_MODE_8_400L) {
2277 if(tmpvar.d > 400) tmpvar.d = 400;
2280 if(tmpvar.d > 400) tmpvar.d = 400;
2282 window_low = tmpvar.d;
2287 tmpvar.d = window_high;
2290 tmpvar.b.h = data & 0x03;
2292 tmpvar.b.l = data & 0xff;
2294 if(display_mode == DISPLAY_MODE_8_400L) {
2295 if(tmpvar.d > 400) tmpvar.d = 400;
2298 if(tmpvar.d > 400) tmpvar.d = 400;
2300 window_high = tmpvar.d;
2306 #if defined(_FM77AV_VARIANTS)
2308 if((addr >= 0x13) && (addr <= 0x1a)) {
2309 alu_write_cmpdata_reg(addr - 0x13, data);
2310 } else if((addr >= 0x1c) && (addr <= 0x1e)) {
2311 alu_write_tilepaint_data(addr, data);
2312 } else if((addr >= 0x24) && (addr <= 0x2b)) {
2313 alu_write_line_position(addr - 0x24, data);
2320 void DISPLAY::init_write_table(void)
2323 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
2324 write_cpu_func_table[_at >> 7] = &DISPLAY::write_cpu_vram_data8;
2325 write_dma_func_table[_at >> 7] = &DISPLAY::write_dma_vram_data8;
2327 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
2328 write_cpu_func_table[_at >> 7] = &DISPLAY::write_console_ram;
2329 write_dma_func_table[_at >> 7] = &DISPLAY::write_console_ram;
2331 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
2332 write_cpu_func_table[_at >> 7] = &DISPLAY::write_work_ram;
2333 write_dma_func_table[_at >> 7] = &DISPLAY::write_work_ram;
2335 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
2336 write_cpu_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
2337 write_dma_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
2339 #if defined(_FM77AV_VARIANTS)
2340 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
2341 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
2342 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
2344 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
2345 write_cpu_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
2346 write_dma_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
2349 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
2350 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
2351 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
2354 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2355 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
2356 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
2357 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
2359 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
2360 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
2361 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
2364 for(_at = 0xd800; _at < 0x10000; _at += 0x80) {
2365 write_cpu_func_table[_at >> 7] = &DISPLAY::write_dummy;
2366 write_dma_func_table[_at >> 7] = &DISPLAY::write_dummy;
2371 void DISPLAY::write_console_ram(uint32_t addr, uint8_t data)
2373 uint32_t raddr = addr & 0xfff;
2374 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2376 if(console_ram_bank >= 1) {
2377 submem_console_av40[((console_ram_bank - 1) << 12) + raddr] = data;
2382 console_ram[raddr] = data;
2386 void DISPLAY::write_work_ram(uint32_t addr, uint8_t data)
2388 uint32_t raddr = addr & 0xfff;
2389 work_ram[raddr] = data;
2393 void DISPLAY::write_shared_ram(uint32_t addr, uint8_t data)
2395 uint32_t raddr = addr & 0x7f;
2396 shared_ram[raddr] = data;
2400 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2401 void DISPLAY::write_subsys_cgram(uint32_t addr, uint8_t data)
2403 uint32_t raddr = addr - 0xd800;
2404 if(ram_protect) return;
2405 if(!monitor_ram) return;
2406 submem_cgram[cgram_bank * 0x0800 + raddr] = data; //FIXME
2409 void DISPLAY::write_subsys_ram(uint32_t addr, uint8_t data)
2411 if(ram_protect) return;
2412 if(!monitor_ram) return;
2413 subsys_ram[addr - 0xe000] = data; //FIXME
2417 #if defined(_FM77AV_VARIANTS)
2418 void DISPLAY::write_hidden_ram(uint32_t addr, uint8_t data)
2420 submem_hidden[addr - 0xd500] = data;
2425 void DISPLAY::write_cpu_vram_data8(uint32_t addr, uint8_t data)
2427 uint32_t color = (addr & 0xc000) >> 14;
2428 #if defined(_FM77AV_VARIANTS)
2430 alu->read_data8(addr + ALU_WRITE_PROXY);
2434 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2435 if(display_mode == DISPLAY_MODE_8_400L) {
2436 color = vram_bank & 0x03;
2437 if(color > 2) color = 0;
2441 if((multimode_accessmask & (1 << color)) != 0) return;
2443 write_vram_data8(addr & 0xffff, data);
2446 void DISPLAY::write_dma_vram_data8(uint32_t addr, uint8_t data)
2448 uint32_t color = (addr & 0xc000) >> 14;
2449 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2450 if(display_mode == DISPLAY_MODE_8_400L) {
2451 color = vram_bank & 0x03;
2452 if(color > 2) color = 0;
2456 if((multimode_accessmask & (1 << color)) != 0) return;
2458 write_vram_data8(addr & 0xffff, data);
2461 void DISPLAY::write_dummy(uint32_t addr, uint8_t data)
2465 void DISPLAY::write_data8(uint32_t addr, uint32_t data)
2469 uint32_t page_offset = 0x0000;
2470 uint8_t val8 = data & 0xff;
2472 uint32_t color = (addr & 0xc000) >> 14;
2475 if(addr < 0x10000) {
2476 void (*_write_func)(uint32_t, uint32_t);
2477 raddr = (addr & 0xffff) >> 7;
2478 if(write_cpu_func_table[raddr] != NULL) {
2479 (this->*write_cpu_func_table[raddr])(addr, (uint8_t)data);
2485 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2486 set_dpalette(addr - FM7_SUBMEM_OFFSET_DPALETTE, val8);
2490 #if defined(_FM77AV_VARIANTS)
2492 else if(addr == FM7_SUBMEM_OFFSET_APALETTE_R) {
2493 set_apalette_r(val8);
2495 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_G) {
2496 set_apalette_g(val8);
2498 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_B) {
2499 set_apalette_b(val8);
2501 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_HI) {
2502 set_apalette_index_hi(val8);
2504 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_LO) {
2505 set_apalette_index_lo(val8);
2509 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2510 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2511 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2512 if(display_mode == DISPLAY_MODE_8_400L) {
2513 color = (addr & 0x18000) >> 15;
2514 if(color > 2) color = 0;
2516 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2517 if(vram_active_block != 0) page_offset = 0x18000;
2519 if(color > 2) color = 0;
2520 if (active_page != 0) {
2521 offset = offset_point_bank1 << 1;
2523 offset = offset_point << 1;
2525 pagemod = 0x8000 * color;
2526 tdata = gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
2527 if(tdata != (uint8_t)data) {
2528 gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset] = data;
2529 vram_wrote_table[(addr & 0x7fff) / 80] = true;
2533 write_vram_data8(addr, data);
2535 write_vram_data8(addr, data);
2537 //if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
2544 uint32_t DISPLAY::read_bios(const _TCHAR *name, uint8_t *ptr, uint32_t size)
2550 if((name == NULL) || (ptr == NULL)) return 0;
2551 s = create_local_path(name);
2552 if(s == NULL) return 0;
2554 if(!fio.Fopen(s, FILEIO_READ_BINARY)) return 0;
2555 blocks = fio.Fread(ptr, size, 1);
2558 return blocks * size;
2562 void DISPLAY::initialize()
2566 screen_update_flag = true;
2567 memset(gvram, 0x00, sizeof(gvram));
2568 vram_wrote_shadow = false;
2569 memset(gvram_shadow, 0x00, sizeof(gvram_shadow));
2570 for(i = 0; i < 411; i++) vram_wrote_table[i] = false;
2571 for(i = 0; i < 411; i++) vram_draw_table[i] = false;
2573 memset(console_ram, 0x00, sizeof(console_ram));
2574 memset(work_ram, 0x00, sizeof(work_ram));
2575 memset(shared_ram, 0x00, sizeof(shared_ram));
2576 memset(subsys_c, 0xff, sizeof(subsys_c));
2577 need_transfer_line = true;
2578 frame_skip_count_draw = 3;
2579 frame_skip_count_transfer = 3;
2581 diag_load_subrom_c = false;
2583 if(read_bios(_T("SUBSYS_8.ROM"), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2584 this->out_debug_log(_T("SUBSYSTEM ROM READING : %s"), diag_load_subrom_c ? "OK" : "NG");
2586 if(read_bios(_T("SUBSYS_C.ROM"), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2587 this->out_debug_log(_T("SUBSYSTEM ROM Type C READING : %s"), diag_load_subrom_c ? "OK" : "NG");
2589 #if defined(_FM77AV_VARIANTS)
2590 memset(subsys_a, 0xff, sizeof(subsys_a));
2591 memset(subsys_b, 0xff, sizeof(subsys_b));
2592 memset(subsys_cg, 0xff, sizeof(subsys_cg));
2593 memset(submem_hidden, 0x00, sizeof(submem_hidden));
2595 diag_load_subrom_a = false;
2596 if(read_bios(_T("SUBSYS_A.ROM"), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
2597 this->out_debug_log(_T("SUBSYSTEM ROM Type A READING : %s"), diag_load_subrom_a ? "OK" : "NG");
2599 diag_load_subrom_b = false;
2600 if(read_bios(_T("SUBSYS_B.ROM"), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
2601 this->out_debug_log(_T("SUBSYSTEM ROM Type B READING : %s"), diag_load_subrom_b ? "OK" : "NG");
2603 diag_load_subrom_cg = false;
2604 if(read_bios(_T("SUBSYSCG.ROM"), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
2605 this->out_debug_log(_T("SUBSYSTEM CG ROM READING : %s"), diag_load_subrom_cg ? "OK" : "NG");
2606 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2607 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2608 memset(subsys_ram, 0x00, sizeof(subsys_ram));
2609 memset(submem_cgram, 0x00, sizeof(submem_cgram));
2610 memset(submem_console_av40, 0x00, sizeof(submem_console_av40));
2617 #if defined(_FM77AV_VARIANTS)
2619 apalette_index.d = 0;
2620 for(i = 0; i < 4096; i++) {
2621 analog_palette_r[i] = i & 0x0f0;
2622 analog_palette_g[i] = (i & 0xf00) >> 4;
2623 analog_palette_b[i] = (i & 0x00f) << 4;
2627 #if defined(_FM77AV_VARIANTS)
2628 hblank_event_id = -1;
2629 hdisp_event_id = -1;
2630 vsync_event_id = -1;
2631 vstart_event_id = -1;
2638 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
2639 is_cyclesteal = true;
2641 is_cyclesteal = false;
2643 // emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2644 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2648 key_firq_req = false; //firq_mask = true;
2649 frame_skip_count_transfer = 3;
2650 frame_skip_count_draw = 3;
2651 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2652 palette_changed = true;
2653 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
2654 //register_vline_event(this);
2655 //register_frame_event(this);
2659 void DISPLAY::release()
2663 #define STATE_VERSION 8
2664 void DISPLAY::save_state(FILEIO *state_fio)
2666 state_fio->FputUint32_BE(STATE_VERSION);
2667 state_fio->FputInt32_BE(this_device_id);
2668 this->out_debug_log("Save State: DISPLAY : id=%d ver=%d\n", this_device_id, STATE_VERSION);
2672 state_fio->FputInt32_BE(clr_count);
2673 state_fio->FputBool(halt_flag);
2674 state_fio->FputInt32_BE(active_page);
2675 state_fio->FputBool(sub_busy);
2676 state_fio->FputBool(crt_flag);
2677 state_fio->FputBool(vram_wrote);
2678 state_fio->FputBool(is_cyclesteal);
2680 state_fio->FputBool(clock_fast);
2682 #if defined(_FM77AV_VARIANTS)
2683 state_fio->FputBool(subcpu_resetreq);
2684 state_fio->FputBool(power_on_reset);
2686 state_fio->FputBool(cancel_request);
2687 state_fio->FputBool(key_firq_req);
2689 state_fio->FputInt32_BE(display_mode);
2690 state_fio->FputUint32_BE(prev_clock);
2693 state_fio->Fwrite(dpalette_data, sizeof(dpalette_data), 1);
2694 state_fio->FputUint8(multimode_accessmask);
2695 state_fio->FputUint8(multimode_dispmask);
2697 state_fio->FputUint32_BE(offset_point);
2698 #if defined(_FM77AV_VARIANTS)
2699 state_fio->FputUint32_BE(offset_point_bank1);
2701 for(i = 0; i < 2; i++) {
2702 state_fio->FputUint32_BE(tmp_offset_point[i].d);
2703 state_fio->FputBool(offset_changed[i]);
2705 state_fio->FputBool(offset_77av);
2706 state_fio->FputBool(diag_load_subrom_c);
2709 state_fio->Fwrite(io_w_latch, sizeof(io_w_latch), 1);
2710 state_fio->Fwrite(console_ram, sizeof(console_ram), 1);
2711 state_fio->Fwrite(work_ram, sizeof(work_ram), 1);
2712 state_fio->Fwrite(shared_ram, sizeof(shared_ram), 1);
2713 state_fio->Fwrite(subsys_c, sizeof(subsys_c), 1);
2714 state_fio->Fwrite(gvram, sizeof(gvram), 1);
2715 state_fio->Fwrite(gvram_shadow, sizeof(gvram_shadow), 1);
2717 #if defined(_FM77_VARIANTS)
2718 state_fio->FputBool(kanjisub);
2719 state_fio->FputUint16_BE(kanjiaddr.w.l);
2720 # if defined(_FM77L4)
2721 state_fio->FputBool(mode400line);
2722 state_fio->FputBool(stat_400linecard);
2724 #elif defined(_FM77AV_VARIANTS)
2725 state_fio->FputBool(kanjisub);
2726 state_fio->FputUint16_BE(kanjiaddr.w.l);
2728 state_fio->FputBool(vblank);
2729 state_fio->FputBool(vsync);
2730 state_fio->FputBool(hblank);
2731 state_fio->FputInt32_BE(vblank_count);
2733 state_fio->FputBool(mode320);
2734 state_fio->FputInt8(display_page);
2735 state_fio->FputInt8(display_page_bak);
2736 state_fio->FputInt32_BE(cgrom_bank);
2737 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
2738 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2739 state_fio->FputInt32_BE(vram_bank);
2742 state_fio->FputUint32_BE(displine);
2743 state_fio->FputUint8(subrom_bank);
2744 state_fio->FputUint8(subrom_bank_using);
2746 state_fio->FputBool(nmi_enable);
2747 state_fio->FputBool(use_alu);
2749 state_fio->FputUint8(apalette_index.b.l);
2750 state_fio->FputUint8(apalette_index.b.h);
2751 state_fio->Fwrite(analog_palette_r, sizeof(analog_palette_r), 1);
2752 state_fio->Fwrite(analog_palette_g, sizeof(analog_palette_g), 1);
2753 state_fio->Fwrite(analog_palette_b, sizeof(analog_palette_b), 1);
2756 state_fio->FputBool(diag_load_subrom_a);
2757 state_fio->FputBool(diag_load_subrom_b);
2758 state_fio->FputBool(diag_load_subrom_cg);
2760 state_fio->Fwrite(subsys_a, sizeof(subsys_a), 1);
2761 state_fio->Fwrite(subsys_b, sizeof(subsys_b), 1);
2762 state_fio->Fwrite(subsys_cg, sizeof(subsys_cg), 1);
2763 state_fio->Fwrite(submem_hidden, sizeof(submem_hidden), 1);
2764 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2765 state_fio->FputBool(mode400line);
2766 state_fio->FputBool(mode256k);
2768 state_fio->FputBool(monitor_ram);
2769 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2770 state_fio->FputUint16_BE(window_low);
2771 state_fio->FputUint16_BE(window_high);
2772 state_fio->FputUint16_BE(window_xbegin);
2773 state_fio->FputUint16_BE(window_xend);
2774 state_fio->FputBool(window_opened);
2776 state_fio->FputBool(kanji_level2);
2778 state_fio->FputUint8(vram_active_block);
2779 state_fio->FputUint8(vram_display_block);
2780 state_fio->FputUint8(console_ram_bank);
2781 state_fio->FputBool(ram_protect);
2783 state_fio->FputUint32_BE(cgram_bank);
2784 state_fio->Fwrite(subsys_ram, sizeof(subsys_ram), 1);
2785 state_fio->Fwrite(submem_cgram, sizeof(submem_cgram), 1);
2786 state_fio->Fwrite(submem_console_av40, sizeof(submem_console_av40), 1);
2792 state_fio->FputInt32_BE(nmi_event_id);
2793 #if defined(_FM77AV_VARIANTS)
2794 state_fio->FputInt32_BE(hblank_event_id);
2795 state_fio->FputInt32_BE(hdisp_event_id);
2796 state_fio->FputInt32_BE(vsync_event_id);
2797 state_fio->FputInt32_BE(vstart_event_id);
2799 state_fio->FputBool(firq_mask);
2800 state_fio->FputBool(vram_accessflag);
2804 bool DISPLAY::load_state(FILEIO *state_fio)
2807 uint32_t version = state_fio->FgetUint32_BE();
2808 if(this_device_id != state_fio->FgetInt32_BE()) {
2811 this->out_debug_log("Load State: DISPLAY : id=%d ver=%d\n", this_device_id, version);
2816 clr_count = state_fio->FgetInt32_BE();
2817 halt_flag = state_fio->FgetBool();
2818 active_page = state_fio->FgetInt32_BE();
2819 sub_busy = state_fio->FgetBool();
2820 crt_flag = state_fio->FgetBool();
2821 vram_wrote = state_fio->FgetBool();
2822 crt_flag_bak = true;
2823 for(i = 0; i < 411; i++) vram_wrote_table[i] = true;
2824 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
2825 is_cyclesteal = state_fio->FgetBool();
2827 clock_fast = state_fio->FgetBool();
2829 #if defined(_FM77AV_VARIANTS)
2830 subcpu_resetreq = state_fio->FgetBool();
2831 power_on_reset = state_fio->FgetBool();
2833 cancel_request = state_fio->FgetBool();
2834 key_firq_req = state_fio->FgetBool();
2836 display_mode = state_fio->FgetInt32_BE();
2837 prev_clock = state_fio->FgetUint32_BE();
2840 for(addr = 0; addr < 8; addr++) set_dpalette(addr, addr);
2842 state_fio->Fread(dpalette_data, sizeof(dpalette_data), 1);
2843 for(addr = 0; addr < 8; addr++) set_dpalette(addr, dpalette_data[addr]);
2844 multimode_accessmask = state_fio->FgetUint8();
2845 multimode_dispmask = state_fio->FgetUint8();
2847 offset_point = state_fio->FgetUint32_BE();
2848 #if defined(_FM77AV_VARIANTS)
2849 offset_point_bank1 = state_fio->FgetUint32_BE();
2851 for(i = 0; i < 2; i++) {
2852 tmp_offset_point[i].d = state_fio->FgetUint32_BE();
2853 offset_changed[i] = state_fio->FgetBool();
2855 offset_77av = state_fio->FgetBool();
2856 diag_load_subrom_c = state_fio->FgetBool();
2858 state_fio->Fread(io_w_latch, sizeof(io_w_latch), 1);
2859 state_fio->Fread(console_ram, sizeof(console_ram), 1);
2860 state_fio->Fread(work_ram, sizeof(work_ram), 1);
2861 state_fio->Fread(shared_ram, sizeof(shared_ram), 1);
2862 state_fio->Fread(subsys_c, sizeof(subsys_c), 1);
2863 state_fio->Fread(gvram, sizeof(gvram), 1);
2864 state_fio->Fread(gvram_shadow, sizeof(gvram_shadow), 1);
2865 #if defined(_FM77_VARIANTS)
2866 kanjisub = state_fio->FgetBool();
2868 kanjiaddr.w.l = state_fio->FgetUint16_BE();
2869 # if defined(_FM77L4)
2870 mode400line = state_fio->FgetBool();
2871 stat_400linecard = state_fio->FgetBool();
2873 #elif defined(_FM77AV_VARIANTS)
2874 kanjisub = state_fio->FgetBool();
2876 kanjiaddr.w.l = state_fio->FgetUint16_BE();
2878 vblank = state_fio->FgetBool();
2879 vsync = state_fio->FgetBool();
2880 hblank = state_fio->FgetBool();
2881 vblank_count = state_fio->FgetInt32_BE();
2883 mode320 = state_fio->FgetBool();
2884 display_page = state_fio->FgetInt8();
2885 display_page_bak = state_fio->FgetInt8();
2886 cgrom_bank = state_fio->FgetInt32_BE();
2887 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
2888 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2889 vram_bank = state_fio->FgetInt32_BE();
2891 screen_update_flag = true;
2892 displine = state_fio->FgetUint32_BE();
2893 subrom_bank = state_fio->FgetUint8();
2894 subrom_bank_using = state_fio->FgetUint8();
2896 nmi_enable = state_fio->FgetBool();
2897 use_alu = state_fio->FgetBool();
2899 apalette_index.b.l = state_fio->FgetUint8();
2900 apalette_index.b.h = state_fio->FgetUint8();
2902 state_fio->Fread(analog_palette_r, sizeof(analog_palette_r), 1);
2903 state_fio->Fread(analog_palette_g, sizeof(analog_palette_g), 1);
2904 state_fio->Fread(analog_palette_b, sizeof(analog_palette_b), 1);
2905 for(i = 0; i < 4096; i++) calc_apalette(i);
2907 diag_load_subrom_a = state_fio->FgetBool();
2908 diag_load_subrom_b = state_fio->FgetBool();
2909 diag_load_subrom_cg = state_fio->FgetBool();
2911 state_fio->Fread(subsys_a, sizeof(subsys_a), 1);
2912 state_fio->Fread(subsys_b, sizeof(subsys_b), 1);
2913 state_fio->Fread(subsys_cg, sizeof(subsys_cg), 1);
2914 state_fio->Fread(submem_hidden, sizeof(submem_hidden), 1);
2916 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2917 mode400line = state_fio->FgetBool();
2918 mode256k = state_fio->FgetBool();
2920 monitor_ram = state_fio->FgetBool();
2921 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2922 window_low = state_fio->FgetUint16_BE();
2923 window_high = state_fio->FgetUint16_BE();
2924 window_xbegin = state_fio->FgetUint16_BE();
2925 window_xend = state_fio->FgetUint16_BE();
2926 window_opened = state_fio->FgetBool();
2928 kanji_level2 = state_fio->FgetBool();
2930 vram_active_block = state_fio->FgetUint8();
2931 vram_display_block = state_fio->FgetUint8();
2932 console_ram_bank = state_fio->FgetUint8();
2933 ram_protect = state_fio->FgetBool();
2935 cgram_bank = state_fio->FgetUint32_BE();
2936 state_fio->Fread(subsys_ram, sizeof(subsys_ram), 1);
2937 state_fio->Fread(submem_cgram, sizeof(submem_cgram), 1);
2938 state_fio->Fread(submem_console_av40, sizeof(submem_console_av40), 1);
2941 palette_changed = true;
2942 vram_wrote_shadow = true; // Force Draw
2943 this->draw_screen();
2944 if(version == 1) return true;
2946 if(version >= 2) { //V2
2947 nmi_event_id = state_fio->FgetInt32_BE();
2948 #if defined(_FM77AV_VARIANTS)
2949 hblank_event_id = state_fio->FgetInt32_BE();
2950 hdisp_event_id = state_fio->FgetInt32_BE();
2951 vsync_event_id = state_fio->FgetInt32_BE();
2952 vstart_event_id = state_fio->FgetInt32_BE();
2954 firq_mask = state_fio->FgetBool();
2955 vram_accessflag = state_fio->FgetBool();
2956 frame_skip_count_draw = 3;
2957 frame_skip_count_transfer = 3;
2958 need_transfer_line = true;
2960 if(version == STATE_VERSION) return true;