2 * Common source code project -> FM-7 -> Display
3 * (C) 2015 K.Ohta <whatisthis.sowhat _at_ gmail.com>
5 * Feb 10, 2015 : Initial.
10 #include "../../fileio.h"
11 #include "fm7_display.h"
12 #if defined(_FM77AV_VARIANTS)
13 # include "mb61vh010.h"
16 DISPLAY::DISPLAY(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
23 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
26 #elif defined(_FM77_VARIANTS)
29 #if defined(_FM77AV_VARIANTS)
35 for(int i = 0; i < 256; i++) {
36 uint16_t n = (uint16_t)i;
37 for(int j = 0; j < 8; j++) {
38 bit_trans_table_0[i][j] = n & 0x80;
39 bit_trans_table_1[i][j] = ((n & 0x80) != 0) ? 0x40 : 0;
40 bit_trans_table_2[i][j] = ((n & 0x80) != 0) ? 0x20 : 0;
41 bit_trans_table_3[i][j] = ((n & 0x80) != 0) ? 0x10 : 0;
42 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
43 bit_trans_table_4[i][j] = ((n & 0x80) != 0) ? 0x08 : 0;
44 bit_trans_table_5[i][j] = ((n & 0x80) != 0) ? 0x04 : 0;
51 set_device_name(_T("DISPLAY SUBSYSTEM"));
59 void DISPLAY::reset_cpuonly()
63 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
64 mainio->write_signal(SIG_FM7_SUB_HALT, 0x00, 0xff);
67 palette_changed = true;
68 multimode_accessmask = 0;
69 multimode_dispmask = 0;
70 for(i = 0; i < 4; i++) {
71 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
72 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
75 //cancel_request = false;
76 switch(config.cpu_type){
85 prev_clock = SUBCLOCK_NORMAL;
87 prev_clock = SUBCLOCK_SLOW;
92 for(i = 0; i < 2; i++) {
93 offset_changed[i] = true;
94 tmp_offset_point[i].d = 0;
97 vram_wrote_shadow = true;
98 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
99 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
103 #if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
109 if(hblank_event_id >= 0) cancel_event(this, hblank_event_id);
110 if(hdisp_event_id >= 0) cancel_event(this, hdisp_event_id);
111 if(vsync_event_id >= 0) cancel_event(this, vsync_event_id);
112 if(vstart_event_id >= 0) cancel_event(this, vstart_event_id);
113 hblank_event_id = -1;
116 vstart_event_id = -1;
117 if(display_mode == DISPLAY_MODE_8_400L) {
118 usec = 0.33 * 1000.0;
120 usec = 0.51 * 1000.0;
123 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
124 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
125 mainio->write_signal(SIG_DISPLAY_VSYNC, 0xff, 0xff);
127 #if defined(_FM77AV_VARIANTS)
129 offset_point_bank1 = 0;
131 display_page_bak = 0;
133 subcpu_resetreq = false;
134 subrom_bank_using = subrom_bank;
139 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
141 vram_display_block = 0;
142 vram_active_block = 0;
144 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
149 window_opened = false;
154 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
155 alu->write_signal(SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
156 alu->write_signal(SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400: 200, 0xffff);
157 alu->write_signal(SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xffffffff : 0, 0xffffffff);
159 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
160 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
161 alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
163 alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
164 alu->write_signal(SIG_ALU_PLANES, 3, 3);
167 for(i = 0; i < 8; i++) set_dpalette(i, i);
168 do_firq(!firq_mask && key_firq_req);
170 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
172 kanjiaddr.d = 0x00000000;
173 # if defined(_FM77L4)
175 stat_400linecard = false;
180 frame_skip_count_draw = 3;
181 frame_skip_count_transfer = 3;
182 need_transfer_line = true;
183 setup_display_mode();
187 void DISPLAY::reset()
190 memset(io_w_latch, 0xff, sizeof(io_w_latch));
192 vram_accessflag = true;
193 display_mode = DISPLAY_MODE_8_200L;
195 screen_update_flag = true;
198 cancel_request = false;
199 #if defined(_FM77AV_VARIANTS)
201 apalette_index.d = 0;
202 for(i = 0; i < 4096; i++) {
203 analog_palette_r[i] = i & 0x0f0;
204 analog_palette_g[i] = (i & 0xf00) >> 4;
205 analog_palette_b[i] = (i & 0x00f) << 4;
210 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
217 #elif defined(_FM77L4)
220 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
221 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
222 key_firq_req = false; //firq_mask = true;
226 #if defined(_FM77AV_VARIANTS)
227 power_on_reset = false;
228 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
232 for(i = 0; i < 8; i++) set_dpalette(i, i);
233 //multimode_accessmask = 0x00;
234 //multimode_dispmask = 0x00;
235 //for(i = 0; i < 4; i++) {
236 // multimode_accessflags[i] = ((multimode_accessmask & (1 << color)) != 0) ? true : false;
237 // multimode_dispflags[i] = ((multimode_dispmask & (1 << color)) != 0) ? true : false;
243 if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
244 register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
245 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
249 void DISPLAY::setup_display_mode(void)
251 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
252 if(display_mode == DISPLAY_MODE_8_400L) {
253 page_offset = 0x0000;
254 pagemod_mask = 0x18000;
256 } else if(display_mode == DISPLAY_MODE_256k) {
257 if(active_page != 0) {
258 page_offset = 0xc000;
260 page_offset = 0x0000;
262 pagemod_mask = 0xe000;
264 } else if(display_mode == DISPLAY_MODE_4096) {
265 if(active_page != 0) {
266 page_offset = 0xc000;
268 page_offset = 0x0000;
270 pagemod_mask = 0xe000;
273 if(active_page != 0) {
274 page_offset = 0xc000;
276 page_offset = 0x0000;
278 pagemod_mask = 0xc000;
281 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
282 if(vram_active_block != 0) page_offset += 0x18000;
284 #elif defined(_FM77AV_VARIANTS)
287 pagemod_mask = 0xe000;
288 } else { // 640x200, 8colors
290 pagemod_mask = 0xc000;
292 if(active_page != 0) {
293 page_offset = 0xc000;
295 page_offset = 0x0000;
297 #elif defined(_FM77L4)
298 if(display_mode == DISPLAY_MODE_8_400L) {
300 pagemod_mask = 0xe000;
301 } else { // 640x200, 8colors
303 pagemod_mask = 0xc000;
305 page_offset = 0x0000;
307 page_offset = 0x0000;
308 pagemod_mask = 0xc000;
312 void DISPLAY::update_config()
316 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
322 * Vram accessing functions moved to vram.cpp .
325 void DISPLAY::do_irq(bool flag)
327 subcpu->write_signal(SIG_CPU_IRQ, flag ? 1: 0, 1);
330 void DISPLAY::do_firq(bool flag)
332 subcpu->write_signal(SIG_CPU_FIRQ, flag ? 1: 0, 1);
335 void DISPLAY::do_nmi(bool flag)
337 #if defined(_FM77AV_VARIANTS)
338 if(!nmi_enable) flag = false;
340 subcpu->write_signal(SIG_CPU_NMI, flag ? 1 : 0, 1);
343 void DISPLAY::set_multimode(uint8_t val)
346 multimode_accessmask = val & 0x07;
347 multimode_dispmask = (val & 0x70) >> 4;
348 for(int i = 0; i < 4; i++) {
349 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
350 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
353 # if defined(_FM77AV_VARIANTS)
354 alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
359 uint8_t DISPLAY::get_multimode(void)
365 val = multimode_accessmask & 0x07;
366 val |= ((multimode_dispmask << 4) & 0x70);
372 uint8_t DISPLAY::get_cpuaccessmask(void)
374 return multimode_accessmask & 0x07;
377 void DISPLAY::set_dpalette(uint32_t addr, uint8_t val)
381 dpalette_data[addr] = val | 0xf8; //0b11111000;
382 b = ((val & 0x01) != 0x00)? 255 : 0x00;
383 r = ((val & 0x02) != 0x00)? 255 : 0x00;
384 g = ((val & 0x04) != 0x00)? 255 : 0x00;
386 dpalette_pixel[addr] = RGB_COLOR(r, g, b);
387 palette_changed = true;
390 uint8_t DISPLAY::get_dpalette(uint32_t addr)
398 data = dpalette_data[addr];
403 void DISPLAY::halt_subcpu(void)
405 subcpu->write_signal(SIG_CPU_BUSREQ, 0x01, 0x01);
408 void DISPLAY::go_subcpu(void)
410 subcpu->write_signal(SIG_CPU_BUSREQ, 0x00, 0x01);
413 void DISPLAY::enter_display(void)
417 subclock = SUBCLOCK_NORMAL;
419 subclock = SUBCLOCK_SLOW;
421 if(!is_cyclesteal && vram_accessflag) {
422 subclock = subclock / 3;
424 if(prev_clock != subclock) p_vm->set_cpu_clock(subcpu, subclock);
425 prev_clock = subclock;
428 void DISPLAY::leave_display(void)
432 void DISPLAY::halt_subsystem(void)
438 void DISPLAY::restart_subsystem(void)
441 #if defined(_FM77AV_VARIANTS)
442 if(subcpu_resetreq) {
443 firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
445 power_on_reset = true;
446 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
448 do_firq(!firq_mask && key_firq_req);
455 void DISPLAY::set_crtflag(void)
462 void DISPLAY::reset_crtflag(void)
469 uint8_t DISPLAY::acknowledge_irq(void)
471 cancel_request = false;
477 uint8_t DISPLAY::beep(void)
479 mainio->write_signal(FM7_MAINIO_BEEP, 0x01, 0x01);
480 return 0xff; // True?
485 uint8_t DISPLAY::attention_irq(void)
487 mainio->write_signal(FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
492 void DISPLAY::set_cyclesteal(uint8_t val)
495 # if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
499 is_cyclesteal = true;
501 is_cyclesteal = false;
509 uint8_t DISPLAY::set_vramaccess(void)
511 vram_accessflag = true;
516 void DISPLAY::reset_vramaccess(void)
518 vram_accessflag = false;
522 uint8_t DISPLAY::reset_subbusy(void)
529 void DISPLAY::set_subbusy(void)
535 #if defined(_FM77AV_VARIANTS)
537 void DISPLAY::alu_write_cmdreg(uint32_t val)
539 alu->write_data8(ALU_CMDREG, val);
540 if((val & 0x80) != 0) {
548 void DISPLAY::alu_write_logical_color(uint8_t val)
550 uint32_t data = (uint32_t)val;
551 alu->write_data8(ALU_LOGICAL_COLOR, data);
555 void DISPLAY::alu_write_mask_reg(uint8_t val)
557 uint32_t data = (uint32_t)val;
558 alu->write_data8(ALU_WRITE_MASKREG, data);
562 void DISPLAY::alu_write_cmpdata_reg(int addr, uint8_t val)
564 uint32_t data = (uint32_t)val;
566 alu->write_data8(ALU_CMPDATA_REG + addr, data);
570 void DISPLAY::alu_write_disable_reg(uint8_t val)
572 uint32_t data = (uint32_t)val;
573 alu->write_data8(ALU_BANK_DISABLE, data);
577 void DISPLAY::alu_write_tilepaint_data(uint32_t addr, uint8_t val)
579 uint32_t data = (uint32_t)val;
582 alu->write_data8(ALU_TILEPAINT_B, data);
585 alu->write_data8(ALU_TILEPAINT_R, data);
588 alu->write_data8(ALU_TILEPAINT_G, data);
591 //alu->write_data8(ALU_TILEPAINT_L, 0xff);
597 void DISPLAY::alu_write_offsetreg_hi(uint8_t val)
599 alu->write_data8(ALU_OFFSET_REG_HIGH, val & 0x7f);
603 void DISPLAY::alu_write_offsetreg_lo(uint8_t val)
605 alu->write_data8(ALU_OFFSET_REG_LO, val);
609 void DISPLAY::alu_write_linepattern_hi(uint8_t val)
611 alu->write_data8(ALU_LINEPATTERN_REG_HIGH, val);
615 void DISPLAY::alu_write_linepattern_lo(uint8_t val)
617 alu->write_data8(ALU_LINEPATTERN_REG_LO, val);
621 void DISPLAY::alu_write_line_position(int addr, uint8_t val)
623 uint32_t data = (uint32_t)val;
626 alu->write_data8(ALU_LINEPOS_START_X_HIGH, data & 0x03);
629 alu->write_data8(ALU_LINEPOS_START_X_LOW, data);
632 alu->write_data8(ALU_LINEPOS_START_Y_HIGH, data & 0x01);
635 alu->write_data8(ALU_LINEPOS_START_Y_LOW, data);
638 alu->write_data8(ALU_LINEPOS_END_X_HIGH, data & 0x03);
641 alu->write_data8(ALU_LINEPOS_END_X_LOW, data);
644 alu->write_data8(ALU_LINEPOS_END_Y_HIGH, data & 0x01);
647 alu->write_data8(ALU_LINEPOS_END_Y_LOW, data);
653 uint8_t DISPLAY::get_miscreg(void)
658 if(!hblank) ret |= 0x80;
659 if(vsync) ret |= 0x04;
660 if(alu->read_signal(SIG_ALU_BUSYSTAT) == 0) ret |= 0x10;
661 if(power_on_reset) ret |= 0x01;
666 void DISPLAY::set_miscreg(uint8_t val)
668 int old_display_page = display_page;
670 nmi_enable = ((val & 0x80) == 0) ? true : false;
671 if(!nmi_enable) do_nmi(false);
673 if((val & 0x40) == 0) {
678 if(display_page != old_display_page) {
681 active_page = ((val & 0x20) == 0) ? 0 : 1;
682 if((val & 0x04) == 0) {
687 cgrom_bank = val & 0x03;
688 setup_display_mode();
692 void DISPLAY::set_monitor_bank(uint8_t var)
694 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
695 if((var & 0x04) != 0){
701 subrom_bank = var & 0x03;
704 subcpu_resetreq = false;
705 power_on_reset = true;
706 firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
708 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
710 do_firq(!firq_mask && key_firq_req);
712 subcpu_resetreq = true;
718 void DISPLAY::set_apalette_index_hi(uint8_t val)
720 apalette_index.b.h = val & 0x0f;
724 void DISPLAY::set_apalette_index_lo(uint8_t val)
726 apalette_index.b.l = val;
729 void DISPLAY::calc_apalette(uint16_t idx)
733 g = analog_palette_g[idx];
734 r = analog_palette_r[idx];
735 b = analog_palette_b[idx];
736 if(g != 0) g |= 0x0f;
737 if(r != 0) r |= 0x0f;
738 if(b != 0) b |= 0x0f;
739 analog_palette_pixel[idx] = RGB_COLOR(r, g, b);
743 void DISPLAY::set_apalette_b(uint8_t val)
747 index = apalette_index.w.l;
748 tmp = (val & 0x0f) << 4;
749 if(analog_palette_b[index] != tmp) {
750 analog_palette_b[index] = tmp;
751 calc_apalette(index);
752 palette_changed = true;
757 void DISPLAY::set_apalette_r(uint8_t val)
761 index = apalette_index.w.l;
762 tmp = (val & 0x0f) << 4;
763 if(analog_palette_r[index] != tmp) {
764 analog_palette_r[index] = tmp;
765 calc_apalette(index);
766 palette_changed = true;
771 void DISPLAY::set_apalette_g(uint8_t val)
775 index = apalette_index.w.l;
776 tmp = (val & 0x0f) << 4;
777 if(analog_palette_g[index] != tmp) {
778 analog_palette_g[index] = tmp;
779 calc_apalette(index);
780 palette_changed = true;
784 #endif // _FM77AV_VARIANTS
787 void DISPLAY::copy_vram_blank_area(void)
791 void DISPLAY::copy_vram_per_line(int begin, int end)
800 uint32_t src_offset_d1;
801 uint32_t src_offset_d2;
802 uint32_t src_offset_d;
807 uint32_t addr_d1, addr_d2;
811 //int dline = (int)displine - 1;
812 int dline = (int)displine;
814 if((begin < 0) || (begin > 4)) return;
815 if((end < 0) || (end > 4)) return;
816 if(begin > end) return;
817 if(dline < 0) return;
819 sectors = end - begin + 1;
821 if(display_mode == DISPLAY_MODE_8_400L) {
822 if(dline >= 400) return;
824 if(dline >= 200) return;
826 #if defined(_FM77AV_VARIANTS)
827 yoff_d1 = offset_point;
828 yoff_d2 = offset_point_bank1;
829 if(display_mode == DISPLAY_MODE_4096) {
830 src_offset = dline * 40 + begin * 8;
831 sectors = sectors * 8;
832 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
835 addr_d1 = (src_offset + yoff_d1) & 0x1fff;
836 addr_d2 = (src_offset + yoff_d2) & 0x1fff;
837 bytes_d1 = 0x2000 - addr_d1;
838 bytes_d2 = 0x2000 - addr_d2;
839 for(k = 0; k < pages; k++) {
841 for(i = 0; i < 3; i++) {
842 for(j = 0; j < 2; j++) {
843 uint32_t _addr_base = src_base + src_offset + poff;
844 if(bytes_d1 < sectors) {
845 my_memcpy(&gvram_shadow[_addr_base],
846 &gvram[addr_d1 + src_base + poff],
848 my_memcpy(&gvram_shadow[_addr_base + bytes_d1],
849 &gvram[src_base + poff],
852 my_memcpy(&gvram_shadow[_addr_base],
853 &gvram[addr_d1 + src_base + poff],
856 _addr_base += 0xc000;
857 if(bytes_d2 < sectors) {
858 my_memcpy(&gvram_shadow[_addr_base],
859 &gvram[addr_d2 + src_base + poff + 0xc000],
861 my_memcpy(&gvram_shadow[_addr_base + bytes_d2],
862 &gvram[src_base + poff + 0xc000],
865 my_memcpy(&gvram_shadow[_addr_base],
866 &gvram[addr_d2 + src_base + poff + 0xc000],
871 src_base = (i + 1) * 0x4000;
875 vram_draw_table[dline] = true;
876 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
878 # if defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV40)
879 else if(display_mode == DISPLAY_MODE_256k) {
880 src_offset = dline * 40 + begin * 8;
881 sectors = sectors * 8;
883 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
885 #elif defined(_FM77AV40)
890 src_offset_d1 = (src_offset + yoff_d1) & 0x1fff;
891 src_offset_d2 = (src_offset + yoff_d2) & 0x1fff;
892 bytes_d1 = 0x2000 - ((src_offset + yoff_d1) & 0x1fff);
893 bytes_d2 = 0x2000 - ((src_offset + yoff_d2) & 0x1fff);
894 for(k = 0; k < pages; k++) {
895 for(i = 0; i < 3; i++) {
896 for(j = 0; j < 2; j++) {
898 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
899 src_offset_d = src_offset_d1;
902 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
903 src_offset_d = src_offset_d2;
906 if(bytes_d < sectors) {
907 my_memcpy(&gvram_shadow[src_offset + src_base],
908 &gvram[src_offset_d + src_base],
910 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
914 my_memcpy(&gvram_shadow[src_offset + src_base],
915 &gvram[src_offset_d + src_base],
921 vram_draw_table[dline] = true;
922 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
924 else if(display_mode == DISPLAY_MODE_8_400L) {
925 src_offset = dline * 80 + begin * 16;
926 sectors = sectors * 16;
927 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
930 if(display_page_bak == 1) { // Is this dirty?
935 yoff_d = (yoff_d << 1) & 0x7fff;
936 src_offset_d = (src_offset + yoff_d) & 0x7fff;
937 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
938 for(i = 0; i < pages; i++) {
939 for(j = 0; j < 3; j++) {
940 src_base = i * 0x18000 + j * 0x8000;
941 if(bytes_d < sectors) {
943 my_memcpy(&gvram_shadow[src_offset + src_base],
944 &gvram[src_offset_d + src_base],
947 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
951 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
952 &gvram[src_offset_d + src_base],
957 vram_draw_table[dline] = true;
958 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
962 src_offset = dline * 80 + begin * 16;
963 sectors = sectors * 16;
964 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
966 #elif defined(_FM77AV40)
968 #elif defined(_FM77AV_VARIANTS)
974 src_offset_d1 = (src_offset + yoff_d1) & 0x3fff;
975 src_offset_d2 = (src_offset + yoff_d2) & 0x3fff;
976 bytes_d1 = 0x4000 - ((src_offset + yoff_d1) & 0x3fff);
977 bytes_d2 = 0x4000 - ((src_offset + yoff_d2) & 0x3fff);
978 for(i = 0; i < pages; i++) {
980 src_offset_d = src_offset_d1;
983 src_offset_d = src_offset_d2;
987 for(j = 0; j < 3; j++) {
988 if(bytes_d < sectors) {
989 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
990 &gvram[src_offset_d + src_base + poff],
992 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
993 &gvram[src_base + poff],
996 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
997 &gvram[src_offset_d + src_base + poff],
1004 vram_draw_table[dline] = true;
1005 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1006 //vram_wrote_table[dline] = false;
1010 src_offset = dline * 80 + begin * 16;
1011 sectors = sectors * 16;
1014 yoff_d = offset_point;
1015 src_offset_d = (src_offset + yoff_d) & 0x3fff;
1016 bytes_d = 0x4000 - ((src_offset + yoff_d) & 0x3fff);
1017 for(j = 0; j < 3; j++) {
1018 src_base = j * 0x4000;
1019 if(bytes_d < sectors) {
1020 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1021 &gvram[src_offset_d + src_base + poff],
1023 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1024 &gvram[src_base + poff],
1027 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1028 &gvram[src_offset_d + src_base + poff],
1032 vram_draw_table[dline] = true;
1033 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1034 //vram_wrote_table[dline] = false;
1040 void DISPLAY::copy_vram_all()
1042 #if defined(_FM77AV_VARIANTS)
1043 uint32_t yoff_d1 = offset_point;
1044 uint32_t yoff_d2 = offset_point_bank1;
1045 uint32_t src_offset_1, src_offset_2;
1047 if(display_mode == DISPLAY_MODE_4096) {
1048 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1053 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1054 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1055 for(int k = 0; k < pages; k++) {
1056 for(int i = 0; i < 3; i++) {
1057 for(int j = 0; j < 2; j++) {
1058 src_offset_1 = i * 0x4000 + j * 0x2000;
1059 src_offset_2 = src_offset_1 + 0xc000;
1060 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1061 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1062 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1063 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1069 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1070 else if(display_mode == DISPLAY_MODE_256k) {
1071 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1072 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1073 for(int i = 0; i < 3; i++) {
1074 for(int j = 0; j < 2; j++) {
1075 src_offset_1 = i * 0x4000 + j * 0x2000;
1076 src_offset_2 = src_offset_1 + 0xc000;
1077 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1078 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1079 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1080 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1084 for(int i = 0; i < 3; i++) {
1085 for(int j = 0; j < 2; j++) {
1086 src_offset_1 = i * 0x4000 + j * 0x2000;
1087 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1088 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1091 } else if(display_mode == DISPLAY_MODE_8_400L) {
1093 uint32_t yoff_d, bytes_d;
1094 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1097 if(display_page_bak == 1) { // Is this dirty?
1102 yoff_d = (yoff_d << 1) & 0x7fff;
1103 bytes_d = 0x8000 - yoff_d;
1104 for(int i = 0; i < pages; i++) {
1105 for(int j = 0; j < 3; j++) {
1106 uint32_t src_base = i * 0x18000 + j * 0x8000;
1107 my_memcpy(&gvram_shadow[src_base],
1108 &gvram[yoff_d + src_base],
1110 if(bytes_d < 0x8000) {
1111 my_memcpy(&gvram_shadow[bytes_d + src_base],
1120 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1122 #elif defined(_FM77AV40)
1127 uint32_t bytes_d1 = 0x4000 - (yoff_d1 & 0x3fff);
1128 uint32_t bytes_d2 = 0x4000 - (yoff_d2 & 0x3fff);
1129 uint32_t yoff_d, bytes_d;
1130 for(int k = 0; k < pages; k++) {
1131 yoff_d = ((k & 1) == 0) ? (yoff_d1 & 0x3fff) : (yoff_d2 & 0x3fff);
1132 bytes_d = ((k & 1) == 0) ? bytes_d1 : bytes_d2;
1133 for(int j = 0; j < 3; j++) {
1134 src_offset_1 = k * 0xc000 + j * 0x4000;
1135 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1136 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1142 uint32_t yoff_d = offset_point & 0x3fff;
1143 uint32_t bytes_d = 0x4000 - (offset_point & 0x3fff);
1144 uint32_t src_offset_1;
1145 for(int j = 0; j < 3; j++) {
1146 src_offset_1 = j * 0x4000;
1147 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1148 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1154 // Timing values from XM7 . Thanks Ryu.
1155 void DISPLAY::event_callback(int event_id, int err)
1160 case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
1161 #if defined(_FM77AV_VARIANTS)
1171 case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
1174 #if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1175 case EVENT_FM7SUB_HDISP:
1178 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x02, 0xff);
1179 if(display_mode == DISPLAY_MODE_8_400L) {
1180 if(displine < 400) f = true;
1182 if(displine < 200) f = true;
1185 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
1187 //copy_vram_per_line(0, 4);
1188 } else if(need_transfer_line) {
1191 for(int iii = 0; iii < 5 ; iii++) {
1192 if(vram_wrote_table[iii + displine * 5]) {
1193 if(begin < 0) begin = iii;
1197 if(end < begin) end = begin;
1198 copy_vram_per_line(begin, end);
1204 if(begin >= 0) end = 4;
1205 copy_vram_per_line(begin, end);
1208 if(display_mode == DISPLAY_MODE_8_400L) {
1209 register_event(this, EVENT_FM7SUB_HBLANK, 30.0, false, &hblank_event_id); // NEXT CYCLE_
1211 register_event(this, EVENT_FM7SUB_HBLANK, 39.5, false, &hblank_event_id); // NEXT CYCLE_
1219 case EVENT_FM7SUB_HBLANK:
1221 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1223 if(display_mode == DISPLAY_MODE_8_400L) {
1224 if((displine < 400)) f = true;
1226 if((displine < 200)) f = true;
1229 if(display_mode == DISPLAY_MODE_8_400L) {
1234 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id);
1238 case EVENT_FM7SUB_VSTART: // Call first.
1243 display_page_bak = display_page;
1244 // Parameter from XM7/VM/display.c , thanks, Ryu.
1245 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1246 mainio->write_signal(SIG_DISPLAY_VSYNC, 0x00, 0xff);
1247 if(vblank_count != 0) {
1248 if(display_mode == DISPLAY_MODE_8_400L) {
1249 usec = (0.98 + 16.4) * 1000.0;
1251 usec = (1.91 + 12.7) * 1000.0;
1253 register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
1255 if(display_mode == DISPLAY_MODE_8_400L) {
1256 usec = 930.0; // 939.0
1258 usec = 1840.0; // 1846.5
1260 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
1264 if(display_mode == DISPLAY_MODE_8_400L) {
1265 usec = 0.34 * 1000.0;
1267 usec = 1.52 * 1000.0;
1269 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1274 case EVENT_FM7SUB_VSYNC:
1278 //write_access_page = (write_access_page + 1) & 1;
1280 if(display_mode == DISPLAY_MODE_8_400L) {
1281 usec = 0.33 * 1000.0;
1283 usec = 0.51 * 1000.0;
1285 mainio->write_signal(SIG_DISPLAY_VSYNC, 0x01, 0xff);
1286 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1287 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1288 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) {
1291 if(display_mode == DISPLAY_MODE_8_400L) lines = 400;
1292 if(need_transfer_line) {
1293 if(vram_wrote) ff = true;
1294 //if(need_transfer_line) ff = true;
1296 for(displine = 0; displine < lines; displine++) {
1298 for(int iii = 0; iii < 5 ; iii++) {
1299 if(vram_wrote_table[iii + displine * 5]) {
1308 for(int yy = 0; yy < lines; yy++) {
1309 if(!vram_draw_table[yy]) {
1311 copy_vram_per_line(0, 4);
1312 vram_draw_table[yy] = true;
1316 vram_wrote_shadow = true;
1317 screen_update_flag = true;
1322 if(display_mode == DISPLAY_MODE_8_400L) lines = 400;
1323 if(need_transfer_line) {
1325 for(int yy = 0; yy < lines; yy++) {
1326 //if(!vram_draw_table[yy]) {
1328 copy_vram_per_line(0, 4);
1335 for(int yy = 0; yy < lines; yy++) {
1336 if(vram_draw_table[yy]) {
1337 vram_wrote_shadow = true;
1338 screen_update_flag = true;
1342 //vram_wrote = false;
1344 frame_skip_count_transfer++;
1346 uint32_t factor = ((config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28) & 3;
1347 if((frame_skip_count_transfer > factor) /* || (vram_wrote) */) {
1348 frame_skip_count_transfer = 0;
1349 need_transfer_line = true;
1351 need_transfer_line = false;
1356 case EVENT_FM7SUB_CLR_BUSY:
1359 case EVENT_FM7SUB_CLR_CRTFLAG:
1365 void DISPLAY::event_frame()
1367 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1371 if(display_mode == DISPLAY_MODE_8_400L) lines = 400;
1372 if(need_transfer_line && vram_wrote) {
1373 for(yy = 0; yy < lines; yy++) {
1374 //if(!vram_draw_table[yy]) {
1376 copy_vram_per_line(0, 4);
1383 for(yy = 0; yy < lines; yy++) {
1384 if(vram_draw_table[yy]) {
1390 screen_update_flag = true;
1391 vram_wrote_shadow = true;
1395 frame_skip_count_transfer++;
1397 uint32_t factor = (config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28;
1398 if(frame_skip_count_transfer > factor) {
1399 frame_skip_count_transfer = 0;
1400 need_transfer_line = true;
1402 need_transfer_line = false;
1404 //vram_wrote = false;
1411 void DISPLAY::event_vline(int v, int clock)
1413 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1414 if(need_transfer_line == false) return;
1418 //copy_vram_per_line(0, 4);
1422 for(int iii = 0; iii < 5 ; iii++) {
1423 if(vram_wrote_table[displine * 5 + iii]) {
1424 if(begin < 0) begin = iii;
1428 if(end < begin) end = begin;
1429 copy_vram_per_line(begin, end);
1435 if(begin >= 0) end = 4;
1436 copy_vram_per_line(begin, end);
1443 uint32_t DISPLAY::read_signal(int id)
1445 uint32_t retval = 0;
1447 case SIG_FM7_SUB_HALT:
1448 case SIG_DISPLAY_HALT:
1449 retval = (halt_flag) ? 0xffffffff : 0;
1451 case SIG_DISPLAY_BUSY:
1452 retval = (sub_busy) ? 0x80 : 0;
1454 case SIG_DISPLAY_MULTIPAGE:
1455 retval = multimode_accessmask;
1457 case SIG_DISPLAY_PLANES:
1460 #if defined(_FM77AV_VARIANTS)
1461 case SIG_DISPLAY_VSYNC:
1462 retval = (vsync) ? 0x01 : 0x00;
1464 case SIG_DISPLAY_DISPLAY:
1465 retval = (!hblank) ? 0x02: 0x00;
1467 case SIG_FM7_SUB_BANK: // Main: FD13
1468 retval = subrom_bank & 0x03;
1469 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1470 if(monitor_ram) retval |= 0x04;
1474 #if defined(_FM77AV_VARIANTS)
1475 case SIG_DISPLAY_MODE320:
1476 retval = (mode320) ? 0x40: 0x00;
1479 case SIG_DISPLAY_Y_HEIGHT:
1480 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1481 retval = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
1486 case SIG_DISPLAY_X_WIDTH:
1487 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1488 retval = (mode320 || mode256k) ? 320 : 640;
1489 #elif defined(_FM77AV_VARIANTS)
1490 retval = (mode320) ? 320 : 640;
1501 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
1503 bool flag = ((data & mask) != 0);
1507 case SIG_FM7_SUB_HALT:
1512 //mainio->write_signal(SIG_FM7_SUB_HALT, data, mask);
1514 case SIG_DISPLAY_HALT:
1518 restart_subsystem();
1521 case SIG_FM7_SUB_CANCEL:
1523 cancel_request = true;
1527 case SIG_DISPLAY_CLOCK:
1531 #if defined(_FM77AV_VARIANTS)
1532 case SIG_FM7_SUB_BANK: // Main: FD13
1533 set_monitor_bank(data & 0xff);
1536 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1537 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1538 //printf("Wrote $FD04: %02x\n", data);
1540 int oldmode = display_mode;
1542 kanjisub = ((data & 0x20) == 0) ? true : false;
1543 mode256k = (((data & 0x10) != 0) && ((data & 0x08) != 0) ) ? true : false;
1544 mode400line = ((data & 0x08) == 0) ? true : false;
1545 ram_protect = ((data & 0x04) == 0) ? true : false;
1546 if(mode400line && !mode320) {
1547 display_mode = DISPLAY_MODE_8_400L;
1548 } else if(mode256k) {
1549 display_mode = DISPLAY_MODE_256k;
1551 display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1553 if(oldmode != display_mode) {
1555 if(mode320 || mode256k) {
1556 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1557 for(y = 0; y < 200; y++) {
1558 pp = emu->get_screen_buffer(y);
1559 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1561 } else if(display_mode == DISPLAY_MODE_8_400L) {
1562 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1563 for(y = 0; y < 400; y++) {
1564 pp = emu->get_screen_buffer(y);
1565 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1568 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1569 for(y = 0; y < 200; y++) {
1570 pp = emu->get_screen_buffer(y);
1571 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1575 alu->write_signal(SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
1576 alu->write_signal(SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200, 0xffff);
1577 alu->write_signal(SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xff : 0x00, 0xff);
1578 frame_skip_count_draw = 3;
1579 frame_skip_count_transfer = 3;
1580 setup_display_mode();
1583 #elif defined(_FM77_VARIANTS)
1585 int oldmode = display_mode;
1586 kanjisub = ((data & 0x20) == 0) ? true : false;
1587 # if defined(_FM77L4)
1588 stat_400linecard = ((data & 0x20) != 0) ? true : false;
1589 mode400line = ((data & 0x08) != 0) ? false : true;
1590 if(mode400line && stat_400linecard) {
1591 display_mode = DISPLAY_MODE_8_400L_TEXT;
1592 } else if(stat_400linecard) {
1593 display_mode = DISPLAY_MODE_8_200L_TEXT;
1595 display_mode = DISPLAY_MODE_8_200L;
1598 setup_display_mode();
1602 #if defined(_FM77AV_VARIANTS)
1603 case SIG_DISPLAY_MODE320: // FD12 bit 6
1604 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1606 //printf("Wrote $FD12: %02x\n", data);
1607 int oldmode = display_mode;
1609 if(!mode320 && !mode256k) {
1610 //display_mode = (mode400line) ? DISPLAY_MODE_8_400L : DISPLAY_MODE_8_200L;
1611 display_mode = DISPLAY_MODE_8_200L;
1613 display_mode = (mode256k) ? DISPLAY_MODE_256k : DISPLAY_MODE_4096;
1615 if(oldmode != display_mode) {
1617 if(mode320 || mode256k) {
1618 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1619 for(y = 0; y < 200; y++) {
1620 pp = emu->get_screen_buffer(y);
1621 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1623 } else { // 200 lines, 8 colors.
1624 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1625 for(y = 0; y < 200; y++) {
1626 pp = emu->get_screen_buffer(y);
1627 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1631 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
1632 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
1633 alu->write_signal(SIG_ALU_400LINE, 0x00, 0xff);
1634 setup_display_mode();
1635 //frame_skip_count = 3;
1644 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1645 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 320 * sizeof(scrntype_t));
1647 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1648 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
1651 display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1652 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
1653 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
1654 alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
1656 if(mode320 != oldflag) setup_display_mode();
1660 case SIG_DISPLAY_MULTIPAGE:
1661 set_multimode(data);
1663 case SIG_FM7_SUB_KEY_MASK:
1664 if(firq_mask == flag) {
1665 do_firq(!flag && key_firq_req);
1669 case SIG_FM7_SUB_KEY_FIRQ:
1670 do_firq(flag & !(firq_mask));
1671 key_firq_req = flag;
1673 case SIG_FM7_SUB_USE_CLR:
1675 clr_count = data & 0x03;
1686 * Vram accessing functions moved to vram.cpp .
1689 uint32_t DISPLAY::read_mmio(uint32_t addr)
1691 uint32_t retval = 0xff;
1693 if(addr < 0xd400) return 0xff;
1695 #if !defined(_FM77AV_VARIANTS)
1696 raddr = (addr - 0xd400) & 0x000f;
1697 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
1698 raddr = (addr - 0xd400) & 0x003f;
1699 #else // FM77AV40EX || FM77AV40SX
1700 raddr = (addr - 0xd400) & 0x00ff;
1703 case 0x00: // Read keyboard
1704 retval = (keyboard->read_data8(0x00) != 0) ? 0xff : 0x7f;
1706 case 0x01: // Read keyboard
1707 retval = keyboard->read_data8(0x01) & 0xff;
1709 case 0x02: // Acknowledge
1718 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1719 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
1721 if(!kanjisub) return 0xff;
1722 # if !defined(_FM77_VARIANTS)
1724 return (uint8_t)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1727 if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1730 if(!kanjisub) return 0xff;
1731 # if !defined(_FM77_VARIANTS)
1733 return (uint8_t)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1736 if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1743 retval = set_vramaccess();
1749 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
1751 #if defined(_FM77AV_VARIANTS)
1754 retval = alu->read_data8(ALU_CMDREG);
1757 retval = alu->read_data8(ALU_LOGICAL_COLOR);
1760 retval = alu->read_data8(ALU_WRITE_MASKREG);
1763 retval = alu->read_data8(ALU_CMP_STATUS_REG);
1766 retval = alu->read_data8(ALU_BANK_DISABLE);
1768 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1769 case 0x2f: // VRAM BANK
1770 retval = 0xfc | (vram_bank & 0x03);
1775 retval = get_miscreg();
1779 retval = keyboard->read_data8(0x31);
1782 retval = keyboard->read_data8(0x32);
1788 return (uint8_t)retval;
1791 uint32_t DISPLAY::read_vram_data8(uint32_t addr)
1795 uint32_t color = (addr >> 14) & 0x03;
1797 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1798 if(display_mode == DISPLAY_MODE_8_400L) {
1799 color = vram_bank & 0x03;
1800 if(color > 2) color = 0;
1802 color = (addr >> 14) & 0x03;
1806 //if((multimode_accessmask & (1 << color)) != 0) return 0xff;
1807 if(multimode_accessflags[color]) return 0xff;
1809 #if defined(_FM77AV_VARIANTS)
1810 if (active_page != 0) {
1811 offset = offset_point_bank1;
1813 offset = offset_point;
1816 offset = offset_point;
1819 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1820 if(display_mode == DISPLAY_MODE_8_400L) {
1822 uint32_t page_offset_alt = 0;
1823 if(addr >= 0x8000) return 0xff;
1824 color = vram_bank & 0x03;
1825 if(color > 2) color = 0;
1827 pagemod = 0x8000 * color;
1828 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1829 if(vram_active_block != 0) page_offset = 0x18000;
1831 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
1832 return gvram[vramaddr];
1835 uint32_t page_offset_alt;
1836 #if defined(_FM77AV40)
1838 page_offset_alt = 0xc000 * (vram_bank & 0x03);
1840 page_offset_alt = 0; // right?
1843 page_offset_alt = 0xc000 * (vram_bank & 0x03);
1845 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
1846 //page_mask = 0x1fff;
1847 //pagemod = addr & 0xe000;
1849 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1851 return gvram[vramaddr];
1853 #elif defined(_FM77AV_VARIANTS)
1855 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1856 return gvram[vramaddr];
1858 #elif defined(_FM77L4) //_FM77L4
1860 if(display_mode == DISPLAY_MODE_8_400L) {
1861 return (uint32_t)read_vram_l4_400l(addr, offset);
1863 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1864 return gvram[vramaddr];
1868 #else // Others (77/7/8)
1869 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1870 return gvram[vramaddr];
1874 void DISPLAY::write_dma_data8(uint32_t addr, uint32_t data)
1876 uint32_t raddr = (addr & 0xffff) >> 7;
1877 if(write_dma_func_table[raddr] != NULL) {
1878 (this->*write_dma_func_table[raddr])(addr, (uint8_t) data);
1882 void DISPLAY::write_vram_data8(uint32_t addr, uint8_t data)
1885 uint32_t color = (addr >> 14) & 0x03;
1889 #if defined(_FM77AV_VARIANTS)
1890 if (active_page != 0) {
1891 offset = offset_point_bank1;
1893 offset = offset_point;
1896 offset = offset_point;
1899 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1900 if(display_mode == DISPLAY_MODE_8_400L) {
1902 uint32_t page_offset_alt = 0;
1904 if(addr >= 0x8000) {
1907 color = vram_bank & 0x03;
1908 if(color > 2) color = 0;
1910 pagemod = 0x8000 * color;
1911 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1912 if(vram_active_block != 0) page_offset_alt = 0x18000;
1914 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
1915 // Reduce data transfer.
1916 tdata = gvram[vramaddr];
1918 naddr = (addr & 0x7fff) >> 4;
1919 gvram[vramaddr] = data;
1920 vram_wrote_table[naddr] = true;
1922 } else if(display_mode == DISPLAY_MODE_256k) {
1923 uint32_t page_offset_alt;
1925 #if defined(_FM77AV40)
1927 page_offset_alt = 0xc000 * (vram_bank & 0x03);
1929 page_offset_alt = 0; // right?
1932 page_offset_alt = 0xc000 * (vram_bank & 0x03);
1934 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
1935 tdata = gvram[vramaddr];
1937 naddr = (addr & page_mask) >> 3;
1938 gvram[vramaddr] = data;
1939 vram_wrote_table[naddr] = true;
1942 } else if(display_mode == DISPLAY_MODE_4096) {
1944 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1945 tdata = gvram[vramaddr];
1947 naddr = (addr & page_mask) >> 3;
1948 gvram[vramaddr] = data;
1949 vram_wrote_table[naddr] = true;
1953 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1954 tdata = gvram[vramaddr];
1956 naddr = (addr & page_mask) >> 4;
1957 gvram[vramaddr] = data;
1958 vram_wrote_table[naddr] = true;
1961 #elif defined(_FM77AV_VARIANTS)
1962 if(display_mode == DISPLAY_MODE_4096) {
1964 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1965 tdata = gvram[vramaddr];
1967 naddr = (addr & page_mask) >> 3;
1968 gvram[vramaddr] = data;
1969 vram_wrote_table[naddr] = true;
1973 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1974 tdata = gvram[vramaddr];
1976 naddr = (addr & page_mask) >> 4;
1977 gvram[vramaddr] = data;
1978 vram_wrote_table[naddr] = true;
1981 #elif defined(_FM77L4) //_FM77L4
1984 if(display_mode == DISPLAY_MODE_8_400L) {
1985 write_vram_l4_400l(addr, data, offset);
1987 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1988 tdata = gvram[vramaddr];
1990 naddr = (addr & 0x3fff) >> 4;
1991 gvram[vramaddr] = data;
1992 vram_wrote_table[naddr] = true;
1996 #else // Others (77/7/8)
1999 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2000 tdata = gvram[vramaddr];
2002 naddr = (addr & 0x3fff) >> 4;
2003 gvram[vramaddr] = data;
2004 vram_wrote_table[naddr] = true;
2010 uint32_t DISPLAY::read_cpu_vram_data8(uint32_t addr)
2013 #if defined(_FM77AV_VARIANTS)
2015 alu->read_data8(addr);
2018 return read_vram_data8(addr);
2021 uint32_t DISPLAY::read_dma_vram_data8(uint32_t addr)
2023 return read_vram_data8(addr);
2026 void DISPLAY::init_read_table(void)
2029 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
2030 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cpu_vram_data8;
2031 read_dma_func_table[_at >> 7] = &DISPLAY::read_dma_vram_data8;
2033 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
2034 read_cpu_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2035 read_dma_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2037 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
2038 read_cpu_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2039 read_dma_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2041 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
2042 read_cpu_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2043 read_dma_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2045 #if defined(_FM77AV_VARIANTS)
2046 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
2047 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2048 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2050 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
2051 read_cpu_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2052 read_dma_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2055 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
2056 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2057 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2060 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
2061 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2062 read_dma_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2064 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
2065 read_cpu_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2066 read_dma_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2070 uint32_t DISPLAY::read_console_ram(uint32_t addr)
2072 uint32_t raddr = addr & 0xfff;
2073 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2075 if(console_ram_bank >= 1) {
2076 return submem_console_av40[((console_ram_bank - 1) << 12) + raddr];
2080 return console_ram[raddr];
2083 uint32_t DISPLAY::read_work_ram(uint32_t addr)
2085 addr = addr & 0x3ff;
2086 return work_ram[addr];
2090 uint32_t DISPLAY::read_shared_ram(uint32_t addr)
2092 addr = addr - 0xd380;
2093 return shared_ram[addr];
2096 #if defined(_FM77AV_VARIANTS)
2097 uint32_t DISPLAY::read_hidden_ram(uint32_t addr)
2099 if(addr >= 0xd500) {
2100 return submem_hidden[addr - 0xd500];
2105 uint32_t DISPLAY::read_cgrom(uint32_t addr)
2107 #if defined(_FM77AV_VARIANTS)
2108 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2110 return submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)]; //FIXME
2113 return subsys_cg[(addr - 0xd800) + cgrom_bank * 0x800];
2115 return subsys_c[addr - 0xd800];
2119 uint32_t DISPLAY::read_subsys_monitor(uint32_t addr)
2121 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2123 return subsys_ram[addr - 0xe000];
2126 #if defined(_FM77AV_VARIANTS)
2127 switch(subrom_bank_using & 3) {
2129 return subsys_c[addr - 0xd800];
2132 return subsys_a[addr - 0xe000];
2135 return subsys_b[addr - 0xe000];
2138 return subsys_cg[addr - 0xe000];
2142 return subsys_c[addr - 0xd800];
2146 uint32_t DISPLAY::read_dma_data8(uint32_t addr)
2148 uint32_t raddr = (addr & 0xffff) >> 7;
2149 if(read_dma_func_table[raddr] != NULL) {
2150 return (this->*read_dma_func_table[raddr])(addr);
2155 uint32_t DISPLAY::read_data8(uint32_t addr)
2157 uint32_t raddr = addr;
2159 if(addr < 0x10000) {
2160 raddr = (addr & 0xffff) >> 7;
2161 if(read_cpu_func_table[raddr] != NULL) {
2162 return (this->*read_cpu_func_table[raddr])(addr);
2167 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2168 return dpalette_data[addr - FM7_SUBMEM_OFFSET_DPALETTE];
2171 #if defined(_FM77AV_VARIANTS)
2173 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2174 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2175 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2176 if(display_mode == DISPLAY_MODE_8_400L) {
2177 uint32_t page_offset_alt = 0;
2178 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2179 if(vram_active_block != 0) page_offset_alt = 0x18000;
2183 color = (addr & 0x18000) >> 15;
2184 if(color > 2) color = 0;
2185 pagemod = 0x8000 * color;
2186 if (active_page != 0) {
2187 offset = offset_point_bank1 << 1;
2189 offset = offset_point << 1;
2191 return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset_alt];
2194 return read_vram_data8(addr);
2201 * Vram accessing functions moved to vram.cpp .
2204 void DISPLAY::write_mmio(uint32_t addr, uint8_t data)
2207 uint8_t active_block_old;
2209 if(addr < 0xd400) return;
2211 #if !defined(_FM77AV_VARIANTS)
2212 addr = (addr - 0xd400) & 0x000f;
2213 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2214 addr = (addr - 0xd400) & 0x003f;
2215 #else // FM77AV40EX || FM77AV40SX
2216 addr = (addr - 0xd400) & 0x00ff;
2218 io_w_latch[addr] = (uint8_t)data;
2220 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4)
2223 set_cyclesteal((uint8_t)data);
2226 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2227 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2230 if(!kanjisub) return;
2231 kanjiaddr.w.h = 0x0000;
2232 kanjiaddr.b.h = (uint8_t) data;
2235 if(!kanjisub) return;
2236 kanjiaddr.w.h = 0x0000;
2237 kanjiaddr.b.l = (uint8_t)data;
2250 if(clr_count <= 0) {
2252 } else { // Read once when using clr_foo() to set busy flag.
2255 usec = (1000.0 * 1000.0) / 2000000.0;
2257 usec = (1000.0 * 1000.0) / 999000.0;
2259 if(!is_cyclesteal && vram_accessflag) usec = usec * 3.0;
2260 usec = (double)clr_count * usec;
2261 register_event(this, EVENT_FM7SUB_CLR_BUSY, usec, false, NULL); // NEXT CYCLE_
2268 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
2273 rval = (uint8_t)data;
2274 if(offset_changed[active_page]) {
2275 #if defined(_FM77AV_VARIANTS)
2276 if(active_page != 0) {
2277 tmp_offset_point[active_page].d = offset_point_bank1;
2279 tmp_offset_point[active_page].d = offset_point;
2282 tmp_offset_point[active_page].d = offset_point;
2285 tmp_offset_point[active_page].w.h = 0x0000;
2287 tmp_offset_point[active_page].b.h = rval;
2289 tmp_offset_point[active_page].b.l = rval;
2291 offset_changed[active_page] = !offset_changed[active_page];
2292 if(offset_changed[active_page]) {
2294 #if defined(_FM77AV_VARIANTS)
2295 if(active_page != 0) {
2297 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fff;
2299 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fe0;
2303 offset_point = tmp_offset_point[active_page].d & 0x007fff;
2305 offset_point = tmp_offset_point[active_page].d & 0x007fe0;
2309 offset_point = tmp_offset_point[active_page].d & 0x7fe0;
2313 #if defined(_FM77AV_VARIANTS)
2316 alu_write_cmdreg(data);
2319 alu_write_logical_color(data);
2322 alu_write_mask_reg(data);
2325 alu_write_disable_reg(data);
2328 alu_write_offsetreg_hi(data);
2331 alu_write_offsetreg_lo(data);
2334 alu_write_linepattern_hi(data);
2337 alu_write_linepattern_lo(data);
2339 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2341 console_ram_bank = (data & 0x18) >> 3;
2342 if(console_ram_bank > 2) console_ram_bank = 0;
2343 cgram_bank = data & 0x07;
2344 kanji_level2 = ((data & 0x80) == 0) ? false : true;
2346 case 0x2f: // VRAM BANK
2347 vram_bank = data & 0x03;
2348 if(vram_bank > 2) vram_bank = 0;
2358 keyboard->write_data8(0x31, data);
2360 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2362 active_block_old = vram_active_block;
2363 vram_active_block = data & 0x01;
2364 if(vram_display_block != (((data & 0x10) != 0) ? 1 : 0)) vram_wrote = true;
2365 vram_display_block = ((data & 0x10) != 0) ? 1 : 0;
2366 if(vram_active_block != active_block_old) setup_display_mode();
2371 tmpvar.d = window_xbegin * 8;
2374 tmpvar.b.h = data & 0x03;
2376 tmpvar.b.l = data & 0xf8;
2378 if(mode320 || mode256k) {
2379 if(tmpvar.d > 320) tmpvar.d = 320;
2381 if(tmpvar.d > 640) tmpvar.d = 640;
2383 window_xbegin = tmpvar.d / 8;
2388 tmpvar.d = window_xend * 8;
2391 tmpvar.b.h = data & 0x03;
2393 tmpvar.b.l = data & 0xf8;
2395 if(mode320 || mode256k) {
2396 if(tmpvar.d > 320) tmpvar.d = 320;
2398 if(tmpvar.d > 640) tmpvar.d = 640;
2400 window_xend = tmpvar.d / 8;
2405 tmpvar.d = window_low;
2408 tmpvar.b.h = data & 0x03;
2410 tmpvar.b.l = data & 0xff;
2412 if(display_mode == DISPLAY_MODE_8_400L) {
2413 if(tmpvar.d > 400) tmpvar.d = 400;
2416 if(tmpvar.d > 400) tmpvar.d = 400;
2418 window_low = tmpvar.d;
2423 tmpvar.d = window_high;
2426 tmpvar.b.h = data & 0x03;
2428 tmpvar.b.l = data & 0xff;
2430 if(display_mode == DISPLAY_MODE_8_400L) {
2431 if(tmpvar.d > 400) tmpvar.d = 400;
2434 if(tmpvar.d > 400) tmpvar.d = 400;
2436 window_high = tmpvar.d;
2442 #if defined(_FM77AV_VARIANTS)
2444 if((addr >= 0x13) && (addr <= 0x1a)) {
2445 alu_write_cmpdata_reg(addr - 0x13, data);
2446 } else if((addr >= 0x1c) && (addr <= 0x1e)) {
2447 alu_write_tilepaint_data(addr, data);
2448 } else if((addr >= 0x24) && (addr <= 0x2b)) {
2449 alu_write_line_position(addr - 0x24, data);
2456 void DISPLAY::init_write_table(void)
2459 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
2460 write_cpu_func_table[_at >> 7] = &DISPLAY::write_cpu_vram_data8;
2461 write_dma_func_table[_at >> 7] = &DISPLAY::write_dma_vram_data8;
2463 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
2464 write_cpu_func_table[_at >> 7] = &DISPLAY::write_console_ram;
2465 write_dma_func_table[_at >> 7] = &DISPLAY::write_console_ram;
2467 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
2468 write_cpu_func_table[_at >> 7] = &DISPLAY::write_work_ram;
2469 write_dma_func_table[_at >> 7] = &DISPLAY::write_work_ram;
2471 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
2472 write_cpu_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
2473 write_dma_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
2475 #if defined(_FM77AV_VARIANTS)
2476 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
2477 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
2478 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
2480 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
2481 write_cpu_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
2482 write_dma_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
2485 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
2486 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
2487 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
2490 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2491 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
2492 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
2493 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
2495 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
2496 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
2497 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
2500 for(_at = 0xd800; _at < 0x10000; _at += 0x80) {
2501 write_cpu_func_table[_at >> 7] = &DISPLAY::write_dummy;
2502 write_dma_func_table[_at >> 7] = &DISPLAY::write_dummy;
2507 void DISPLAY::write_console_ram(uint32_t addr, uint8_t data)
2509 uint32_t raddr = addr & 0xfff;
2510 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2512 if(console_ram_bank >= 1) {
2513 submem_console_av40[((console_ram_bank - 1) << 12) + raddr] = data;
2518 console_ram[raddr] = data;
2522 void DISPLAY::write_work_ram(uint32_t addr, uint8_t data)
2524 uint32_t raddr = addr & 0xfff;
2525 work_ram[raddr] = data;
2529 void DISPLAY::write_shared_ram(uint32_t addr, uint8_t data)
2531 uint32_t raddr = addr & 0x7f;
2532 shared_ram[raddr] = data;
2536 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2537 void DISPLAY::write_subsys_cgram(uint32_t addr, uint8_t data)
2539 uint32_t raddr = addr - 0xd800;
2540 if(ram_protect) return;
2541 if(!monitor_ram) return;
2542 submem_cgram[cgram_bank * 0x0800 + raddr] = data; //FIXME
2545 void DISPLAY::write_subsys_ram(uint32_t addr, uint8_t data)
2547 if(ram_protect) return;
2548 if(!monitor_ram) return;
2549 subsys_ram[addr - 0xe000] = data; //FIXME
2553 #if defined(_FM77AV_VARIANTS)
2554 void DISPLAY::write_hidden_ram(uint32_t addr, uint8_t data)
2556 submem_hidden[addr - 0xd500] = data;
2561 void DISPLAY::write_cpu_vram_data8(uint32_t addr, uint8_t data)
2563 uint32_t color = (addr & 0xc000) >> 14;
2564 #if defined(_FM77AV_VARIANTS)
2566 alu->read_data8(addr);
2570 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2571 if(display_mode == DISPLAY_MODE_8_400L) {
2572 color = vram_bank & 0x03;
2573 if(color > 2) color = 0;
2577 //if((multimode_accessmask & (1 << color)) != 0) return;
2578 if(multimode_accessflags[color]) return;
2580 write_vram_data8(addr & 0xffff, data);
2583 void DISPLAY::write_dma_vram_data8(uint32_t addr, uint8_t data)
2585 uint32_t color = (addr & 0xc000) >> 14;
2586 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2587 if(display_mode == DISPLAY_MODE_8_400L) {
2588 color = vram_bank & 0x03;
2589 if(color > 2) color = 0;
2593 //if((multimode_accessmask & (1 << color)) != 0) return;
2594 if(multimode_accessflags[color]) return;
2596 write_vram_data8(addr & 0xffff, data);
2599 void DISPLAY::write_dummy(uint32_t addr, uint8_t data)
2603 void DISPLAY::write_data8(uint32_t addr, uint32_t data)
2607 //uint32_t page_offset = 0x0000;
2608 uint8_t val8 = data & 0xff;
2609 uint32_t color = (addr & 0xc000) >> 14;
2612 if(addr < 0x10000) {
2613 void (*_write_func)(uint32_t, uint32_t);
2614 raddr = (addr & 0xffff) >> 7;
2615 if(write_cpu_func_table[raddr] != NULL) {
2616 (this->*write_cpu_func_table[raddr])(addr, (uint8_t)data);
2622 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2623 set_dpalette(addr - FM7_SUBMEM_OFFSET_DPALETTE, val8);
2627 #if defined(_FM77AV_VARIANTS)
2629 else if(addr == FM7_SUBMEM_OFFSET_APALETTE_R) {
2630 set_apalette_r(val8);
2632 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_G) {
2633 set_apalette_g(val8);
2635 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_B) {
2636 set_apalette_b(val8);
2638 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_HI) {
2639 set_apalette_index_hi(val8);
2641 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_LO) {
2642 set_apalette_index_lo(val8);
2646 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2647 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2648 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2649 if(display_mode == DISPLAY_MODE_8_400L) {
2652 uint32_t page_offset_alt = 0;
2654 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2655 if(vram_active_block != 0) page_offset_alt = 0x18000;
2657 color = (addr & 0x18000) >> 15;
2658 if(color > 2) color = 0;
2659 if (active_page != 0) {
2660 offset = offset_point_bank1 << 1;
2662 offset = offset_point << 1;
2664 naddr = (addr & 0x7fff) >> 4;
2665 pagemod = 0x8000 * color;
2666 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2667 tdata = gvram[vramaddr];
2668 if(tdata != (uint8_t)data) {
2669 gvram[vramaddr] = data;
2670 vram_wrote_table[naddr] = true;
2674 write_vram_data8(addr, data);
2676 write_vram_data8(addr, data);
2678 //if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
2685 uint32_t DISPLAY::read_bios(const _TCHAR *name, uint8_t *ptr, uint32_t size)
2691 if((name == NULL) || (ptr == NULL)) return 0;
2692 s = create_local_path(name);
2693 if(s == NULL) return 0;
2695 if(!fio.Fopen(s, FILEIO_READ_BINARY)) return 0;
2696 blocks = fio.Fread(ptr, size, 1);
2699 return blocks * size;
2703 void DISPLAY::initialize()
2707 screen_update_flag = true;
2708 memset(gvram, 0x00, sizeof(gvram));
2709 vram_wrote_shadow = false;
2710 memset(gvram_shadow, 0x00, sizeof(gvram_shadow));
2711 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
2712 for(i = 0; i < 411; i++) vram_draw_table[i] = false;
2714 memset(console_ram, 0x00, sizeof(console_ram));
2715 memset(work_ram, 0x00, sizeof(work_ram));
2716 memset(shared_ram, 0x00, sizeof(shared_ram));
2717 memset(subsys_c, 0xff, sizeof(subsys_c));
2718 need_transfer_line = true;
2719 frame_skip_count_draw = 3;
2720 frame_skip_count_transfer = 3;
2722 diag_load_subrom_c = false;
2724 if(read_bios(_T("SUBSYS_8.ROM"), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2725 this->out_debug_log(_T("SUBSYSTEM ROM READING : %s"), diag_load_subrom_c ? "OK" : "NG");
2727 if(read_bios(_T("SUBSYS_C.ROM"), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2728 this->out_debug_log(_T("SUBSYSTEM ROM Type C READING : %s"), diag_load_subrom_c ? "OK" : "NG");
2730 #if defined(_FM77AV_VARIANTS)
2731 memset(subsys_a, 0xff, sizeof(subsys_a));
2732 memset(subsys_b, 0xff, sizeof(subsys_b));
2733 memset(subsys_cg, 0xff, sizeof(subsys_cg));
2734 memset(submem_hidden, 0x00, sizeof(submem_hidden));
2736 diag_load_subrom_a = false;
2737 if(read_bios(_T("SUBSYS_A.ROM"), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
2738 this->out_debug_log(_T("SUBSYSTEM ROM Type A READING : %s"), diag_load_subrom_a ? "OK" : "NG");
2740 diag_load_subrom_b = false;
2741 if(read_bios(_T("SUBSYS_B.ROM"), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
2742 this->out_debug_log(_T("SUBSYSTEM ROM Type B READING : %s"), diag_load_subrom_b ? "OK" : "NG");
2744 diag_load_subrom_cg = false;
2745 if(read_bios(_T("SUBSYSCG.ROM"), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
2746 this->out_debug_log(_T("SUBSYSTEM CG ROM READING : %s"), diag_load_subrom_cg ? "OK" : "NG");
2747 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2748 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2749 memset(subsys_ram, 0x00, sizeof(subsys_ram));
2750 memset(submem_cgram, 0x00, sizeof(submem_cgram));
2751 memset(submem_console_av40, 0x00, sizeof(submem_console_av40));
2758 #if defined(_FM77AV_VARIANTS)
2760 apalette_index.d = 0;
2761 for(i = 0; i < 4096; i++) {
2762 analog_palette_r[i] = i & 0x0f0;
2763 analog_palette_g[i] = (i & 0xf00) >> 4;
2764 analog_palette_b[i] = (i & 0x00f) << 4;
2768 #if defined(_FM77AV_VARIANTS)
2769 hblank_event_id = -1;
2770 hdisp_event_id = -1;
2771 vsync_event_id = -1;
2772 vstart_event_id = -1;
2779 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
2780 is_cyclesteal = true;
2782 is_cyclesteal = false;
2784 multimode_accessmask = multimode_dispmask = 0;
2785 for(i = 0; i < 4; i++) {
2786 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
2787 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
2789 // emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2790 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2791 prev_clock = SUBCLOCK_NORMAL;
2795 key_firq_req = false; //firq_mask = true;
2796 frame_skip_count_transfer = 3;
2797 frame_skip_count_draw = 3;
2798 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2799 palette_changed = true;
2800 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
2801 //register_vline_event(this);
2802 //register_frame_event(this);
2804 setup_display_mode();
2807 void DISPLAY::release()
2811 #define STATE_VERSION 8
2812 void DISPLAY::save_state(FILEIO *state_fio)
2814 state_fio->FputUint32_BE(STATE_VERSION);
2815 state_fio->FputInt32_BE(this_device_id);
2816 this->out_debug_log(_T("Save State: DISPLAY : id=%d ver=%d\n"), this_device_id, STATE_VERSION);
2820 state_fio->FputInt32_BE(clr_count);
2821 state_fio->FputBool(halt_flag);
2822 state_fio->FputInt32_BE(active_page);
2823 state_fio->FputBool(sub_busy);
2824 state_fio->FputBool(crt_flag);
2825 state_fio->FputBool(vram_wrote);
2826 state_fio->FputBool(is_cyclesteal);
2828 state_fio->FputBool(clock_fast);
2830 #if defined(_FM77AV_VARIANTS)
2831 state_fio->FputBool(subcpu_resetreq);
2832 state_fio->FputBool(power_on_reset);
2834 state_fio->FputBool(cancel_request);
2835 state_fio->FputBool(key_firq_req);
2837 state_fio->FputInt32_BE(display_mode);
2838 state_fio->FputUint32_BE(prev_clock);
2841 state_fio->Fwrite(dpalette_data, sizeof(dpalette_data), 1);
2842 state_fio->FputUint8(multimode_accessmask);
2843 state_fio->FputUint8(multimode_dispmask);
2845 state_fio->FputUint32_BE(offset_point);
2846 #if defined(_FM77AV_VARIANTS)
2847 state_fio->FputUint32_BE(offset_point_bank1);
2849 for(i = 0; i < 2; i++) {
2850 state_fio->FputUint32_BE(tmp_offset_point[i].d);
2851 state_fio->FputBool(offset_changed[i]);
2853 state_fio->FputBool(offset_77av);
2854 state_fio->FputBool(diag_load_subrom_c);
2857 state_fio->Fwrite(io_w_latch, sizeof(io_w_latch), 1);
2858 state_fio->Fwrite(console_ram, sizeof(console_ram), 1);
2859 state_fio->Fwrite(work_ram, sizeof(work_ram), 1);
2860 state_fio->Fwrite(shared_ram, sizeof(shared_ram), 1);
2861 state_fio->Fwrite(subsys_c, sizeof(subsys_c), 1);
2862 state_fio->Fwrite(gvram, sizeof(gvram), 1);
2863 state_fio->Fwrite(gvram_shadow, sizeof(gvram_shadow), 1);
2865 #if defined(_FM77_VARIANTS)
2866 state_fio->FputBool(kanjisub);
2867 state_fio->FputUint16_BE(kanjiaddr.w.l);
2868 # if defined(_FM77L4)
2869 state_fio->FputBool(mode400line);
2870 state_fio->FputBool(stat_400linecard);
2872 #elif defined(_FM77AV_VARIANTS)
2873 state_fio->FputBool(kanjisub);
2874 state_fio->FputUint16_BE(kanjiaddr.w.l);
2876 state_fio->FputBool(vblank);
2877 state_fio->FputBool(vsync);
2878 state_fio->FputBool(hblank);
2879 state_fio->FputInt32_BE(vblank_count);
2881 state_fio->FputBool(mode320);
2882 state_fio->FputInt8(display_page);
2883 state_fio->FputInt8(display_page_bak);
2884 state_fio->FputInt32_BE(cgrom_bank);
2885 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
2886 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2887 state_fio->FputInt32_BE(vram_bank);
2890 state_fio->FputUint32_BE(displine);
2891 state_fio->FputUint8(subrom_bank);
2892 state_fio->FputUint8(subrom_bank_using);
2894 state_fio->FputBool(nmi_enable);
2895 state_fio->FputBool(use_alu);
2897 state_fio->FputUint8(apalette_index.b.l);
2898 state_fio->FputUint8(apalette_index.b.h);
2899 state_fio->Fwrite(analog_palette_r, sizeof(analog_palette_r), 1);
2900 state_fio->Fwrite(analog_palette_g, sizeof(analog_palette_g), 1);
2901 state_fio->Fwrite(analog_palette_b, sizeof(analog_palette_b), 1);
2904 state_fio->FputBool(diag_load_subrom_a);
2905 state_fio->FputBool(diag_load_subrom_b);
2906 state_fio->FputBool(diag_load_subrom_cg);
2908 state_fio->Fwrite(subsys_a, sizeof(subsys_a), 1);
2909 state_fio->Fwrite(subsys_b, sizeof(subsys_b), 1);
2910 state_fio->Fwrite(subsys_cg, sizeof(subsys_cg), 1);
2911 state_fio->Fwrite(submem_hidden, sizeof(submem_hidden), 1);
2912 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2913 state_fio->FputBool(mode400line);
2914 state_fio->FputBool(mode256k);
2916 state_fio->FputBool(monitor_ram);
2917 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2918 state_fio->FputUint16_BE(window_low);
2919 state_fio->FputUint16_BE(window_high);
2920 state_fio->FputUint16_BE(window_xbegin);
2921 state_fio->FputUint16_BE(window_xend);
2922 state_fio->FputBool(window_opened);
2924 state_fio->FputBool(kanji_level2);
2926 state_fio->FputUint8(vram_active_block);
2927 state_fio->FputUint8(vram_display_block);
2928 state_fio->FputUint8(console_ram_bank);
2929 state_fio->FputBool(ram_protect);
2931 state_fio->FputUint32_BE(cgram_bank);
2932 state_fio->Fwrite(subsys_ram, sizeof(subsys_ram), 1);
2933 state_fio->Fwrite(submem_cgram, sizeof(submem_cgram), 1);
2934 state_fio->Fwrite(submem_console_av40, sizeof(submem_console_av40), 1);
2940 state_fio->FputInt32_BE(nmi_event_id);
2941 #if defined(_FM77AV_VARIANTS)
2942 state_fio->FputInt32_BE(hblank_event_id);
2943 state_fio->FputInt32_BE(hdisp_event_id);
2944 state_fio->FputInt32_BE(vsync_event_id);
2945 state_fio->FputInt32_BE(vstart_event_id);
2947 state_fio->FputBool(firq_mask);
2948 state_fio->FputBool(vram_accessflag);
2952 bool DISPLAY::load_state(FILEIO *state_fio)
2955 uint32_t version = state_fio->FgetUint32_BE();
2956 if(this_device_id != state_fio->FgetInt32_BE()) {
2959 this->out_debug_log(_T("Load State: DISPLAY : id=%d ver=%d\n"), this_device_id, version);
2964 clr_count = state_fio->FgetInt32_BE();
2965 halt_flag = state_fio->FgetBool();
2966 active_page = state_fio->FgetInt32_BE();
2967 sub_busy = state_fio->FgetBool();
2968 crt_flag = state_fio->FgetBool();
2969 vram_wrote = state_fio->FgetBool();
2970 crt_flag_bak = true;
2971 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
2972 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
2973 is_cyclesteal = state_fio->FgetBool();
2975 clock_fast = state_fio->FgetBool();
2977 #if defined(_FM77AV_VARIANTS)
2978 subcpu_resetreq = state_fio->FgetBool();
2979 power_on_reset = state_fio->FgetBool();
2981 cancel_request = state_fio->FgetBool();
2982 key_firq_req = state_fio->FgetBool();
2984 display_mode = state_fio->FgetInt32_BE();
2985 prev_clock = state_fio->FgetUint32_BE();
2988 for(addr = 0; addr < 8; addr++) set_dpalette(addr, addr);
2990 state_fio->Fread(dpalette_data, sizeof(dpalette_data), 1);
2991 for(addr = 0; addr < 8; addr++) set_dpalette(addr, dpalette_data[addr]);
2992 multimode_accessmask = state_fio->FgetUint8();
2993 multimode_dispmask = state_fio->FgetUint8();
2994 for(i = 0; i < 4; i++) {
2995 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
2996 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
2999 offset_point = state_fio->FgetUint32_BE();
3000 #if defined(_FM77AV_VARIANTS)
3001 offset_point_bank1 = state_fio->FgetUint32_BE();
3003 for(i = 0; i < 2; i++) {
3004 tmp_offset_point[i].d = state_fio->FgetUint32_BE();
3005 offset_changed[i] = state_fio->FgetBool();
3007 offset_77av = state_fio->FgetBool();
3008 diag_load_subrom_c = state_fio->FgetBool();
3010 state_fio->Fread(io_w_latch, sizeof(io_w_latch), 1);
3011 state_fio->Fread(console_ram, sizeof(console_ram), 1);
3012 state_fio->Fread(work_ram, sizeof(work_ram), 1);
3013 state_fio->Fread(shared_ram, sizeof(shared_ram), 1);
3014 state_fio->Fread(subsys_c, sizeof(subsys_c), 1);
3015 state_fio->Fread(gvram, sizeof(gvram), 1);
3016 state_fio->Fread(gvram_shadow, sizeof(gvram_shadow), 1);
3017 #if defined(_FM77_VARIANTS)
3018 kanjisub = state_fio->FgetBool();
3020 kanjiaddr.w.l = state_fio->FgetUint16_BE();
3021 # if defined(_FM77L4)
3022 mode400line = state_fio->FgetBool();
3023 stat_400linecard = state_fio->FgetBool();
3025 #elif defined(_FM77AV_VARIANTS)
3026 kanjisub = state_fio->FgetBool();
3028 kanjiaddr.w.l = state_fio->FgetUint16_BE();
3030 vblank = state_fio->FgetBool();
3031 vsync = state_fio->FgetBool();
3032 hblank = state_fio->FgetBool();
3033 vblank_count = state_fio->FgetInt32_BE();
3035 mode320 = state_fio->FgetBool();
3036 display_page = state_fio->FgetInt8();
3037 display_page_bak = state_fio->FgetInt8();
3038 cgrom_bank = state_fio->FgetInt32_BE();
3039 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3040 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3041 vram_bank = state_fio->FgetInt32_BE();
3043 screen_update_flag = true;
3044 displine = state_fio->FgetUint32_BE();
3045 subrom_bank = state_fio->FgetUint8();
3046 subrom_bank_using = state_fio->FgetUint8();
3048 nmi_enable = state_fio->FgetBool();
3049 use_alu = state_fio->FgetBool();
3051 apalette_index.b.l = state_fio->FgetUint8();
3052 apalette_index.b.h = state_fio->FgetUint8();
3054 state_fio->Fread(analog_palette_r, sizeof(analog_palette_r), 1);
3055 state_fio->Fread(analog_palette_g, sizeof(analog_palette_g), 1);
3056 state_fio->Fread(analog_palette_b, sizeof(analog_palette_b), 1);
3057 for(i = 0; i < 4096; i++) calc_apalette(i);
3059 diag_load_subrom_a = state_fio->FgetBool();
3060 diag_load_subrom_b = state_fio->FgetBool();
3061 diag_load_subrom_cg = state_fio->FgetBool();
3063 state_fio->Fread(subsys_a, sizeof(subsys_a), 1);
3064 state_fio->Fread(subsys_b, sizeof(subsys_b), 1);
3065 state_fio->Fread(subsys_cg, sizeof(subsys_cg), 1);
3066 state_fio->Fread(submem_hidden, sizeof(submem_hidden), 1);
3068 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3069 mode400line = state_fio->FgetBool();
3070 mode256k = state_fio->FgetBool();
3072 monitor_ram = state_fio->FgetBool();
3073 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3074 window_low = state_fio->FgetUint16_BE();
3075 window_high = state_fio->FgetUint16_BE();
3076 window_xbegin = state_fio->FgetUint16_BE();
3077 window_xend = state_fio->FgetUint16_BE();
3078 window_opened = state_fio->FgetBool();
3080 kanji_level2 = state_fio->FgetBool();
3082 vram_active_block = state_fio->FgetUint8();
3083 vram_display_block = state_fio->FgetUint8();
3084 console_ram_bank = state_fio->FgetUint8();
3085 ram_protect = state_fio->FgetBool();
3087 cgram_bank = state_fio->FgetUint32_BE();
3088 state_fio->Fread(subsys_ram, sizeof(subsys_ram), 1);
3089 state_fio->Fread(submem_cgram, sizeof(submem_cgram), 1);
3090 state_fio->Fread(submem_console_av40, sizeof(submem_console_av40), 1);
3093 palette_changed = true;
3094 vram_wrote_shadow = true; // Force Draw
3095 this->draw_screen();
3096 if(version == 1) return true;
3098 if(version >= 2) { //V2
3099 nmi_event_id = state_fio->FgetInt32_BE();
3100 #if defined(_FM77AV_VARIANTS)
3101 hblank_event_id = state_fio->FgetInt32_BE();
3102 hdisp_event_id = state_fio->FgetInt32_BE();
3103 vsync_event_id = state_fio->FgetInt32_BE();
3104 vstart_event_id = state_fio->FgetInt32_BE();
3106 firq_mask = state_fio->FgetBool();
3107 vram_accessflag = state_fio->FgetBool();
3108 frame_skip_count_draw = 3;
3109 frame_skip_count_transfer = 3;
3110 need_transfer_line = true;
3112 if(version == STATE_VERSION) return true;
3113 setup_display_mode();