2 * Common source code project -> FM-7 -> Display
3 * (C) 2015 K.Ohta <whatisthis.sowhat _at_ gmail.com>
5 * Feb 10, 2015 : Initial.
9 #include "emu_template.h"
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_TEMPLATE* 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)
47 #if defined(USE_GREEN_DISPLAY)
48 use_green_monitor = false;
51 set_device_name(_T("DISPLAY SUBSYSTEM"));
59 void DISPLAY::reset_some_devices()
63 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
64 call_write_signal(mainio, SIG_FM7_SUB_HALT, 0x00, 0xff);
67 palette_changed = true;
68 multimode_accessmask = 0;
69 multimode_dispmask = 0;
70 for(i = 0; i < 4; i++) {
71 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
72 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
74 //firq_mask = false; // 20180215 Thanks to Ryu takegami.
75 //cancel_request = false;
76 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
77 switch(config.cpu_type){
86 prev_clock = SUBCLOCK_NORMAL;
88 prev_clock = SUBCLOCK_SLOW;
93 for(i = 0; i < 2; i++) {
94 offset_changed[i] = true;
95 tmp_offset_point[i].d = 0;
98 vram_wrote_shadow = true;
99 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
100 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
104 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
111 if(hblank_event_id >= 0) cancel_event(this, hblank_event_id);
112 if(hdisp_event_id >= 0) cancel_event(this, hdisp_event_id);
114 if(vsync_event_id >= 0) cancel_event(this, vsync_event_id);
115 if(vstart_event_id >= 0) cancel_event(this, vstart_event_id);
116 hblank_event_id = -1;
119 vstart_event_id = -1;
121 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
122 usec = 0.33 * 1000.0;
123 vm->set_vm_frame_rate(55.40);
125 usec = 0.51 * 1000.0;
126 vm->set_vm_frame_rate(FRAMES_PER_SEC);
129 //register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
130 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
131 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0xff, 0xff);
134 display_page_bak = 0;
136 #if defined(_FM77AV_VARIANTS)
138 offset_point_bank1 = 0;
140 subcpu_resetreq = false;
141 subrom_bank_using = subrom_bank;
146 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
148 vram_display_block = 0;
149 vram_active_block = 0;
151 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
156 window_opened = false;
161 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
162 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
163 call_write_signal(alu, SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400: 200, 0xffff);
164 call_write_signal(alu, SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xffffffff : 0, 0xffffffff);
166 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
167 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
168 call_write_signal(alu, SIG_ALU_400LINE, 0, 0xffffffff);
170 call_write_signal(alu, SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
171 call_write_signal(alu, SIG_ALU_PLANES, 3, 3);
173 for(i = 0; i < 8; i++) set_dpalette(i, i);
174 #if defined(USE_GREEN_DISPLAY)
175 //memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
176 for(i = 0; i < 8; i++) dpalette_pixel_green[i] = dpalette_green_tmp[i];
178 //memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
179 for(i = 0; i < 8; i++) dpalette_pixel[i] = dpalette_pixel_tmp[i];
180 //do_firq(!firq_mask && key_firq_req);
182 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
183 //kanjisub = false; // Fixed by Ryu takegami
184 kanjiaddr.d = 0x00000000;
185 # if defined(_FM77L4)
187 stat_400linecard = false;
192 frame_skip_count_draw = 3;
193 frame_skip_count_transfer = 3;
194 need_transfer_line = true;
195 setup_display_mode();
200 void DISPLAY::reset()
204 vram_accessflag = true;
205 display_mode = DISPLAY_MODE_8_200L;
207 crt_flag = false; // Fixed by Ryu Takegami
208 screen_update_flag = true;
209 crt_flag_bak = false;
210 cancel_request = false;
211 #if defined(_FM77AV_VARIANTS)
213 apalette_index.d = 0;
214 for(i = 0; i < 4096; i++) {
215 analog_palette_r[i] = i & 0x0f0;
216 analog_palette_g[i] = (i & 0xf00) >> 4;
217 analog_palette_b[i] = (i & 0x00f) << 4;
219 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
223 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
230 #elif defined(_FM77L4)
232 stat_400linecard = false;
236 text_width40 = false;
241 text_start_addr.d = 0x0000;
249 text_scroll_count = 0;
255 uint8_t *regs = l4crtc->get_regs();
256 display_mode = DISPLAY_MODE_1_400L;
257 if(event_id_l4_cursor_blink >= 0) {
258 cancel_event(this, event_id_l4_cursor_blink);
260 if(event_id_l4_text_blink >= 0) {
261 cancel_event(this, event_id_l4_text_blink);
263 event_id_l4_cursor_blink = -1;
264 event_id_l4_text_blink = -1;
266 usec = ((regs[10] & 0x20) == 0) ? 160.0 : 320.0;
267 usec = usec * 1000.0;
268 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, usec, true, &event_id_l4_cursor_blink);
269 usec = 160.0 * 1000.0;
270 register_event(this, EVENT_FM7SUB_TEXT_BLINK, usec, true, &event_id_l4_text_blink);
273 //memset(crtc_regs, 0x00, sizeof(crtc_regs));
276 #if !defined(FIXED_FRAMEBUFFER_SIZE)
277 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
279 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
281 emu->set_vm_screen_lines(200);
283 reset_some_devices();
285 #if defined(_FM77AV_VARIANTS)
286 power_on_reset = false;
287 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
289 // for(i = 0; i < 8; i++) set_dpalette(i, i);
292 for(i = 0; i < 8; i++) set_dpalette(i, i);
293 #if defined(USE_GREEN_DISPLAY) && defined(USE_MONITOR_TYPE)
294 for(i = 0; i < 8; i++) dpalette_pixel_green[i] = dpalette_green_tmp[i];
295 // memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
296 switch(config.monitor_type) {
297 case FM7_MONITOR_GREEN:
298 use_green_monitor = true;
300 case FM7_MONITOR_STANDARD:
302 use_green_monitor = false;
306 //use_green_monitor = false;
310 //memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
311 for(i = 0; i < 8; i++) dpalette_pixel[i] = dpalette_pixel_tmp[i];
314 if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
315 register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
318 key_firq_req = false;
323 void DISPLAY::reset_subcpu(bool _check_firq)
325 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0, 1);
326 call_write_signal(subcpu, SIG_CPU_BUSREQ, 0, 1);
329 do_firq(!firq_mask && key_firq_req);
332 void DISPLAY::setup_display_mode(void)
334 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
335 if(display_mode == DISPLAY_MODE_8_400L) {
336 page_offset = 0x0000;
337 pagemod_mask = 0x18000;
339 } else if(display_mode == DISPLAY_MODE_256k) {
340 if(active_page != 0) {
341 page_offset = 0xc000;
343 page_offset = 0x0000;
345 pagemod_mask = 0xe000;
347 } else if(display_mode == DISPLAY_MODE_4096) {
348 if(active_page != 0) {
349 page_offset = 0xc000;
351 page_offset = 0x0000;
353 pagemod_mask = 0xe000;
356 if(active_page != 0) {
357 page_offset = 0xc000;
359 page_offset = 0x0000;
361 pagemod_mask = 0xc000;
364 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
365 if(vram_active_block != 0) page_offset += 0x18000;
367 #elif defined(_FM77AV_VARIANTS)
370 pagemod_mask = 0xe000;
371 } else { // 640x200, 8colors
373 pagemod_mask = 0xc000;
375 if(active_page != 0) {
376 page_offset = 0xc000;
378 page_offset = 0x0000;
380 #elif defined(_FM77L4)
381 if(display_mode == DISPLAY_MODE_1_400L) {
383 pagemod_mask = 0x0000;
384 page_offset = 0x0000;
385 } else { // 640x200, 8colors
387 pagemod_mask = 0xc000;
388 page_offset = 0x0000;
390 page_offset = 0x0000;
392 page_offset = 0x0000;
393 pagemod_mask = 0xc000;
398 void DISPLAY::update_config()
404 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
410 * Vram accessing functions moved to vram.cpp .
413 void DISPLAY::do_irq(bool flag)
415 call_write_signal(subcpu, SIG_CPU_IRQ, flag ? 1: 0, 1);
418 void DISPLAY::do_firq(bool flag)
420 call_write_signal(subcpu, SIG_CPU_FIRQ, flag ? 1: 0, 1);
423 void DISPLAY::do_nmi(bool flag)
425 #if defined(_FM77AV_VARIANTS)
426 if(!nmi_enable) flag = false;
428 call_write_signal(subcpu, SIG_CPU_NMI, flag ? 1 : 0, 1);
431 void DISPLAY::set_multimode(uint8_t val)
434 multimode_accessmask = val & 0x07;
435 multimode_dispmask = (val & 0x70) >> 4;
436 for(int i = 0; i < 4; i++) {
437 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
438 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
441 # if defined(_FM77AV_VARIANTS)
442 call_write_signal(alu, SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
447 uint8_t DISPLAY::get_multimode(void)
453 val = multimode_accessmask & 0x07;
454 val |= ((multimode_dispmask << 4) & 0x70);
460 uint8_t DISPLAY::get_cpuaccessmask(void)
462 return multimode_accessmask & 0x07;
465 void DISPLAY::set_dpalette(uint32_t addr, uint8_t val)
469 // if(dpalette_data[addr] != (val | 0xf8)) {
470 dpalette_data[addr] = val | 0xf8; //0b11111000;
471 b = ((val & 0x01) != 0x00)? 255 : 0x00;
472 r = ((val & 0x02) != 0x00)? 255 : 0x00;
473 g = ((val & 0x04) != 0x00)? 255 : 0x00;
475 dpalette_pixel_tmp[addr] = RGB_COLOR(r, g, b);
476 #if defined(USE_GREEN_DISPLAY)
477 static const scrntype_t colortable[8] = {0, 48, 70, 100, 140, 175, 202, 255};
478 g = colortable[val & 0x07];
479 b = r = ((val & 0x07) > 4) ? 48 : 0;
480 dpalette_green_tmp[addr] = RGB_COLOR(r, g, b);
482 palette_changed = true;
486 uint8_t DISPLAY::get_dpalette(uint32_t addr)
494 data = dpalette_data[addr];
499 void DISPLAY::halt_subcpu(void)
501 //call_write_signal(subcpu, SIG_CPU_BUSREQ, 0x01, 0x01);
502 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0x01, 0x01);
505 void DISPLAY::go_subcpu(void)
507 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0x00, 0x01);
510 void DISPLAY::enter_display(void)
515 subclock = SUBCLOCK_NORMAL;
517 subclock = SUBCLOCK_SLOW;
519 if(!(is_cyclesteal) && (vram_accessflag)) {
520 subclock = subclock / 3;
522 if(prev_clock != subclock) {
523 vm->set_cpu_clock(subcpu, subclock);
525 prev_clock = subclock;
529 void DISPLAY::leave_display(void)
533 void DISPLAY::halt_subsystem(void)
539 void DISPLAY::restart_subsystem(void)
542 #if defined(_FM77AV_VARIANTS)
543 if(subcpu_resetreq) {
544 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
545 reset_some_devices();
546 power_on_reset = true;
554 void DISPLAY::set_crtflag(void)
561 void DISPLAY::reset_crtflag(void)
568 uint8_t DISPLAY::acknowledge_irq(void)
570 cancel_request = false;
576 uint8_t DISPLAY::beep(void)
578 call_write_signal(mainio, FM7_MAINIO_BEEP, 0x01, 0x01);
579 return 0xff; // True?
584 uint8_t DISPLAY::attention_irq(void)
586 call_write_signal(mainio, FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
591 void DISPLAY::set_cyclesteal(uint8_t val)
594 # if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
598 is_cyclesteal = true;
600 is_cyclesteal = false;
607 void DISPLAY::setup_400linemode(uint8_t val)
611 cursor_lsb = ((val & 0x10) != 0);
612 text_width40 = ((val & 0x08) != 0);
613 workram_l4 = ((val & 0x04) != 0);
614 bool tmpmode = ((val & 0x02) != 0);
615 if(tmpmode != mode400line) {
616 int oldmode = display_mode;
617 mode400line = tmpmode;
618 if(mode400line && stat_400linecard) {
619 display_mode = DISPLAY_MODE_1_400L;
621 display_mode = DISPLAY_MODE_8_200L;
623 if(oldmode != display_mode) {
625 if(display_mode == DISPLAY_MODE_1_400L) {
626 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
627 for(int y = 0; y < 400; y++) {
628 pp = emu->get_screen_buffer(y);
629 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
633 vm->set_vm_frame_rate(FRAMES_PER_SEC);
634 #if !defined(FIXED_FRAMEBUFFER_SIZE)
635 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
636 for(int y = 0; y < 200; y++) {
637 pp = emu->get_screen_buffer(y);
638 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
641 for(int y = 0; y < 400; y++) {
642 pp = emu->get_screen_buffer(y);
643 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
648 setup_display_mode();
656 uint8_t DISPLAY::set_vramaccess(void)
658 vram_accessflag = true;
664 void DISPLAY::reset_vramaccess(void)
666 vram_accessflag = false;
671 uint8_t DISPLAY::reset_subbusy(void)
678 void DISPLAY::set_subbusy(void)
684 #if defined(_FM77AV_VARIANTS)
686 void DISPLAY::alu_write_cmdreg(uint32_t val)
688 call_write_data8(alu, ALU_CMDREG, val);
689 if((val & 0x80) != 0) {
697 void DISPLAY::alu_write_logical_color(uint8_t val)
699 uint32_t data = (uint32_t)val;
700 call_write_data8(alu, ALU_LOGICAL_COLOR, data);
704 void DISPLAY::alu_write_mask_reg(uint8_t val)
706 uint32_t data = (uint32_t)val;
707 call_write_data8(alu, ALU_WRITE_MASKREG, data);
711 void DISPLAY::alu_write_cmpdata_reg(int addr, uint8_t val)
713 uint32_t data = (uint32_t)val;
715 call_write_data8(alu, ALU_CMPDATA_REG + addr, data);
719 void DISPLAY::alu_write_disable_reg(uint8_t val)
721 uint32_t data = (uint32_t)val;
722 call_write_data8(alu, ALU_BANK_DISABLE, data);
726 void DISPLAY::alu_write_tilepaint_data(uint32_t addr, uint8_t val)
728 uint32_t data = (uint32_t)val;
731 call_write_data8(alu, ALU_TILEPAINT_B, data);
734 call_write_data8(alu, ALU_TILEPAINT_R, data);
737 call_write_data8(alu, ALU_TILEPAINT_G, data);
740 //call_write_data8(alu, ALU_TILEPAINT_L, 0xff);
746 void DISPLAY::alu_write_offsetreg_hi(uint8_t val)
748 call_write_data8(alu, ALU_OFFSET_REG_HIGH, val & 0x7f);
752 void DISPLAY::alu_write_offsetreg_lo(uint8_t val)
754 call_write_data8(alu, ALU_OFFSET_REG_LO, val);
758 void DISPLAY::alu_write_linepattern_hi(uint8_t val)
760 call_write_data8(alu, ALU_LINEPATTERN_REG_HIGH, val);
764 void DISPLAY::alu_write_linepattern_lo(uint8_t val)
766 call_write_data8(alu, ALU_LINEPATTERN_REG_LO, val);
770 void DISPLAY::alu_write_line_position(int addr, uint8_t val)
772 uint32_t data = (uint32_t)val;
775 call_write_data8(alu, ALU_LINEPOS_START_X_HIGH, data & 0x03);
778 call_write_data8(alu, ALU_LINEPOS_START_X_LOW, data);
781 call_write_data8(alu, ALU_LINEPOS_START_Y_HIGH, data & 0x01);
784 call_write_data8(alu, ALU_LINEPOS_START_Y_LOW, data);
787 call_write_data8(alu, ALU_LINEPOS_END_X_HIGH, data & 0x03);
790 call_write_data8(alu, ALU_LINEPOS_END_X_LOW, data);
793 call_write_data8(alu, ALU_LINEPOS_END_Y_HIGH, data & 0x01);
796 call_write_data8(alu, ALU_LINEPOS_END_Y_LOW, data);
802 uint8_t DISPLAY::get_miscreg(void)
807 if(!hblank) ret |= 0x80;
808 if(vsync) ret |= 0x04;
809 if(alu->read_signal(SIG_ALU_BUSYSTAT) == 0) ret |= 0x10;
810 if(power_on_reset) ret |= 0x01;
815 void DISPLAY::set_miscreg(uint8_t val)
817 int old_display_page = display_page;
819 nmi_enable = ((val & 0x80) == 0) ? true : false;
820 if(!nmi_enable) do_nmi(false);
822 if((val & 0x40) == 0) {
827 if(display_page != old_display_page) {
830 active_page = ((val & 0x20) == 0) ? 0 : 1;
831 if((val & 0x04) == 0) {
836 cgrom_bank = val & 0x03;
837 setup_display_mode();
841 void DISPLAY::set_monitor_bank(uint8_t var)
843 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
844 if((var & 0x04) != 0){
850 subrom_bank = var & 0x03;
853 subcpu_resetreq = false;
854 power_on_reset = true;
855 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
856 reset_some_devices();
859 subcpu_resetreq = true;
865 void DISPLAY::set_apalette_index_hi(uint8_t val)
867 apalette_index.b.h = val & 0x0f;
871 void DISPLAY::set_apalette_index_lo(uint8_t val)
873 apalette_index.b.l = val;
876 void DISPLAY::calc_apalette(uint16_t idx)
880 g = analog_palette_g[idx];
881 r = analog_palette_r[idx];
882 b = analog_palette_b[idx];
883 if(g != 0) g |= 0x0f;
884 if(r != 0) r |= 0x0f;
885 if(b != 0) b |= 0x0f;
886 analog_palette_pixel_tmp[idx] = RGB_COLOR(r, g, b);
890 void DISPLAY::set_apalette_b(uint8_t val)
894 index = apalette_index.w.l;
895 tmp = (val & 0x0f) << 4;
896 if(analog_palette_b[index] != tmp) {
897 analog_palette_b[index] = tmp;
898 calc_apalette(index);
899 palette_changed = true;
904 void DISPLAY::set_apalette_r(uint8_t val)
908 index = apalette_index.w.l;
909 tmp = (val & 0x0f) << 4;
910 if(analog_palette_r[index] != tmp) {
911 analog_palette_r[index] = tmp;
912 calc_apalette(index);
913 palette_changed = true;
918 void DISPLAY::set_apalette_g(uint8_t val)
922 index = apalette_index.w.l;
923 tmp = (val & 0x0f) << 4;
924 if(analog_palette_g[index] != tmp) {
925 analog_palette_g[index] = tmp;
926 calc_apalette(index);
927 palette_changed = true;
931 #endif // _FM77AV_VARIANTS
934 void DISPLAY::copy_vram_blank_area(void)
938 void DISPLAY::copy_vram_per_line(int begin, int end)
941 uint32_t yoff_d1 = 0;
942 uint32_t yoff_d2 = 0;
947 uint32_t src_offset_d1;
948 uint32_t src_offset_d2;
949 uint32_t src_offset_d;
954 uint32_t addr_d1, addr_d2;
958 //int dline = (int)displine - 1;
959 int dline = (int)displine;
961 if((begin < 0) || (begin > 4)) return;
962 if((end < 0) || (end > 4)) return;
963 if(begin > end) return;
964 if(dline < 0) return;
966 sectors = end - begin + 1;
968 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)){
969 if(dline >= 400) return;
971 if(dline >= 200) return;
973 #if defined(_FM77AV_VARIANTS)
974 yoff_d1 = offset_point;
975 yoff_d2 = offset_point_bank1;
976 if(display_mode == DISPLAY_MODE_4096) {
977 src_offset = dline * 40 + begin * 8;
978 sectors = sectors * 8;
979 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
982 addr_d1 = (src_offset + yoff_d1) & 0x1fff;
983 addr_d2 = (src_offset + yoff_d2) & 0x1fff;
984 bytes_d1 = 0x2000 - addr_d1;
985 bytes_d2 = 0x2000 - addr_d2;
986 for(k = 0; k < pages; k++) {
988 for(i = 0; i < 3; i++) {
989 for(j = 0; j < 2; j++) {
990 uint32_t _addr_base = src_base + src_offset + poff;
991 if(bytes_d1 < sectors) {
992 my_memcpy(&gvram_shadow[_addr_base],
993 &gvram[addr_d1 + src_base + poff],
995 my_memcpy(&gvram_shadow[_addr_base + bytes_d1],
996 &gvram[src_base + poff],
999 my_memcpy(&gvram_shadow[_addr_base],
1000 &gvram[addr_d1 + src_base + poff],
1003 _addr_base += 0xc000;
1004 if(bytes_d2 < sectors) {
1005 my_memcpy(&gvram_shadow[_addr_base],
1006 &gvram[addr_d2 + src_base + poff + 0xc000],
1008 my_memcpy(&gvram_shadow[_addr_base + bytes_d2],
1009 &gvram[src_base + poff + 0xc000],
1010 sectors - bytes_d2);
1012 my_memcpy(&gvram_shadow[_addr_base],
1013 &gvram[addr_d2 + src_base + poff + 0xc000],
1018 src_base = (i + 1) * 0x4000;
1022 vram_draw_table[dline] = true;
1023 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1025 # if defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV40)
1026 else if(display_mode == DISPLAY_MODE_256k) {
1027 src_offset = dline * 40 + begin * 8;
1028 sectors = sectors * 8;
1030 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1032 #elif defined(_FM77AV40)
1037 src_offset_d1 = (src_offset + yoff_d1) & 0x1fff;
1038 src_offset_d2 = (src_offset + yoff_d2) & 0x1fff;
1039 bytes_d1 = 0x2000 - ((src_offset + yoff_d1) & 0x1fff);
1040 bytes_d2 = 0x2000 - ((src_offset + yoff_d2) & 0x1fff);
1041 for(k = 0; k < pages; k++) {
1042 for(i = 0; i < 3; i++) {
1043 for(j = 0; j < 2; j++) {
1045 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
1046 src_offset_d = src_offset_d1;
1049 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
1050 src_offset_d = src_offset_d2;
1053 if(bytes_d < sectors) {
1054 my_memcpy(&gvram_shadow[src_offset + src_base],
1055 &gvram[src_offset_d + src_base],
1057 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1061 my_memcpy(&gvram_shadow[src_offset + src_base],
1062 &gvram[src_offset_d + src_base],
1068 vram_draw_table[dline] = true;
1069 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1071 else if(display_mode == DISPLAY_MODE_8_400L) {
1072 src_offset = dline * 80 + begin * 16;
1073 sectors = sectors * 16;
1074 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1077 if(display_page_bak == 1) { // Is this dirty?
1082 yoff_d = (yoff_d << 1) & 0x7fff;
1083 src_offset_d = (src_offset + yoff_d) & 0x7fff;
1084 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
1085 for(i = 0; i < pages; i++) {
1086 for(j = 0; j < 3; j++) {
1087 src_base = i * 0x18000 + j * 0x8000;
1088 if(bytes_d < sectors) {
1090 my_memcpy(&gvram_shadow[src_offset + src_base],
1091 &gvram[src_offset_d + src_base],
1094 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1098 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1099 &gvram[src_offset_d + src_base],
1104 vram_draw_table[dline] = true;
1105 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1109 src_offset = dline * 80 + begin * 16;
1110 sectors = sectors * 16;
1111 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1113 #elif defined(_FM77AV40)
1115 #elif defined(_FM77AV_VARIANTS)
1121 src_offset_d1 = (src_offset + yoff_d1) & 0x3fff;
1122 src_offset_d2 = (src_offset + yoff_d2) & 0x3fff;
1123 bytes_d1 = 0x4000 - ((src_offset + yoff_d1) & 0x3fff);
1124 bytes_d2 = 0x4000 - ((src_offset + yoff_d2) & 0x3fff);
1125 for(i = 0; i < pages; i++) {
1127 src_offset_d = src_offset_d1;
1130 src_offset_d = src_offset_d2;
1134 for(j = 0; j < 3; j++) {
1135 if(bytes_d < sectors) {
1136 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1137 &gvram[src_offset_d + src_base + poff],
1139 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1140 &gvram[src_base + poff],
1143 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1144 &gvram[src_offset_d + src_base + poff],
1151 vram_draw_table[dline] = true;
1152 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1153 //vram_wrote_table[dline] = false;
1156 #if defined(_FM77L4)
1157 if(display_mode == DISPLAY_MODE_1_400L) {
1158 src_offset = dline * 80 + begin * 16;
1159 sectors = sectors * 16;
1160 yoff_d = (yoff_d1 << 1) & 0x7fff;
1161 src_offset_d = (src_offset + yoff_d) & 0x7fff;
1162 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
1163 if(bytes_d < sectors) {
1165 my_memcpy(&gvram_shadow[src_offset],
1166 &gvram[src_offset_d],
1169 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1173 my_memcpy(&gvram_shadow[src_offset + poff],
1174 &gvram[src_offset_d ],
1177 vram_draw_table[dline] = true;
1178 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1183 src_offset = dline * 80 + begin * 16;
1184 sectors = sectors * 16;
1187 yoff_d = offset_point;
1188 src_offset_d = (src_offset + yoff_d) & 0x3fff;
1189 bytes_d = 0x4000 - ((src_offset + yoff_d) & 0x3fff);
1190 for(j = 0; j < 3; j++) {
1191 src_base = j * 0x4000;
1192 if(bytes_d < sectors) {
1193 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1194 &gvram[src_offset_d + src_base + poff],
1196 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1197 &gvram[src_base + poff],
1200 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1201 &gvram[src_offset_d + src_base + poff],
1205 vram_draw_table[dline] = true;
1206 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1207 //vram_wrote_table[dline] = false;
1213 void DISPLAY::copy_vram_all()
1215 #if defined(_FM77AV_VARIANTS)
1216 uint32_t yoff_d1 = offset_point;
1217 uint32_t yoff_d2 = offset_point_bank1;
1218 uint32_t src_offset_1, src_offset_2;
1220 if(display_mode == DISPLAY_MODE_4096) {
1221 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1226 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1227 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1228 for(int k = 0; k < pages; k++) {
1229 for(int i = 0; i < 3; i++) {
1230 for(int j = 0; j < 2; j++) {
1231 src_offset_1 = i * 0x4000 + j * 0x2000;
1232 src_offset_2 = src_offset_1 + 0xc000;
1233 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1234 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1235 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1236 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1242 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1243 else if(display_mode == DISPLAY_MODE_256k) {
1244 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1245 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1246 for(int i = 0; i < 3; i++) {
1247 for(int j = 0; j < 2; j++) {
1248 src_offset_1 = i * 0x4000 + j * 0x2000;
1249 src_offset_2 = src_offset_1 + 0xc000;
1250 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1251 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1252 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1253 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1257 for(int i = 0; i < 3; i++) {
1258 for(int j = 0; j < 2; j++) {
1259 src_offset_1 = i * 0x4000 + j * 0x2000;
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);
1264 } else if(display_mode == DISPLAY_MODE_8_400L) {
1266 uint32_t yoff_d, bytes_d;
1267 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1270 if(display_page_bak == 1) { // Is this dirty?
1275 yoff_d = (yoff_d << 1) & 0x7fff;
1276 bytes_d = 0x8000 - yoff_d;
1277 for(int i = 0; i < pages; i++) {
1278 for(int j = 0; j < 3; j++) {
1279 uint32_t src_base = i * 0x18000 + j * 0x8000;
1280 my_memcpy(&gvram_shadow[src_base],
1281 &gvram[yoff_d + src_base],
1283 if(bytes_d < 0x8000) {
1284 my_memcpy(&gvram_shadow[bytes_d + src_base],
1293 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1295 #elif defined(_FM77AV40)
1300 uint32_t bytes_d1 = 0x4000 - (yoff_d1 & 0x3fff);
1301 uint32_t bytes_d2 = 0x4000 - (yoff_d2 & 0x3fff);
1302 uint32_t yoff_d, bytes_d;
1303 for(int k = 0; k < pages; k++) {
1304 yoff_d = ((k & 1) == 0) ? (yoff_d1 & 0x3fff) : (yoff_d2 & 0x3fff);
1305 bytes_d = ((k & 1) == 0) ? bytes_d1 : bytes_d2;
1306 for(int j = 0; j < 3; j++) {
1307 src_offset_1 = k * 0xc000 + j * 0x4000;
1308 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1309 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1314 # if defined(_FM77L4)
1315 if(display_mode == DISPLAY_MODE_1_400L) {
1316 uint32_t yoff_d = offset_point & 0x7fff;
1317 uint32_t bytes_d = 0x8000 - (offset_point & 0x7fff);
1318 my_memcpy(&gvram_shadow[0], &gvram[0 + yoff_d], bytes_d);
1319 my_memcpy(&gvram_shadow[0 + bytes_d], &gvram[0], 0x8000 - bytes_d);
1324 uint32_t yoff_d = offset_point & 0x3fff;
1325 uint32_t bytes_d = 0x4000 - (offset_point & 0x3fff);
1326 uint32_t src_offset_1;
1327 for(int j = 0; j < 3; j++) {
1328 src_offset_1 = j * 0x4000;
1329 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1330 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1336 // Timing values from XM7 . Thanks Ryu.
1337 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1338 void DISPLAY::event_callback_hdisp(void)
1343 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x02, 0xff);
1344 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1345 if(displine < 400) f = true;
1347 if(displine < 200) f = true;
1350 hdisp_event_id = -1;
1352 // DO ONLY WHEN SYNC-TO-HSYNC.
1353 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
1355 //copy_vram_per_line(0, 4);
1356 } else if(need_transfer_line) { // Not frame skip.
1359 for(int iii = 0; iii < 5 ; iii++) {
1360 if(vram_wrote_table[iii + displine * 5]) {
1361 if(begin < 0) begin = iii; // Check first.
1366 if(end < begin) end = begin;
1368 copy_vram_per_line(begin, end);
1369 // Prepare to next block.
1375 // Tail of this line.
1378 copy_vram_per_line(begin, end);
1382 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1383 register_event(this, EVENT_FM7SUB_HBLANK, 30.0, false, &hblank_event_id); // NEXT CYCLE_
1385 register_event(this, EVENT_FM7SUB_HBLANK, 39.5, false, &hblank_event_id); // NEXT CYCLE_
1393 void DISPLAY::event_callback_hblank(void)
1400 hblank_event_id = -1;
1402 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1403 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1404 if((displine < 400)) f = true;
1407 if((displine < 200)) f = true;
1411 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id);
1416 void DISPLAY::event_callback_vstart(void)
1423 display_page_bak = display_page;
1425 // Parameter from XM7/VM/display.c , thanks, Ryu.
1426 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1427 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x00, 0xff);
1429 if(vblank_count != 0) {
1430 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1431 usec = (0.98 + 16.4) * 1000.0;
1433 usec = (1.91 + 12.7) * 1000.0;
1435 register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
1437 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1438 usec = 930.0; // 939.0
1440 usec = 1840.0; // 1846.5
1442 vstart_event_id = -1;
1443 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
1444 //register_event(this, EVENT_FM7SUB_HBLANK, usec, false, &hdisp_event_id); // NEXT CYCLE_
1447 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1448 usec = 0.34 * 1000.0;
1450 usec = 1.52 * 1000.0;
1452 vsync_event_id = -1;
1453 hblank_event_id = -1;
1454 hdisp_event_id = -1;
1455 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1459 void DISPLAY::event_callback_vsync(void)
1465 //write_access_page = (write_access_page + 1) & 1;
1468 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x01, 0xff);
1469 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1470 //if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1471 // usec = 0.33 * 1000.0;
1473 // usec = 0.51 * 1000.0;
1475 //register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1476 vsync_event_id = -1; // Fix for logging "[EVENT] EVENT: device (name=DISPLAY SUBSYSTEM, id=25) tries to cancel event 6 that is not its own (owned by (name=PRINTER I/F id=20))!!!"
1477 if(palette_changed) {
1478 #if defined(_FM77AV_VARIANTS)
1479 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
1481 #if defined(USE_GREEN_DISPLAY)
1482 //memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
1483 for(int i = 0; i < 8; i++) dpalette_green_tmp[i] = dpalette_pixel_green[i];
1485 //memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
1486 for(int i = 0; i < 8; i++) dpalette_pixel[i] = dpalette_pixel_tmp[i];
1487 vram_wrote_shadow = true;
1488 for(int yy = 0; yy < 400; yy++) {
1489 vram_draw_table[yy] = true;
1491 palette_changed = false;
1493 // Transfer on VSYNC
1494 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) {
1498 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L))lines = 400;
1499 if(need_transfer_line) {
1500 if(vram_wrote) { // transfer all line
1501 for(displine = 0; displine < lines; displine++) {
1502 //if(!vram_draw_table[displine]) {
1503 copy_vram_per_line(0, 4);
1507 } else { // transfer wrote line
1510 for(displine = 0; displine < lines; displine++) {
1511 //if(!vram_draw_table[displine]) {
1512 for(int iii = 0; iii < 5 ; iii++) {
1513 if(vram_wrote_table[iii + displine * 5]) {
1520 if(end < begin) end = begin;
1521 copy_vram_per_line(begin, end);
1528 if(end < 0) end = 4;
1529 copy_vram_per_line(begin, end);
1537 for(int yy = 0; yy < lines; yy++) {
1538 if(vram_draw_table[yy]) {
1539 vram_wrote_shadow = true;
1540 screen_update_flag = true;
1545 // TRANSFER per HSYNC a.k.a SYNC-TO-HSYNC.
1547 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) lines = 400;
1549 if(need_transfer_line) {
1550 if(vram_wrote) { // Transfer all line.
1551 for(int yy = 0; yy < lines; yy++) {
1553 copy_vram_per_line(0, 4);
1559 for(int yy = 0; yy < lines; yy++) {
1560 if(vram_draw_table[yy]) {
1561 vram_wrote_shadow = true;
1562 screen_update_flag = true;
1566 //vram_wrote = false;
1568 frame_skip_count_transfer++;
1570 // Check frame skip for next frame.
1571 uint32_t factor = ((config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28) & 3;
1572 if((frame_skip_count_transfer > factor) /* || (vram_wrote) */) {
1573 frame_skip_count_transfer = 0;
1574 need_transfer_line = true;
1576 need_transfer_line = false;
1582 #if defined(_FM77L4)
1583 void DISPLAY::cursor_blink_77l4()
1585 if(!(mode400line && stat_400linecard)) return;
1586 uint8_t *regs = l4crtc->get_regs();
1590 if((regs[10] & 0x40) != 0) {
1591 cursor_blink = !cursor_blink;
1592 uint16_t addr = cursor_addr.w.l;
1594 x = ((addr / 2) % 40) / 8;
1595 y = (addr / 2) / 40;
1596 } else { // Width 80
1597 x = ((addr / 2) % 80) / 8;
1598 y = (addr / 2) / 80;
1600 for(int yy = 0; yy < 8; yy++) {
1601 naddr = (y + yy) * 5 + x;
1602 vram_wrote_table[naddr] = true;
1608 void DISPLAY::text_blink_77l4()
1611 uint16_t offset = text_start_addr.w.l;
1614 if(!(mode400line && stat_400linecard)) return;
1615 text_blink = !text_blink;
1616 for(addr = 0; addr < (80 * 50); addr++) {
1617 naddr = ((addr + offset) & 0x0ffe) + 1;
1618 if((text_vram[naddr] & 0x10) != 0) { // ATTR BLINK
1620 x = ((naddr / 2) % 40) / 8;
1621 y = (naddr / 2) / 40;
1622 } else { // Width 80
1623 x = ((naddr / 2) % 80) / 8;
1624 y = (naddr / 2) / 80;
1626 for(int yy = 0; yy < 8; yy++) {
1627 naddr = (y + yy) * 5 + x;
1628 vram_wrote_table[naddr] = true;
1633 #endif //#if defined(_FM77L4)
1635 void DISPLAY::event_callback(int event_id, int err)
1640 case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
1641 #if defined(_FM77AV_VARIANTS)
1649 case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
1652 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1653 case EVENT_FM7SUB_HDISP:
1654 event_callback_hdisp();
1656 case EVENT_FM7SUB_HBLANK:
1657 event_callback_hblank();
1659 case EVENT_FM7SUB_VSTART: // Call first.
1660 event_callback_vstart();
1662 case EVENT_FM7SUB_VSYNC:
1663 event_callback_vsync();
1666 case EVENT_FM7SUB_DELAY_BUSY:
1670 case EVENT_FM7SUB_CLEAR_DELAY:
1673 case EVENT_FM7SUB_CLR_CRTFLAG:
1676 #if defined(_FM77L4)
1677 case EVENT_FM7SUB_CURSOR_BLINK:
1678 cursor_blink_77l4();
1680 case EVENT_FM7SUB_TEXT_BLINK:
1687 void DISPLAY::event_frame()
1694 //write_access_page = (write_access_page + 1) & 1;
1695 //out_debug_log(_T("DISPLINE=%d"), displine);
1697 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1698 usec = 0.34 * 1000.0;
1700 usec = 1.52 * 1000.0;
1702 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x01, 0xff);
1703 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1704 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1708 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1712 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) lines = 400;
1714 if(need_transfer_line && vram_wrote) {
1715 for(yy = 0; yy < lines; yy++) {
1716 //if(!vram_draw_table[yy]) {
1718 copy_vram_per_line(0, 4);
1726 for(yy = 0; yy < lines; yy++) {
1727 if(vram_draw_table[yy]) {
1733 screen_update_flag = true;
1734 vram_wrote_shadow = true;
1738 frame_skip_count_transfer++;
1740 uint32_t factor = (config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28;
1741 if(frame_skip_count_transfer > factor) {
1742 frame_skip_count_transfer = 0;
1743 need_transfer_line = true;
1745 need_transfer_line = false;
1747 //vram_wrote = false;
1755 void DISPLAY::event_vline(int v, int clock)
1757 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1759 if(need_transfer_line == false) return;
1762 // Not transfer, will transfer at event_frame.
1763 copy_vram_per_line(0, 4);
1767 for(int iii = 0; iii < 5 ; iii++) {
1768 if(vram_wrote_table[displine * 5 + iii]) {
1769 if(begin < 0) begin = iii;
1773 if(end < begin) end = begin;
1774 copy_vram_per_line(begin, end);
1782 copy_vram_per_line(begin, end);
1790 uint32_t DISPLAY::read_signal(int id)
1792 uint32_t retval = 0;
1794 case SIG_FM7_SUB_HALT:
1795 case SIG_DISPLAY_HALT:
1796 retval = (halt_flag) ? 0xffffffff : 0;
1798 case SIG_DISPLAY_BUSY:
1799 retval = (sub_busy) ? 0x80 : 0;
1801 case SIG_DISPLAY_MULTIPAGE:
1802 retval = multimode_accessmask;
1804 case SIG_DISPLAY_PLANES:
1807 #if defined(_FM77AV_VARIANTS)
1808 case SIG_DISPLAY_VSYNC:
1809 retval = (vsync) ? 0x01 : 0x00;
1811 case SIG_DISPLAY_DISPLAY:
1812 retval = (!hblank) ? 0x02: 0x00;
1814 case SIG_FM7_SUB_BANK: // Main: FD13
1815 retval = subrom_bank & 0x03;
1816 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1817 if(monitor_ram) retval |= 0x04;
1821 #if defined(_FM77AV_VARIANTS)
1822 case SIG_DISPLAY_MODE320:
1823 retval = (mode320) ? 0x40: 0x00;
1826 case SIG_DISPLAY_Y_HEIGHT:
1827 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77L4)
1828 retval = ((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) ? 400 : 200;
1833 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1835 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1836 retval |= (kanjisub) ? 0x00 : 0x20;
1837 retval |= (mode256k) ? 0x10 : 0x00;
1838 retval |= (mode400line) ? 0x00 : 0x08;
1839 retval |= (ram_protect) ? 0x00 : 0x04;
1840 #elif defined(_FM77_VARIANTS)
1842 retval |= (kanjisub) ? 0x00 : 0x20;
1843 # if defined(_FM77L4)
1844 retval |= (stat_400linecard) ? 0x00 : 0x08;
1852 case SIG_DISPLAY_X_WIDTH:
1853 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1854 retval = (mode320 || mode256k) ? 320 : 640;
1855 #elif defined(_FM77AV_VARIANTS)
1856 retval = (mode320) ? 320 : 640;
1867 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
1869 bool flag = ((data & mask) != 0);
1873 case SIG_FM7_SUB_HALT:
1878 //call_write_signal(mainio, SIG_FM7_SUB_HALT, data, mask);
1880 case SIG_DISPLAY_HALT:
1884 restart_subsystem();
1887 case SIG_FM7_SUB_CANCEL:
1889 cancel_request = true;
1893 case SIG_DISPLAY_CLOCK:
1897 #if defined(_FM77AV_VARIANTS)
1898 case SIG_FM7_SUB_BANK: // Main: FD13
1899 set_monitor_bank(data & 0xff);
1902 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1903 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1904 //out_debug_log("Wrote $FD04: %02x\n", data);
1906 int oldmode = display_mode;
1908 kanjisub = ((data & 0x20) == 0) ? true : false;
1909 mode256k = (((data & 0x10) != 0) && ((data & 0x08) != 0) ) ? true : false;
1910 mode400line = ((data & 0x08) == 0) ? true : false;
1911 ram_protect = ((data & 0x04) == 0) ? true : false;
1912 if((mode400line) && !(mode320)) {
1913 display_mode = DISPLAY_MODE_8_400L;
1914 } else if(mode256k) {
1915 display_mode = DISPLAY_MODE_256k;
1917 display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1919 if(oldmode != display_mode) {
1921 if(mode320 || mode256k) {
1922 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
1923 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1924 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1925 for(y = 0; y < 200; y++) {
1926 pp = emu->get_screen_buffer(y);
1927 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1930 for(y = 0; y < 400; y++) {
1931 pp = emu->get_screen_buffer(y);
1932 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1935 //emu->set_vm_screen_lines(200);
1936 } else if(display_mode == DISPLAY_MODE_8_400L) {
1937 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1938 if(oldmode != DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(55.40);
1939 for(y = 0; y < 400; y++) {
1940 pp = emu->get_screen_buffer(y);
1941 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1944 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
1945 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1946 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1947 for(y = 0; y < 200; y++) {
1948 pp = emu->get_screen_buffer(y);
1949 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1952 for(y = 0; y < 400; y++) {
1953 pp = emu->get_screen_buffer(y);
1954 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1957 //emu->set_vm_screen_lines(200);
1960 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
1961 call_write_signal(alu, SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200, 0xffff);
1962 call_write_signal(alu, SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xff : 0x00, 0xff);
1963 frame_skip_count_draw = 3;
1964 frame_skip_count_transfer = 3;
1965 setup_display_mode();
1968 #elif defined(_FM77_VARIANTS)
1970 int oldmode = display_mode;
1971 kanjisub = ((data & 0x20) == 0) ? true : false;
1972 # if defined(_FM77L4)
1973 stat_400linecard = ((data & 0x08) != 0) ? false : true;
1974 if(mode400line && stat_400linecard) {
1976 uint8_t *regs = l4crtc->get_regs();
1977 display_mode = DISPLAY_MODE_1_400L;
1978 if(event_id_l4_cursor_blink >= 0) {
1979 cancel_event(this, event_id_l4_cursor_blink);
1981 if(event_id_l4_text_blink >= 0) {
1982 cancel_event(this, event_id_l4_text_blink);
1984 event_id_l4_cursor_blink = -1;
1985 event_id_l4_text_blink = -1;
1987 usec = ((regs[10] & 0x20) == 0) ? 160.0 : 320.0;
1988 usec = usec * 1000.0;
1989 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, usec, true, &event_id_l4_cursor_blink);
1990 usec = 160.0 * 1000.0;
1991 register_event(this, EVENT_FM7SUB_TEXT_BLINK, usec, true, &event_id_l4_text_blink);
1994 display_mode = DISPLAY_MODE_8_200L;
1996 if(oldmode != display_mode) {
1998 if(display_mode == DISPLAY_MODE_1_400L) {
1999 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2000 for(int y = 0; y < 400; y++) {
2001 pp = emu->get_screen_buffer(y);
2002 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2006 vm->set_vm_frame_rate(FRAMES_PER_SEC);
2007 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2008 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2009 for(int y = 0; y < 200; y++) {
2010 pp = emu->get_screen_buffer(y);
2011 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2014 for(int y = 0; y < 400; y++) {
2015 pp = emu->get_screen_buffer(y);
2016 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2021 setup_display_mode();
2028 #if defined(_FM77AV_VARIANTS)
2029 case SIG_DISPLAY_MODE320: // FD12 bit 6
2030 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2032 //out_debug_log("Wrote $FD12: %02x\n", data);
2033 int oldmode = display_mode;
2036 display_mode = DISPLAY_MODE_8_400L;
2037 } else if(mode256k) {
2038 display_mode = DISPLAY_MODE_256k;
2039 } else if(!(mode320) && !(mode256k)) {
2040 //display_mode = (mode400line) ? DISPLAY_MODE_8_400L : DISPLAY_MODE_8_200L;
2041 display_mode = DISPLAY_MODE_8_200L;
2043 display_mode = (mode256k) ? DISPLAY_MODE_256k : DISPLAY_MODE_4096;
2045 if(oldmode != display_mode) {
2047 if(mode320 || mode256k) {
2048 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
2049 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2050 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2051 for(y = 0; y < 200; y++) {
2052 pp = emu->get_screen_buffer(y);
2053 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
2056 for(y = 0; y < 400; y++) {
2057 pp = emu->get_screen_buffer(y);
2058 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2061 //emu->set_vm_screen_lines(200);
2062 } else { // 200 lines, 8 colors.
2063 if(display_mode == DISPLAY_MODE_8_400L) {
2064 if(oldmode != DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(55.40);
2066 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
2068 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2069 int ymax = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
2071 emu->set_vm_screen_size(640, ymax, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2072 for(y = 0; y < ymax; y++) {
2073 pp = emu->get_screen_buffer(y);
2074 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2077 for(y = 0; y < 400; y++) {
2078 pp = emu->get_screen_buffer(y);
2079 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2082 //emu->set_vm_screen_lines(200);
2085 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
2086 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
2087 call_write_signal(alu, SIG_ALU_400LINE, 0x00, 0xff);
2088 setup_display_mode();
2089 //frame_skip_count = 3;
2092 # else /* FM77AV/20/20EX */
2095 if(oldflag != mode320) {
2098 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2099 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2100 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 320 * sizeof(scrntype_t));
2102 for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2104 //emu->set_vm_screen_lines(200);
2106 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2107 emu->set_vm_screen_size(640, 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, 640 * 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);
2115 display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
2116 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
2117 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
2118 call_write_signal(alu, SIG_ALU_400LINE, 0, 0xffffffff);
2120 setup_display_mode();
2125 case SIG_DISPLAY_MULTIPAGE:
2126 set_multimode(data);
2128 case SIG_FM7_SUB_KEY_MASK:
2129 if(firq_mask == flag) {
2130 do_firq(!flag && key_firq_req);
2134 case SIG_FM7_SUB_KEY_FIRQ:
2135 do_firq(flag & !(firq_mask));
2136 key_firq_req = flag;
2144 * Vram accessing functions moved to vram.cpp .
2147 uint32_t DISPLAY::read_mmio(uint32_t addr)
2149 uint32_t retval = 0xff;
2151 if(addr < 0xd400) return 0xff;
2153 #if !defined(_FM77AV_VARIANTS)
2154 raddr = (addr - 0xd400) & 0x000f;
2155 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2156 raddr = (addr - 0xd400) & 0x003f;
2157 #else // FM77AV40EX || FM77AV40SX
2158 raddr = (addr - 0xd400) & 0x00ff;
2161 case 0x00: // Read keyboard
2162 retval = (call_read_data8(keyboard, 0x00) != 0) ? 0xff : 0x7f;
2164 case 0x01: // Read keyboard
2165 retval = call_read_data8(keyboard, 0x01) & 0xff;
2167 case 0x02: // Acknowledge
2176 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2177 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2179 if(!kanjisub) return 0xff;
2180 # if !defined(_FM77_VARIANTS)
2182 return (uint8_t)call_read_data8(kanjiclass2, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
2185 if(kanjiclass1 != NULL) retval = call_read_data8(kanjiclass1, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
2188 if(!kanjisub) return 0xff;
2189 # if !defined(_FM77_VARIANTS)
2191 return (uint8_t)call_read_data8(kanjiclass2, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
2194 if(kanjiclass1 != NULL) retval = call_read_data8(kanjiclass1, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
2201 retval = set_vramaccess();
2204 { // If use CLR insn to set busy flag, clear flag at first, then delay and set flag.
2206 // Delay at least 3+ clocks (CLR <$0A )
2209 usec = (4000.0 * 1000.0) / 2000000.0;
2211 usec = (4000.0 * 1000.0) / 999000.0;
2213 register_event(this, EVENT_FM7SUB_CLEAR_DELAY, usec, false, NULL); // NEXT CYCLE_
2217 #if defined(_FM77L4)
2219 if(stat_400linecard) {
2220 retval = l4crtc->read_io8(0);
2224 if(stat_400linecard) {
2225 retval = l4crtc->read_io8(1);
2226 // Update parameters.
2231 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
2233 #if defined(_FM77AV_VARIANTS)
2236 retval = call_read_data8(alu, ALU_CMDREG);
2239 retval = call_read_data8(alu, ALU_LOGICAL_COLOR);
2242 retval = call_read_data8(alu, ALU_WRITE_MASKREG);
2245 retval = call_read_data8(alu, ALU_CMP_STATUS_REG);
2248 retval = call_read_data8(alu, ALU_BANK_DISABLE);
2250 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2251 case 0x2f: // VRAM BANK
2252 retval = 0xfc | (vram_bank & 0x03);
2257 retval = get_miscreg();
2261 retval = call_read_data8(keyboard, 0x31);
2264 retval = call_read_data8(keyboard, 0x32);
2270 return (uint8_t)retval;
2273 uint32_t DISPLAY::read_vram_data8(uint32_t addr)
2277 uint32_t color = (addr >> 14) & 0x03;
2278 #if defined(_FM77L4)
2281 offset = offset_point;
2283 if(multimode_accessflags[2]) return 0xff;
2284 vramaddr = ((addr + offset) & 0x3fff) + 0x8000;
2285 return gvram[vramaddr];
2289 return text_vram[addr & 0x0fff];
2290 } else if(addr < 0xc000) {
2291 return subsys_l4[addr - 0x9800];
2297 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2298 if(display_mode == DISPLAY_MODE_8_400L) {
2299 color = vram_bank & 0x03;
2300 if(color > 2) color = 0;
2302 color = (addr >> 14) & 0x03;
2306 //if((multimode_accessmask & (1 << color)) != 0) return 0xff;
2307 if(multimode_accessflags[color]) return 0xff;
2309 #if defined(_FM77AV_VARIANTS)
2310 if (active_page != 0) {
2311 offset = offset_point_bank1;
2313 offset = offset_point;
2316 offset = offset_point;
2318 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2319 if(vram_active_block != 0) {
2320 if(display_mode != DISPLAY_MODE_256k) offset = 0; // Don't scroll at BLOCK 1.
2323 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2324 if(display_mode == DISPLAY_MODE_8_400L) {
2326 uint32_t page_offset_alt = 0;
2327 if(addr >= 0x8000) return 0xff;
2328 color = vram_bank & 0x03;
2329 if(color > 2) color = 0;
2331 pagemod = 0x8000 * color;
2332 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2333 if(vram_active_block != 0) page_offset = 0x18000;
2335 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2336 return gvram[vramaddr];
2339 uint32_t page_offset_alt;
2340 #if defined(_FM77AV40)
2342 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2344 page_offset_alt = 0; // right?
2347 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2349 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
2350 //page_mask = 0x1fff;
2351 //pagemod = addr & 0xe000;
2353 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2355 return gvram[vramaddr];
2357 #elif defined(_FM77AV_VARIANTS)
2359 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2360 return gvram[vramaddr];
2362 #elif defined(_FM77L4) //_FM77L4
2365 vramaddr = (addr + offset) & 0x7fff;
2366 return gvram[vramaddr];
2368 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2369 return gvram[vramaddr];
2373 #else // Others (77/7/8)
2374 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2375 return gvram[vramaddr];
2379 void DISPLAY::write_dma_data8(uint32_t addr, uint32_t data)
2381 uint32_t raddr = (addr & 0xffff) >> 7;
2382 if(write_dma_func_table[raddr] != NULL) {
2383 (this->*write_dma_func_table[raddr])(addr, (uint8_t) data);
2387 void DISPLAY::write_vram_data8(uint32_t addr, uint8_t data)
2390 uint32_t color = (addr >> 14) & 0x03;
2394 #if defined(_FM77AV_VARIANTS)
2395 if (active_page != 0) {
2396 offset = offset_point_bank1;
2398 offset = offset_point;
2401 offset = offset_point;
2403 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2404 if(vram_active_block != 0) offset = 0; // Don't scroll at BLOCK 1.
2407 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2408 if(display_mode == DISPLAY_MODE_8_400L) {
2410 uint32_t page_offset_alt = 0;
2412 if(addr >= 0x8000) {
2415 color = vram_bank & 0x03;
2416 if(color > 2) color = 0;
2418 pagemod = 0x8000 * color;
2419 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2420 if(vram_active_block != 0) page_offset_alt = 0x18000;
2422 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2423 // Reduce data transfer.
2424 tdata = gvram[vramaddr];
2426 naddr = (addr & 0x7fff) >> 4;
2427 gvram[vramaddr] = data;
2428 vram_wrote_table[naddr] = true;
2430 } else if(display_mode == DISPLAY_MODE_256k) {
2431 uint32_t page_offset_alt;
2433 #if defined(_FM77AV40)
2435 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2437 page_offset_alt = 0; // right?
2440 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2442 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
2443 tdata = gvram[vramaddr];
2445 naddr = (addr & page_mask) >> 3;
2446 gvram[vramaddr] = data;
2447 vram_wrote_table[naddr] = true;
2450 } else if(display_mode == DISPLAY_MODE_4096) {
2452 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2453 tdata = gvram[vramaddr];
2455 naddr = (addr & page_mask) >> 3;
2456 gvram[vramaddr] = data;
2457 vram_wrote_table[naddr] = true;
2461 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2462 tdata = gvram[vramaddr];
2464 naddr = (addr & page_mask) >> 4;
2465 gvram[vramaddr] = data;
2466 vram_wrote_table[naddr] = true;
2469 #elif defined(_FM77AV_VARIANTS)
2470 if(display_mode == DISPLAY_MODE_4096) {
2472 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2473 tdata = gvram[vramaddr];
2475 naddr = (addr & page_mask) >> 3;
2476 gvram[vramaddr] = data;
2477 vram_wrote_table[naddr] = true;
2481 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2482 tdata = gvram[vramaddr];
2484 naddr = (addr & page_mask) >> 4;
2485 gvram[vramaddr] = data;
2486 vram_wrote_table[naddr] = true;
2489 #elif defined(_FM77L4) //_FM77L4
2490 if(display_mode == DISPLAY_MODE_1_400L) {
2493 //if(multimode_accessflags[2]) return;
2494 vramaddr = ((addr + offset) & 0x3fff) + 0x8000;
2495 gvram[vramaddr] = data;
2498 vramaddr = (addr + offset) & 0x7fff;
2499 tdata = gvram[vramaddr];
2501 naddr = (addr & 0x7fff) >> 4;
2502 gvram[vramaddr] = data;
2503 vram_wrote_table[naddr] = true;
2510 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2511 tdata = gvram[vramaddr];
2513 naddr = (addr & 0x3fff) >> 4;
2514 gvram[vramaddr] = data;
2515 vram_wrote_table[naddr] = true;
2518 #else // Others (77/7/8)
2521 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2522 tdata = gvram[vramaddr];
2524 naddr = (addr & 0x3fff) >> 4;
2525 gvram[vramaddr] = data;
2526 vram_wrote_table[naddr] = true;
2532 uint32_t DISPLAY::read_cpu_vram_data8(uint32_t addr)
2535 #if defined(_FM77AV_VARIANTS)
2537 call_read_data8(alu, addr);
2540 return read_vram_data8(addr);
2543 uint32_t DISPLAY::read_dma_vram_data8(uint32_t addr)
2545 return read_vram_data8(addr);
2548 void DISPLAY::init_read_table(void)
2551 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
2552 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cpu_vram_data8;
2553 read_dma_func_table[_at >> 7] = &DISPLAY::read_dma_vram_data8;
2555 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
2556 read_cpu_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2557 read_dma_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2559 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
2560 read_cpu_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2561 read_dma_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2563 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
2564 read_cpu_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2565 read_dma_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2567 #if defined(_FM77AV_VARIANTS)
2568 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
2569 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2570 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2572 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
2573 read_cpu_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2574 read_dma_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2577 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
2578 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2579 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2582 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
2583 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2584 read_dma_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2586 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
2587 read_cpu_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2588 read_dma_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2592 uint32_t DISPLAY::read_console_ram(uint32_t addr)
2594 uint32_t raddr = addr & 0xfff;
2595 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2597 if(console_ram_bank >= 1) {
2598 return submem_console_av40[((console_ram_bank - 1) << 12) + raddr];
2602 return console_ram[raddr];
2605 uint32_t DISPLAY::read_work_ram(uint32_t addr)
2607 addr = addr & 0x3ff;
2608 return work_ram[addr];
2612 uint32_t DISPLAY::read_shared_ram(uint32_t addr)
2614 addr = addr - 0xd380;
2615 return shared_ram[addr];
2618 #if defined(_FM77AV_VARIANTS)
2619 uint32_t DISPLAY::read_hidden_ram(uint32_t addr)
2621 if(addr >= 0xd500) {
2622 return submem_hidden[addr - 0xd500];
2628 uint32_t DISPLAY::read_cgrom(uint32_t addr)
2630 #if defined(_FM77AV_VARIANTS)
2631 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2633 return submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)]; //FIXME
2636 return subsys_cg[(addr - 0xd800) + cgrom_bank * 0x800];
2638 return subsys_c[addr - 0xd800];
2642 uint32_t DISPLAY::read_subsys_monitor(uint32_t addr)
2644 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2646 return subsys_ram[addr - 0xe000];
2649 #if defined(_FM77AV_VARIANTS)
2650 switch(subrom_bank_using & 3) {
2652 return subsys_c[addr - 0xd800];
2655 return subsys_a[addr - 0xe000];
2658 return subsys_b[addr - 0xe000];
2661 return subsys_cg[addr - 0xe000];
2664 #elif defined(_FM77L4)
2666 return subsys_l4[addr - 0xb800];
2668 return subsys_c[addr - 0xd800];
2670 return subsys_c[addr - 0xd800];
2674 uint32_t DISPLAY::read_dma_data8(uint32_t addr)
2676 uint32_t raddr = (addr & 0xffff) >> 7;
2677 if(read_dma_func_table[raddr] != NULL) {
2678 return (this->*read_dma_func_table[raddr])(addr);
2683 uint32_t DISPLAY::read_data8(uint32_t addr)
2685 uint32_t raddr = addr;
2687 if(addr < 0x10000) {
2688 raddr = (addr & 0xffff) >> 7;
2689 if(read_cpu_func_table[raddr] != NULL) {
2690 return (this->*read_cpu_func_table[raddr])(addr);
2695 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2696 return dpalette_data[addr - FM7_SUBMEM_OFFSET_DPALETTE];
2699 #if defined(_FM77AV_VARIANTS)
2701 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2702 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2703 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2704 if(vram_active_block != 0) {
2708 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2709 if(display_mode == DISPLAY_MODE_8_400L) {
2710 uint32_t page_offset_alt = 0;
2713 color = (addr & 0x18000) >> 15;
2714 if(color > 2) color = 0;
2715 pagemod = 0x8000 * color;
2716 if (active_page != 0) {
2717 offset = offset_point_bank1 << 1;
2719 offset = offset_point << 1;
2721 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2722 if(vram_active_block != 0) {
2723 page_offset_alt = 0x18000;
2727 return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset_alt];
2730 return read_vram_data8(addr);
2737 * Vram accessing functions moved to vram.cpp .
2740 void DISPLAY::write_mmio(uint32_t addr, uint8_t data)
2743 uint8_t active_block_old;
2745 if(addr < 0xd400) return;
2747 #if !defined(_FM77AV_VARIANTS)
2748 addr = (addr - 0xd400) & 0x000f;
2749 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2750 addr = (addr - 0xd400) & 0x003f;
2751 #else // FM77AV40EX || FM77AV40SX
2752 addr = (addr - 0xd400) & 0x00ff;
2754 io_w_latch[addr] = (uint8_t)data;
2756 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4)
2759 set_cyclesteal((uint8_t)data);
2760 # if defined(_FM77L4)
2761 setup_400linemode((uint8_t)data);
2765 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2766 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2769 if(!kanjisub) return;
2770 kanjiaddr.w.h = 0x0000;
2771 kanjiaddr.b.h = (uint8_t) data;
2774 if(!kanjisub) return;
2775 kanjiaddr.w.h = 0x0000;
2776 kanjiaddr.b.l = (uint8_t)data;
2789 if(delay_busy) { // If WRITE after READ immediately.Perhaps use CLR insn.
2791 // Delay at least 5+ clocks (CLR $D40A or CLR (INDEX = $D40A))
2793 usec = (6000.0 * 1000.0) / 2000000.0;
2795 usec = (6000.0 * 1000.0) / 999000.0;
2797 register_event(this, EVENT_FM7SUB_DELAY_BUSY, usec, false, NULL); // NEXT CYCLE_
2805 #if defined(_FM77L4)
2807 if(stat_400linecard) {
2808 l4crtc->write_io8(0, data & 0x1f);
2812 if(stat_400linecard) {
2813 l4crtc->write_io8(1, data);
2814 // Update parameters.
2815 uint8_t crtc_addr = l4crtc->read_io8(0);
2816 const uint8_t *regs = l4crtc->get_regs();
2817 switch(crtc_addr & 0x1f) {
2820 cursor_addr.w.l &= 0x0ffc;
2821 cursor_addr.w.l |= (((uint16_t)regs[14]) << 10);
2822 cursor_addr.w.l |= (((uint16_t)regs[15]) << 2);
2824 cursor_addr.w.l += 2;
2826 cursor_addr.w.l &= 0xfff;
2828 if((crtc_addr & 0x1f) == 10) {
2830 if(event_id_l4_cursor_blink >= 0) {
2831 cancel_event(this, event_id_l4_cursor_blink);
2833 usec = ((data & 0x20) == 0) ? 160.0 : 320.0;
2834 usec = usec * 1000.0;
2835 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, usec, true, &event_id_l4_cursor_blink);
2839 text_start_addr.w.l &= 0x03fc;
2840 text_start_addr.w.l |= (((uint16_t)data & 3) << 10);
2841 text_scroll_count++;
2842 if((text_scroll_count & 1) == 0) {
2847 text_start_addr.w.l &= 0xfc00;
2848 text_start_addr.w.l |= ((uint16_t)data << 2);
2849 text_scroll_count++;
2850 if((text_scroll_count & 1) == 0) {
2855 text_scroll_count++;
2856 if((text_scroll_count & 1) == 0) {
2858 cursor_addr.w.l &= 0x0ffc;
2859 cursor_addr.w.l |= (((uint16_t)regs[14]) << 10);
2860 cursor_addr.w.l |= (((uint16_t)regs[15]) << 2);
2862 cursor_addr.w.l += 2;
2864 cursor_addr.w.l &= 0xfff;
2875 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
2880 rval = (uint8_t)data;
2881 if(offset_changed[active_page]) {
2882 #if defined(_FM77AV_VARIANTS)
2883 if(active_page != 0) {
2884 tmp_offset_point[active_page].d = offset_point_bank1;
2886 tmp_offset_point[active_page].d = offset_point;
2889 tmp_offset_point[active_page].d = offset_point;
2892 tmp_offset_point[active_page].w.h = 0x0000;
2894 tmp_offset_point[active_page].b.h = rval;
2896 tmp_offset_point[active_page].b.l = rval;
2898 offset_changed[active_page] = !offset_changed[active_page];
2899 if(offset_changed[active_page]) {
2901 #if defined(_FM77AV_VARIANTS)
2902 if(active_page != 0) {
2904 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fff;
2906 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fe0;
2910 offset_point = tmp_offset_point[active_page].d & 0x007fff;
2912 offset_point = tmp_offset_point[active_page].d & 0x007fe0;
2916 offset_point = tmp_offset_point[active_page].d & 0x7fe0;
2920 #if defined(_FM77AV_VARIANTS)
2923 alu_write_cmdreg(data);
2926 alu_write_logical_color(data);
2929 alu_write_mask_reg(data);
2932 alu_write_disable_reg(data);
2935 alu_write_offsetreg_hi(data);
2938 alu_write_offsetreg_lo(data);
2941 alu_write_linepattern_hi(data);
2944 alu_write_linepattern_lo(data);
2946 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2948 console_ram_bank = (data & 0x18) >> 3;
2949 if(console_ram_bank > 2) console_ram_bank = 0;
2950 cgram_bank = data & 0x07;
2951 kanji_level2 = ((data & 0x80) == 0) ? false : true;
2953 case 0x2f: // VRAM BANK
2954 vram_bank = data & 0x03;
2955 if(vram_bank > 2) vram_bank = 0;
2965 call_write_data8(keyboard, 0x31, data);
2967 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2969 active_block_old = vram_active_block;
2970 vram_active_block = data & 0x01;
2971 if(vram_display_block != (((data & 0x10) != 0) ? 1 : 0)) vram_wrote = true;
2972 vram_display_block = ((data & 0x10) != 0) ? 1 : 0;
2973 if(vram_active_block != active_block_old) setup_display_mode();
2978 tmpvar.d = window_xbegin * 8;
2981 tmpvar.b.h = data & 0x03;
2983 tmpvar.b.l = data & 0xf8;
2985 if(mode320 || mode256k) {
2986 if(tmpvar.d > 320) tmpvar.d = 320;
2988 if(tmpvar.d > 640) tmpvar.d = 640;
2990 window_xbegin = tmpvar.d / 8;
2995 tmpvar.d = window_xend * 8;
2998 tmpvar.b.h = data & 0x03;
3000 tmpvar.b.l = data & 0xf8;
3002 if(mode320 || mode256k) {
3003 if(tmpvar.d > 320) tmpvar.d = 320;
3005 if(tmpvar.d > 640) tmpvar.d = 640;
3007 window_xend = tmpvar.d / 8;
3012 tmpvar.d = window_low;
3015 tmpvar.b.h = data & 0x03;
3017 tmpvar.b.l = data & 0xff;
3019 if(display_mode == DISPLAY_MODE_8_400L) {
3020 if(tmpvar.d > 400) tmpvar.d = 400;
3023 if(tmpvar.d > 400) tmpvar.d = 400;
3025 window_low = tmpvar.d;
3030 tmpvar.d = window_high;
3033 tmpvar.b.h = data & 0x03;
3035 tmpvar.b.l = data & 0xff;
3037 if(display_mode == DISPLAY_MODE_8_400L) {
3038 if(tmpvar.d > 400) tmpvar.d = 400;
3041 if(tmpvar.d > 400) tmpvar.d = 400;
3043 window_high = tmpvar.d;
3049 #if defined(_FM77AV_VARIANTS)
3051 if((addr >= 0x13) && (addr <= 0x1a)) {
3052 alu_write_cmpdata_reg(addr - 0x13, data);
3053 } else if((addr >= 0x1c) && (addr <= 0x1e)) {
3054 alu_write_tilepaint_data(addr, data);
3055 } else if((addr >= 0x24) && (addr <= 0x2b)) {
3056 alu_write_line_position(addr - 0x24, data);
3063 void DISPLAY::init_write_table(void)
3066 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
3067 write_cpu_func_table[_at >> 7] = &DISPLAY::write_cpu_vram_data8;
3068 write_dma_func_table[_at >> 7] = &DISPLAY::write_dma_vram_data8;
3070 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
3071 write_cpu_func_table[_at >> 7] = &DISPLAY::write_console_ram;
3072 write_dma_func_table[_at >> 7] = &DISPLAY::write_console_ram;
3074 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
3075 write_cpu_func_table[_at >> 7] = &DISPLAY::write_work_ram;
3076 write_dma_func_table[_at >> 7] = &DISPLAY::write_work_ram;
3078 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
3079 write_cpu_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
3080 write_dma_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
3082 #if defined(_FM77AV_VARIANTS)
3083 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
3084 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
3085 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
3087 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
3088 write_cpu_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
3089 write_dma_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
3092 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
3093 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
3094 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
3097 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
3098 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
3099 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
3100 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
3102 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
3103 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
3104 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
3107 for(_at = 0xd800; _at < 0x10000; _at += 0x80) {
3108 write_cpu_func_table[_at >> 7] = &DISPLAY::write_dummy;
3109 write_dma_func_table[_at >> 7] = &DISPLAY::write_dummy;
3114 void DISPLAY::write_console_ram(uint32_t addr, uint8_t data)
3116 uint32_t raddr = addr & 0xfff;
3117 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3119 if(console_ram_bank >= 1) {
3120 submem_console_av40[((console_ram_bank - 1) << 12) + raddr] = data;
3125 console_ram[raddr] = data;
3129 void DISPLAY::write_work_ram(uint32_t addr, uint8_t data)
3131 uint32_t raddr = addr & 0xfff;
3132 work_ram[raddr] = data;
3136 void DISPLAY::write_shared_ram(uint32_t addr, uint8_t data)
3138 uint32_t raddr = addr & 0x7f;
3139 shared_ram[raddr] = data;
3143 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
3144 void DISPLAY::write_subsys_cgram(uint32_t addr, uint8_t data)
3146 uint32_t raddr = addr - 0xd800;
3147 if(ram_protect) return;
3148 if(!monitor_ram) return;
3149 submem_cgram[cgram_bank * 0x0800 + raddr] = data; //FIXME
3152 void DISPLAY::write_subsys_ram(uint32_t addr, uint8_t data)
3154 if(ram_protect) return;
3155 if(!monitor_ram) return;
3156 subsys_ram[addr - 0xe000] = data; //FIXME
3160 #if defined(_FM77AV_VARIANTS)
3161 void DISPLAY::write_hidden_ram(uint32_t addr, uint8_t data)
3163 submem_hidden[addr - 0xd500] = data;
3168 void DISPLAY::write_cpu_vram_data8(uint32_t addr, uint8_t data)
3170 uint32_t color = (addr & 0xc000) >> 14;
3171 #if defined(_FM77AV_VARIANTS)
3173 call_read_data8(alu, addr);
3177 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3178 if(display_mode == DISPLAY_MODE_8_400L) {
3179 color = vram_bank & 0x03;
3180 if(color > 2) color = 0;
3183 #if defined(_FM77L4)
3187 if(!(multimode_accessflags[2])) write_vram_data8(addr & 0x7fff, data);
3190 } else if(addr < 0x9800) {
3193 addr = addr & 0x0fff;
3194 if(text_vram[addr] != data) {
3195 text_vram[addr] = data;
3197 x = ((addr / 2) % 40) / 8;
3198 y = (addr / 2) / 40;
3199 } else { // Width 80
3200 x = ((addr / 2) % 80) / 8;
3201 y = (addr / 2) / 80;
3203 for(int yy = 0; yy < 8; yy++) {
3204 naddr = (y + yy) * 5 + x;
3205 vram_wrote_table[naddr] = true;
3215 //if((multimode_accessmask & (1 << color)) != 0) return;
3216 if(multimode_accessflags[color]) return;
3218 write_vram_data8(addr & 0xffff, data);
3221 void DISPLAY::write_dma_vram_data8(uint32_t addr, uint8_t data)
3223 uint32_t color = (addr & 0xc000) >> 14;
3224 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3225 if(display_mode == DISPLAY_MODE_8_400L) {
3226 color = vram_bank & 0x03;
3227 if(color > 2) color = 0;
3231 //if((multimode_accessmask & (1 << color)) != 0) return;
3232 if(multimode_accessflags[color]) return;
3234 write_vram_data8(addr & 0xffff, data);
3237 void DISPLAY::write_dummy(uint32_t addr, uint8_t data)
3241 void DISPLAY::write_data8(uint32_t addr, uint32_t data)
3245 //uint32_t page_offset = 0x0000;
3246 uint8_t val8 = data & 0xff;
3247 uint32_t color = (addr & 0xc000) >> 14;
3250 if(addr < 0x10000) {
3251 void (*_write_func)(uint32_t, uint32_t);
3252 raddr = (addr & 0xffff) >> 7;
3253 if(write_cpu_func_table[raddr] != NULL) {
3254 (this->*write_cpu_func_table[raddr])(addr, (uint8_t)data);
3260 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
3261 set_dpalette(addr - FM7_SUBMEM_OFFSET_DPALETTE, val8);
3265 #if defined(_FM77AV_VARIANTS)
3267 else if(addr == FM7_SUBMEM_OFFSET_APALETTE_R) {
3268 set_apalette_r(val8);
3270 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_G) {
3271 set_apalette_g(val8);
3273 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_B) {
3274 set_apalette_b(val8);
3276 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_HI) {
3277 set_apalette_index_hi(val8);
3279 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_LO) {
3280 set_apalette_index_lo(val8);
3284 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
3285 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
3286 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3287 if(display_mode == DISPLAY_MODE_8_400L) {
3290 uint32_t page_offset_alt = 0;
3292 color = (addr & 0x18000) >> 15;
3293 if(color > 2) color = 0;
3294 if (active_page != 0) {
3295 offset = offset_point_bank1 << 1;
3297 offset = offset_point << 1;
3299 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3300 if(vram_active_block != 0) {
3301 page_offset_alt = 0x18000;
3305 naddr = (addr & 0x7fff) >> 4;
3306 pagemod = 0x8000 * color;
3307 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
3308 tdata = gvram[vramaddr];
3309 if(tdata != (uint8_t)data) {
3310 gvram[vramaddr] = data;
3311 vram_wrote_table[naddr] = true;
3315 write_vram_data8(addr, data);
3317 write_vram_data8(addr, data);
3319 //if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
3326 uint32_t DISPLAY::read_bios(const _TCHAR *name, uint8_t *ptr, uint32_t size)
3332 if((name == NULL) || (ptr == NULL)) return 0;
3333 s = create_local_path(name);
3334 if(s == NULL) return 0;
3336 if(!fio.Fopen(s, FILEIO_READ_BINARY)) return 0;
3337 blocks = fio.Fread(ptr, size, 1);
3340 return blocks * size;
3344 void DISPLAY::initialize()
3349 PrepareBitTransTableUint16((_bit_trans_table_t*)(&(bit_trans_table_0[0][0])), 0x0080, 0x0000);
3350 PrepareBitTransTableUint16((_bit_trans_table_t*)(&(bit_trans_table_1[0][0])), 0x0040, 0x0000);
3351 PrepareBitTransTableUint16((_bit_trans_table_t*)(&(bit_trans_table_2[0][0])), 0x0020, 0x0000);
3352 PrepareBitTransTableUint16((_bit_trans_table_t*)(&(bit_trans_table_3[0][0])), 0x0010, 0x0000);
3353 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3354 PrepareBitTransTableUint16((_bit_trans_table_t*)(&(bit_trans_table_4[0][0])), 0x0008, 0x0000);
3355 PrepareBitTransTableUint16((_bit_trans_table_t*)(&(bit_trans_table_5[0][0])), 0x0004, 0x0000);
3358 for(int i = 0; i < 256; i++) {
3359 uint16_t n = (uint16_t)i;
3360 for(int j = 0; j < 8; j++) {
3361 bit_trans_table_0[i][j] = n & 0x80;
3362 bit_trans_table_1[i][j] = ((n & 0x80) != 0) ? 0x40 : 0;
3363 bit_trans_table_2[i][j] = ((n & 0x80) != 0) ? 0x20 : 0;
3364 bit_trans_table_3[i][j] = ((n & 0x80) != 0) ? 0x10 : 0;
3365 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3366 bit_trans_table_4[i][j] = ((n & 0x80) != 0) ? 0x08 : 0;
3367 bit_trans_table_5[i][j] = ((n & 0x80) != 0) ? 0x04 : 0;
3373 memset(io_w_latch, 0xff, sizeof(io_w_latch));
3374 screen_update_flag = true;
3375 memset(gvram, 0x00, sizeof(gvram));
3376 vram_wrote_shadow = false;
3377 memset(gvram_shadow, 0x00, sizeof(gvram_shadow));
3378 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
3379 for(i = 0; i < 411; i++) vram_draw_table[i] = false;
3380 force_update = false;
3382 memset(console_ram, 0x00, sizeof(console_ram));
3383 memset(work_ram, 0x00, sizeof(work_ram));
3384 memset(shared_ram, 0x00, sizeof(shared_ram));
3385 memset(subsys_c, 0xff, sizeof(subsys_c));
3386 need_transfer_line = true;
3387 frame_skip_count_draw = 3;
3388 frame_skip_count_transfer = 3;
3390 diag_load_subrom_c = false;
3392 if(read_bios(_T(ROM_FM8_SUBSYSTEM), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
3393 this->out_debug_log(_T("SUBSYSTEM ROM READING : %s"), diag_load_subrom_c ? "OK" : "NG");
3395 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_C), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
3396 this->out_debug_log(_T("SUBSYSTEM ROM Type C READING : %s"), diag_load_subrom_c ? "OK" : "NG");
3398 #if defined(_FM77AV_VARIANTS)
3399 memset(subsys_a, 0xff, sizeof(subsys_a));
3400 memset(subsys_b, 0xff, sizeof(subsys_b));
3401 memset(subsys_cg, 0xff, sizeof(subsys_cg));
3402 memset(submem_hidden, 0x00, sizeof(submem_hidden));
3404 diag_load_subrom_a = false;
3405 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_A), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
3406 this->out_debug_log(_T("SUBSYSTEM ROM Type A READING : %s"), diag_load_subrom_a ? "OK" : "NG");
3408 diag_load_subrom_b = false;
3409 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_B), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
3410 this->out_debug_log(_T("SUBSYSTEM ROM Type B READING : %s"), diag_load_subrom_b ? "OK" : "NG");
3412 diag_load_subrom_cg = false;
3413 if(read_bios(_T(ROM_FM7_SUBSYSTEM_CG), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
3414 this->out_debug_log(_T("SUBSYSTEM CG ROM READING : %s"), diag_load_subrom_cg ? "OK" : "NG");
3415 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
3416 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3417 memset(subsys_ram, 0x00, sizeof(subsys_ram));
3418 memset(submem_cgram, 0x00, sizeof(submem_cgram));
3419 memset(submem_console_av40, 0x00, sizeof(submem_console_av40));
3423 #if defined(_FM77L4)
3424 memset(subsys_cg_l4, 0xff, sizeof(subsys_cg_l4));
3425 memset(subsys_l4, 0xff, sizeof(subsys_l4));
3427 read_bios(_T(ROM_FM77_400LINE_ANKCG), subsys_cg_l4, sizeof(subsys_cg_l4));
3428 read_bios(_T(ROM_FM77_400LINE_SUBSYS), subsys_l4, sizeof(subsys_l4));
3429 memset(text_vram, 0x00, sizeof(text_vram));
3430 //memset(crtc_regs, 0x00, sizeof(crtc_regs));
3434 text_width40 = false;
3437 cursor_blink = true;
3439 text_start_addr.d = 0x0000;
3447 text_scroll_count = 0;
3449 event_id_l4_cursor_blink = -1;
3450 event_id_l4_text_blink = -1;
3456 #if defined(_FM77AV_VARIANTS)
3458 apalette_index.d = 0;
3459 for(i = 0; i < 4096; i++) {
3460 analog_palette_r[i] = i & 0x0f0;
3461 analog_palette_g[i] = (i & 0xf00) >> 4;
3462 analog_palette_b[i] = (i & 0x00f) << 4;
3464 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
3467 for(i = 0; i < 8; i++) set_dpalette(i, i);
3468 #if defined(USE_GREEN_DISPLAY)
3469 for(i = 0; i < 8; i++) dpalette_pixel_green[i] = dpalette_green_tmp[i];
3470 //memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3471 use_green_monitor = false;
3474 for(i = 0; i < 8; i++) dpalette_pixel[i] = dpalette_pixel_tmp[i];
3475 //memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3476 //#if defined(_FM77AV_VARIANTS)
3477 hblank_event_id = -1;
3478 hdisp_event_id = -1;
3479 vsync_event_id = -1;
3480 vstart_event_id = -1;
3487 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
3488 is_cyclesteal = true;
3490 is_cyclesteal = false;
3492 multimode_accessmask = multimode_dispmask = 0;
3493 for(i = 0; i < 4; i++) {
3494 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
3495 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
3498 prev_clock = SUBCLOCK_NORMAL;
3502 key_firq_req = false; //firq_mask = true;
3503 frame_skip_count_transfer = 3;
3504 frame_skip_count_draw = 3;
3505 #if !defined(FIXED_FRAMEBUFFER_SIZE)
3506 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
3508 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
3510 emu->set_vm_screen_lines(200);
3511 #if defined(_FM77AV40SX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3512 mode400line = false;
3514 #elif defined(_FM77L4)
3515 mode400line = false;
3518 palette_changed = true;
3519 //#if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
3520 //register_vline_event(this);
3521 register_frame_event(this);
3523 setup_display_mode();
3526 void DISPLAY::release()
3530 #define STATE_VERSION 12
3532 bool DISPLAY::process_state(FILEIO *state_fio, bool loading)
3534 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
3537 if(!state_fio->StateCheckInt32(this_device_id)) {
3542 state_fio->StateValue(delay_busy);
3543 state_fio->StateValue(halt_flag);
3544 state_fio->StateValue(active_page);
3545 state_fio->StateValue(sub_busy);
3546 state_fio->StateValue(crt_flag);
3547 state_fio->StateValue(vram_wrote);
3548 state_fio->StateValue(is_cyclesteal);
3550 state_fio->StateValue(clock_fast);
3552 #if defined(_FM77AV_VARIANTS)
3553 state_fio->StateValue(subcpu_resetreq);
3554 state_fio->StateValue(power_on_reset);
3556 state_fio->StateValue(cancel_request);
3557 state_fio->StateValue(key_firq_req);
3558 state_fio->StateValue(display_mode);
3559 state_fio->StateValue(prev_clock);
3561 state_fio->StateArray(dpalette_data, sizeof(dpalette_data), 1);
3562 state_fio->StateValue(multimode_accessmask);
3563 state_fio->StateValue(multimode_dispmask);
3565 state_fio->StateValue(offset_point);
3566 #if defined(_FM77AV_VARIANTS)
3567 state_fio->StateValue(offset_point_bank1);
3569 //for(i = 0; i < 2; i++) {
3570 state_fio->StateArray(tmp_offset_point, sizeof(tmp_offset_point), 1);
3571 state_fio->StateArray(offset_changed, sizeof(offset_changed), 1);
3573 state_fio->StateValue(offset_77av);
3574 state_fio->StateValue(diag_load_subrom_c);
3575 state_fio->StateArray(io_w_latch, sizeof(io_w_latch), 1);
3576 state_fio->StateArray(console_ram, sizeof(console_ram), 1);
3577 state_fio->StateArray(work_ram, sizeof(work_ram), 1);
3578 state_fio->StateArray(shared_ram, sizeof(shared_ram), 1);
3579 state_fio->StateArray(subsys_c, sizeof(subsys_c), 1);
3580 state_fio->StateArray(gvram, sizeof(gvram), 1);
3581 state_fio->StateArray(gvram_shadow, sizeof(gvram_shadow), 1);
3582 #if defined(_FM77_VARIANTS)
3583 state_fio->StateValue(kanjisub);
3584 state_fio->StateValue(kanjiaddr.d);
3585 # if defined(_FM77L4)
3586 state_fio->StateValue(mode400line);
3587 state_fio->StateValue(stat_400linecard);
3589 #elif defined(_FM77AV_VARIANTS)
3590 state_fio->StateValue(kanjisub);
3591 state_fio->StateValue(kanjiaddr.d);
3592 state_fio->StateValue(mode320);
3593 state_fio->StateValue(cgrom_bank);
3594 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3595 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3596 state_fio->StateValue(vram_bank);
3598 state_fio->StateValue(displine);
3599 state_fio->StateValue(subrom_bank);
3600 state_fio->StateValue(subrom_bank_using);
3601 state_fio->StateValue(nmi_enable);
3602 state_fio->StateValue(use_alu);
3603 state_fio->StateValue(apalette_index.d);
3604 state_fio->StateArray(analog_palette_r, sizeof(analog_palette_r), 1);
3605 state_fio->StateArray(analog_palette_g, sizeof(analog_palette_g), 1);
3606 state_fio->StateArray(analog_palette_b, sizeof(analog_palette_b), 1);
3607 state_fio->StateValue(diag_load_subrom_a);
3608 state_fio->StateValue(diag_load_subrom_b);
3609 state_fio->StateValue(diag_load_subrom_cg);
3611 state_fio->StateArray(subsys_a, sizeof(subsys_a), 1);
3612 state_fio->StateArray(subsys_b, sizeof(subsys_b), 1);
3613 state_fio->StateArray(subsys_cg, sizeof(subsys_cg), 1);
3614 state_fio->StateArray(submem_hidden, sizeof(submem_hidden), 1);
3615 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3616 state_fio->StateValue(mode400line);
3617 state_fio->StateValue(mode256k);
3618 state_fio->StateValue(monitor_ram);
3619 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3620 state_fio->StateValue(window_low);
3621 state_fio->StateValue(window_high);
3622 state_fio->StateValue(window_xbegin);
3623 state_fio->StateValue(window_xend);
3624 state_fio->StateValue(window_opened);
3626 state_fio->StateValue(kanji_level2);
3627 state_fio->StateValue(vram_active_block);
3628 state_fio->StateValue(vram_display_block);
3629 state_fio->StateValue(console_ram_bank);
3630 state_fio->StateValue(ram_protect);
3631 state_fio->StateValue(cgram_bank);
3632 state_fio->StateArray(subsys_ram, sizeof(subsys_ram), 1);
3633 state_fio->StateArray(submem_cgram, sizeof(submem_cgram), 1);
3634 state_fio->StateArray(submem_console_av40, sizeof(submem_console_av40), 1);
3640 state_fio->StateValue(nmi_event_id);
3641 //#if defined(_FM77AV_VARIANTS)
3642 state_fio->StateValue(hblank_event_id);
3643 state_fio->StateValue(hdisp_event_id);
3644 state_fio->StateValue(vsync_event_id);
3645 state_fio->StateValue(vstart_event_id);
3647 state_fio->StateValue(firq_mask);
3648 state_fio->StateValue(vram_accessflag);
3649 state_fio->StateValue(display_page);
3650 state_fio->StateValue(display_page_bak);
3651 state_fio->StateValue(vblank);
3652 state_fio->StateValue(vsync);
3653 state_fio->StateValue(hblank);
3654 state_fio->StateValue(vblank_count);
3656 #if defined(_FM77L4)
3657 state_fio->StateArray(subsys_cg_l4, sizeof(subsys_cg_l4), 1);
3658 state_fio->StateArray(subsys_l4, sizeof(subsys_l4), 1);
3659 state_fio->StateArray(text_vram, sizeof(text_vram), 1);
3660 //state_fio->Fwrite(crtc_regs, sizeof(crtc_regs), 1);
3661 state_fio->StateValue(workram_l4);
3662 state_fio->StateValue(cursor_lsb);
3663 state_fio->StateValue(text_width40);
3665 state_fio->StateValue(text_blink);
3666 state_fio->StateValue(cursor_blink);
3668 state_fio->StateValue(text_start_addr.d);
3669 state_fio->StateValue(text_lines);
3670 state_fio->StateValue(text_xmax);
3672 state_fio->StateValue(cursor_addr.d);
3673 state_fio->StateValue(cursor_start);
3674 state_fio->StateValue(cursor_end);
3675 state_fio->StateValue(cursor_type);
3676 state_fio->StateValue(text_scroll_count);
3678 state_fio->StateValue(event_id_l4_cursor_blink);
3679 state_fio->StateValue(event_id_l4_text_blink);
3685 crt_flag_bak = true;
3686 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
3687 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
3689 for(addr = 0; addr < 8; addr++) set_dpalette(addr, addr);
3690 //memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3692 for(addr = 0; addr < 8; addr++) set_dpalette(addr, dpalette_data[addr]);
3693 for(i = 0; i < 4; i++) {
3694 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
3695 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
3699 for(i = 0; i < 8; i++) dpalette_pixel[i] = dpalette_pixel_tmp[i];
3700 #if defined(USE_GREEN_DISPLAY)
3701 //memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3702 for(i = 0; i < 8; i++) dpalette_pixel_green[i] = dpalette_green_tmp[i];
3705 #if defined(_FM77AV_VARIANTS)
3706 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3707 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3709 screen_update_flag = true;
3710 for(i = 0; i < 4096; i++) calc_apalette(i);
3711 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
3714 palette_changed = true;
3715 vram_wrote_shadow = true; // Force Draw
3716 this->draw_screen();
3718 frame_skip_count_draw = 3;
3719 frame_skip_count_transfer = 3;
3720 need_transfer_line = true;
3721 #if defined(USE_GREEN_DISPLAY) && defined(USE_MONITOR_TYPE)
3722 switch(config.monitor_type) {
3723 case FM7_MONITOR_GREEN:
3724 use_green_monitor = true;
3726 case FM7_MONITOR_STANDARD:
3728 use_green_monitor = false;
3732 //use_green_monitor = false;
3734 force_update = true;
3735 setup_display_mode();