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"
25 DISPLAY::DISPLAY(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
30 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
33 #elif defined(_FM77_VARIANTS)
36 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
37 kanjisub = false; // fix by Ryu Takegami
39 #if defined(_FM77AV_VARIANTS)
45 for(int i = 0; i < 256; i++) {
46 uint16_t n = (uint16_t)i;
47 for(int j = 0; j < 8; j++) {
48 bit_trans_table_0[i][j] = n & 0x80;
49 bit_trans_table_1[i][j] = ((n & 0x80) != 0) ? 0x40 : 0;
50 bit_trans_table_2[i][j] = ((n & 0x80) != 0) ? 0x20 : 0;
51 bit_trans_table_3[i][j] = ((n & 0x80) != 0) ? 0x10 : 0;
52 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
53 bit_trans_table_4[i][j] = ((n & 0x80) != 0) ? 0x08 : 0;
54 bit_trans_table_5[i][j] = ((n & 0x80) != 0) ? 0x04 : 0;
61 #if defined(USE_GREEN_DISPLAY)
62 use_green_monitor = false;
65 set_device_name(_T("DISPLAY SUBSYSTEM"));
73 void DISPLAY::reset_some_devices()
77 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
78 call_write_signal(mainio, SIG_FM7_SUB_HALT, 0x00, 0xff);
81 palette_changed = true;
82 multimode_accessmask = 0;
83 multimode_dispmask = 0;
84 for(i = 0; i < 4; i++) {
85 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
86 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
88 //firq_mask = false; // 20180215 Thanks to Ryu takegami.
89 //cancel_request = false;
90 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
91 switch(config.cpu_type){
100 prev_clock = SUBCLOCK_NORMAL;
102 prev_clock = SUBCLOCK_SLOW;
107 for(i = 0; i < 2; i++) {
108 offset_changed[i] = true;
109 tmp_offset_point[i].d = 0;
112 vram_wrote_shadow = true;
113 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
114 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
118 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
125 if(hblank_event_id >= 0) cancel_event(this, hblank_event_id);
126 if(hdisp_event_id >= 0) cancel_event(this, hdisp_event_id);
128 if(vsync_event_id >= 0) cancel_event(this, vsync_event_id);
129 if(vstart_event_id >= 0) cancel_event(this, vstart_event_id);
130 hblank_event_id = -1;
133 vstart_event_id = -1;
135 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
136 usec = 0.33 * 1000.0;
137 vm->set_vm_frame_rate(55.40);
139 usec = 0.51 * 1000.0;
140 vm->set_vm_frame_rate(FRAMES_PER_SEC);
143 //register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
144 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
145 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0xff, 0xff);
148 display_page_bak = 0;
150 #if defined(_FM77AV_VARIANTS)
152 offset_point_bank1 = 0;
154 subcpu_resetreq = false;
155 subrom_bank_using = subrom_bank;
160 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
162 vram_display_block = 0;
163 vram_active_block = 0;
165 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
170 window_opened = false;
175 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
176 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
177 call_write_signal(alu, SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400: 200, 0xffff);
178 call_write_signal(alu, SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xffffffff : 0, 0xffffffff);
180 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
181 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
182 call_write_signal(alu, SIG_ALU_400LINE, 0, 0xffffffff);
184 call_write_signal(alu, SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
185 call_write_signal(alu, SIG_ALU_PLANES, 3, 3);
187 for(i = 0; i < 8; i++) set_dpalette(i, i);
188 #if defined(USE_GREEN_DISPLAY)
189 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
191 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
192 //do_firq(!firq_mask && key_firq_req);
194 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
195 //kanjisub = false; // Fixed by Ryu takegami
196 kanjiaddr.d = 0x00000000;
197 # if defined(_FM77L4)
199 stat_400linecard = false;
204 frame_skip_count_draw = 3;
205 frame_skip_count_transfer = 3;
206 need_transfer_line = true;
207 setup_display_mode();
212 void DISPLAY::reset()
217 vram_accessflag = true;
218 display_mode = DISPLAY_MODE_8_200L;
220 crt_flag = false; // Fixed by Ryu Takegami
221 screen_update_flag = true;
222 crt_flag_bak = false;
223 cancel_request = false;
224 #if defined(_FM77AV_VARIANTS)
226 apalette_index.d = 0;
227 for(i = 0; i < 4096; i++) {
228 analog_palette_r[i] = i & 0x0f0;
229 analog_palette_g[i] = (i & 0xf00) >> 4;
230 analog_palette_b[i] = (i & 0x00f) << 4;
232 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
236 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
243 #elif defined(_FM77L4)
245 stat_400linecard = false;
249 text_width40 = false;
254 text_start_addr.d = 0x0000;
262 text_scroll_count = 0;
268 uint8_t *regs = l4crtc->get_regs();
269 display_mode = DISPLAY_MODE_1_400L;
270 if(event_id_l4_cursor_blink >= 0) {
271 cancel_event(this, event_id_l4_cursor_blink);
273 if(event_id_l4_text_blink >= 0) {
274 cancel_event(this, event_id_l4_text_blink);
276 event_id_l4_cursor_blink = -1;
277 event_id_l4_text_blink = -1;
279 usec = ((regs[10] & 0x20) == 0) ? 160.0 : 320.0;
280 usec = usec * 1000.0;
281 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
282 usec = 160.0 * 1000.0;
283 register_event(this, EVENT_FM7SUB_TEXT_BLINK, true, usec, &event_id_l4_cursor_blink);
286 //memset(crtc_regs, 0x00, sizeof(crtc_regs));
289 #if !defined(FIXED_FRAMEBUFFER_SIZE)
290 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
292 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
294 emu->set_vm_screen_lines(200);
296 reset_some_devices();
298 #if defined(_FM77AV_VARIANTS)
299 power_on_reset = false;
300 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
304 for(i = 0; i < 8; i++) set_dpalette(i, i);
307 #if defined(USE_GREEN_DISPLAY) && defined(USE_MONITOR_TYPE)
308 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
309 switch(config.monitor_type) {
310 case FM7_MONITOR_GREEN:
311 use_green_monitor = true;
313 case FM7_MONITOR_STANDARD:
315 use_green_monitor = false;
319 //use_green_monitor = false;
323 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
326 if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
327 register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
330 key_firq_req = false;
335 void DISPLAY::reset_subcpu(bool _check_firq)
337 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0, 1);
338 call_write_signal(subcpu, SIG_CPU_BUSREQ, 0, 1);
341 do_firq(!firq_mask && key_firq_req);
344 void DISPLAY::setup_display_mode(void)
346 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
347 if(display_mode == DISPLAY_MODE_8_400L) {
348 page_offset = 0x0000;
349 pagemod_mask = 0x18000;
351 } else if(display_mode == DISPLAY_MODE_256k) {
352 if(active_page != 0) {
353 page_offset = 0xc000;
355 page_offset = 0x0000;
357 pagemod_mask = 0xe000;
359 } else if(display_mode == DISPLAY_MODE_4096) {
360 if(active_page != 0) {
361 page_offset = 0xc000;
363 page_offset = 0x0000;
365 pagemod_mask = 0xe000;
368 if(active_page != 0) {
369 page_offset = 0xc000;
371 page_offset = 0x0000;
373 pagemod_mask = 0xc000;
376 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
377 if(vram_active_block != 0) page_offset += 0x18000;
379 #elif defined(_FM77AV_VARIANTS)
382 pagemod_mask = 0xe000;
383 } else { // 640x200, 8colors
385 pagemod_mask = 0xc000;
387 if(active_page != 0) {
388 page_offset = 0xc000;
390 page_offset = 0x0000;
392 #elif defined(_FM77L4)
393 if(display_mode == DISPLAY_MODE_1_400L) {
395 pagemod_mask = 0x0000;
396 page_offset = 0x0000;
397 } else { // 640x200, 8colors
399 pagemod_mask = 0xc000;
400 page_offset = 0x0000;
402 page_offset = 0x0000;
404 page_offset = 0x0000;
405 pagemod_mask = 0xc000;
410 void DISPLAY::update_config()
416 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
422 * Vram accessing functions moved to vram.cpp .
425 void DISPLAY::do_irq(bool flag)
427 call_write_signal(subcpu, SIG_CPU_IRQ, flag ? 1: 0, 1);
430 void DISPLAY::do_firq(bool flag)
432 call_write_signal(subcpu, SIG_CPU_FIRQ, flag ? 1: 0, 1);
435 void DISPLAY::do_nmi(bool flag)
437 #if defined(_FM77AV_VARIANTS)
438 if(!nmi_enable) flag = false;
440 call_write_signal(subcpu, SIG_CPU_NMI, flag ? 1 : 0, 1);
443 void DISPLAY::set_multimode(uint8_t val)
446 multimode_accessmask = val & 0x07;
447 multimode_dispmask = (val & 0x70) >> 4;
448 for(int i = 0; i < 4; i++) {
449 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
450 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
453 # if defined(_FM77AV_VARIANTS)
454 call_write_signal(alu, SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
459 uint8_t DISPLAY::get_multimode(void)
465 val = multimode_accessmask & 0x07;
466 val |= ((multimode_dispmask << 4) & 0x70);
472 uint8_t DISPLAY::get_cpuaccessmask(void)
474 return multimode_accessmask & 0x07;
477 void DISPLAY::set_dpalette(uint32_t addr, uint8_t val)
481 dpalette_data[addr] = val | 0xf8; //0b11111000;
482 b = ((val & 0x01) != 0x00)? 255 : 0x00;
483 r = ((val & 0x02) != 0x00)? 255 : 0x00;
484 g = ((val & 0x04) != 0x00)? 255 : 0x00;
486 dpalette_pixel_tmp[addr] = RGB_COLOR(r, g, b);
487 #if defined(USE_GREEN_DISPLAY)
488 static const scrntype_t colortable[8] = {0, 48, 70, 100, 140, 175, 202, 255};
489 g = colortable[val & 0x07];
490 b = r = ((val & 0x07) > 4) ? 48 : 0;
491 dpalette_green_tmp[addr] = RGB_COLOR(r, g, b);
493 palette_changed = true;
496 uint8_t DISPLAY::get_dpalette(uint32_t addr)
504 data = dpalette_data[addr];
509 void DISPLAY::halt_subcpu(void)
511 //call_write_signal(subcpu, SIG_CPU_BUSREQ, 0x01, 0x01);
512 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0x01, 0x01);
515 void DISPLAY::go_subcpu(void)
517 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0x00, 0x01);
520 void DISPLAY::enter_display(void)
525 subclock = SUBCLOCK_NORMAL;
527 subclock = SUBCLOCK_SLOW;
529 if(!(is_cyclesteal) && (vram_accessflag)) {
530 subclock = subclock / 3;
532 if(prev_clock != subclock) {
533 vm->set_cpu_clock(subcpu, subclock);
535 prev_clock = subclock;
539 void DISPLAY::leave_display(void)
543 void DISPLAY::halt_subsystem(void)
549 void DISPLAY::restart_subsystem(void)
552 #if defined(_FM77AV_VARIANTS)
553 if(subcpu_resetreq) {
554 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
555 reset_some_devices();
556 power_on_reset = true;
564 void DISPLAY::set_crtflag(void)
571 void DISPLAY::reset_crtflag(void)
578 uint8_t DISPLAY::acknowledge_irq(void)
580 cancel_request = false;
586 uint8_t DISPLAY::beep(void)
588 call_write_signal(mainio, FM7_MAINIO_BEEP, 0x01, 0x01);
589 return 0xff; // True?
594 uint8_t DISPLAY::attention_irq(void)
596 call_write_signal(mainio, FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
601 void DISPLAY::set_cyclesteal(uint8_t val)
604 # if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
608 is_cyclesteal = true;
610 is_cyclesteal = false;
617 void DISPLAY::setup_400linemode(uint8_t val)
621 cursor_lsb = ((val & 0x10) != 0);
622 text_width40 = ((val & 0x08) != 0);
623 workram_l4 = ((val & 0x04) != 0);
624 bool tmpmode = ((val & 0x02) != 0);
625 if(tmpmode != mode400line) {
626 int oldmode = display_mode;
627 mode400line = tmpmode;
628 if(mode400line && stat_400linecard) {
629 display_mode = DISPLAY_MODE_1_400L;
631 display_mode = DISPLAY_MODE_8_200L;
633 if(oldmode != display_mode) {
635 if(display_mode == DISPLAY_MODE_1_400L) {
636 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
637 for(int y = 0; y < 400; y++) {
638 pp = emu->get_screen_buffer(y);
639 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
643 vm->set_vm_frame_rate(FRAMES_PER_SEC);
644 #if !defined(FIXED_FRAMEBUFFER_SIZE)
645 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
646 for(int y = 0; y < 200; y++) {
647 pp = emu->get_screen_buffer(y);
648 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
651 for(int y = 0; y < 400; y++) {
652 pp = emu->get_screen_buffer(y);
653 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
658 setup_display_mode();
666 uint8_t DISPLAY::set_vramaccess(void)
668 vram_accessflag = true;
674 void DISPLAY::reset_vramaccess(void)
676 vram_accessflag = false;
681 uint8_t DISPLAY::reset_subbusy(void)
688 void DISPLAY::set_subbusy(void)
694 #if defined(_FM77AV_VARIANTS)
696 void DISPLAY::alu_write_cmdreg(uint32_t val)
698 call_write_data8(alu, ALU_CMDREG, val);
699 if((val & 0x80) != 0) {
707 void DISPLAY::alu_write_logical_color(uint8_t val)
709 uint32_t data = (uint32_t)val;
710 call_write_data8(alu, ALU_LOGICAL_COLOR, data);
714 void DISPLAY::alu_write_mask_reg(uint8_t val)
716 uint32_t data = (uint32_t)val;
717 call_write_data8(alu, ALU_WRITE_MASKREG, data);
721 void DISPLAY::alu_write_cmpdata_reg(int addr, uint8_t val)
723 uint32_t data = (uint32_t)val;
725 call_write_data8(alu, ALU_CMPDATA_REG + addr, data);
729 void DISPLAY::alu_write_disable_reg(uint8_t val)
731 uint32_t data = (uint32_t)val;
732 call_write_data8(alu, ALU_BANK_DISABLE, data);
736 void DISPLAY::alu_write_tilepaint_data(uint32_t addr, uint8_t val)
738 uint32_t data = (uint32_t)val;
741 call_write_data8(alu, ALU_TILEPAINT_B, data);
744 call_write_data8(alu, ALU_TILEPAINT_R, data);
747 call_write_data8(alu, ALU_TILEPAINT_G, data);
750 //call_write_data8(alu, ALU_TILEPAINT_L, 0xff);
756 void DISPLAY::alu_write_offsetreg_hi(uint8_t val)
758 call_write_data8(alu, ALU_OFFSET_REG_HIGH, val & 0x7f);
762 void DISPLAY::alu_write_offsetreg_lo(uint8_t val)
764 call_write_data8(alu, ALU_OFFSET_REG_LO, val);
768 void DISPLAY::alu_write_linepattern_hi(uint8_t val)
770 call_write_data8(alu, ALU_LINEPATTERN_REG_HIGH, val);
774 void DISPLAY::alu_write_linepattern_lo(uint8_t val)
776 call_write_data8(alu, ALU_LINEPATTERN_REG_LO, val);
780 void DISPLAY::alu_write_line_position(int addr, uint8_t val)
782 uint32_t data = (uint32_t)val;
785 call_write_data8(alu, ALU_LINEPOS_START_X_HIGH, data & 0x03);
788 call_write_data8(alu, ALU_LINEPOS_START_X_LOW, data);
791 call_write_data8(alu, ALU_LINEPOS_START_Y_HIGH, data & 0x01);
794 call_write_data8(alu, ALU_LINEPOS_START_Y_LOW, data);
797 call_write_data8(alu, ALU_LINEPOS_END_X_HIGH, data & 0x03);
800 call_write_data8(alu, ALU_LINEPOS_END_X_LOW, data);
803 call_write_data8(alu, ALU_LINEPOS_END_Y_HIGH, data & 0x01);
806 call_write_data8(alu, ALU_LINEPOS_END_Y_LOW, data);
812 uint8_t DISPLAY::get_miscreg(void)
817 if(!hblank) ret |= 0x80;
818 if(vsync) ret |= 0x04;
819 if(alu->read_signal(SIG_ALU_BUSYSTAT) == 0) ret |= 0x10;
820 if(power_on_reset) ret |= 0x01;
825 void DISPLAY::set_miscreg(uint8_t val)
827 int old_display_page = display_page;
829 nmi_enable = ((val & 0x80) == 0) ? true : false;
830 if(!nmi_enable) do_nmi(false);
832 if((val & 0x40) == 0) {
837 if(display_page != old_display_page) {
840 active_page = ((val & 0x20) == 0) ? 0 : 1;
841 if((val & 0x04) == 0) {
846 cgrom_bank = val & 0x03;
847 setup_display_mode();
851 void DISPLAY::set_monitor_bank(uint8_t var)
853 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
854 if((var & 0x04) != 0){
860 subrom_bank = var & 0x03;
863 subcpu_resetreq = false;
864 power_on_reset = true;
865 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
866 reset_some_devices();
869 subcpu_resetreq = true;
875 void DISPLAY::set_apalette_index_hi(uint8_t val)
877 apalette_index.b.h = val & 0x0f;
881 void DISPLAY::set_apalette_index_lo(uint8_t val)
883 apalette_index.b.l = val;
886 void DISPLAY::calc_apalette(uint16_t idx)
890 g = analog_palette_g[idx];
891 r = analog_palette_r[idx];
892 b = analog_palette_b[idx];
893 if(g != 0) g |= 0x0f;
894 if(r != 0) r |= 0x0f;
895 if(b != 0) b |= 0x0f;
896 analog_palette_pixel_tmp[idx] = RGB_COLOR(r, g, b);
900 void DISPLAY::set_apalette_b(uint8_t val)
904 index = apalette_index.w.l;
905 tmp = (val & 0x0f) << 4;
906 if(analog_palette_b[index] != tmp) {
907 analog_palette_b[index] = tmp;
908 calc_apalette(index);
909 palette_changed = true;
914 void DISPLAY::set_apalette_r(uint8_t val)
918 index = apalette_index.w.l;
919 tmp = (val & 0x0f) << 4;
920 if(analog_palette_r[index] != tmp) {
921 analog_palette_r[index] = tmp;
922 calc_apalette(index);
923 palette_changed = true;
928 void DISPLAY::set_apalette_g(uint8_t val)
932 index = apalette_index.w.l;
933 tmp = (val & 0x0f) << 4;
934 if(analog_palette_g[index] != tmp) {
935 analog_palette_g[index] = tmp;
936 calc_apalette(index);
937 palette_changed = true;
941 #endif // _FM77AV_VARIANTS
944 void DISPLAY::copy_vram_blank_area(void)
948 void DISPLAY::copy_vram_per_line(int begin, int end)
957 uint32_t src_offset_d1;
958 uint32_t src_offset_d2;
959 uint32_t src_offset_d;
964 uint32_t addr_d1, addr_d2;
968 //int dline = (int)displine - 1;
969 int dline = (int)displine;
971 if((begin < 0) || (begin > 4)) return;
972 if((end < 0) || (end > 4)) return;
973 if(begin > end) return;
974 if(dline < 0) return;
976 sectors = end - begin + 1;
978 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)){
979 if(dline >= 400) return;
981 if(dline >= 200) return;
983 #if defined(_FM77AV_VARIANTS)
984 yoff_d1 = offset_point;
985 yoff_d2 = offset_point_bank1;
986 if(display_mode == DISPLAY_MODE_4096) {
987 src_offset = dline * 40 + begin * 8;
988 sectors = sectors * 8;
989 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
992 addr_d1 = (src_offset + yoff_d1) & 0x1fff;
993 addr_d2 = (src_offset + yoff_d2) & 0x1fff;
994 bytes_d1 = 0x2000 - addr_d1;
995 bytes_d2 = 0x2000 - addr_d2;
996 for(k = 0; k < pages; k++) {
998 for(i = 0; i < 3; i++) {
999 for(j = 0; j < 2; j++) {
1000 uint32_t _addr_base = src_base + src_offset + poff;
1001 if(bytes_d1 < sectors) {
1002 my_memcpy(&gvram_shadow[_addr_base],
1003 &gvram[addr_d1 + src_base + poff],
1005 my_memcpy(&gvram_shadow[_addr_base + bytes_d1],
1006 &gvram[src_base + poff],
1007 sectors - bytes_d1);
1009 my_memcpy(&gvram_shadow[_addr_base],
1010 &gvram[addr_d1 + src_base + poff],
1013 _addr_base += 0xc000;
1014 if(bytes_d2 < sectors) {
1015 my_memcpy(&gvram_shadow[_addr_base],
1016 &gvram[addr_d2 + src_base + poff + 0xc000],
1018 my_memcpy(&gvram_shadow[_addr_base + bytes_d2],
1019 &gvram[src_base + poff + 0xc000],
1020 sectors - bytes_d2);
1022 my_memcpy(&gvram_shadow[_addr_base],
1023 &gvram[addr_d2 + src_base + poff + 0xc000],
1028 src_base = (i + 1) * 0x4000;
1032 vram_draw_table[dline] = true;
1033 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1035 # if defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV40)
1036 else if(display_mode == DISPLAY_MODE_256k) {
1037 src_offset = dline * 40 + begin * 8;
1038 sectors = sectors * 8;
1040 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1042 #elif defined(_FM77AV40)
1047 src_offset_d1 = (src_offset + yoff_d1) & 0x1fff;
1048 src_offset_d2 = (src_offset + yoff_d2) & 0x1fff;
1049 bytes_d1 = 0x2000 - ((src_offset + yoff_d1) & 0x1fff);
1050 bytes_d2 = 0x2000 - ((src_offset + yoff_d2) & 0x1fff);
1051 for(k = 0; k < pages; k++) {
1052 for(i = 0; i < 3; i++) {
1053 for(j = 0; j < 2; j++) {
1055 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
1056 src_offset_d = src_offset_d1;
1059 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
1060 src_offset_d = src_offset_d2;
1063 if(bytes_d < sectors) {
1064 my_memcpy(&gvram_shadow[src_offset + src_base],
1065 &gvram[src_offset_d + src_base],
1067 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1071 my_memcpy(&gvram_shadow[src_offset + src_base],
1072 &gvram[src_offset_d + src_base],
1078 vram_draw_table[dline] = true;
1079 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1081 else if(display_mode == DISPLAY_MODE_8_400L) {
1082 src_offset = dline * 80 + begin * 16;
1083 sectors = sectors * 16;
1084 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1087 if(display_page_bak == 1) { // Is this dirty?
1092 yoff_d = (yoff_d << 1) & 0x7fff;
1093 src_offset_d = (src_offset + yoff_d) & 0x7fff;
1094 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
1095 for(i = 0; i < pages; i++) {
1096 for(j = 0; j < 3; j++) {
1097 src_base = i * 0x18000 + j * 0x8000;
1098 if(bytes_d < sectors) {
1100 my_memcpy(&gvram_shadow[src_offset + src_base],
1101 &gvram[src_offset_d + src_base],
1104 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1108 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1109 &gvram[src_offset_d + src_base],
1114 vram_draw_table[dline] = true;
1115 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1119 src_offset = dline * 80 + begin * 16;
1120 sectors = sectors * 16;
1121 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1123 #elif defined(_FM77AV40)
1125 #elif defined(_FM77AV_VARIANTS)
1131 src_offset_d1 = (src_offset + yoff_d1) & 0x3fff;
1132 src_offset_d2 = (src_offset + yoff_d2) & 0x3fff;
1133 bytes_d1 = 0x4000 - ((src_offset + yoff_d1) & 0x3fff);
1134 bytes_d2 = 0x4000 - ((src_offset + yoff_d2) & 0x3fff);
1135 for(i = 0; i < pages; i++) {
1137 src_offset_d = src_offset_d1;
1140 src_offset_d = src_offset_d2;
1144 for(j = 0; j < 3; j++) {
1145 if(bytes_d < sectors) {
1146 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1147 &gvram[src_offset_d + src_base + poff],
1149 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1150 &gvram[src_base + poff],
1153 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1154 &gvram[src_offset_d + src_base + poff],
1161 vram_draw_table[dline] = true;
1162 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1163 //vram_wrote_table[dline] = false;
1166 #if defined(_FM77L4)
1167 if(display_mode == DISPLAY_MODE_1_400L) {
1168 src_offset = dline * 80 + begin * 16;
1169 sectors = sectors * 16;
1170 yoff_d = (yoff_d1 << 1) & 0x7fff;
1171 src_offset_d = (src_offset + yoff_d) & 0x7fff;
1172 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
1173 if(bytes_d < sectors) {
1175 my_memcpy(&gvram_shadow[src_offset],
1176 &gvram[src_offset_d],
1179 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1183 my_memcpy(&gvram_shadow[src_offset + poff],
1184 &gvram[src_offset_d ],
1187 vram_draw_table[dline] = true;
1188 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1193 src_offset = dline * 80 + begin * 16;
1194 sectors = sectors * 16;
1197 yoff_d = offset_point;
1198 src_offset_d = (src_offset + yoff_d) & 0x3fff;
1199 bytes_d = 0x4000 - ((src_offset + yoff_d) & 0x3fff);
1200 for(j = 0; j < 3; j++) {
1201 src_base = j * 0x4000;
1202 if(bytes_d < sectors) {
1203 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1204 &gvram[src_offset_d + src_base + poff],
1206 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1207 &gvram[src_base + poff],
1210 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1211 &gvram[src_offset_d + src_base + poff],
1215 vram_draw_table[dline] = true;
1216 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1217 //vram_wrote_table[dline] = false;
1223 void DISPLAY::copy_vram_all()
1225 #if defined(_FM77AV_VARIANTS)
1226 uint32_t yoff_d1 = offset_point;
1227 uint32_t yoff_d2 = offset_point_bank1;
1228 uint32_t src_offset_1, src_offset_2;
1230 if(display_mode == DISPLAY_MODE_4096) {
1231 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1236 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1237 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1238 for(int k = 0; k < pages; k++) {
1239 for(int i = 0; i < 3; i++) {
1240 for(int j = 0; j < 2; j++) {
1241 src_offset_1 = i * 0x4000 + j * 0x2000;
1242 src_offset_2 = src_offset_1 + 0xc000;
1243 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1244 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1245 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1246 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1252 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1253 else if(display_mode == DISPLAY_MODE_256k) {
1254 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1255 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1256 for(int i = 0; i < 3; i++) {
1257 for(int j = 0; j < 2; j++) {
1258 src_offset_1 = i * 0x4000 + j * 0x2000;
1259 src_offset_2 = src_offset_1 + 0xc000;
1260 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1261 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1262 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1263 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1267 for(int i = 0; i < 3; i++) {
1268 for(int j = 0; j < 2; j++) {
1269 src_offset_1 = i * 0x4000 + j * 0x2000;
1270 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1271 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1274 } else if(display_mode == DISPLAY_MODE_8_400L) {
1276 uint32_t yoff_d, bytes_d;
1277 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1280 if(display_page_bak == 1) { // Is this dirty?
1285 yoff_d = (yoff_d << 1) & 0x7fff;
1286 bytes_d = 0x8000 - yoff_d;
1287 for(int i = 0; i < pages; i++) {
1288 for(int j = 0; j < 3; j++) {
1289 uint32_t src_base = i * 0x18000 + j * 0x8000;
1290 my_memcpy(&gvram_shadow[src_base],
1291 &gvram[yoff_d + src_base],
1293 if(bytes_d < 0x8000) {
1294 my_memcpy(&gvram_shadow[bytes_d + src_base],
1303 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1305 #elif defined(_FM77AV40)
1310 uint32_t bytes_d1 = 0x4000 - (yoff_d1 & 0x3fff);
1311 uint32_t bytes_d2 = 0x4000 - (yoff_d2 & 0x3fff);
1312 uint32_t yoff_d, bytes_d;
1313 for(int k = 0; k < pages; k++) {
1314 yoff_d = ((k & 1) == 0) ? (yoff_d1 & 0x3fff) : (yoff_d2 & 0x3fff);
1315 bytes_d = ((k & 1) == 0) ? bytes_d1 : bytes_d2;
1316 for(int j = 0; j < 3; j++) {
1317 src_offset_1 = k * 0xc000 + j * 0x4000;
1318 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1319 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1324 # if defined(_FM77L4)
1325 if(display_mode == DISPLAY_MODE_1_400L) {
1326 uint32_t yoff_d = offset_point & 0x7fff;
1327 uint32_t bytes_d = 0x8000 - (offset_point & 0x7fff);
1328 my_memcpy(&gvram_shadow[0], &gvram[0 + yoff_d], bytes_d);
1329 my_memcpy(&gvram_shadow[0 + bytes_d], &gvram[0], 0x8000 - bytes_d);
1334 uint32_t yoff_d = offset_point & 0x3fff;
1335 uint32_t bytes_d = 0x4000 - (offset_point & 0x3fff);
1336 uint32_t src_offset_1;
1337 for(int j = 0; j < 3; j++) {
1338 src_offset_1 = j * 0x4000;
1339 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1340 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1346 // Timing values from XM7 . Thanks Ryu.
1347 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1348 void DISPLAY::event_callback_hdisp(void)
1353 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x02, 0xff);
1354 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1355 if(displine < 400) f = true;
1357 if(displine < 200) f = true;
1360 hdisp_event_id = -1;
1362 // DO ONLY WHEN SYNC-TO-HSYNC.
1363 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
1365 //copy_vram_per_line(0, 4);
1366 } else if(need_transfer_line) { // Not frame skip.
1369 for(int iii = 0; iii < 5 ; iii++) {
1370 if(vram_wrote_table[iii + displine * 5]) {
1371 if(begin < 0) begin = iii; // Check first.
1376 if(end < begin) end = begin;
1378 copy_vram_per_line(begin, end);
1379 // Prepare to next block.
1385 // Tail of this line.
1388 copy_vram_per_line(begin, end);
1392 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1393 register_event(this, EVENT_FM7SUB_HBLANK, 30.0, false, &hblank_event_id); // NEXT CYCLE_
1395 register_event(this, EVENT_FM7SUB_HBLANK, 39.5, false, &hblank_event_id); // NEXT CYCLE_
1403 void DISPLAY::event_callback_hblank(void)
1410 hblank_event_id = -1;
1412 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1413 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1414 if((displine < 400)) f = true;
1417 if((displine < 200)) f = true;
1421 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id);
1426 void DISPLAY::event_callback_vstart(void)
1433 display_page_bak = display_page;
1435 // Parameter from XM7/VM/display.c , thanks, Ryu.
1436 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1437 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x00, 0xff);
1439 if(vblank_count != 0) {
1440 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1441 usec = (0.98 + 16.4) * 1000.0;
1443 usec = (1.91 + 12.7) * 1000.0;
1445 register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
1447 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1448 usec = 930.0; // 939.0
1450 usec = 1840.0; // 1846.5
1452 vstart_event_id = -1;
1453 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
1454 //register_event(this, EVENT_FM7SUB_HBLANK, usec, false, &hdisp_event_id); // NEXT CYCLE_
1457 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1458 usec = 0.34 * 1000.0;
1460 usec = 1.52 * 1000.0;
1462 vsync_event_id = -1;
1463 hblank_event_id = -1;
1464 hdisp_event_id = -1;
1465 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1469 void DISPLAY::event_callback_vsync(void)
1475 //write_access_page = (write_access_page + 1) & 1;
1478 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1479 usec = 0.33 * 1000.0;
1481 usec = 0.51 * 1000.0;
1483 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x01, 0xff);
1484 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1485 //register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1487 if(palette_changed) {
1488 #if defined(_FM77AV_VARIANTS)
1489 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
1491 #if defined(USE_GREEN_DISPLAY)
1492 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
1494 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
1495 vram_wrote_shadow = true;
1496 for(int yy = 0; yy < 400; yy++) {
1497 vram_draw_table[yy] = true;
1499 palette_changed = false;
1501 // Transfer on VSYNC
1502 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) {
1506 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L))lines = 400;
1507 if(need_transfer_line) {
1508 if(vram_wrote) { // transfer all line
1509 for(displine = 0; displine < lines; displine++) {
1510 //if(!vram_draw_table[displine]) {
1511 copy_vram_per_line(0, 4);
1515 } else { // transfer wrote line
1518 for(displine = 0; displine < lines; displine++) {
1519 //if(!vram_draw_table[displine]) {
1520 for(int iii = 0; iii < 5 ; iii++) {
1521 if(vram_wrote_table[iii + displine * 5]) {
1528 if(end < begin) end = begin;
1529 copy_vram_per_line(begin, end);
1536 if(end < 0) end = 4;
1537 copy_vram_per_line(begin, end);
1545 for(int yy = 0; yy < lines; yy++) {
1546 if(vram_draw_table[yy]) {
1547 vram_wrote_shadow = true;
1548 screen_update_flag = true;
1553 // TRANSFER per HSYNC a.k.a SYNC-TO-HSYNC.
1555 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) lines = 400;
1557 if(need_transfer_line) {
1558 if(vram_wrote) { // Transfer all line.
1559 for(int yy = 0; yy < lines; yy++) {
1561 copy_vram_per_line(0, 4);
1567 for(int yy = 0; yy < lines; yy++) {
1568 if(vram_draw_table[yy]) {
1569 vram_wrote_shadow = true;
1570 screen_update_flag = true;
1574 //vram_wrote = false;
1576 frame_skip_count_transfer++;
1578 // Check frame skip for next frame.
1579 uint32_t factor = ((config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28) & 3;
1580 if((frame_skip_count_transfer > factor) /* || (vram_wrote) */) {
1581 frame_skip_count_transfer = 0;
1582 need_transfer_line = true;
1584 need_transfer_line = false;
1590 #if defined(_FM77L4)
1591 void DISPLAY::cursor_blink_77l4()
1593 if(!(mode400line && stat_400linecard)) return;
1594 uint8_t *regs = l4crtc->get_regs();
1598 if((regs[10] & 0x40) != 0) {
1599 cursor_blink = !cursor_blink;
1600 uint16_t addr = cursor_addr.w.l;
1602 x = ((addr / 2) % 40) / 8;
1603 y = (addr / 2) / 40;
1604 } else { // Width 80
1605 x = ((addr / 2) % 80) / 8;
1606 y = (addr / 2) / 80;
1608 for(int yy = 0; yy < 8; yy++) {
1609 naddr = (y + yy) * 5 + x;
1610 vram_wrote_table[naddr] = true;
1616 void DISPLAY::text_blink_77l4()
1619 uint16_t offset = text_start_addr.w.l;
1622 if(!(mode400line && stat_400linecard)) return;
1623 text_blink = !text_blink;
1624 for(addr = 0; addr < (80 * 50); addr++) {
1625 naddr = ((addr + offset) & 0x0ffe) + 1;
1626 if((text_vram[naddr] & 0x10) != 0) { // ATTR BLINK
1628 x = ((naddr / 2) % 40) / 8;
1629 y = (naddr / 2) / 40;
1630 } else { // Width 80
1631 x = ((naddr / 2) % 80) / 8;
1632 y = (naddr / 2) / 80;
1634 for(int yy = 0; yy < 8; yy++) {
1635 naddr = (y + yy) * 5 + x;
1636 vram_wrote_table[naddr] = true;
1641 #endif //#if defined(_FM77L4)
1643 void DISPLAY::event_callback(int event_id, int err)
1648 case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
1649 #if defined(_FM77AV_VARIANTS)
1657 case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
1660 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1661 case EVENT_FM7SUB_HDISP:
1662 event_callback_hdisp();
1664 case EVENT_FM7SUB_HBLANK:
1665 event_callback_hblank();
1667 case EVENT_FM7SUB_VSTART: // Call first.
1668 event_callback_vstart();
1670 case EVENT_FM7SUB_VSYNC:
1671 event_callback_vsync();
1674 case EVENT_FM7SUB_DELAY_BUSY:
1678 case EVENT_FM7SUB_CLEAR_DELAY:
1681 case EVENT_FM7SUB_CLR_CRTFLAG:
1684 #if defined(_FM77L4)
1685 case EVENT_FM7SUB_CURSOR_BLINK:
1686 cursor_blink_77l4();
1688 case EVENT_FM7SUB_TEXT_BLINK:
1695 void DISPLAY::event_frame()
1702 //write_access_page = (write_access_page + 1) & 1;
1703 //out_debug_log(_T("DISPLINE=%d"), displine);
1705 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1706 usec = 0.34 * 1000.0;
1708 usec = 1.52 * 1000.0;
1710 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x01, 0xff);
1711 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1712 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1716 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1720 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) lines = 400;
1722 if(need_transfer_line && vram_wrote) {
1723 for(yy = 0; yy < lines; yy++) {
1724 //if(!vram_draw_table[yy]) {
1726 copy_vram_per_line(0, 4);
1734 for(yy = 0; yy < lines; yy++) {
1735 if(vram_draw_table[yy]) {
1741 screen_update_flag = true;
1742 vram_wrote_shadow = true;
1746 frame_skip_count_transfer++;
1748 uint32_t factor = (config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28;
1749 if(frame_skip_count_transfer > factor) {
1750 frame_skip_count_transfer = 0;
1751 need_transfer_line = true;
1753 need_transfer_line = false;
1755 //vram_wrote = false;
1763 void DISPLAY::event_vline(int v, int clock)
1765 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1767 if(need_transfer_line == false) return;
1770 // Not transfer, will transfer at event_frame.
1771 copy_vram_per_line(0, 4);
1775 for(int iii = 0; iii < 5 ; iii++) {
1776 if(vram_wrote_table[displine * 5 + iii]) {
1777 if(begin < 0) begin = iii;
1781 if(end < begin) end = begin;
1782 copy_vram_per_line(begin, end);
1790 copy_vram_per_line(begin, end);
1798 uint32_t DISPLAY::read_signal(int id)
1800 uint32_t retval = 0;
1802 case SIG_FM7_SUB_HALT:
1803 case SIG_DISPLAY_HALT:
1804 retval = (halt_flag) ? 0xffffffff : 0;
1806 case SIG_DISPLAY_BUSY:
1807 retval = (sub_busy) ? 0x80 : 0;
1809 case SIG_DISPLAY_MULTIPAGE:
1810 retval = multimode_accessmask;
1812 case SIG_DISPLAY_PLANES:
1815 #if defined(_FM77AV_VARIANTS)
1816 case SIG_DISPLAY_VSYNC:
1817 retval = (vsync) ? 0x01 : 0x00;
1819 case SIG_DISPLAY_DISPLAY:
1820 retval = (!hblank) ? 0x02: 0x00;
1822 case SIG_FM7_SUB_BANK: // Main: FD13
1823 retval = subrom_bank & 0x03;
1824 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1825 if(monitor_ram) retval |= 0x04;
1829 #if defined(_FM77AV_VARIANTS)
1830 case SIG_DISPLAY_MODE320:
1831 retval = (mode320) ? 0x40: 0x00;
1834 case SIG_DISPLAY_Y_HEIGHT:
1835 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77L4)
1836 retval = ((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) ? 400 : 200;
1841 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1843 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1844 retval |= (kanjisub) ? 0x00 : 0x20;
1845 retval |= (mode256k) ? 0x10 : 0x00;
1846 retval |= (mode400line) ? 0x00 : 0x08;
1847 retval |= (ram_protect) ? 0x00 : 0x04;
1848 #elif defined(_FM77_VARIANTS)
1850 retval |= (kanjisub) ? 0x00 : 0x20;
1851 # if defined(_FM77L4)
1852 retval |= (stat_400linecard) ? 0x00 : 0x08;
1860 case SIG_DISPLAY_X_WIDTH:
1861 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1862 retval = (mode320 || mode256k) ? 320 : 640;
1863 #elif defined(_FM77AV_VARIANTS)
1864 retval = (mode320) ? 320 : 640;
1875 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
1877 bool flag = ((data & mask) != 0);
1881 case SIG_FM7_SUB_HALT:
1886 //call_write_signal(mainio, SIG_FM7_SUB_HALT, data, mask);
1888 case SIG_DISPLAY_HALT:
1892 restart_subsystem();
1895 case SIG_FM7_SUB_CANCEL:
1897 cancel_request = true;
1901 case SIG_DISPLAY_CLOCK:
1905 #if defined(_FM77AV_VARIANTS)
1906 case SIG_FM7_SUB_BANK: // Main: FD13
1907 set_monitor_bank(data & 0xff);
1910 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1911 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1912 //printf("Wrote $FD04: %02x\n", data);
1914 int oldmode = display_mode;
1916 kanjisub = ((data & 0x20) == 0) ? true : false;
1917 mode256k = (((data & 0x10) != 0) && ((data & 0x08) != 0) ) ? true : false;
1918 mode400line = ((data & 0x08) == 0) ? true : false;
1919 ram_protect = ((data & 0x04) == 0) ? true : false;
1920 if((mode400line) && !(mode320)) {
1921 display_mode = DISPLAY_MODE_8_400L;
1922 } else if(mode256k) {
1923 display_mode = DISPLAY_MODE_256k;
1925 display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1927 if(oldmode != display_mode) {
1929 if(mode320 || mode256k) {
1930 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
1931 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1932 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1933 for(y = 0; y < 200; y++) {
1934 pp = emu->get_screen_buffer(y);
1935 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1938 for(y = 0; y < 400; y++) {
1939 pp = emu->get_screen_buffer(y);
1940 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1943 //emu->set_vm_screen_lines(200);
1944 } else if(display_mode == DISPLAY_MODE_8_400L) {
1945 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1946 if(oldmode != DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(55.40);
1947 for(y = 0; y < 400; y++) {
1948 pp = emu->get_screen_buffer(y);
1949 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1952 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
1953 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1954 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1955 for(y = 0; y < 200; y++) {
1956 pp = emu->get_screen_buffer(y);
1957 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1960 for(y = 0; y < 400; y++) {
1961 pp = emu->get_screen_buffer(y);
1962 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1965 //emu->set_vm_screen_lines(200);
1968 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
1969 call_write_signal(alu, SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200, 0xffff);
1970 call_write_signal(alu, SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xff : 0x00, 0xff);
1971 frame_skip_count_draw = 3;
1972 frame_skip_count_transfer = 3;
1973 setup_display_mode();
1976 #elif defined(_FM77_VARIANTS)
1978 int oldmode = display_mode;
1979 kanjisub = ((data & 0x20) == 0) ? true : false;
1980 # if defined(_FM77L4)
1981 stat_400linecard = ((data & 0x08) != 0) ? false : true;
1982 if(mode400line && stat_400linecard) {
1984 uint8_t *regs = l4crtc->get_regs();
1985 display_mode = DISPLAY_MODE_1_400L;
1986 if(event_id_l4_cursor_blink >= 0) {
1987 cancel_event(this, event_id_l4_cursor_blink);
1989 if(event_id_l4_text_blink >= 0) {
1990 cancel_event(this, event_id_l4_text_blink);
1992 event_id_l4_cursor_blink = -1;
1993 event_id_l4_text_blink = -1;
1995 usec = ((regs[10] & 0x20) == 0) ? 160.0 : 320.0;
1996 usec = usec * 1000.0;
1997 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
1998 usec = 160.0 * 1000.0;
1999 register_event(this, EVENT_FM7SUB_TEXT_BLINK, true, usec, &event_id_l4_cursor_blink);
2002 display_mode = DISPLAY_MODE_8_200L;
2004 if(oldmode != display_mode) {
2006 if(display_mode == DISPLAY_MODE_1_400L) {
2007 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2008 for(int y = 0; y < 400; y++) {
2009 pp = emu->get_screen_buffer(y);
2010 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2014 vm->set_vm_frame_rate(FRAMES_PER_SEC);
2015 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2016 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2017 for(int y = 0; y < 200; y++) {
2018 pp = emu->get_screen_buffer(y);
2019 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2022 for(int y = 0; y < 400; y++) {
2023 pp = emu->get_screen_buffer(y);
2024 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2029 setup_display_mode();
2036 #if defined(_FM77AV_VARIANTS)
2037 case SIG_DISPLAY_MODE320: // FD12 bit 6
2038 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2040 //printf("Wrote $FD12: %02x\n", data);
2041 int oldmode = display_mode;
2044 display_mode = DISPLAY_MODE_8_400L;
2045 } else if(mode256k) {
2046 display_mode = DISPLAY_MODE_256k;
2047 } else if(!(mode320) && !(mode256k)) {
2048 //display_mode = (mode400line) ? DISPLAY_MODE_8_400L : DISPLAY_MODE_8_200L;
2049 display_mode = DISPLAY_MODE_8_200L;
2051 display_mode = (mode256k) ? DISPLAY_MODE_256k : DISPLAY_MODE_4096;
2053 if(oldmode != display_mode) {
2055 if(mode320 || mode256k) {
2056 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
2057 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2058 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2059 for(y = 0; y < 200; y++) {
2060 pp = emu->get_screen_buffer(y);
2061 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
2064 for(y = 0; y < 400; y++) {
2065 pp = emu->get_screen_buffer(y);
2066 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2069 //emu->set_vm_screen_lines(200);
2070 } else { // 200 lines, 8 colors.
2071 if(display_mode == DISPLAY_MODE_8_400L) {
2072 if(oldmode != DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(55.40);
2074 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
2076 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2077 int ymax = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
2079 emu->set_vm_screen_size(640, ymax, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2080 for(y = 0; y < ymax; y++) {
2081 pp = emu->get_screen_buffer(y);
2082 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2085 for(y = 0; y < 400; y++) {
2086 pp = emu->get_screen_buffer(y);
2087 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2090 //emu->set_vm_screen_lines(200);
2093 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
2094 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
2095 call_write_signal(alu, SIG_ALU_400LINE, 0x00, 0xff);
2096 setup_display_mode();
2097 //frame_skip_count = 3;
2100 # else /* FM77AV/20/20EX */
2103 if(oldflag != mode320) {
2106 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2107 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2108 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 320 * sizeof(scrntype_t));
2110 for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2112 //emu->set_vm_screen_lines(200);
2114 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2115 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2116 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2118 for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2120 //emu->set_vm_screen_lines(200);
2123 display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
2124 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
2125 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
2126 call_write_signal(alu, SIG_ALU_400LINE, 0, 0xffffffff);
2128 setup_display_mode();
2133 case SIG_DISPLAY_MULTIPAGE:
2134 set_multimode(data);
2136 case SIG_FM7_SUB_KEY_MASK:
2137 if(firq_mask == flag) {
2138 do_firq(!flag && key_firq_req);
2142 case SIG_FM7_SUB_KEY_FIRQ:
2143 do_firq(flag & !(firq_mask));
2144 key_firq_req = flag;
2152 * Vram accessing functions moved to vram.cpp .
2155 uint32_t DISPLAY::read_mmio(uint32_t addr)
2157 uint32_t retval = 0xff;
2159 if(addr < 0xd400) return 0xff;
2161 #if !defined(_FM77AV_VARIANTS)
2162 raddr = (addr - 0xd400) & 0x000f;
2163 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2164 raddr = (addr - 0xd400) & 0x003f;
2165 #else // FM77AV40EX || FM77AV40SX
2166 raddr = (addr - 0xd400) & 0x00ff;
2169 case 0x00: // Read keyboard
2170 retval = (call_read_data8(keyboard, 0x00) != 0) ? 0xff : 0x7f;
2172 case 0x01: // Read keyboard
2173 retval = call_read_data8(keyboard, 0x01) & 0xff;
2175 case 0x02: // Acknowledge
2184 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2185 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2187 if(!kanjisub) return 0xff;
2188 # if !defined(_FM77_VARIANTS)
2190 return (uint8_t)call_read_data8(kanjiclass2, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
2193 if(kanjiclass1 != NULL) retval = call_read_data8(kanjiclass1, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
2196 if(!kanjisub) return 0xff;
2197 # if !defined(_FM77_VARIANTS)
2199 return (uint8_t)call_read_data8(kanjiclass2, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
2202 if(kanjiclass1 != NULL) retval = call_read_data8(kanjiclass1, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
2209 retval = set_vramaccess();
2212 { // If use CLR insn to set busy flag, clear flag at first, then delay and set flag.
2214 // Delay at least 3+ clocks (CLR <$0A )
2217 usec = (4000.0 * 1000.0) / 2000000.0;
2219 usec = (4000.0 * 1000.0) / 999000.0;
2221 register_event(this, EVENT_FM7SUB_CLEAR_DELAY, usec, false, NULL); // NEXT CYCLE_
2225 #if defined(_FM77L4)
2227 if(stat_400linecard) {
2228 retval = l4crtc->read_io8(0);
2232 if(stat_400linecard) {
2233 retval = l4crtc->read_io8(1);
2234 // Update parameters.
2239 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
2241 #if defined(_FM77AV_VARIANTS)
2244 retval = call_read_data8(alu, ALU_CMDREG);
2247 retval = call_read_data8(alu, ALU_LOGICAL_COLOR);
2250 retval = call_read_data8(alu, ALU_WRITE_MASKREG);
2253 retval = call_read_data8(alu, ALU_CMP_STATUS_REG);
2256 retval = call_read_data8(alu, ALU_BANK_DISABLE);
2258 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2259 case 0x2f: // VRAM BANK
2260 retval = 0xfc | (vram_bank & 0x03);
2265 retval = get_miscreg();
2269 retval = call_read_data8(keyboard, 0x31);
2272 retval = call_read_data8(keyboard, 0x32);
2278 return (uint8_t)retval;
2281 uint32_t DISPLAY::read_vram_data8(uint32_t addr)
2285 uint32_t color = (addr >> 14) & 0x03;
2286 #if defined(_FM77L4)
2289 offset = offset_point;
2291 if(multimode_accessflags[2]) return 0xff;
2292 vramaddr = ((addr + offset) & 0x3fff) + 0x8000;
2293 return gvram[vramaddr];
2297 return text_vram[addr & 0x0fff];
2298 } else if(addr < 0xc000) {
2299 return subsys_l4[addr - 0x9800];
2305 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2306 if(display_mode == DISPLAY_MODE_8_400L) {
2307 color = vram_bank & 0x03;
2308 if(color > 2) color = 0;
2310 color = (addr >> 14) & 0x03;
2314 //if((multimode_accessmask & (1 << color)) != 0) return 0xff;
2315 if(multimode_accessflags[color]) return 0xff;
2317 #if defined(_FM77AV_VARIANTS)
2318 if (active_page != 0) {
2319 offset = offset_point_bank1;
2321 offset = offset_point;
2324 offset = offset_point;
2326 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2327 if(vram_active_block != 0) {
2328 if(display_mode != DISPLAY_MODE_256k) offset = 0; // Don't scroll at BLOCK 1.
2331 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2332 if(display_mode == DISPLAY_MODE_8_400L) {
2334 uint32_t page_offset_alt = 0;
2335 if(addr >= 0x8000) return 0xff;
2336 color = vram_bank & 0x03;
2337 if(color > 2) color = 0;
2339 pagemod = 0x8000 * color;
2340 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2341 if(vram_active_block != 0) page_offset = 0x18000;
2343 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2344 return gvram[vramaddr];
2347 uint32_t page_offset_alt;
2348 #if defined(_FM77AV40)
2350 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2352 page_offset_alt = 0; // right?
2355 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2357 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
2358 //page_mask = 0x1fff;
2359 //pagemod = addr & 0xe000;
2361 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2363 return gvram[vramaddr];
2365 #elif defined(_FM77AV_VARIANTS)
2367 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2368 return gvram[vramaddr];
2370 #elif defined(_FM77L4) //_FM77L4
2373 vramaddr = (addr + offset) & 0x7fff;
2374 return gvram[vramaddr];
2376 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2377 return gvram[vramaddr];
2381 #else // Others (77/7/8)
2382 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2383 return gvram[vramaddr];
2387 void DISPLAY::write_dma_data8(uint32_t addr, uint32_t data)
2389 uint32_t raddr = (addr & 0xffff) >> 7;
2390 if(write_dma_func_table[raddr] != NULL) {
2391 (this->*write_dma_func_table[raddr])(addr, (uint8_t) data);
2395 void DISPLAY::write_vram_data8(uint32_t addr, uint8_t data)
2398 uint32_t color = (addr >> 14) & 0x03;
2402 #if defined(_FM77AV_VARIANTS)
2403 if (active_page != 0) {
2404 offset = offset_point_bank1;
2406 offset = offset_point;
2409 offset = offset_point;
2411 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2412 if(vram_active_block != 0) offset = 0; // Don't scroll at BLOCK 1.
2415 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2416 if(display_mode == DISPLAY_MODE_8_400L) {
2418 uint32_t page_offset_alt = 0;
2420 if(addr >= 0x8000) {
2423 color = vram_bank & 0x03;
2424 if(color > 2) color = 0;
2426 pagemod = 0x8000 * color;
2427 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2428 if(vram_active_block != 0) page_offset_alt = 0x18000;
2430 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2431 // Reduce data transfer.
2432 tdata = gvram[vramaddr];
2434 naddr = (addr & 0x7fff) >> 4;
2435 gvram[vramaddr] = data;
2436 vram_wrote_table[naddr] = true;
2438 } else if(display_mode == DISPLAY_MODE_256k) {
2439 uint32_t page_offset_alt;
2441 #if defined(_FM77AV40)
2443 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2445 page_offset_alt = 0; // right?
2448 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2450 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
2451 tdata = gvram[vramaddr];
2453 naddr = (addr & page_mask) >> 3;
2454 gvram[vramaddr] = data;
2455 vram_wrote_table[naddr] = true;
2458 } else if(display_mode == DISPLAY_MODE_4096) {
2460 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2461 tdata = gvram[vramaddr];
2463 naddr = (addr & page_mask) >> 3;
2464 gvram[vramaddr] = data;
2465 vram_wrote_table[naddr] = true;
2469 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2470 tdata = gvram[vramaddr];
2472 naddr = (addr & page_mask) >> 4;
2473 gvram[vramaddr] = data;
2474 vram_wrote_table[naddr] = true;
2477 #elif defined(_FM77AV_VARIANTS)
2478 if(display_mode == DISPLAY_MODE_4096) {
2480 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2481 tdata = gvram[vramaddr];
2483 naddr = (addr & page_mask) >> 3;
2484 gvram[vramaddr] = data;
2485 vram_wrote_table[naddr] = true;
2489 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2490 tdata = gvram[vramaddr];
2492 naddr = (addr & page_mask) >> 4;
2493 gvram[vramaddr] = data;
2494 vram_wrote_table[naddr] = true;
2497 #elif defined(_FM77L4) //_FM77L4
2498 if(display_mode == DISPLAY_MODE_1_400L) {
2501 //if(multimode_accessflags[2]) return;
2502 vramaddr = ((addr + offset) & 0x3fff) + 0x8000;
2503 gvram[vramaddr] = data;
2506 vramaddr = (addr + offset) & 0x7fff;
2507 tdata = gvram[vramaddr];
2509 naddr = (addr & 0x7fff) >> 4;
2510 gvram[vramaddr] = data;
2511 vram_wrote_table[naddr] = true;
2518 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2519 tdata = gvram[vramaddr];
2521 naddr = (addr & 0x3fff) >> 4;
2522 gvram[vramaddr] = data;
2523 vram_wrote_table[naddr] = true;
2526 #else // Others (77/7/8)
2529 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2530 tdata = gvram[vramaddr];
2532 naddr = (addr & 0x3fff) >> 4;
2533 gvram[vramaddr] = data;
2534 vram_wrote_table[naddr] = true;
2540 uint32_t DISPLAY::read_cpu_vram_data8(uint32_t addr)
2543 #if defined(_FM77AV_VARIANTS)
2545 call_read_data8(alu, addr);
2548 return read_vram_data8(addr);
2551 uint32_t DISPLAY::read_dma_vram_data8(uint32_t addr)
2553 return read_vram_data8(addr);
2556 void DISPLAY::init_read_table(void)
2559 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
2560 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cpu_vram_data8;
2561 read_dma_func_table[_at >> 7] = &DISPLAY::read_dma_vram_data8;
2563 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
2564 read_cpu_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2565 read_dma_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2567 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
2568 read_cpu_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2569 read_dma_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2571 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
2572 read_cpu_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2573 read_dma_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2575 #if defined(_FM77AV_VARIANTS)
2576 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
2577 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2578 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2580 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
2581 read_cpu_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2582 read_dma_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2585 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
2586 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2587 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2590 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
2591 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2592 read_dma_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2594 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
2595 read_cpu_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2596 read_dma_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2600 uint32_t DISPLAY::read_console_ram(uint32_t addr)
2602 uint32_t raddr = addr & 0xfff;
2603 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2605 if(console_ram_bank >= 1) {
2606 return submem_console_av40[((console_ram_bank - 1) << 12) + raddr];
2610 return console_ram[raddr];
2613 uint32_t DISPLAY::read_work_ram(uint32_t addr)
2615 addr = addr & 0x3ff;
2616 return work_ram[addr];
2620 uint32_t DISPLAY::read_shared_ram(uint32_t addr)
2622 addr = addr - 0xd380;
2623 return shared_ram[addr];
2626 #if defined(_FM77AV_VARIANTS)
2627 uint32_t DISPLAY::read_hidden_ram(uint32_t addr)
2629 if(addr >= 0xd500) {
2630 return submem_hidden[addr - 0xd500];
2636 uint32_t DISPLAY::read_cgrom(uint32_t addr)
2638 #if defined(_FM77AV_VARIANTS)
2639 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2641 return submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)]; //FIXME
2644 return subsys_cg[(addr - 0xd800) + cgrom_bank * 0x800];
2646 return subsys_c[addr - 0xd800];
2650 uint32_t DISPLAY::read_subsys_monitor(uint32_t addr)
2652 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2654 return subsys_ram[addr - 0xe000];
2657 #if defined(_FM77AV_VARIANTS)
2658 switch(subrom_bank_using & 3) {
2660 return subsys_c[addr - 0xd800];
2663 return subsys_a[addr - 0xe000];
2666 return subsys_b[addr - 0xe000];
2669 return subsys_cg[addr - 0xe000];
2672 #elif defined(_FM77L4)
2674 return subsys_l4[addr - 0xb800];
2676 return subsys_c[addr - 0xd800];
2678 return subsys_c[addr - 0xd800];
2682 uint32_t DISPLAY::read_dma_data8(uint32_t addr)
2684 uint32_t raddr = (addr & 0xffff) >> 7;
2685 if(read_dma_func_table[raddr] != NULL) {
2686 return (this->*read_dma_func_table[raddr])(addr);
2691 uint32_t DISPLAY::read_data8(uint32_t addr)
2693 uint32_t raddr = addr;
2695 if(addr < 0x10000) {
2696 raddr = (addr & 0xffff) >> 7;
2697 if(read_cpu_func_table[raddr] != NULL) {
2698 return (this->*read_cpu_func_table[raddr])(addr);
2703 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2704 return dpalette_data[addr - FM7_SUBMEM_OFFSET_DPALETTE];
2707 #if defined(_FM77AV_VARIANTS)
2709 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2710 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2711 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2712 if(vram_active_block != 0) {
2716 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2717 if(display_mode == DISPLAY_MODE_8_400L) {
2718 uint32_t page_offset_alt = 0;
2721 color = (addr & 0x18000) >> 15;
2722 if(color > 2) color = 0;
2723 pagemod = 0x8000 * color;
2724 if (active_page != 0) {
2725 offset = offset_point_bank1 << 1;
2727 offset = offset_point << 1;
2729 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2730 if(vram_active_block != 0) {
2731 page_offset_alt = 0x18000;
2735 return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset_alt];
2738 return read_vram_data8(addr);
2745 * Vram accessing functions moved to vram.cpp .
2748 void DISPLAY::write_mmio(uint32_t addr, uint8_t data)
2751 uint8_t active_block_old;
2753 if(addr < 0xd400) return;
2755 #if !defined(_FM77AV_VARIANTS)
2756 addr = (addr - 0xd400) & 0x000f;
2757 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2758 addr = (addr - 0xd400) & 0x003f;
2759 #else // FM77AV40EX || FM77AV40SX
2760 addr = (addr - 0xd400) & 0x00ff;
2762 io_w_latch[addr] = (uint8_t)data;
2764 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4)
2767 set_cyclesteal((uint8_t)data);
2768 # if defined(_FM77L4)
2769 setup_400linemode((uint8_t)data);
2773 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2774 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2777 if(!kanjisub) return;
2778 kanjiaddr.w.h = 0x0000;
2779 kanjiaddr.b.h = (uint8_t) data;
2782 if(!kanjisub) return;
2783 kanjiaddr.w.h = 0x0000;
2784 kanjiaddr.b.l = (uint8_t)data;
2797 if(delay_busy) { // If WRITE after READ immediately.Perhaps use CLR insn.
2799 // Delay at least 5+ clocks (CLR $D40A or CLR (INDEX = $D40A))
2801 usec = (6000.0 * 1000.0) / 2000000.0;
2803 usec = (6000.0 * 1000.0) / 999000.0;
2805 register_event(this, EVENT_FM7SUB_DELAY_BUSY, usec, false, NULL); // NEXT CYCLE_
2813 #if defined(_FM77L4)
2815 if(stat_400linecard) {
2816 l4crtc->write_io8(0, data & 0x1f);
2820 if(stat_400linecard) {
2821 l4crtc->write_io8(1, data);
2822 // Update parameters.
2823 uint8_t crtc_addr = l4crtc->read_io8(0);
2824 const uint8_t *regs = l4crtc->get_regs();
2825 switch(crtc_addr & 0x1f) {
2828 cursor_addr.w.l &= 0x0ffc;
2829 cursor_addr.w.l |= (((uint16_t)regs[14]) << 10);
2830 cursor_addr.w.l |= (((uint16_t)regs[15]) << 2);
2832 cursor_addr.w.l += 2;
2834 cursor_addr.w.l &= 0xfff;
2836 if((crtc_addr & 0x1f) == 10) {
2838 if(event_id_l4_cursor_blink >= 0) {
2839 cancel_event(this, event_id_l4_cursor_blink);
2841 usec = ((data & 0x20) == 0) ? 160.0 : 320.0;
2842 usec = usec * 1000.0;
2843 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
2847 text_start_addr.w.l &= 0x03fc;
2848 text_start_addr.w.l |= (((uint16_t)data & 3) << 10);
2849 text_scroll_count++;
2850 if((text_scroll_count & 1) == 0) {
2855 text_start_addr.w.l &= 0xfc00;
2856 text_start_addr.w.l |= ((uint16_t)data << 2);
2857 text_scroll_count++;
2858 if((text_scroll_count & 1) == 0) {
2863 text_scroll_count++;
2864 if((text_scroll_count & 1) == 0) {
2866 cursor_addr.w.l &= 0x0ffc;
2867 cursor_addr.w.l |= (((uint16_t)regs[14]) << 10);
2868 cursor_addr.w.l |= (((uint16_t)regs[15]) << 2);
2870 cursor_addr.w.l += 2;
2872 cursor_addr.w.l &= 0xfff;
2883 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
2888 rval = (uint8_t)data;
2889 if(offset_changed[active_page]) {
2890 #if defined(_FM77AV_VARIANTS)
2891 if(active_page != 0) {
2892 tmp_offset_point[active_page].d = offset_point_bank1;
2894 tmp_offset_point[active_page].d = offset_point;
2897 tmp_offset_point[active_page].d = offset_point;
2900 tmp_offset_point[active_page].w.h = 0x0000;
2902 tmp_offset_point[active_page].b.h = rval;
2904 tmp_offset_point[active_page].b.l = rval;
2906 offset_changed[active_page] = !offset_changed[active_page];
2907 if(offset_changed[active_page]) {
2909 #if defined(_FM77AV_VARIANTS)
2910 if(active_page != 0) {
2912 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fff;
2914 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fe0;
2918 offset_point = tmp_offset_point[active_page].d & 0x007fff;
2920 offset_point = tmp_offset_point[active_page].d & 0x007fe0;
2924 offset_point = tmp_offset_point[active_page].d & 0x7fe0;
2928 #if defined(_FM77AV_VARIANTS)
2931 alu_write_cmdreg(data);
2934 alu_write_logical_color(data);
2937 alu_write_mask_reg(data);
2940 alu_write_disable_reg(data);
2943 alu_write_offsetreg_hi(data);
2946 alu_write_offsetreg_lo(data);
2949 alu_write_linepattern_hi(data);
2952 alu_write_linepattern_lo(data);
2954 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2956 console_ram_bank = (data & 0x18) >> 3;
2957 if(console_ram_bank > 2) console_ram_bank = 0;
2958 cgram_bank = data & 0x07;
2959 kanji_level2 = ((data & 0x80) == 0) ? false : true;
2961 case 0x2f: // VRAM BANK
2962 vram_bank = data & 0x03;
2963 if(vram_bank > 2) vram_bank = 0;
2973 call_write_data8(keyboard, 0x31, data);
2975 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2977 active_block_old = vram_active_block;
2978 vram_active_block = data & 0x01;
2979 if(vram_display_block != (((data & 0x10) != 0) ? 1 : 0)) vram_wrote = true;
2980 vram_display_block = ((data & 0x10) != 0) ? 1 : 0;
2981 if(vram_active_block != active_block_old) setup_display_mode();
2986 tmpvar.d = window_xbegin * 8;
2989 tmpvar.b.h = data & 0x03;
2991 tmpvar.b.l = data & 0xf8;
2993 if(mode320 || mode256k) {
2994 if(tmpvar.d > 320) tmpvar.d = 320;
2996 if(tmpvar.d > 640) tmpvar.d = 640;
2998 window_xbegin = tmpvar.d / 8;
3003 tmpvar.d = window_xend * 8;
3006 tmpvar.b.h = data & 0x03;
3008 tmpvar.b.l = data & 0xf8;
3010 if(mode320 || mode256k) {
3011 if(tmpvar.d > 320) tmpvar.d = 320;
3013 if(tmpvar.d > 640) tmpvar.d = 640;
3015 window_xend = tmpvar.d / 8;
3020 tmpvar.d = window_low;
3023 tmpvar.b.h = data & 0x03;
3025 tmpvar.b.l = data & 0xff;
3027 if(display_mode == DISPLAY_MODE_8_400L) {
3028 if(tmpvar.d > 400) tmpvar.d = 400;
3031 if(tmpvar.d > 400) tmpvar.d = 400;
3033 window_low = tmpvar.d;
3038 tmpvar.d = window_high;
3041 tmpvar.b.h = data & 0x03;
3043 tmpvar.b.l = data & 0xff;
3045 if(display_mode == DISPLAY_MODE_8_400L) {
3046 if(tmpvar.d > 400) tmpvar.d = 400;
3049 if(tmpvar.d > 400) tmpvar.d = 400;
3051 window_high = tmpvar.d;
3057 #if defined(_FM77AV_VARIANTS)
3059 if((addr >= 0x13) && (addr <= 0x1a)) {
3060 alu_write_cmpdata_reg(addr - 0x13, data);
3061 } else if((addr >= 0x1c) && (addr <= 0x1e)) {
3062 alu_write_tilepaint_data(addr, data);
3063 } else if((addr >= 0x24) && (addr <= 0x2b)) {
3064 alu_write_line_position(addr - 0x24, data);
3071 void DISPLAY::init_write_table(void)
3074 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
3075 write_cpu_func_table[_at >> 7] = &DISPLAY::write_cpu_vram_data8;
3076 write_dma_func_table[_at >> 7] = &DISPLAY::write_dma_vram_data8;
3078 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
3079 write_cpu_func_table[_at >> 7] = &DISPLAY::write_console_ram;
3080 write_dma_func_table[_at >> 7] = &DISPLAY::write_console_ram;
3082 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
3083 write_cpu_func_table[_at >> 7] = &DISPLAY::write_work_ram;
3084 write_dma_func_table[_at >> 7] = &DISPLAY::write_work_ram;
3086 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
3087 write_cpu_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
3088 write_dma_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
3090 #if defined(_FM77AV_VARIANTS)
3091 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
3092 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
3093 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
3095 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
3096 write_cpu_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
3097 write_dma_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
3100 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
3101 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
3102 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
3105 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
3106 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
3107 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
3108 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
3110 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
3111 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
3112 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
3115 for(_at = 0xd800; _at < 0x10000; _at += 0x80) {
3116 write_cpu_func_table[_at >> 7] = &DISPLAY::write_dummy;
3117 write_dma_func_table[_at >> 7] = &DISPLAY::write_dummy;
3122 void DISPLAY::write_console_ram(uint32_t addr, uint8_t data)
3124 uint32_t raddr = addr & 0xfff;
3125 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3127 if(console_ram_bank >= 1) {
3128 submem_console_av40[((console_ram_bank - 1) << 12) + raddr] = data;
3133 console_ram[raddr] = data;
3137 void DISPLAY::write_work_ram(uint32_t addr, uint8_t data)
3139 uint32_t raddr = addr & 0xfff;
3140 work_ram[raddr] = data;
3144 void DISPLAY::write_shared_ram(uint32_t addr, uint8_t data)
3146 uint32_t raddr = addr & 0x7f;
3147 shared_ram[raddr] = data;
3151 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
3152 void DISPLAY::write_subsys_cgram(uint32_t addr, uint8_t data)
3154 uint32_t raddr = addr - 0xd800;
3155 if(ram_protect) return;
3156 if(!monitor_ram) return;
3157 submem_cgram[cgram_bank * 0x0800 + raddr] = data; //FIXME
3160 void DISPLAY::write_subsys_ram(uint32_t addr, uint8_t data)
3162 if(ram_protect) return;
3163 if(!monitor_ram) return;
3164 subsys_ram[addr - 0xe000] = data; //FIXME
3168 #if defined(_FM77AV_VARIANTS)
3169 void DISPLAY::write_hidden_ram(uint32_t addr, uint8_t data)
3171 submem_hidden[addr - 0xd500] = data;
3176 void DISPLAY::write_cpu_vram_data8(uint32_t addr, uint8_t data)
3178 uint32_t color = (addr & 0xc000) >> 14;
3179 #if defined(_FM77AV_VARIANTS)
3181 call_read_data8(alu, addr);
3185 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3186 if(display_mode == DISPLAY_MODE_8_400L) {
3187 color = vram_bank & 0x03;
3188 if(color > 2) color = 0;
3191 #if defined(_FM77L4)
3195 if(!(multimode_accessflags[2])) write_vram_data8(addr & 0x7fff, data);
3198 } else if(addr < 0x9800) {
3201 addr = addr & 0x0fff;
3202 if(text_vram[addr] != data) {
3203 text_vram[addr] = data;
3205 x = ((addr / 2) % 40) / 8;
3206 y = (addr / 2) / 40;
3207 } else { // Width 80
3208 x = ((addr / 2) % 80) / 8;
3209 y = (addr / 2) / 80;
3211 for(int yy = 0; yy < 8; yy++) {
3212 naddr = (y + yy) * 5 + x;
3213 vram_wrote_table[naddr] = true;
3223 //if((multimode_accessmask & (1 << color)) != 0) return;
3224 if(multimode_accessflags[color]) return;
3226 write_vram_data8(addr & 0xffff, data);
3229 void DISPLAY::write_dma_vram_data8(uint32_t addr, uint8_t data)
3231 uint32_t color = (addr & 0xc000) >> 14;
3232 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3233 if(display_mode == DISPLAY_MODE_8_400L) {
3234 color = vram_bank & 0x03;
3235 if(color > 2) color = 0;
3239 //if((multimode_accessmask & (1 << color)) != 0) return;
3240 if(multimode_accessflags[color]) return;
3242 write_vram_data8(addr & 0xffff, data);
3245 void DISPLAY::write_dummy(uint32_t addr, uint8_t data)
3249 void DISPLAY::write_data8(uint32_t addr, uint32_t data)
3253 //uint32_t page_offset = 0x0000;
3254 uint8_t val8 = data & 0xff;
3255 uint32_t color = (addr & 0xc000) >> 14;
3258 if(addr < 0x10000) {
3259 void (*_write_func)(uint32_t, uint32_t);
3260 raddr = (addr & 0xffff) >> 7;
3261 if(write_cpu_func_table[raddr] != NULL) {
3262 (this->*write_cpu_func_table[raddr])(addr, (uint8_t)data);
3268 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
3269 set_dpalette(addr - FM7_SUBMEM_OFFSET_DPALETTE, val8);
3273 #if defined(_FM77AV_VARIANTS)
3275 else if(addr == FM7_SUBMEM_OFFSET_APALETTE_R) {
3276 set_apalette_r(val8);
3278 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_G) {
3279 set_apalette_g(val8);
3281 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_B) {
3282 set_apalette_b(val8);
3284 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_HI) {
3285 set_apalette_index_hi(val8);
3287 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_LO) {
3288 set_apalette_index_lo(val8);
3292 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
3293 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
3294 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3295 if(display_mode == DISPLAY_MODE_8_400L) {
3298 uint32_t page_offset_alt = 0;
3300 color = (addr & 0x18000) >> 15;
3301 if(color > 2) color = 0;
3302 if (active_page != 0) {
3303 offset = offset_point_bank1 << 1;
3305 offset = offset_point << 1;
3307 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3308 if(vram_active_block != 0) {
3309 page_offset_alt = 0x18000;
3313 naddr = (addr & 0x7fff) >> 4;
3314 pagemod = 0x8000 * color;
3315 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
3316 tdata = gvram[vramaddr];
3317 if(tdata != (uint8_t)data) {
3318 gvram[vramaddr] = data;
3319 vram_wrote_table[naddr] = true;
3323 write_vram_data8(addr, data);
3325 write_vram_data8(addr, data);
3327 //if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
3334 uint32_t DISPLAY::read_bios(const _TCHAR *name, uint8_t *ptr, uint32_t size)
3340 if((name == NULL) || (ptr == NULL)) return 0;
3341 s = create_local_path(name);
3342 if(s == NULL) return 0;
3344 if(!fio.Fopen(s, FILEIO_READ_BINARY)) return 0;
3345 blocks = fio.Fread(ptr, size, 1);
3348 return blocks * size;
3352 void DISPLAY::initialize()
3356 memset(io_w_latch, 0xff, sizeof(io_w_latch));
3357 screen_update_flag = true;
3358 memset(gvram, 0x00, sizeof(gvram));
3359 vram_wrote_shadow = false;
3360 memset(gvram_shadow, 0x00, sizeof(gvram_shadow));
3361 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
3362 for(i = 0; i < 411; i++) vram_draw_table[i] = false;
3363 force_update = false;
3365 memset(console_ram, 0x00, sizeof(console_ram));
3366 memset(work_ram, 0x00, sizeof(work_ram));
3367 memset(shared_ram, 0x00, sizeof(shared_ram));
3368 memset(subsys_c, 0xff, sizeof(subsys_c));
3369 need_transfer_line = true;
3370 frame_skip_count_draw = 3;
3371 frame_skip_count_transfer = 3;
3373 diag_load_subrom_c = false;
3375 if(read_bios(_T(ROM_FM8_SUBSYSTEM), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
3376 this->out_debug_log(_T("SUBSYSTEM ROM READING : %s"), diag_load_subrom_c ? "OK" : "NG");
3378 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_C), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
3379 this->out_debug_log(_T("SUBSYSTEM ROM Type C READING : %s"), diag_load_subrom_c ? "OK" : "NG");
3381 #if defined(_FM77AV_VARIANTS)
3382 memset(subsys_a, 0xff, sizeof(subsys_a));
3383 memset(subsys_b, 0xff, sizeof(subsys_b));
3384 memset(subsys_cg, 0xff, sizeof(subsys_cg));
3385 memset(submem_hidden, 0x00, sizeof(submem_hidden));
3387 diag_load_subrom_a = false;
3388 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_A), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
3389 this->out_debug_log(_T("SUBSYSTEM ROM Type A READING : %s"), diag_load_subrom_a ? "OK" : "NG");
3391 diag_load_subrom_b = false;
3392 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_B), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
3393 this->out_debug_log(_T("SUBSYSTEM ROM Type B READING : %s"), diag_load_subrom_b ? "OK" : "NG");
3395 diag_load_subrom_cg = false;
3396 if(read_bios(_T(ROM_FM7_SUBSYSTEM_CG), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
3397 this->out_debug_log(_T("SUBSYSTEM CG ROM READING : %s"), diag_load_subrom_cg ? "OK" : "NG");
3398 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
3399 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3400 memset(subsys_ram, 0x00, sizeof(subsys_ram));
3401 memset(submem_cgram, 0x00, sizeof(submem_cgram));
3402 memset(submem_console_av40, 0x00, sizeof(submem_console_av40));
3406 #if defined(_FM77L4)
3407 memset(subsys_cg_l4, 0xff, sizeof(subsys_cg_l4));
3408 memset(subsys_l4, 0xff, sizeof(subsys_l4));
3410 read_bios(_T(ROM_FM77_400LINE_ANKCG), subsys_cg_l4, sizeof(subsys_cg_l4));
3411 read_bios(_T(ROM_FM77_400LINE_SUBSYS), subsys_l4, sizeof(subsys_l4));
3412 memset(text_vram, 0x00, sizeof(text_vram));
3413 //memset(crtc_regs, 0x00, sizeof(crtc_regs));
3417 text_width40 = false;
3420 cursor_blink = true;
3422 text_start_addr.d = 0x0000;
3430 text_scroll_count = 0;
3432 event_id_l4_cursor_blink = -1;
3433 event_id_l4_text_blink = -1;
3439 #if defined(_FM77AV_VARIANTS)
3441 apalette_index.d = 0;
3442 for(i = 0; i < 4096; i++) {
3443 analog_palette_r[i] = i & 0x0f0;
3444 analog_palette_g[i] = (i & 0xf00) >> 4;
3445 analog_palette_b[i] = (i & 0x00f) << 4;
3447 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
3450 for(i = 0; i < 8; i++) set_dpalette(i, i);
3451 #if defined(USE_GREEN_DISPLAY)
3452 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3453 use_green_monitor = false;
3456 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3457 //#if defined(_FM77AV_VARIANTS)
3458 hblank_event_id = -1;
3459 hdisp_event_id = -1;
3460 vsync_event_id = -1;
3461 vstart_event_id = -1;
3468 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
3469 is_cyclesteal = true;
3471 is_cyclesteal = false;
3473 multimode_accessmask = multimode_dispmask = 0;
3474 for(i = 0; i < 4; i++) {
3475 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
3476 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
3479 prev_clock = SUBCLOCK_NORMAL;
3483 key_firq_req = false; //firq_mask = true;
3484 frame_skip_count_transfer = 3;
3485 frame_skip_count_draw = 3;
3486 #if !defined(FIXED_FRAMEBUFFER_SIZE)
3487 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
3489 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
3491 emu->set_vm_screen_lines(200);
3492 #if defined(_FM77AV40SX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3493 mode400line = false;
3495 #elif defined(_FM77L4)
3496 mode400line = false;
3499 palette_changed = true;
3500 //#if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
3501 //register_vline_event(this);
3502 register_frame_event(this);
3504 setup_display_mode();
3507 void DISPLAY::release()
3511 #define STATE_VERSION 12
3513 bool DISPLAY::process_state(FILEIO *state_fio, bool loading)
3515 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
3518 if(!state_fio->StateCheckInt32(this_device_id)) {
3523 state_fio->StateBool(delay_busy);
3524 state_fio->StateBool(halt_flag);
3525 state_fio->StateInt32(active_page);
3526 state_fio->StateBool(sub_busy);
3527 state_fio->StateBool(crt_flag);
3528 state_fio->StateBool(vram_wrote);
3529 state_fio->StateBool(is_cyclesteal);
3531 state_fio->StateBool(clock_fast);
3533 #if defined(_FM77AV_VARIANTS)
3534 state_fio->StateBool(subcpu_resetreq);
3535 state_fio->StateBool(power_on_reset);
3537 state_fio->StateBool(cancel_request);
3538 state_fio->StateBool(key_firq_req);
3539 state_fio->StateInt32(display_mode);
3540 state_fio->StateUint32(prev_clock);
3542 state_fio->StateBuffer(dpalette_data, sizeof(dpalette_data), 1);
3543 state_fio->StateUint8(multimode_accessmask);
3544 state_fio->StateUint8(multimode_dispmask);
3546 state_fio->StateUint32(offset_point);
3547 #if defined(_FM77AV_VARIANTS)
3548 state_fio->StateUint32(offset_point_bank1);
3550 //for(i = 0; i < 2; i++) {
3551 state_fio->StateBuffer(tmp_offset_point, sizeof(tmp_offset_point), 1);
3552 state_fio->StateBuffer(offset_changed, sizeof(offset_changed), 1);
3554 state_fio->StateBool(offset_77av);
3555 state_fio->StateBool(diag_load_subrom_c);
3556 state_fio->StateBuffer(io_w_latch, sizeof(io_w_latch), 1);
3557 state_fio->StateBuffer(console_ram, sizeof(console_ram), 1);
3558 state_fio->StateBuffer(work_ram, sizeof(work_ram), 1);
3559 state_fio->StateBuffer(shared_ram, sizeof(shared_ram), 1);
3560 state_fio->StateBuffer(subsys_c, sizeof(subsys_c), 1);
3561 state_fio->StateBuffer(gvram, sizeof(gvram), 1);
3562 state_fio->StateBuffer(gvram_shadow, sizeof(gvram_shadow), 1);
3563 #if defined(_FM77_VARIANTS)
3564 state_fio->StateBool(kanjisub);
3565 state_fio->StateUint32(kanjiaddr.d);
3566 # if defined(_FM77L4)
3567 state_fio->StateBool(mode400line);
3568 state_fio->StateBool(stat_400linecard);
3570 #elif defined(_FM77AV_VARIANTS)
3571 state_fio->StateBool(kanjisub);
3572 state_fio->StateUint32(kanjiaddr.d);
3573 state_fio->StateBool(mode320);
3574 state_fio->StateInt32(cgrom_bank);
3575 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3576 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3577 state_fio->StateInt32(vram_bank);
3579 state_fio->StateUint32(displine);
3580 state_fio->StateUint8(subrom_bank);
3581 state_fio->StateUint8(subrom_bank_using);
3582 state_fio->StateBool(nmi_enable);
3583 state_fio->StateBool(use_alu);
3584 state_fio->StateUint32(apalette_index.d);
3585 state_fio->StateBuffer(analog_palette_r, sizeof(analog_palette_r), 1);
3586 state_fio->StateBuffer(analog_palette_g, sizeof(analog_palette_g), 1);
3587 state_fio->StateBuffer(analog_palette_b, sizeof(analog_palette_b), 1);
3588 state_fio->StateBool(diag_load_subrom_a);
3589 state_fio->StateBool(diag_load_subrom_b);
3590 state_fio->StateBool(diag_load_subrom_cg);
3592 state_fio->StateBuffer(subsys_a, sizeof(subsys_a), 1);
3593 state_fio->StateBuffer(subsys_b, sizeof(subsys_b), 1);
3594 state_fio->StateBuffer(subsys_cg, sizeof(subsys_cg), 1);
3595 state_fio->StateBuffer(submem_hidden, sizeof(submem_hidden), 1);
3596 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3597 state_fio->StateBool(mode400line);
3598 state_fio->StateBool(mode256k);
3599 state_fio->StateBool(monitor_ram);
3600 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3601 state_fio->StateUint16(window_low);
3602 state_fio->StateUint16(window_high);
3603 state_fio->StateUint16(window_xbegin);
3604 state_fio->StateUint16(window_xend);
3605 state_fio->StateBool(window_opened);
3607 state_fio->StateBool(kanji_level2);
3608 state_fio->StateUint8(vram_active_block);
3609 state_fio->StateUint8(vram_display_block);
3610 state_fio->StateUint8(console_ram_bank);
3611 state_fio->StateBool(ram_protect);
3612 state_fio->StateUint8(cgram_bank);
3613 state_fio->StateBuffer(subsys_ram, sizeof(subsys_ram), 1);
3614 state_fio->StateBuffer(submem_cgram, sizeof(submem_cgram), 1);
3615 state_fio->StateBuffer(submem_console_av40, sizeof(submem_console_av40), 1);
3621 state_fio->StateInt32(nmi_event_id);
3622 //#if defined(_FM77AV_VARIANTS)
3623 state_fio->StateInt32(hblank_event_id);
3624 state_fio->StateInt32(hdisp_event_id);
3625 state_fio->StateInt32(vsync_event_id);
3626 state_fio->StateInt32(vstart_event_id);
3628 state_fio->StateBool(firq_mask);
3629 state_fio->StateBool(vram_accessflag);
3630 state_fio->StateInt8(display_page);
3631 state_fio->StateInt8(display_page_bak);
3632 state_fio->StateBool(vblank);
3633 state_fio->StateBool(vsync);
3634 state_fio->StateBool(hblank);
3635 state_fio->StateInt32(vblank_count);
3637 #if defined(_FM77L4)
3638 state_fio->StateBuffer(subsys_cg_l4, sizeof(subsys_cg_l4), 1);
3639 state_fio->StateBuffer(subsys_l4, sizeof(subsys_l4), 1);
3640 state_fio->StateBuffer(text_vram, sizeof(text_vram), 1);
3641 //state_fio->Fwrite(crtc_regs, sizeof(crtc_regs), 1);
3642 state_fio->StateBool(workram_l4);
3643 state_fio->StateBool(cursor_lsb);
3644 state_fio->StateBool(text_width40);
3646 state_fio->StateBool(text_blink);
3647 state_fio->StateBool(cursor_blink);
3649 state_fio->StateUint32(text_start_addr.d);
3650 state_fio->StateUint32(text_lines);
3651 state_fio->StateUint32(text_xmax);
3653 state_fio->StateUint32(cursor_addr.d);
3654 state_fio->StateInt32(cursor_start);
3655 state_fio->StateInt32(cursor_end);
3656 state_fio->StateUint8(cursor_type);
3657 state_fio->StateUint8(text_scroll_count);
3659 state_fio->StateInt32(event_id_l4_cursor_blink);
3660 state_fio->StateInt32(event_id_l4_text_blink);
3666 crt_flag_bak = true;
3667 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
3668 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
3670 for(addr = 0; addr < 8; addr++) set_dpalette(addr, addr);
3671 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3672 #if defined(USE_GREEN_DISPLAY)
3673 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3677 for(addr = 0; addr < 8; addr++) set_dpalette(addr, dpalette_data[addr]);
3678 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3679 #if defined(USE_GREEN_DISPLAY)
3680 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3682 for(i = 0; i < 4; i++) {
3683 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
3684 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
3687 #if defined(_FM77_VARIANTS)
3688 # if defined(_FM77L4)
3690 #elif defined(_FM77AV_VARIANTS)
3691 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3692 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3694 screen_update_flag = true;
3695 for(i = 0; i < 4096; i++) calc_apalette(i);
3696 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
3699 palette_changed = true;
3700 vram_wrote_shadow = true; // Force Draw
3701 this->draw_screen();
3703 frame_skip_count_draw = 3;
3704 frame_skip_count_transfer = 3;
3705 need_transfer_line = true;
3706 #if defined(USE_GREEN_DISPLAY) && defined(USE_MONITOR_TYPE)
3707 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3708 switch(config.monitor_type) {
3709 case FM7_MONITOR_GREEN:
3710 use_green_monitor = true;
3712 case FM7_MONITOR_STANDARD:
3714 use_green_monitor = false;
3718 //use_green_monitor = false;
3720 force_update = true;
3721 setup_display_mode();