2 * Common source code project -> FM-7 -> Display
3 * (C) 2015 K.Ohta <whatisthis.sowhat _at_ gmail.com>
5 * Feb 10, 2015 : Initial.
8 #include "../../fileio.h"
9 #include "fm7_display.h"
10 #if defined(_FM77AV_VARIANTS)
11 # include "mb61vh010.h"
14 DISPLAY::DISPLAY(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
21 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
24 #elif defined(_FM77_VARIANTS)
27 #if defined(_FM77AV_VARIANTS)
33 set_device_name(_T("DISPLAY SUBSYSTEM"));
41 void DISPLAY::reset_cpuonly()
45 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
46 mainio->write_signal(SIG_FM7_SUB_HALT, 0x00, 0xff);
49 palette_changed = true;
50 multimode_accessmask = 0;
51 multimode_dispmask = 0;
53 //cancel_request = false;
54 switch(config.cpu_type){
65 for(i = 0; i < 2; i++) {
66 offset_changed[i] = true;
67 tmp_offset_point[i].d = 0;
70 vram_wrote_shadow = true;
71 for(i = 0; i < 411; i++) vram_wrote_table[i] = true;
72 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
74 #if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
81 if(hblank_event_id >= 0) cancel_event(this, hblank_event_id);
82 if(hdisp_event_id >= 0) cancel_event(this, hdisp_event_id);
83 if(vsync_event_id >= 0) cancel_event(this, vsync_event_id);
84 if(vstart_event_id >= 0) cancel_event(this, vstart_event_id);
89 if(display_mode == DISPLAY_MODE_8_400L) {
95 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
96 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
97 mainio->write_signal(SIG_DISPLAY_VSYNC, 0xff, 0xff);
99 #if defined(_FM77AV_VARIANTS)
101 offset_point_bank1 = 0;
103 display_page_bak = 0;
106 subcpu_resetreq = false;
107 subrom_bank_using = subrom_bank;
112 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
114 vram_display_block = 0;
115 vram_active_block = 0;
117 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
122 window_opened = false;
127 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
128 alu->write_signal(SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
129 alu->write_signal(SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400: 200, 0xffff);
130 alu->write_signal(SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xffffffff : 0, 0xffffffff);
132 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
133 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
134 alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
136 alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
137 alu->write_signal(SIG_ALU_PLANES, 3, 3);
140 for(i = 0; i < 8; i++) set_dpalette(i, i);
141 do_firq(!firq_mask && key_firq_req);
143 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
145 kanjiaddr.d = 0x00000000;
146 # if defined(_FM77L4)
148 stat_400linecard = false;
153 frame_skip_count = 3;
157 void DISPLAY::reset()
161 memset(io_w_latch, 0xff, sizeof(io_w_latch));
163 vram_accessflag = true;
164 display_mode = DISPLAY_MODE_8_200L;
166 screen_update_flag = true;
169 cancel_request = false;
170 #if defined(_FM77AV_VARIANTS)
172 apalette_index.d = 0;
173 for(i = 0; i < 4096; i++) {
174 analog_palette_r[i] = i & 0x0f0;
175 analog_palette_g[i] = (i & 0xf00) >> 4;
176 analog_palette_b[i] = (i & 0x00f) << 4;
181 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
188 #elif defined(_FM77L4)
191 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
192 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
193 key_firq_req = false; //firq_mask = true;
197 #if defined(_FM77AV_VARIANTS)
198 power_on_reset = false;
199 for(i = 0; i < 411; i++) vram_wrote_table[i] = false;
203 for(i = 0; i < 8; i++) set_dpalette(i, i);
204 multimode_accessmask = 0x00;
205 multimode_dispmask = 0x00;
210 if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
211 register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
212 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
216 void DISPLAY::update_config()
220 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
226 * Vram accessing functions moved to vram.cpp .
229 void DISPLAY::do_irq(bool flag)
231 subcpu->write_signal(SIG_CPU_IRQ, flag ? 1: 0, 1);
234 void DISPLAY::do_firq(bool flag)
236 subcpu->write_signal(SIG_CPU_FIRQ, flag ? 1: 0, 1);
239 void DISPLAY::do_nmi(bool flag)
241 #if defined(_FM77AV_VARIANTS)
242 if(!nmi_enable) flag = false;
244 subcpu->write_signal(SIG_CPU_NMI, flag ? 1 : 0, 1);
247 void DISPLAY::set_multimode(uint8_t val)
250 multimode_accessmask = val & 0x07;
251 multimode_dispmask = (val & 0x70) >> 4;
253 # if defined(_FM77AV_VARIANTS)
254 alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
259 uint8_t DISPLAY::get_multimode(void)
265 val = multimode_accessmask & 0x07;
266 val |= ((multimode_dispmask << 4) & 0x70);
272 uint8_t DISPLAY::get_cpuaccessmask(void)
274 return multimode_accessmask & 0x07;
277 void DISPLAY::set_dpalette(uint32_t addr, uint8_t val)
281 dpalette_data[addr] = val | 0xf8; //0b11111000;
282 b = ((val & 0x01) != 0x00)? 255 : 0x00;
283 r = ((val & 0x02) != 0x00)? 255 : 0x00;
284 g = ((val & 0x04) != 0x00)? 255 : 0x00;
286 dpalette_pixel[addr] = RGB_COLOR(r, g, b);
287 palette_changed = true;
290 uint8_t DISPLAY::get_dpalette(uint32_t addr)
298 data = dpalette_data[addr];
303 void DISPLAY::halt_subcpu(void)
305 subcpu->write_signal(SIG_CPU_BUSREQ, 0x01, 0x01);
308 void DISPLAY::go_subcpu(void)
310 subcpu->write_signal(SIG_CPU_BUSREQ, 0x00, 0x01);
313 void DISPLAY::enter_display(void)
317 subclock = SUBCLOCK_NORMAL;
319 subclock = SUBCLOCK_SLOW;
321 if(!is_cyclesteal && vram_accessflag) {
322 subclock = subclock / 3;
324 if(prev_clock != subclock) p_vm->set_cpu_clock(subcpu, subclock);
325 prev_clock = subclock;
328 void DISPLAY::leave_display(void)
332 void DISPLAY::halt_subsystem(void)
338 void DISPLAY::restart_subsystem(void)
341 #if defined(_FM77AV_VARIANTS)
342 if(subcpu_resetreq) {
343 firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
345 power_on_reset = true;
346 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
348 do_firq(!firq_mask && key_firq_req);
355 void DISPLAY::set_crtflag(void)
362 void DISPLAY::reset_crtflag(void)
369 uint8_t DISPLAY::acknowledge_irq(void)
371 cancel_request = false;
377 uint8_t DISPLAY::beep(void)
379 mainio->write_signal(FM7_MAINIO_BEEP, 0x01, 0x01);
380 return 0xff; // True?
385 uint8_t DISPLAY::attention_irq(void)
387 mainio->write_signal(FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
392 void DISPLAY::set_cyclesteal(uint8_t val)
395 # if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
399 is_cyclesteal = true;
401 is_cyclesteal = false;
409 uint8_t DISPLAY::set_vramaccess(void)
411 vram_accessflag = true;
416 void DISPLAY::reset_vramaccess(void)
418 vram_accessflag = false;
422 uint8_t DISPLAY::reset_subbusy(void)
429 void DISPLAY::set_subbusy(void)
435 #if defined(_FM77AV_VARIANTS)
437 void DISPLAY::alu_write_cmdreg(uint32_t val)
439 alu->write_data8(ALU_CMDREG, val);
440 if((val & 0x80) != 0) {
448 void DISPLAY::alu_write_logical_color(uint8_t val)
450 uint32_t data = (uint32_t)val;
451 alu->write_data8(ALU_LOGICAL_COLOR, data);
455 void DISPLAY::alu_write_mask_reg(uint8_t val)
457 uint32_t data = (uint32_t)val;
458 alu->write_data8(ALU_WRITE_MASKREG, data);
462 void DISPLAY::alu_write_cmpdata_reg(int addr, uint8_t val)
464 uint32_t data = (uint32_t)val;
466 alu->write_data8(ALU_CMPDATA_REG + addr, data);
470 void DISPLAY::alu_write_disable_reg(uint8_t val)
472 uint32_t data = (uint32_t)val;
473 alu->write_data8(ALU_BANK_DISABLE, data);
477 void DISPLAY::alu_write_tilepaint_data(uint32_t addr, uint8_t val)
479 uint32_t data = (uint32_t)val;
482 alu->write_data8(ALU_TILEPAINT_B, data);
485 alu->write_data8(ALU_TILEPAINT_R, data);
488 alu->write_data8(ALU_TILEPAINT_G, data);
491 //alu->write_data8(ALU_TILEPAINT_L, 0xff);
497 void DISPLAY::alu_write_offsetreg_hi(uint8_t val)
499 alu->write_data8(ALU_OFFSET_REG_HIGH, val & 0x7f);
503 void DISPLAY::alu_write_offsetreg_lo(uint8_t val)
505 alu->write_data8(ALU_OFFSET_REG_LO, val);
509 void DISPLAY::alu_write_linepattern_hi(uint8_t val)
511 alu->write_data8(ALU_LINEPATTERN_REG_HIGH, val);
515 void DISPLAY::alu_write_linepattern_lo(uint8_t val)
517 alu->write_data8(ALU_LINEPATTERN_REG_LO, val);
521 void DISPLAY::alu_write_line_position(int addr, uint8_t val)
523 uint32_t data = (uint32_t)val;
526 alu->write_data8(ALU_LINEPOS_START_X_HIGH, data & 0x03);
529 alu->write_data8(ALU_LINEPOS_START_X_LOW, data);
532 alu->write_data8(ALU_LINEPOS_START_Y_HIGH, data & 0x01);
535 alu->write_data8(ALU_LINEPOS_START_Y_LOW, data);
538 alu->write_data8(ALU_LINEPOS_END_X_HIGH, data & 0x03);
541 alu->write_data8(ALU_LINEPOS_END_X_LOW, data);
544 alu->write_data8(ALU_LINEPOS_END_Y_HIGH, data & 0x01);
547 alu->write_data8(ALU_LINEPOS_END_Y_LOW, data);
553 uint8_t DISPLAY::get_miscreg(void)
558 if(!hblank) ret |= 0x80;
559 if(vsync) ret |= 0x04;
560 if(alu->read_signal(SIG_ALU_BUSYSTAT) == 0) ret |= 0x10;
561 if(power_on_reset) ret |= 0x01;
566 void DISPLAY::set_miscreg(uint8_t val)
568 int old_display_page = display_page;
570 nmi_enable = ((val & 0x80) == 0) ? true : false;
571 if(!nmi_enable) do_nmi(false);
573 if((val & 0x40) == 0) {
578 if(display_page != old_display_page) {
581 active_page = ((val & 0x20) == 0) ? 0 : 1;
582 if((val & 0x04) == 0) {
587 cgrom_bank = val & 0x03;
591 void DISPLAY::set_monitor_bank(uint8_t var)
593 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
594 if((var & 0x04) != 0){
600 subrom_bank = var & 0x03;
603 subcpu_resetreq = false;
604 power_on_reset = true;
605 firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
607 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
609 do_firq(!firq_mask && key_firq_req);
611 subcpu_resetreq = true;
617 void DISPLAY::set_apalette_index_hi(uint8_t val)
619 apalette_index.b.h = val & 0x0f;
623 void DISPLAY::set_apalette_index_lo(uint8_t val)
625 apalette_index.b.l = val;
628 void DISPLAY::calc_apalette(uint16_t idx)
632 g = analog_palette_g[idx];
633 r = analog_palette_r[idx];
634 b = analog_palette_b[idx];
635 if(g != 0) g |= 0x0f;
636 if(r != 0) r |= 0x0f;
637 if(b != 0) b |= 0x0f;
638 analog_palette_pixel[idx] = RGB_COLOR(r, g, b);
642 void DISPLAY::set_apalette_b(uint8_t val)
646 index = apalette_index.w.l;
647 tmp = (val & 0x0f) << 4;
648 if(analog_palette_b[index] != tmp) {
649 analog_palette_b[index] = tmp;
650 calc_apalette(index);
651 palette_changed = true;
656 void DISPLAY::set_apalette_r(uint8_t val)
660 index = apalette_index.w.l;
661 tmp = (val & 0x0f) << 4;
662 if(analog_palette_r[index] != tmp) {
663 analog_palette_r[index] = tmp;
664 calc_apalette(index);
665 palette_changed = true;
670 void DISPLAY::set_apalette_g(uint8_t val)
674 index = apalette_index.w.l;
675 tmp = (val & 0x0f) << 4;
676 if(analog_palette_g[index] != tmp) {
677 analog_palette_g[index] = tmp;
678 calc_apalette(index);
679 palette_changed = true;
683 #endif // _FM77AV_VARIANTS
686 void DISPLAY::copy_vram_blank_area(void)
691 void DISPLAY::copy_vram_per_line(void)
700 uint32_t src_offset_d1;
701 uint32_t src_offset_d2;
702 uint32_t src_offset_d;
707 //int dline = (int)displine - 1;
708 int dline = (int)displine;
710 if(dline < 0) return;
711 if(display_mode == DISPLAY_MODE_8_400L) {
712 if(dline >= 400) return;
714 if(dline >= 200) return;
716 #if defined(_FM77AV_VARIANTS)
717 yoff_d1 = offset_point;
718 yoff_d2 = offset_point_bank1;
719 if(display_mode == DISPLAY_MODE_4096) {
720 src_offset = dline * 40;
721 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
724 bytes_d1 = 0x2000 - ((src_offset + yoff_d1) & 0x1fff);
725 bytes_d2 = 0x2000 - ((src_offset + yoff_d2) & 0x1fff);
726 for(k = 0; k < pages; k++) {
727 for(i = 0; i < 3; i++) {
728 for(j = 0; j < 2; j++) {
729 src_base = i * 0x4000 + j * 0x2000;
731 memcpy(&gvram_shadow[src_offset + src_base + poff],
732 &gvram[((src_offset + yoff_d1) & 0x1fff) + src_base + poff],
734 memcpy(&gvram_shadow[src_offset + bytes_d1 + src_base + poff],
735 &gvram[src_base + poff],
738 memcpy(&gvram_shadow[src_offset + src_base + poff],
739 &gvram[((src_offset + yoff_d1) & 0x1fff) + src_base + poff],
742 src_base = i * 0x4000 + j * 0x2000 + 0xc000;
744 memcpy(&gvram_shadow[src_offset + src_base + poff],
745 &gvram[((src_offset + yoff_d2) & 0x1fff) + src_base + poff],
747 memcpy(&gvram_shadow[src_offset + bytes_d2 + src_base + poff],
748 &gvram[src_base + poff],
751 memcpy(&gvram_shadow[src_offset + src_base + poff],
752 &gvram[((src_offset + yoff_d2) & 0x1fff) + src_base + poff],
759 vram_draw_table[dline] = true;
760 vram_wrote_table[dline] = false;
762 # if defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV40)
763 else if(display_mode == DISPLAY_MODE_256k) {
764 src_offset = dline * 40;
766 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
768 #elif defined(_FM77AV40)
773 src_offset_d1 = (src_offset + yoff_d1) & 0x1fff;
774 src_offset_d2 = (src_offset + yoff_d2) & 0x1fff;
775 bytes_d1 = 0x2000 - ((src_offset + yoff_d1) & 0x1fff);
776 bytes_d2 = 0x2000 - ((src_offset + yoff_d2) & 0x1fff);
777 for(k = 0; k < pages; k++) {
778 for(i = 0; i < 3; i++) {
779 for(j = 0; j < 2; j++) {
781 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
782 src_offset_d = src_offset_d1;
785 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
786 src_offset_d = src_offset_d2;
790 memcpy(&gvram_shadow[src_offset + src_base],
791 &gvram[src_offset_d + src_base],
793 memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
797 memcpy(&gvram_shadow[src_offset + src_base],
798 &gvram[src_offset_d + src_base],
804 vram_draw_table[dline] = true;
805 vram_wrote_table[dline] = false;
807 else if(display_mode == DISPLAY_MODE_8_400L) {
808 src_offset = dline * 80;
809 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
811 # elif defined(_FM77AV40)
814 if(display_page_bak == 1) { // Is this dirty?
819 yoff_d = (yoff_d << 1) & 0x7fff;
820 src_offset_d = (src_offset + yoff_d) & 0x7fff;
821 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
822 for(i = 0; i < pages; i++) {
823 for(j = 0; j < 3; j++) {
824 src_base = i * 0x18000 + j * 0x8000;
826 memcpy(&gvram_shadow[src_offset + src_base],
827 &gvram[src_offset_d + src_base],
829 memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
833 memcpy(&gvram_shadow[src_offset + src_base + poff],
834 &gvram[src_offset_d + src_base],
839 vram_draw_table[dline] = true;
840 vram_wrote_table[dline] = false;
844 src_offset = dline * 80;
845 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
847 #elif defined(_FM77AV40)
849 #elif defined(_FM77AV_VARIANTS)
855 src_offset_d1 = (src_offset + yoff_d1) & 0x3fff;
856 src_offset_d2 = (src_offset + yoff_d2) & 0x3fff;
857 bytes_d1 = 0x4000 - ((src_offset + yoff_d1) & 0x3fff);
858 bytes_d2 = 0x4000 - ((src_offset + yoff_d2) & 0x3fff);
859 for(i = 0; i < pages; i++) {
860 for(j = 0; j < 3; j++) {
861 src_base = j * 0x4000;
863 src_offset_d = src_offset_d1;
866 src_offset_d = src_offset_d2;
870 memcpy(&gvram_shadow[src_offset + src_base + poff],
871 &gvram[src_offset_d + src_base + poff],
873 memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
874 &gvram[src_base + poff],
877 memcpy(&gvram_shadow[src_offset + src_base + poff],
878 &gvram[src_offset_d + src_base + poff],
884 vram_draw_table[dline] = true;
885 vram_wrote_table[dline] = false;
889 src_offset = dline * 80;
892 yoff_d = offset_point;
893 src_offset_d = (src_offset + yoff_d) & 0x3fff;
894 bytes_d = 0x4000 - ((src_offset + yoff_d) & 0x3fff);
895 for(j = 0; j < 3; j++) {
896 src_base = j * 0x4000;
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],
910 vram_draw_table[dline] = true;
911 vram_wrote_table[dline] = false;
917 void DISPLAY::copy_vram_all()
919 #if defined(_FM77AV_VARIANTS)
920 uint32_t yoff_d1 = offset_point;
921 uint32_t yoff_d2 = offset_point_bank1;
922 uint32_t src_offset_1, src_offset_2;
924 if(display_mode == DISPLAY_MODE_4096) {
925 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
930 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
931 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
932 for(int k = 0; k < pages; k++) {
933 for(int i = 0; i < 3; i++) {
934 for(int j = 0; j < 2; j++) {
935 src_offset_1 = i * 0x4000 + j * 0x2000;
936 src_offset_2 = src_offset_1 + 0xc000;
937 memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
938 memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
939 memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
940 memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
946 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
947 else if(display_mode == DISPLAY_MODE_256k) {
948 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
949 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
950 for(int i = 0; i < 3; i++) {
951 for(int j = 0; j < 2; j++) {
952 src_offset_1 = i * 0x4000 + j * 0x2000;
953 src_offset_2 = src_offset_1 + 0xc000;
954 memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
955 memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
956 memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
957 memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
961 for(int i = 0; i < 3; i++) {
962 for(int j = 0; j < 2; j++) {
963 src_offset_1 = i * 0x4000 + j * 0x2000;
964 memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
965 memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
968 } else if(display_mode == DISPLAY_MODE_8_400L) {
969 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
977 if(display_page_bak == 1) { // Is this dirty?
982 yoff_d = (yoff_d << 1) & 0x7fff;
983 bytes_d = 0x8000 - yoff_d;
984 for(int k = 0; k < pages; k++) {
985 for(int i = 0; i < 3; i++) {
986 src_offset_1 = i * 0x8000;
987 memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + yoff_d + poff], bytes_d);
988 memcpy(&gvram_shadow[src_offset_1 + bytes_d + poff], &gvram[src_offset_1 + poff], 0x8000 - bytes_d);
995 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
997 #elif defined(_FM77AV40)
1002 uint32_t bytes_d1 = 0x4000 - (yoff_d1 & 0x3fff);
1003 uint32_t bytes_d2 = 0x4000 - (yoff_d2 & 0x3fff);
1004 uint32_t yoff_d, bytes_d;
1005 for(int k = 0; k < pages; k++) {
1006 yoff_d = ((k & 1) == 0) ? (yoff_d1 & 0x3fff) : (yoff_d2 & 0x3fff);
1007 bytes_d = ((k & 1) == 0) ? bytes_d1 : bytes_d2;
1008 for(int j = 0; j < 3; j++) {
1009 src_offset_1 = k * 0xc000 + j * 0x4000;
1010 memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1011 memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1017 uint32_t yoff_d = offset_point & 0x3fff;
1018 uint32_t bytes_d = 0x4000 - (offset_point & 0x3fff);
1019 uint32_t src_offset_1;
1020 for(int j = 0; j < 3; j++) {
1021 src_offset_1 = j * 0x4000;
1022 memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1023 memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1029 // Timing values from XM7 . Thanks Ryu.
1030 void DISPLAY::event_callback(int event_id, int err)
1035 case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
1036 #if defined(_FM77AV_VARIANTS)
1046 case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
1049 #if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1050 case EVENT_FM7SUB_HDISP:
1053 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x02, 0xff);
1054 if(display_mode == DISPLAY_MODE_8_400L) {
1056 if(displine < 400) f = true;
1059 if(displine < 200) f = true;
1062 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
1063 if(vram_wrote_table[displine] || vram_wrote) copy_vram_per_line();
1065 register_event(this, EVENT_FM7SUB_HBLANK, usec, false, &hblank_event_id); // NEXT CYCLE_
1072 case EVENT_FM7SUB_HBLANK:
1074 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1076 if(display_mode == DISPLAY_MODE_8_400L) {
1077 if((displine < 400)) f = true;
1079 if((displine < 200)) f = true;
1082 if(display_mode == DISPLAY_MODE_8_400L) {
1087 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id);
1091 case EVENT_FM7SUB_VSTART: // Call first.
1096 display_page_bak = display_page;
1098 // Parameter from XM7/VM/display.c , thanks, Ryu.
1099 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1100 mainio->write_signal(SIG_DISPLAY_VSYNC, 0x00, 0xff);
1101 if(vblank_count != 0) {
1102 if(display_mode == DISPLAY_MODE_8_400L) {
1103 usec = (0.98 + 16.4) * 1000.0;
1105 usec = (1.91 + 12.7) * 1000.0;
1107 register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
1109 if(display_mode == DISPLAY_MODE_8_400L) {
1110 usec = 930.0; // 939.0
1112 usec = 1840.0; // 1846.5
1114 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
1118 if(display_mode == DISPLAY_MODE_8_400L) {
1119 usec = 0.34 * 1000.0;
1121 usec = 1.52 * 1000.0;
1123 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1128 case EVENT_FM7SUB_VSYNC:
1133 if(display_mode == DISPLAY_MODE_8_400L) {
1134 usec = 0.33 * 1000.0;
1136 usec = 0.51 * 1000.0;
1138 mainio->write_signal(SIG_DISPLAY_VSYNC, 0x01, 0xff);
1139 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1140 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1141 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) {
1145 if(display_mode == DISPLAY_MODE_8_400L) lines = 400;
1146 for(int yy = 0; yy < lines; yy++) {
1147 if(vram_wrote_table[yy]) {
1148 vram_wrote_table[yy] = false;
1156 for(int yy = 0; yy < 400; yy++) vram_draw_table[yy] = true;
1158 vram_wrote_shadow = true;
1159 screen_update_flag = true;
1163 for(int yy = 0; yy < 400; yy++) {
1164 if(!vram_draw_table[yy]) {
1166 copy_vram_per_line();
1171 for(int yy = 0; yy < 400; yy++) {
1172 if(vram_draw_table[yy]) {
1173 vram_wrote_shadow = true;
1174 screen_update_flag = true;
1182 case EVENT_FM7SUB_CLR_BUSY:
1185 case EVENT_FM7SUB_CLR_CRTFLAG:
1191 void DISPLAY::event_frame()
1193 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1198 for(yy = 0; yy < 400; yy++) {
1199 if(!vram_draw_table[yy]) {
1201 copy_vram_per_line();
1206 for(yy = 0; yy < 400; yy++) {
1207 if(vram_draw_table[yy]) {
1213 screen_update_flag = true;
1214 vram_wrote_shadow = true;
1223 void DISPLAY::event_vline(int v, int clock)
1225 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1226 // if((v >= 200) || (v < 0)) return;
1228 if(vram_wrote_table[displine] || vram_wrote) {
1229 copy_vram_per_line();
1236 uint32_t DISPLAY::read_signal(int id)
1238 uint32_t retval = 0;
1240 case SIG_FM7_SUB_HALT:
1241 case SIG_DISPLAY_HALT:
1242 retval = (halt_flag) ? 0xffffffff : 0;
1244 case SIG_DISPLAY_BUSY:
1245 retval = (sub_busy) ? 0x80 : 0;
1247 case SIG_DISPLAY_MULTIPAGE:
1248 retval = multimode_accessmask;
1250 case SIG_DISPLAY_PLANES:
1253 #if defined(_FM77AV_VARIANTS)
1254 case SIG_DISPLAY_VSYNC:
1255 retval = (vsync) ? 0x01 : 0x00;
1257 case SIG_DISPLAY_DISPLAY:
1258 retval = (!hblank) ? 0x02: 0x00;
1260 case SIG_FM7_SUB_BANK: // Main: FD13
1261 retval = subrom_bank & 0x03;
1262 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1263 if(monitor_ram) retval |= 0x04;
1267 #if defined(_FM77AV_VARIANTS)
1268 case SIG_DISPLAY_MODE320:
1269 retval = (mode320) ? 0x40: 0x00;
1272 case SIG_DISPLAY_Y_HEIGHT:
1273 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1274 retval = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
1279 case SIG_DISPLAY_X_WIDTH:
1280 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1281 retval = (mode320 || mode256k) ? 320 : 640;
1282 #elif defined(_FM77AV_VARIANTS)
1283 retval = (mode320) ? 320 : 640;
1294 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
1296 bool flag = ((data & mask) != 0);
1299 case SIG_FM7_SUB_HALT:
1304 //mainio->write_signal(SIG_FM7_SUB_HALT, data, mask);
1306 case SIG_DISPLAY_HALT:
1310 restart_subsystem();
1313 case SIG_FM7_SUB_CANCEL:
1315 cancel_request = true;
1319 case SIG_DISPLAY_CLOCK:
1323 #if defined(_FM77AV_VARIANTS)
1324 case SIG_FM7_SUB_BANK: // Main: FD13
1325 set_monitor_bank(data & 0xff);
1328 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1329 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1330 //printf("Wrote $FD04: %02x\n", data);
1332 int oldmode = display_mode;
1334 kanjisub = ((data & 0x20) == 0) ? true : false;
1335 mode256k = (((data & 0x10) != 0) && ((data & 0x08) != 0) ) ? true : false;
1336 mode400line = ((data & 0x08) == 0) ? true : false;
1337 ram_protect = ((data & 0x04) == 0) ? true : false;
1338 if(mode400line && !mode320) {
1339 display_mode = DISPLAY_MODE_8_400L;
1340 } else if(mode256k) {
1341 display_mode = DISPLAY_MODE_256k;
1343 display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1345 if(oldmode != display_mode) {
1347 if(mode320 || mode256k) {
1348 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1349 for(y = 0; y < 200; y++) {
1350 pp = emu->get_screen_buffer(y);
1351 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1353 } else if(display_mode == DISPLAY_MODE_8_400L) {
1354 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1355 for(y = 0; y < 400; y++) {
1356 pp = emu->get_screen_buffer(y);
1357 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1360 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1361 for(y = 0; y < 200; y++) {
1362 pp = emu->get_screen_buffer(y);
1363 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1367 alu->write_signal(SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
1368 alu->write_signal(SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200, 0xffff);
1369 alu->write_signal(SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xff : 0x00, 0xff);
1370 frame_skip_count = 3;
1373 #elif defined(_FM77_VARIANTS)
1375 int oldmode = display_mode;
1376 kanjisub = ((data & 0x20) == 0) ? true : false;
1377 # if defined(_FM77L4)
1378 stat_400linecard = ((data & 0x20) != 0) ? true : false;
1379 mode400line = ((data & 0x08) != 0) ? false : true;
1380 if(mode400line && stat_400linecard) {
1381 display_mode = DISPLAY_MODE_8_400L_TEXT;
1382 } else if(stat_400linecard) {
1383 display_mode = DISPLAY_MODE_8_200L_TEXT;
1385 display_mode = DISPLAY_MODE_8_200L;
1391 #if defined(_FM77AV_VARIANTS)
1392 case SIG_DISPLAY_MODE320: // FD12 bit 6
1393 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1395 //printf("Wrote $FD12: %02x\n", data);
1396 int oldmode = display_mode;
1398 if(!mode320 && !mode256k) {
1399 //display_mode = (mode400line) ? DISPLAY_MODE_8_400L : DISPLAY_MODE_8_200L;
1400 display_mode = DISPLAY_MODE_8_200L;
1402 display_mode = (mode256k) ? DISPLAY_MODE_256k : DISPLAY_MODE_4096;
1404 if(oldmode != display_mode) {
1406 if(mode320 || mode256k) {
1407 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1408 for(y = 0; y < 200; y++) {
1409 pp = emu->get_screen_buffer(y);
1410 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1412 } else { // 200 lines, 8 colors.
1413 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1414 for(y = 0; y < 200; y++) {
1415 pp = emu->get_screen_buffer(y);
1416 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1420 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
1421 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
1422 alu->write_signal(SIG_ALU_400LINE, 0x00, 0xff);
1423 //frame_skip_count = 3;
1431 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1432 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 320 * sizeof(scrntype_t));
1434 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1435 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
1438 display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1439 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
1440 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
1441 alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
1446 case SIG_DISPLAY_MULTIPAGE:
1447 set_multimode(data);
1449 case SIG_FM7_SUB_KEY_MASK:
1450 if(firq_mask == flag) {
1451 do_firq(!flag && key_firq_req);
1455 case SIG_FM7_SUB_KEY_FIRQ:
1456 do_firq(flag & !(firq_mask));
1457 key_firq_req = flag;
1459 case SIG_FM7_SUB_USE_CLR:
1461 clr_count = data & 0x03;
1472 * Vram accessing functions moved to vram.cpp .
1475 uint8_t DISPLAY::read_mmio(uint32_t addr)
1477 uint32_t retval = 0xff;
1479 if(addr < 0xd400) return 0xff;
1481 #if !defined(_FM77AV_VARIANTS)
1482 raddr = (addr - 0xd400) & 0x000f;
1483 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
1484 raddr = (addr - 0xd400) & 0x003f;
1485 #else // FM77AV40EX || FM77AV40SX
1486 raddr = (addr - 0xd400) & 0x00ff;
1489 case 0x00: // Read keyboard
1490 retval = (keyboard->read_data8(0x00) != 0) ? 0xff : 0x7f;
1492 case 0x01: // Read keyboard
1493 retval = keyboard->read_data8(0x01) & 0xff;
1495 case 0x02: // Acknowledge
1504 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1505 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
1507 if(!kanjisub) return 0xff;
1508 # if !defined(_FM77_VARIANTS)
1510 return (uint8_t)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1513 if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1516 if(!kanjisub) return 0xff;
1517 # if !defined(_FM77_VARIANTS)
1519 return (uint8_t)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1522 if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1529 retval = set_vramaccess();
1535 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
1537 #if defined(_FM77AV_VARIANTS)
1540 retval = alu->read_data8(ALU_CMDREG);
1543 retval = alu->read_data8(ALU_LOGICAL_COLOR);
1546 retval = alu->read_data8(ALU_WRITE_MASKREG);
1549 retval = alu->read_data8(ALU_CMP_STATUS_REG);
1552 retval = alu->read_data8(ALU_BANK_DISABLE);
1554 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1555 case 0x2f: // VRAM BANK
1556 retval = 0xfc | (vram_bank & 0x03);
1561 retval = get_miscreg();
1565 retval = keyboard->read_data8(0x31);
1568 retval = keyboard->read_data8(0x32);
1574 return (uint8_t)retval;
1577 uint32_t DISPLAY::read_vram_data8(uint32_t addr)
1580 uint32_t page_offset = 0;
1581 uint32_t page_mask = 0x3fff;
1582 uint32_t color = (addr >> 14) & 0x03;
1585 #if defined(_FM77AV_VARIANTS)
1586 if (active_page != 0) {
1587 offset = offset_point_bank1;
1589 offset = offset_point;
1592 offset = offset_point;
1595 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1596 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1597 if(vram_active_block != 0) page_offset = 0x18000;
1599 if(display_mode == DISPLAY_MODE_8_400L) {
1600 if(addr >= 0x8000) return 0xff;
1601 color = vram_bank & 0x03;
1602 if(color > 2) color = 0;
1604 pagemod = 0x8000 * color;
1605 return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
1608 #if defined(_FM77AV40)
1610 page_offset = 0xc000 * (vram_bank & 0x03);
1612 page_offset = 0; // right?
1615 page_offset = 0xc000 * (vram_bank & 0x03);
1618 pagemod = addr & 0xe000;
1622 pagemod = addr & 0xe000;
1624 pagemod = addr & 0xc000;
1626 if(active_page != 0) {
1627 page_offset += 0xc000;
1630 return gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1632 #elif defined(_FM77AV_VARIANTS)
1634 if(active_page != 0) {
1635 page_offset += 0xc000;
1639 pagemod = addr & 0xe000;
1641 pagemod = addr & 0xc000;
1643 return gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1645 #elif defined(_FM77L4) //_FM77L4
1647 if(display_mode == DISPLAY_MODE_8_400L) {
1648 return (uint32_t)read_vram_l4_400l(addr, offset);
1650 pagemod = addr & 0xc000;
1651 return gvram[((addr + offset) & 0x3fff) | pagemod];
1655 #else // Others (77/7/8)
1656 pagemod = addr & 0xc000;
1657 return gvram[((addr + offset) & 0x3fff) | pagemod];
1661 void DISPLAY::write_dma_data8(uint32_t addr, uint32_t data)
1663 uint32_t raddr = addr & 0xffff;
1666 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1667 if(display_mode == DISPLAY_MODE_8_400L) {
1668 color = vram_bank & 0x03;
1669 if(color > 2) color = 0;
1671 color = (addr >> 14) & 0x03;
1675 if((multimode_accessmask & (1 << color)) != 0) return;
1677 return write_vram_data8(raddr, (uint8_t)data);
1679 return write_data8_main(raddr, (uint8_t)data);
1684 void DISPLAY::write_vram_data8(uint32_t addr, uint8_t data)
1687 uint32_t page_offset = 0;
1688 uint32_t page_mask = 0x3fff;
1689 uint32_t color = (addr >> 14) & 0x03;
1693 #if defined(_FM77AV_VARIANTS)
1694 if (active_page != 0) {
1695 offset = offset_point_bank1;
1697 offset = offset_point;
1700 offset = offset_point;
1703 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1704 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1705 if(vram_active_block != 0) page_offset = 0x18000;
1707 if(display_mode == DISPLAY_MODE_8_400L) {
1708 if(addr >= 0x8000) {
1711 color = vram_bank & 0x03;
1712 if(color > 2) color = 0;
1714 pagemod = 0x8000 * color;
1715 // Reduce data transfer.
1716 tdata = gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
1718 gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset] = data;
1719 vram_wrote_table[(addr & 0x7fff) / 80] = true;
1721 } else if(display_mode == DISPLAY_MODE_256k) {
1722 #if defined(_FM77AV40)
1724 page_offset = 0xc000 * (vram_bank & 0x03);
1726 page_offset = 0; // right?
1729 page_offset = 0xc000 * (vram_bank & 0x03);
1732 pagemod = addr & 0xe000;
1733 tdata = gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1735 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1736 vram_wrote_table[(addr & page_mask) / 40] = true;
1739 } else if(display_mode == DISPLAY_MODE_4096) {
1740 if(active_page != 0) {
1741 page_offset += 0xc000;
1744 pagemod = addr & 0xe000;
1745 tdata = gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1747 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1748 vram_wrote_table[(addr & page_mask) / 40] = true;
1751 if(active_page != 0) {
1752 page_offset += 0xc000;
1755 pagemod = addr & 0xc000;
1756 tdata = gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1758 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1759 vram_wrote_table[(addr & page_mask) / 80] = true;
1762 #elif defined(_FM77AV_VARIANTS)
1763 if(display_mode == DISPLAY_MODE_4096) {
1764 if(active_page != 0) {
1765 page_offset = 0xc000;
1768 pagemod = addr & 0xe000;
1769 tdata = gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1771 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1772 vram_wrote_table[(addr & page_mask) / 40] = true;
1775 if(active_page != 0) {
1776 page_offset = 0xc000;
1779 pagemod = addr & 0xc000;
1780 tdata = gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1782 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1783 vram_wrote_table[(addr & page_mask) / 80] = true;
1786 #elif defined(_FM77L4) //_FM77L4
1788 if(display_mode == DISPLAY_MODE_8_400L) {
1789 write_vram_l4_400l(addr, data, offset);
1791 pagemod = addr & 0xc000;
1792 tdata = gvram[((addr + offset) & 0x3fff) | pagemod];
1794 gvram[((addr + offset) & 0x3fff) | pagemod] = data;
1795 vram_wrote_table[(addr & 0x3fff) / 80] = true;
1799 #else // Others (77/7/8)
1800 pagemod = addr & 0xc000;
1801 tdata = gvram[((addr + offset) & 0x3fff) | pagemod];
1803 gvram[((addr + offset) & 0x3fff) | pagemod] = data;
1804 vram_wrote_table[(addr & 0x3fff) / 80] = true;
1809 uint32_t DISPLAY::read_data8_main(uint32_t addr)
1812 if(addr < 0xc000) return 0xff;
1814 raddr = addr - 0xc000;
1815 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1817 if(console_ram_bank >= 1) {
1818 return submem_console_av40[((console_ram_bank - 1) << 12) + raddr];
1822 return console_ram[raddr];
1823 } else if(addr < 0xd380) {
1824 raddr = addr - 0xd000;
1825 return work_ram[raddr];
1826 } else if(addr < 0xd400) {
1827 raddr = addr - 0xd380;
1828 return shared_ram[raddr];
1829 } else if(addr < 0xd800) {
1830 #if defined(_FM77AV_VARIANTS)
1831 if(addr >= 0xd500) {
1832 return submem_hidden[addr - 0xd500];
1835 return read_mmio(addr);
1836 } else if(addr < 0x10000) {
1837 #if !defined(_FM77AV_VARIANTS)
1838 return subsys_c[addr - 0xd800];
1841 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
1843 return submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)]; //FIXME
1846 return subsys_cg[(addr - 0xd800) + cgrom_bank * 0x800];
1847 } else if(addr < 0x10000) {
1848 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
1850 return subsys_ram[addr - 0xe000];
1853 switch(subrom_bank_using & 3) {
1855 return subsys_c[addr - 0xd800];
1858 return subsys_a[addr - 0xe000];
1861 return subsys_b[addr - 0xe000];
1864 return subsys_cg[addr - 0xe000];
1873 uint32_t DISPLAY::read_dma_data8(uint32_t addr)
1875 uint32_t raddr = addr & 0xffff;
1878 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1879 if(display_mode == DISPLAY_MODE_8_400L) {
1880 color = vram_bank & 0x03;
1881 if(color > 2) color = 0;
1883 color = (addr >> 14) & 0x03;
1887 if((multimode_accessmask & (1 << color)) != 0) return 0xff;
1889 return read_vram_data8(raddr);
1891 return read_data8_main(raddr);
1896 uint32_t DISPLAY::read_data8(uint32_t addr)
1898 uint32_t raddr = addr;
1900 uint32_t color = (addr & 0x0c000) >> 14;
1902 #if defined(_FM77AV_VARIANTS)
1904 alu->read_data8(addr + ALU_WRITE_PROXY);
1907 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1908 if(display_mode == DISPLAY_MODE_8_400L) {
1909 color = vram_bank & 0x03;
1910 if(color > 2) color = 0;
1912 color = (addr >> 14) & 0x03;
1916 if((multimode_accessmask & (1 << color)) != 0) return 0xff;
1918 return read_vram_data8(addr);
1919 } else if(addr < 0x10000) {
1920 return read_data8_main(addr);
1923 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
1924 return dpalette_data[addr - FM7_SUBMEM_OFFSET_DPALETTE];
1927 #if defined(_FM77AV_VARIANTS)
1929 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
1930 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
1931 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1932 if(display_mode == DISPLAY_MODE_8_400L) {
1933 uint32_t page_offset = 0;
1934 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1935 if(vram_active_block != 0) page_offset = 0x18000;
1937 color = (addr & 0x18000) >> 15;
1938 if(color > 2) color = 0;
1940 if (active_page != 0) {
1941 offset = offset_point_bank1 << 1;
1943 offset = offset_point << 1;
1945 if(color > 2) color = 0;
1946 uint32_t pagemod = 0x8000 * color;
1947 return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
1950 return read_vram_data8(addr);
1957 * Vram accessing functions moved to vram.cpp .
1960 void DISPLAY::write_mmio(uint32_t addr, uint32_t data)
1964 if(addr < 0xd400) return;
1966 #if !defined(_FM77AV_VARIANTS)
1967 addr = (addr - 0xd400) & 0x000f;
1968 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
1969 addr = (addr - 0xd400) & 0x003f;
1970 #else // FM77AV40EX || FM77AV40SX
1971 addr = (addr - 0xd400) & 0x00ff;
1973 io_w_latch[addr] = (uint8_t)data;
1975 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4)
1978 set_cyclesteal((uint8_t)data);
1981 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1982 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
1985 if(!kanjisub) return;
1986 kanjiaddr.w.h = 0x0000;
1987 kanjiaddr.b.h = (uint8_t) data;
1990 if(!kanjisub) return;
1991 kanjiaddr.w.h = 0x0000;
1992 kanjiaddr.b.l = (uint8_t)data;
2005 if(clr_count <= 0) {
2007 } else { // Read once when using clr_foo() to set busy flag.
2010 usec = (1000.0 * 1000.0) / 2000000.0;
2012 usec = (1000.0 * 1000.0) / 999000.0;
2014 if(!is_cyclesteal && vram_accessflag) usec = usec * 3.0;
2015 usec = (double)clr_count * usec;
2016 register_event(this, EVENT_FM7SUB_CLR_BUSY, usec, false, NULL); // NEXT CYCLE_
2023 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
2028 rval = (uint8_t)data;
2029 if(offset_changed[active_page]) {
2030 #if defined(_FM77AV_VARIANTS)
2031 if(active_page != 0) {
2032 tmp_offset_point[active_page].d = offset_point_bank1;
2034 tmp_offset_point[active_page].d = offset_point;
2037 tmp_offset_point[active_page].d = offset_point;
2040 tmp_offset_point[active_page].w.h = 0x0000;
2042 tmp_offset_point[active_page].b.h = rval;
2044 tmp_offset_point[active_page].b.l = rval;
2046 offset_changed[active_page] = !offset_changed[active_page];
2047 if(offset_changed[active_page]) {
2049 #if defined(_FM77AV_VARIANTS)
2050 if(active_page != 0) {
2052 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fff;
2054 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fe0;
2058 offset_point = tmp_offset_point[active_page].d & 0x007fff;
2060 offset_point = tmp_offset_point[active_page].d & 0x007fe0;
2064 offset_point = tmp_offset_point[active_page].d & 0x7fe0;
2068 #if defined(_FM77AV_VARIANTS)
2071 alu_write_cmdreg(data);
2074 alu_write_logical_color(data);
2077 alu_write_mask_reg(data);
2080 alu_write_disable_reg(data);
2083 alu_write_offsetreg_hi(data);
2086 alu_write_offsetreg_lo(data);
2089 alu_write_linepattern_hi(data);
2092 alu_write_linepattern_lo(data);
2094 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2096 console_ram_bank = (data & 0x18) >> 3;
2097 if(console_ram_bank > 2) console_ram_bank = 0;
2098 cgram_bank = data & 0x07;
2099 kanji_level2 = ((data & 0x80) == 0) ? false : true;
2101 case 0x2f: // VRAM BANK
2102 vram_bank = data & 0x03;
2103 if(vram_bank > 2) vram_bank = 0;
2113 keyboard->write_data8(0x31, data);
2115 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2117 vram_active_block = data & 0x01;
2118 if(vram_display_block != (((data & 0x10) != 0) ? 1 : 0)) vram_wrote = true;
2119 vram_display_block = ((data & 0x10) != 0) ? 1 : 0;
2124 tmpvar.d = window_xbegin * 8;
2127 tmpvar.b.h = data & 0x03;
2129 tmpvar.b.l = data & 0xf8;
2131 if(mode320 || mode256k) {
2132 if(tmpvar.d > 320) tmpvar.d = 320;
2134 if(tmpvar.d > 640) tmpvar.d = 640;
2136 window_xbegin = tmpvar.d / 8;
2141 tmpvar.d = window_xend * 8;
2144 tmpvar.b.h = data & 0x03;
2146 tmpvar.b.l = data & 0xf8;
2148 if(mode320 || mode256k) {
2149 if(tmpvar.d > 320) tmpvar.d = 320;
2151 if(tmpvar.d > 640) tmpvar.d = 640;
2153 window_xend = tmpvar.d / 8;
2158 tmpvar.d = window_low;
2161 tmpvar.b.h = data & 0x03;
2163 tmpvar.b.l = data & 0xff;
2165 if(display_mode == DISPLAY_MODE_8_400L) {
2166 if(tmpvar.d > 400) tmpvar.d = 400;
2169 if(tmpvar.d > 400) tmpvar.d = 400;
2171 window_low = tmpvar.d;
2176 tmpvar.d = window_high;
2179 tmpvar.b.h = data & 0x03;
2181 tmpvar.b.l = data & 0xff;
2183 if(display_mode == DISPLAY_MODE_8_400L) {
2184 if(tmpvar.d > 400) tmpvar.d = 400;
2187 if(tmpvar.d > 400) tmpvar.d = 400;
2189 window_high = tmpvar.d;
2195 #if defined(_FM77AV_VARIANTS)
2197 if((addr >= 0x13) && (addr <= 0x1a)) {
2198 alu_write_cmpdata_reg(addr - 0x13, data);
2199 } else if((addr >= 0x1c) && (addr <= 0x1e)) {
2200 alu_write_tilepaint_data(addr, data);
2201 } else if((addr >= 0x24) && (addr <= 0x2b)) {
2202 alu_write_line_position(addr - 0x24, data);
2209 void DISPLAY::write_data8_main(uint32_t addr, uint8_t data)
2213 uint32_t page_offset = 0x0000;
2215 if(addr < 0xc000) return;
2218 raddr = addr - 0xc000;
2219 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2221 if(console_ram_bank >= 1) {
2222 submem_console_av40[((console_ram_bank - 1) << 12) + raddr] = data;
2227 console_ram[raddr] = data;
2229 } else if(addr < 0xd380) {
2230 raddr = addr - 0xd000;
2231 work_ram[raddr] = data;
2233 } else if(addr < 0xd400) {
2234 raddr = addr - 0xd380;
2235 shared_ram[raddr] = data;
2237 } else if(addr < 0xd800) {
2238 #if defined(_FM77AV_VARIANTS)
2239 if(addr >= 0xd500) {
2240 submem_hidden[addr - 0xd500] = data;
2244 write_mmio(addr, data);
2246 } else if(addr < 0x10000) {
2247 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2248 if(ram_protect) return;
2251 submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)] = data; //FIXME
2253 subsys_ram[addr - 0xe000] = data;
2261 void DISPLAY::write_data8(uint32_t addr, uint32_t data)
2265 uint32_t page_offset = 0x0000;
2266 uint8_t val8 = data & 0xff;
2268 uint32_t color = (addr & 0xc000) >> 14;
2272 #if defined(_FM77AV_VARIANTS)
2274 alu->read_data8(addr + ALU_WRITE_PROXY);
2277 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2278 if(display_mode == DISPLAY_MODE_8_400L) {
2279 color = vram_bank & 0x03;
2280 if(color > 2) color = 0;
2285 if((multimode_accessmask & (1 << color)) != 0) return;
2287 write_vram_data8(addr, val8);
2289 } else if(addr < 0x10000) {
2290 write_data8_main(addr, val8);
2294 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2295 set_dpalette(addr - FM7_SUBMEM_OFFSET_DPALETTE, val8);
2299 #if defined(_FM77AV_VARIANTS)
2301 else if(addr == FM7_SUBMEM_OFFSET_APALETTE_R) {
2302 set_apalette_r(val8);
2304 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_G) {
2305 set_apalette_g(val8);
2307 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_B) {
2308 set_apalette_b(val8);
2310 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_HI) {
2311 set_apalette_index_hi(val8);
2313 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_LO) {
2314 set_apalette_index_lo(val8);
2318 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2319 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2320 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2321 if(display_mode == DISPLAY_MODE_8_400L) {
2322 color = (addr & 0x18000) >> 15;
2323 if(color > 2) color = 0;
2325 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2326 if(vram_active_block != 0) page_offset = 0x18000;
2328 if(color > 2) color = 0;
2329 if (active_page != 0) {
2330 offset = offset_point_bank1 << 1;
2332 offset = offset_point << 1;
2334 pagemod = 0x8000 * color;
2335 tdata = gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
2336 if(tdata != (uint8_t)data) {
2337 gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset] = data;
2338 vram_wrote_table[(addr & 0x7fff) / 80] = true;
2342 write_vram_data8(addr, data);
2344 write_vram_data8(addr, data);
2346 //if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
2353 uint32_t DISPLAY::read_bios(const _TCHAR *name, uint8_t *ptr, uint32_t size)
2359 if((name == NULL) || (ptr == NULL)) return 0;
2360 s = create_local_path(name);
2361 if(s == NULL) return 0;
2363 if(!fio.Fopen(s, FILEIO_READ_BINARY)) return 0;
2364 blocks = fio.Fread(ptr, size, 1);
2367 return blocks * size;
2371 void DISPLAY::initialize()
2375 screen_update_flag = true;
2376 memset(gvram, 0x00, sizeof(gvram));
2377 vram_wrote_shadow = false;
2378 memset(gvram_shadow, 0x00, sizeof(gvram_shadow));
2379 for(i = 0; i < 411; i++) vram_wrote_table[i] = false;
2380 for(i = 0; i < 411; i++) vram_draw_table[i] = false;
2382 memset(console_ram, 0x00, sizeof(console_ram));
2383 memset(work_ram, 0x00, sizeof(work_ram));
2384 memset(shared_ram, 0x00, sizeof(shared_ram));
2385 memset(subsys_c, 0xff, sizeof(subsys_c));
2387 diag_load_subrom_c = false;
2389 if(read_bios(_T("SUBSYS_8.ROM"), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2390 this->out_debug_log(_T("SUBSYSTEM ROM READING : %s"), diag_load_subrom_c ? "OK" : "NG");
2392 if(read_bios(_T("SUBSYS_C.ROM"), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2393 this->out_debug_log(_T("SUBSYSTEM ROM Type C READING : %s"), diag_load_subrom_c ? "OK" : "NG");
2395 #if defined(_FM77AV_VARIANTS)
2396 memset(subsys_a, 0xff, sizeof(subsys_a));
2397 memset(subsys_b, 0xff, sizeof(subsys_b));
2398 memset(subsys_cg, 0xff, sizeof(subsys_cg));
2399 memset(submem_hidden, 0x00, sizeof(submem_hidden));
2401 diag_load_subrom_a = false;
2402 if(read_bios(_T("SUBSYS_A.ROM"), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
2403 this->out_debug_log(_T("SUBSYSTEM ROM Type A READING : %s"), diag_load_subrom_a ? "OK" : "NG");
2405 diag_load_subrom_b = false;
2406 if(read_bios(_T("SUBSYS_B.ROM"), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
2407 this->out_debug_log(_T("SUBSYSTEM ROM Type B READING : %s"), diag_load_subrom_b ? "OK" : "NG");
2409 diag_load_subrom_cg = false;
2410 if(read_bios(_T("SUBSYSCG.ROM"), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
2411 this->out_debug_log(_T("SUBSYSTEM CG ROM READING : %s"), diag_load_subrom_cg ? "OK" : "NG");
2412 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2413 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2414 memset(subsys_ram, 0x00, sizeof(subsys_ram));
2415 memset(submem_cgram, 0x00, sizeof(submem_cgram));
2416 memset(submem_console_av40, 0x00, sizeof(submem_console_av40));
2420 #if defined(_FM77AV_VARIANTS)
2422 apalette_index.d = 0;
2423 for(i = 0; i < 4096; i++) {
2424 analog_palette_r[i] = i & 0x0f0;
2425 analog_palette_g[i] = (i & 0xf00) >> 4;
2426 analog_palette_b[i] = (i & 0x00f) << 4;
2430 #if defined(_FM77AV_VARIANTS)
2431 hblank_event_id = -1;
2432 hdisp_event_id = -1;
2433 vsync_event_id = -1;
2434 vstart_event_id = -1;
2441 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
2442 is_cyclesteal = true;
2444 is_cyclesteal = false;
2446 // emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2447 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2451 key_firq_req = false; //firq_mask = true;
2452 frame_skip_count = 3;
2453 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2454 palette_changed = true;
2455 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
2456 //register_vline_event(this);
2457 //register_frame_event(this);
2462 void DISPLAY::release()
2466 #define STATE_VERSION 7
2467 void DISPLAY::save_state(FILEIO *state_fio)
2469 state_fio->FputUint32_BE(STATE_VERSION);
2470 state_fio->FputInt32_BE(this_device_id);
2471 this->out_debug_log("Save State: DISPLAY : id=%d ver=%d\n", this_device_id, STATE_VERSION);
2475 state_fio->FputInt32_BE(clr_count);
2476 state_fio->FputBool(halt_flag);
2477 state_fio->FputInt32_BE(active_page);
2478 state_fio->FputBool(sub_busy);
2479 state_fio->FputBool(crt_flag);
2480 state_fio->FputBool(vram_wrote);
2481 state_fio->FputBool(is_cyclesteal);
2483 state_fio->FputBool(clock_fast);
2485 #if defined(_FM77AV_VARIANTS)
2486 state_fio->FputBool(subcpu_resetreq);
2487 state_fio->FputBool(power_on_reset);
2489 state_fio->FputBool(cancel_request);
2490 state_fio->FputBool(key_firq_req);
2492 state_fio->FputInt32_BE(display_mode);
2493 state_fio->FputUint32_BE(prev_clock);
2496 state_fio->Fwrite(dpalette_data, sizeof(dpalette_data), 1);
2497 state_fio->FputUint8(multimode_accessmask);
2498 state_fio->FputUint8(multimode_dispmask);
2500 state_fio->FputUint32_BE(offset_point);
2501 #if defined(_FM77AV_VARIANTS)
2502 state_fio->FputUint32_BE(offset_point_bank1);
2504 for(i = 0; i < 2; i++) {
2505 state_fio->FputUint32_BE(tmp_offset_point[i].d);
2506 state_fio->FputBool(offset_changed[i]);
2508 state_fio->FputBool(offset_77av);
2509 state_fio->FputBool(diag_load_subrom_c);
2512 state_fio->Fwrite(io_w_latch, sizeof(io_w_latch), 1);
2513 state_fio->Fwrite(console_ram, sizeof(console_ram), 1);
2514 state_fio->Fwrite(work_ram, sizeof(work_ram), 1);
2515 state_fio->Fwrite(shared_ram, sizeof(shared_ram), 1);
2516 state_fio->Fwrite(subsys_c, sizeof(subsys_c), 1);
2517 state_fio->Fwrite(gvram, sizeof(gvram), 1);
2518 state_fio->Fwrite(gvram_shadow, sizeof(gvram_shadow), 1);
2520 #if defined(_FM77_VARIANTS)
2521 state_fio->FputBool(kanjisub);
2522 state_fio->FputUint16_BE(kanjiaddr.w.l);
2523 # if defined(_FM77L4)
2524 state_fio->FputBool(mode400line);
2525 state_fio->FputBool(stat_400linecard);
2527 #elif defined(_FM77AV_VARIANTS)
2528 state_fio->FputBool(kanjisub);
2529 state_fio->FputUint16_BE(kanjiaddr.w.l);
2531 state_fio->FputBool(vblank);
2532 state_fio->FputBool(vsync);
2533 state_fio->FputBool(hblank);
2534 state_fio->FputInt32_BE(vblank_count);
2536 state_fio->FputBool(mode320);
2537 state_fio->FputInt8(display_page);
2538 state_fio->FputInt8(display_page_bak);
2539 state_fio->FputInt32_BE(cgrom_bank);
2540 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
2541 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2542 state_fio->FputInt32_BE(vram_bank);
2545 state_fio->FputUint32_BE(displine);
2546 state_fio->FputUint8(subrom_bank);
2547 state_fio->FputUint8(subrom_bank_using);
2549 state_fio->FputBool(nmi_enable);
2550 state_fio->FputBool(use_alu);
2552 state_fio->FputUint8(apalette_index.b.l);
2553 state_fio->FputUint8(apalette_index.b.h);
2554 state_fio->Fwrite(analog_palette_r, sizeof(analog_palette_r), 1);
2555 state_fio->Fwrite(analog_palette_g, sizeof(analog_palette_g), 1);
2556 state_fio->Fwrite(analog_palette_b, sizeof(analog_palette_b), 1);
2559 state_fio->FputBool(diag_load_subrom_a);
2560 state_fio->FputBool(diag_load_subrom_b);
2561 state_fio->FputBool(diag_load_subrom_cg);
2563 state_fio->Fwrite(subsys_a, sizeof(subsys_a), 1);
2564 state_fio->Fwrite(subsys_b, sizeof(subsys_b), 1);
2565 state_fio->Fwrite(subsys_cg, sizeof(subsys_cg), 1);
2566 state_fio->Fwrite(submem_hidden, sizeof(submem_hidden), 1);
2567 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2568 state_fio->FputBool(mode400line);
2569 state_fio->FputBool(mode256k);
2571 state_fio->FputBool(monitor_ram);
2572 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2573 state_fio->FputUint16_BE(window_low);
2574 state_fio->FputUint16_BE(window_high);
2575 state_fio->FputUint16_BE(window_xbegin);
2576 state_fio->FputUint16_BE(window_xend);
2577 state_fio->FputBool(window_opened);
2579 state_fio->FputBool(kanji_level2);
2581 state_fio->FputUint8(vram_active_block);
2582 state_fio->FputUint8(vram_display_block);
2583 state_fio->FputUint8(console_ram_bank);
2584 state_fio->FputBool(ram_protect);
2586 state_fio->FputUint32_BE(cgram_bank);
2587 state_fio->Fwrite(subsys_ram, sizeof(subsys_ram), 1);
2588 state_fio->Fwrite(submem_cgram, sizeof(submem_cgram), 1);
2589 state_fio->Fwrite(submem_console_av40, sizeof(submem_console_av40), 1);
2595 state_fio->FputInt32_BE(nmi_event_id);
2596 #if defined(_FM77AV_VARIANTS)
2597 state_fio->FputInt32_BE(hblank_event_id);
2598 state_fio->FputInt32_BE(hdisp_event_id);
2599 state_fio->FputInt32_BE(vsync_event_id);
2600 state_fio->FputInt32_BE(vstart_event_id);
2602 state_fio->FputBool(firq_mask);
2603 state_fio->FputBool(vram_accessflag);
2604 state_fio->FputUint32_BE(frame_skip_count);
2608 bool DISPLAY::load_state(FILEIO *state_fio)
2611 uint32_t version = state_fio->FgetUint32_BE();
2612 if(this_device_id != state_fio->FgetInt32_BE()) {
2615 this->out_debug_log("Load State: DISPLAY : id=%d ver=%d\n", this_device_id, version);
2620 clr_count = state_fio->FgetInt32_BE();
2621 halt_flag = state_fio->FgetBool();
2622 active_page = state_fio->FgetInt32_BE();
2623 sub_busy = state_fio->FgetBool();
2624 crt_flag = state_fio->FgetBool();
2625 vram_wrote = state_fio->FgetBool();
2626 crt_flag_bak = true;
2627 for(i = 0; i < 411; i++) vram_wrote_table[i] = true;
2628 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
2629 is_cyclesteal = state_fio->FgetBool();
2631 clock_fast = state_fio->FgetBool();
2633 #if defined(_FM77AV_VARIANTS)
2634 subcpu_resetreq = state_fio->FgetBool();
2635 power_on_reset = state_fio->FgetBool();
2637 cancel_request = state_fio->FgetBool();
2638 key_firq_req = state_fio->FgetBool();
2640 display_mode = state_fio->FgetInt32_BE();
2641 prev_clock = state_fio->FgetUint32_BE();
2644 for(addr = 0; addr < 8; addr++) set_dpalette(addr, addr);
2646 state_fio->Fread(dpalette_data, sizeof(dpalette_data), 1);
2647 for(addr = 0; addr < 8; addr++) set_dpalette(addr, dpalette_data[addr]);
2648 multimode_accessmask = state_fio->FgetUint8();
2649 multimode_dispmask = state_fio->FgetUint8();
2651 offset_point = state_fio->FgetUint32_BE();
2652 #if defined(_FM77AV_VARIANTS)
2653 offset_point_bank1 = state_fio->FgetUint32_BE();
2655 for(i = 0; i < 2; i++) {
2656 tmp_offset_point[i].d = state_fio->FgetUint32_BE();
2657 offset_changed[i] = state_fio->FgetBool();
2659 offset_77av = state_fio->FgetBool();
2660 diag_load_subrom_c = state_fio->FgetBool();
2662 state_fio->Fread(io_w_latch, sizeof(io_w_latch), 1);
2663 state_fio->Fread(console_ram, sizeof(console_ram), 1);
2664 state_fio->Fread(work_ram, sizeof(work_ram), 1);
2665 state_fio->Fread(shared_ram, sizeof(shared_ram), 1);
2666 state_fio->Fread(subsys_c, sizeof(subsys_c), 1);
2667 state_fio->Fread(gvram, sizeof(gvram), 1);
2668 state_fio->Fread(gvram_shadow, sizeof(gvram_shadow), 1);
2669 #if defined(_FM77_VARIANTS)
2670 kanjisub = state_fio->FgetBool();
2672 kanjiaddr.w.l = state_fio->FgetUint16_BE();
2673 # if defined(_FM77L4)
2674 mode400line = state_fio->FgetBool();
2675 stat_400linecard = state_fio->FgetBool();
2677 #elif defined(_FM77AV_VARIANTS)
2678 kanjisub = state_fio->FgetBool();
2680 kanjiaddr.w.l = state_fio->FgetUint16_BE();
2682 vblank = state_fio->FgetBool();
2683 vsync = state_fio->FgetBool();
2684 hblank = state_fio->FgetBool();
2685 vblank_count = state_fio->FgetInt32_BE();
2687 mode320 = state_fio->FgetBool();
2688 display_page = state_fio->FgetInt8();
2689 display_page_bak = state_fio->FgetInt8();
2690 cgrom_bank = state_fio->FgetInt32_BE();
2691 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
2692 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2693 vram_bank = state_fio->FgetInt32_BE();
2695 screen_update_flag = true;
2696 displine = state_fio->FgetUint32_BE();
2697 subrom_bank = state_fio->FgetUint8();
2698 subrom_bank_using = state_fio->FgetUint8();
2700 nmi_enable = state_fio->FgetBool();
2701 use_alu = state_fio->FgetBool();
2703 apalette_index.b.l = state_fio->FgetUint8();
2704 apalette_index.b.h = state_fio->FgetUint8();
2706 state_fio->Fread(analog_palette_r, sizeof(analog_palette_r), 1);
2707 state_fio->Fread(analog_palette_g, sizeof(analog_palette_g), 1);
2708 state_fio->Fread(analog_palette_b, sizeof(analog_palette_b), 1);
2709 for(i = 0; i < 4096; i++) calc_apalette(i);
2711 diag_load_subrom_a = state_fio->FgetBool();
2712 diag_load_subrom_b = state_fio->FgetBool();
2713 diag_load_subrom_cg = state_fio->FgetBool();
2715 state_fio->Fread(subsys_a, sizeof(subsys_a), 1);
2716 state_fio->Fread(subsys_b, sizeof(subsys_b), 1);
2717 state_fio->Fread(subsys_cg, sizeof(subsys_cg), 1);
2718 state_fio->Fread(submem_hidden, sizeof(submem_hidden), 1);
2720 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2721 mode400line = state_fio->FgetBool();
2722 mode256k = state_fio->FgetBool();
2724 monitor_ram = state_fio->FgetBool();
2725 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2726 window_low = state_fio->FgetUint16_BE();
2727 window_high = state_fio->FgetUint16_BE();
2728 window_xbegin = state_fio->FgetUint16_BE();
2729 window_xend = state_fio->FgetUint16_BE();
2730 window_opened = state_fio->FgetBool();
2732 kanji_level2 = state_fio->FgetBool();
2734 vram_active_block = state_fio->FgetUint8();
2735 vram_display_block = state_fio->FgetUint8();
2736 console_ram_bank = state_fio->FgetUint8();
2737 ram_protect = state_fio->FgetBool();
2739 cgram_bank = state_fio->FgetUint32_BE();
2740 state_fio->Fread(subsys_ram, sizeof(subsys_ram), 1);
2741 state_fio->Fread(submem_cgram, sizeof(submem_cgram), 1);
2742 state_fio->Fread(submem_console_av40, sizeof(submem_console_av40), 1);
2745 palette_changed = true;
2746 vram_wrote_shadow = true; // Force Draw
2747 this->draw_screen();
2748 if(version == 1) return true;
2750 if(version >= 2) { //V2
2751 nmi_event_id = state_fio->FgetInt32_BE();
2752 #if defined(_FM77AV_VARIANTS)
2753 hblank_event_id = state_fio->FgetInt32_BE();
2754 hdisp_event_id = state_fio->FgetInt32_BE();
2755 vsync_event_id = state_fio->FgetInt32_BE();
2756 vstart_event_id = state_fio->FgetInt32_BE();
2758 firq_mask = state_fio->FgetBool();
2759 vram_accessflag = state_fio->FgetBool();
2760 frame_skip_count = state_fio->FgetUint32_BE();
2762 if(version == STATE_VERSION) return true;