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)
40 void DISPLAY::reset_cpuonly()
44 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
45 mainio->write_signal(SIG_FM7_SUB_HALT, 0x00, 0xff);
48 multimode_accessmask = 0;
49 multimode_dispmask = 0;
51 //cancel_request = false;
52 switch(config.cpu_type){
63 for(i = 0; i < 2; i++) {
64 offset_changed[i] = true;
65 tmp_offset_point[i].d = 0;
68 vram_wrote_shadow = true;
69 for(i = 0; i < 411; i++) vram_wrote_table[i] = true;
70 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
72 #if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
79 if(hblank_event_id >= 0) cancel_event(this, hblank_event_id);
80 if(hdisp_event_id >= 0) cancel_event(this, hdisp_event_id);
81 if(vsync_event_id >= 0) cancel_event(this, vsync_event_id);
82 if(vstart_event_id >= 0) cancel_event(this, vstart_event_id);
87 if(display_mode == DISPLAY_MODE_8_400L) {
93 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
94 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
95 mainio->write_signal(SIG_DISPLAY_VSYNC, 0xff, 0xff);
97 #if defined(_FM77AV_VARIANTS)
99 offset_point_bank1 = 0;
101 display_page_bak = 0;
104 subcpu_resetreq = false;
105 subrom_bank_using = subrom_bank;
110 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
112 vram_display_block = 0;
113 vram_active_block = 0;
115 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
120 window_opened = false;
125 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
126 alu->write_signal(SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
127 alu->write_signal(SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400: 200, 0xffff);
128 alu->write_signal(SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xffffffff : 0, 0xffffffff);
130 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
131 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
132 alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
134 alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
135 alu->write_signal(SIG_ALU_PLANES, 3, 3);
138 for(i = 0; i < 8; i++) set_dpalette(i, i);
139 do_firq(!firq_mask && key_firq_req);
141 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
143 kanjiaddr.d = 0x00000000;
144 # if defined(_FM77L4)
146 stat_400linecard = false;
151 frame_skip_count = 3;
155 void DISPLAY::reset()
159 memset(io_w_latch, 0xff, sizeof(io_w_latch));
161 vram_accessflag = true;
162 display_mode = DISPLAY_MODE_8_200L;
164 screen_update_flag = true;
167 cancel_request = false;
168 #if defined(_FM77AV_VARIANTS)
170 apalette_index.d = 0;
171 for(i = 0; i < 4096; i++) {
172 analog_palette_r[i] = i & 0x0f0;
173 analog_palette_g[i] = i & 0xf00;
174 analog_palette_b[i] = i & 0x00f;
179 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
186 #elif defined(_FM77L4)
189 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
190 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
191 key_firq_req = false; //firq_mask = true;
195 #if defined(_FM77AV_VARIANTS)
196 power_on_reset = false;
197 for(i = 0; i < 411; i++) vram_wrote_table[i] = false;
201 for(i = 0; i < 8; i++) set_dpalette(i, i);
202 multimode_accessmask = 0x00;
203 multimode_dispmask = 0x00;
208 if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
209 register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
210 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
214 void DISPLAY::update_config()
218 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
224 * Vram accessing functions moved to vram.cpp .
227 void DISPLAY::do_irq(bool flag)
229 subcpu->write_signal(SIG_CPU_IRQ, flag ? 1: 0, 1);
232 void DISPLAY::do_firq(bool flag)
234 subcpu->write_signal(SIG_CPU_FIRQ, flag ? 1: 0, 1);
237 void DISPLAY::do_nmi(bool flag)
239 #if defined(_FM77AV_VARIANTS)
240 if(!nmi_enable) flag = false;
242 subcpu->write_signal(SIG_CPU_NMI, flag ? 1 : 0, 1);
245 void DISPLAY::set_multimode(uint8_t val)
248 multimode_accessmask = val & 0x07;
249 multimode_dispmask = (val & 0x70) >> 4;
251 # if defined(_FM77AV_VARIANTS)
252 alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
257 uint8_t DISPLAY::get_multimode(void)
263 val = multimode_accessmask & 0x07;
264 val |= ((multimode_dispmask << 4) & 0x70);
270 uint8_t DISPLAY::get_cpuaccessmask(void)
272 return multimode_accessmask & 0x07;
275 void DISPLAY::set_dpalette(uint32_t addr, uint8_t val)
279 dpalette_data[addr] = val | 0xf8; //0b11111000;
281 b = ((val & 0x01) != 0x00)? 255 : 0x00;
282 r = ((val & 0x02) != 0x00)? 255 : 0x00;
283 g = ((val & 0x04) != 0x00)? 255 : 0x00;
285 dpalette_pixel[addr] = RGB_COLOR(r, g, b);
288 uint8_t DISPLAY::get_dpalette(uint32_t addr)
296 data = dpalette_data[addr];
301 void DISPLAY::halt_subcpu(void)
303 subcpu->write_signal(SIG_CPU_BUSREQ, 0x01, 0x01);
306 void DISPLAY::go_subcpu(void)
308 subcpu->write_signal(SIG_CPU_BUSREQ, 0x00, 0x01);
311 void DISPLAY::enter_display(void)
315 subclock = SUBCLOCK_NORMAL;
317 subclock = SUBCLOCK_SLOW;
319 if(!is_cyclesteal && vram_accessflag) {
320 subclock = subclock / 3;
322 if(prev_clock != subclock) p_vm->set_cpu_clock(subcpu, subclock);
323 prev_clock = subclock;
326 void DISPLAY::leave_display(void)
330 void DISPLAY::halt_subsystem(void)
336 void DISPLAY::restart_subsystem(void)
339 #if defined(_FM77AV_VARIANTS)
340 if(subcpu_resetreq) {
341 firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
343 power_on_reset = true;
344 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
346 do_firq(!firq_mask && key_firq_req);
353 void DISPLAY::set_crtflag(void)
360 void DISPLAY::reset_crtflag(void)
367 uint8_t DISPLAY::acknowledge_irq(void)
369 cancel_request = false;
375 uint8_t DISPLAY::beep(void)
377 mainio->write_signal(FM7_MAINIO_BEEP, 0x01, 0x01);
378 return 0xff; // True?
383 uint8_t DISPLAY::attention_irq(void)
385 mainio->write_signal(FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
390 void DISPLAY::set_cyclesteal(uint8_t val)
393 # if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
397 is_cyclesteal = true;
399 is_cyclesteal = false;
407 uint8_t DISPLAY::set_vramaccess(void)
409 vram_accessflag = true;
414 void DISPLAY::reset_vramaccess(void)
416 vram_accessflag = false;
420 uint8_t DISPLAY::reset_subbusy(void)
427 void DISPLAY::set_subbusy(void)
433 #if defined(_FM77AV_VARIANTS)
435 void DISPLAY::alu_write_cmdreg(uint32_t val)
437 alu->write_data8(ALU_CMDREG, val);
438 if((val & 0x80) != 0) {
446 void DISPLAY::alu_write_logical_color(uint8_t val)
448 uint32_t data = (uint32_t)val;
449 alu->write_data8(ALU_LOGICAL_COLOR, data);
453 void DISPLAY::alu_write_mask_reg(uint8_t val)
455 uint32_t data = (uint32_t)val;
456 alu->write_data8(ALU_WRITE_MASKREG, data);
460 void DISPLAY::alu_write_cmpdata_reg(int addr, uint8_t val)
462 uint32_t data = (uint32_t)val;
464 alu->write_data8(ALU_CMPDATA_REG + addr, data);
468 void DISPLAY::alu_write_disable_reg(uint8_t val)
470 uint32_t data = (uint32_t)val;
471 alu->write_data8(ALU_BANK_DISABLE, data);
475 void DISPLAY::alu_write_tilepaint_data(uint32_t addr, uint8_t val)
477 uint32_t data = (uint32_t)val;
480 alu->write_data8(ALU_TILEPAINT_B, data);
483 alu->write_data8(ALU_TILEPAINT_R, data);
486 alu->write_data8(ALU_TILEPAINT_G, data);
489 //alu->write_data8(ALU_TILEPAINT_L, 0xff);
495 void DISPLAY::alu_write_offsetreg_hi(uint8_t val)
497 alu->write_data8(ALU_OFFSET_REG_HIGH, val & 0x7f);
501 void DISPLAY::alu_write_offsetreg_lo(uint8_t val)
503 alu->write_data8(ALU_OFFSET_REG_LO, val);
507 void DISPLAY::alu_write_linepattern_hi(uint8_t val)
509 alu->write_data8(ALU_LINEPATTERN_REG_HIGH, val);
513 void DISPLAY::alu_write_linepattern_lo(uint8_t val)
515 alu->write_data8(ALU_LINEPATTERN_REG_LO, val);
519 void DISPLAY::alu_write_line_position(int addr, uint8_t val)
521 uint32_t data = (uint32_t)val;
524 alu->write_data8(ALU_LINEPOS_START_X_HIGH, data & 0x03);
527 alu->write_data8(ALU_LINEPOS_START_X_LOW, data);
530 alu->write_data8(ALU_LINEPOS_START_Y_HIGH, data & 0x01);
533 alu->write_data8(ALU_LINEPOS_START_Y_LOW, data);
536 alu->write_data8(ALU_LINEPOS_END_X_HIGH, data & 0x03);
539 alu->write_data8(ALU_LINEPOS_END_X_LOW, data);
542 alu->write_data8(ALU_LINEPOS_END_Y_HIGH, data & 0x01);
545 alu->write_data8(ALU_LINEPOS_END_Y_LOW, data);
551 uint8_t DISPLAY::get_miscreg(void)
556 if(!hblank) ret |= 0x80;
557 if(vsync) ret |= 0x04;
558 if(alu->read_signal(SIG_ALU_BUSYSTAT) == 0) ret |= 0x10;
559 if(power_on_reset) ret |= 0x01;
564 void DISPLAY::set_miscreg(uint8_t val)
566 int old_display_page = display_page;
568 nmi_enable = ((val & 0x80) == 0) ? true : false;
569 if(!nmi_enable) do_nmi(false);
571 if((val & 0x40) == 0) {
576 if(display_page != old_display_page) {
579 active_page = ((val & 0x20) == 0) ? 0 : 1;
580 if((val & 0x04) == 0) {
585 cgrom_bank = val & 0x03;
589 void DISPLAY::set_monitor_bank(uint8_t var)
591 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
592 if((var & 0x04) != 0){
598 subrom_bank = var & 0x03;
601 subcpu_resetreq = false;
602 power_on_reset = true;
603 firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
605 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
607 do_firq(!firq_mask && key_firq_req);
609 subcpu_resetreq = true;
615 void DISPLAY::set_apalette_index_hi(uint8_t val)
617 apalette_index.b.h = val & 0x0f;
621 void DISPLAY::set_apalette_index_lo(uint8_t val)
623 apalette_index.b.l = val;
626 void DISPLAY::calc_apalette(uint16_t idx)
630 g = analog_palette_g[idx];
631 r = analog_palette_r[idx];
632 b = analog_palette_b[idx];
633 analog_palette_pixel[idx] = RGB_COLOR(r, g, b);
637 void DISPLAY::set_apalette_b(uint8_t val)
641 index = apalette_index.w.l;
642 tmp = (val & 0x0f) << 4;
643 if(analog_palette_b[index] != tmp) {
644 analog_palette_b[index] = tmp;
645 calc_apalette(index);
651 void DISPLAY::set_apalette_r(uint8_t val)
655 index = apalette_index.w.l;
656 tmp = (val & 0x0f) << 4;
657 if(analog_palette_r[index] != tmp) {
658 analog_palette_r[index] = tmp;
659 calc_apalette(index);
665 void DISPLAY::set_apalette_g(uint8_t val)
669 index = apalette_index.w.l;
670 tmp = (val & 0x0f) << 4;
671 if(analog_palette_g[index] != tmp) {
672 analog_palette_g[index] = tmp;
673 calc_apalette(index);
678 #endif // _FM77AV_VARIANTS
681 void DISPLAY::copy_vram_blank_area(void)
686 void DISPLAY::copy_vram_per_line(void)
695 uint32_t src_offset_d1;
696 uint32_t src_offset_d2;
697 uint32_t src_offset_d;
702 //int dline = (int)displine - 1;
703 int dline = (int)displine;
705 if(dline < 0) return;
706 if(display_mode == DISPLAY_MODE_8_400L) {
707 if(dline >= 400) return;
709 if(dline >= 200) return;
711 #if defined(_FM77AV_VARIANTS)
712 yoff_d1 = offset_point;
713 yoff_d2 = offset_point_bank1;
714 if(display_mode == DISPLAY_MODE_4096) {
715 src_offset = dline * 40;
716 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
719 bytes_d1 = 0x2000 - ((src_offset + yoff_d1) & 0x1fff);
720 bytes_d2 = 0x2000 - ((src_offset + yoff_d2) & 0x1fff);
721 for(k = 0; k < pages; k++) {
722 for(i = 0; i < 3; i++) {
723 for(j = 0; j < 2; j++) {
724 src_base = i * 0x4000 + j * 0x2000;
726 memcpy(&gvram_shadow[src_offset + src_base + poff],
727 &gvram[((src_offset + yoff_d1) & 0x1fff) + src_base + poff],
729 memcpy(&gvram_shadow[src_offset + bytes_d1 + src_base + poff],
730 &gvram[src_base + poff],
733 memcpy(&gvram_shadow[src_offset + src_base + poff],
734 &gvram[((src_offset + yoff_d1) & 0x1fff) + src_base + poff],
737 src_base = i * 0x4000 + j * 0x2000 + 0xc000;
739 memcpy(&gvram_shadow[src_offset + src_base + poff],
740 &gvram[((src_offset + yoff_d2) & 0x1fff) + src_base + poff],
742 memcpy(&gvram_shadow[src_offset + bytes_d2 + src_base + poff],
743 &gvram[src_base + poff],
746 memcpy(&gvram_shadow[src_offset + src_base + poff],
747 &gvram[((src_offset + yoff_d2) & 0x1fff) + src_base + poff],
754 vram_draw_table[dline] = true;
755 vram_wrote_table[dline] = false;
757 # if defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV40)
758 else if(display_mode == DISPLAY_MODE_256k) {
759 src_offset = dline * 40;
761 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
763 #elif defined(_FM77AV40)
768 src_offset_d1 = (src_offset + yoff_d1) & 0x1fff;
769 src_offset_d2 = (src_offset + yoff_d2) & 0x1fff;
770 bytes_d1 = 0x2000 - ((src_offset + yoff_d1) & 0x1fff);
771 bytes_d2 = 0x2000 - ((src_offset + yoff_d2) & 0x1fff);
772 for(k = 0; k < pages; k++) {
773 for(i = 0; i < 3; i++) {
774 for(j = 0; j < 2; j++) {
776 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
777 src_offset_d = src_offset_d1;
780 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
781 src_offset_d = src_offset_d2;
785 memcpy(&gvram_shadow[src_offset + src_base],
786 &gvram[src_offset_d + src_base],
788 memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
792 memcpy(&gvram_shadow[src_offset + src_base],
793 &gvram[src_offset_d + src_base],
799 vram_draw_table[dline] = true;
800 vram_wrote_table[dline] = false;
802 else if(display_mode == DISPLAY_MODE_8_400L) {
803 src_offset = dline * 80;
804 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
806 # elif defined(_FM77AV40)
809 if(display_page_bak == 1) { // Is this dirty?
814 yoff_d = (yoff_d << 1) & 0x7fff;
815 src_offset_d = (src_offset + yoff_d) & 0x7fff;
816 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
817 for(i = 0; i < pages; i++) {
818 for(j = 0; j < 3; j++) {
819 src_base = i * 0x18000 + j * 0x8000;
821 memcpy(&gvram_shadow[src_offset + src_base],
822 &gvram[src_offset_d + src_base],
824 memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
828 memcpy(&gvram_shadow[src_offset + src_base + poff],
829 &gvram[src_offset_d + src_base],
834 vram_draw_table[dline] = true;
835 vram_wrote_table[dline] = false;
839 src_offset = dline * 80;
840 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
842 #elif defined(_FM77AV40)
844 #elif defined(_FM77AV_VARIANTS)
849 src_offset_d1 = (src_offset + yoff_d1) & 0x3fff;
850 src_offset_d2 = (src_offset + yoff_d2) & 0x3fff;
851 bytes_d1 = 0x4000 - ((src_offset + yoff_d1) & 0x3fff);
852 bytes_d2 = 0x4000 - ((src_offset + yoff_d2) & 0x3fff);
853 for(i = 0; i < pages; i++) {
854 for(j = 0; j < 3; j++) {
855 src_base = j * 0x4000;
857 src_offset_d = src_offset_d1;
860 src_offset_d = src_offset_d2;
864 memcpy(&gvram_shadow[src_offset + src_base + poff],
865 &gvram[src_offset_d + src_base + poff],
867 memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
868 &gvram[src_base + poff],
871 memcpy(&gvram_shadow[src_offset + src_base + poff],
872 &gvram[src_offset_d + src_base + poff],
878 vram_draw_table[dline] = true;
879 vram_wrote_table[dline] = false;
883 src_offset = dline * 80;
886 yoff_d = offset_point;
887 src_offset_d = (src_offset + yoff_d) & 0x3fff;
888 bytes_d = 0x4000 - ((src_offset + yoff_d) & 0x3fff);
889 for(j = 0; j < 3; j++) {
890 src_base = j * 0x4000;
892 memcpy(&gvram_shadow[src_offset + src_base + poff],
893 &gvram[src_offset_d + src_base + poff],
895 memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
896 &gvram[src_base + poff],
899 memcpy(&gvram_shadow[src_offset + src_base + poff],
900 &gvram[src_offset_d + src_base + poff],
904 vram_draw_table[dline] = true;
905 vram_wrote_table[dline] = false;
911 void DISPLAY::copy_vram_all()
913 #if defined(_FM77AV_VARIANTS)
914 uint32_t yoff_d1 = offset_point;
915 uint32_t yoff_d2 = offset_point_bank1;
916 uint32_t src_offset_1, src_offset_2;
918 if(display_mode == DISPLAY_MODE_4096) {
919 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
924 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
925 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
926 for(int k = 0; k < pages; k++) {
927 for(int i = 0; i < 3; i++) {
928 for(int j = 0; j < 2; j++) {
929 src_offset_1 = i * 0x4000 + j * 0x2000;
930 src_offset_2 = src_offset_1 + 0xc000;
931 memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
932 memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
933 memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
934 memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
940 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
941 else if(display_mode == DISPLAY_MODE_256k) {
942 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
943 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
944 for(int i = 0; i < 3; i++) {
945 for(int j = 0; j < 2; j++) {
946 src_offset_1 = i * 0x4000 + j * 0x2000;
947 src_offset_2 = src_offset_1 + 0xc000;
948 memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
949 memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
950 memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
951 memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
955 for(int i = 0; i < 3; i++) {
956 for(int j = 0; j < 2; j++) {
957 src_offset_1 = i * 0x4000 + j * 0x2000;
958 memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
959 memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
962 } else if(display_mode == DISPLAY_MODE_8_400L) {
963 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
971 if(display_page_bak == 1) { // Is this dirty?
976 yoff_d = (yoff_d << 1) & 0x7fff;
977 bytes_d = 0x8000 - yoff_d;
978 for(int k = 0; k < pages; k++) {
979 for(int i = 0; i < 3; i++) {
980 src_offset_1 = i * 0x8000;
981 memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + yoff_d + poff], bytes_d);
982 memcpy(&gvram_shadow[src_offset_1 + bytes_d + poff], &gvram[src_offset_1 + poff], 0x8000 - bytes_d);
989 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
991 #elif defined(_FM77AV40)
996 uint32_t bytes_d1 = 0x4000 - (yoff_d1 & 0x3fff);
997 uint32_t bytes_d2 = 0x4000 - (yoff_d2 & 0x3fff);
998 uint32_t yoff_d, bytes_d;
999 for(int k = 0; k < pages; k++) {
1000 yoff_d = ((k & 1) == 0) ? (yoff_d1 & 0x3fff) : (yoff_d2 & 0x3fff);
1001 bytes_d = ((k & 1) == 0) ? bytes_d1 : bytes_d2;
1002 for(int j = 0; j < 3; j++) {
1003 src_offset_1 = k * 0xc000 + j * 0x4000;
1004 memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1005 memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1011 uint32_t yoff_d = offset_point & 0x3fff;
1012 uint32_t bytes_d = 0x4000 - (offset_point & 0x3fff);
1013 uint32_t src_offset_1;
1014 for(int j = 0; j < 3; j++) {
1015 src_offset_1 = j * 0x4000;
1016 memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1017 memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1023 // Timing values from XM7 . Thanks Ryu.
1024 void DISPLAY::event_callback(int event_id, int err)
1029 case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
1030 #if defined(_FM77AV_VARIANTS)
1040 case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
1043 #if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1044 case EVENT_FM7SUB_HDISP:
1047 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x02, 0xff);
1048 //if(displine == 0) enter_display();
1049 if(display_mode == DISPLAY_MODE_8_400L) {
1051 if(displine < 400) f = true;
1054 if(displine < 200) f = true;
1057 register_event(this, EVENT_FM7SUB_HBLANK, usec, false, &hblank_event_id); // NEXT CYCLE_
1064 case EVENT_FM7SUB_HBLANK:
1066 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1068 if(display_mode == DISPLAY_MODE_8_400L) {
1069 if((displine < 400)) f = true;
1071 if((displine < 200)) f = true;
1073 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
1074 if(vram_wrote_table[displine]) copy_vram_per_line();
1077 if(display_mode == DISPLAY_MODE_8_400L) {
1082 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id);
1086 case EVENT_FM7SUB_VSTART: // Call first.
1091 display_page_bak = display_page;
1093 // Parameter from XM7/VM/display.c , thanks, Ryu.
1094 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1095 mainio->write_signal(SIG_DISPLAY_VSYNC, 0x00, 0xff);
1096 if(vblank_count != 0) {
1097 if(display_mode == DISPLAY_MODE_8_400L) {
1098 usec = (0.98 + 16.4) * 1000.0;
1100 usec = (1.91 + 12.7) * 1000.0;
1102 register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
1104 if(display_mode == DISPLAY_MODE_8_400L) {
1105 usec = 930.0; // 939.0
1107 usec = 1840.0; // 1846.5
1109 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
1113 if(display_mode == DISPLAY_MODE_8_400L) {
1114 usec = 0.34 * 1000.0;
1116 usec = 1.52 * 1000.0;
1118 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1123 case EVENT_FM7SUB_VSYNC:
1128 if(display_mode == DISPLAY_MODE_8_400L) {
1129 usec = 0.33 * 1000.0;
1131 usec = 0.51 * 1000.0;
1133 mainio->write_signal(SIG_DISPLAY_VSYNC, 0x01, 0xff);
1134 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1135 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1136 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) {
1140 if(display_mode == DISPLAY_MODE_8_400L) lines = 400;
1141 for(int yy = 0; yy < lines; yy++) {
1142 if(vram_wrote_table[yy]) {
1143 vram_wrote_table[yy] = false;
1151 for(int yy = 0; yy < 400; yy++) vram_draw_table[yy] = true;
1153 vram_wrote_shadow = true;
1154 screen_update_flag = true;
1159 for(int yy = 0; yy < 400; yy++) {
1160 vram_draw_table[yy] = true;
1161 //vram_wrote_table[yy] = false;
1164 for(int yy = 0; yy < 400; yy++) {
1165 if(vram_draw_table[yy]) {
1166 vram_wrote_shadow = true;
1167 screen_update_flag = true;
1175 case EVENT_FM7SUB_CLR_BUSY:
1178 case EVENT_FM7SUB_CLR_CRTFLAG:
1184 void DISPLAY::event_frame()
1186 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1191 for(yy = 0; yy < 400; yy++) {
1192 if(vram_wrote_table[yy]) {
1201 for(yy = 0; yy < 400; yy++) {
1202 vram_draw_table[yy] = true;
1203 vram_wrote_table[yy] = false;
1205 screen_update_flag = true;
1206 vram_wrote_shadow = true;
1213 void DISPLAY::event_vline(int v, int clock)
1215 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1221 uint32_t DISPLAY::read_signal(int id)
1223 uint32_t retval = 0;
1225 case SIG_FM7_SUB_HALT:
1226 case SIG_DISPLAY_HALT:
1227 retval = (halt_flag) ? 0xffffffff : 0;
1229 case SIG_DISPLAY_BUSY:
1230 retval = (sub_busy) ? 0x80 : 0;
1232 case SIG_DISPLAY_MULTIPAGE:
1233 retval = multimode_accessmask;
1235 case SIG_DISPLAY_PLANES:
1238 #if defined(_FM77AV_VARIANTS)
1239 case SIG_DISPLAY_VSYNC:
1240 retval = (vsync) ? 0x01 : 0x00;
1242 case SIG_DISPLAY_DISPLAY:
1243 retval = (!hblank) ? 0x02: 0x00;
1245 case SIG_FM7_SUB_BANK: // Main: FD13
1246 retval = subrom_bank & 0x03;
1247 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1248 if(monitor_ram) retval |= 0x04;
1252 #if defined(_FM77AV_VARIANTS)
1253 case SIG_DISPLAY_MODE320:
1254 retval = (mode320) ? 0x40: 0x00;
1257 case SIG_DISPLAY_Y_HEIGHT:
1258 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1259 retval = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
1264 case SIG_DISPLAY_X_WIDTH:
1265 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1266 retval = (mode320 || mode256k) ? 320 : 640;
1267 #elif defined(_FM77AV_VARIANTS)
1268 retval = (mode320) ? 320 : 640;
1279 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
1281 bool flag = ((data & mask) != 0);
1284 case SIG_FM7_SUB_HALT:
1289 //mainio->write_signal(SIG_FM7_SUB_HALT, data, mask);
1291 case SIG_DISPLAY_HALT:
1295 restart_subsystem();
1298 case SIG_FM7_SUB_CANCEL:
1300 cancel_request = true;
1304 case SIG_DISPLAY_CLOCK:
1308 #if defined(_FM77AV_VARIANTS)
1309 case SIG_FM7_SUB_BANK: // Main: FD13
1310 set_monitor_bank(data & 0xff);
1313 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1314 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1315 //printf("Wrote $FD04: %02x\n", data);
1317 int oldmode = display_mode;
1319 kanjisub = ((data & 0x20) == 0) ? true : false;
1320 mode256k = (((data & 0x10) != 0) && ((data & 0x08) != 0) ) ? true : false;
1321 mode400line = ((data & 0x08) == 0) ? true : false;
1322 ram_protect = ((data & 0x04) == 0) ? true : false;
1323 if(mode400line && !mode320) {
1324 display_mode = DISPLAY_MODE_8_400L;
1325 } else if(mode256k) {
1326 display_mode = DISPLAY_MODE_256k;
1328 display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1330 if(oldmode != display_mode) {
1332 if(mode320 || mode256k) {
1333 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1334 for(y = 0; y < 200; y++) {
1335 pp = emu->get_screen_buffer(y);
1336 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1338 } else if(display_mode == DISPLAY_MODE_8_400L) {
1339 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1340 for(y = 0; y < 400; y++) {
1341 pp = emu->get_screen_buffer(y);
1342 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1345 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1346 for(y = 0; y < 200; y++) {
1347 pp = emu->get_screen_buffer(y);
1348 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1352 alu->write_signal(SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
1353 alu->write_signal(SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200, 0xffff);
1354 alu->write_signal(SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xff : 0x00, 0xff);
1355 frame_skip_count = 3;
1358 #elif defined(_FM77_VARIANTS)
1360 int oldmode = display_mode;
1361 kanjisub = ((data & 0x20) == 0) ? true : false;
1362 # if defined(_FM77L4)
1363 stat_400linecard = ((data & 0x20) != 0) ? true : false;
1364 mode400line = ((data & 0x08) != 0) ? false : true;
1365 if(mode400line && stat_400linecard) {
1366 display_mode = DISPLAY_MODE_8_400L_TEXT;
1367 } else if(stat_400linecard) {
1368 display_mode = DISPLAY_MODE_8_200L_TEXT;
1370 display_mode = DISPLAY_MODE_8_200L;
1376 #if defined(_FM77AV_VARIANTS)
1377 case SIG_DISPLAY_MODE320: // FD12 bit 6
1378 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1380 //printf("Wrote $FD12: %02x\n", data);
1381 int oldmode = display_mode;
1383 if(!mode320 && !mode256k) {
1384 //display_mode = (mode400line) ? DISPLAY_MODE_8_400L : DISPLAY_MODE_8_200L;
1385 display_mode = DISPLAY_MODE_8_200L;
1387 display_mode = (mode256k) ? DISPLAY_MODE_256k : DISPLAY_MODE_4096;
1389 if(oldmode != display_mode) {
1391 if(mode320 || mode256k) {
1392 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1393 for(y = 0; y < 200; y++) {
1394 pp = emu->get_screen_buffer(y);
1395 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1397 } else { // 200 lines, 8 colors.
1398 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1399 for(y = 0; y < 200; y++) {
1400 pp = emu->get_screen_buffer(y);
1401 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1405 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
1406 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
1407 alu->write_signal(SIG_ALU_400LINE, 0x00, 0xff);
1408 //frame_skip_count = 3;
1416 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1417 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 320 * sizeof(scrntype_t));
1419 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1420 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
1423 display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1424 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
1425 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
1426 alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
1431 case SIG_DISPLAY_MULTIPAGE:
1432 set_multimode(data);
1434 case SIG_FM7_SUB_KEY_MASK:
1435 if(firq_mask == flag) {
1436 do_firq(!flag && key_firq_req);
1440 case SIG_FM7_SUB_KEY_FIRQ:
1441 do_firq(flag & !(firq_mask));
1442 key_firq_req = flag;
1444 case SIG_FM7_SUB_USE_CLR:
1446 clr_count = data & 0x03;
1457 * Vram accessing functions moved to vram.cpp .
1460 uint8_t DISPLAY::read_mmio(uint32_t addr)
1462 uint32_t retval = 0xff;
1464 if(addr < 0xd400) return 0xff;
1466 #if !defined(_FM77AV_VARIANTS)
1467 raddr = (addr - 0xd400) & 0x000f;
1468 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
1469 raddr = (addr - 0xd400) & 0x003f;
1470 #else // FM77AV40EX || FM77AV40SX
1471 raddr = (addr - 0xd400) & 0x00ff;
1474 case 0x00: // Read keyboard
1475 retval = (keyboard->read_data8(0x00) != 0) ? 0xff : 0x7f;
1477 case 0x01: // Read keyboard
1478 retval = keyboard->read_data8(0x01) & 0xff;
1480 case 0x02: // Acknowledge
1489 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1490 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
1492 if(!kanjisub) return 0xff;
1493 # if !defined(_FM77_VARIANTS)
1495 return (uint8_t)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1498 if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1501 if(!kanjisub) return 0xff;
1502 # if !defined(_FM77_VARIANTS)
1504 return (uint8_t)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1507 if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1514 retval = set_vramaccess();
1520 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
1522 #if defined(_FM77AV_VARIANTS)
1525 retval = alu->read_data8(ALU_CMDREG);
1528 retval = alu->read_data8(ALU_LOGICAL_COLOR);
1531 retval = alu->read_data8(ALU_WRITE_MASKREG);
1534 retval = alu->read_data8(ALU_CMP_STATUS_REG);
1537 retval = alu->read_data8(ALU_BANK_DISABLE);
1539 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1540 case 0x2f: // VRAM BANK
1541 retval = 0xfc | (vram_bank & 0x03);
1546 retval = get_miscreg();
1550 retval = keyboard->read_data8(0x31);
1553 retval = keyboard->read_data8(0x32);
1559 return (uint8_t)retval;
1562 uint32_t DISPLAY::read_vram_data8(uint32_t addr)
1565 uint32_t page_offset = 0;
1566 uint32_t page_mask = 0x3fff;
1567 uint32_t color = (addr >> 14) & 0x03;
1570 #if defined(_FM77AV_VARIANTS)
1571 if (active_page != 0) {
1572 offset = offset_point_bank1;
1574 offset = offset_point;
1577 offset = offset_point;
1580 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1581 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1582 if(vram_active_block != 0) page_offset = 0x18000;
1584 if(display_mode == DISPLAY_MODE_8_400L) {
1585 if(addr >= 0x8000) return 0xff;
1586 color = vram_bank & 0x03;
1587 if(color > 2) color = 0;
1589 pagemod = 0x8000 * color;
1590 return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
1593 #if defined(_FM77AV40)
1595 page_offset = 0xc000 * (vram_bank & 0x03);
1597 page_offset = 0; // right?
1600 page_offset = 0xc000 * (vram_bank & 0x03);
1603 pagemod = addr & 0xe000;
1607 pagemod = addr & 0xe000;
1609 pagemod = addr & 0xc000;
1611 if(active_page != 0) {
1612 page_offset += 0xc000;
1615 return gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1617 #elif defined(_FM77AV_VARIANTS)
1619 if(active_page != 0) {
1620 page_offset += 0xc000;
1624 pagemod = addr & 0xe000;
1626 pagemod = addr & 0xc000;
1628 return gvram[(((addr + offset) & page_mask) | pagemod) + page_offset];
1630 #elif defined(_FM77L4) //_FM77L4
1632 if(display_mode == DISPLAY_MODE_8_400L) {
1633 return (uint32_t)read_vram_l4_400l(addr, offset);
1635 pagemod = addr & 0xc000;
1636 return gvram[((addr + offset) & 0x3fff) | pagemod];
1640 #else // Others (77/7/8)
1641 pagemod = addr & 0xc000;
1642 return gvram[((addr + offset) & 0x3fff) | pagemod];
1646 void DISPLAY::write_dma_data8(uint32_t addr, uint32_t data)
1648 uint32_t raddr = addr & 0xffff;
1651 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1652 if(display_mode == DISPLAY_MODE_8_400L) {
1653 color = vram_bank & 0x03;
1654 if(color > 2) color = 0;
1656 color = (addr >> 14) & 0x03;
1660 if((multimode_accessmask & (1 << color)) != 0) return;
1662 return write_vram_data8(raddr, (uint8_t)data);
1664 return write_data8_main(raddr, (uint8_t)data);
1669 void DISPLAY::write_vram_data8(uint32_t addr, uint8_t data)
1672 uint32_t page_offset = 0;
1673 uint32_t page_mask = 0x3fff;
1674 uint32_t color = (addr >> 14) & 0x03;
1677 #if defined(_FM77AV_VARIANTS)
1678 if (active_page != 0) {
1679 offset = offset_point_bank1;
1681 offset = offset_point;
1684 offset = offset_point;
1687 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1688 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1689 if(vram_active_block != 0) page_offset = 0x18000;
1691 if(display_mode == DISPLAY_MODE_8_400L) {
1692 if(addr >= 0x8000) {
1695 color = vram_bank & 0x03;
1696 if(color > 2) color = 0;
1698 pagemod = 0x8000 * color;
1699 gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset] = data;
1700 //vram_wrote_table[((addr + offset) % 0x8000) / 80] = true;
1701 vram_wrote_table[(addr & 0x7fff) / 80] = true;
1702 } else if(display_mode == DISPLAY_MODE_256k) {
1703 #if defined(_FM77AV40)
1705 page_offset = 0xc000 * (vram_bank & 0x03);
1707 page_offset = 0; // right?
1710 page_offset = 0xc000 * (vram_bank & 0x03);
1713 pagemod = addr & 0xe000;
1714 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1715 //vram_wrote_table[((addr + offset) % 0x2000) / 40] = true;
1716 vram_wrote_table[(addr & page_mask) / 40] = true;
1718 } else if(display_mode == DISPLAY_MODE_4096) {
1719 if(active_page != 0) {
1720 page_offset += 0xc000;
1723 pagemod = addr & 0xe000;
1724 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1725 //vram_wrote_table[((addr + offset) % 0x2000) / 40] = true;
1726 vram_wrote_table[(addr & page_mask) / 40] = true;
1728 if(active_page != 0) {
1729 page_offset += 0xc000;
1732 pagemod = addr & 0xc000;
1733 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1734 //vram_wrote_table[((addr + offset) & page_mask) / 80] = true;
1735 vram_wrote_table[(addr & page_mask) / 80] = true;
1738 #elif defined(_FM77AV_VARIANTS)
1739 if(display_mode == DISPLAY_MODE_4096) {
1740 if(active_page != 0) {
1741 page_offset = 0xc000;
1744 pagemod = addr & 0xe000;
1745 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1746 //vram_wrote_table[((addr + offset) % 0x2000) / 40] = true;
1747 vram_wrote_table[(addr & page_mask) / 40] = true;
1749 if(active_page != 0) {
1750 page_offset = 0xc000;
1753 pagemod = addr & 0xc000;
1754 gvram[(((addr + offset) & page_mask) | pagemod) + page_offset] = data;
1755 //vram_wrote_table[((addr + offset) % 0x4000) / 80] = true;
1756 vram_wrote_table[(addr & page_mask) / 80] = true;
1758 #elif defined(_FM77L4) //_FM77L4
1760 if(display_mode == DISPLAY_MODE_8_400L) {
1761 write_vram_l4_400l(addr, data, offset);
1763 pagemod = addr & 0xc000;
1764 gvram[((addr + offset) & 0x3fff) | pagemod] = data;
1766 vram_wrote_table[(addr & 0x3fff) / 80] = true;
1768 #else // Others (77/7/8)
1769 pagemod = addr & 0xc000;
1770 gvram[((addr + offset) & 0x3fff) | pagemod] = data;
1771 vram_wrote_table[(addr & 0x3fff) / 80] = true;
1775 uint32_t DISPLAY::read_data8_main(uint32_t addr)
1778 if(addr < 0xc000) return 0xff;
1780 raddr = addr - 0xc000;
1781 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1783 if(console_ram_bank >= 1) {
1784 return submem_console_av40[((console_ram_bank - 1) << 12) + raddr];
1788 return console_ram[raddr];
1789 } else if(addr < 0xd380) {
1790 raddr = addr - 0xd000;
1791 return work_ram[raddr];
1792 } else if(addr < 0xd400) {
1793 raddr = addr - 0xd380;
1794 return shared_ram[raddr];
1795 } else if(addr < 0xd800) {
1796 #if defined(_FM77AV_VARIANTS)
1797 if(addr >= 0xd500) {
1798 return submem_hidden[addr - 0xd500];
1801 return read_mmio(addr);
1802 } else if(addr < 0x10000) {
1803 #if !defined(_FM77AV_VARIANTS)
1804 return subsys_c[addr - 0xd800];
1807 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
1809 return submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)]; //FIXME
1812 return subsys_cg[(addr - 0xd800) + cgrom_bank * 0x800];
1813 } else if(addr < 0x10000) {
1814 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
1816 return subsys_ram[addr - 0xe000];
1819 switch(subrom_bank_using & 3) {
1821 return subsys_c[addr - 0xd800];
1824 return subsys_a[addr - 0xe000];
1827 return subsys_b[addr - 0xe000];
1830 return subsys_cg[addr - 0xe000];
1839 uint32_t DISPLAY::read_dma_data8(uint32_t addr)
1841 uint32_t raddr = addr & 0xffff;
1844 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1845 if(display_mode == DISPLAY_MODE_8_400L) {
1846 color = vram_bank & 0x03;
1847 if(color > 2) color = 0;
1849 color = (addr >> 14) & 0x03;
1853 if((multimode_accessmask & (1 << color)) != 0) return 0xff;
1855 return read_vram_data8(raddr);
1857 return read_data8_main(raddr);
1862 uint32_t DISPLAY::read_data8(uint32_t addr)
1864 uint32_t raddr = addr;
1866 uint32_t color = (addr & 0x0c000) >> 14;
1868 #if defined(_FM77AV_VARIANTS)
1870 alu->read_data8(addr + ALU_WRITE_PROXY);
1873 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1874 if(display_mode == DISPLAY_MODE_8_400L) {
1875 color = vram_bank & 0x03;
1876 if(color > 2) color = 0;
1878 color = (addr >> 14) & 0x03;
1882 if((multimode_accessmask & (1 << color)) != 0) return 0xff;
1884 return read_vram_data8(addr);
1885 } else if(addr < 0x10000) {
1886 return read_data8_main(addr);
1889 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
1890 return dpalette_data[addr - FM7_SUBMEM_OFFSET_DPALETTE];
1893 #if defined(_FM77AV_VARIANTS)
1895 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
1896 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
1897 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1898 if(display_mode == DISPLAY_MODE_8_400L) {
1899 uint32_t page_offset = 0;
1900 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1901 if(vram_active_block != 0) page_offset = 0x18000;
1903 color = (addr & 0x18000) >> 15;
1904 if(color > 2) color = 0;
1906 if (active_page != 0) {
1907 offset = offset_point_bank1 << 1;
1909 offset = offset_point << 1;
1911 if(color > 2) color = 0;
1912 uint32_t pagemod = 0x8000 * color;
1913 return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset];
1916 return read_vram_data8(addr);
1923 * Vram accessing functions moved to vram.cpp .
1926 void DISPLAY::write_mmio(uint32_t addr, uint32_t data)
1930 if(addr < 0xd400) return;
1932 #if !defined(_FM77AV_VARIANTS)
1933 addr = (addr - 0xd400) & 0x000f;
1934 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
1935 addr = (addr - 0xd400) & 0x003f;
1936 #else // FM77AV40EX || FM77AV40SX
1937 addr = (addr - 0xd400) & 0x00ff;
1939 io_w_latch[addr] = (uint8_t)data;
1941 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4)
1944 set_cyclesteal((uint8_t)data);
1947 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1948 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
1951 if(!kanjisub) return;
1952 kanjiaddr.w.h = 0x0000;
1953 kanjiaddr.b.h = (uint8_t) data;
1956 if(!kanjisub) return;
1957 kanjiaddr.w.h = 0x0000;
1958 kanjiaddr.b.l = (uint8_t)data;
1971 if(clr_count <= 0) {
1973 } else { // Read once when using clr_foo() to set busy flag.
1976 usec = (1000.0 * 1000.0) / 2000000.0;
1978 usec = (1000.0 * 1000.0) / 999000.0;
1980 if(!is_cyclesteal && vram_accessflag) usec = usec * 3.0;
1981 usec = (double)clr_count * usec;
1982 register_event(this, EVENT_FM7SUB_CLR_BUSY, usec, false, NULL); // NEXT CYCLE_
1989 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
1994 rval = (uint8_t)data;
1995 if(offset_changed[active_page]) {
1996 #if defined(_FM77AV_VARIANTS)
1997 if(active_page != 0) {
1998 tmp_offset_point[active_page].d = offset_point_bank1;
2000 tmp_offset_point[active_page].d = offset_point;
2003 tmp_offset_point[active_page].d = offset_point;
2006 tmp_offset_point[active_page].w.h = 0x0000;
2008 tmp_offset_point[active_page].b.h = rval;
2010 tmp_offset_point[active_page].b.l = rval;
2012 offset_changed[active_page] = !offset_changed[active_page];
2013 if(offset_changed[active_page]) {
2015 #if defined(_FM77AV_VARIANTS)
2016 if(active_page != 0) {
2018 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fff;
2020 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fe0;
2024 offset_point = tmp_offset_point[active_page].d & 0x007fff;
2026 offset_point = tmp_offset_point[active_page].d & 0x007fe0;
2030 offset_point = tmp_offset_point[active_page].d & 0x7fe0;
2034 #if defined(_FM77AV_VARIANTS)
2037 alu_write_cmdreg(data);
2040 alu_write_logical_color(data);
2043 alu_write_mask_reg(data);
2046 alu_write_disable_reg(data);
2049 alu_write_offsetreg_hi(data);
2052 alu_write_offsetreg_lo(data);
2055 alu_write_linepattern_hi(data);
2058 alu_write_linepattern_lo(data);
2060 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2062 console_ram_bank = (data & 0x18) >> 3;
2063 if(console_ram_bank > 2) console_ram_bank = 0;
2064 cgram_bank = data & 0x07;
2065 kanji_level2 = ((data & 0x80) == 0) ? false : true;
2067 case 0x2f: // VRAM BANK
2068 vram_bank = data & 0x03;
2069 if(vram_bank > 2) vram_bank = 0;
2079 keyboard->write_data8(0x31, data);
2081 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2083 vram_active_block = data & 0x01;
2084 if(vram_display_block != (((data & 0x10) != 0) ? 1 : 0)) vram_wrote = true;
2085 vram_display_block = ((data & 0x10) != 0) ? 1 : 0;
2090 tmpvar.d = window_xbegin * 8;
2093 tmpvar.b.h = data & 0x03;
2095 tmpvar.b.l = data & 0xf8;
2097 if(mode320 || mode256k) {
2098 if(tmpvar.d > 320) tmpvar.d = 320;
2100 if(tmpvar.d > 640) tmpvar.d = 640;
2102 window_xbegin = tmpvar.d / 8;
2107 tmpvar.d = window_xend * 8;
2110 tmpvar.b.h = data & 0x03;
2112 tmpvar.b.l = data & 0xf8;
2114 if(mode320 || mode256k) {
2115 if(tmpvar.d > 320) tmpvar.d = 320;
2117 if(tmpvar.d > 640) tmpvar.d = 640;
2119 window_xend = tmpvar.d / 8;
2124 tmpvar.d = window_low;
2127 tmpvar.b.h = data & 0x03;
2129 tmpvar.b.l = data & 0xff;
2131 if(display_mode == DISPLAY_MODE_8_400L) {
2132 if(tmpvar.d > 400) tmpvar.d = 400;
2135 if(tmpvar.d > 400) tmpvar.d = 400;
2137 window_low = tmpvar.d;
2142 tmpvar.d = window_high;
2145 tmpvar.b.h = data & 0x03;
2147 tmpvar.b.l = data & 0xff;
2149 if(display_mode == DISPLAY_MODE_8_400L) {
2150 if(tmpvar.d > 400) tmpvar.d = 400;
2153 if(tmpvar.d > 400) tmpvar.d = 400;
2155 window_high = tmpvar.d;
2161 #if defined(_FM77AV_VARIANTS)
2163 if((addr >= 0x13) && (addr <= 0x1a)) {
2164 alu_write_cmpdata_reg(addr - 0x13, data);
2165 } else if((addr >= 0x1c) && (addr <= 0x1e)) {
2166 alu_write_tilepaint_data(addr, data);
2167 } else if((addr >= 0x24) && (addr <= 0x2b)) {
2168 alu_write_line_position(addr - 0x24, data);
2175 void DISPLAY::write_data8_main(uint32_t addr, uint8_t data)
2179 uint32_t page_offset = 0x0000;
2181 if(addr < 0xc000) return;
2184 raddr = addr - 0xc000;
2185 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2187 if(console_ram_bank >= 1) {
2188 submem_console_av40[((console_ram_bank - 1) << 12) + raddr] = data;
2193 console_ram[raddr] = data;
2195 } else if(addr < 0xd380) {
2196 raddr = addr - 0xd000;
2197 work_ram[raddr] = data;
2199 } else if(addr < 0xd400) {
2200 raddr = addr - 0xd380;
2201 shared_ram[raddr] = data;
2203 } else if(addr < 0xd800) {
2204 #if defined(_FM77AV_VARIANTS)
2205 if(addr >= 0xd500) {
2206 submem_hidden[addr - 0xd500] = data;
2210 write_mmio(addr, data);
2212 } else if(addr < 0x10000) {
2213 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2214 if(ram_protect) return;
2217 submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)] = data; //FIXME
2219 subsys_ram[addr - 0xe000] = data;
2227 void DISPLAY::write_data8(uint32_t addr, uint32_t data)
2231 uint32_t page_offset = 0x0000;
2232 uint8_t val8 = data & 0xff;
2234 uint32_t color = (addr & 0xc000) >> 14;
2237 #if defined(_FM77AV_VARIANTS)
2239 alu->read_data8(addr + ALU_WRITE_PROXY);
2242 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2243 if(display_mode == DISPLAY_MODE_8_400L) {
2244 color = vram_bank & 0x03;
2245 if(color > 2) color = 0;
2250 if((multimode_accessmask & (1 << color)) != 0) return;
2252 write_vram_data8(addr, val8);
2254 } else if(addr < 0x10000) {
2255 write_data8_main(addr, val8);
2259 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2260 set_dpalette(addr - FM7_SUBMEM_OFFSET_DPALETTE, val8);
2264 #if defined(_FM77AV_VARIANTS)
2266 else if(addr == FM7_SUBMEM_OFFSET_APALETTE_R) {
2267 set_apalette_r(val8);
2269 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_G) {
2270 set_apalette_g(val8);
2272 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_B) {
2273 set_apalette_b(val8);
2275 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_HI) {
2276 set_apalette_index_hi(val8);
2278 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_LO) {
2279 set_apalette_index_lo(val8);
2283 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2284 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2285 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2286 if(display_mode == DISPLAY_MODE_8_400L) {
2287 color = (addr & 0x18000) >> 15;
2288 if(color > 2) color = 0;
2290 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2291 if(vram_active_block != 0) page_offset = 0x18000;
2293 if(color > 2) color = 0;
2294 if (active_page != 0) {
2295 offset = offset_point_bank1 << 1;
2297 offset = offset_point << 1;
2299 pagemod = 0x8000 * color;
2300 gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset] = data;
2301 vram_wrote_table[(addr & 0x7fff) / 80] = true;
2304 write_vram_data8(addr, data);
2306 write_vram_data8(addr, data);
2308 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
2315 uint32_t DISPLAY::read_bios(const _TCHAR *name, uint8_t *ptr, uint32_t size)
2321 if((name == NULL) || (ptr == NULL)) return 0;
2322 s = create_local_path(name);
2323 if(s == NULL) return 0;
2325 if(!fio.Fopen(s, FILEIO_READ_BINARY)) return 0;
2326 blocks = fio.Fread(ptr, size, 1);
2329 return blocks * size;
2333 void DISPLAY::initialize()
2337 screen_update_flag = true;
2338 memset(gvram, 0x00, sizeof(gvram));
2339 vram_wrote_shadow = false;
2340 memset(gvram_shadow, 0x00, sizeof(gvram_shadow));
2341 for(i = 0; i < 411; i++) vram_wrote_table[i] = false;
2342 for(i = 0; i < 411; i++) vram_draw_table[i] = false;
2344 memset(console_ram, 0x00, sizeof(console_ram));
2345 memset(work_ram, 0x00, sizeof(work_ram));
2346 memset(shared_ram, 0x00, sizeof(shared_ram));
2347 memset(subsys_c, 0xff, sizeof(subsys_c));
2349 diag_load_subrom_c = false;
2351 if(read_bios(_T("SUBSYS_8.ROM"), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2352 emu->out_debug_log(_T("SUBSYSTEM ROM READING : %s"), diag_load_subrom_c ? "OK" : "NG");
2354 if(read_bios(_T("SUBSYS_C.ROM"), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2355 emu->out_debug_log(_T("SUBSYSTEM ROM Type C READING : %s"), diag_load_subrom_c ? "OK" : "NG");
2357 #if defined(_FM77AV_VARIANTS)
2358 memset(subsys_a, 0xff, sizeof(subsys_a));
2359 memset(subsys_b, 0xff, sizeof(subsys_b));
2360 memset(subsys_cg, 0xff, sizeof(subsys_cg));
2361 memset(submem_hidden, 0x00, sizeof(submem_hidden));
2363 diag_load_subrom_a = false;
2364 if(read_bios(_T("SUBSYS_A.ROM"), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
2365 emu->out_debug_log(_T("SUBSYSTEM ROM Type A READING : %s"), diag_load_subrom_a ? "OK" : "NG");
2367 diag_load_subrom_b = false;
2368 if(read_bios(_T("SUBSYS_B.ROM"), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
2369 emu->out_debug_log(_T("SUBSYSTEM ROM Type B READING : %s"), diag_load_subrom_b ? "OK" : "NG");
2371 diag_load_subrom_cg = false;
2372 if(read_bios(_T("SUBSYSCG.ROM"), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
2373 emu->out_debug_log(_T("SUBSYSTEM CG ROM READING : %s"), diag_load_subrom_cg ? "OK" : "NG");
2374 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2375 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2376 memset(subsys_ram, 0x00, sizeof(subsys_ram));
2377 memset(submem_cgram, 0x00, sizeof(submem_cgram));
2378 memset(submem_console_av40, 0x00, sizeof(submem_console_av40));
2382 #if defined(_FM77AV_VARIANTS)
2384 apalette_index.d = 0;
2385 for(i = 0; i < 4096; i++) {
2386 analog_palette_r[i] = i & 0x0f0;
2387 analog_palette_g[i] = i & 0xf00;
2388 analog_palette_b[i] = i & 0x00f;
2392 #if defined(_FM77AV_VARIANTS)
2393 hblank_event_id = -1;
2394 hdisp_event_id = -1;
2395 vsync_event_id = -1;
2396 vstart_event_id = -1;
2403 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
2404 is_cyclesteal = true;
2406 is_cyclesteal = false;
2408 // emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2409 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2413 key_firq_req = false; //firq_mask = true;
2414 frame_skip_count = 3;
2415 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2418 void DISPLAY::release()
2422 #define STATE_VERSION 6
2423 void DISPLAY::save_state(FILEIO *state_fio)
2425 state_fio->FputUint32_BE(STATE_VERSION);
2426 state_fio->FputInt32_BE(this_device_id);
2427 p_emu->out_debug_log("Save State: DISPLAY : id=%d ver=%d\n", this_device_id, STATE_VERSION);
2431 state_fio->FputInt32_BE(clr_count);
2432 state_fio->FputBool(halt_flag);
2433 state_fio->FputInt32_BE(active_page);
2434 state_fio->FputBool(sub_busy);
2435 state_fio->FputBool(crt_flag);
2436 state_fio->FputBool(vram_wrote);
2437 state_fio->FputBool(vram_wrote_shadow);
2438 for(i = 0; i < 411; i++) state_fio->FputBool(vram_wrote_table[i]);
2439 for(i = 0; i < 411; i++) state_fio->FputBool(vram_draw_table[i]);
2440 state_fio->FputBool(is_cyclesteal);
2442 state_fio->FputBool(clock_fast);
2444 #if defined(_FM77AV_VARIANTS)
2445 state_fio->FputBool(subcpu_resetreq);
2446 state_fio->FputBool(power_on_reset);
2448 state_fio->FputBool(cancel_request);
2449 state_fio->FputBool(key_firq_req);
2451 state_fio->FputInt32_BE(display_mode);
2452 state_fio->FputUint32_BE(prev_clock);
2455 state_fio->Fwrite(dpalette_data, sizeof(dpalette_data), 1);
2456 state_fio->FputUint8(multimode_accessmask);
2457 state_fio->FputUint8(multimode_dispmask);
2459 state_fio->FputUint32_BE(offset_point);
2460 #if defined(_FM77AV_VARIANTS)
2461 state_fio->FputUint32_BE(offset_point_bank1);
2463 for(i = 0; i < 2; i++) {
2464 state_fio->FputUint32_BE(tmp_offset_point[i].d);
2465 state_fio->FputBool(offset_changed[i]);
2467 state_fio->FputBool(offset_77av);
2468 state_fio->FputBool(diag_load_subrom_c);
2471 state_fio->Fwrite(io_w_latch, sizeof(io_w_latch), 1);
2472 state_fio->Fwrite(console_ram, sizeof(console_ram), 1);
2473 state_fio->Fwrite(work_ram, sizeof(work_ram), 1);
2474 state_fio->Fwrite(shared_ram, sizeof(shared_ram), 1);
2475 state_fio->Fwrite(subsys_c, sizeof(subsys_c), 1);
2476 state_fio->Fwrite(gvram, sizeof(gvram), 1);
2477 state_fio->Fwrite(gvram_shadow, sizeof(gvram_shadow), 1);
2479 #if defined(_FM77_VARIANTS)
2480 state_fio->FputBool(kanjisub);
2481 state_fio->FputUint16_BE(kanjiaddr.w.l);
2482 # if defined(_FM77L4)
2483 state_fio->FputBool(mode400line);
2484 state_fio->FputBool(stat_400linecard);
2486 #elif defined(_FM77AV_VARIANTS)
2487 state_fio->FputBool(kanjisub);
2488 state_fio->FputUint16_BE(kanjiaddr.w.l);
2490 state_fio->FputBool(vblank);
2491 state_fio->FputBool(vsync);
2492 state_fio->FputBool(hblank);
2493 state_fio->FputInt32_BE(vblank_count);
2495 state_fio->FputBool(mode320);
2496 state_fio->FputInt8(display_page);
2497 state_fio->FputInt8(display_page_bak);
2498 state_fio->FputInt32_BE(cgrom_bank);
2499 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
2500 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2501 state_fio->FputInt32_BE(vram_bank);
2504 state_fio->FputUint32_BE(displine);
2505 state_fio->FputUint8(subrom_bank);
2506 state_fio->FputUint8(subrom_bank_using);
2508 state_fio->FputBool(nmi_enable);
2509 state_fio->FputBool(use_alu);
2511 state_fio->FputUint8(apalette_index.b.l);
2512 state_fio->FputUint8(apalette_index.b.h);
2513 state_fio->Fwrite(analog_palette_r, sizeof(analog_palette_r), 1);
2514 state_fio->Fwrite(analog_palette_g, sizeof(analog_palette_g), 1);
2515 state_fio->Fwrite(analog_palette_b, sizeof(analog_palette_b), 1);
2518 state_fio->FputBool(diag_load_subrom_a);
2519 state_fio->FputBool(diag_load_subrom_b);
2520 state_fio->FputBool(diag_load_subrom_cg);
2522 state_fio->Fwrite(subsys_a, sizeof(subsys_a), 1);
2523 state_fio->Fwrite(subsys_b, sizeof(subsys_b), 1);
2524 state_fio->Fwrite(subsys_cg, sizeof(subsys_cg), 1);
2525 state_fio->Fwrite(submem_hidden, sizeof(submem_hidden), 1);
2526 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2527 state_fio->FputBool(mode400line);
2528 state_fio->FputBool(mode256k);
2530 state_fio->FputBool(monitor_ram);
2531 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2532 state_fio->FputUint16_BE(window_low);
2533 state_fio->FputUint16_BE(window_high);
2534 state_fio->FputUint16_BE(window_xbegin);
2535 state_fio->FputUint16_BE(window_xend);
2536 state_fio->FputBool(window_opened);
2538 state_fio->FputBool(kanji_level2);
2540 state_fio->FputUint8(vram_active_block);
2541 state_fio->FputUint8(vram_display_block);
2542 state_fio->FputUint8(console_ram_bank);
2543 state_fio->FputBool(ram_protect);
2545 state_fio->FputUint32_BE(cgram_bank);
2546 state_fio->Fwrite(subsys_ram, sizeof(subsys_ram), 1);
2547 state_fio->Fwrite(submem_cgram, sizeof(submem_cgram), 1);
2548 state_fio->Fwrite(submem_console_av40, sizeof(submem_console_av40), 1);
2554 state_fio->FputInt32_BE(nmi_event_id);
2555 #if defined(_FM77AV_VARIANTS)
2556 state_fio->FputInt32_BE(hblank_event_id);
2557 state_fio->FputInt32_BE(hdisp_event_id);
2558 state_fio->FputInt32_BE(vsync_event_id);
2559 state_fio->FputInt32_BE(vstart_event_id);
2561 state_fio->FputBool(firq_mask);
2562 state_fio->FputBool(vram_accessflag);
2563 state_fio->FputUint32_BE(frame_skip_count);
2567 bool DISPLAY::load_state(FILEIO *state_fio)
2570 uint32_t version = state_fio->FgetUint32_BE();
2571 if(this_device_id != state_fio->FgetInt32_BE()) {
2574 p_emu->out_debug_log("Load State: DISPLAY : id=%d ver=%d\n", this_device_id, version);
2579 clr_count = state_fio->FgetInt32_BE();
2580 halt_flag = state_fio->FgetBool();
2581 active_page = state_fio->FgetInt32_BE();
2582 sub_busy = state_fio->FgetBool();
2583 crt_flag = state_fio->FgetBool();
2584 vram_wrote = state_fio->FgetBool();
2585 crt_flag_bak = true;
2586 vram_wrote_shadow = state_fio->FgetBool();
2587 for(i = 0; i < 411; i++) vram_wrote_table[i] = state_fio->FgetBool();
2588 for(i = 0; i < 411; i++) vram_draw_table[i] = state_fio->FgetBool();
2589 is_cyclesteal = state_fio->FgetBool();
2591 clock_fast = state_fio->FgetBool();
2593 #if defined(_FM77AV_VARIANTS)
2594 subcpu_resetreq = state_fio->FgetBool();
2595 power_on_reset = state_fio->FgetBool();
2597 cancel_request = state_fio->FgetBool();
2598 key_firq_req = state_fio->FgetBool();
2600 display_mode = state_fio->FgetInt32_BE();
2601 prev_clock = state_fio->FgetUint32_BE();
2604 for(addr = 0; addr < 8; addr++) set_dpalette(addr, addr);
2606 state_fio->Fread(dpalette_data, sizeof(dpalette_data), 1);
2607 for(addr = 0; addr < 8; addr++) set_dpalette(addr, dpalette_data[addr]);
2608 multimode_accessmask = state_fio->FgetUint8();
2609 multimode_dispmask = state_fio->FgetUint8();
2611 offset_point = state_fio->FgetUint32_BE();
2612 #if defined(_FM77AV_VARIANTS)
2613 offset_point_bank1 = state_fio->FgetUint32_BE();
2615 for(i = 0; i < 2; i++) {
2616 tmp_offset_point[i].d = state_fio->FgetUint32_BE();
2617 offset_changed[i] = state_fio->FgetBool();
2619 offset_77av = state_fio->FgetBool();
2620 diag_load_subrom_c = state_fio->FgetBool();
2622 state_fio->Fread(io_w_latch, sizeof(io_w_latch), 1);
2623 state_fio->Fread(console_ram, sizeof(console_ram), 1);
2624 state_fio->Fread(work_ram, sizeof(work_ram), 1);
2625 state_fio->Fread(shared_ram, sizeof(shared_ram), 1);
2626 state_fio->Fread(subsys_c, sizeof(subsys_c), 1);
2627 state_fio->Fread(gvram, sizeof(gvram), 1);
2628 state_fio->Fread(gvram_shadow, sizeof(gvram_shadow), 1);
2629 #if defined(_FM77_VARIANTS)
2630 kanjisub = state_fio->FgetBool();
2632 kanjiaddr.w.l = state_fio->FgetUint16_BE();
2633 # if defined(_FM77L4)
2634 mode400line = state_fio->FgetBool();
2635 stat_400linecard = state_fio->FgetBool();
2637 #elif defined(_FM77AV_VARIANTS)
2638 kanjisub = state_fio->FgetBool();
2640 kanjiaddr.w.l = state_fio->FgetUint16_BE();
2642 vblank = state_fio->FgetBool();
2643 vsync = state_fio->FgetBool();
2644 hblank = state_fio->FgetBool();
2645 vblank_count = state_fio->FgetInt32_BE();
2647 mode320 = state_fio->FgetBool();
2648 display_page = state_fio->FgetInt8();
2649 display_page_bak = state_fio->FgetInt8();
2650 cgrom_bank = state_fio->FgetInt32_BE();
2651 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
2652 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2653 vram_bank = state_fio->FgetInt32_BE();
2655 screen_update_flag = true;
2656 displine = state_fio->FgetUint32_BE();
2657 subrom_bank = state_fio->FgetUint8();
2658 subrom_bank_using = state_fio->FgetUint8();
2660 nmi_enable = state_fio->FgetBool();
2661 use_alu = state_fio->FgetBool();
2663 apalette_index.b.l = state_fio->FgetUint8();
2664 apalette_index.b.h = state_fio->FgetUint8();
2666 state_fio->Fread(analog_palette_r, sizeof(analog_palette_r), 1);
2667 state_fio->Fread(analog_palette_g, sizeof(analog_palette_g), 1);
2668 state_fio->Fread(analog_palette_b, sizeof(analog_palette_b), 1);
2669 for(i = 0; i < 4096; i++) calc_apalette(i);
2671 diag_load_subrom_a = state_fio->FgetBool();
2672 diag_load_subrom_b = state_fio->FgetBool();
2673 diag_load_subrom_cg = state_fio->FgetBool();
2675 state_fio->Fread(subsys_a, sizeof(subsys_a), 1);
2676 state_fio->Fread(subsys_b, sizeof(subsys_b), 1);
2677 state_fio->Fread(subsys_cg, sizeof(subsys_cg), 1);
2678 state_fio->Fread(submem_hidden, sizeof(submem_hidden), 1);
2680 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2681 mode400line = state_fio->FgetBool();
2682 mode256k = state_fio->FgetBool();
2684 monitor_ram = state_fio->FgetBool();
2685 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2686 window_low = state_fio->FgetUint16_BE();
2687 window_high = state_fio->FgetUint16_BE();
2688 window_xbegin = state_fio->FgetUint16_BE();
2689 window_xend = state_fio->FgetUint16_BE();
2690 window_opened = state_fio->FgetBool();
2692 kanji_level2 = state_fio->FgetBool();
2694 vram_active_block = state_fio->FgetUint8();
2695 vram_display_block = state_fio->FgetUint8();
2696 console_ram_bank = state_fio->FgetUint8();
2697 ram_protect = state_fio->FgetBool();
2699 cgram_bank = state_fio->FgetUint32_BE();
2700 state_fio->Fread(subsys_ram, sizeof(subsys_ram), 1);
2701 state_fio->Fread(submem_cgram, sizeof(submem_cgram), 1);
2702 state_fio->Fread(submem_console_av40, sizeof(submem_console_av40), 1);
2705 bool vram_wrote_shadow_bak = vram_wrote_shadow;
2706 vram_wrote_shadow = true; // Force Draw
2707 this->draw_screen();
2708 vram_wrote_shadow = vram_wrote_shadow_bak;
2709 if(version == 1) return true;
2711 if(version >= 2) { //V2
2712 nmi_event_id = state_fio->FgetInt32_BE();
2713 #if defined(_FM77AV_VARIANTS)
2714 hblank_event_id = state_fio->FgetInt32_BE();
2715 hdisp_event_id = state_fio->FgetInt32_BE();
2716 vsync_event_id = state_fio->FgetInt32_BE();
2717 vstart_event_id = state_fio->FgetInt32_BE();
2719 firq_mask = state_fio->FgetBool();
2720 vram_accessflag = state_fio->FgetBool();
2721 frame_skip_count = state_fio->FgetUint32_BE();
2723 if(version == STATE_VERSION) return true;