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 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
80 switch(config.cpu_type){
89 prev_clock = SUBCLOCK_NORMAL;
91 prev_clock = SUBCLOCK_SLOW;
96 for(i = 0; i < 2; i++) {
97 offset_changed[i] = true;
98 tmp_offset_point[i].d = 0;
101 vram_wrote_shadow = true;
102 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
103 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
107 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
114 if(hblank_event_id >= 0) cancel_event(this, hblank_event_id);
115 if(hdisp_event_id >= 0) cancel_event(this, hdisp_event_id);
117 if(vsync_event_id >= 0) cancel_event(this, vsync_event_id);
118 if(vstart_event_id >= 0) cancel_event(this, vstart_event_id);
119 hblank_event_id = -1;
122 vstart_event_id = -1;
124 if(display_mode == DISPLAY_MODE_8_400L) {
125 usec = 0.33 * 1000.0;
126 p_vm->set_vm_frame_rate(55.40);
128 usec = 0.51 * 1000.0;
129 p_vm->set_vm_frame_rate(FRAMES_PER_SEC);
132 //register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
133 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
134 mainio->write_signal(SIG_DISPLAY_VSYNC, 0xff, 0xff);
137 display_page_bak = 0;
139 #if defined(_FM77AV_VARIANTS)
141 offset_point_bank1 = 0;
143 subcpu_resetreq = false;
144 subrom_bank_using = subrom_bank;
149 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
151 vram_display_block = 0;
152 vram_active_block = 0;
154 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
159 window_opened = false;
164 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
165 alu->write_signal(SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
166 alu->write_signal(SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400: 200, 0xffff);
167 alu->write_signal(SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xffffffff : 0, 0xffffffff);
169 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
170 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
171 alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
173 alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
174 alu->write_signal(SIG_ALU_PLANES, 3, 3);
176 for(i = 0; i < 8; i++) set_dpalette(i, i);
177 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
178 //do_firq(!firq_mask && key_firq_req);
180 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
181 //kanjisub = false; // Fixed by Ryu takegami
182 kanjiaddr.d = 0x00000000;
183 # if defined(_FM77L4)
185 stat_400linecard = false;
190 frame_skip_count_draw = 3;
191 frame_skip_count_transfer = 3;
192 need_transfer_line = true;
193 setup_display_mode();
198 void DISPLAY::reset()
203 vram_accessflag = true;
204 display_mode = DISPLAY_MODE_8_200L;
206 crt_flag = false; // Fixed by Ryu Takegami
207 screen_update_flag = true;
208 crt_flag_bak = false;
210 cancel_request = false;
211 #if defined(_FM77AV_VARIANTS)
213 apalette_index.d = 0;
214 for(i = 0; i < 4096; i++) {
215 analog_palette_r[i] = i & 0x0f0;
216 analog_palette_g[i] = (i & 0xf00) >> 4;
217 analog_palette_b[i] = (i & 0x00f) << 4;
219 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
223 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
230 #elif defined(_FM77L4)
234 #if !defined(FIXED_FRAMEBUFFER_SIZE)
235 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
237 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
239 emu->set_vm_screen_lines(200);
241 reset_some_devices();
243 #if defined(_FM77AV_VARIANTS)
244 power_on_reset = false;
245 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
249 for(i = 0; i < 8; i++) set_dpalette(i, i);
252 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
255 if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
256 register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
259 key_firq_req = false;
264 void DISPLAY::reset_subcpu(bool _check_firq)
266 subcpu->write_signal(SIG_CPU_HALTREQ, 0, 1);
267 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
270 do_firq(!firq_mask && key_firq_req);
273 void DISPLAY::setup_display_mode(void)
275 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
276 if(display_mode == DISPLAY_MODE_8_400L) {
277 page_offset = 0x0000;
278 pagemod_mask = 0x18000;
280 } else if(display_mode == DISPLAY_MODE_256k) {
281 if(active_page != 0) {
282 page_offset = 0xc000;
284 page_offset = 0x0000;
286 pagemod_mask = 0xe000;
288 } else if(display_mode == DISPLAY_MODE_4096) {
289 if(active_page != 0) {
290 page_offset = 0xc000;
292 page_offset = 0x0000;
294 pagemod_mask = 0xe000;
297 if(active_page != 0) {
298 page_offset = 0xc000;
300 page_offset = 0x0000;
302 pagemod_mask = 0xc000;
305 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
306 if(vram_active_block != 0) page_offset += 0x18000;
308 #elif defined(_FM77AV_VARIANTS)
311 pagemod_mask = 0xe000;
312 } else { // 640x200, 8colors
314 pagemod_mask = 0xc000;
316 if(active_page != 0) {
317 page_offset = 0xc000;
319 page_offset = 0x0000;
321 #elif defined(_FM77L4)
322 if(display_mode == DISPLAY_MODE_8_400L) {
324 pagemod_mask = 0xe000;
325 } else { // 640x200, 8colors
327 pagemod_mask = 0xc000;
329 page_offset = 0x0000;
331 page_offset = 0x0000;
332 pagemod_mask = 0xc000;
336 void DISPLAY::update_config()
340 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
346 * Vram accessing functions moved to vram.cpp .
349 void DISPLAY::do_irq(bool flag)
351 subcpu->write_signal(SIG_CPU_IRQ, flag ? 1: 0, 1);
354 void DISPLAY::do_firq(bool flag)
356 subcpu->write_signal(SIG_CPU_FIRQ, flag ? 1: 0, 1);
359 void DISPLAY::do_nmi(bool flag)
361 #if defined(_FM77AV_VARIANTS)
362 if(!nmi_enable) flag = false;
364 subcpu->write_signal(SIG_CPU_NMI, flag ? 1 : 0, 1);
367 void DISPLAY::set_multimode(uint8_t val)
370 multimode_accessmask = val & 0x07;
371 multimode_dispmask = (val & 0x70) >> 4;
372 for(int i = 0; i < 4; i++) {
373 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
374 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
377 # if defined(_FM77AV_VARIANTS)
378 alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
383 uint8_t DISPLAY::get_multimode(void)
389 val = multimode_accessmask & 0x07;
390 val |= ((multimode_dispmask << 4) & 0x70);
396 uint8_t DISPLAY::get_cpuaccessmask(void)
398 return multimode_accessmask & 0x07;
401 void DISPLAY::set_dpalette(uint32_t addr, uint8_t val)
405 dpalette_data[addr] = val | 0xf8; //0b11111000;
406 b = ((val & 0x01) != 0x00)? 255 : 0x00;
407 r = ((val & 0x02) != 0x00)? 255 : 0x00;
408 g = ((val & 0x04) != 0x00)? 255 : 0x00;
410 dpalette_pixel_tmp[addr] = RGB_COLOR(r, g, b);
411 palette_changed = true;
414 uint8_t DISPLAY::get_dpalette(uint32_t addr)
422 data = dpalette_data[addr];
427 void DISPLAY::halt_subcpu(void)
429 //subcpu->write_signal(SIG_CPU_BUSREQ, 0x01, 0x01);
430 subcpu->write_signal(SIG_CPU_HALTREQ, 0x01, 0x01);
433 void DISPLAY::go_subcpu(void)
435 subcpu->write_signal(SIG_CPU_HALTREQ, 0x00, 0x01);
438 void DISPLAY::enter_display(void)
443 subclock = SUBCLOCK_NORMAL;
445 subclock = SUBCLOCK_SLOW;
447 if(!(is_cyclesteal) && (vram_accessflag)) {
448 subclock = subclock / 3;
450 if(prev_clock != subclock) {
451 p_vm->set_cpu_clock(subcpu, subclock);
453 prev_clock = subclock;
457 void DISPLAY::leave_display(void)
461 void DISPLAY::halt_subsystem(void)
467 void DISPLAY::restart_subsystem(void)
470 #if defined(_FM77AV_VARIANTS)
471 if(subcpu_resetreq) {
472 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
473 reset_some_devices();
474 power_on_reset = true;
482 void DISPLAY::set_crtflag(void)
489 void DISPLAY::reset_crtflag(void)
496 uint8_t DISPLAY::acknowledge_irq(void)
498 cancel_request = false;
504 uint8_t DISPLAY::beep(void)
506 mainio->write_signal(FM7_MAINIO_BEEP, 0x01, 0x01);
507 return 0xff; // True?
512 uint8_t DISPLAY::attention_irq(void)
514 mainio->write_signal(FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
519 void DISPLAY::set_cyclesteal(uint8_t val)
522 # if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
526 is_cyclesteal = true;
528 is_cyclesteal = false;
536 uint8_t DISPLAY::set_vramaccess(void)
538 vram_accessflag = true;
544 void DISPLAY::reset_vramaccess(void)
546 vram_accessflag = false;
551 uint8_t DISPLAY::reset_subbusy(void)
558 void DISPLAY::set_subbusy(void)
564 #if defined(_FM77AV_VARIANTS)
566 void DISPLAY::alu_write_cmdreg(uint32_t val)
568 alu->write_data8(ALU_CMDREG, val);
569 if((val & 0x80) != 0) {
577 void DISPLAY::alu_write_logical_color(uint8_t val)
579 uint32_t data = (uint32_t)val;
580 alu->write_data8(ALU_LOGICAL_COLOR, data);
584 void DISPLAY::alu_write_mask_reg(uint8_t val)
586 uint32_t data = (uint32_t)val;
587 alu->write_data8(ALU_WRITE_MASKREG, data);
591 void DISPLAY::alu_write_cmpdata_reg(int addr, uint8_t val)
593 uint32_t data = (uint32_t)val;
595 alu->write_data8(ALU_CMPDATA_REG + addr, data);
599 void DISPLAY::alu_write_disable_reg(uint8_t val)
601 uint32_t data = (uint32_t)val;
602 alu->write_data8(ALU_BANK_DISABLE, data);
606 void DISPLAY::alu_write_tilepaint_data(uint32_t addr, uint8_t val)
608 uint32_t data = (uint32_t)val;
611 alu->write_data8(ALU_TILEPAINT_B, data);
614 alu->write_data8(ALU_TILEPAINT_R, data);
617 alu->write_data8(ALU_TILEPAINT_G, data);
620 //alu->write_data8(ALU_TILEPAINT_L, 0xff);
626 void DISPLAY::alu_write_offsetreg_hi(uint8_t val)
628 alu->write_data8(ALU_OFFSET_REG_HIGH, val & 0x7f);
632 void DISPLAY::alu_write_offsetreg_lo(uint8_t val)
634 alu->write_data8(ALU_OFFSET_REG_LO, val);
638 void DISPLAY::alu_write_linepattern_hi(uint8_t val)
640 alu->write_data8(ALU_LINEPATTERN_REG_HIGH, val);
644 void DISPLAY::alu_write_linepattern_lo(uint8_t val)
646 alu->write_data8(ALU_LINEPATTERN_REG_LO, val);
650 void DISPLAY::alu_write_line_position(int addr, uint8_t val)
652 uint32_t data = (uint32_t)val;
655 alu->write_data8(ALU_LINEPOS_START_X_HIGH, data & 0x03);
658 alu->write_data8(ALU_LINEPOS_START_X_LOW, data);
661 alu->write_data8(ALU_LINEPOS_START_Y_HIGH, data & 0x01);
664 alu->write_data8(ALU_LINEPOS_START_Y_LOW, data);
667 alu->write_data8(ALU_LINEPOS_END_X_HIGH, data & 0x03);
670 alu->write_data8(ALU_LINEPOS_END_X_LOW, data);
673 alu->write_data8(ALU_LINEPOS_END_Y_HIGH, data & 0x01);
676 alu->write_data8(ALU_LINEPOS_END_Y_LOW, data);
682 uint8_t DISPLAY::get_miscreg(void)
687 if(!hblank) ret |= 0x80;
688 if(vsync) ret |= 0x04;
689 if(alu->read_signal(SIG_ALU_BUSYSTAT) == 0) ret |= 0x10;
690 if(power_on_reset) ret |= 0x01;
695 void DISPLAY::set_miscreg(uint8_t val)
697 int old_display_page = display_page;
699 nmi_enable = ((val & 0x80) == 0) ? true : false;
700 if(!nmi_enable) do_nmi(false);
702 if((val & 0x40) == 0) {
707 if(display_page != old_display_page) {
710 active_page = ((val & 0x20) == 0) ? 0 : 1;
711 if((val & 0x04) == 0) {
716 cgrom_bank = val & 0x03;
717 setup_display_mode();
721 void DISPLAY::set_monitor_bank(uint8_t var)
723 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
724 if((var & 0x04) != 0){
730 subrom_bank = var & 0x03;
733 subcpu_resetreq = false;
734 power_on_reset = true;
735 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
736 reset_some_devices();
739 subcpu_resetreq = true;
745 void DISPLAY::set_apalette_index_hi(uint8_t val)
747 apalette_index.b.h = val & 0x0f;
751 void DISPLAY::set_apalette_index_lo(uint8_t val)
753 apalette_index.b.l = val;
756 void DISPLAY::calc_apalette(uint16_t idx)
760 g = analog_palette_g[idx];
761 r = analog_palette_r[idx];
762 b = analog_palette_b[idx];
763 if(g != 0) g |= 0x0f;
764 if(r != 0) r |= 0x0f;
765 if(b != 0) b |= 0x0f;
766 analog_palette_pixel_tmp[idx] = RGB_COLOR(r, g, b);
770 void DISPLAY::set_apalette_b(uint8_t val)
774 index = apalette_index.w.l;
775 tmp = (val & 0x0f) << 4;
776 if(analog_palette_b[index] != tmp) {
777 analog_palette_b[index] = tmp;
778 calc_apalette(index);
779 palette_changed = true;
784 void DISPLAY::set_apalette_r(uint8_t val)
788 index = apalette_index.w.l;
789 tmp = (val & 0x0f) << 4;
790 if(analog_palette_r[index] != tmp) {
791 analog_palette_r[index] = tmp;
792 calc_apalette(index);
793 palette_changed = true;
798 void DISPLAY::set_apalette_g(uint8_t val)
802 index = apalette_index.w.l;
803 tmp = (val & 0x0f) << 4;
804 if(analog_palette_g[index] != tmp) {
805 analog_palette_g[index] = tmp;
806 calc_apalette(index);
807 palette_changed = true;
811 #endif // _FM77AV_VARIANTS
814 void DISPLAY::copy_vram_blank_area(void)
818 void DISPLAY::copy_vram_per_line(int begin, int end)
827 uint32_t src_offset_d1;
828 uint32_t src_offset_d2;
829 uint32_t src_offset_d;
834 uint32_t addr_d1, addr_d2;
838 //int dline = (int)displine - 1;
839 int dline = (int)displine;
841 if((begin < 0) || (begin > 4)) return;
842 if((end < 0) || (end > 4)) return;
843 if(begin > end) return;
844 if(dline < 0) return;
846 sectors = end - begin + 1;
848 if(display_mode == DISPLAY_MODE_8_400L) {
849 if(dline >= 400) return;
851 if(dline >= 200) return;
853 #if defined(_FM77AV_VARIANTS)
854 yoff_d1 = offset_point;
855 yoff_d2 = offset_point_bank1;
856 if(display_mode == DISPLAY_MODE_4096) {
857 src_offset = dline * 40 + begin * 8;
858 sectors = sectors * 8;
859 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
862 addr_d1 = (src_offset + yoff_d1) & 0x1fff;
863 addr_d2 = (src_offset + yoff_d2) & 0x1fff;
864 bytes_d1 = 0x2000 - addr_d1;
865 bytes_d2 = 0x2000 - addr_d2;
866 for(k = 0; k < pages; k++) {
868 for(i = 0; i < 3; i++) {
869 for(j = 0; j < 2; j++) {
870 uint32_t _addr_base = src_base + src_offset + poff;
871 if(bytes_d1 < sectors) {
872 my_memcpy(&gvram_shadow[_addr_base],
873 &gvram[addr_d1 + src_base + poff],
875 my_memcpy(&gvram_shadow[_addr_base + bytes_d1],
876 &gvram[src_base + poff],
879 my_memcpy(&gvram_shadow[_addr_base],
880 &gvram[addr_d1 + src_base + poff],
883 _addr_base += 0xc000;
884 if(bytes_d2 < sectors) {
885 my_memcpy(&gvram_shadow[_addr_base],
886 &gvram[addr_d2 + src_base + poff + 0xc000],
888 my_memcpy(&gvram_shadow[_addr_base + bytes_d2],
889 &gvram[src_base + poff + 0xc000],
892 my_memcpy(&gvram_shadow[_addr_base],
893 &gvram[addr_d2 + src_base + poff + 0xc000],
898 src_base = (i + 1) * 0x4000;
902 vram_draw_table[dline] = true;
903 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
905 # if defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV40)
906 else if(display_mode == DISPLAY_MODE_256k) {
907 src_offset = dline * 40 + begin * 8;
908 sectors = sectors * 8;
910 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
912 #elif defined(_FM77AV40)
917 src_offset_d1 = (src_offset + yoff_d1) & 0x1fff;
918 src_offset_d2 = (src_offset + yoff_d2) & 0x1fff;
919 bytes_d1 = 0x2000 - ((src_offset + yoff_d1) & 0x1fff);
920 bytes_d2 = 0x2000 - ((src_offset + yoff_d2) & 0x1fff);
921 for(k = 0; k < pages; k++) {
922 for(i = 0; i < 3; i++) {
923 for(j = 0; j < 2; j++) {
925 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
926 src_offset_d = src_offset_d1;
929 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
930 src_offset_d = src_offset_d2;
933 if(bytes_d < sectors) {
934 my_memcpy(&gvram_shadow[src_offset + src_base],
935 &gvram[src_offset_d + src_base],
937 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
941 my_memcpy(&gvram_shadow[src_offset + src_base],
942 &gvram[src_offset_d + src_base],
948 vram_draw_table[dline] = true;
949 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
951 else if(display_mode == DISPLAY_MODE_8_400L) {
952 src_offset = dline * 80 + begin * 16;
953 sectors = sectors * 16;
954 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
957 if(display_page_bak == 1) { // Is this dirty?
962 yoff_d = (yoff_d << 1) & 0x7fff;
963 src_offset_d = (src_offset + yoff_d) & 0x7fff;
964 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
965 for(i = 0; i < pages; i++) {
966 for(j = 0; j < 3; j++) {
967 src_base = i * 0x18000 + j * 0x8000;
968 if(bytes_d < sectors) {
970 my_memcpy(&gvram_shadow[src_offset + src_base],
971 &gvram[src_offset_d + src_base],
974 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
978 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
979 &gvram[src_offset_d + src_base],
984 vram_draw_table[dline] = true;
985 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
989 src_offset = dline * 80 + begin * 16;
990 sectors = sectors * 16;
991 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
993 #elif defined(_FM77AV40)
995 #elif defined(_FM77AV_VARIANTS)
1001 src_offset_d1 = (src_offset + yoff_d1) & 0x3fff;
1002 src_offset_d2 = (src_offset + yoff_d2) & 0x3fff;
1003 bytes_d1 = 0x4000 - ((src_offset + yoff_d1) & 0x3fff);
1004 bytes_d2 = 0x4000 - ((src_offset + yoff_d2) & 0x3fff);
1005 for(i = 0; i < pages; i++) {
1007 src_offset_d = src_offset_d1;
1010 src_offset_d = src_offset_d2;
1014 for(j = 0; j < 3; j++) {
1015 if(bytes_d < sectors) {
1016 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1017 &gvram[src_offset_d + src_base + poff],
1019 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1020 &gvram[src_base + poff],
1023 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1024 &gvram[src_offset_d + src_base + poff],
1031 vram_draw_table[dline] = true;
1032 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1033 //vram_wrote_table[dline] = false;
1037 src_offset = dline * 80 + begin * 16;
1038 sectors = sectors * 16;
1041 yoff_d = offset_point;
1042 src_offset_d = (src_offset + yoff_d) & 0x3fff;
1043 bytes_d = 0x4000 - ((src_offset + yoff_d) & 0x3fff);
1044 for(j = 0; j < 3; j++) {
1045 src_base = j * 0x4000;
1046 if(bytes_d < sectors) {
1047 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1048 &gvram[src_offset_d + src_base + poff],
1050 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1051 &gvram[src_base + poff],
1054 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1055 &gvram[src_offset_d + src_base + poff],
1059 vram_draw_table[dline] = true;
1060 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1061 //vram_wrote_table[dline] = false;
1067 void DISPLAY::copy_vram_all()
1069 #if defined(_FM77AV_VARIANTS)
1070 uint32_t yoff_d1 = offset_point;
1071 uint32_t yoff_d2 = offset_point_bank1;
1072 uint32_t src_offset_1, src_offset_2;
1074 if(display_mode == DISPLAY_MODE_4096) {
1075 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1080 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1081 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1082 for(int k = 0; k < pages; k++) {
1083 for(int i = 0; i < 3; i++) {
1084 for(int j = 0; j < 2; j++) {
1085 src_offset_1 = i * 0x4000 + j * 0x2000;
1086 src_offset_2 = src_offset_1 + 0xc000;
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);
1089 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1090 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1096 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1097 else if(display_mode == DISPLAY_MODE_256k) {
1098 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1099 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1100 for(int i = 0; i < 3; i++) {
1101 for(int j = 0; j < 2; j++) {
1102 src_offset_1 = i * 0x4000 + j * 0x2000;
1103 src_offset_2 = src_offset_1 + 0xc000;
1104 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1105 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1106 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1107 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1111 for(int i = 0; i < 3; i++) {
1112 for(int j = 0; j < 2; j++) {
1113 src_offset_1 = i * 0x4000 + j * 0x2000;
1114 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1115 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1118 } else if(display_mode == DISPLAY_MODE_8_400L) {
1120 uint32_t yoff_d, bytes_d;
1121 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1124 if(display_page_bak == 1) { // Is this dirty?
1129 yoff_d = (yoff_d << 1) & 0x7fff;
1130 bytes_d = 0x8000 - yoff_d;
1131 for(int i = 0; i < pages; i++) {
1132 for(int j = 0; j < 3; j++) {
1133 uint32_t src_base = i * 0x18000 + j * 0x8000;
1134 my_memcpy(&gvram_shadow[src_base],
1135 &gvram[yoff_d + src_base],
1137 if(bytes_d < 0x8000) {
1138 my_memcpy(&gvram_shadow[bytes_d + src_base],
1147 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1149 #elif defined(_FM77AV40)
1154 uint32_t bytes_d1 = 0x4000 - (yoff_d1 & 0x3fff);
1155 uint32_t bytes_d2 = 0x4000 - (yoff_d2 & 0x3fff);
1156 uint32_t yoff_d, bytes_d;
1157 for(int k = 0; k < pages; k++) {
1158 yoff_d = ((k & 1) == 0) ? (yoff_d1 & 0x3fff) : (yoff_d2 & 0x3fff);
1159 bytes_d = ((k & 1) == 0) ? bytes_d1 : bytes_d2;
1160 for(int j = 0; j < 3; j++) {
1161 src_offset_1 = k * 0xc000 + j * 0x4000;
1162 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1163 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1169 uint32_t yoff_d = offset_point & 0x3fff;
1170 uint32_t bytes_d = 0x4000 - (offset_point & 0x3fff);
1171 uint32_t src_offset_1;
1172 for(int j = 0; j < 3; j++) {
1173 src_offset_1 = j * 0x4000;
1174 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1175 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1181 // Timing values from XM7 . Thanks Ryu.
1182 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1183 void DISPLAY::event_callback_hdisp(void)
1188 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x02, 0xff);
1189 if(display_mode == DISPLAY_MODE_8_400L) {
1190 if(displine < 400) f = true;
1192 if(displine < 200) f = true;
1195 hdisp_event_id = -1;
1197 // DO ONLY WHEN SYNC-TO-HSYNC.
1198 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
1200 //copy_vram_per_line(0, 4);
1201 } else if(need_transfer_line) { // Not frame skip.
1204 for(int iii = 0; iii < 5 ; iii++) {
1205 if(vram_wrote_table[iii + displine * 5]) {
1206 if(begin < 0) begin = iii; // Check first.
1211 if(end < begin) end = begin;
1213 copy_vram_per_line(begin, end);
1214 // Prepare to next block.
1220 // Tail of this line.
1223 copy_vram_per_line(begin, end);
1227 if(display_mode == DISPLAY_MODE_8_400L) {
1228 register_event(this, EVENT_FM7SUB_HBLANK, 30.0, false, &hblank_event_id); // NEXT CYCLE_
1230 register_event(this, EVENT_FM7SUB_HBLANK, 39.5, false, &hblank_event_id); // NEXT CYCLE_
1238 void DISPLAY::event_callback_hblank(void)
1245 hblank_event_id = -1;
1247 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1248 if(display_mode == DISPLAY_MODE_8_400L) {
1249 if((displine < 400)) f = true;
1252 if((displine < 200)) f = true;
1256 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id);
1261 void DISPLAY::event_callback_vstart(void)
1268 display_page_bak = display_page;
1270 // Parameter from XM7/VM/display.c , thanks, Ryu.
1271 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1272 mainio->write_signal(SIG_DISPLAY_VSYNC, 0x00, 0xff);
1274 if(vblank_count != 0) {
1275 if(display_mode == DISPLAY_MODE_8_400L) {
1276 usec = (0.98 + 16.4) * 1000.0;
1278 usec = (1.91 + 12.7) * 1000.0;
1280 register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
1282 if(display_mode == DISPLAY_MODE_8_400L) {
1283 usec = 930.0; // 939.0
1285 usec = 1840.0; // 1846.5
1287 vstart_event_id = -1;
1288 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
1289 //register_event(this, EVENT_FM7SUB_HBLANK, usec, false, &hdisp_event_id); // NEXT CYCLE_
1292 if(display_mode == DISPLAY_MODE_8_400L) {
1293 usec = 0.34 * 1000.0;
1295 usec = 1.52 * 1000.0;
1297 vsync_event_id = -1;
1298 hblank_event_id = -1;
1299 hdisp_event_id = -1;
1300 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1304 void DISPLAY::event_callback_vsync(void)
1310 //write_access_page = (write_access_page + 1) & 1;
1313 if(display_mode == DISPLAY_MODE_8_400L) {
1314 usec = 0.33 * 1000.0;
1316 usec = 0.51 * 1000.0;
1318 mainio->write_signal(SIG_DISPLAY_VSYNC, 0x01, 0xff);
1319 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1320 //register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1322 if(palette_changed) {
1323 #if defined(_FM77AV_VARIANTS)
1324 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
1326 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
1327 vram_wrote_shadow = true;
1328 for(int yy = 0; yy < 400; yy++) {
1329 vram_draw_table[yy] = true;
1331 palette_changed = false;
1333 // Transfer on VSYNC
1334 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) {
1337 if(display_mode == DISPLAY_MODE_8_400L) lines = 400;
1338 if(need_transfer_line) {
1339 if(vram_wrote) { // transfer all line
1340 for(displine = 0; displine < lines; displine++) {
1341 //if(!vram_draw_table[displine]) {
1342 copy_vram_per_line(0, 4);
1346 } else { // transfer wrote line
1349 for(displine = 0; displine < lines; displine++) {
1350 //if(!vram_draw_table[displine]) {
1351 for(int iii = 0; iii < 5 ; iii++) {
1352 if(vram_wrote_table[iii + displine * 5]) {
1359 if(end < begin) end = begin;
1360 copy_vram_per_line(begin, end);
1367 if(end < 0) end = 4;
1368 copy_vram_per_line(begin, end);
1376 for(int yy = 0; yy < lines; yy++) {
1377 if(vram_draw_table[yy]) {
1378 vram_wrote_shadow = true;
1379 screen_update_flag = true;
1384 // TRANSFER per HSYNC a.k.a SYNC-TO-HSYNC.
1386 if(display_mode == DISPLAY_MODE_8_400L) lines = 400;
1388 if(need_transfer_line) {
1389 if(vram_wrote) { // Transfer all line.
1390 for(int yy = 0; yy < lines; yy++) {
1392 copy_vram_per_line(0, 4);
1398 for(int yy = 0; yy < lines; yy++) {
1399 if(vram_draw_table[yy]) {
1400 vram_wrote_shadow = true;
1401 screen_update_flag = true;
1405 //vram_wrote = false;
1407 frame_skip_count_transfer++;
1409 // Check frame skip for next frame.
1410 uint32_t factor = ((config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28) & 3;
1411 if((frame_skip_count_transfer > factor) /* || (vram_wrote) */) {
1412 frame_skip_count_transfer = 0;
1413 need_transfer_line = true;
1415 need_transfer_line = false;
1422 void DISPLAY::event_callback(int event_id, int err)
1427 case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
1428 #if defined(_FM77AV_VARIANTS)
1436 case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
1439 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1440 case EVENT_FM7SUB_HDISP:
1441 event_callback_hdisp();
1443 case EVENT_FM7SUB_HBLANK:
1444 event_callback_hblank();
1446 case EVENT_FM7SUB_VSTART: // Call first.
1447 event_callback_vstart();
1449 case EVENT_FM7SUB_VSYNC:
1450 event_callback_vsync();
1453 case EVENT_FM7SUB_CLR_BUSY:
1456 case EVENT_FM7SUB_CLR_CRTFLAG:
1462 void DISPLAY::event_frame()
1469 //write_access_page = (write_access_page + 1) & 1;
1470 //out_debug_log(_T("DISPLINE=%d"), displine);
1472 if(display_mode == DISPLAY_MODE_8_400L) {
1473 usec = 0.34 * 1000.0;
1475 usec = 1.52 * 1000.0;
1477 mainio->write_signal(SIG_DISPLAY_VSYNC, 0x01, 0xff);
1478 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1479 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1483 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1487 if(display_mode == DISPLAY_MODE_8_400L) lines = 400;
1489 if(need_transfer_line && vram_wrote) {
1490 for(yy = 0; yy < lines; yy++) {
1491 //if(!vram_draw_table[yy]) {
1493 copy_vram_per_line(0, 4);
1501 for(yy = 0; yy < lines; yy++) {
1502 if(vram_draw_table[yy]) {
1508 screen_update_flag = true;
1509 vram_wrote_shadow = true;
1513 frame_skip_count_transfer++;
1515 uint32_t factor = (config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28;
1516 if(frame_skip_count_transfer > factor) {
1517 frame_skip_count_transfer = 0;
1518 need_transfer_line = true;
1520 need_transfer_line = false;
1522 //vram_wrote = false;
1530 void DISPLAY::event_vline(int v, int clock)
1532 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1534 if(need_transfer_line == false) return;
1537 // Not transfer, will transfer at event_frame.
1538 copy_vram_per_line(0, 4);
1542 for(int iii = 0; iii < 5 ; iii++) {
1543 if(vram_wrote_table[displine * 5 + iii]) {
1544 if(begin < 0) begin = iii;
1548 if(end < begin) end = begin;
1549 copy_vram_per_line(begin, end);
1557 copy_vram_per_line(begin, end);
1565 uint32_t DISPLAY::read_signal(int id)
1567 uint32_t retval = 0;
1569 case SIG_FM7_SUB_HALT:
1570 case SIG_DISPLAY_HALT:
1571 retval = (halt_flag) ? 0xffffffff : 0;
1573 case SIG_DISPLAY_BUSY:
1574 retval = (sub_busy) ? 0x80 : 0;
1576 case SIG_DISPLAY_MULTIPAGE:
1577 retval = multimode_accessmask;
1579 case SIG_DISPLAY_PLANES:
1582 #if defined(_FM77AV_VARIANTS)
1583 case SIG_DISPLAY_VSYNC:
1584 retval = (vsync) ? 0x01 : 0x00;
1586 case SIG_DISPLAY_DISPLAY:
1587 retval = (!hblank) ? 0x02: 0x00;
1589 case SIG_FM7_SUB_BANK: // Main: FD13
1590 retval = subrom_bank & 0x03;
1591 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1592 if(monitor_ram) retval |= 0x04;
1596 #if defined(_FM77AV_VARIANTS)
1597 case SIG_DISPLAY_MODE320:
1598 retval = (mode320) ? 0x40: 0x00;
1601 case SIG_DISPLAY_Y_HEIGHT:
1602 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1603 retval = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
1608 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1610 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1611 retval |= (kanjisub) ? 0x00 : 0x20;
1612 retval |= (mode256k) ? 0x10 : 0x00;
1613 retval |= (mode400line) ? 0x00 : 0x08;
1614 retval |= (ram_protect) ? 0x00 : 0x04;
1615 #elif defined(_FM77L4)
1616 retval |= (mode400line) ? 0x00 : 0x08;
1619 case SIG_DISPLAY_X_WIDTH:
1620 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1621 retval = (mode320 || mode256k) ? 320 : 640;
1622 #elif defined(_FM77AV_VARIANTS)
1623 retval = (mode320) ? 320 : 640;
1634 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
1636 bool flag = ((data & mask) != 0);
1640 case SIG_FM7_SUB_HALT:
1645 //mainio->write_signal(SIG_FM7_SUB_HALT, data, mask);
1647 case SIG_DISPLAY_HALT:
1651 restart_subsystem();
1654 case SIG_FM7_SUB_CANCEL:
1656 cancel_request = true;
1660 case SIG_DISPLAY_CLOCK:
1664 #if defined(_FM77AV_VARIANTS)
1665 case SIG_FM7_SUB_BANK: // Main: FD13
1666 set_monitor_bank(data & 0xff);
1669 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1670 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1671 //printf("Wrote $FD04: %02x\n", data);
1673 int oldmode = display_mode;
1675 kanjisub = ((data & 0x20) == 0) ? true : false;
1676 mode256k = (((data & 0x10) != 0) && ((data & 0x08) != 0) ) ? true : false;
1677 mode400line = ((data & 0x08) == 0) ? true : false;
1678 ram_protect = ((data & 0x04) == 0) ? true : false;
1679 if((mode400line) && !(mode320)) {
1680 display_mode = DISPLAY_MODE_8_400L;
1681 } else if(mode256k) {
1682 display_mode = DISPLAY_MODE_256k;
1684 display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1686 if(oldmode != display_mode) {
1688 if(mode320 || mode256k) {
1689 if(oldmode == DISPLAY_MODE_8_400L) p_vm->set_vm_frame_rate(FRAMES_PER_SEC);
1690 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1691 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1692 for(y = 0; y < 200; y++) {
1693 pp = emu->get_screen_buffer(y);
1694 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1697 for(y = 0; y < 400; y++) {
1698 pp = emu->get_screen_buffer(y);
1699 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1702 //emu->set_vm_screen_lines(200);
1703 } else if(display_mode == DISPLAY_MODE_8_400L) {
1704 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1705 if(oldmode != DISPLAY_MODE_8_400L) p_vm->set_vm_frame_rate(55.40);
1706 for(y = 0; y < 400; y++) {
1707 pp = emu->get_screen_buffer(y);
1708 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1711 if(oldmode == DISPLAY_MODE_8_400L) p_vm->set_vm_frame_rate(FRAMES_PER_SEC);
1712 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1713 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1714 for(y = 0; y < 200; y++) {
1715 pp = emu->get_screen_buffer(y);
1716 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1719 for(y = 0; y < 400; y++) {
1720 pp = emu->get_screen_buffer(y);
1721 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1724 //emu->set_vm_screen_lines(200);
1727 alu->write_signal(SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
1728 alu->write_signal(SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200, 0xffff);
1729 alu->write_signal(SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xff : 0x00, 0xff);
1730 frame_skip_count_draw = 3;
1731 frame_skip_count_transfer = 3;
1732 setup_display_mode();
1735 #elif defined(_FM77_VARIANTS)
1737 int oldmode = display_mode;
1738 kanjisub = ((data & 0x20) == 0) ? true : false;
1739 # if defined(_FM77L4)
1740 stat_400linecard = ((data & 0x10) != 0) ? true : false;
1741 mode400line = ((data & 0x08) != 0) ? false : true;
1742 if(mode400line && stat_400linecard) {
1743 display_mode = DISPLAY_MODE_8_400L_TEXT;
1744 } else if(stat_400linecard) {
1745 display_mode = DISPLAY_MODE_8_200L_TEXT;
1747 display_mode = DISPLAY_MODE_8_200L;
1750 setup_display_mode();
1754 #if defined(_FM77AV_VARIANTS)
1755 case SIG_DISPLAY_MODE320: // FD12 bit 6
1756 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1758 //printf("Wrote $FD12: %02x\n", data);
1759 int oldmode = display_mode;
1762 display_mode = DISPLAY_MODE_8_400L;
1763 } else if(mode256k) {
1764 display_mode = DISPLAY_MODE_256k;
1765 } else if(!(mode320) && !(mode256k)) {
1766 //display_mode = (mode400line) ? DISPLAY_MODE_8_400L : DISPLAY_MODE_8_200L;
1767 display_mode = DISPLAY_MODE_8_200L;
1769 display_mode = (mode256k) ? DISPLAY_MODE_256k : DISPLAY_MODE_4096;
1771 if(oldmode != display_mode) {
1773 if(mode320 || mode256k) {
1774 if(oldmode == DISPLAY_MODE_8_400L) p_vm->set_vm_frame_rate(FRAMES_PER_SEC);
1775 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1776 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1777 for(y = 0; y < 200; y++) {
1778 pp = emu->get_screen_buffer(y);
1779 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1782 for(y = 0; y < 400; y++) {
1783 pp = emu->get_screen_buffer(y);
1784 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1787 //emu->set_vm_screen_lines(200);
1788 } else { // 200 lines, 8 colors.
1789 if(display_mode == DISPLAY_MODE_8_400L) {
1790 if(oldmode != DISPLAY_MODE_8_400L) p_vm->set_vm_frame_rate(55.40);
1792 if(oldmode == DISPLAY_MODE_8_400L) p_vm->set_vm_frame_rate(FRAMES_PER_SEC);
1794 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1795 int ymax = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
1797 emu->set_vm_screen_size(640, ymax, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1798 for(y = 0; y < ymax; y++) {
1799 pp = emu->get_screen_buffer(y);
1800 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1803 for(y = 0; y < 400; y++) {
1804 pp = emu->get_screen_buffer(y);
1805 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1808 //emu->set_vm_screen_lines(200);
1811 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
1812 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
1813 alu->write_signal(SIG_ALU_400LINE, 0x00, 0xff);
1814 setup_display_mode();
1815 //frame_skip_count = 3;
1818 # else /* FM77AV/20/20EX */
1821 if(oldflag != mode320) {
1824 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1825 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1826 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 320 * sizeof(scrntype_t));
1828 for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
1830 //emu->set_vm_screen_lines(200);
1832 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1833 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1834 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
1836 for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
1838 //emu->set_vm_screen_lines(200);
1841 display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1842 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
1843 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
1844 alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
1846 setup_display_mode();
1851 case SIG_DISPLAY_MULTIPAGE:
1852 set_multimode(data);
1854 case SIG_FM7_SUB_KEY_MASK:
1855 if(firq_mask == flag) {
1856 do_firq(!flag && key_firq_req);
1860 case SIG_FM7_SUB_KEY_FIRQ:
1861 do_firq(flag & !(firq_mask));
1862 key_firq_req = flag;
1864 case SIG_FM7_SUB_USE_CLR:
1866 clr_count = data & 0x03;
1877 * Vram accessing functions moved to vram.cpp .
1880 uint32_t DISPLAY::read_mmio(uint32_t addr)
1882 uint32_t retval = 0xff;
1884 if(addr < 0xd400) return 0xff;
1886 #if !defined(_FM77AV_VARIANTS)
1887 raddr = (addr - 0xd400) & 0x000f;
1888 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
1889 raddr = (addr - 0xd400) & 0x003f;
1890 #else // FM77AV40EX || FM77AV40SX
1891 raddr = (addr - 0xd400) & 0x00ff;
1894 case 0x00: // Read keyboard
1895 retval = (keyboard->read_data8(0x00) != 0) ? 0xff : 0x7f;
1897 case 0x01: // Read keyboard
1898 retval = keyboard->read_data8(0x01) & 0xff;
1900 case 0x02: // Acknowledge
1909 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1910 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
1912 if(!kanjisub) return 0xff;
1913 # if !defined(_FM77_VARIANTS)
1915 return (uint8_t)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1918 if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1921 if(!kanjisub) return 0xff;
1922 # if !defined(_FM77_VARIANTS)
1924 return (uint8_t)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1927 if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1934 retval = set_vramaccess();
1940 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
1942 #if defined(_FM77AV_VARIANTS)
1945 retval = alu->read_data8(ALU_CMDREG);
1948 retval = alu->read_data8(ALU_LOGICAL_COLOR);
1951 retval = alu->read_data8(ALU_WRITE_MASKREG);
1954 retval = alu->read_data8(ALU_CMP_STATUS_REG);
1957 retval = alu->read_data8(ALU_BANK_DISABLE);
1959 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1960 case 0x2f: // VRAM BANK
1961 retval = 0xfc | (vram_bank & 0x03);
1966 retval = get_miscreg();
1970 retval = keyboard->read_data8(0x31);
1973 retval = keyboard->read_data8(0x32);
1979 return (uint8_t)retval;
1982 uint32_t DISPLAY::read_vram_data8(uint32_t addr)
1986 uint32_t color = (addr >> 14) & 0x03;
1987 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1988 if(display_mode == DISPLAY_MODE_8_400L) {
1989 color = vram_bank & 0x03;
1990 if(color > 2) color = 0;
1992 color = (addr >> 14) & 0x03;
1996 //if((multimode_accessmask & (1 << color)) != 0) return 0xff;
1997 if(multimode_accessflags[color]) return 0xff;
1999 #if defined(_FM77AV_VARIANTS)
2000 if (active_page != 0) {
2001 offset = offset_point_bank1;
2003 offset = offset_point;
2006 offset = offset_point;
2008 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2009 if(vram_active_block != 0) {
2010 if(display_mode != DISPLAY_MODE_256k) offset = 0; // Don't scroll at BLOCK 1.
2013 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2014 if(display_mode == DISPLAY_MODE_8_400L) {
2016 uint32_t page_offset_alt = 0;
2017 if(addr >= 0x8000) return 0xff;
2018 color = vram_bank & 0x03;
2019 if(color > 2) color = 0;
2021 pagemod = 0x8000 * color;
2022 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2023 if(vram_active_block != 0) page_offset = 0x18000;
2025 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2026 return gvram[vramaddr];
2029 uint32_t page_offset_alt;
2030 #if defined(_FM77AV40)
2032 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2034 page_offset_alt = 0; // right?
2037 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2039 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
2040 //page_mask = 0x1fff;
2041 //pagemod = addr & 0xe000;
2043 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2045 return gvram[vramaddr];
2047 #elif defined(_FM77AV_VARIANTS)
2049 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2050 return gvram[vramaddr];
2052 #elif defined(_FM77L4) //_FM77L4
2054 if(display_mode == DISPLAY_MODE_8_400L) {
2055 return (uint32_t)read_vram_l4_400l(addr, offset);
2057 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2058 return gvram[vramaddr];
2062 #else // Others (77/7/8)
2063 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2064 return gvram[vramaddr];
2068 void DISPLAY::write_dma_data8(uint32_t addr, uint32_t data)
2070 uint32_t raddr = (addr & 0xffff) >> 7;
2071 if(write_dma_func_table[raddr] != NULL) {
2072 (this->*write_dma_func_table[raddr])(addr, (uint8_t) data);
2076 void DISPLAY::write_vram_data8(uint32_t addr, uint8_t data)
2079 uint32_t color = (addr >> 14) & 0x03;
2083 #if defined(_FM77AV_VARIANTS)
2084 if (active_page != 0) {
2085 offset = offset_point_bank1;
2087 offset = offset_point;
2090 offset = offset_point;
2092 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2093 if(vram_active_block != 0) offset = 0; // Don't scroll at BLOCK 1.
2096 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2097 if(display_mode == DISPLAY_MODE_8_400L) {
2099 uint32_t page_offset_alt = 0;
2101 if(addr >= 0x8000) {
2104 color = vram_bank & 0x03;
2105 if(color > 2) color = 0;
2107 pagemod = 0x8000 * color;
2108 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2109 if(vram_active_block != 0) page_offset_alt = 0x18000;
2111 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2112 // Reduce data transfer.
2113 tdata = gvram[vramaddr];
2115 naddr = (addr & 0x7fff) >> 4;
2116 gvram[vramaddr] = data;
2117 vram_wrote_table[naddr] = true;
2119 } else if(display_mode == DISPLAY_MODE_256k) {
2120 uint32_t page_offset_alt;
2122 #if defined(_FM77AV40)
2124 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2126 page_offset_alt = 0; // right?
2129 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2131 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
2132 tdata = gvram[vramaddr];
2134 naddr = (addr & page_mask) >> 3;
2135 gvram[vramaddr] = data;
2136 vram_wrote_table[naddr] = true;
2139 } else if(display_mode == DISPLAY_MODE_4096) {
2141 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2142 tdata = gvram[vramaddr];
2144 naddr = (addr & page_mask) >> 3;
2145 gvram[vramaddr] = data;
2146 vram_wrote_table[naddr] = true;
2150 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2151 tdata = gvram[vramaddr];
2153 naddr = (addr & page_mask) >> 4;
2154 gvram[vramaddr] = data;
2155 vram_wrote_table[naddr] = true;
2158 #elif defined(_FM77AV_VARIANTS)
2159 if(display_mode == DISPLAY_MODE_4096) {
2161 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2162 tdata = gvram[vramaddr];
2164 naddr = (addr & page_mask) >> 3;
2165 gvram[vramaddr] = data;
2166 vram_wrote_table[naddr] = true;
2170 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2171 tdata = gvram[vramaddr];
2173 naddr = (addr & page_mask) >> 4;
2174 gvram[vramaddr] = data;
2175 vram_wrote_table[naddr] = true;
2178 #elif defined(_FM77L4) //_FM77L4
2181 if(display_mode == DISPLAY_MODE_8_400L) {
2182 write_vram_l4_400l(addr, data, offset);
2184 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2185 tdata = gvram[vramaddr];
2187 naddr = (addr & 0x3fff) >> 4;
2188 gvram[vramaddr] = data;
2189 vram_wrote_table[naddr] = true;
2193 #else // Others (77/7/8)
2196 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2197 tdata = gvram[vramaddr];
2199 naddr = (addr & 0x3fff) >> 4;
2200 gvram[vramaddr] = data;
2201 vram_wrote_table[naddr] = true;
2207 uint32_t DISPLAY::read_cpu_vram_data8(uint32_t addr)
2210 #if defined(_FM77AV_VARIANTS)
2212 alu->read_data8(addr);
2215 return read_vram_data8(addr);
2218 uint32_t DISPLAY::read_dma_vram_data8(uint32_t addr)
2220 return read_vram_data8(addr);
2223 void DISPLAY::init_read_table(void)
2226 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
2227 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cpu_vram_data8;
2228 read_dma_func_table[_at >> 7] = &DISPLAY::read_dma_vram_data8;
2230 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
2231 read_cpu_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2232 read_dma_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2234 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
2235 read_cpu_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2236 read_dma_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2238 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
2239 read_cpu_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2240 read_dma_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2242 #if defined(_FM77AV_VARIANTS)
2243 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
2244 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2245 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2247 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
2248 read_cpu_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2249 read_dma_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2252 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
2253 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2254 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2257 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
2258 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2259 read_dma_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2261 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
2262 read_cpu_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2263 read_dma_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2267 uint32_t DISPLAY::read_console_ram(uint32_t addr)
2269 uint32_t raddr = addr & 0xfff;
2270 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2272 if(console_ram_bank >= 1) {
2273 return submem_console_av40[((console_ram_bank - 1) << 12) + raddr];
2277 return console_ram[raddr];
2280 uint32_t DISPLAY::read_work_ram(uint32_t addr)
2282 addr = addr & 0x3ff;
2283 return work_ram[addr];
2287 uint32_t DISPLAY::read_shared_ram(uint32_t addr)
2289 addr = addr - 0xd380;
2290 return shared_ram[addr];
2293 #if defined(_FM77AV_VARIANTS)
2294 uint32_t DISPLAY::read_hidden_ram(uint32_t addr)
2296 if(addr >= 0xd500) {
2297 return submem_hidden[addr - 0xd500];
2303 uint32_t DISPLAY::read_cgrom(uint32_t addr)
2305 #if defined(_FM77AV_VARIANTS)
2306 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2308 return submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)]; //FIXME
2311 return subsys_cg[(addr - 0xd800) + cgrom_bank * 0x800];
2313 return subsys_c[addr - 0xd800];
2317 uint32_t DISPLAY::read_subsys_monitor(uint32_t addr)
2319 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2321 return subsys_ram[addr - 0xe000];
2324 #if defined(_FM77AV_VARIANTS)
2325 switch(subrom_bank_using & 3) {
2327 return subsys_c[addr - 0xd800];
2330 return subsys_a[addr - 0xe000];
2333 return subsys_b[addr - 0xe000];
2336 return subsys_cg[addr - 0xe000];
2340 return subsys_c[addr - 0xd800];
2344 uint32_t DISPLAY::read_dma_data8(uint32_t addr)
2346 uint32_t raddr = (addr & 0xffff) >> 7;
2347 if(read_dma_func_table[raddr] != NULL) {
2348 return (this->*read_dma_func_table[raddr])(addr);
2353 uint32_t DISPLAY::read_data8(uint32_t addr)
2355 uint32_t raddr = addr;
2357 if(addr < 0x10000) {
2358 raddr = (addr & 0xffff) >> 7;
2359 if(read_cpu_func_table[raddr] != NULL) {
2360 return (this->*read_cpu_func_table[raddr])(addr);
2365 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2366 return dpalette_data[addr - FM7_SUBMEM_OFFSET_DPALETTE];
2369 #if defined(_FM77AV_VARIANTS)
2371 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2372 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2373 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2374 if(vram_active_block != 0) {
2378 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2379 if(display_mode == DISPLAY_MODE_8_400L) {
2380 uint32_t page_offset_alt = 0;
2383 color = (addr & 0x18000) >> 15;
2384 if(color > 2) color = 0;
2385 pagemod = 0x8000 * color;
2386 if (active_page != 0) {
2387 offset = offset_point_bank1 << 1;
2389 offset = offset_point << 1;
2391 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2392 if(vram_active_block != 0) {
2393 page_offset_alt = 0x18000;
2397 return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset_alt];
2400 return read_vram_data8(addr);
2407 * Vram accessing functions moved to vram.cpp .
2410 void DISPLAY::write_mmio(uint32_t addr, uint8_t data)
2413 uint8_t active_block_old;
2415 if(addr < 0xd400) return;
2417 #if !defined(_FM77AV_VARIANTS)
2418 addr = (addr - 0xd400) & 0x000f;
2419 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2420 addr = (addr - 0xd400) & 0x003f;
2421 #else // FM77AV40EX || FM77AV40SX
2422 addr = (addr - 0xd400) & 0x00ff;
2424 io_w_latch[addr] = (uint8_t)data;
2426 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4)
2429 set_cyclesteal((uint8_t)data);
2432 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2433 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2436 if(!kanjisub) return;
2437 kanjiaddr.w.h = 0x0000;
2438 kanjiaddr.b.h = (uint8_t) data;
2441 if(!kanjisub) return;
2442 kanjiaddr.w.h = 0x0000;
2443 kanjiaddr.b.l = (uint8_t)data;
2456 if(clr_count <= 0) {
2458 } else { // Read once when using clr_foo() to set busy flag.
2461 usec = (1000.0 * 1000.0) / 2000000.0;
2463 usec = (1000.0 * 1000.0) / 999000.0;
2465 if(!(is_cyclesteal) && (vram_accessflag)) usec = usec * 3.0;
2466 usec = (double)clr_count * usec;
2467 register_event(this, EVENT_FM7SUB_CLR_BUSY, usec, false, NULL); // NEXT CYCLE_
2474 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
2479 rval = (uint8_t)data;
2480 if(offset_changed[active_page]) {
2481 #if defined(_FM77AV_VARIANTS)
2482 if(active_page != 0) {
2483 tmp_offset_point[active_page].d = offset_point_bank1;
2485 tmp_offset_point[active_page].d = offset_point;
2488 tmp_offset_point[active_page].d = offset_point;
2491 tmp_offset_point[active_page].w.h = 0x0000;
2493 tmp_offset_point[active_page].b.h = rval;
2495 tmp_offset_point[active_page].b.l = rval;
2497 offset_changed[active_page] = !offset_changed[active_page];
2498 if(offset_changed[active_page]) {
2500 #if defined(_FM77AV_VARIANTS)
2501 if(active_page != 0) {
2503 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fff;
2505 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fe0;
2509 offset_point = tmp_offset_point[active_page].d & 0x007fff;
2511 offset_point = tmp_offset_point[active_page].d & 0x007fe0;
2515 offset_point = tmp_offset_point[active_page].d & 0x7fe0;
2519 #if defined(_FM77AV_VARIANTS)
2522 alu_write_cmdreg(data);
2525 alu_write_logical_color(data);
2528 alu_write_mask_reg(data);
2531 alu_write_disable_reg(data);
2534 alu_write_offsetreg_hi(data);
2537 alu_write_offsetreg_lo(data);
2540 alu_write_linepattern_hi(data);
2543 alu_write_linepattern_lo(data);
2545 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2547 console_ram_bank = (data & 0x18) >> 3;
2548 if(console_ram_bank > 2) console_ram_bank = 0;
2549 cgram_bank = data & 0x07;
2550 kanji_level2 = ((data & 0x80) == 0) ? false : true;
2552 case 0x2f: // VRAM BANK
2553 vram_bank = data & 0x03;
2554 if(vram_bank > 2) vram_bank = 0;
2564 keyboard->write_data8(0x31, data);
2566 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2568 active_block_old = vram_active_block;
2569 vram_active_block = data & 0x01;
2570 if(vram_display_block != (((data & 0x10) != 0) ? 1 : 0)) vram_wrote = true;
2571 vram_display_block = ((data & 0x10) != 0) ? 1 : 0;
2572 if(vram_active_block != active_block_old) setup_display_mode();
2577 tmpvar.d = window_xbegin * 8;
2580 tmpvar.b.h = data & 0x03;
2582 tmpvar.b.l = data & 0xf8;
2584 if(mode320 || mode256k) {
2585 if(tmpvar.d > 320) tmpvar.d = 320;
2587 if(tmpvar.d > 640) tmpvar.d = 640;
2589 window_xbegin = tmpvar.d / 8;
2594 tmpvar.d = window_xend * 8;
2597 tmpvar.b.h = data & 0x03;
2599 tmpvar.b.l = data & 0xf8;
2601 if(mode320 || mode256k) {
2602 if(tmpvar.d > 320) tmpvar.d = 320;
2604 if(tmpvar.d > 640) tmpvar.d = 640;
2606 window_xend = tmpvar.d / 8;
2611 tmpvar.d = window_low;
2614 tmpvar.b.h = data & 0x03;
2616 tmpvar.b.l = data & 0xff;
2618 if(display_mode == DISPLAY_MODE_8_400L) {
2619 if(tmpvar.d > 400) tmpvar.d = 400;
2622 if(tmpvar.d > 400) tmpvar.d = 400;
2624 window_low = tmpvar.d;
2629 tmpvar.d = window_high;
2632 tmpvar.b.h = data & 0x03;
2634 tmpvar.b.l = data & 0xff;
2636 if(display_mode == DISPLAY_MODE_8_400L) {
2637 if(tmpvar.d > 400) tmpvar.d = 400;
2640 if(tmpvar.d > 400) tmpvar.d = 400;
2642 window_high = tmpvar.d;
2648 #if defined(_FM77AV_VARIANTS)
2650 if((addr >= 0x13) && (addr <= 0x1a)) {
2651 alu_write_cmpdata_reg(addr - 0x13, data);
2652 } else if((addr >= 0x1c) && (addr <= 0x1e)) {
2653 alu_write_tilepaint_data(addr, data);
2654 } else if((addr >= 0x24) && (addr <= 0x2b)) {
2655 alu_write_line_position(addr - 0x24, data);
2662 void DISPLAY::init_write_table(void)
2665 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
2666 write_cpu_func_table[_at >> 7] = &DISPLAY::write_cpu_vram_data8;
2667 write_dma_func_table[_at >> 7] = &DISPLAY::write_dma_vram_data8;
2669 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
2670 write_cpu_func_table[_at >> 7] = &DISPLAY::write_console_ram;
2671 write_dma_func_table[_at >> 7] = &DISPLAY::write_console_ram;
2673 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
2674 write_cpu_func_table[_at >> 7] = &DISPLAY::write_work_ram;
2675 write_dma_func_table[_at >> 7] = &DISPLAY::write_work_ram;
2677 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
2678 write_cpu_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
2679 write_dma_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
2681 #if defined(_FM77AV_VARIANTS)
2682 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
2683 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
2684 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
2686 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
2687 write_cpu_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
2688 write_dma_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
2691 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
2692 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
2693 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
2696 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2697 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
2698 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
2699 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
2701 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
2702 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
2703 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
2706 for(_at = 0xd800; _at < 0x10000; _at += 0x80) {
2707 write_cpu_func_table[_at >> 7] = &DISPLAY::write_dummy;
2708 write_dma_func_table[_at >> 7] = &DISPLAY::write_dummy;
2713 void DISPLAY::write_console_ram(uint32_t addr, uint8_t data)
2715 uint32_t raddr = addr & 0xfff;
2716 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2718 if(console_ram_bank >= 1) {
2719 submem_console_av40[((console_ram_bank - 1) << 12) + raddr] = data;
2724 console_ram[raddr] = data;
2728 void DISPLAY::write_work_ram(uint32_t addr, uint8_t data)
2730 uint32_t raddr = addr & 0xfff;
2731 work_ram[raddr] = data;
2735 void DISPLAY::write_shared_ram(uint32_t addr, uint8_t data)
2737 uint32_t raddr = addr & 0x7f;
2738 shared_ram[raddr] = data;
2742 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2743 void DISPLAY::write_subsys_cgram(uint32_t addr, uint8_t data)
2745 uint32_t raddr = addr - 0xd800;
2746 if(ram_protect) return;
2747 if(!monitor_ram) return;
2748 submem_cgram[cgram_bank * 0x0800 + raddr] = data; //FIXME
2751 void DISPLAY::write_subsys_ram(uint32_t addr, uint8_t data)
2753 if(ram_protect) return;
2754 if(!monitor_ram) return;
2755 subsys_ram[addr - 0xe000] = data; //FIXME
2759 #if defined(_FM77AV_VARIANTS)
2760 void DISPLAY::write_hidden_ram(uint32_t addr, uint8_t data)
2762 submem_hidden[addr - 0xd500] = data;
2767 void DISPLAY::write_cpu_vram_data8(uint32_t addr, uint8_t data)
2769 uint32_t color = (addr & 0xc000) >> 14;
2770 #if defined(_FM77AV_VARIANTS)
2772 alu->read_data8(addr);
2776 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2777 if(display_mode == DISPLAY_MODE_8_400L) {
2778 color = vram_bank & 0x03;
2779 if(color > 2) color = 0;
2783 //if((multimode_accessmask & (1 << color)) != 0) return;
2784 if(multimode_accessflags[color]) return;
2786 write_vram_data8(addr & 0xffff, data);
2789 void DISPLAY::write_dma_vram_data8(uint32_t addr, uint8_t data)
2791 uint32_t color = (addr & 0xc000) >> 14;
2792 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2793 if(display_mode == DISPLAY_MODE_8_400L) {
2794 color = vram_bank & 0x03;
2795 if(color > 2) color = 0;
2799 //if((multimode_accessmask & (1 << color)) != 0) return;
2800 if(multimode_accessflags[color]) return;
2802 write_vram_data8(addr & 0xffff, data);
2805 void DISPLAY::write_dummy(uint32_t addr, uint8_t data)
2809 void DISPLAY::write_data8(uint32_t addr, uint32_t data)
2813 //uint32_t page_offset = 0x0000;
2814 uint8_t val8 = data & 0xff;
2815 uint32_t color = (addr & 0xc000) >> 14;
2818 if(addr < 0x10000) {
2819 void (*_write_func)(uint32_t, uint32_t);
2820 raddr = (addr & 0xffff) >> 7;
2821 if(write_cpu_func_table[raddr] != NULL) {
2822 (this->*write_cpu_func_table[raddr])(addr, (uint8_t)data);
2828 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2829 set_dpalette(addr - FM7_SUBMEM_OFFSET_DPALETTE, val8);
2833 #if defined(_FM77AV_VARIANTS)
2835 else if(addr == FM7_SUBMEM_OFFSET_APALETTE_R) {
2836 set_apalette_r(val8);
2838 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_G) {
2839 set_apalette_g(val8);
2841 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_B) {
2842 set_apalette_b(val8);
2844 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_HI) {
2845 set_apalette_index_hi(val8);
2847 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_LO) {
2848 set_apalette_index_lo(val8);
2852 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2853 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2854 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2855 if(display_mode == DISPLAY_MODE_8_400L) {
2858 uint32_t page_offset_alt = 0;
2860 color = (addr & 0x18000) >> 15;
2861 if(color > 2) color = 0;
2862 if (active_page != 0) {
2863 offset = offset_point_bank1 << 1;
2865 offset = offset_point << 1;
2867 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2868 if(vram_active_block != 0) {
2869 page_offset_alt = 0x18000;
2873 naddr = (addr & 0x7fff) >> 4;
2874 pagemod = 0x8000 * color;
2875 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2876 tdata = gvram[vramaddr];
2877 if(tdata != (uint8_t)data) {
2878 gvram[vramaddr] = data;
2879 vram_wrote_table[naddr] = true;
2883 write_vram_data8(addr, data);
2885 write_vram_data8(addr, data);
2887 //if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
2894 uint32_t DISPLAY::read_bios(const _TCHAR *name, uint8_t *ptr, uint32_t size)
2900 if((name == NULL) || (ptr == NULL)) return 0;
2901 s = create_local_path(name);
2902 if(s == NULL) return 0;
2904 if(!fio.Fopen(s, FILEIO_READ_BINARY)) return 0;
2905 blocks = fio.Fread(ptr, size, 1);
2908 return blocks * size;
2912 void DISPLAY::initialize()
2916 memset(io_w_latch, 0xff, sizeof(io_w_latch));
2917 screen_update_flag = true;
2918 memset(gvram, 0x00, sizeof(gvram));
2919 vram_wrote_shadow = false;
2920 memset(gvram_shadow, 0x00, sizeof(gvram_shadow));
2921 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
2922 for(i = 0; i < 411; i++) vram_draw_table[i] = false;
2924 memset(console_ram, 0x00, sizeof(console_ram));
2925 memset(work_ram, 0x00, sizeof(work_ram));
2926 memset(shared_ram, 0x00, sizeof(shared_ram));
2927 memset(subsys_c, 0xff, sizeof(subsys_c));
2928 need_transfer_line = true;
2929 frame_skip_count_draw = 3;
2930 frame_skip_count_transfer = 3;
2932 diag_load_subrom_c = false;
2934 if(read_bios(_T(ROM_FM8_SUBSYSTEM), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2935 this->out_debug_log(_T("SUBSYSTEM ROM READING : %s"), diag_load_subrom_c ? "OK" : "NG");
2937 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_C), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2938 this->out_debug_log(_T("SUBSYSTEM ROM Type C READING : %s"), diag_load_subrom_c ? "OK" : "NG");
2940 #if defined(_FM77AV_VARIANTS)
2941 memset(subsys_a, 0xff, sizeof(subsys_a));
2942 memset(subsys_b, 0xff, sizeof(subsys_b));
2943 memset(subsys_cg, 0xff, sizeof(subsys_cg));
2944 memset(submem_hidden, 0x00, sizeof(submem_hidden));
2946 diag_load_subrom_a = false;
2947 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_A), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
2948 this->out_debug_log(_T("SUBSYSTEM ROM Type A READING : %s"), diag_load_subrom_a ? "OK" : "NG");
2950 diag_load_subrom_b = false;
2951 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_B), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
2952 this->out_debug_log(_T("SUBSYSTEM ROM Type B READING : %s"), diag_load_subrom_b ? "OK" : "NG");
2954 diag_load_subrom_cg = false;
2955 if(read_bios(_T(ROM_FM7_SUBSYSTEM_CG), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
2956 this->out_debug_log(_T("SUBSYSTEM CG ROM READING : %s"), diag_load_subrom_cg ? "OK" : "NG");
2957 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2958 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2959 memset(subsys_ram, 0x00, sizeof(subsys_ram));
2960 memset(submem_cgram, 0x00, sizeof(submem_cgram));
2961 memset(submem_console_av40, 0x00, sizeof(submem_console_av40));
2968 #if defined(_FM77AV_VARIANTS)
2970 apalette_index.d = 0;
2971 for(i = 0; i < 4096; i++) {
2972 analog_palette_r[i] = i & 0x0f0;
2973 analog_palette_g[i] = (i & 0xf00) >> 4;
2974 analog_palette_b[i] = (i & 0x00f) << 4;
2976 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
2979 for(i = 0; i < 8; i++) set_dpalette(i, i);
2980 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
2981 //#if defined(_FM77AV_VARIANTS)
2982 hblank_event_id = -1;
2983 hdisp_event_id = -1;
2984 vsync_event_id = -1;
2985 vstart_event_id = -1;
2992 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
2993 is_cyclesteal = true;
2995 is_cyclesteal = false;
2997 multimode_accessmask = multimode_dispmask = 0;
2998 for(i = 0; i < 4; i++) {
2999 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
3000 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
3003 prev_clock = SUBCLOCK_NORMAL;
3007 key_firq_req = false; //firq_mask = true;
3008 frame_skip_count_transfer = 3;
3009 frame_skip_count_draw = 3;
3010 #if !defined(FIXED_FRAMEBUFFER_SIZE)
3011 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
3013 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
3015 emu->set_vm_screen_lines(200);
3016 #if defined(_FM77AV40SX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3017 mode400line = false;
3019 #elif defined(_FM77L4)
3020 mode400line = false;
3023 palette_changed = true;
3024 //#if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
3025 //register_vline_event(this);
3026 register_frame_event(this);
3028 setup_display_mode();
3031 void DISPLAY::release()
3035 #define STATE_VERSION 8
3036 void DISPLAY::save_state(FILEIO *state_fio)
3038 state_fio->FputUint32_BE(STATE_VERSION);
3039 state_fio->FputInt32_BE(this_device_id);
3040 this->out_debug_log(_T("Save State: DISPLAY : id=%d ver=%d\n"), this_device_id, STATE_VERSION);
3044 state_fio->FputInt32_BE(clr_count);
3045 state_fio->FputBool(halt_flag);
3046 state_fio->FputInt32_BE(active_page);
3047 state_fio->FputBool(sub_busy);
3048 state_fio->FputBool(crt_flag);
3049 state_fio->FputBool(vram_wrote);
3050 state_fio->FputBool(is_cyclesteal);
3052 state_fio->FputBool(clock_fast);
3054 #if defined(_FM77AV_VARIANTS)
3055 state_fio->FputBool(subcpu_resetreq);
3056 state_fio->FputBool(power_on_reset);
3058 state_fio->FputBool(cancel_request);
3059 state_fio->FputBool(key_firq_req);
3061 state_fio->FputInt32_BE(display_mode);
3062 state_fio->FputUint32_BE(prev_clock);
3065 state_fio->Fwrite(dpalette_data, sizeof(dpalette_data), 1);
3066 state_fio->FputUint8(multimode_accessmask);
3067 state_fio->FputUint8(multimode_dispmask);
3069 state_fio->FputUint32_BE(offset_point);
3070 #if defined(_FM77AV_VARIANTS)
3071 state_fio->FputUint32_BE(offset_point_bank1);
3073 for(i = 0; i < 2; i++) {
3074 state_fio->FputUint32_BE(tmp_offset_point[i].d);
3075 state_fio->FputBool(offset_changed[i]);
3077 state_fio->FputBool(offset_77av);
3078 state_fio->FputBool(diag_load_subrom_c);
3081 state_fio->Fwrite(io_w_latch, sizeof(io_w_latch), 1);
3082 state_fio->Fwrite(console_ram, sizeof(console_ram), 1);
3083 state_fio->Fwrite(work_ram, sizeof(work_ram), 1);
3084 state_fio->Fwrite(shared_ram, sizeof(shared_ram), 1);
3085 state_fio->Fwrite(subsys_c, sizeof(subsys_c), 1);
3086 state_fio->Fwrite(gvram, sizeof(gvram), 1);
3087 state_fio->Fwrite(gvram_shadow, sizeof(gvram_shadow), 1);
3089 #if defined(_FM77_VARIANTS)
3090 state_fio->FputBool(kanjisub);
3091 state_fio->FputUint16_BE(kanjiaddr.w.l);
3092 # if defined(_FM77L4)
3093 state_fio->FputBool(mode400line);
3094 state_fio->FputBool(stat_400linecard);
3096 #elif defined(_FM77AV_VARIANTS)
3097 state_fio->FputBool(kanjisub);
3098 state_fio->FputUint16_BE(kanjiaddr.w.l);
3100 state_fio->FputBool(mode320);
3101 state_fio->FputInt32_BE(cgrom_bank);
3102 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3103 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3104 state_fio->FputInt32_BE(vram_bank);
3107 state_fio->FputUint32_BE(displine);
3108 state_fio->FputUint8(subrom_bank);
3109 state_fio->FputUint8(subrom_bank_using);
3111 state_fio->FputBool(nmi_enable);
3112 state_fio->FputBool(use_alu);
3114 state_fio->FputUint8(apalette_index.b.l);
3115 state_fio->FputUint8(apalette_index.b.h);
3116 state_fio->Fwrite(analog_palette_r, sizeof(analog_palette_r), 1);
3117 state_fio->Fwrite(analog_palette_g, sizeof(analog_palette_g), 1);
3118 state_fio->Fwrite(analog_palette_b, sizeof(analog_palette_b), 1);
3121 state_fio->FputBool(diag_load_subrom_a);
3122 state_fio->FputBool(diag_load_subrom_b);
3123 state_fio->FputBool(diag_load_subrom_cg);
3125 state_fio->Fwrite(subsys_a, sizeof(subsys_a), 1);
3126 state_fio->Fwrite(subsys_b, sizeof(subsys_b), 1);
3127 state_fio->Fwrite(subsys_cg, sizeof(subsys_cg), 1);
3128 state_fio->Fwrite(submem_hidden, sizeof(submem_hidden), 1);
3129 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3130 state_fio->FputBool(mode400line);
3131 state_fio->FputBool(mode256k);
3133 state_fio->FputBool(monitor_ram);
3134 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3135 state_fio->FputUint16_BE(window_low);
3136 state_fio->FputUint16_BE(window_high);
3137 state_fio->FputUint16_BE(window_xbegin);
3138 state_fio->FputUint16_BE(window_xend);
3139 state_fio->FputBool(window_opened);
3141 state_fio->FputBool(kanji_level2);
3143 state_fio->FputUint8(vram_active_block);
3144 state_fio->FputUint8(vram_display_block);
3145 state_fio->FputUint8(console_ram_bank);
3146 state_fio->FputBool(ram_protect);
3148 state_fio->FputUint32_BE(cgram_bank);
3149 state_fio->Fwrite(subsys_ram, sizeof(subsys_ram), 1);
3150 state_fio->Fwrite(submem_cgram, sizeof(submem_cgram), 1);
3151 state_fio->Fwrite(submem_console_av40, sizeof(submem_console_av40), 1);
3157 state_fio->FputInt32_BE(nmi_event_id);
3158 //#if defined(_FM77AV_VARIANTS)
3159 state_fio->FputInt32_BE(hblank_event_id);
3160 state_fio->FputInt32_BE(hdisp_event_id);
3161 state_fio->FputInt32_BE(vsync_event_id);
3162 state_fio->FputInt32_BE(vstart_event_id);
3164 state_fio->FputBool(firq_mask);
3165 state_fio->FputBool(vram_accessflag);
3167 state_fio->FputInt8(display_page);
3168 state_fio->FputInt8(display_page_bak);
3170 state_fio->FputBool(vblank);
3171 state_fio->FputBool(vsync);
3172 state_fio->FputBool(hblank);
3173 state_fio->FputInt32_BE(vblank_count);
3177 bool DISPLAY::load_state(FILEIO *state_fio)
3180 uint32_t version = state_fio->FgetUint32_BE();
3181 if(this_device_id != state_fio->FgetInt32_BE()) {
3184 this->out_debug_log(_T("Load State: DISPLAY : id=%d ver=%d\n"), this_device_id, version);
3189 clr_count = state_fio->FgetInt32_BE();
3190 halt_flag = state_fio->FgetBool();
3191 active_page = state_fio->FgetInt32_BE();
3192 sub_busy = state_fio->FgetBool();
3193 crt_flag = state_fio->FgetBool();
3194 vram_wrote = state_fio->FgetBool();
3195 crt_flag_bak = true;
3196 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
3197 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
3198 is_cyclesteal = state_fio->FgetBool();
3200 clock_fast = state_fio->FgetBool();
3202 #if defined(_FM77AV_VARIANTS)
3203 subcpu_resetreq = state_fio->FgetBool();
3204 power_on_reset = state_fio->FgetBool();
3206 cancel_request = state_fio->FgetBool();
3207 key_firq_req = state_fio->FgetBool();
3209 display_mode = state_fio->FgetInt32_BE();
3210 prev_clock = state_fio->FgetUint32_BE();
3213 for(addr = 0; addr < 8; addr++) set_dpalette(addr, addr);
3215 state_fio->Fread(dpalette_data, sizeof(dpalette_data), 1);
3216 for(addr = 0; addr < 8; addr++) set_dpalette(addr, dpalette_data[addr]);
3217 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3219 multimode_accessmask = state_fio->FgetUint8();
3220 multimode_dispmask = state_fio->FgetUint8();
3221 for(i = 0; i < 4; i++) {
3222 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
3223 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
3226 offset_point = state_fio->FgetUint32_BE();
3227 #if defined(_FM77AV_VARIANTS)
3228 offset_point_bank1 = state_fio->FgetUint32_BE();
3230 for(i = 0; i < 2; i++) {
3231 tmp_offset_point[i].d = state_fio->FgetUint32_BE();
3232 offset_changed[i] = state_fio->FgetBool();
3234 offset_77av = state_fio->FgetBool();
3235 diag_load_subrom_c = state_fio->FgetBool();
3237 state_fio->Fread(io_w_latch, sizeof(io_w_latch), 1);
3238 state_fio->Fread(console_ram, sizeof(console_ram), 1);
3239 state_fio->Fread(work_ram, sizeof(work_ram), 1);
3240 state_fio->Fread(shared_ram, sizeof(shared_ram), 1);
3241 state_fio->Fread(subsys_c, sizeof(subsys_c), 1);
3242 state_fio->Fread(gvram, sizeof(gvram), 1);
3243 state_fio->Fread(gvram_shadow, sizeof(gvram_shadow), 1);
3244 #if defined(_FM77_VARIANTS)
3245 kanjisub = state_fio->FgetBool();
3247 kanjiaddr.w.l = state_fio->FgetUint16_BE();
3248 # if defined(_FM77L4)
3249 mode400line = state_fio->FgetBool();
3250 stat_400linecard = state_fio->FgetBool();
3252 #elif defined(_FM77AV_VARIANTS)
3253 kanjisub = state_fio->FgetBool();
3255 kanjiaddr.w.l = state_fio->FgetUint16_BE();
3257 mode320 = state_fio->FgetBool();
3258 cgrom_bank = state_fio->FgetInt32_BE();
3259 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3260 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3261 vram_bank = state_fio->FgetInt32_BE();
3263 screen_update_flag = true;
3264 displine = state_fio->FgetUint32_BE();
3265 subrom_bank = state_fio->FgetUint8();
3266 subrom_bank_using = state_fio->FgetUint8();
3268 nmi_enable = state_fio->FgetBool();
3269 use_alu = state_fio->FgetBool();
3271 apalette_index.b.l = state_fio->FgetUint8();
3272 apalette_index.b.h = state_fio->FgetUint8();
3274 state_fio->Fread(analog_palette_r, sizeof(analog_palette_r), 1);
3275 state_fio->Fread(analog_palette_g, sizeof(analog_palette_g), 1);
3276 state_fio->Fread(analog_palette_b, sizeof(analog_palette_b), 1);
3277 for(i = 0; i < 4096; i++) calc_apalette(i);
3278 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
3280 diag_load_subrom_a = state_fio->FgetBool();
3281 diag_load_subrom_b = state_fio->FgetBool();
3282 diag_load_subrom_cg = state_fio->FgetBool();
3284 state_fio->Fread(subsys_a, sizeof(subsys_a), 1);
3285 state_fio->Fread(subsys_b, sizeof(subsys_b), 1);
3286 state_fio->Fread(subsys_cg, sizeof(subsys_cg), 1);
3287 state_fio->Fread(submem_hidden, sizeof(submem_hidden), 1);
3289 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3290 mode400line = state_fio->FgetBool();
3291 mode256k = state_fio->FgetBool();
3293 monitor_ram = state_fio->FgetBool();
3294 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3295 window_low = state_fio->FgetUint16_BE();
3296 window_high = state_fio->FgetUint16_BE();
3297 window_xbegin = state_fio->FgetUint16_BE();
3298 window_xend = state_fio->FgetUint16_BE();
3299 window_opened = state_fio->FgetBool();
3301 kanji_level2 = state_fio->FgetBool();
3303 vram_active_block = state_fio->FgetUint8();
3304 vram_display_block = state_fio->FgetUint8();
3305 console_ram_bank = state_fio->FgetUint8();
3306 ram_protect = state_fio->FgetBool();
3308 cgram_bank = state_fio->FgetUint32_BE();
3309 state_fio->Fread(subsys_ram, sizeof(subsys_ram), 1);
3310 state_fio->Fread(submem_cgram, sizeof(submem_cgram), 1);
3311 state_fio->Fread(submem_console_av40, sizeof(submem_console_av40), 1);
3314 palette_changed = true;
3315 vram_wrote_shadow = true; // Force Draw
3316 this->draw_screen();
3317 if(version == 1) return true;
3319 if(version >= 2) { //V2
3320 nmi_event_id = state_fio->FgetInt32_BE();
3321 //#if defined(_FM77AV_VARIANTS)
3322 hblank_event_id = state_fio->FgetInt32_BE();
3323 hdisp_event_id = state_fio->FgetInt32_BE();
3324 vsync_event_id = state_fio->FgetInt32_BE();
3325 vstart_event_id = state_fio->FgetInt32_BE();
3327 display_page = state_fio->FgetInt8();
3328 display_page_bak = state_fio->FgetInt8();
3330 vblank = state_fio->FgetBool();
3331 vsync = state_fio->FgetBool();
3332 hblank = state_fio->FgetBool();
3333 vblank_count = state_fio->FgetInt32_BE();
3335 firq_mask = state_fio->FgetBool();
3336 vram_accessflag = state_fio->FgetBool();
3337 frame_skip_count_draw = 3;
3338 frame_skip_count_transfer = 3;
3339 need_transfer_line = true;
3341 if(version == STATE_VERSION) return true;
3342 setup_display_mode();