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(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
30 kanjisub = false; // fix by Ryu Takegami
32 #if defined(_FM77AV_VARIANTS)
38 for(int i = 0; i < 256; i++) {
39 uint16_t n = (uint16_t)i;
40 for(int j = 0; j < 8; j++) {
41 bit_trans_table_0[i][j] = n & 0x80;
42 bit_trans_table_1[i][j] = ((n & 0x80) != 0) ? 0x40 : 0;
43 bit_trans_table_2[i][j] = ((n & 0x80) != 0) ? 0x20 : 0;
44 bit_trans_table_3[i][j] = ((n & 0x80) != 0) ? 0x10 : 0;
45 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
46 bit_trans_table_4[i][j] = ((n & 0x80) != 0) ? 0x08 : 0;
47 bit_trans_table_5[i][j] = ((n & 0x80) != 0) ? 0x04 : 0;
54 set_device_name(_T("DISPLAY SUBSYSTEM"));
62 void DISPLAY::reset_some_devices()
66 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
67 mainio->write_signal(SIG_FM7_SUB_HALT, 0x00, 0xff);
70 palette_changed = true;
71 multimode_accessmask = 0;
72 multimode_dispmask = 0;
73 for(i = 0; i < 4; i++) {
74 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
75 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
77 //firq_mask = false; // 20180215 Thanks to Ryu takegami.
78 //cancel_request = false;
79 switch(config.cpu_type){
88 prev_clock = SUBCLOCK_NORMAL;
90 prev_clock = SUBCLOCK_SLOW;
95 for(i = 0; i < 2; i++) {
96 offset_changed[i] = true;
97 tmp_offset_point[i].d = 0;
100 vram_wrote_shadow = true;
101 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
102 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
106 #if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
112 if(hblank_event_id >= 0) cancel_event(this, hblank_event_id);
113 if(hdisp_event_id >= 0) cancel_event(this, hdisp_event_id);
114 if(vsync_event_id >= 0) cancel_event(this, vsync_event_id);
115 if(vstart_event_id >= 0) cancel_event(this, vstart_event_id);
116 hblank_event_id = -1;
119 vstart_event_id = -1;
120 if(display_mode == DISPLAY_MODE_8_400L) {
121 usec = 0.33 * 1000.0;
123 usec = 0.51 * 1000.0;
126 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
127 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
128 mainio->write_signal(SIG_DISPLAY_VSYNC, 0xff, 0xff);
130 #if defined(_FM77AV_VARIANTS)
132 offset_point_bank1 = 0;
134 display_page_bak = 0;
136 subcpu_resetreq = false;
137 subrom_bank_using = subrom_bank;
142 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
144 vram_display_block = 0;
145 vram_active_block = 0;
147 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
152 window_opened = false;
157 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
158 alu->write_signal(SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
159 alu->write_signal(SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400: 200, 0xffff);
160 alu->write_signal(SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xffffffff : 0, 0xffffffff);
162 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
163 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
164 alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
166 alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
167 alu->write_signal(SIG_ALU_PLANES, 3, 3);
169 for(i = 0; i < 8; i++) set_dpalette(i, i);
170 //do_firq(!firq_mask && key_firq_req);
172 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
173 //kanjisub = false; // Fixed by Ryu takegami
174 kanjiaddr.d = 0x00000000;
175 # if defined(_FM77L4)
177 stat_400linecard = false;
182 frame_skip_count_draw = 3;
183 frame_skip_count_transfer = 3;
184 need_transfer_line = true;
185 setup_display_mode();
189 void DISPLAY::reset()
194 vram_accessflag = true;
195 display_mode = DISPLAY_MODE_8_200L;
197 crt_flag = false; // Fixed by Ryu Takegami
198 screen_update_flag = true;
199 crt_flag_bak = false;
201 cancel_request = false;
202 #if defined(_FM77AV_VARIANTS)
204 apalette_index.d = 0;
205 for(i = 0; i < 4096; i++) {
206 analog_palette_r[i] = i & 0x0f0;
207 analog_palette_g[i] = (i & 0xf00) >> 4;
208 analog_palette_b[i] = (i & 0x00f) << 4;
213 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
220 #elif defined(_FM77L4)
224 #if !defined(FIXED_FRAMEBUFFER_SIZE)
225 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
227 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
229 emu->set_vm_screen_lines(200);
231 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
232 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
233 reset_some_devices();
235 #if defined(_FM77AV_VARIANTS)
236 power_on_reset = false;
237 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
241 for(i = 0; i < 8; i++) set_dpalette(i, i);
246 if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
247 register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
251 void DISPLAY::reset_subcpu(bool _check_firq)
253 subcpu->write_signal(SIG_CPU_HALTREQ, 0, 1);
254 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
257 do_firq(!firq_mask && key_firq_req);
260 void DISPLAY::setup_display_mode(void)
262 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
263 if(display_mode == DISPLAY_MODE_8_400L) {
264 page_offset = 0x0000;
265 pagemod_mask = 0x18000;
267 } else if(display_mode == DISPLAY_MODE_256k) {
268 if(active_page != 0) {
269 page_offset = 0xc000;
271 page_offset = 0x0000;
273 pagemod_mask = 0xe000;
275 } else if(display_mode == DISPLAY_MODE_4096) {
276 if(active_page != 0) {
277 page_offset = 0xc000;
279 page_offset = 0x0000;
281 pagemod_mask = 0xe000;
284 if(active_page != 0) {
285 page_offset = 0xc000;
287 page_offset = 0x0000;
289 pagemod_mask = 0xc000;
292 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
293 if(vram_active_block != 0) page_offset += 0x18000;
295 #elif defined(_FM77AV_VARIANTS)
298 pagemod_mask = 0xe000;
299 } else { // 640x200, 8colors
301 pagemod_mask = 0xc000;
303 if(active_page != 0) {
304 page_offset = 0xc000;
306 page_offset = 0x0000;
308 #elif defined(_FM77L4)
309 if(display_mode == DISPLAY_MODE_8_400L) {
311 pagemod_mask = 0xe000;
312 } else { // 640x200, 8colors
314 pagemod_mask = 0xc000;
316 page_offset = 0x0000;
318 page_offset = 0x0000;
319 pagemod_mask = 0xc000;
323 void DISPLAY::update_config()
327 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
333 * Vram accessing functions moved to vram.cpp .
336 void DISPLAY::do_irq(bool flag)
338 subcpu->write_signal(SIG_CPU_IRQ, flag ? 1: 0, 1);
341 void DISPLAY::do_firq(bool flag)
343 subcpu->write_signal(SIG_CPU_FIRQ, flag ? 1: 0, 1);
346 void DISPLAY::do_nmi(bool flag)
348 #if defined(_FM77AV_VARIANTS)
349 if(!nmi_enable) flag = false;
351 subcpu->write_signal(SIG_CPU_NMI, flag ? 1 : 0, 1);
354 void DISPLAY::set_multimode(uint8_t val)
357 multimode_accessmask = val & 0x07;
358 multimode_dispmask = (val & 0x70) >> 4;
359 for(int i = 0; i < 4; i++) {
360 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
361 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
364 # if defined(_FM77AV_VARIANTS)
365 alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
370 uint8_t DISPLAY::get_multimode(void)
376 val = multimode_accessmask & 0x07;
377 val |= ((multimode_dispmask << 4) & 0x70);
383 uint8_t DISPLAY::get_cpuaccessmask(void)
385 return multimode_accessmask & 0x07;
388 void DISPLAY::set_dpalette(uint32_t addr, uint8_t val)
392 dpalette_data[addr] = val | 0xf8; //0b11111000;
393 b = ((val & 0x01) != 0x00)? 255 : 0x00;
394 r = ((val & 0x02) != 0x00)? 255 : 0x00;
395 g = ((val & 0x04) != 0x00)? 255 : 0x00;
397 dpalette_pixel[addr] = RGB_COLOR(r, g, b);
398 palette_changed = true;
401 uint8_t DISPLAY::get_dpalette(uint32_t addr)
409 data = dpalette_data[addr];
414 void DISPLAY::halt_subcpu(void)
416 //subcpu->write_signal(SIG_CPU_BUSREQ, 0x01, 0x01);
417 subcpu->write_signal(SIG_CPU_HALTREQ, 0x01, 0x01);
420 void DISPLAY::go_subcpu(void)
422 subcpu->write_signal(SIG_CPU_HALTREQ, 0x00, 0x01);
425 void DISPLAY::enter_display(void)
429 subclock = SUBCLOCK_NORMAL;
431 subclock = SUBCLOCK_SLOW;
433 if(!is_cyclesteal && vram_accessflag) {
434 subclock = subclock / 3;
436 if(prev_clock != subclock) p_vm->set_cpu_clock(subcpu, subclock);
437 prev_clock = subclock;
440 void DISPLAY::leave_display(void)
444 void DISPLAY::halt_subsystem(void)
450 void DISPLAY::restart_subsystem(void)
453 #if defined(_FM77AV_VARIANTS)
454 if(subcpu_resetreq) {
455 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
456 reset_some_devices();
457 power_on_reset = true;
465 void DISPLAY::set_crtflag(void)
472 void DISPLAY::reset_crtflag(void)
479 uint8_t DISPLAY::acknowledge_irq(void)
481 cancel_request = false;
487 uint8_t DISPLAY::beep(void)
489 mainio->write_signal(FM7_MAINIO_BEEP, 0x01, 0x01);
490 return 0xff; // True?
495 uint8_t DISPLAY::attention_irq(void)
497 mainio->write_signal(FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
502 void DISPLAY::set_cyclesteal(uint8_t val)
505 # if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
509 is_cyclesteal = true;
511 is_cyclesteal = false;
519 uint8_t DISPLAY::set_vramaccess(void)
521 vram_accessflag = true;
526 void DISPLAY::reset_vramaccess(void)
528 vram_accessflag = false;
532 uint8_t DISPLAY::reset_subbusy(void)
539 void DISPLAY::set_subbusy(void)
545 #if defined(_FM77AV_VARIANTS)
547 void DISPLAY::alu_write_cmdreg(uint32_t val)
549 alu->write_data8(ALU_CMDREG, val);
550 if((val & 0x80) != 0) {
558 void DISPLAY::alu_write_logical_color(uint8_t val)
560 uint32_t data = (uint32_t)val;
561 alu->write_data8(ALU_LOGICAL_COLOR, data);
565 void DISPLAY::alu_write_mask_reg(uint8_t val)
567 uint32_t data = (uint32_t)val;
568 alu->write_data8(ALU_WRITE_MASKREG, data);
572 void DISPLAY::alu_write_cmpdata_reg(int addr, uint8_t val)
574 uint32_t data = (uint32_t)val;
576 alu->write_data8(ALU_CMPDATA_REG + addr, data);
580 void DISPLAY::alu_write_disable_reg(uint8_t val)
582 uint32_t data = (uint32_t)val;
583 alu->write_data8(ALU_BANK_DISABLE, data);
587 void DISPLAY::alu_write_tilepaint_data(uint32_t addr, uint8_t val)
589 uint32_t data = (uint32_t)val;
592 alu->write_data8(ALU_TILEPAINT_B, data);
595 alu->write_data8(ALU_TILEPAINT_R, data);
598 alu->write_data8(ALU_TILEPAINT_G, data);
601 //alu->write_data8(ALU_TILEPAINT_L, 0xff);
607 void DISPLAY::alu_write_offsetreg_hi(uint8_t val)
609 alu->write_data8(ALU_OFFSET_REG_HIGH, val & 0x7f);
613 void DISPLAY::alu_write_offsetreg_lo(uint8_t val)
615 alu->write_data8(ALU_OFFSET_REG_LO, val);
619 void DISPLAY::alu_write_linepattern_hi(uint8_t val)
621 alu->write_data8(ALU_LINEPATTERN_REG_HIGH, val);
625 void DISPLAY::alu_write_linepattern_lo(uint8_t val)
627 alu->write_data8(ALU_LINEPATTERN_REG_LO, val);
631 void DISPLAY::alu_write_line_position(int addr, uint8_t val)
633 uint32_t data = (uint32_t)val;
636 alu->write_data8(ALU_LINEPOS_START_X_HIGH, data & 0x03);
639 alu->write_data8(ALU_LINEPOS_START_X_LOW, data);
642 alu->write_data8(ALU_LINEPOS_START_Y_HIGH, data & 0x01);
645 alu->write_data8(ALU_LINEPOS_START_Y_LOW, data);
648 alu->write_data8(ALU_LINEPOS_END_X_HIGH, data & 0x03);
651 alu->write_data8(ALU_LINEPOS_END_X_LOW, data);
654 alu->write_data8(ALU_LINEPOS_END_Y_HIGH, data & 0x01);
657 alu->write_data8(ALU_LINEPOS_END_Y_LOW, data);
663 uint8_t DISPLAY::get_miscreg(void)
668 if(!hblank) ret |= 0x80;
669 if(vsync) ret |= 0x04;
670 if(alu->read_signal(SIG_ALU_BUSYSTAT) == 0) ret |= 0x10;
671 if(power_on_reset) ret |= 0x01;
676 void DISPLAY::set_miscreg(uint8_t val)
678 int old_display_page = display_page;
680 nmi_enable = ((val & 0x80) == 0) ? true : false;
681 if(!nmi_enable) do_nmi(false);
683 if((val & 0x40) == 0) {
688 if(display_page != old_display_page) {
691 active_page = ((val & 0x20) == 0) ? 0 : 1;
692 if((val & 0x04) == 0) {
697 cgrom_bank = val & 0x03;
698 setup_display_mode();
702 void DISPLAY::set_monitor_bank(uint8_t var)
704 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
705 if((var & 0x04) != 0){
711 subrom_bank = var & 0x03;
714 subcpu_resetreq = false;
715 power_on_reset = true;
716 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
717 reset_some_devices();
720 subcpu_resetreq = true;
726 void DISPLAY::set_apalette_index_hi(uint8_t val)
728 apalette_index.b.h = val & 0x0f;
732 void DISPLAY::set_apalette_index_lo(uint8_t val)
734 apalette_index.b.l = val;
737 void DISPLAY::calc_apalette(uint16_t idx)
741 g = analog_palette_g[idx];
742 r = analog_palette_r[idx];
743 b = analog_palette_b[idx];
744 if(g != 0) g |= 0x0f;
745 if(r != 0) r |= 0x0f;
746 if(b != 0) b |= 0x0f;
747 analog_palette_pixel[idx] = RGB_COLOR(r, g, b);
751 void DISPLAY::set_apalette_b(uint8_t val)
755 index = apalette_index.w.l;
756 tmp = (val & 0x0f) << 4;
757 if(analog_palette_b[index] != tmp) {
758 analog_palette_b[index] = tmp;
759 calc_apalette(index);
760 palette_changed = true;
765 void DISPLAY::set_apalette_r(uint8_t val)
769 index = apalette_index.w.l;
770 tmp = (val & 0x0f) << 4;
771 if(analog_palette_r[index] != tmp) {
772 analog_palette_r[index] = tmp;
773 calc_apalette(index);
774 palette_changed = true;
779 void DISPLAY::set_apalette_g(uint8_t val)
783 index = apalette_index.w.l;
784 tmp = (val & 0x0f) << 4;
785 if(analog_palette_g[index] != tmp) {
786 analog_palette_g[index] = tmp;
787 calc_apalette(index);
788 palette_changed = true;
792 #endif // _FM77AV_VARIANTS
795 void DISPLAY::copy_vram_blank_area(void)
799 void DISPLAY::copy_vram_per_line(int begin, int end)
808 uint32_t src_offset_d1;
809 uint32_t src_offset_d2;
810 uint32_t src_offset_d;
815 uint32_t addr_d1, addr_d2;
819 //int dline = (int)displine - 1;
820 int dline = (int)displine;
822 if((begin < 0) || (begin > 4)) return;
823 if((end < 0) || (end > 4)) return;
824 if(begin > end) return;
825 if(dline < 0) return;
827 sectors = end - begin + 1;
829 if(display_mode == DISPLAY_MODE_8_400L) {
830 if(dline >= 400) return;
832 if(dline >= 200) return;
834 #if defined(_FM77AV_VARIANTS)
835 yoff_d1 = offset_point;
836 yoff_d2 = offset_point_bank1;
837 if(display_mode == DISPLAY_MODE_4096) {
838 src_offset = dline * 40 + begin * 8;
839 sectors = sectors * 8;
840 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
843 addr_d1 = (src_offset + yoff_d1) & 0x1fff;
844 addr_d2 = (src_offset + yoff_d2) & 0x1fff;
845 bytes_d1 = 0x2000 - addr_d1;
846 bytes_d2 = 0x2000 - addr_d2;
847 for(k = 0; k < pages; k++) {
849 for(i = 0; i < 3; i++) {
850 for(j = 0; j < 2; j++) {
851 uint32_t _addr_base = src_base + src_offset + poff;
852 if(bytes_d1 < sectors) {
853 my_memcpy(&gvram_shadow[_addr_base],
854 &gvram[addr_d1 + src_base + poff],
856 my_memcpy(&gvram_shadow[_addr_base + bytes_d1],
857 &gvram[src_base + poff],
860 my_memcpy(&gvram_shadow[_addr_base],
861 &gvram[addr_d1 + src_base + poff],
864 _addr_base += 0xc000;
865 if(bytes_d2 < sectors) {
866 my_memcpy(&gvram_shadow[_addr_base],
867 &gvram[addr_d2 + src_base + poff + 0xc000],
869 my_memcpy(&gvram_shadow[_addr_base + bytes_d2],
870 &gvram[src_base + poff + 0xc000],
873 my_memcpy(&gvram_shadow[_addr_base],
874 &gvram[addr_d2 + src_base + poff + 0xc000],
879 src_base = (i + 1) * 0x4000;
883 vram_draw_table[dline] = true;
884 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
886 # if defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV40)
887 else if(display_mode == DISPLAY_MODE_256k) {
888 src_offset = dline * 40 + begin * 8;
889 sectors = sectors * 8;
891 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
893 #elif defined(_FM77AV40)
898 src_offset_d1 = (src_offset + yoff_d1) & 0x1fff;
899 src_offset_d2 = (src_offset + yoff_d2) & 0x1fff;
900 bytes_d1 = 0x2000 - ((src_offset + yoff_d1) & 0x1fff);
901 bytes_d2 = 0x2000 - ((src_offset + yoff_d2) & 0x1fff);
902 for(k = 0; k < pages; k++) {
903 for(i = 0; i < 3; i++) {
904 for(j = 0; j < 2; j++) {
906 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
907 src_offset_d = src_offset_d1;
910 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
911 src_offset_d = src_offset_d2;
914 if(bytes_d < sectors) {
915 my_memcpy(&gvram_shadow[src_offset + src_base],
916 &gvram[src_offset_d + src_base],
918 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
922 my_memcpy(&gvram_shadow[src_offset + src_base],
923 &gvram[src_offset_d + src_base],
929 vram_draw_table[dline] = true;
930 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
932 else if(display_mode == DISPLAY_MODE_8_400L) {
933 src_offset = dline * 80 + begin * 16;
934 sectors = sectors * 16;
935 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
938 if(display_page_bak == 1) { // Is this dirty?
943 yoff_d = (yoff_d << 1) & 0x7fff;
944 src_offset_d = (src_offset + yoff_d) & 0x7fff;
945 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
946 for(i = 0; i < pages; i++) {
947 for(j = 0; j < 3; j++) {
948 src_base = i * 0x18000 + j * 0x8000;
949 if(bytes_d < sectors) {
951 my_memcpy(&gvram_shadow[src_offset + src_base],
952 &gvram[src_offset_d + src_base],
955 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
959 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
960 &gvram[src_offset_d + src_base],
965 vram_draw_table[dline] = true;
966 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
970 src_offset = dline * 80 + begin * 16;
971 sectors = sectors * 16;
972 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
974 #elif defined(_FM77AV40)
976 #elif defined(_FM77AV_VARIANTS)
982 src_offset_d1 = (src_offset + yoff_d1) & 0x3fff;
983 src_offset_d2 = (src_offset + yoff_d2) & 0x3fff;
984 bytes_d1 = 0x4000 - ((src_offset + yoff_d1) & 0x3fff);
985 bytes_d2 = 0x4000 - ((src_offset + yoff_d2) & 0x3fff);
986 for(i = 0; i < pages; i++) {
988 src_offset_d = src_offset_d1;
991 src_offset_d = src_offset_d2;
995 for(j = 0; j < 3; j++) {
996 if(bytes_d < sectors) {
997 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
998 &gvram[src_offset_d + src_base + poff],
1000 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1001 &gvram[src_base + poff],
1004 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1005 &gvram[src_offset_d + src_base + poff],
1012 vram_draw_table[dline] = true;
1013 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1014 //vram_wrote_table[dline] = false;
1018 src_offset = dline * 80 + begin * 16;
1019 sectors = sectors * 16;
1022 yoff_d = offset_point;
1023 src_offset_d = (src_offset + yoff_d) & 0x3fff;
1024 bytes_d = 0x4000 - ((src_offset + yoff_d) & 0x3fff);
1025 for(j = 0; j < 3; j++) {
1026 src_base = j * 0x4000;
1027 if(bytes_d < sectors) {
1028 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1029 &gvram[src_offset_d + src_base + poff],
1031 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1032 &gvram[src_base + poff],
1035 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1036 &gvram[src_offset_d + src_base + poff],
1040 vram_draw_table[dline] = true;
1041 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1042 //vram_wrote_table[dline] = false;
1048 void DISPLAY::copy_vram_all()
1050 #if defined(_FM77AV_VARIANTS)
1051 uint32_t yoff_d1 = offset_point;
1052 uint32_t yoff_d2 = offset_point_bank1;
1053 uint32_t src_offset_1, src_offset_2;
1055 if(display_mode == DISPLAY_MODE_4096) {
1056 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1061 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1062 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1063 for(int k = 0; k < pages; k++) {
1064 for(int i = 0; i < 3; i++) {
1065 for(int j = 0; j < 2; j++) {
1066 src_offset_1 = i * 0x4000 + j * 0x2000;
1067 src_offset_2 = src_offset_1 + 0xc000;
1068 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1069 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1070 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1071 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1077 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1078 else if(display_mode == DISPLAY_MODE_256k) {
1079 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1080 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1081 for(int i = 0; i < 3; i++) {
1082 for(int j = 0; j < 2; j++) {
1083 src_offset_1 = i * 0x4000 + j * 0x2000;
1084 src_offset_2 = src_offset_1 + 0xc000;
1085 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1086 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1087 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1088 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1092 for(int i = 0; i < 3; i++) {
1093 for(int j = 0; j < 2; j++) {
1094 src_offset_1 = i * 0x4000 + j * 0x2000;
1095 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1096 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1099 } else if(display_mode == DISPLAY_MODE_8_400L) {
1101 uint32_t yoff_d, bytes_d;
1102 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1105 if(display_page_bak == 1) { // Is this dirty?
1110 yoff_d = (yoff_d << 1) & 0x7fff;
1111 bytes_d = 0x8000 - yoff_d;
1112 for(int i = 0; i < pages; i++) {
1113 for(int j = 0; j < 3; j++) {
1114 uint32_t src_base = i * 0x18000 + j * 0x8000;
1115 my_memcpy(&gvram_shadow[src_base],
1116 &gvram[yoff_d + src_base],
1118 if(bytes_d < 0x8000) {
1119 my_memcpy(&gvram_shadow[bytes_d + src_base],
1128 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1130 #elif defined(_FM77AV40)
1135 uint32_t bytes_d1 = 0x4000 - (yoff_d1 & 0x3fff);
1136 uint32_t bytes_d2 = 0x4000 - (yoff_d2 & 0x3fff);
1137 uint32_t yoff_d, bytes_d;
1138 for(int k = 0; k < pages; k++) {
1139 yoff_d = ((k & 1) == 0) ? (yoff_d1 & 0x3fff) : (yoff_d2 & 0x3fff);
1140 bytes_d = ((k & 1) == 0) ? bytes_d1 : bytes_d2;
1141 for(int j = 0; j < 3; j++) {
1142 src_offset_1 = k * 0xc000 + j * 0x4000;
1143 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1144 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1150 uint32_t yoff_d = offset_point & 0x3fff;
1151 uint32_t bytes_d = 0x4000 - (offset_point & 0x3fff);
1152 uint32_t src_offset_1;
1153 for(int j = 0; j < 3; j++) {
1154 src_offset_1 = j * 0x4000;
1155 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1156 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1162 // Timing values from XM7 . Thanks Ryu.
1163 #if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1164 void DISPLAY::event_callback_hdisp(void)
1171 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x02, 0xff);
1172 if(display_mode == DISPLAY_MODE_8_400L) {
1173 if(displine < 400) f = true;
1175 if(displine < 200) f = true;
1179 // DO ONLY WHEN SYNC-TO-HSYNC.
1180 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
1182 //copy_vram_per_line(0, 4);
1183 } else if(need_transfer_line) { // Not frame skip.
1186 for(int iii = 0; iii < 5 ; iii++) {
1187 if(vram_wrote_table[iii + displine * 5]) {
1188 if(begin < 0) begin = iii; // Check first.
1193 if(end < begin) end = begin;
1195 copy_vram_per_line(begin, end);
1196 // Prepare to next block.
1202 // Tail of this line.
1205 copy_vram_per_line(begin, end);
1209 if(display_mode == DISPLAY_MODE_8_400L) {
1210 register_event(this, EVENT_FM7SUB_HBLANK, 30.0, false, &hblank_event_id); // NEXT CYCLE_
1212 register_event(this, EVENT_FM7SUB_HBLANK, 39.5, false, &hblank_event_id); // NEXT CYCLE_
1220 void DISPLAY::event_callback_hblank(void)
1228 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1229 if(display_mode == DISPLAY_MODE_8_400L) {
1230 if((displine < 400)) f = true;
1233 if((displine < 200)) f = true;
1237 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id);
1242 void DISPLAY::event_callback_vstart(void)
1249 display_page_bak = display_page;
1251 // Parameter from XM7/VM/display.c , thanks, Ryu.
1252 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1253 mainio->write_signal(SIG_DISPLAY_VSYNC, 0x00, 0xff);
1255 if(vblank_count != 0) {
1256 if(display_mode == DISPLAY_MODE_8_400L) {
1257 usec = (0.98 + 16.4) * 1000.0;
1259 usec = (1.91 + 12.7) * 1000.0;
1261 register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
1263 if(display_mode == DISPLAY_MODE_8_400L) {
1264 usec = 930.0; // 939.0
1266 usec = 1840.0; // 1846.5
1268 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
1271 if(display_mode == DISPLAY_MODE_8_400L) {
1272 usec = 0.34 * 1000.0;
1274 usec = 1.52 * 1000.0;
1276 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1280 void DISPLAY::event_callback_vsync(void)
1286 //write_access_page = (write_access_page + 1) & 1;
1288 if(display_mode == DISPLAY_MODE_8_400L) {
1289 usec = 0.33 * 1000.0;
1291 usec = 0.51 * 1000.0;
1293 mainio->write_signal(SIG_DISPLAY_VSYNC, 0x01, 0xff);
1294 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1295 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1297 // Transfer on VSYNC
1298 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) {
1301 if(display_mode == DISPLAY_MODE_8_400L) lines = 400;
1303 if(need_transfer_line) {
1304 if(vram_wrote) ff = true;
1305 //if(need_transfer_line) ff = true;
1307 for(displine = 0; displine < lines; displine++) {
1309 for(int iii = 0; iii < 5 ; iii++) {
1310 if(vram_wrote_table[iii + displine * 5]) {
1320 for(int yy = 0; yy < lines; yy++) {
1321 if(!vram_draw_table[yy]) {
1323 copy_vram_per_line(0, 4);
1324 vram_draw_table[yy] = true;
1328 vram_wrote_shadow = true;
1329 screen_update_flag = true;
1333 if(need_transfer_line) {
1334 if(vram_wrote) { // transfer all line
1335 for(displine = 0; displine < lines; displine++) {
1336 //if(!vram_draw_table[displine]) {
1337 copy_vram_per_line(0, 4);
1341 } else { // transfer wrote line
1344 for(displine = 0; displine < lines; displine++) {
1345 //if(!vram_draw_table[displine]) {
1346 for(int iii = 0; iii < 5 ; iii++) {
1347 if(vram_wrote_table[iii + displine * 5]) {
1354 if(end < begin) end = begin;
1355 copy_vram_per_line(begin, end);
1362 if(end < 0) end = 4;
1363 copy_vram_per_line(begin, end);
1371 for(int yy = 0; yy < lines; yy++) {
1372 if(vram_draw_table[yy]) {
1373 vram_wrote_shadow = true;
1374 screen_update_flag = true;
1380 // TRANSFER per HSYNC a.k.a SYNC-TO-HSYNC.
1382 if(display_mode == DISPLAY_MODE_8_400L) lines = 400;
1384 if(need_transfer_line) {
1385 if(vram_wrote) { // Transfer all line.
1386 for(int yy = 0; yy < lines; yy++) {
1388 copy_vram_per_line(0, 4);
1394 for(int yy = 0; yy < lines; yy++) {
1395 if(vram_draw_table[yy]) {
1396 vram_wrote_shadow = true;
1397 screen_update_flag = true;
1401 //vram_wrote = false;
1403 frame_skip_count_transfer++;
1405 // Check frame skip for next frame.
1406 uint32_t factor = ((config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28) & 3;
1407 if((frame_skip_count_transfer > factor) /* || (vram_wrote) */) {
1408 frame_skip_count_transfer = 0;
1409 need_transfer_line = true;
1411 need_transfer_line = false;
1418 void DISPLAY::event_callback(int event_id, int err)
1423 case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
1424 #if defined(_FM77AV_VARIANTS)
1432 case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
1435 #if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1436 case EVENT_FM7SUB_HDISP:
1437 event_callback_hdisp();
1439 case EVENT_FM7SUB_HBLANK:
1440 event_callback_hblank();
1442 case EVENT_FM7SUB_VSTART: // Call first.
1443 event_callback_vstart();
1445 case EVENT_FM7SUB_VSYNC:
1446 event_callback_vsync();
1449 case EVENT_FM7SUB_CLR_BUSY:
1452 case EVENT_FM7SUB_CLR_CRTFLAG:
1458 void DISPLAY::event_frame()
1460 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1464 if(display_mode == DISPLAY_MODE_8_400L) lines = 400;
1466 if(need_transfer_line && vram_wrote) {
1467 for(yy = 0; yy < lines; yy++) {
1468 //if(!vram_draw_table[yy]) {
1470 copy_vram_per_line(0, 4);
1478 for(yy = 0; yy < lines; yy++) {
1479 if(vram_draw_table[yy]) {
1485 screen_update_flag = true;
1486 vram_wrote_shadow = true;
1490 frame_skip_count_transfer++;
1492 uint32_t factor = (config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28;
1493 if(frame_skip_count_transfer > factor) {
1494 frame_skip_count_transfer = 0;
1495 need_transfer_line = true;
1497 need_transfer_line = false;
1499 //vram_wrote = false;
1506 void DISPLAY::event_vline(int v, int clock)
1508 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1510 if(need_transfer_line == false) return;
1513 // Not transfer, will transfer at event_frame.
1514 copy_vram_per_line(0, 4);
1518 for(int iii = 0; iii < 5 ; iii++) {
1519 if(vram_wrote_table[displine * 5 + iii]) {
1520 if(begin < 0) begin = iii;
1524 if(end < begin) end = begin;
1525 copy_vram_per_line(begin, end);
1533 copy_vram_per_line(begin, end);
1541 uint32_t DISPLAY::read_signal(int id)
1543 uint32_t retval = 0;
1545 case SIG_FM7_SUB_HALT:
1546 case SIG_DISPLAY_HALT:
1547 retval = (halt_flag) ? 0xffffffff : 0;
1549 case SIG_DISPLAY_BUSY:
1550 retval = (sub_busy) ? 0x80 : 0;
1552 case SIG_DISPLAY_MULTIPAGE:
1553 retval = multimode_accessmask;
1555 case SIG_DISPLAY_PLANES:
1558 #if defined(_FM77AV_VARIANTS)
1559 case SIG_DISPLAY_VSYNC:
1560 retval = (vsync) ? 0x01 : 0x00;
1562 case SIG_DISPLAY_DISPLAY:
1563 retval = (!hblank) ? 0x02: 0x00;
1565 case SIG_FM7_SUB_BANK: // Main: FD13
1566 retval = subrom_bank & 0x03;
1567 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1568 if(monitor_ram) retval |= 0x04;
1572 #if defined(_FM77AV_VARIANTS)
1573 case SIG_DISPLAY_MODE320:
1574 retval = (mode320) ? 0x40: 0x00;
1577 case SIG_DISPLAY_Y_HEIGHT:
1578 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1579 retval = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
1584 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1586 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1587 retval |= (kanjisub) ? 0x00 : 0x20;
1588 retval |= (mode256k) ? 0x10 : 0x00;
1589 retval |= (mode400line) ? 0x00 : 0x08;
1590 retval |= (ram_protect) ? 0x00 : 0x04;
1591 #elif defined(_FM77L4)
1592 retval |= (mode400line) ? 0x00 : 0x08;
1595 case SIG_DISPLAY_X_WIDTH:
1596 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1597 retval = (mode320 || mode256k) ? 320 : 640;
1598 #elif defined(_FM77AV_VARIANTS)
1599 retval = (mode320) ? 320 : 640;
1610 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
1612 bool flag = ((data & mask) != 0);
1616 case SIG_FM7_SUB_HALT:
1621 //mainio->write_signal(SIG_FM7_SUB_HALT, data, mask);
1623 case SIG_DISPLAY_HALT:
1627 restart_subsystem();
1630 case SIG_FM7_SUB_CANCEL:
1632 cancel_request = true;
1636 case SIG_DISPLAY_CLOCK:
1640 #if defined(_FM77AV_VARIANTS)
1641 case SIG_FM7_SUB_BANK: // Main: FD13
1642 set_monitor_bank(data & 0xff);
1645 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1646 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1647 //printf("Wrote $FD04: %02x\n", data);
1649 int oldmode = display_mode;
1651 kanjisub = ((data & 0x20) == 0) ? true : false;
1652 mode256k = (((data & 0x10) != 0) && ((data & 0x08) != 0) ) ? true : false;
1653 mode400line = ((data & 0x08) == 0) ? true : false;
1654 ram_protect = ((data & 0x04) == 0) ? true : false;
1655 if((mode400line) && !(mode320)) {
1656 display_mode = DISPLAY_MODE_8_400L;
1657 } else if(mode256k) {
1658 display_mode = DISPLAY_MODE_256k;
1660 display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1662 if(oldmode != display_mode) {
1664 if(mode320 || mode256k) {
1665 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1666 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1667 for(y = 0; y < 200; y++) {
1668 pp = emu->get_screen_buffer(y);
1669 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1672 for(y = 0; y < 400; y++) {
1673 pp = emu->get_screen_buffer(y);
1674 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1677 //emu->set_vm_screen_lines(200);
1678 } else if(display_mode == DISPLAY_MODE_8_400L) {
1679 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1680 //emu->set_vm_screen_lines(400);
1681 for(y = 0; y < 400; y++) {
1682 pp = emu->get_screen_buffer(y);
1683 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1686 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1687 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1688 for(y = 0; y < 200; y++) {
1689 pp = emu->get_screen_buffer(y);
1690 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1693 for(y = 0; y < 400; y++) {
1694 pp = emu->get_screen_buffer(y);
1695 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1698 //emu->set_vm_screen_lines(200);
1701 alu->write_signal(SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
1702 alu->write_signal(SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200, 0xffff);
1703 alu->write_signal(SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xff : 0x00, 0xff);
1704 frame_skip_count_draw = 3;
1705 frame_skip_count_transfer = 3;
1706 setup_display_mode();
1709 #elif defined(_FM77_VARIANTS)
1711 int oldmode = display_mode;
1712 kanjisub = ((data & 0x20) == 0) ? true : false;
1713 # if defined(_FM77L4)
1714 stat_400linecard = ((data & 0x10) != 0) ? true : false;
1715 mode400line = ((data & 0x08) != 0) ? false : true;
1716 if(mode400line && stat_400linecard) {
1717 display_mode = DISPLAY_MODE_8_400L_TEXT;
1718 } else if(stat_400linecard) {
1719 display_mode = DISPLAY_MODE_8_200L_TEXT;
1721 display_mode = DISPLAY_MODE_8_200L;
1724 setup_display_mode();
1728 #if defined(_FM77AV_VARIANTS)
1729 case SIG_DISPLAY_MODE320: // FD12 bit 6
1730 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1732 //printf("Wrote $FD12: %02x\n", data);
1733 int oldmode = display_mode;
1736 display_mode = DISPLAY_MODE_8_400L;
1737 } else if(mode256k) {
1738 display_mode = DISPLAY_MODE_256k;
1739 } else if(!(mode320) && !(mode256k)) {
1740 //display_mode = (mode400line) ? DISPLAY_MODE_8_400L : DISPLAY_MODE_8_200L;
1741 display_mode = DISPLAY_MODE_8_200L;
1743 display_mode = (mode256k) ? DISPLAY_MODE_256k : DISPLAY_MODE_4096;
1745 if(oldmode != display_mode) {
1747 if(mode320 || mode256k) {
1748 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1749 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1750 for(y = 0; y < 200; y++) {
1751 pp = emu->get_screen_buffer(y);
1752 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1755 for(y = 0; y < 400; y++) {
1756 pp = emu->get_screen_buffer(y);
1757 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1760 //emu->set_vm_screen_lines(200);
1761 } else { // 200 lines, 8 colors.
1762 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1763 int ymax = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
1765 emu->set_vm_screen_size(640, ymax, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1766 for(y = 0; y < ymax; y++) {
1767 pp = emu->get_screen_buffer(y);
1768 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1771 for(y = 0; y < 400; y++) {
1772 pp = emu->get_screen_buffer(y);
1773 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1776 //emu->set_vm_screen_lines(200);
1779 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
1780 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
1781 alu->write_signal(SIG_ALU_400LINE, 0x00, 0xff);
1782 setup_display_mode();
1783 //frame_skip_count = 3;
1786 # else /* FM77AV/20/20EX */
1789 if(oldflag != mode320) {
1792 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1793 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1794 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 320 * sizeof(scrntype_t));
1796 for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
1798 //emu->set_vm_screen_lines(200);
1800 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1801 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1802 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
1804 for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
1806 //emu->set_vm_screen_lines(200);
1809 display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1810 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
1811 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
1812 alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
1814 setup_display_mode();
1819 case SIG_DISPLAY_MULTIPAGE:
1820 set_multimode(data);
1822 case SIG_FM7_SUB_KEY_MASK:
1823 if(firq_mask == flag) {
1824 do_firq(!flag && key_firq_req);
1828 case SIG_FM7_SUB_KEY_FIRQ:
1829 do_firq(flag & !(firq_mask));
1830 key_firq_req = flag;
1832 case SIG_FM7_SUB_USE_CLR:
1834 clr_count = data & 0x03;
1845 * Vram accessing functions moved to vram.cpp .
1848 uint32_t DISPLAY::read_mmio(uint32_t addr)
1850 uint32_t retval = 0xff;
1852 if(addr < 0xd400) return 0xff;
1854 #if !defined(_FM77AV_VARIANTS)
1855 raddr = (addr - 0xd400) & 0x000f;
1856 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
1857 raddr = (addr - 0xd400) & 0x003f;
1858 #else // FM77AV40EX || FM77AV40SX
1859 raddr = (addr - 0xd400) & 0x00ff;
1862 case 0x00: // Read keyboard
1863 retval = (keyboard->read_data8(0x00) != 0) ? 0xff : 0x7f;
1865 case 0x01: // Read keyboard
1866 retval = keyboard->read_data8(0x01) & 0xff;
1868 case 0x02: // Acknowledge
1877 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1878 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
1880 if(!kanjisub) return 0xff;
1881 # if !defined(_FM77_VARIANTS)
1883 return (uint8_t)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1886 if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1889 if(!kanjisub) return 0xff;
1890 # if !defined(_FM77_VARIANTS)
1892 return (uint8_t)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1895 if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1902 retval = set_vramaccess();
1908 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
1910 #if defined(_FM77AV_VARIANTS)
1913 retval = alu->read_data8(ALU_CMDREG);
1916 retval = alu->read_data8(ALU_LOGICAL_COLOR);
1919 retval = alu->read_data8(ALU_WRITE_MASKREG);
1922 retval = alu->read_data8(ALU_CMP_STATUS_REG);
1925 retval = alu->read_data8(ALU_BANK_DISABLE);
1927 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1928 case 0x2f: // VRAM BANK
1929 retval = 0xfc | (vram_bank & 0x03);
1934 retval = get_miscreg();
1938 retval = keyboard->read_data8(0x31);
1941 retval = keyboard->read_data8(0x32);
1947 return (uint8_t)retval;
1950 uint32_t DISPLAY::read_vram_data8(uint32_t addr)
1954 uint32_t color = (addr >> 14) & 0x03;
1955 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1956 if(display_mode == DISPLAY_MODE_8_400L) {
1957 color = vram_bank & 0x03;
1958 if(color > 2) color = 0;
1960 color = (addr >> 14) & 0x03;
1964 //if((multimode_accessmask & (1 << color)) != 0) return 0xff;
1965 if(multimode_accessflags[color]) return 0xff;
1967 #if defined(_FM77AV_VARIANTS)
1968 if (active_page != 0) {
1969 offset = offset_point_bank1;
1971 offset = offset_point;
1974 offset = offset_point;
1976 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1977 if(vram_active_block != 0) offset = 0; // Don't scroll at BLOCK 1.
1979 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1980 if(display_mode == DISPLAY_MODE_8_400L) {
1982 uint32_t page_offset_alt = 0;
1983 if(addr >= 0x8000) return 0xff;
1984 color = vram_bank & 0x03;
1985 if(color > 2) color = 0;
1987 pagemod = 0x8000 * color;
1988 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1989 if(vram_active_block != 0) page_offset = 0x18000;
1991 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
1992 return gvram[vramaddr];
1995 uint32_t page_offset_alt;
1996 #if defined(_FM77AV40)
1998 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2000 page_offset_alt = 0; // right?
2003 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2005 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
2006 //page_mask = 0x1fff;
2007 //pagemod = addr & 0xe000;
2009 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2011 return gvram[vramaddr];
2013 #elif defined(_FM77AV_VARIANTS)
2015 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2016 return gvram[vramaddr];
2018 #elif defined(_FM77L4) //_FM77L4
2020 if(display_mode == DISPLAY_MODE_8_400L) {
2021 return (uint32_t)read_vram_l4_400l(addr, offset);
2023 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2024 return gvram[vramaddr];
2028 #else // Others (77/7/8)
2029 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2030 return gvram[vramaddr];
2034 void DISPLAY::write_dma_data8(uint32_t addr, uint32_t data)
2036 uint32_t raddr = (addr & 0xffff) >> 7;
2037 if(write_dma_func_table[raddr] != NULL) {
2038 (this->*write_dma_func_table[raddr])(addr, (uint8_t) data);
2042 void DISPLAY::write_vram_data8(uint32_t addr, uint8_t data)
2045 uint32_t color = (addr >> 14) & 0x03;
2049 #if defined(_FM77AV_VARIANTS)
2050 if (active_page != 0) {
2051 offset = offset_point_bank1;
2053 offset = offset_point;
2056 offset = offset_point;
2058 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2059 if(vram_active_block != 0) offset = 0; // Don't scroll at BLOCK 1.
2062 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2063 if(display_mode == DISPLAY_MODE_8_400L) {
2065 uint32_t page_offset_alt = 0;
2067 if(addr >= 0x8000) {
2070 color = vram_bank & 0x03;
2071 if(color > 2) color = 0;
2073 pagemod = 0x8000 * color;
2074 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2075 if(vram_active_block != 0) page_offset_alt = 0x18000;
2077 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2078 // Reduce data transfer.
2079 tdata = gvram[vramaddr];
2081 naddr = (addr & 0x7fff) >> 4;
2082 gvram[vramaddr] = data;
2083 vram_wrote_table[naddr] = true;
2085 } else if(display_mode == DISPLAY_MODE_256k) {
2086 uint32_t page_offset_alt;
2088 #if defined(_FM77AV40)
2090 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2092 page_offset_alt = 0; // right?
2095 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2097 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
2098 tdata = gvram[vramaddr];
2100 naddr = (addr & page_mask) >> 3;
2101 gvram[vramaddr] = data;
2102 vram_wrote_table[naddr] = true;
2105 } else if(display_mode == DISPLAY_MODE_4096) {
2107 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2108 tdata = gvram[vramaddr];
2110 naddr = (addr & page_mask) >> 3;
2111 gvram[vramaddr] = data;
2112 vram_wrote_table[naddr] = true;
2116 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2117 tdata = gvram[vramaddr];
2119 naddr = (addr & page_mask) >> 4;
2120 gvram[vramaddr] = data;
2121 vram_wrote_table[naddr] = true;
2124 #elif defined(_FM77AV_VARIANTS)
2125 if(display_mode == DISPLAY_MODE_4096) {
2127 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2128 tdata = gvram[vramaddr];
2130 naddr = (addr & page_mask) >> 3;
2131 gvram[vramaddr] = data;
2132 vram_wrote_table[naddr] = true;
2136 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2137 tdata = gvram[vramaddr];
2139 naddr = (addr & page_mask) >> 4;
2140 gvram[vramaddr] = data;
2141 vram_wrote_table[naddr] = true;
2144 #elif defined(_FM77L4) //_FM77L4
2147 if(display_mode == DISPLAY_MODE_8_400L) {
2148 write_vram_l4_400l(addr, data, offset);
2150 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2151 tdata = gvram[vramaddr];
2153 naddr = (addr & 0x3fff) >> 4;
2154 gvram[vramaddr] = data;
2155 vram_wrote_table[naddr] = true;
2159 #else // Others (77/7/8)
2162 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2163 tdata = gvram[vramaddr];
2165 naddr = (addr & 0x3fff) >> 4;
2166 gvram[vramaddr] = data;
2167 vram_wrote_table[naddr] = true;
2173 uint32_t DISPLAY::read_cpu_vram_data8(uint32_t addr)
2176 #if defined(_FM77AV_VARIANTS)
2178 alu->read_data8(addr);
2181 return read_vram_data8(addr);
2184 uint32_t DISPLAY::read_dma_vram_data8(uint32_t addr)
2186 return read_vram_data8(addr);
2189 void DISPLAY::init_read_table(void)
2192 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
2193 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cpu_vram_data8;
2194 read_dma_func_table[_at >> 7] = &DISPLAY::read_dma_vram_data8;
2196 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
2197 read_cpu_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2198 read_dma_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2200 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
2201 read_cpu_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2202 read_dma_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2204 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
2205 read_cpu_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2206 read_dma_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2208 #if defined(_FM77AV_VARIANTS)
2209 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
2210 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2211 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2213 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
2214 read_cpu_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2215 read_dma_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2218 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
2219 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2220 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2223 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
2224 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2225 read_dma_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2227 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
2228 read_cpu_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2229 read_dma_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2233 uint32_t DISPLAY::read_console_ram(uint32_t addr)
2235 uint32_t raddr = addr & 0xfff;
2236 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2238 if(console_ram_bank >= 1) {
2239 return submem_console_av40[((console_ram_bank - 1) << 12) + raddr];
2243 return console_ram[raddr];
2246 uint32_t DISPLAY::read_work_ram(uint32_t addr)
2248 addr = addr & 0x3ff;
2249 return work_ram[addr];
2253 uint32_t DISPLAY::read_shared_ram(uint32_t addr)
2255 addr = addr - 0xd380;
2256 return shared_ram[addr];
2259 #if defined(_FM77AV_VARIANTS)
2260 uint32_t DISPLAY::read_hidden_ram(uint32_t addr)
2262 if(addr >= 0xd500) {
2263 return submem_hidden[addr - 0xd500];
2268 uint32_t DISPLAY::read_cgrom(uint32_t addr)
2270 #if defined(_FM77AV_VARIANTS)
2271 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2273 return submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)]; //FIXME
2276 return subsys_cg[(addr - 0xd800) + cgrom_bank * 0x800];
2278 return subsys_c[addr - 0xd800];
2282 uint32_t DISPLAY::read_subsys_monitor(uint32_t addr)
2284 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2286 return subsys_ram[addr - 0xe000];
2289 #if defined(_FM77AV_VARIANTS)
2290 switch(subrom_bank_using & 3) {
2292 return subsys_c[addr - 0xd800];
2295 return subsys_a[addr - 0xe000];
2298 return subsys_b[addr - 0xe000];
2301 return subsys_cg[addr - 0xe000];
2305 return subsys_c[addr - 0xd800];
2309 uint32_t DISPLAY::read_dma_data8(uint32_t addr)
2311 uint32_t raddr = (addr & 0xffff) >> 7;
2312 if(read_dma_func_table[raddr] != NULL) {
2313 return (this->*read_dma_func_table[raddr])(addr);
2318 uint32_t DISPLAY::read_data8(uint32_t addr)
2320 uint32_t raddr = addr;
2322 if(addr < 0x10000) {
2323 raddr = (addr & 0xffff) >> 7;
2324 if(read_cpu_func_table[raddr] != NULL) {
2325 return (this->*read_cpu_func_table[raddr])(addr);
2330 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2331 return dpalette_data[addr - FM7_SUBMEM_OFFSET_DPALETTE];
2334 #if defined(_FM77AV_VARIANTS)
2336 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2337 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2338 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2339 if(vram_active_block != 0) {
2343 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2344 if(display_mode == DISPLAY_MODE_8_400L) {
2345 uint32_t page_offset_alt = 0;
2346 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2347 if(vram_active_block != 0) {
2348 page_offset_alt = 0x18000;
2353 color = (addr & 0x18000) >> 15;
2354 if(color > 2) color = 0;
2355 pagemod = 0x8000 * color;
2356 if (active_page != 0) {
2357 offset = offset_point_bank1 << 1;
2359 offset = offset_point << 1;
2361 return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset_alt];
2364 return read_vram_data8(addr);
2371 * Vram accessing functions moved to vram.cpp .
2374 void DISPLAY::write_mmio(uint32_t addr, uint8_t data)
2377 uint8_t active_block_old;
2379 if(addr < 0xd400) return;
2381 #if !defined(_FM77AV_VARIANTS)
2382 addr = (addr - 0xd400) & 0x000f;
2383 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2384 addr = (addr - 0xd400) & 0x003f;
2385 #else // FM77AV40EX || FM77AV40SX
2386 addr = (addr - 0xd400) & 0x00ff;
2388 io_w_latch[addr] = (uint8_t)data;
2390 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4)
2393 set_cyclesteal((uint8_t)data);
2396 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2397 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2400 if(!kanjisub) return;
2401 kanjiaddr.w.h = 0x0000;
2402 kanjiaddr.b.h = (uint8_t) data;
2405 if(!kanjisub) return;
2406 kanjiaddr.w.h = 0x0000;
2407 kanjiaddr.b.l = (uint8_t)data;
2420 if(clr_count <= 0) {
2422 } else { // Read once when using clr_foo() to set busy flag.
2425 usec = (1000.0 * 1000.0) / 2000000.0;
2427 usec = (1000.0 * 1000.0) / 999000.0;
2429 if(!(is_cyclesteal) && (vram_accessflag)) usec = usec * 3.0;
2430 usec = (double)clr_count * usec;
2431 register_event(this, EVENT_FM7SUB_CLR_BUSY, usec, false, NULL); // NEXT CYCLE_
2438 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
2443 rval = (uint8_t)data;
2444 if(offset_changed[active_page]) {
2445 #if defined(_FM77AV_VARIANTS)
2446 if(active_page != 0) {
2447 tmp_offset_point[active_page].d = offset_point_bank1;
2449 tmp_offset_point[active_page].d = offset_point;
2452 tmp_offset_point[active_page].d = offset_point;
2455 tmp_offset_point[active_page].w.h = 0x0000;
2457 tmp_offset_point[active_page].b.h = rval;
2459 tmp_offset_point[active_page].b.l = rval;
2461 offset_changed[active_page] = !offset_changed[active_page];
2462 if(offset_changed[active_page]) {
2464 #if defined(_FM77AV_VARIANTS)
2465 if(active_page != 0) {
2467 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fff;
2469 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fe0;
2473 offset_point = tmp_offset_point[active_page].d & 0x007fff;
2475 offset_point = tmp_offset_point[active_page].d & 0x007fe0;
2479 offset_point = tmp_offset_point[active_page].d & 0x7fe0;
2483 #if defined(_FM77AV_VARIANTS)
2486 alu_write_cmdreg(data);
2489 alu_write_logical_color(data);
2492 alu_write_mask_reg(data);
2495 alu_write_disable_reg(data);
2498 alu_write_offsetreg_hi(data);
2501 alu_write_offsetreg_lo(data);
2504 alu_write_linepattern_hi(data);
2507 alu_write_linepattern_lo(data);
2509 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2511 console_ram_bank = (data & 0x18) >> 3;
2512 if(console_ram_bank > 2) console_ram_bank = 0;
2513 cgram_bank = data & 0x07;
2514 kanji_level2 = ((data & 0x80) == 0) ? false : true;
2516 case 0x2f: // VRAM BANK
2517 vram_bank = data & 0x03;
2518 if(vram_bank > 2) vram_bank = 0;
2528 keyboard->write_data8(0x31, data);
2530 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2532 active_block_old = vram_active_block;
2533 vram_active_block = data & 0x01;
2534 if(vram_display_block != (((data & 0x10) != 0) ? 1 : 0)) vram_wrote = true;
2535 vram_display_block = ((data & 0x10) != 0) ? 1 : 0;
2536 if(vram_active_block != active_block_old) setup_display_mode();
2541 tmpvar.d = window_xbegin * 8;
2544 tmpvar.b.h = data & 0x03;
2546 tmpvar.b.l = data & 0xf8;
2548 if(mode320 || mode256k) {
2549 if(tmpvar.d > 320) tmpvar.d = 320;
2551 if(tmpvar.d > 640) tmpvar.d = 640;
2553 window_xbegin = tmpvar.d / 8;
2558 tmpvar.d = window_xend * 8;
2561 tmpvar.b.h = data & 0x03;
2563 tmpvar.b.l = data & 0xf8;
2565 if(mode320 || mode256k) {
2566 if(tmpvar.d > 320) tmpvar.d = 320;
2568 if(tmpvar.d > 640) tmpvar.d = 640;
2570 window_xend = tmpvar.d / 8;
2575 tmpvar.d = window_low;
2578 tmpvar.b.h = data & 0x03;
2580 tmpvar.b.l = data & 0xff;
2582 if(display_mode == DISPLAY_MODE_8_400L) {
2583 if(tmpvar.d > 400) tmpvar.d = 400;
2586 if(tmpvar.d > 400) tmpvar.d = 400;
2588 window_low = tmpvar.d;
2593 tmpvar.d = window_high;
2596 tmpvar.b.h = data & 0x03;
2598 tmpvar.b.l = data & 0xff;
2600 if(display_mode == DISPLAY_MODE_8_400L) {
2601 if(tmpvar.d > 400) tmpvar.d = 400;
2604 if(tmpvar.d > 400) tmpvar.d = 400;
2606 window_high = tmpvar.d;
2612 #if defined(_FM77AV_VARIANTS)
2614 if((addr >= 0x13) && (addr <= 0x1a)) {
2615 alu_write_cmpdata_reg(addr - 0x13, data);
2616 } else if((addr >= 0x1c) && (addr <= 0x1e)) {
2617 alu_write_tilepaint_data(addr, data);
2618 } else if((addr >= 0x24) && (addr <= 0x2b)) {
2619 alu_write_line_position(addr - 0x24, data);
2626 void DISPLAY::init_write_table(void)
2629 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
2630 write_cpu_func_table[_at >> 7] = &DISPLAY::write_cpu_vram_data8;
2631 write_dma_func_table[_at >> 7] = &DISPLAY::write_dma_vram_data8;
2633 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
2634 write_cpu_func_table[_at >> 7] = &DISPLAY::write_console_ram;
2635 write_dma_func_table[_at >> 7] = &DISPLAY::write_console_ram;
2637 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
2638 write_cpu_func_table[_at >> 7] = &DISPLAY::write_work_ram;
2639 write_dma_func_table[_at >> 7] = &DISPLAY::write_work_ram;
2641 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
2642 write_cpu_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
2643 write_dma_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
2645 #if defined(_FM77AV_VARIANTS)
2646 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
2647 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
2648 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
2650 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
2651 write_cpu_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
2652 write_dma_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
2655 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
2656 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
2657 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
2660 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2661 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
2662 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
2663 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
2665 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
2666 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
2667 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
2670 for(_at = 0xd800; _at < 0x10000; _at += 0x80) {
2671 write_cpu_func_table[_at >> 7] = &DISPLAY::write_dummy;
2672 write_dma_func_table[_at >> 7] = &DISPLAY::write_dummy;
2677 void DISPLAY::write_console_ram(uint32_t addr, uint8_t data)
2679 uint32_t raddr = addr & 0xfff;
2680 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2682 if(console_ram_bank >= 1) {
2683 submem_console_av40[((console_ram_bank - 1) << 12) + raddr] = data;
2688 console_ram[raddr] = data;
2692 void DISPLAY::write_work_ram(uint32_t addr, uint8_t data)
2694 uint32_t raddr = addr & 0xfff;
2695 work_ram[raddr] = data;
2699 void DISPLAY::write_shared_ram(uint32_t addr, uint8_t data)
2701 uint32_t raddr = addr & 0x7f;
2702 shared_ram[raddr] = data;
2706 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2707 void DISPLAY::write_subsys_cgram(uint32_t addr, uint8_t data)
2709 uint32_t raddr = addr - 0xd800;
2710 if(ram_protect) return;
2711 if(!monitor_ram) return;
2712 submem_cgram[cgram_bank * 0x0800 + raddr] = data; //FIXME
2715 void DISPLAY::write_subsys_ram(uint32_t addr, uint8_t data)
2717 if(ram_protect) return;
2718 if(!monitor_ram) return;
2719 subsys_ram[addr - 0xe000] = data; //FIXME
2723 #if defined(_FM77AV_VARIANTS)
2724 void DISPLAY::write_hidden_ram(uint32_t addr, uint8_t data)
2726 submem_hidden[addr - 0xd500] = data;
2731 void DISPLAY::write_cpu_vram_data8(uint32_t addr, uint8_t data)
2733 uint32_t color = (addr & 0xc000) >> 14;
2734 #if defined(_FM77AV_VARIANTS)
2736 alu->read_data8(addr);
2740 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2741 if(display_mode == DISPLAY_MODE_8_400L) {
2742 color = vram_bank & 0x03;
2743 if(color > 2) color = 0;
2747 //if((multimode_accessmask & (1 << color)) != 0) return;
2748 if(multimode_accessflags[color]) return;
2750 write_vram_data8(addr & 0xffff, data);
2753 void DISPLAY::write_dma_vram_data8(uint32_t addr, uint8_t data)
2755 uint32_t color = (addr & 0xc000) >> 14;
2756 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2757 if(display_mode == DISPLAY_MODE_8_400L) {
2758 color = vram_bank & 0x03;
2759 if(color > 2) color = 0;
2763 //if((multimode_accessmask & (1 << color)) != 0) return;
2764 if(multimode_accessflags[color]) return;
2766 write_vram_data8(addr & 0xffff, data);
2769 void DISPLAY::write_dummy(uint32_t addr, uint8_t data)
2773 void DISPLAY::write_data8(uint32_t addr, uint32_t data)
2777 //uint32_t page_offset = 0x0000;
2778 uint8_t val8 = data & 0xff;
2779 uint32_t color = (addr & 0xc000) >> 14;
2782 if(addr < 0x10000) {
2783 void (*_write_func)(uint32_t, uint32_t);
2784 raddr = (addr & 0xffff) >> 7;
2785 if(write_cpu_func_table[raddr] != NULL) {
2786 (this->*write_cpu_func_table[raddr])(addr, (uint8_t)data);
2792 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2793 set_dpalette(addr - FM7_SUBMEM_OFFSET_DPALETTE, val8);
2797 #if defined(_FM77AV_VARIANTS)
2799 else if(addr == FM7_SUBMEM_OFFSET_APALETTE_R) {
2800 set_apalette_r(val8);
2802 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_G) {
2803 set_apalette_g(val8);
2805 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_B) {
2806 set_apalette_b(val8);
2808 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_HI) {
2809 set_apalette_index_hi(val8);
2811 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_LO) {
2812 set_apalette_index_lo(val8);
2816 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2817 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2818 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2819 if(vram_active_block != 0) {
2823 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2824 if(display_mode == DISPLAY_MODE_8_400L) {
2827 uint32_t page_offset_alt = 0;
2829 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2830 if(vram_active_block != 0) page_offset_alt = 0x18000;
2832 color = (addr & 0x18000) >> 15;
2833 if(color > 2) color = 0;
2834 if (active_page != 0) {
2835 offset = offset_point_bank1 << 1;
2837 offset = offset_point << 1;
2839 naddr = (addr & 0x7fff) >> 4;
2840 pagemod = 0x8000 * color;
2841 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2842 tdata = gvram[vramaddr];
2843 if(tdata != (uint8_t)data) {
2844 gvram[vramaddr] = data;
2845 vram_wrote_table[naddr] = true;
2849 write_vram_data8(addr, data);
2851 write_vram_data8(addr, data);
2853 //if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
2860 uint32_t DISPLAY::read_bios(const _TCHAR *name, uint8_t *ptr, uint32_t size)
2866 if((name == NULL) || (ptr == NULL)) return 0;
2867 s = create_local_path(name);
2868 if(s == NULL) return 0;
2870 if(!fio.Fopen(s, FILEIO_READ_BINARY)) return 0;
2871 blocks = fio.Fread(ptr, size, 1);
2874 return blocks * size;
2878 void DISPLAY::initialize()
2882 memset(io_w_latch, 0xff, sizeof(io_w_latch));
2883 screen_update_flag = true;
2884 memset(gvram, 0x00, sizeof(gvram));
2885 vram_wrote_shadow = false;
2886 memset(gvram_shadow, 0x00, sizeof(gvram_shadow));
2887 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
2888 for(i = 0; i < 411; i++) vram_draw_table[i] = false;
2890 memset(console_ram, 0x00, sizeof(console_ram));
2891 memset(work_ram, 0x00, sizeof(work_ram));
2892 memset(shared_ram, 0x00, sizeof(shared_ram));
2893 memset(subsys_c, 0xff, sizeof(subsys_c));
2894 need_transfer_line = true;
2895 frame_skip_count_draw = 3;
2896 frame_skip_count_transfer = 3;
2898 diag_load_subrom_c = false;
2900 if(read_bios(_T(ROM_FM8_SUBSYSTEM), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2901 this->out_debug_log(_T("SUBSYSTEM ROM READING : %s"), diag_load_subrom_c ? "OK" : "NG");
2903 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_C), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2904 this->out_debug_log(_T("SUBSYSTEM ROM Type C READING : %s"), diag_load_subrom_c ? "OK" : "NG");
2906 #if defined(_FM77AV_VARIANTS)
2907 memset(subsys_a, 0xff, sizeof(subsys_a));
2908 memset(subsys_b, 0xff, sizeof(subsys_b));
2909 memset(subsys_cg, 0xff, sizeof(subsys_cg));
2910 memset(submem_hidden, 0x00, sizeof(submem_hidden));
2912 diag_load_subrom_a = false;
2913 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_A), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
2914 this->out_debug_log(_T("SUBSYSTEM ROM Type A READING : %s"), diag_load_subrom_a ? "OK" : "NG");
2916 diag_load_subrom_b = false;
2917 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_B), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
2918 this->out_debug_log(_T("SUBSYSTEM ROM Type B READING : %s"), diag_load_subrom_b ? "OK" : "NG");
2920 diag_load_subrom_cg = false;
2921 if(read_bios(_T(ROM_FM7_SUBSYSTEM_CG), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
2922 this->out_debug_log(_T("SUBSYSTEM CG ROM READING : %s"), diag_load_subrom_cg ? "OK" : "NG");
2923 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2924 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2925 memset(subsys_ram, 0x00, sizeof(subsys_ram));
2926 memset(submem_cgram, 0x00, sizeof(submem_cgram));
2927 memset(submem_console_av40, 0x00, sizeof(submem_console_av40));
2934 #if defined(_FM77AV_VARIANTS)
2936 apalette_index.d = 0;
2937 for(i = 0; i < 4096; i++) {
2938 analog_palette_r[i] = i & 0x0f0;
2939 analog_palette_g[i] = (i & 0xf00) >> 4;
2940 analog_palette_b[i] = (i & 0x00f) << 4;
2944 #if defined(_FM77AV_VARIANTS)
2945 hblank_event_id = -1;
2946 hdisp_event_id = -1;
2947 vsync_event_id = -1;
2948 vstart_event_id = -1;
2955 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
2956 is_cyclesteal = true;
2958 is_cyclesteal = false;
2960 multimode_accessmask = multimode_dispmask = 0;
2961 for(i = 0; i < 4; i++) {
2962 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
2963 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
2966 prev_clock = SUBCLOCK_NORMAL;
2970 key_firq_req = false; //firq_mask = true;
2971 frame_skip_count_transfer = 3;
2972 frame_skip_count_draw = 3;
2973 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2974 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2976 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2978 emu->set_vm_screen_lines(200);
2979 #if defined(_FM77AV40SX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2980 mode400line = false;
2982 #elif defined(_FM77L4)
2983 mode400line = false;
2986 palette_changed = true;
2987 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
2988 register_vline_event(this);
2989 register_frame_event(this);
2991 setup_display_mode();
2994 void DISPLAY::release()
2998 #define STATE_VERSION 8
2999 void DISPLAY::save_state(FILEIO *state_fio)
3001 state_fio->FputUint32_BE(STATE_VERSION);
3002 state_fio->FputInt32_BE(this_device_id);
3003 this->out_debug_log(_T("Save State: DISPLAY : id=%d ver=%d\n"), this_device_id, STATE_VERSION);
3007 state_fio->FputInt32_BE(clr_count);
3008 state_fio->FputBool(halt_flag);
3009 state_fio->FputInt32_BE(active_page);
3010 state_fio->FputBool(sub_busy);
3011 state_fio->FputBool(crt_flag);
3012 state_fio->FputBool(vram_wrote);
3013 state_fio->FputBool(is_cyclesteal);
3015 state_fio->FputBool(clock_fast);
3017 #if defined(_FM77AV_VARIANTS)
3018 state_fio->FputBool(subcpu_resetreq);
3019 state_fio->FputBool(power_on_reset);
3021 state_fio->FputBool(cancel_request);
3022 state_fio->FputBool(key_firq_req);
3024 state_fio->FputInt32_BE(display_mode);
3025 state_fio->FputUint32_BE(prev_clock);
3028 state_fio->Fwrite(dpalette_data, sizeof(dpalette_data), 1);
3029 state_fio->FputUint8(multimode_accessmask);
3030 state_fio->FputUint8(multimode_dispmask);
3032 state_fio->FputUint32_BE(offset_point);
3033 #if defined(_FM77AV_VARIANTS)
3034 state_fio->FputUint32_BE(offset_point_bank1);
3036 for(i = 0; i < 2; i++) {
3037 state_fio->FputUint32_BE(tmp_offset_point[i].d);
3038 state_fio->FputBool(offset_changed[i]);
3040 state_fio->FputBool(offset_77av);
3041 state_fio->FputBool(diag_load_subrom_c);
3044 state_fio->Fwrite(io_w_latch, sizeof(io_w_latch), 1);
3045 state_fio->Fwrite(console_ram, sizeof(console_ram), 1);
3046 state_fio->Fwrite(work_ram, sizeof(work_ram), 1);
3047 state_fio->Fwrite(shared_ram, sizeof(shared_ram), 1);
3048 state_fio->Fwrite(subsys_c, sizeof(subsys_c), 1);
3049 state_fio->Fwrite(gvram, sizeof(gvram), 1);
3050 state_fio->Fwrite(gvram_shadow, sizeof(gvram_shadow), 1);
3052 #if defined(_FM77_VARIANTS)
3053 state_fio->FputBool(kanjisub);
3054 state_fio->FputUint16_BE(kanjiaddr.w.l);
3055 # if defined(_FM77L4)
3056 state_fio->FputBool(mode400line);
3057 state_fio->FputBool(stat_400linecard);
3059 #elif defined(_FM77AV_VARIANTS)
3060 state_fio->FputBool(kanjisub);
3061 state_fio->FputUint16_BE(kanjiaddr.w.l);
3063 state_fio->FputBool(vblank);
3064 state_fio->FputBool(vsync);
3065 state_fio->FputBool(hblank);
3066 state_fio->FputInt32_BE(vblank_count);
3068 state_fio->FputBool(mode320);
3069 state_fio->FputInt8(display_page);
3070 state_fio->FputInt8(display_page_bak);
3071 state_fio->FputInt32_BE(cgrom_bank);
3072 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3073 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3074 state_fio->FputInt32_BE(vram_bank);
3077 state_fio->FputUint32_BE(displine);
3078 state_fio->FputUint8(subrom_bank);
3079 state_fio->FputUint8(subrom_bank_using);
3081 state_fio->FputBool(nmi_enable);
3082 state_fio->FputBool(use_alu);
3084 state_fio->FputUint8(apalette_index.b.l);
3085 state_fio->FputUint8(apalette_index.b.h);
3086 state_fio->Fwrite(analog_palette_r, sizeof(analog_palette_r), 1);
3087 state_fio->Fwrite(analog_palette_g, sizeof(analog_palette_g), 1);
3088 state_fio->Fwrite(analog_palette_b, sizeof(analog_palette_b), 1);
3091 state_fio->FputBool(diag_load_subrom_a);
3092 state_fio->FputBool(diag_load_subrom_b);
3093 state_fio->FputBool(diag_load_subrom_cg);
3095 state_fio->Fwrite(subsys_a, sizeof(subsys_a), 1);
3096 state_fio->Fwrite(subsys_b, sizeof(subsys_b), 1);
3097 state_fio->Fwrite(subsys_cg, sizeof(subsys_cg), 1);
3098 state_fio->Fwrite(submem_hidden, sizeof(submem_hidden), 1);
3099 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3100 state_fio->FputBool(mode400line);
3101 state_fio->FputBool(mode256k);
3103 state_fio->FputBool(monitor_ram);
3104 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3105 state_fio->FputUint16_BE(window_low);
3106 state_fio->FputUint16_BE(window_high);
3107 state_fio->FputUint16_BE(window_xbegin);
3108 state_fio->FputUint16_BE(window_xend);
3109 state_fio->FputBool(window_opened);
3111 state_fio->FputBool(kanji_level2);
3113 state_fio->FputUint8(vram_active_block);
3114 state_fio->FputUint8(vram_display_block);
3115 state_fio->FputUint8(console_ram_bank);
3116 state_fio->FputBool(ram_protect);
3118 state_fio->FputUint32_BE(cgram_bank);
3119 state_fio->Fwrite(subsys_ram, sizeof(subsys_ram), 1);
3120 state_fio->Fwrite(submem_cgram, sizeof(submem_cgram), 1);
3121 state_fio->Fwrite(submem_console_av40, sizeof(submem_console_av40), 1);
3127 state_fio->FputInt32_BE(nmi_event_id);
3128 #if defined(_FM77AV_VARIANTS)
3129 state_fio->FputInt32_BE(hblank_event_id);
3130 state_fio->FputInt32_BE(hdisp_event_id);
3131 state_fio->FputInt32_BE(vsync_event_id);
3132 state_fio->FputInt32_BE(vstart_event_id);
3134 state_fio->FputBool(firq_mask);
3135 state_fio->FputBool(vram_accessflag);
3139 bool DISPLAY::load_state(FILEIO *state_fio)
3142 uint32_t version = state_fio->FgetUint32_BE();
3143 if(this_device_id != state_fio->FgetInt32_BE()) {
3146 this->out_debug_log(_T("Load State: DISPLAY : id=%d ver=%d\n"), this_device_id, version);
3151 clr_count = state_fio->FgetInt32_BE();
3152 halt_flag = state_fio->FgetBool();
3153 active_page = state_fio->FgetInt32_BE();
3154 sub_busy = state_fio->FgetBool();
3155 crt_flag = state_fio->FgetBool();
3156 vram_wrote = state_fio->FgetBool();
3157 crt_flag_bak = true;
3158 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
3159 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
3160 is_cyclesteal = state_fio->FgetBool();
3162 clock_fast = state_fio->FgetBool();
3164 #if defined(_FM77AV_VARIANTS)
3165 subcpu_resetreq = state_fio->FgetBool();
3166 power_on_reset = state_fio->FgetBool();
3168 cancel_request = state_fio->FgetBool();
3169 key_firq_req = state_fio->FgetBool();
3171 display_mode = state_fio->FgetInt32_BE();
3172 prev_clock = state_fio->FgetUint32_BE();
3175 for(addr = 0; addr < 8; addr++) set_dpalette(addr, addr);
3177 state_fio->Fread(dpalette_data, sizeof(dpalette_data), 1);
3178 for(addr = 0; addr < 8; addr++) set_dpalette(addr, dpalette_data[addr]);
3179 multimode_accessmask = state_fio->FgetUint8();
3180 multimode_dispmask = state_fio->FgetUint8();
3181 for(i = 0; i < 4; i++) {
3182 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
3183 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
3186 offset_point = state_fio->FgetUint32_BE();
3187 #if defined(_FM77AV_VARIANTS)
3188 offset_point_bank1 = state_fio->FgetUint32_BE();
3190 for(i = 0; i < 2; i++) {
3191 tmp_offset_point[i].d = state_fio->FgetUint32_BE();
3192 offset_changed[i] = state_fio->FgetBool();
3194 offset_77av = state_fio->FgetBool();
3195 diag_load_subrom_c = state_fio->FgetBool();
3197 state_fio->Fread(io_w_latch, sizeof(io_w_latch), 1);
3198 state_fio->Fread(console_ram, sizeof(console_ram), 1);
3199 state_fio->Fread(work_ram, sizeof(work_ram), 1);
3200 state_fio->Fread(shared_ram, sizeof(shared_ram), 1);
3201 state_fio->Fread(subsys_c, sizeof(subsys_c), 1);
3202 state_fio->Fread(gvram, sizeof(gvram), 1);
3203 state_fio->Fread(gvram_shadow, sizeof(gvram_shadow), 1);
3204 #if defined(_FM77_VARIANTS)
3205 kanjisub = state_fio->FgetBool();
3207 kanjiaddr.w.l = state_fio->FgetUint16_BE();
3208 # if defined(_FM77L4)
3209 mode400line = state_fio->FgetBool();
3210 stat_400linecard = state_fio->FgetBool();
3212 #elif defined(_FM77AV_VARIANTS)
3213 kanjisub = state_fio->FgetBool();
3215 kanjiaddr.w.l = state_fio->FgetUint16_BE();
3217 vblank = state_fio->FgetBool();
3218 vsync = state_fio->FgetBool();
3219 hblank = state_fio->FgetBool();
3220 vblank_count = state_fio->FgetInt32_BE();
3222 mode320 = state_fio->FgetBool();
3223 display_page = state_fio->FgetInt8();
3224 display_page_bak = state_fio->FgetInt8();
3225 cgrom_bank = state_fio->FgetInt32_BE();
3226 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3227 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3228 vram_bank = state_fio->FgetInt32_BE();
3230 screen_update_flag = true;
3231 displine = state_fio->FgetUint32_BE();
3232 subrom_bank = state_fio->FgetUint8();
3233 subrom_bank_using = state_fio->FgetUint8();
3235 nmi_enable = state_fio->FgetBool();
3236 use_alu = state_fio->FgetBool();
3238 apalette_index.b.l = state_fio->FgetUint8();
3239 apalette_index.b.h = state_fio->FgetUint8();
3241 state_fio->Fread(analog_palette_r, sizeof(analog_palette_r), 1);
3242 state_fio->Fread(analog_palette_g, sizeof(analog_palette_g), 1);
3243 state_fio->Fread(analog_palette_b, sizeof(analog_palette_b), 1);
3244 for(i = 0; i < 4096; i++) calc_apalette(i);
3246 diag_load_subrom_a = state_fio->FgetBool();
3247 diag_load_subrom_b = state_fio->FgetBool();
3248 diag_load_subrom_cg = state_fio->FgetBool();
3250 state_fio->Fread(subsys_a, sizeof(subsys_a), 1);
3251 state_fio->Fread(subsys_b, sizeof(subsys_b), 1);
3252 state_fio->Fread(subsys_cg, sizeof(subsys_cg), 1);
3253 state_fio->Fread(submem_hidden, sizeof(submem_hidden), 1);
3255 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3256 mode400line = state_fio->FgetBool();
3257 mode256k = state_fio->FgetBool();
3259 monitor_ram = state_fio->FgetBool();
3260 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3261 window_low = state_fio->FgetUint16_BE();
3262 window_high = state_fio->FgetUint16_BE();
3263 window_xbegin = state_fio->FgetUint16_BE();
3264 window_xend = state_fio->FgetUint16_BE();
3265 window_opened = state_fio->FgetBool();
3267 kanji_level2 = state_fio->FgetBool();
3269 vram_active_block = state_fio->FgetUint8();
3270 vram_display_block = state_fio->FgetUint8();
3271 console_ram_bank = state_fio->FgetUint8();
3272 ram_protect = state_fio->FgetBool();
3274 cgram_bank = state_fio->FgetUint32_BE();
3275 state_fio->Fread(subsys_ram, sizeof(subsys_ram), 1);
3276 state_fio->Fread(submem_cgram, sizeof(submem_cgram), 1);
3277 state_fio->Fread(submem_console_av40, sizeof(submem_console_av40), 1);
3280 palette_changed = true;
3281 vram_wrote_shadow = true; // Force Draw
3282 this->draw_screen();
3283 if(version == 1) return true;
3285 if(version >= 2) { //V2
3286 nmi_event_id = state_fio->FgetInt32_BE();
3287 #if defined(_FM77AV_VARIANTS)
3288 hblank_event_id = state_fio->FgetInt32_BE();
3289 hdisp_event_id = state_fio->FgetInt32_BE();
3290 vsync_event_id = state_fio->FgetInt32_BE();
3291 vstart_event_id = state_fio->FgetInt32_BE();
3293 firq_mask = state_fio->FgetBool();
3294 vram_accessflag = state_fio->FgetBool();
3295 frame_skip_count_draw = 3;
3296 frame_skip_count_transfer = 3;
3297 need_transfer_line = true;
3299 if(version == STATE_VERSION) return true;
3300 setup_display_mode();