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 #include "../hd46505.h"
19 #include "fm7_mainio.h"
20 #include "./fm7_keyboard.h"
21 #include "./kanjirom.h"
23 DISPLAY::DISPLAY(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
28 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
31 #elif defined(_FM77_VARIANTS)
34 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
35 kanjisub = false; // fix by Ryu Takegami
37 #if defined(_FM77AV_VARIANTS)
43 for(int i = 0; i < 256; i++) {
44 uint16_t n = (uint16_t)i;
45 for(int j = 0; j < 8; j++) {
46 bit_trans_table_0[i][j] = n & 0x80;
47 bit_trans_table_1[i][j] = ((n & 0x80) != 0) ? 0x40 : 0;
48 bit_trans_table_2[i][j] = ((n & 0x80) != 0) ? 0x20 : 0;
49 bit_trans_table_3[i][j] = ((n & 0x80) != 0) ? 0x10 : 0;
50 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
51 bit_trans_table_4[i][j] = ((n & 0x80) != 0) ? 0x08 : 0;
52 bit_trans_table_5[i][j] = ((n & 0x80) != 0) ? 0x04 : 0;
59 #if defined(USE_GREEN_DISPLAY)
60 use_green_monitor = false;
63 set_device_name(_T("DISPLAY SUBSYSTEM"));
71 void DISPLAY::reset_some_devices()
75 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
76 call_write_signal(mainio, SIG_FM7_SUB_HALT, 0x00, 0xff);
79 palette_changed = true;
80 multimode_accessmask = 0;
81 multimode_dispmask = 0;
82 for(i = 0; i < 4; i++) {
83 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
84 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
86 //firq_mask = false; // 20180215 Thanks to Ryu takegami.
87 //cancel_request = false;
88 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
89 switch(config.cpu_type){
98 prev_clock = SUBCLOCK_NORMAL;
100 prev_clock = SUBCLOCK_SLOW;
105 for(i = 0; i < 2; i++) {
106 offset_changed[i] = true;
107 tmp_offset_point[i].d = 0;
110 vram_wrote_shadow = true;
111 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
112 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
116 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
123 if(hblank_event_id >= 0) cancel_event(this, hblank_event_id);
124 if(hdisp_event_id >= 0) cancel_event(this, hdisp_event_id);
126 if(vsync_event_id >= 0) cancel_event(this, vsync_event_id);
127 if(vstart_event_id >= 0) cancel_event(this, vstart_event_id);
128 hblank_event_id = -1;
131 vstart_event_id = -1;
133 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
134 usec = 0.33 * 1000.0;
135 vm->set_vm_frame_rate(55.40);
137 usec = 0.51 * 1000.0;
138 vm->set_vm_frame_rate(FRAMES_PER_SEC);
141 //register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
142 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
143 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0xff, 0xff);
146 display_page_bak = 0;
148 #if defined(_FM77AV_VARIANTS)
150 offset_point_bank1 = 0;
152 subcpu_resetreq = false;
153 subrom_bank_using = subrom_bank;
158 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
160 vram_display_block = 0;
161 vram_active_block = 0;
163 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
168 window_opened = false;
173 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
174 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
175 call_write_signal(alu, SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400: 200, 0xffff);
176 call_write_signal(alu, SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xffffffff : 0, 0xffffffff);
178 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
179 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
180 call_write_signal(alu, SIG_ALU_400LINE, 0, 0xffffffff);
182 call_write_signal(alu, SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
183 call_write_signal(alu, SIG_ALU_PLANES, 3, 3);
185 for(i = 0; i < 8; i++) set_dpalette(i, i);
186 #if defined(USE_GREEN_DISPLAY)
187 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
189 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
190 //do_firq(!firq_mask && key_firq_req);
192 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
193 //kanjisub = false; // Fixed by Ryu takegami
194 kanjiaddr.d = 0x00000000;
195 # if defined(_FM77L4)
197 stat_400linecard = false;
202 frame_skip_count_draw = 3;
203 frame_skip_count_transfer = 3;
204 need_transfer_line = true;
205 setup_display_mode();
210 void DISPLAY::reset()
215 vram_accessflag = true;
216 display_mode = DISPLAY_MODE_8_200L;
218 crt_flag = false; // Fixed by Ryu Takegami
219 screen_update_flag = true;
220 crt_flag_bak = false;
221 cancel_request = false;
222 #if defined(_FM77AV_VARIANTS)
224 apalette_index.d = 0;
225 for(i = 0; i < 4096; i++) {
226 analog_palette_r[i] = i & 0x0f0;
227 analog_palette_g[i] = (i & 0xf00) >> 4;
228 analog_palette_b[i] = (i & 0x00f) << 4;
230 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
234 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
241 #elif defined(_FM77L4)
243 stat_400linecard = false;
247 text_width40 = false;
252 text_start_addr.d = 0x0000;
260 text_scroll_count = 0;
266 uint8_t *regs = l4crtc->get_regs();
267 display_mode = DISPLAY_MODE_1_400L;
268 if(event_id_l4_cursor_blink >= 0) {
269 cancel_event(this, event_id_l4_cursor_blink);
271 if(event_id_l4_text_blink >= 0) {
272 cancel_event(this, event_id_l4_text_blink);
274 event_id_l4_cursor_blink = -1;
275 event_id_l4_text_blink = -1;
277 usec = ((regs[10] & 0x20) == 0) ? 160.0 : 320.0;
278 usec = usec * 1000.0;
279 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
280 usec = 160.0 * 1000.0;
281 register_event(this, EVENT_FM7SUB_TEXT_BLINK, true, usec, &event_id_l4_cursor_blink);
284 //memset(crtc_regs, 0x00, sizeof(crtc_regs));
287 #if !defined(FIXED_FRAMEBUFFER_SIZE)
288 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
290 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
292 emu->set_vm_screen_lines(200);
294 reset_some_devices();
296 #if defined(_FM77AV_VARIANTS)
297 power_on_reset = false;
298 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
302 for(i = 0; i < 8; i++) set_dpalette(i, i);
305 #if defined(USE_GREEN_DISPLAY) && defined(USE_MONITOR_TYPE)
306 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
307 switch(config.monitor_type) {
308 case FM7_MONITOR_GREEN:
309 use_green_monitor = true;
311 case FM7_MONITOR_STANDARD:
313 use_green_monitor = false;
317 //use_green_monitor = false;
321 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
324 if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
325 register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
328 key_firq_req = false;
333 void DISPLAY::reset_subcpu(bool _check_firq)
335 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0, 1);
336 call_write_signal(subcpu, SIG_CPU_BUSREQ, 0, 1);
339 do_firq(!firq_mask && key_firq_req);
342 void DISPLAY::setup_display_mode(void)
344 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
345 if(display_mode == DISPLAY_MODE_8_400L) {
346 page_offset = 0x0000;
347 pagemod_mask = 0x18000;
349 } else if(display_mode == DISPLAY_MODE_256k) {
350 if(active_page != 0) {
351 page_offset = 0xc000;
353 page_offset = 0x0000;
355 pagemod_mask = 0xe000;
357 } else if(display_mode == DISPLAY_MODE_4096) {
358 if(active_page != 0) {
359 page_offset = 0xc000;
361 page_offset = 0x0000;
363 pagemod_mask = 0xe000;
366 if(active_page != 0) {
367 page_offset = 0xc000;
369 page_offset = 0x0000;
371 pagemod_mask = 0xc000;
374 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
375 if(vram_active_block != 0) page_offset += 0x18000;
377 #elif defined(_FM77AV_VARIANTS)
380 pagemod_mask = 0xe000;
381 } else { // 640x200, 8colors
383 pagemod_mask = 0xc000;
385 if(active_page != 0) {
386 page_offset = 0xc000;
388 page_offset = 0x0000;
390 #elif defined(_FM77L4)
391 if(display_mode == DISPLAY_MODE_1_400L) {
393 pagemod_mask = 0x0000;
394 page_offset = 0x0000;
395 } else { // 640x200, 8colors
397 pagemod_mask = 0xc000;
398 page_offset = 0x0000;
400 page_offset = 0x0000;
402 page_offset = 0x0000;
403 pagemod_mask = 0xc000;
408 void DISPLAY::update_config()
414 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
420 * Vram accessing functions moved to vram.cpp .
423 void DISPLAY::do_irq(bool flag)
425 call_write_signal(subcpu, SIG_CPU_IRQ, flag ? 1: 0, 1);
428 void DISPLAY::do_firq(bool flag)
430 call_write_signal(subcpu, SIG_CPU_FIRQ, flag ? 1: 0, 1);
433 void DISPLAY::do_nmi(bool flag)
435 #if defined(_FM77AV_VARIANTS)
436 if(!nmi_enable) flag = false;
438 call_write_signal(subcpu, SIG_CPU_NMI, flag ? 1 : 0, 1);
441 void DISPLAY::set_multimode(uint8_t val)
444 multimode_accessmask = val & 0x07;
445 multimode_dispmask = (val & 0x70) >> 4;
446 for(int i = 0; i < 4; i++) {
447 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
448 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
451 # if defined(_FM77AV_VARIANTS)
452 call_write_signal(alu, SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
457 uint8_t DISPLAY::get_multimode(void)
463 val = multimode_accessmask & 0x07;
464 val |= ((multimode_dispmask << 4) & 0x70);
470 uint8_t DISPLAY::get_cpuaccessmask(void)
472 return multimode_accessmask & 0x07;
475 void DISPLAY::set_dpalette(uint32_t addr, uint8_t val)
479 dpalette_data[addr] = val | 0xf8; //0b11111000;
480 b = ((val & 0x01) != 0x00)? 255 : 0x00;
481 r = ((val & 0x02) != 0x00)? 255 : 0x00;
482 g = ((val & 0x04) != 0x00)? 255 : 0x00;
484 dpalette_pixel_tmp[addr] = RGB_COLOR(r, g, b);
485 #if defined(USE_GREEN_DISPLAY)
486 static const scrntype_t colortable[8] = {0, 48, 70, 100, 140, 175, 202, 255};
487 g = colortable[val & 0x07];
488 b = r = ((val & 0x07) > 4) ? 48 : 0;
489 dpalette_green_tmp[addr] = RGB_COLOR(r, g, b);
491 palette_changed = true;
494 uint8_t DISPLAY::get_dpalette(uint32_t addr)
502 data = dpalette_data[addr];
507 void DISPLAY::halt_subcpu(void)
509 //call_write_signal(subcpu, SIG_CPU_BUSREQ, 0x01, 0x01);
510 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0x01, 0x01);
513 void DISPLAY::go_subcpu(void)
515 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0x00, 0x01);
518 void DISPLAY::enter_display(void)
523 subclock = SUBCLOCK_NORMAL;
525 subclock = SUBCLOCK_SLOW;
527 if(!(is_cyclesteal) && (vram_accessflag)) {
528 subclock = subclock / 3;
530 if(prev_clock != subclock) {
531 vm->set_cpu_clock(subcpu, subclock);
533 prev_clock = subclock;
537 void DISPLAY::leave_display(void)
541 void DISPLAY::halt_subsystem(void)
547 void DISPLAY::restart_subsystem(void)
550 #if defined(_FM77AV_VARIANTS)
551 if(subcpu_resetreq) {
552 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
553 reset_some_devices();
554 power_on_reset = true;
562 void DISPLAY::set_crtflag(void)
569 void DISPLAY::reset_crtflag(void)
576 uint8_t DISPLAY::acknowledge_irq(void)
578 cancel_request = false;
584 uint8_t DISPLAY::beep(void)
586 call_write_signal(mainio, FM7_MAINIO_BEEP, 0x01, 0x01);
587 return 0xff; // True?
592 uint8_t DISPLAY::attention_irq(void)
594 call_write_signal(mainio, FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
599 void DISPLAY::set_cyclesteal(uint8_t val)
602 # if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
606 is_cyclesteal = true;
608 is_cyclesteal = false;
615 void DISPLAY::setup_400linemode(uint8_t val)
619 cursor_lsb = ((val & 0x10) != 0);
620 text_width40 = ((val & 0x08) != 0);
621 workram_l4 = ((val & 0x04) != 0);
622 bool tmpmode = ((val & 0x02) != 0);
623 if(tmpmode != mode400line) {
624 int oldmode = display_mode;
625 mode400line = tmpmode;
626 if(mode400line && stat_400linecard) {
627 display_mode = DISPLAY_MODE_1_400L;
629 display_mode = DISPLAY_MODE_8_200L;
631 if(oldmode != display_mode) {
633 if(display_mode == DISPLAY_MODE_1_400L) {
634 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
635 for(int y = 0; y < 400; y++) {
636 pp = emu->get_screen_buffer(y);
637 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
641 vm->set_vm_frame_rate(FRAMES_PER_SEC);
642 #if !defined(FIXED_FRAMEBUFFER_SIZE)
643 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
644 for(int y = 0; y < 200; y++) {
645 pp = emu->get_screen_buffer(y);
646 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
649 for(int y = 0; y < 400; y++) {
650 pp = emu->get_screen_buffer(y);
651 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
656 setup_display_mode();
664 uint8_t DISPLAY::set_vramaccess(void)
666 vram_accessflag = true;
672 void DISPLAY::reset_vramaccess(void)
674 vram_accessflag = false;
679 uint8_t DISPLAY::reset_subbusy(void)
686 void DISPLAY::set_subbusy(void)
692 #if defined(_FM77AV_VARIANTS)
694 void DISPLAY::alu_write_cmdreg(uint32_t val)
696 call_write_data8(alu, ALU_CMDREG, val);
697 if((val & 0x80) != 0) {
705 void DISPLAY::alu_write_logical_color(uint8_t val)
707 uint32_t data = (uint32_t)val;
708 call_write_data8(alu, ALU_LOGICAL_COLOR, data);
712 void DISPLAY::alu_write_mask_reg(uint8_t val)
714 uint32_t data = (uint32_t)val;
715 call_write_data8(alu, ALU_WRITE_MASKREG, data);
719 void DISPLAY::alu_write_cmpdata_reg(int addr, uint8_t val)
721 uint32_t data = (uint32_t)val;
723 call_write_data8(alu, ALU_CMPDATA_REG + addr, data);
727 void DISPLAY::alu_write_disable_reg(uint8_t val)
729 uint32_t data = (uint32_t)val;
730 call_write_data8(alu, ALU_BANK_DISABLE, data);
734 void DISPLAY::alu_write_tilepaint_data(uint32_t addr, uint8_t val)
736 uint32_t data = (uint32_t)val;
739 call_write_data8(alu, ALU_TILEPAINT_B, data);
742 call_write_data8(alu, ALU_TILEPAINT_R, data);
745 call_write_data8(alu, ALU_TILEPAINT_G, data);
748 //call_write_data8(alu, ALU_TILEPAINT_L, 0xff);
754 void DISPLAY::alu_write_offsetreg_hi(uint8_t val)
756 call_write_data8(alu, ALU_OFFSET_REG_HIGH, val & 0x7f);
760 void DISPLAY::alu_write_offsetreg_lo(uint8_t val)
762 call_write_data8(alu, ALU_OFFSET_REG_LO, val);
766 void DISPLAY::alu_write_linepattern_hi(uint8_t val)
768 call_write_data8(alu, ALU_LINEPATTERN_REG_HIGH, val);
772 void DISPLAY::alu_write_linepattern_lo(uint8_t val)
774 call_write_data8(alu, ALU_LINEPATTERN_REG_LO, val);
778 void DISPLAY::alu_write_line_position(int addr, uint8_t val)
780 uint32_t data = (uint32_t)val;
783 call_write_data8(alu, ALU_LINEPOS_START_X_HIGH, data & 0x03);
786 call_write_data8(alu, ALU_LINEPOS_START_X_LOW, data);
789 call_write_data8(alu, ALU_LINEPOS_START_Y_HIGH, data & 0x01);
792 call_write_data8(alu, ALU_LINEPOS_START_Y_LOW, data);
795 call_write_data8(alu, ALU_LINEPOS_END_X_HIGH, data & 0x03);
798 call_write_data8(alu, ALU_LINEPOS_END_X_LOW, data);
801 call_write_data8(alu, ALU_LINEPOS_END_Y_HIGH, data & 0x01);
804 call_write_data8(alu, ALU_LINEPOS_END_Y_LOW, data);
810 uint8_t DISPLAY::get_miscreg(void)
815 if(!hblank) ret |= 0x80;
816 if(vsync) ret |= 0x04;
817 if(alu->read_signal(SIG_ALU_BUSYSTAT) == 0) ret |= 0x10;
818 if(power_on_reset) ret |= 0x01;
823 void DISPLAY::set_miscreg(uint8_t val)
825 int old_display_page = display_page;
827 nmi_enable = ((val & 0x80) == 0) ? true : false;
828 if(!nmi_enable) do_nmi(false);
830 if((val & 0x40) == 0) {
835 if(display_page != old_display_page) {
838 active_page = ((val & 0x20) == 0) ? 0 : 1;
839 if((val & 0x04) == 0) {
844 cgrom_bank = val & 0x03;
845 setup_display_mode();
849 void DISPLAY::set_monitor_bank(uint8_t var)
851 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
852 if((var & 0x04) != 0){
858 subrom_bank = var & 0x03;
861 subcpu_resetreq = false;
862 power_on_reset = true;
863 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
864 reset_some_devices();
867 subcpu_resetreq = true;
873 void DISPLAY::set_apalette_index_hi(uint8_t val)
875 apalette_index.b.h = val & 0x0f;
879 void DISPLAY::set_apalette_index_lo(uint8_t val)
881 apalette_index.b.l = val;
884 void DISPLAY::calc_apalette(uint16_t idx)
888 g = analog_palette_g[idx];
889 r = analog_palette_r[idx];
890 b = analog_palette_b[idx];
891 if(g != 0) g |= 0x0f;
892 if(r != 0) r |= 0x0f;
893 if(b != 0) b |= 0x0f;
894 analog_palette_pixel_tmp[idx] = RGB_COLOR(r, g, b);
898 void DISPLAY::set_apalette_b(uint8_t val)
902 index = apalette_index.w.l;
903 tmp = (val & 0x0f) << 4;
904 if(analog_palette_b[index] != tmp) {
905 analog_palette_b[index] = tmp;
906 calc_apalette(index);
907 palette_changed = true;
912 void DISPLAY::set_apalette_r(uint8_t val)
916 index = apalette_index.w.l;
917 tmp = (val & 0x0f) << 4;
918 if(analog_palette_r[index] != tmp) {
919 analog_palette_r[index] = tmp;
920 calc_apalette(index);
921 palette_changed = true;
926 void DISPLAY::set_apalette_g(uint8_t val)
930 index = apalette_index.w.l;
931 tmp = (val & 0x0f) << 4;
932 if(analog_palette_g[index] != tmp) {
933 analog_palette_g[index] = tmp;
934 calc_apalette(index);
935 palette_changed = true;
939 #endif // _FM77AV_VARIANTS
942 void DISPLAY::copy_vram_blank_area(void)
946 void DISPLAY::copy_vram_per_line(int begin, int end)
955 uint32_t src_offset_d1;
956 uint32_t src_offset_d2;
957 uint32_t src_offset_d;
962 uint32_t addr_d1, addr_d2;
966 //int dline = (int)displine - 1;
967 int dline = (int)displine;
969 if((begin < 0) || (begin > 4)) return;
970 if((end < 0) || (end > 4)) return;
971 if(begin > end) return;
972 if(dline < 0) return;
974 sectors = end - begin + 1;
976 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)){
977 if(dline >= 400) return;
979 if(dline >= 200) return;
981 #if defined(_FM77AV_VARIANTS)
982 yoff_d1 = offset_point;
983 yoff_d2 = offset_point_bank1;
984 if(display_mode == DISPLAY_MODE_4096) {
985 src_offset = dline * 40 + begin * 8;
986 sectors = sectors * 8;
987 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
990 addr_d1 = (src_offset + yoff_d1) & 0x1fff;
991 addr_d2 = (src_offset + yoff_d2) & 0x1fff;
992 bytes_d1 = 0x2000 - addr_d1;
993 bytes_d2 = 0x2000 - addr_d2;
994 for(k = 0; k < pages; k++) {
996 for(i = 0; i < 3; i++) {
997 for(j = 0; j < 2; j++) {
998 uint32_t _addr_base = src_base + src_offset + poff;
999 if(bytes_d1 < sectors) {
1000 my_memcpy(&gvram_shadow[_addr_base],
1001 &gvram[addr_d1 + src_base + poff],
1003 my_memcpy(&gvram_shadow[_addr_base + bytes_d1],
1004 &gvram[src_base + poff],
1005 sectors - bytes_d1);
1007 my_memcpy(&gvram_shadow[_addr_base],
1008 &gvram[addr_d1 + src_base + poff],
1011 _addr_base += 0xc000;
1012 if(bytes_d2 < sectors) {
1013 my_memcpy(&gvram_shadow[_addr_base],
1014 &gvram[addr_d2 + src_base + poff + 0xc000],
1016 my_memcpy(&gvram_shadow[_addr_base + bytes_d2],
1017 &gvram[src_base + poff + 0xc000],
1018 sectors - bytes_d2);
1020 my_memcpy(&gvram_shadow[_addr_base],
1021 &gvram[addr_d2 + src_base + poff + 0xc000],
1026 src_base = (i + 1) * 0x4000;
1030 vram_draw_table[dline] = true;
1031 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1033 # if defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV40)
1034 else if(display_mode == DISPLAY_MODE_256k) {
1035 src_offset = dline * 40 + begin * 8;
1036 sectors = sectors * 8;
1038 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1040 #elif defined(_FM77AV40)
1045 src_offset_d1 = (src_offset + yoff_d1) & 0x1fff;
1046 src_offset_d2 = (src_offset + yoff_d2) & 0x1fff;
1047 bytes_d1 = 0x2000 - ((src_offset + yoff_d1) & 0x1fff);
1048 bytes_d2 = 0x2000 - ((src_offset + yoff_d2) & 0x1fff);
1049 for(k = 0; k < pages; k++) {
1050 for(i = 0; i < 3; i++) {
1051 for(j = 0; j < 2; j++) {
1053 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
1054 src_offset_d = src_offset_d1;
1057 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
1058 src_offset_d = src_offset_d2;
1061 if(bytes_d < sectors) {
1062 my_memcpy(&gvram_shadow[src_offset + src_base],
1063 &gvram[src_offset_d + src_base],
1065 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1069 my_memcpy(&gvram_shadow[src_offset + src_base],
1070 &gvram[src_offset_d + src_base],
1076 vram_draw_table[dline] = true;
1077 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1079 else if(display_mode == DISPLAY_MODE_8_400L) {
1080 src_offset = dline * 80 + begin * 16;
1081 sectors = sectors * 16;
1082 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1085 if(display_page_bak == 1) { // Is this dirty?
1090 yoff_d = (yoff_d << 1) & 0x7fff;
1091 src_offset_d = (src_offset + yoff_d) & 0x7fff;
1092 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
1093 for(i = 0; i < pages; i++) {
1094 for(j = 0; j < 3; j++) {
1095 src_base = i * 0x18000 + j * 0x8000;
1096 if(bytes_d < sectors) {
1098 my_memcpy(&gvram_shadow[src_offset + src_base],
1099 &gvram[src_offset_d + src_base],
1102 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1106 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1107 &gvram[src_offset_d + src_base],
1112 vram_draw_table[dline] = true;
1113 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1117 src_offset = dline * 80 + begin * 16;
1118 sectors = sectors * 16;
1119 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1121 #elif defined(_FM77AV40)
1123 #elif defined(_FM77AV_VARIANTS)
1129 src_offset_d1 = (src_offset + yoff_d1) & 0x3fff;
1130 src_offset_d2 = (src_offset + yoff_d2) & 0x3fff;
1131 bytes_d1 = 0x4000 - ((src_offset + yoff_d1) & 0x3fff);
1132 bytes_d2 = 0x4000 - ((src_offset + yoff_d2) & 0x3fff);
1133 for(i = 0; i < pages; i++) {
1135 src_offset_d = src_offset_d1;
1138 src_offset_d = src_offset_d2;
1142 for(j = 0; j < 3; j++) {
1143 if(bytes_d < sectors) {
1144 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1145 &gvram[src_offset_d + src_base + poff],
1147 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1148 &gvram[src_base + poff],
1151 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1152 &gvram[src_offset_d + src_base + poff],
1159 vram_draw_table[dline] = true;
1160 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1161 //vram_wrote_table[dline] = false;
1164 #if defined(_FM77L4)
1165 if(display_mode == DISPLAY_MODE_1_400L) {
1166 src_offset = dline * 80 + begin * 16;
1167 sectors = sectors * 16;
1168 yoff_d = (yoff_d1 << 1) & 0x7fff;
1169 src_offset_d = (src_offset + yoff_d) & 0x7fff;
1170 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
1171 if(bytes_d < sectors) {
1173 my_memcpy(&gvram_shadow[src_offset],
1174 &gvram[src_offset_d],
1177 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1181 my_memcpy(&gvram_shadow[src_offset + poff],
1182 &gvram[src_offset_d ],
1185 vram_draw_table[dline] = true;
1186 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1191 src_offset = dline * 80 + begin * 16;
1192 sectors = sectors * 16;
1195 yoff_d = offset_point;
1196 src_offset_d = (src_offset + yoff_d) & 0x3fff;
1197 bytes_d = 0x4000 - ((src_offset + yoff_d) & 0x3fff);
1198 for(j = 0; j < 3; j++) {
1199 src_base = j * 0x4000;
1200 if(bytes_d < sectors) {
1201 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1202 &gvram[src_offset_d + src_base + poff],
1204 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1205 &gvram[src_base + poff],
1208 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1209 &gvram[src_offset_d + src_base + poff],
1213 vram_draw_table[dline] = true;
1214 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1215 //vram_wrote_table[dline] = false;
1221 void DISPLAY::copy_vram_all()
1223 #if defined(_FM77AV_VARIANTS)
1224 uint32_t yoff_d1 = offset_point;
1225 uint32_t yoff_d2 = offset_point_bank1;
1226 uint32_t src_offset_1, src_offset_2;
1228 if(display_mode == DISPLAY_MODE_4096) {
1229 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1234 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1235 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1236 for(int k = 0; k < pages; k++) {
1237 for(int i = 0; i < 3; i++) {
1238 for(int j = 0; j < 2; j++) {
1239 src_offset_1 = i * 0x4000 + j * 0x2000;
1240 src_offset_2 = src_offset_1 + 0xc000;
1241 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1242 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1243 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1244 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1250 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1251 else if(display_mode == DISPLAY_MODE_256k) {
1252 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1253 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1254 for(int i = 0; i < 3; i++) {
1255 for(int j = 0; j < 2; j++) {
1256 src_offset_1 = i * 0x4000 + j * 0x2000;
1257 src_offset_2 = src_offset_1 + 0xc000;
1258 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1259 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1260 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1261 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1265 for(int i = 0; i < 3; i++) {
1266 for(int j = 0; j < 2; j++) {
1267 src_offset_1 = i * 0x4000 + j * 0x2000;
1268 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1269 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1272 } else if(display_mode == DISPLAY_MODE_8_400L) {
1274 uint32_t yoff_d, bytes_d;
1275 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1278 if(display_page_bak == 1) { // Is this dirty?
1283 yoff_d = (yoff_d << 1) & 0x7fff;
1284 bytes_d = 0x8000 - yoff_d;
1285 for(int i = 0; i < pages; i++) {
1286 for(int j = 0; j < 3; j++) {
1287 uint32_t src_base = i * 0x18000 + j * 0x8000;
1288 my_memcpy(&gvram_shadow[src_base],
1289 &gvram[yoff_d + src_base],
1291 if(bytes_d < 0x8000) {
1292 my_memcpy(&gvram_shadow[bytes_d + src_base],
1301 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1303 #elif defined(_FM77AV40)
1308 uint32_t bytes_d1 = 0x4000 - (yoff_d1 & 0x3fff);
1309 uint32_t bytes_d2 = 0x4000 - (yoff_d2 & 0x3fff);
1310 uint32_t yoff_d, bytes_d;
1311 for(int k = 0; k < pages; k++) {
1312 yoff_d = ((k & 1) == 0) ? (yoff_d1 & 0x3fff) : (yoff_d2 & 0x3fff);
1313 bytes_d = ((k & 1) == 0) ? bytes_d1 : bytes_d2;
1314 for(int j = 0; j < 3; j++) {
1315 src_offset_1 = k * 0xc000 + j * 0x4000;
1316 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1317 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1322 # if defined(_FM77L4)
1323 if(display_mode == DISPLAY_MODE_1_400L) {
1324 uint32_t yoff_d = offset_point & 0x7fff;
1325 uint32_t bytes_d = 0x8000 - (offset_point & 0x7fff);
1326 my_memcpy(&gvram_shadow[0], &gvram[0 + yoff_d], bytes_d);
1327 my_memcpy(&gvram_shadow[0 + bytes_d], &gvram[0], 0x8000 - bytes_d);
1332 uint32_t yoff_d = offset_point & 0x3fff;
1333 uint32_t bytes_d = 0x4000 - (offset_point & 0x3fff);
1334 uint32_t src_offset_1;
1335 for(int j = 0; j < 3; j++) {
1336 src_offset_1 = j * 0x4000;
1337 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1338 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1344 // Timing values from XM7 . Thanks Ryu.
1345 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1346 void DISPLAY::event_callback_hdisp(void)
1351 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x02, 0xff);
1352 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1353 if(displine < 400) f = true;
1355 if(displine < 200) f = true;
1358 hdisp_event_id = -1;
1360 // DO ONLY WHEN SYNC-TO-HSYNC.
1361 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
1363 //copy_vram_per_line(0, 4);
1364 } else if(need_transfer_line) { // Not frame skip.
1367 for(int iii = 0; iii < 5 ; iii++) {
1368 if(vram_wrote_table[iii + displine * 5]) {
1369 if(begin < 0) begin = iii; // Check first.
1374 if(end < begin) end = begin;
1376 copy_vram_per_line(begin, end);
1377 // Prepare to next block.
1383 // Tail of this line.
1386 copy_vram_per_line(begin, end);
1390 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1391 register_event(this, EVENT_FM7SUB_HBLANK, 30.0, false, &hblank_event_id); // NEXT CYCLE_
1393 register_event(this, EVENT_FM7SUB_HBLANK, 39.5, false, &hblank_event_id); // NEXT CYCLE_
1401 void DISPLAY::event_callback_hblank(void)
1408 hblank_event_id = -1;
1410 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1411 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1412 if((displine < 400)) f = true;
1415 if((displine < 200)) f = true;
1419 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id);
1424 void DISPLAY::event_callback_vstart(void)
1431 display_page_bak = display_page;
1433 // Parameter from XM7/VM/display.c , thanks, Ryu.
1434 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1435 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x00, 0xff);
1437 if(vblank_count != 0) {
1438 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1439 usec = (0.98 + 16.4) * 1000.0;
1441 usec = (1.91 + 12.7) * 1000.0;
1443 register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
1445 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1446 usec = 930.0; // 939.0
1448 usec = 1840.0; // 1846.5
1450 vstart_event_id = -1;
1451 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
1452 //register_event(this, EVENT_FM7SUB_HBLANK, usec, false, &hdisp_event_id); // NEXT CYCLE_
1455 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1456 usec = 0.34 * 1000.0;
1458 usec = 1.52 * 1000.0;
1460 vsync_event_id = -1;
1461 hblank_event_id = -1;
1462 hdisp_event_id = -1;
1463 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1467 void DISPLAY::event_callback_vsync(void)
1473 //write_access_page = (write_access_page + 1) & 1;
1476 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1477 usec = 0.33 * 1000.0;
1479 usec = 0.51 * 1000.0;
1481 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x01, 0xff);
1482 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1483 //register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1485 if(palette_changed) {
1486 #if defined(_FM77AV_VARIANTS)
1487 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
1489 #if defined(USE_GREEN_DISPLAY)
1490 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
1492 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
1493 vram_wrote_shadow = true;
1494 for(int yy = 0; yy < 400; yy++) {
1495 vram_draw_table[yy] = true;
1497 palette_changed = false;
1499 // Transfer on VSYNC
1500 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) {
1504 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L))lines = 400;
1505 if(need_transfer_line) {
1506 if(vram_wrote) { // transfer all line
1507 for(displine = 0; displine < lines; displine++) {
1508 //if(!vram_draw_table[displine]) {
1509 copy_vram_per_line(0, 4);
1513 } else { // transfer wrote line
1516 for(displine = 0; displine < lines; displine++) {
1517 //if(!vram_draw_table[displine]) {
1518 for(int iii = 0; iii < 5 ; iii++) {
1519 if(vram_wrote_table[iii + displine * 5]) {
1526 if(end < begin) end = begin;
1527 copy_vram_per_line(begin, end);
1534 if(end < 0) end = 4;
1535 copy_vram_per_line(begin, end);
1543 for(int yy = 0; yy < lines; yy++) {
1544 if(vram_draw_table[yy]) {
1545 vram_wrote_shadow = true;
1546 screen_update_flag = true;
1551 // TRANSFER per HSYNC a.k.a SYNC-TO-HSYNC.
1553 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) lines = 400;
1555 if(need_transfer_line) {
1556 if(vram_wrote) { // Transfer all line.
1557 for(int yy = 0; yy < lines; yy++) {
1559 copy_vram_per_line(0, 4);
1565 for(int yy = 0; yy < lines; yy++) {
1566 if(vram_draw_table[yy]) {
1567 vram_wrote_shadow = true;
1568 screen_update_flag = true;
1572 //vram_wrote = false;
1574 frame_skip_count_transfer++;
1576 // Check frame skip for next frame.
1577 uint32_t factor = ((config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28) & 3;
1578 if((frame_skip_count_transfer > factor) /* || (vram_wrote) */) {
1579 frame_skip_count_transfer = 0;
1580 need_transfer_line = true;
1582 need_transfer_line = false;
1588 #if defined(_FM77L4)
1589 void DISPLAY::cursor_blink_77l4()
1591 if(!(mode400line && stat_400linecard)) return;
1592 uint8_t *regs = l4crtc->get_regs();
1596 if((regs[10] & 0x40) != 0) {
1597 cursor_blink = !cursor_blink;
1598 uint16_t addr = cursor_addr.w.l;
1600 x = ((addr / 2) % 40) / 8;
1601 y = (addr / 2) / 40;
1602 } else { // Width 80
1603 x = ((addr / 2) % 80) / 8;
1604 y = (addr / 2) / 80;
1606 for(int yy = 0; yy < 8; yy++) {
1607 naddr = (y + yy) * 5 + x;
1608 vram_wrote_table[naddr] = true;
1614 void DISPLAY::text_blink_77l4()
1617 uint16_t offset = text_start_addr.w.l;
1620 if(!(mode400line && stat_400linecard)) return;
1621 text_blink = !text_blink;
1622 for(addr = 0; addr < (80 * 50); addr++) {
1623 naddr = ((addr + offset) & 0x0ffe) + 1;
1624 if((text_vram[naddr] & 0x10) != 0) { // ATTR BLINK
1626 x = ((naddr / 2) % 40) / 8;
1627 y = (naddr / 2) / 40;
1628 } else { // Width 80
1629 x = ((naddr / 2) % 80) / 8;
1630 y = (naddr / 2) / 80;
1632 for(int yy = 0; yy < 8; yy++) {
1633 naddr = (y + yy) * 5 + x;
1634 vram_wrote_table[naddr] = true;
1639 #endif //#if defined(_FM77L4)
1641 void DISPLAY::event_callback(int event_id, int err)
1646 case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
1647 #if defined(_FM77AV_VARIANTS)
1655 case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
1658 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1659 case EVENT_FM7SUB_HDISP:
1660 event_callback_hdisp();
1662 case EVENT_FM7SUB_HBLANK:
1663 event_callback_hblank();
1665 case EVENT_FM7SUB_VSTART: // Call first.
1666 event_callback_vstart();
1668 case EVENT_FM7SUB_VSYNC:
1669 event_callback_vsync();
1672 case EVENT_FM7SUB_DELAY_BUSY:
1676 case EVENT_FM7SUB_CLEAR_DELAY:
1679 case EVENT_FM7SUB_CLR_CRTFLAG:
1682 #if defined(_FM77L4)
1683 case EVENT_FM7SUB_CURSOR_BLINK:
1684 cursor_blink_77l4();
1686 case EVENT_FM7SUB_TEXT_BLINK:
1693 void DISPLAY::event_frame()
1700 //write_access_page = (write_access_page + 1) & 1;
1701 //out_debug_log(_T("DISPLINE=%d"), displine);
1703 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1704 usec = 0.34 * 1000.0;
1706 usec = 1.52 * 1000.0;
1708 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x01, 0xff);
1709 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1710 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1714 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1718 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) lines = 400;
1720 if(need_transfer_line && vram_wrote) {
1721 for(yy = 0; yy < lines; yy++) {
1722 //if(!vram_draw_table[yy]) {
1724 copy_vram_per_line(0, 4);
1732 for(yy = 0; yy < lines; yy++) {
1733 if(vram_draw_table[yy]) {
1739 screen_update_flag = true;
1740 vram_wrote_shadow = true;
1744 frame_skip_count_transfer++;
1746 uint32_t factor = (config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28;
1747 if(frame_skip_count_transfer > factor) {
1748 frame_skip_count_transfer = 0;
1749 need_transfer_line = true;
1751 need_transfer_line = false;
1753 //vram_wrote = false;
1761 void DISPLAY::event_vline(int v, int clock)
1763 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1765 if(need_transfer_line == false) return;
1768 // Not transfer, will transfer at event_frame.
1769 copy_vram_per_line(0, 4);
1773 for(int iii = 0; iii < 5 ; iii++) {
1774 if(vram_wrote_table[displine * 5 + iii]) {
1775 if(begin < 0) begin = iii;
1779 if(end < begin) end = begin;
1780 copy_vram_per_line(begin, end);
1788 copy_vram_per_line(begin, end);
1796 uint32_t DISPLAY::read_signal(int id)
1798 uint32_t retval = 0;
1800 case SIG_FM7_SUB_HALT:
1801 case SIG_DISPLAY_HALT:
1802 retval = (halt_flag) ? 0xffffffff : 0;
1804 case SIG_DISPLAY_BUSY:
1805 retval = (sub_busy) ? 0x80 : 0;
1807 case SIG_DISPLAY_MULTIPAGE:
1808 retval = multimode_accessmask;
1810 case SIG_DISPLAY_PLANES:
1813 #if defined(_FM77AV_VARIANTS)
1814 case SIG_DISPLAY_VSYNC:
1815 retval = (vsync) ? 0x01 : 0x00;
1817 case SIG_DISPLAY_DISPLAY:
1818 retval = (!hblank) ? 0x02: 0x00;
1820 case SIG_FM7_SUB_BANK: // Main: FD13
1821 retval = subrom_bank & 0x03;
1822 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1823 if(monitor_ram) retval |= 0x04;
1827 #if defined(_FM77AV_VARIANTS)
1828 case SIG_DISPLAY_MODE320:
1829 retval = (mode320) ? 0x40: 0x00;
1832 case SIG_DISPLAY_Y_HEIGHT:
1833 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77L4)
1834 retval = ((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) ? 400 : 200;
1839 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1841 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1842 retval |= (kanjisub) ? 0x00 : 0x20;
1843 retval |= (mode256k) ? 0x10 : 0x00;
1844 retval |= (mode400line) ? 0x00 : 0x08;
1845 retval |= (ram_protect) ? 0x00 : 0x04;
1846 #elif defined(_FM77_VARIANTS)
1848 retval |= (kanjisub) ? 0x00 : 0x20;
1849 # if defined(_FM77L4)
1850 retval |= (stat_400linecard) ? 0x00 : 0x08;
1858 case SIG_DISPLAY_X_WIDTH:
1859 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1860 retval = (mode320 || mode256k) ? 320 : 640;
1861 #elif defined(_FM77AV_VARIANTS)
1862 retval = (mode320) ? 320 : 640;
1873 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
1875 bool flag = ((data & mask) != 0);
1879 case SIG_FM7_SUB_HALT:
1884 //call_write_signal(mainio, SIG_FM7_SUB_HALT, data, mask);
1886 case SIG_DISPLAY_HALT:
1890 restart_subsystem();
1893 case SIG_FM7_SUB_CANCEL:
1895 cancel_request = true;
1899 case SIG_DISPLAY_CLOCK:
1903 #if defined(_FM77AV_VARIANTS)
1904 case SIG_FM7_SUB_BANK: // Main: FD13
1905 set_monitor_bank(data & 0xff);
1908 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1909 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1910 //printf("Wrote $FD04: %02x\n", data);
1912 int oldmode = display_mode;
1914 kanjisub = ((data & 0x20) == 0) ? true : false;
1915 mode256k = (((data & 0x10) != 0) && ((data & 0x08) != 0) ) ? true : false;
1916 mode400line = ((data & 0x08) == 0) ? true : false;
1917 ram_protect = ((data & 0x04) == 0) ? true : false;
1918 if((mode400line) && !(mode320)) {
1919 display_mode = DISPLAY_MODE_8_400L;
1920 } else if(mode256k) {
1921 display_mode = DISPLAY_MODE_256k;
1923 display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1925 if(oldmode != display_mode) {
1927 if(mode320 || mode256k) {
1928 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
1929 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1930 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1931 for(y = 0; y < 200; y++) {
1932 pp = emu->get_screen_buffer(y);
1933 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1936 for(y = 0; y < 400; y++) {
1937 pp = emu->get_screen_buffer(y);
1938 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1941 //emu->set_vm_screen_lines(200);
1942 } else if(display_mode == DISPLAY_MODE_8_400L) {
1943 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1944 if(oldmode != DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(55.40);
1945 for(y = 0; y < 400; y++) {
1946 pp = emu->get_screen_buffer(y);
1947 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1950 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
1951 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1952 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1953 for(y = 0; y < 200; y++) {
1954 pp = emu->get_screen_buffer(y);
1955 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1958 for(y = 0; y < 400; y++) {
1959 pp = emu->get_screen_buffer(y);
1960 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1963 //emu->set_vm_screen_lines(200);
1966 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
1967 call_write_signal(alu, SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200, 0xffff);
1968 call_write_signal(alu, SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xff : 0x00, 0xff);
1969 frame_skip_count_draw = 3;
1970 frame_skip_count_transfer = 3;
1971 setup_display_mode();
1974 #elif defined(_FM77_VARIANTS)
1976 int oldmode = display_mode;
1977 kanjisub = ((data & 0x20) == 0) ? true : false;
1978 # if defined(_FM77L4)
1979 stat_400linecard = ((data & 0x08) != 0) ? false : true;
1980 if(mode400line && stat_400linecard) {
1982 uint8_t *regs = l4crtc->get_regs();
1983 display_mode = DISPLAY_MODE_1_400L;
1984 if(event_id_l4_cursor_blink >= 0) {
1985 cancel_event(this, event_id_l4_cursor_blink);
1987 if(event_id_l4_text_blink >= 0) {
1988 cancel_event(this, event_id_l4_text_blink);
1990 event_id_l4_cursor_blink = -1;
1991 event_id_l4_text_blink = -1;
1993 usec = ((regs[10] & 0x20) == 0) ? 160.0 : 320.0;
1994 usec = usec * 1000.0;
1995 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
1996 usec = 160.0 * 1000.0;
1997 register_event(this, EVENT_FM7SUB_TEXT_BLINK, true, usec, &event_id_l4_cursor_blink);
2000 display_mode = DISPLAY_MODE_8_200L;
2002 if(oldmode != display_mode) {
2004 if(display_mode == DISPLAY_MODE_1_400L) {
2005 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2006 for(int y = 0; y < 400; y++) {
2007 pp = emu->get_screen_buffer(y);
2008 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2012 vm->set_vm_frame_rate(FRAMES_PER_SEC);
2013 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2014 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2015 for(int y = 0; y < 200; y++) {
2016 pp = emu->get_screen_buffer(y);
2017 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2020 for(int y = 0; y < 400; y++) {
2021 pp = emu->get_screen_buffer(y);
2022 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2027 setup_display_mode();
2034 #if defined(_FM77AV_VARIANTS)
2035 case SIG_DISPLAY_MODE320: // FD12 bit 6
2036 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2038 //printf("Wrote $FD12: %02x\n", data);
2039 int oldmode = display_mode;
2042 display_mode = DISPLAY_MODE_8_400L;
2043 } else if(mode256k) {
2044 display_mode = DISPLAY_MODE_256k;
2045 } else if(!(mode320) && !(mode256k)) {
2046 //display_mode = (mode400line) ? DISPLAY_MODE_8_400L : DISPLAY_MODE_8_200L;
2047 display_mode = DISPLAY_MODE_8_200L;
2049 display_mode = (mode256k) ? DISPLAY_MODE_256k : DISPLAY_MODE_4096;
2051 if(oldmode != display_mode) {
2053 if(mode320 || mode256k) {
2054 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
2055 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2056 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2057 for(y = 0; y < 200; y++) {
2058 pp = emu->get_screen_buffer(y);
2059 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
2062 for(y = 0; y < 400; y++) {
2063 pp = emu->get_screen_buffer(y);
2064 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2067 //emu->set_vm_screen_lines(200);
2068 } else { // 200 lines, 8 colors.
2069 if(display_mode == DISPLAY_MODE_8_400L) {
2070 if(oldmode != DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(55.40);
2072 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
2074 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2075 int ymax = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
2077 emu->set_vm_screen_size(640, ymax, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2078 for(y = 0; y < ymax; y++) {
2079 pp = emu->get_screen_buffer(y);
2080 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2083 for(y = 0; y < 400; y++) {
2084 pp = emu->get_screen_buffer(y);
2085 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2088 //emu->set_vm_screen_lines(200);
2091 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
2092 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
2093 call_write_signal(alu, SIG_ALU_400LINE, 0x00, 0xff);
2094 setup_display_mode();
2095 //frame_skip_count = 3;
2098 # else /* FM77AV/20/20EX */
2101 if(oldflag != mode320) {
2104 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2105 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2106 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 320 * sizeof(scrntype_t));
2108 for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2110 //emu->set_vm_screen_lines(200);
2112 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2113 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2114 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2116 for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2118 //emu->set_vm_screen_lines(200);
2121 display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
2122 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
2123 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
2124 call_write_signal(alu, SIG_ALU_400LINE, 0, 0xffffffff);
2126 setup_display_mode();
2131 case SIG_DISPLAY_MULTIPAGE:
2132 set_multimode(data);
2134 case SIG_FM7_SUB_KEY_MASK:
2135 if(firq_mask == flag) {
2136 do_firq(!flag && key_firq_req);
2140 case SIG_FM7_SUB_KEY_FIRQ:
2141 do_firq(flag & !(firq_mask));
2142 key_firq_req = flag;
2150 * Vram accessing functions moved to vram.cpp .
2153 uint32_t DISPLAY::read_mmio(uint32_t addr)
2155 uint32_t retval = 0xff;
2157 if(addr < 0xd400) return 0xff;
2159 #if !defined(_FM77AV_VARIANTS)
2160 raddr = (addr - 0xd400) & 0x000f;
2161 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2162 raddr = (addr - 0xd400) & 0x003f;
2163 #else // FM77AV40EX || FM77AV40SX
2164 raddr = (addr - 0xd400) & 0x00ff;
2167 case 0x00: // Read keyboard
2168 retval = (call_read_data8(keyboard, 0x00) != 0) ? 0xff : 0x7f;
2170 case 0x01: // Read keyboard
2171 retval = call_read_data8(keyboard, 0x01) & 0xff;
2173 case 0x02: // Acknowledge
2182 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2183 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2185 if(!kanjisub) return 0xff;
2186 # if !defined(_FM77_VARIANTS)
2188 return (uint8_t)call_read_data8(kanjiclass2, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
2191 if(kanjiclass1 != NULL) retval = call_read_data8(kanjiclass1, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
2194 if(!kanjisub) return 0xff;
2195 # if !defined(_FM77_VARIANTS)
2197 return (uint8_t)call_read_data8(kanjiclass2, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
2200 if(kanjiclass1 != NULL) retval = call_read_data8(kanjiclass1, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
2207 retval = set_vramaccess();
2210 { // If use CLR insn to set busy flag, clear flag at first, then delay and set flag.
2212 // Delay at least 3+ clocks (CLR <$0A )
2215 usec = (4000.0 * 1000.0) / 2000000.0;
2217 usec = (4000.0 * 1000.0) / 999000.0;
2219 register_event(this, EVENT_FM7SUB_CLEAR_DELAY, usec, false, NULL); // NEXT CYCLE_
2223 #if defined(_FM77L4)
2225 if(stat_400linecard) {
2226 retval = l4crtc->read_io8(0);
2230 if(stat_400linecard) {
2231 retval = l4crtc->read_io8(1);
2232 // Update parameters.
2237 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
2239 #if defined(_FM77AV_VARIANTS)
2242 retval = call_read_data8(alu, ALU_CMDREG);
2245 retval = call_read_data8(alu, ALU_LOGICAL_COLOR);
2248 retval = call_read_data8(alu, ALU_WRITE_MASKREG);
2251 retval = call_read_data8(alu, ALU_CMP_STATUS_REG);
2254 retval = call_read_data8(alu, ALU_BANK_DISABLE);
2256 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2257 case 0x2f: // VRAM BANK
2258 retval = 0xfc | (vram_bank & 0x03);
2263 retval = get_miscreg();
2267 retval = call_read_data8(keyboard, 0x31);
2270 retval = call_read_data8(keyboard, 0x32);
2276 return (uint8_t)retval;
2279 uint32_t DISPLAY::read_vram_data8(uint32_t addr)
2283 uint32_t color = (addr >> 14) & 0x03;
2284 #if defined(_FM77L4)
2287 offset = offset_point;
2289 if(multimode_accessflags[2]) return 0xff;
2290 vramaddr = ((addr + offset) & 0x3fff) + 0x8000;
2291 return gvram[vramaddr];
2295 return text_vram[addr & 0x0fff];
2296 } else if(addr < 0xc000) {
2297 return subsys_l4[addr - 0x9800];
2303 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2304 if(display_mode == DISPLAY_MODE_8_400L) {
2305 color = vram_bank & 0x03;
2306 if(color > 2) color = 0;
2308 color = (addr >> 14) & 0x03;
2312 //if((multimode_accessmask & (1 << color)) != 0) return 0xff;
2313 if(multimode_accessflags[color]) return 0xff;
2315 #if defined(_FM77AV_VARIANTS)
2316 if (active_page != 0) {
2317 offset = offset_point_bank1;
2319 offset = offset_point;
2322 offset = offset_point;
2324 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2325 if(vram_active_block != 0) {
2326 if(display_mode != DISPLAY_MODE_256k) offset = 0; // Don't scroll at BLOCK 1.
2329 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2330 if(display_mode == DISPLAY_MODE_8_400L) {
2332 uint32_t page_offset_alt = 0;
2333 if(addr >= 0x8000) return 0xff;
2334 color = vram_bank & 0x03;
2335 if(color > 2) color = 0;
2337 pagemod = 0x8000 * color;
2338 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2339 if(vram_active_block != 0) page_offset = 0x18000;
2341 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2342 return gvram[vramaddr];
2345 uint32_t page_offset_alt;
2346 #if defined(_FM77AV40)
2348 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2350 page_offset_alt = 0; // right?
2353 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2355 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
2356 //page_mask = 0x1fff;
2357 //pagemod = addr & 0xe000;
2359 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2361 return gvram[vramaddr];
2363 #elif defined(_FM77AV_VARIANTS)
2365 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2366 return gvram[vramaddr];
2368 #elif defined(_FM77L4) //_FM77L4
2371 vramaddr = (addr + offset) & 0x7fff;
2372 return gvram[vramaddr];
2374 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2375 return gvram[vramaddr];
2379 #else // Others (77/7/8)
2380 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2381 return gvram[vramaddr];
2385 void DISPLAY::write_dma_data8(uint32_t addr, uint32_t data)
2387 uint32_t raddr = (addr & 0xffff) >> 7;
2388 if(write_dma_func_table[raddr] != NULL) {
2389 (this->*write_dma_func_table[raddr])(addr, (uint8_t) data);
2393 void DISPLAY::write_vram_data8(uint32_t addr, uint8_t data)
2396 uint32_t color = (addr >> 14) & 0x03;
2400 #if defined(_FM77AV_VARIANTS)
2401 if (active_page != 0) {
2402 offset = offset_point_bank1;
2404 offset = offset_point;
2407 offset = offset_point;
2409 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2410 if(vram_active_block != 0) offset = 0; // Don't scroll at BLOCK 1.
2413 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2414 if(display_mode == DISPLAY_MODE_8_400L) {
2416 uint32_t page_offset_alt = 0;
2418 if(addr >= 0x8000) {
2421 color = vram_bank & 0x03;
2422 if(color > 2) color = 0;
2424 pagemod = 0x8000 * color;
2425 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2426 if(vram_active_block != 0) page_offset_alt = 0x18000;
2428 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2429 // Reduce data transfer.
2430 tdata = gvram[vramaddr];
2432 naddr = (addr & 0x7fff) >> 4;
2433 gvram[vramaddr] = data;
2434 vram_wrote_table[naddr] = true;
2436 } else if(display_mode == DISPLAY_MODE_256k) {
2437 uint32_t page_offset_alt;
2439 #if defined(_FM77AV40)
2441 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2443 page_offset_alt = 0; // right?
2446 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2448 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
2449 tdata = gvram[vramaddr];
2451 naddr = (addr & page_mask) >> 3;
2452 gvram[vramaddr] = data;
2453 vram_wrote_table[naddr] = true;
2456 } else if(display_mode == DISPLAY_MODE_4096) {
2458 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2459 tdata = gvram[vramaddr];
2461 naddr = (addr & page_mask) >> 3;
2462 gvram[vramaddr] = data;
2463 vram_wrote_table[naddr] = true;
2467 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2468 tdata = gvram[vramaddr];
2470 naddr = (addr & page_mask) >> 4;
2471 gvram[vramaddr] = data;
2472 vram_wrote_table[naddr] = true;
2475 #elif defined(_FM77AV_VARIANTS)
2476 if(display_mode == DISPLAY_MODE_4096) {
2478 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2479 tdata = gvram[vramaddr];
2481 naddr = (addr & page_mask) >> 3;
2482 gvram[vramaddr] = data;
2483 vram_wrote_table[naddr] = true;
2487 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2488 tdata = gvram[vramaddr];
2490 naddr = (addr & page_mask) >> 4;
2491 gvram[vramaddr] = data;
2492 vram_wrote_table[naddr] = true;
2495 #elif defined(_FM77L4) //_FM77L4
2496 if(display_mode == DISPLAY_MODE_1_400L) {
2499 //if(multimode_accessflags[2]) return;
2500 vramaddr = ((addr + offset) & 0x3fff) + 0x8000;
2501 gvram[vramaddr] = data;
2504 vramaddr = (addr + offset) & 0x7fff;
2505 tdata = gvram[vramaddr];
2507 naddr = (addr & 0x7fff) >> 4;
2508 gvram[vramaddr] = data;
2509 vram_wrote_table[naddr] = true;
2516 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2517 tdata = gvram[vramaddr];
2519 naddr = (addr & 0x3fff) >> 4;
2520 gvram[vramaddr] = data;
2521 vram_wrote_table[naddr] = true;
2524 #else // Others (77/7/8)
2527 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2528 tdata = gvram[vramaddr];
2530 naddr = (addr & 0x3fff) >> 4;
2531 gvram[vramaddr] = data;
2532 vram_wrote_table[naddr] = true;
2538 uint32_t DISPLAY::read_cpu_vram_data8(uint32_t addr)
2541 #if defined(_FM77AV_VARIANTS)
2543 call_read_data8(alu, addr);
2546 return read_vram_data8(addr);
2549 uint32_t DISPLAY::read_dma_vram_data8(uint32_t addr)
2551 return read_vram_data8(addr);
2554 void DISPLAY::init_read_table(void)
2557 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
2558 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cpu_vram_data8;
2559 read_dma_func_table[_at >> 7] = &DISPLAY::read_dma_vram_data8;
2561 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
2562 read_cpu_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2563 read_dma_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2565 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
2566 read_cpu_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2567 read_dma_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2569 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
2570 read_cpu_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2571 read_dma_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2573 #if defined(_FM77AV_VARIANTS)
2574 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
2575 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2576 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2578 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
2579 read_cpu_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2580 read_dma_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2583 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
2584 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2585 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2588 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
2589 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2590 read_dma_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2592 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
2593 read_cpu_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2594 read_dma_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2598 uint32_t DISPLAY::read_console_ram(uint32_t addr)
2600 uint32_t raddr = addr & 0xfff;
2601 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2603 if(console_ram_bank >= 1) {
2604 return submem_console_av40[((console_ram_bank - 1) << 12) + raddr];
2608 return console_ram[raddr];
2611 uint32_t DISPLAY::read_work_ram(uint32_t addr)
2613 addr = addr & 0x3ff;
2614 return work_ram[addr];
2618 uint32_t DISPLAY::read_shared_ram(uint32_t addr)
2620 addr = addr - 0xd380;
2621 return shared_ram[addr];
2624 #if defined(_FM77AV_VARIANTS)
2625 uint32_t DISPLAY::read_hidden_ram(uint32_t addr)
2627 if(addr >= 0xd500) {
2628 return submem_hidden[addr - 0xd500];
2634 uint32_t DISPLAY::read_cgrom(uint32_t addr)
2636 #if defined(_FM77AV_VARIANTS)
2637 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2639 return submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)]; //FIXME
2642 return subsys_cg[(addr - 0xd800) + cgrom_bank * 0x800];
2644 return subsys_c[addr - 0xd800];
2648 uint32_t DISPLAY::read_subsys_monitor(uint32_t addr)
2650 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2652 return subsys_ram[addr - 0xe000];
2655 #if defined(_FM77AV_VARIANTS)
2656 switch(subrom_bank_using & 3) {
2658 return subsys_c[addr - 0xd800];
2661 return subsys_a[addr - 0xe000];
2664 return subsys_b[addr - 0xe000];
2667 return subsys_cg[addr - 0xe000];
2670 #elif defined(_FM77L4)
2672 return subsys_l4[addr - 0xb800];
2674 return subsys_c[addr - 0xd800];
2676 return subsys_c[addr - 0xd800];
2680 uint32_t DISPLAY::read_dma_data8(uint32_t addr)
2682 uint32_t raddr = (addr & 0xffff) >> 7;
2683 if(read_dma_func_table[raddr] != NULL) {
2684 return (this->*read_dma_func_table[raddr])(addr);
2689 uint32_t DISPLAY::read_data8(uint32_t addr)
2691 uint32_t raddr = addr;
2693 if(addr < 0x10000) {
2694 raddr = (addr & 0xffff) >> 7;
2695 if(read_cpu_func_table[raddr] != NULL) {
2696 return (this->*read_cpu_func_table[raddr])(addr);
2701 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2702 return dpalette_data[addr - FM7_SUBMEM_OFFSET_DPALETTE];
2705 #if defined(_FM77AV_VARIANTS)
2707 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2708 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2709 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2710 if(vram_active_block != 0) {
2714 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2715 if(display_mode == DISPLAY_MODE_8_400L) {
2716 uint32_t page_offset_alt = 0;
2719 color = (addr & 0x18000) >> 15;
2720 if(color > 2) color = 0;
2721 pagemod = 0x8000 * color;
2722 if (active_page != 0) {
2723 offset = offset_point_bank1 << 1;
2725 offset = offset_point << 1;
2727 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2728 if(vram_active_block != 0) {
2729 page_offset_alt = 0x18000;
2733 return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset_alt];
2736 return read_vram_data8(addr);
2743 * Vram accessing functions moved to vram.cpp .
2746 void DISPLAY::write_mmio(uint32_t addr, uint8_t data)
2749 uint8_t active_block_old;
2751 if(addr < 0xd400) return;
2753 #if !defined(_FM77AV_VARIANTS)
2754 addr = (addr - 0xd400) & 0x000f;
2755 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2756 addr = (addr - 0xd400) & 0x003f;
2757 #else // FM77AV40EX || FM77AV40SX
2758 addr = (addr - 0xd400) & 0x00ff;
2760 io_w_latch[addr] = (uint8_t)data;
2762 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4)
2765 set_cyclesteal((uint8_t)data);
2766 # if defined(_FM77L4)
2767 setup_400linemode((uint8_t)data);
2771 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2772 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2775 if(!kanjisub) return;
2776 kanjiaddr.w.h = 0x0000;
2777 kanjiaddr.b.h = (uint8_t) data;
2780 if(!kanjisub) return;
2781 kanjiaddr.w.h = 0x0000;
2782 kanjiaddr.b.l = (uint8_t)data;
2795 if(delay_busy) { // If WRITE after READ immediately.Perhaps use CLR insn.
2797 // Delay at least 5+ clocks (CLR $D40A or CLR (INDEX = $D40A))
2799 usec = (6000.0 * 1000.0) / 2000000.0;
2801 usec = (6000.0 * 1000.0) / 999000.0;
2803 register_event(this, EVENT_FM7SUB_DELAY_BUSY, usec, false, NULL); // NEXT CYCLE_
2811 #if defined(_FM77L4)
2813 if(stat_400linecard) {
2814 l4crtc->write_io8(0, data & 0x1f);
2818 if(stat_400linecard) {
2819 l4crtc->write_io8(1, data);
2820 // Update parameters.
2821 uint8_t crtc_addr = l4crtc->read_io8(0);
2822 const uint8_t *regs = l4crtc->get_regs();
2823 switch(crtc_addr & 0x1f) {
2826 cursor_addr.w.l &= 0x0ffc;
2827 cursor_addr.w.l |= (((uint16_t)regs[14]) << 10);
2828 cursor_addr.w.l |= (((uint16_t)regs[15]) << 2);
2830 cursor_addr.w.l += 2;
2832 cursor_addr.w.l &= 0xfff;
2834 if((crtc_addr & 0x1f) == 10) {
2836 if(event_id_l4_cursor_blink >= 0) {
2837 cancel_event(this, event_id_l4_cursor_blink);
2839 usec = ((data & 0x20) == 0) ? 160.0 : 320.0;
2840 usec = usec * 1000.0;
2841 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
2845 text_start_addr.w.l &= 0x03fc;
2846 text_start_addr.w.l |= (((uint16_t)data & 3) << 10);
2847 text_scroll_count++;
2848 if((text_scroll_count & 1) == 0) {
2853 text_start_addr.w.l &= 0xfc00;
2854 text_start_addr.w.l |= ((uint16_t)data << 2);
2855 text_scroll_count++;
2856 if((text_scroll_count & 1) == 0) {
2861 text_scroll_count++;
2862 if((text_scroll_count & 1) == 0) {
2864 cursor_addr.w.l &= 0x0ffc;
2865 cursor_addr.w.l |= (((uint16_t)regs[14]) << 10);
2866 cursor_addr.w.l |= (((uint16_t)regs[15]) << 2);
2868 cursor_addr.w.l += 2;
2870 cursor_addr.w.l &= 0xfff;
2881 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
2886 rval = (uint8_t)data;
2887 if(offset_changed[active_page]) {
2888 #if defined(_FM77AV_VARIANTS)
2889 if(active_page != 0) {
2890 tmp_offset_point[active_page].d = offset_point_bank1;
2892 tmp_offset_point[active_page].d = offset_point;
2895 tmp_offset_point[active_page].d = offset_point;
2898 tmp_offset_point[active_page].w.h = 0x0000;
2900 tmp_offset_point[active_page].b.h = rval;
2902 tmp_offset_point[active_page].b.l = rval;
2904 offset_changed[active_page] = !offset_changed[active_page];
2905 if(offset_changed[active_page]) {
2907 #if defined(_FM77AV_VARIANTS)
2908 if(active_page != 0) {
2910 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fff;
2912 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fe0;
2916 offset_point = tmp_offset_point[active_page].d & 0x007fff;
2918 offset_point = tmp_offset_point[active_page].d & 0x007fe0;
2922 offset_point = tmp_offset_point[active_page].d & 0x7fe0;
2926 #if defined(_FM77AV_VARIANTS)
2929 alu_write_cmdreg(data);
2932 alu_write_logical_color(data);
2935 alu_write_mask_reg(data);
2938 alu_write_disable_reg(data);
2941 alu_write_offsetreg_hi(data);
2944 alu_write_offsetreg_lo(data);
2947 alu_write_linepattern_hi(data);
2950 alu_write_linepattern_lo(data);
2952 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2954 console_ram_bank = (data & 0x18) >> 3;
2955 if(console_ram_bank > 2) console_ram_bank = 0;
2956 cgram_bank = data & 0x07;
2957 kanji_level2 = ((data & 0x80) == 0) ? false : true;
2959 case 0x2f: // VRAM BANK
2960 vram_bank = data & 0x03;
2961 if(vram_bank > 2) vram_bank = 0;
2971 call_write_data8(keyboard, 0x31, data);
2973 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2975 active_block_old = vram_active_block;
2976 vram_active_block = data & 0x01;
2977 if(vram_display_block != (((data & 0x10) != 0) ? 1 : 0)) vram_wrote = true;
2978 vram_display_block = ((data & 0x10) != 0) ? 1 : 0;
2979 if(vram_active_block != active_block_old) setup_display_mode();
2984 tmpvar.d = window_xbegin * 8;
2987 tmpvar.b.h = data & 0x03;
2989 tmpvar.b.l = data & 0xf8;
2991 if(mode320 || mode256k) {
2992 if(tmpvar.d > 320) tmpvar.d = 320;
2994 if(tmpvar.d > 640) tmpvar.d = 640;
2996 window_xbegin = tmpvar.d / 8;
3001 tmpvar.d = window_xend * 8;
3004 tmpvar.b.h = data & 0x03;
3006 tmpvar.b.l = data & 0xf8;
3008 if(mode320 || mode256k) {
3009 if(tmpvar.d > 320) tmpvar.d = 320;
3011 if(tmpvar.d > 640) tmpvar.d = 640;
3013 window_xend = tmpvar.d / 8;
3018 tmpvar.d = window_low;
3021 tmpvar.b.h = data & 0x03;
3023 tmpvar.b.l = data & 0xff;
3025 if(display_mode == DISPLAY_MODE_8_400L) {
3026 if(tmpvar.d > 400) tmpvar.d = 400;
3029 if(tmpvar.d > 400) tmpvar.d = 400;
3031 window_low = tmpvar.d;
3036 tmpvar.d = window_high;
3039 tmpvar.b.h = data & 0x03;
3041 tmpvar.b.l = data & 0xff;
3043 if(display_mode == DISPLAY_MODE_8_400L) {
3044 if(tmpvar.d > 400) tmpvar.d = 400;
3047 if(tmpvar.d > 400) tmpvar.d = 400;
3049 window_high = tmpvar.d;
3055 #if defined(_FM77AV_VARIANTS)
3057 if((addr >= 0x13) && (addr <= 0x1a)) {
3058 alu_write_cmpdata_reg(addr - 0x13, data);
3059 } else if((addr >= 0x1c) && (addr <= 0x1e)) {
3060 alu_write_tilepaint_data(addr, data);
3061 } else if((addr >= 0x24) && (addr <= 0x2b)) {
3062 alu_write_line_position(addr - 0x24, data);
3069 void DISPLAY::init_write_table(void)
3072 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
3073 write_cpu_func_table[_at >> 7] = &DISPLAY::write_cpu_vram_data8;
3074 write_dma_func_table[_at >> 7] = &DISPLAY::write_dma_vram_data8;
3076 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
3077 write_cpu_func_table[_at >> 7] = &DISPLAY::write_console_ram;
3078 write_dma_func_table[_at >> 7] = &DISPLAY::write_console_ram;
3080 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
3081 write_cpu_func_table[_at >> 7] = &DISPLAY::write_work_ram;
3082 write_dma_func_table[_at >> 7] = &DISPLAY::write_work_ram;
3084 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
3085 write_cpu_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
3086 write_dma_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
3088 #if defined(_FM77AV_VARIANTS)
3089 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
3090 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
3091 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
3093 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
3094 write_cpu_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
3095 write_dma_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
3098 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
3099 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
3100 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
3103 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
3104 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
3105 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
3106 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
3108 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
3109 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
3110 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
3113 for(_at = 0xd800; _at < 0x10000; _at += 0x80) {
3114 write_cpu_func_table[_at >> 7] = &DISPLAY::write_dummy;
3115 write_dma_func_table[_at >> 7] = &DISPLAY::write_dummy;
3120 void DISPLAY::write_console_ram(uint32_t addr, uint8_t data)
3122 uint32_t raddr = addr & 0xfff;
3123 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3125 if(console_ram_bank >= 1) {
3126 submem_console_av40[((console_ram_bank - 1) << 12) + raddr] = data;
3131 console_ram[raddr] = data;
3135 void DISPLAY::write_work_ram(uint32_t addr, uint8_t data)
3137 uint32_t raddr = addr & 0xfff;
3138 work_ram[raddr] = data;
3142 void DISPLAY::write_shared_ram(uint32_t addr, uint8_t data)
3144 uint32_t raddr = addr & 0x7f;
3145 shared_ram[raddr] = data;
3149 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
3150 void DISPLAY::write_subsys_cgram(uint32_t addr, uint8_t data)
3152 uint32_t raddr = addr - 0xd800;
3153 if(ram_protect) return;
3154 if(!monitor_ram) return;
3155 submem_cgram[cgram_bank * 0x0800 + raddr] = data; //FIXME
3158 void DISPLAY::write_subsys_ram(uint32_t addr, uint8_t data)
3160 if(ram_protect) return;
3161 if(!monitor_ram) return;
3162 subsys_ram[addr - 0xe000] = data; //FIXME
3166 #if defined(_FM77AV_VARIANTS)
3167 void DISPLAY::write_hidden_ram(uint32_t addr, uint8_t data)
3169 submem_hidden[addr - 0xd500] = data;
3174 void DISPLAY::write_cpu_vram_data8(uint32_t addr, uint8_t data)
3176 uint32_t color = (addr & 0xc000) >> 14;
3177 #if defined(_FM77AV_VARIANTS)
3179 call_read_data8(alu, addr);
3183 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3184 if(display_mode == DISPLAY_MODE_8_400L) {
3185 color = vram_bank & 0x03;
3186 if(color > 2) color = 0;
3189 #if defined(_FM77L4)
3193 if(!(multimode_accessflags[2])) write_vram_data8(addr & 0x7fff, data);
3196 } else if(addr < 0x9800) {
3199 addr = addr & 0x0fff;
3200 if(text_vram[addr] != data) {
3201 text_vram[addr] = data;
3203 x = ((addr / 2) % 40) / 8;
3204 y = (addr / 2) / 40;
3205 } else { // Width 80
3206 x = ((addr / 2) % 80) / 8;
3207 y = (addr / 2) / 80;
3209 for(int yy = 0; yy < 8; yy++) {
3210 naddr = (y + yy) * 5 + x;
3211 vram_wrote_table[naddr] = true;
3221 //if((multimode_accessmask & (1 << color)) != 0) return;
3222 if(multimode_accessflags[color]) return;
3224 write_vram_data8(addr & 0xffff, data);
3227 void DISPLAY::write_dma_vram_data8(uint32_t addr, uint8_t data)
3229 uint32_t color = (addr & 0xc000) >> 14;
3230 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3231 if(display_mode == DISPLAY_MODE_8_400L) {
3232 color = vram_bank & 0x03;
3233 if(color > 2) color = 0;
3237 //if((multimode_accessmask & (1 << color)) != 0) return;
3238 if(multimode_accessflags[color]) return;
3240 write_vram_data8(addr & 0xffff, data);
3243 void DISPLAY::write_dummy(uint32_t addr, uint8_t data)
3247 void DISPLAY::write_data8(uint32_t addr, uint32_t data)
3251 //uint32_t page_offset = 0x0000;
3252 uint8_t val8 = data & 0xff;
3253 uint32_t color = (addr & 0xc000) >> 14;
3256 if(addr < 0x10000) {
3257 void (*_write_func)(uint32_t, uint32_t);
3258 raddr = (addr & 0xffff) >> 7;
3259 if(write_cpu_func_table[raddr] != NULL) {
3260 (this->*write_cpu_func_table[raddr])(addr, (uint8_t)data);
3266 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
3267 set_dpalette(addr - FM7_SUBMEM_OFFSET_DPALETTE, val8);
3271 #if defined(_FM77AV_VARIANTS)
3273 else if(addr == FM7_SUBMEM_OFFSET_APALETTE_R) {
3274 set_apalette_r(val8);
3276 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_G) {
3277 set_apalette_g(val8);
3279 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_B) {
3280 set_apalette_b(val8);
3282 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_HI) {
3283 set_apalette_index_hi(val8);
3285 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_LO) {
3286 set_apalette_index_lo(val8);
3290 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
3291 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
3292 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3293 if(display_mode == DISPLAY_MODE_8_400L) {
3296 uint32_t page_offset_alt = 0;
3298 color = (addr & 0x18000) >> 15;
3299 if(color > 2) color = 0;
3300 if (active_page != 0) {
3301 offset = offset_point_bank1 << 1;
3303 offset = offset_point << 1;
3305 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3306 if(vram_active_block != 0) {
3307 page_offset_alt = 0x18000;
3311 naddr = (addr & 0x7fff) >> 4;
3312 pagemod = 0x8000 * color;
3313 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
3314 tdata = gvram[vramaddr];
3315 if(tdata != (uint8_t)data) {
3316 gvram[vramaddr] = data;
3317 vram_wrote_table[naddr] = true;
3321 write_vram_data8(addr, data);
3323 write_vram_data8(addr, data);
3325 //if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
3332 uint32_t DISPLAY::read_bios(const _TCHAR *name, uint8_t *ptr, uint32_t size)
3338 if((name == NULL) || (ptr == NULL)) return 0;
3339 s = create_local_path(name);
3340 if(s == NULL) return 0;
3342 if(!fio.Fopen(s, FILEIO_READ_BINARY)) return 0;
3343 blocks = fio.Fread(ptr, size, 1);
3346 return blocks * size;
3350 void DISPLAY::initialize()
3354 memset(io_w_latch, 0xff, sizeof(io_w_latch));
3355 screen_update_flag = true;
3356 memset(gvram, 0x00, sizeof(gvram));
3357 vram_wrote_shadow = false;
3358 memset(gvram_shadow, 0x00, sizeof(gvram_shadow));
3359 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
3360 for(i = 0; i < 411; i++) vram_draw_table[i] = false;
3361 force_update = false;
3363 memset(console_ram, 0x00, sizeof(console_ram));
3364 memset(work_ram, 0x00, sizeof(work_ram));
3365 memset(shared_ram, 0x00, sizeof(shared_ram));
3366 memset(subsys_c, 0xff, sizeof(subsys_c));
3367 need_transfer_line = true;
3368 frame_skip_count_draw = 3;
3369 frame_skip_count_transfer = 3;
3371 diag_load_subrom_c = false;
3373 if(read_bios(_T(ROM_FM8_SUBSYSTEM), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
3374 this->out_debug_log(_T("SUBSYSTEM ROM READING : %s"), diag_load_subrom_c ? "OK" : "NG");
3376 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_C), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
3377 this->out_debug_log(_T("SUBSYSTEM ROM Type C READING : %s"), diag_load_subrom_c ? "OK" : "NG");
3379 #if defined(_FM77AV_VARIANTS)
3380 memset(subsys_a, 0xff, sizeof(subsys_a));
3381 memset(subsys_b, 0xff, sizeof(subsys_b));
3382 memset(subsys_cg, 0xff, sizeof(subsys_cg));
3383 memset(submem_hidden, 0x00, sizeof(submem_hidden));
3385 diag_load_subrom_a = false;
3386 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_A), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
3387 this->out_debug_log(_T("SUBSYSTEM ROM Type A READING : %s"), diag_load_subrom_a ? "OK" : "NG");
3389 diag_load_subrom_b = false;
3390 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_B), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
3391 this->out_debug_log(_T("SUBSYSTEM ROM Type B READING : %s"), diag_load_subrom_b ? "OK" : "NG");
3393 diag_load_subrom_cg = false;
3394 if(read_bios(_T(ROM_FM7_SUBSYSTEM_CG), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
3395 this->out_debug_log(_T("SUBSYSTEM CG ROM READING : %s"), diag_load_subrom_cg ? "OK" : "NG");
3396 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
3397 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3398 memset(subsys_ram, 0x00, sizeof(subsys_ram));
3399 memset(submem_cgram, 0x00, sizeof(submem_cgram));
3400 memset(submem_console_av40, 0x00, sizeof(submem_console_av40));
3404 #if defined(_FM77L4)
3405 memset(subsys_cg_l4, 0xff, sizeof(subsys_cg_l4));
3406 memset(subsys_l4, 0xff, sizeof(subsys_l4));
3408 read_bios(_T(ROM_FM77_400LINE_ANKCG), subsys_cg_l4, sizeof(subsys_cg_l4));
3409 read_bios(_T(ROM_FM77_400LINE_SUBSYS), subsys_l4, sizeof(subsys_l4));
3410 memset(text_vram, 0x00, sizeof(text_vram));
3411 //memset(crtc_regs, 0x00, sizeof(crtc_regs));
3415 text_width40 = false;
3418 cursor_blink = true;
3420 text_start_addr.d = 0x0000;
3428 text_scroll_count = 0;
3430 event_id_l4_cursor_blink = -1;
3431 event_id_l4_text_blink = -1;
3437 #if defined(_FM77AV_VARIANTS)
3439 apalette_index.d = 0;
3440 for(i = 0; i < 4096; i++) {
3441 analog_palette_r[i] = i & 0x0f0;
3442 analog_palette_g[i] = (i & 0xf00) >> 4;
3443 analog_palette_b[i] = (i & 0x00f) << 4;
3445 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
3448 for(i = 0; i < 8; i++) set_dpalette(i, i);
3449 #if defined(USE_GREEN_DISPLAY)
3450 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3451 use_green_monitor = false;
3454 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3455 //#if defined(_FM77AV_VARIANTS)
3456 hblank_event_id = -1;
3457 hdisp_event_id = -1;
3458 vsync_event_id = -1;
3459 vstart_event_id = -1;
3466 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
3467 is_cyclesteal = true;
3469 is_cyclesteal = false;
3471 multimode_accessmask = multimode_dispmask = 0;
3472 for(i = 0; i < 4; i++) {
3473 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
3474 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
3477 prev_clock = SUBCLOCK_NORMAL;
3481 key_firq_req = false; //firq_mask = true;
3482 frame_skip_count_transfer = 3;
3483 frame_skip_count_draw = 3;
3484 #if !defined(FIXED_FRAMEBUFFER_SIZE)
3485 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
3487 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
3489 emu->set_vm_screen_lines(200);
3490 #if defined(_FM77AV40SX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3491 mode400line = false;
3493 #elif defined(_FM77L4)
3494 mode400line = false;
3497 palette_changed = true;
3498 //#if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
3499 //register_vline_event(this);
3500 register_frame_event(this);
3502 setup_display_mode();
3505 void DISPLAY::release()
3509 #define STATE_VERSION 12
3511 bool DISPLAY::process_state(FILEIO *state_fio, bool loading)
3513 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
3516 if(!state_fio->StateCheckInt32(this_device_id)) {
3521 state_fio->StateBool(delay_busy);
3522 state_fio->StateBool(halt_flag);
3523 state_fio->StateInt32(active_page);
3524 state_fio->StateBool(sub_busy);
3525 state_fio->StateBool(crt_flag);
3526 state_fio->StateBool(vram_wrote);
3527 state_fio->StateBool(is_cyclesteal);
3529 state_fio->StateBool(clock_fast);
3531 #if defined(_FM77AV_VARIANTS)
3532 state_fio->StateBool(subcpu_resetreq);
3533 state_fio->StateBool(power_on_reset);
3535 state_fio->StateBool(cancel_request);
3536 state_fio->StateBool(key_firq_req);
3537 state_fio->StateInt32(display_mode);
3538 state_fio->StateUint32(prev_clock);
3540 state_fio->StateBuffer(dpalette_data, sizeof(dpalette_data), 1);
3541 state_fio->StateUint8(multimode_accessmask);
3542 state_fio->StateUint8(multimode_dispmask);
3544 state_fio->StateUint32(offset_point);
3545 #if defined(_FM77AV_VARIANTS)
3546 state_fio->StateUint32(offset_point_bank1);
3548 //for(i = 0; i < 2; i++) {
3549 state_fio->StateBuffer(tmp_offset_point, sizeof(tmp_offset_point), 1);
3550 state_fio->StateBuffer(offset_changed, sizeof(offset_changed), 1);
3552 state_fio->StateBool(offset_77av);
3553 state_fio->StateBool(diag_load_subrom_c);
3554 state_fio->StateBuffer(io_w_latch, sizeof(io_w_latch), 1);
3555 state_fio->StateBuffer(console_ram, sizeof(console_ram), 1);
3556 state_fio->StateBuffer(work_ram, sizeof(work_ram), 1);
3557 state_fio->StateBuffer(shared_ram, sizeof(shared_ram), 1);
3558 state_fio->StateBuffer(subsys_c, sizeof(subsys_c), 1);
3559 state_fio->StateBuffer(gvram, sizeof(gvram), 1);
3560 state_fio->StateBuffer(gvram_shadow, sizeof(gvram_shadow), 1);
3561 #if defined(_FM77_VARIANTS)
3562 state_fio->StateBool(kanjisub);
3563 state_fio->StateUint32(kanjiaddr.d);
3564 # if defined(_FM77L4)
3565 state_fio->StateBool(mode400line);
3566 state_fio->StateBool(stat_400linecard);
3568 #elif defined(_FM77AV_VARIANTS)
3569 state_fio->StateBool(kanjisub);
3570 state_fio->StateUint32(kanjiaddr.d);
3571 state_fio->StateBool(mode320);
3572 state_fio->StateInt32(cgrom_bank);
3573 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3574 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3575 state_fio->StateInt32(vram_bank);
3577 state_fio->StateUint32(displine);
3578 state_fio->StateUint8(subrom_bank);
3579 state_fio->StateUint8(subrom_bank_using);
3580 state_fio->StateBool(nmi_enable);
3581 state_fio->StateBool(use_alu);
3582 state_fio->StateUint32(apalette_index.d);
3583 state_fio->StateBuffer(analog_palette_r, sizeof(analog_palette_r), 1);
3584 state_fio->StateBuffer(analog_palette_g, sizeof(analog_palette_g), 1);
3585 state_fio->StateBuffer(analog_palette_b, sizeof(analog_palette_b), 1);
3586 state_fio->StateBool(diag_load_subrom_a);
3587 state_fio->StateBool(diag_load_subrom_b);
3588 state_fio->StateBool(diag_load_subrom_cg);
3590 state_fio->StateBuffer(subsys_a, sizeof(subsys_a), 1);
3591 state_fio->StateBuffer(subsys_b, sizeof(subsys_b), 1);
3592 state_fio->StateBuffer(subsys_cg, sizeof(subsys_cg), 1);
3593 state_fio->StateBuffer(submem_hidden, sizeof(submem_hidden), 1);
3594 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3595 state_fio->StateBool(mode400line);
3596 state_fio->StateBool(mode256k);
3597 state_fio->StateBool(monitor_ram);
3598 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3599 state_fio->StateUint16(window_low);
3600 state_fio->StateUint16(window_high);
3601 state_fio->StateUint16(window_xbegin);
3602 state_fio->StateUint16(window_xend);
3603 state_fio->StateBool(window_opened);
3605 state_fio->StateBool(kanji_level2);
3606 state_fio->StateUint8(vram_active_block);
3607 state_fio->StateUint8(vram_display_block);
3608 state_fio->StateUint8(console_ram_bank);
3609 state_fio->StateBool(ram_protect);
3610 state_fio->StateUint8(cgram_bank);
3611 state_fio->StateBuffer(subsys_ram, sizeof(subsys_ram), 1);
3612 state_fio->StateBuffer(submem_cgram, sizeof(submem_cgram), 1);
3613 state_fio->StateBuffer(submem_console_av40, sizeof(submem_console_av40), 1);
3619 state_fio->StateInt32(nmi_event_id);
3620 //#if defined(_FM77AV_VARIANTS)
3621 state_fio->StateInt32(hblank_event_id);
3622 state_fio->StateInt32(hdisp_event_id);
3623 state_fio->StateInt32(vsync_event_id);
3624 state_fio->StateInt32(vstart_event_id);
3626 state_fio->StateBool(firq_mask);
3627 state_fio->StateBool(vram_accessflag);
3628 state_fio->StateInt8(display_page);
3629 state_fio->StateInt8(display_page_bak);
3630 state_fio->StateBool(vblank);
3631 state_fio->StateBool(vsync);
3632 state_fio->StateBool(hblank);
3633 state_fio->StateInt32(vblank_count);
3635 #if defined(_FM77L4)
3636 state_fio->StateBuffer(subsys_cg_l4, sizeof(subsys_cg_l4), 1);
3637 state_fio->StateBuffer(subsys_l4, sizeof(subsys_l4), 1);
3638 state_fio->StateBuffer(text_vram, sizeof(text_vram), 1);
3639 //state_fio->Fwrite(crtc_regs, sizeof(crtc_regs), 1);
3640 state_fio->StateBool(workram_l4);
3641 state_fio->StateBool(cursor_lsb);
3642 state_fio->StateBool(text_width40);
3644 state_fio->StateBool(text_blink);
3645 state_fio->StateBool(cursor_blink);
3647 state_fio->StateUint32(text_start_addr.d);
3648 state_fio->StateUint32(text_lines);
3649 state_fio->StateUint32(text_xmax);
3651 state_fio->StateUint32(cursor_addr.d);
3652 state_fio->StateInt32(cursor_start);
3653 state_fio->StateInt32(cursor_end);
3654 state_fio->StateUint8(cursor_type);
3655 state_fio->StateUint8(text_scroll_count);
3657 state_fio->StateInt32(event_id_l4_cursor_blink);
3658 state_fio->StateInt32(event_id_l4_text_blink);
3664 crt_flag_bak = true;
3665 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
3666 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
3668 for(addr = 0; addr < 8; addr++) set_dpalette(addr, addr);
3669 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3670 #if defined(USE_GREEN_DISPLAY)
3671 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3675 for(addr = 0; addr < 8; addr++) set_dpalette(addr, dpalette_data[addr]);
3676 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3677 #if defined(USE_GREEN_DISPLAY)
3678 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3680 for(i = 0; i < 4; i++) {
3681 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
3682 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
3685 #if defined(_FM77_VARIANTS)
3686 # if defined(_FM77L4)
3688 #elif defined(_FM77AV_VARIANTS)
3689 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3690 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3692 screen_update_flag = true;
3693 for(i = 0; i < 4096; i++) calc_apalette(i);
3694 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
3697 palette_changed = true;
3698 vram_wrote_shadow = true; // Force Draw
3699 this->draw_screen();
3701 frame_skip_count_draw = 3;
3702 frame_skip_count_transfer = 3;
3703 need_transfer_line = true;
3704 #if defined(USE_GREEN_DISPLAY) && defined(USE_MONITOR_TYPE)
3705 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3706 switch(config.monitor_type) {
3707 case FM7_MONITOR_GREEN:
3708 use_green_monitor = true;
3710 case FM7_MONITOR_STANDARD:
3712 use_green_monitor = false;
3716 //use_green_monitor = false;
3718 force_update = true;
3719 setup_display_mode();