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)
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));
177 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
178 //do_firq(!firq_mask && key_firq_req);
180 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
181 //kanjisub = false; // Fixed by Ryu takegami
182 kanjiaddr.d = 0x00000000;
183 # if defined(_FM77L4)
185 stat_400linecard = false;
190 frame_skip_count_draw = 3;
191 frame_skip_count_transfer = 3;
192 need_transfer_line = true;
193 setup_display_mode();
198 void DISPLAY::reset()
202 vram_accessflag = true;
203 display_mode = DISPLAY_MODE_8_200L;
205 crt_flag = false; // Fixed by Ryu Takegami
206 screen_update_flag = true;
207 crt_flag_bak = false;
208 cancel_request = false;
209 #if defined(_FM77AV_VARIANTS)
211 apalette_index.d = 0;
212 for(i = 0; i < 4096; i++) {
213 analog_palette_r[i] = i & 0x0f0;
214 analog_palette_g[i] = (i & 0xf00) >> 4;
215 analog_palette_b[i] = (i & 0x00f) << 4;
217 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
221 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
228 #elif defined(_FM77L4)
230 stat_400linecard = false;
234 text_width40 = false;
239 text_start_addr.d = 0x0000;
247 text_scroll_count = 0;
253 uint8_t *regs = l4crtc->get_regs();
254 display_mode = DISPLAY_MODE_1_400L;
255 if(event_id_l4_cursor_blink >= 0) {
256 cancel_event(this, event_id_l4_cursor_blink);
258 if(event_id_l4_text_blink >= 0) {
259 cancel_event(this, event_id_l4_text_blink);
261 event_id_l4_cursor_blink = -1;
262 event_id_l4_text_blink = -1;
264 usec = ((regs[10] & 0x20) == 0) ? 160.0 : 320.0;
265 usec = usec * 1000.0;
266 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
267 usec = 160.0 * 1000.0;
268 register_event(this, EVENT_FM7SUB_TEXT_BLINK, true, usec, &event_id_l4_cursor_blink);
271 //memset(crtc_regs, 0x00, sizeof(crtc_regs));
274 #if !defined(FIXED_FRAMEBUFFER_SIZE)
275 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
277 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
279 emu->set_vm_screen_lines(200);
281 reset_some_devices();
283 #if defined(_FM77AV_VARIANTS)
284 power_on_reset = false;
285 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
289 for(i = 0; i < 8; i++) set_dpalette(i, i);
292 #if defined(USE_GREEN_DISPLAY) && defined(USE_MONITOR_TYPE)
293 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
294 switch(config.monitor_type) {
295 case FM7_MONITOR_GREEN:
296 use_green_monitor = true;
298 case FM7_MONITOR_STANDARD:
300 use_green_monitor = false;
304 //use_green_monitor = false;
308 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
311 if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
312 register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
315 key_firq_req = false;
320 void DISPLAY::reset_subcpu(bool _check_firq)
322 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0, 1);
323 call_write_signal(subcpu, SIG_CPU_BUSREQ, 0, 1);
326 do_firq(!firq_mask && key_firq_req);
329 void DISPLAY::setup_display_mode(void)
331 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
332 if(display_mode == DISPLAY_MODE_8_400L) {
333 page_offset = 0x0000;
334 pagemod_mask = 0x18000;
336 } else if(display_mode == DISPLAY_MODE_256k) {
337 if(active_page != 0) {
338 page_offset = 0xc000;
340 page_offset = 0x0000;
342 pagemod_mask = 0xe000;
344 } else if(display_mode == DISPLAY_MODE_4096) {
345 if(active_page != 0) {
346 page_offset = 0xc000;
348 page_offset = 0x0000;
350 pagemod_mask = 0xe000;
353 if(active_page != 0) {
354 page_offset = 0xc000;
356 page_offset = 0x0000;
358 pagemod_mask = 0xc000;
361 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
362 if(vram_active_block != 0) page_offset += 0x18000;
364 #elif defined(_FM77AV_VARIANTS)
367 pagemod_mask = 0xe000;
368 } else { // 640x200, 8colors
370 pagemod_mask = 0xc000;
372 if(active_page != 0) {
373 page_offset = 0xc000;
375 page_offset = 0x0000;
377 #elif defined(_FM77L4)
378 if(display_mode == DISPLAY_MODE_1_400L) {
380 pagemod_mask = 0x0000;
381 page_offset = 0x0000;
382 } else { // 640x200, 8colors
384 pagemod_mask = 0xc000;
385 page_offset = 0x0000;
387 page_offset = 0x0000;
389 page_offset = 0x0000;
390 pagemod_mask = 0xc000;
395 void DISPLAY::update_config()
401 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
407 * Vram accessing functions moved to vram.cpp .
410 void DISPLAY::do_irq(bool flag)
412 call_write_signal(subcpu, SIG_CPU_IRQ, flag ? 1: 0, 1);
415 void DISPLAY::do_firq(bool flag)
417 call_write_signal(subcpu, SIG_CPU_FIRQ, flag ? 1: 0, 1);
420 void DISPLAY::do_nmi(bool flag)
422 #if defined(_FM77AV_VARIANTS)
423 if(!nmi_enable) flag = false;
425 call_write_signal(subcpu, SIG_CPU_NMI, flag ? 1 : 0, 1);
428 void DISPLAY::set_multimode(uint8_t val)
431 multimode_accessmask = val & 0x07;
432 multimode_dispmask = (val & 0x70) >> 4;
433 for(int i = 0; i < 4; i++) {
434 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
435 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
438 # if defined(_FM77AV_VARIANTS)
439 call_write_signal(alu, SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
444 uint8_t DISPLAY::get_multimode(void)
450 val = multimode_accessmask & 0x07;
451 val |= ((multimode_dispmask << 4) & 0x70);
457 uint8_t DISPLAY::get_cpuaccessmask(void)
459 return multimode_accessmask & 0x07;
462 void DISPLAY::set_dpalette(uint32_t addr, uint8_t val)
466 if(dpalette_data[addr] != (val | 0xf8)) {
467 dpalette_data[addr] = val | 0xf8; //0b11111000;
468 b = ((val & 0x01) != 0x00)? 255 : 0x00;
469 r = ((val & 0x02) != 0x00)? 255 : 0x00;
470 g = ((val & 0x04) != 0x00)? 255 : 0x00;
472 dpalette_pixel_tmp[addr] = RGB_COLOR(r, g, b);
473 #if defined(USE_GREEN_DISPLAY)
474 static const scrntype_t colortable[8] = {0, 48, 70, 100, 140, 175, 202, 255};
475 g = colortable[val & 0x07];
476 b = r = ((val & 0x07) > 4) ? 48 : 0;
477 dpalette_green_tmp[addr] = RGB_COLOR(r, g, b);
479 palette_changed = true;
483 uint8_t DISPLAY::get_dpalette(uint32_t addr)
491 data = dpalette_data[addr];
496 void DISPLAY::halt_subcpu(void)
498 //call_write_signal(subcpu, SIG_CPU_BUSREQ, 0x01, 0x01);
499 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0x01, 0x01);
502 void DISPLAY::go_subcpu(void)
504 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0x00, 0x01);
507 void DISPLAY::enter_display(void)
512 subclock = SUBCLOCK_NORMAL;
514 subclock = SUBCLOCK_SLOW;
516 if(!(is_cyclesteal) && (vram_accessflag)) {
517 subclock = subclock / 3;
519 if(prev_clock != subclock) {
520 vm->set_cpu_clock(subcpu, subclock);
522 prev_clock = subclock;
526 void DISPLAY::leave_display(void)
530 void DISPLAY::halt_subsystem(void)
536 void DISPLAY::restart_subsystem(void)
539 #if defined(_FM77AV_VARIANTS)
540 if(subcpu_resetreq) {
541 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
542 reset_some_devices();
543 power_on_reset = true;
551 void DISPLAY::set_crtflag(void)
558 void DISPLAY::reset_crtflag(void)
565 uint8_t DISPLAY::acknowledge_irq(void)
567 cancel_request = false;
573 uint8_t DISPLAY::beep(void)
575 call_write_signal(mainio, FM7_MAINIO_BEEP, 0x01, 0x01);
576 return 0xff; // True?
581 uint8_t DISPLAY::attention_irq(void)
583 call_write_signal(mainio, FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
588 void DISPLAY::set_cyclesteal(uint8_t val)
591 # if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
595 is_cyclesteal = true;
597 is_cyclesteal = false;
604 void DISPLAY::setup_400linemode(uint8_t val)
608 cursor_lsb = ((val & 0x10) != 0);
609 text_width40 = ((val & 0x08) != 0);
610 workram_l4 = ((val & 0x04) != 0);
611 bool tmpmode = ((val & 0x02) != 0);
612 if(tmpmode != mode400line) {
613 int oldmode = display_mode;
614 mode400line = tmpmode;
615 if(mode400line && stat_400linecard) {
616 display_mode = DISPLAY_MODE_1_400L;
618 display_mode = DISPLAY_MODE_8_200L;
620 if(oldmode != display_mode) {
622 if(display_mode == DISPLAY_MODE_1_400L) {
623 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
624 for(int y = 0; y < 400; y++) {
625 pp = emu->get_screen_buffer(y);
626 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
630 vm->set_vm_frame_rate(FRAMES_PER_SEC);
631 #if !defined(FIXED_FRAMEBUFFER_SIZE)
632 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
633 for(int y = 0; y < 200; y++) {
634 pp = emu->get_screen_buffer(y);
635 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
638 for(int y = 0; y < 400; y++) {
639 pp = emu->get_screen_buffer(y);
640 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
645 setup_display_mode();
653 uint8_t DISPLAY::set_vramaccess(void)
655 vram_accessflag = true;
661 void DISPLAY::reset_vramaccess(void)
663 vram_accessflag = false;
668 uint8_t DISPLAY::reset_subbusy(void)
675 void DISPLAY::set_subbusy(void)
681 #if defined(_FM77AV_VARIANTS)
683 void DISPLAY::alu_write_cmdreg(uint32_t val)
685 call_write_data8(alu, ALU_CMDREG, val);
686 if((val & 0x80) != 0) {
694 void DISPLAY::alu_write_logical_color(uint8_t val)
696 uint32_t data = (uint32_t)val;
697 call_write_data8(alu, ALU_LOGICAL_COLOR, data);
701 void DISPLAY::alu_write_mask_reg(uint8_t val)
703 uint32_t data = (uint32_t)val;
704 call_write_data8(alu, ALU_WRITE_MASKREG, data);
708 void DISPLAY::alu_write_cmpdata_reg(int addr, uint8_t val)
710 uint32_t data = (uint32_t)val;
712 call_write_data8(alu, ALU_CMPDATA_REG + addr, data);
716 void DISPLAY::alu_write_disable_reg(uint8_t val)
718 uint32_t data = (uint32_t)val;
719 call_write_data8(alu, ALU_BANK_DISABLE, data);
723 void DISPLAY::alu_write_tilepaint_data(uint32_t addr, uint8_t val)
725 uint32_t data = (uint32_t)val;
728 call_write_data8(alu, ALU_TILEPAINT_B, data);
731 call_write_data8(alu, ALU_TILEPAINT_R, data);
734 call_write_data8(alu, ALU_TILEPAINT_G, data);
737 //call_write_data8(alu, ALU_TILEPAINT_L, 0xff);
743 void DISPLAY::alu_write_offsetreg_hi(uint8_t val)
745 call_write_data8(alu, ALU_OFFSET_REG_HIGH, val & 0x7f);
749 void DISPLAY::alu_write_offsetreg_lo(uint8_t val)
751 call_write_data8(alu, ALU_OFFSET_REG_LO, val);
755 void DISPLAY::alu_write_linepattern_hi(uint8_t val)
757 call_write_data8(alu, ALU_LINEPATTERN_REG_HIGH, val);
761 void DISPLAY::alu_write_linepattern_lo(uint8_t val)
763 call_write_data8(alu, ALU_LINEPATTERN_REG_LO, val);
767 void DISPLAY::alu_write_line_position(int addr, uint8_t val)
769 uint32_t data = (uint32_t)val;
772 call_write_data8(alu, ALU_LINEPOS_START_X_HIGH, data & 0x03);
775 call_write_data8(alu, ALU_LINEPOS_START_X_LOW, data);
778 call_write_data8(alu, ALU_LINEPOS_START_Y_HIGH, data & 0x01);
781 call_write_data8(alu, ALU_LINEPOS_START_Y_LOW, data);
784 call_write_data8(alu, ALU_LINEPOS_END_X_HIGH, data & 0x03);
787 call_write_data8(alu, ALU_LINEPOS_END_X_LOW, data);
790 call_write_data8(alu, ALU_LINEPOS_END_Y_HIGH, data & 0x01);
793 call_write_data8(alu, ALU_LINEPOS_END_Y_LOW, data);
799 uint8_t DISPLAY::get_miscreg(void)
804 if(!hblank) ret |= 0x80;
805 if(vsync) ret |= 0x04;
806 if(alu->read_signal(SIG_ALU_BUSYSTAT) == 0) ret |= 0x10;
807 if(power_on_reset) ret |= 0x01;
812 void DISPLAY::set_miscreg(uint8_t val)
814 int old_display_page = display_page;
816 nmi_enable = ((val & 0x80) == 0) ? true : false;
817 if(!nmi_enable) do_nmi(false);
819 if((val & 0x40) == 0) {
824 if(display_page != old_display_page) {
827 active_page = ((val & 0x20) == 0) ? 0 : 1;
828 if((val & 0x04) == 0) {
833 cgrom_bank = val & 0x03;
834 setup_display_mode();
838 void DISPLAY::set_monitor_bank(uint8_t var)
840 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
841 if((var & 0x04) != 0){
847 subrom_bank = var & 0x03;
850 subcpu_resetreq = false;
851 power_on_reset = true;
852 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
853 reset_some_devices();
856 subcpu_resetreq = true;
862 void DISPLAY::set_apalette_index_hi(uint8_t val)
864 apalette_index.b.h = val & 0x0f;
868 void DISPLAY::set_apalette_index_lo(uint8_t val)
870 apalette_index.b.l = val;
873 void DISPLAY::calc_apalette(uint16_t idx)
877 g = analog_palette_g[idx];
878 r = analog_palette_r[idx];
879 b = analog_palette_b[idx];
880 if(g != 0) g |= 0x0f;
881 if(r != 0) r |= 0x0f;
882 if(b != 0) b |= 0x0f;
883 analog_palette_pixel_tmp[idx] = RGB_COLOR(r, g, b);
887 void DISPLAY::set_apalette_b(uint8_t val)
891 index = apalette_index.w.l;
892 tmp = (val & 0x0f) << 4;
893 if(analog_palette_b[index] != tmp) {
894 analog_palette_b[index] = tmp;
895 calc_apalette(index);
896 palette_changed = true;
901 void DISPLAY::set_apalette_r(uint8_t val)
905 index = apalette_index.w.l;
906 tmp = (val & 0x0f) << 4;
907 if(analog_palette_r[index] != tmp) {
908 analog_palette_r[index] = tmp;
909 calc_apalette(index);
910 palette_changed = true;
915 void DISPLAY::set_apalette_g(uint8_t val)
919 index = apalette_index.w.l;
920 tmp = (val & 0x0f) << 4;
921 if(analog_palette_g[index] != tmp) {
922 analog_palette_g[index] = tmp;
923 calc_apalette(index);
924 palette_changed = true;
928 #endif // _FM77AV_VARIANTS
931 void DISPLAY::copy_vram_blank_area(void)
935 void DISPLAY::copy_vram_per_line(int begin, int end)
938 uint32_t yoff_d1 = 0;
939 uint32_t yoff_d2 = 0;
944 uint32_t src_offset_d1;
945 uint32_t src_offset_d2;
946 uint32_t src_offset_d;
951 uint32_t addr_d1, addr_d2;
955 //int dline = (int)displine - 1;
956 int dline = (int)displine;
958 if((begin < 0) || (begin > 4)) return;
959 if((end < 0) || (end > 4)) return;
960 if(begin > end) return;
961 if(dline < 0) return;
963 sectors = end - begin + 1;
965 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)){
966 if(dline >= 400) return;
968 if(dline >= 200) return;
970 #if defined(_FM77AV_VARIANTS)
971 yoff_d1 = offset_point;
972 yoff_d2 = offset_point_bank1;
973 if(display_mode == DISPLAY_MODE_4096) {
974 src_offset = dline * 40 + begin * 8;
975 sectors = sectors * 8;
976 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
979 addr_d1 = (src_offset + yoff_d1) & 0x1fff;
980 addr_d2 = (src_offset + yoff_d2) & 0x1fff;
981 bytes_d1 = 0x2000 - addr_d1;
982 bytes_d2 = 0x2000 - addr_d2;
983 for(k = 0; k < pages; k++) {
985 for(i = 0; i < 3; i++) {
986 for(j = 0; j < 2; j++) {
987 uint32_t _addr_base = src_base + src_offset + poff;
988 if(bytes_d1 < sectors) {
989 my_memcpy(&gvram_shadow[_addr_base],
990 &gvram[addr_d1 + src_base + poff],
992 my_memcpy(&gvram_shadow[_addr_base + bytes_d1],
993 &gvram[src_base + poff],
996 my_memcpy(&gvram_shadow[_addr_base],
997 &gvram[addr_d1 + src_base + poff],
1000 _addr_base += 0xc000;
1001 if(bytes_d2 < sectors) {
1002 my_memcpy(&gvram_shadow[_addr_base],
1003 &gvram[addr_d2 + src_base + poff + 0xc000],
1005 my_memcpy(&gvram_shadow[_addr_base + bytes_d2],
1006 &gvram[src_base + poff + 0xc000],
1007 sectors - bytes_d2);
1009 my_memcpy(&gvram_shadow[_addr_base],
1010 &gvram[addr_d2 + src_base + poff + 0xc000],
1015 src_base = (i + 1) * 0x4000;
1019 vram_draw_table[dline] = true;
1020 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1022 # if defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV40)
1023 else if(display_mode == DISPLAY_MODE_256k) {
1024 src_offset = dline * 40 + begin * 8;
1025 sectors = sectors * 8;
1027 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1029 #elif defined(_FM77AV40)
1034 src_offset_d1 = (src_offset + yoff_d1) & 0x1fff;
1035 src_offset_d2 = (src_offset + yoff_d2) & 0x1fff;
1036 bytes_d1 = 0x2000 - ((src_offset + yoff_d1) & 0x1fff);
1037 bytes_d2 = 0x2000 - ((src_offset + yoff_d2) & 0x1fff);
1038 for(k = 0; k < pages; k++) {
1039 for(i = 0; i < 3; i++) {
1040 for(j = 0; j < 2; j++) {
1042 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
1043 src_offset_d = src_offset_d1;
1046 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
1047 src_offset_d = src_offset_d2;
1050 if(bytes_d < sectors) {
1051 my_memcpy(&gvram_shadow[src_offset + src_base],
1052 &gvram[src_offset_d + src_base],
1054 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1058 my_memcpy(&gvram_shadow[src_offset + src_base],
1059 &gvram[src_offset_d + src_base],
1065 vram_draw_table[dline] = true;
1066 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1068 else if(display_mode == DISPLAY_MODE_8_400L) {
1069 src_offset = dline * 80 + begin * 16;
1070 sectors = sectors * 16;
1071 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1074 if(display_page_bak == 1) { // Is this dirty?
1079 yoff_d = (yoff_d << 1) & 0x7fff;
1080 src_offset_d = (src_offset + yoff_d) & 0x7fff;
1081 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
1082 for(i = 0; i < pages; i++) {
1083 for(j = 0; j < 3; j++) {
1084 src_base = i * 0x18000 + j * 0x8000;
1085 if(bytes_d < sectors) {
1087 my_memcpy(&gvram_shadow[src_offset + src_base],
1088 &gvram[src_offset_d + src_base],
1091 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1095 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1096 &gvram[src_offset_d + src_base],
1101 vram_draw_table[dline] = true;
1102 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1106 src_offset = dline * 80 + begin * 16;
1107 sectors = sectors * 16;
1108 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1110 #elif defined(_FM77AV40)
1112 #elif defined(_FM77AV_VARIANTS)
1118 src_offset_d1 = (src_offset + yoff_d1) & 0x3fff;
1119 src_offset_d2 = (src_offset + yoff_d2) & 0x3fff;
1120 bytes_d1 = 0x4000 - ((src_offset + yoff_d1) & 0x3fff);
1121 bytes_d2 = 0x4000 - ((src_offset + yoff_d2) & 0x3fff);
1122 for(i = 0; i < pages; i++) {
1124 src_offset_d = src_offset_d1;
1127 src_offset_d = src_offset_d2;
1131 for(j = 0; j < 3; j++) {
1132 if(bytes_d < sectors) {
1133 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1134 &gvram[src_offset_d + src_base + poff],
1136 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1137 &gvram[src_base + poff],
1140 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1141 &gvram[src_offset_d + src_base + poff],
1148 vram_draw_table[dline] = true;
1149 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1150 //vram_wrote_table[dline] = false;
1153 #if defined(_FM77L4)
1154 if(display_mode == DISPLAY_MODE_1_400L) {
1155 src_offset = dline * 80 + begin * 16;
1156 sectors = sectors * 16;
1157 yoff_d = (yoff_d1 << 1) & 0x7fff;
1158 src_offset_d = (src_offset + yoff_d) & 0x7fff;
1159 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
1160 if(bytes_d < sectors) {
1162 my_memcpy(&gvram_shadow[src_offset],
1163 &gvram[src_offset_d],
1166 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1170 my_memcpy(&gvram_shadow[src_offset + poff],
1171 &gvram[src_offset_d ],
1174 vram_draw_table[dline] = true;
1175 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1180 src_offset = dline * 80 + begin * 16;
1181 sectors = sectors * 16;
1184 yoff_d = offset_point;
1185 src_offset_d = (src_offset + yoff_d) & 0x3fff;
1186 bytes_d = 0x4000 - ((src_offset + yoff_d) & 0x3fff);
1187 for(j = 0; j < 3; j++) {
1188 src_base = j * 0x4000;
1189 if(bytes_d < sectors) {
1190 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1191 &gvram[src_offset_d + src_base + poff],
1193 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1194 &gvram[src_base + poff],
1197 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1198 &gvram[src_offset_d + src_base + poff],
1202 vram_draw_table[dline] = true;
1203 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1204 //vram_wrote_table[dline] = false;
1210 void DISPLAY::copy_vram_all()
1212 #if defined(_FM77AV_VARIANTS)
1213 uint32_t yoff_d1 = offset_point;
1214 uint32_t yoff_d2 = offset_point_bank1;
1215 uint32_t src_offset_1, src_offset_2;
1217 if(display_mode == DISPLAY_MODE_4096) {
1218 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1223 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1224 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1225 for(int k = 0; k < pages; k++) {
1226 for(int i = 0; i < 3; i++) {
1227 for(int j = 0; j < 2; j++) {
1228 src_offset_1 = i * 0x4000 + j * 0x2000;
1229 src_offset_2 = src_offset_1 + 0xc000;
1230 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1231 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1232 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1233 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1239 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1240 else if(display_mode == DISPLAY_MODE_256k) {
1241 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1242 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1243 for(int i = 0; i < 3; i++) {
1244 for(int j = 0; j < 2; j++) {
1245 src_offset_1 = i * 0x4000 + j * 0x2000;
1246 src_offset_2 = src_offset_1 + 0xc000;
1247 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1248 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1249 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1250 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1254 for(int i = 0; i < 3; i++) {
1255 for(int j = 0; j < 2; j++) {
1256 src_offset_1 = i * 0x4000 + j * 0x2000;
1257 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1258 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1261 } else if(display_mode == DISPLAY_MODE_8_400L) {
1263 uint32_t yoff_d, bytes_d;
1264 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1267 if(display_page_bak == 1) { // Is this dirty?
1272 yoff_d = (yoff_d << 1) & 0x7fff;
1273 bytes_d = 0x8000 - yoff_d;
1274 for(int i = 0; i < pages; i++) {
1275 for(int j = 0; j < 3; j++) {
1276 uint32_t src_base = i * 0x18000 + j * 0x8000;
1277 my_memcpy(&gvram_shadow[src_base],
1278 &gvram[yoff_d + src_base],
1280 if(bytes_d < 0x8000) {
1281 my_memcpy(&gvram_shadow[bytes_d + src_base],
1290 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1292 #elif defined(_FM77AV40)
1297 uint32_t bytes_d1 = 0x4000 - (yoff_d1 & 0x3fff);
1298 uint32_t bytes_d2 = 0x4000 - (yoff_d2 & 0x3fff);
1299 uint32_t yoff_d, bytes_d;
1300 for(int k = 0; k < pages; k++) {
1301 yoff_d = ((k & 1) == 0) ? (yoff_d1 & 0x3fff) : (yoff_d2 & 0x3fff);
1302 bytes_d = ((k & 1) == 0) ? bytes_d1 : bytes_d2;
1303 for(int j = 0; j < 3; j++) {
1304 src_offset_1 = k * 0xc000 + j * 0x4000;
1305 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1306 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1311 # if defined(_FM77L4)
1312 if(display_mode == DISPLAY_MODE_1_400L) {
1313 uint32_t yoff_d = offset_point & 0x7fff;
1314 uint32_t bytes_d = 0x8000 - (offset_point & 0x7fff);
1315 my_memcpy(&gvram_shadow[0], &gvram[0 + yoff_d], bytes_d);
1316 my_memcpy(&gvram_shadow[0 + bytes_d], &gvram[0], 0x8000 - bytes_d);
1321 uint32_t yoff_d = offset_point & 0x3fff;
1322 uint32_t bytes_d = 0x4000 - (offset_point & 0x3fff);
1323 uint32_t src_offset_1;
1324 for(int j = 0; j < 3; j++) {
1325 src_offset_1 = j * 0x4000;
1326 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1327 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1333 // Timing values from XM7 . Thanks Ryu.
1334 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1335 void DISPLAY::event_callback_hdisp(void)
1340 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x02, 0xff);
1341 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1342 if(displine < 400) f = true;
1344 if(displine < 200) f = true;
1347 hdisp_event_id = -1;
1349 // DO ONLY WHEN SYNC-TO-HSYNC.
1350 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
1352 //copy_vram_per_line(0, 4);
1353 } else if(need_transfer_line) { // Not frame skip.
1356 for(int iii = 0; iii < 5 ; iii++) {
1357 if(vram_wrote_table[iii + displine * 5]) {
1358 if(begin < 0) begin = iii; // Check first.
1363 if(end < begin) end = begin;
1365 copy_vram_per_line(begin, end);
1366 // Prepare to next block.
1372 // Tail of this line.
1375 copy_vram_per_line(begin, end);
1379 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1380 register_event(this, EVENT_FM7SUB_HBLANK, 30.0, false, &hblank_event_id); // NEXT CYCLE_
1382 register_event(this, EVENT_FM7SUB_HBLANK, 39.5, false, &hblank_event_id); // NEXT CYCLE_
1390 void DISPLAY::event_callback_hblank(void)
1397 hblank_event_id = -1;
1399 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1400 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1401 if((displine < 400)) f = true;
1404 if((displine < 200)) f = true;
1408 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id);
1413 void DISPLAY::event_callback_vstart(void)
1420 display_page_bak = display_page;
1422 // Parameter from XM7/VM/display.c , thanks, Ryu.
1423 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1424 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x00, 0xff);
1426 if(vblank_count != 0) {
1427 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1428 usec = (0.98 + 16.4) * 1000.0;
1430 usec = (1.91 + 12.7) * 1000.0;
1432 register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
1434 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1435 usec = 930.0; // 939.0
1437 usec = 1840.0; // 1846.5
1439 vstart_event_id = -1;
1440 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
1441 //register_event(this, EVENT_FM7SUB_HBLANK, usec, false, &hdisp_event_id); // NEXT CYCLE_
1444 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1445 usec = 0.34 * 1000.0;
1447 usec = 1.52 * 1000.0;
1449 vsync_event_id = -1;
1450 hblank_event_id = -1;
1451 hdisp_event_id = -1;
1452 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1456 void DISPLAY::event_callback_vsync(void)
1462 //write_access_page = (write_access_page + 1) & 1;
1465 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x01, 0xff);
1466 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1467 //if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1468 // usec = 0.33 * 1000.0;
1470 // usec = 0.51 * 1000.0;
1472 //register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1473 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))!!!"
1474 if(palette_changed) {
1475 #if defined(_FM77AV_VARIANTS)
1476 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
1478 #if defined(USE_GREEN_DISPLAY)
1479 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
1481 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
1482 vram_wrote_shadow = true;
1483 for(int yy = 0; yy < 400; yy++) {
1484 vram_draw_table[yy] = true;
1486 palette_changed = false;
1488 // Transfer on VSYNC
1489 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) {
1493 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L))lines = 400;
1494 if(need_transfer_line) {
1495 if(vram_wrote) { // transfer all line
1496 for(displine = 0; displine < lines; displine++) {
1497 //if(!vram_draw_table[displine]) {
1498 copy_vram_per_line(0, 4);
1502 } else { // transfer wrote line
1505 for(displine = 0; displine < lines; displine++) {
1506 //if(!vram_draw_table[displine]) {
1507 for(int iii = 0; iii < 5 ; iii++) {
1508 if(vram_wrote_table[iii + displine * 5]) {
1515 if(end < begin) end = begin;
1516 copy_vram_per_line(begin, end);
1523 if(end < 0) end = 4;
1524 copy_vram_per_line(begin, end);
1532 for(int yy = 0; yy < lines; yy++) {
1533 if(vram_draw_table[yy]) {
1534 vram_wrote_shadow = true;
1535 screen_update_flag = true;
1540 // TRANSFER per HSYNC a.k.a SYNC-TO-HSYNC.
1542 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) lines = 400;
1544 if(need_transfer_line) {
1545 if(vram_wrote) { // Transfer all line.
1546 for(int yy = 0; yy < lines; yy++) {
1548 copy_vram_per_line(0, 4);
1554 for(int yy = 0; yy < lines; yy++) {
1555 if(vram_draw_table[yy]) {
1556 vram_wrote_shadow = true;
1557 screen_update_flag = true;
1561 //vram_wrote = false;
1563 frame_skip_count_transfer++;
1565 // Check frame skip for next frame.
1566 uint32_t factor = ((config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28) & 3;
1567 if((frame_skip_count_transfer > factor) /* || (vram_wrote) */) {
1568 frame_skip_count_transfer = 0;
1569 need_transfer_line = true;
1571 need_transfer_line = false;
1577 #if defined(_FM77L4)
1578 void DISPLAY::cursor_blink_77l4()
1580 if(!(mode400line && stat_400linecard)) return;
1581 uint8_t *regs = l4crtc->get_regs();
1585 if((regs[10] & 0x40) != 0) {
1586 cursor_blink = !cursor_blink;
1587 uint16_t addr = cursor_addr.w.l;
1589 x = ((addr / 2) % 40) / 8;
1590 y = (addr / 2) / 40;
1591 } else { // Width 80
1592 x = ((addr / 2) % 80) / 8;
1593 y = (addr / 2) / 80;
1595 for(int yy = 0; yy < 8; yy++) {
1596 naddr = (y + yy) * 5 + x;
1597 vram_wrote_table[naddr] = true;
1603 void DISPLAY::text_blink_77l4()
1606 uint16_t offset = text_start_addr.w.l;
1609 if(!(mode400line && stat_400linecard)) return;
1610 text_blink = !text_blink;
1611 for(addr = 0; addr < (80 * 50); addr++) {
1612 naddr = ((addr + offset) & 0x0ffe) + 1;
1613 if((text_vram[naddr] & 0x10) != 0) { // ATTR BLINK
1615 x = ((naddr / 2) % 40) / 8;
1616 y = (naddr / 2) / 40;
1617 } else { // Width 80
1618 x = ((naddr / 2) % 80) / 8;
1619 y = (naddr / 2) / 80;
1621 for(int yy = 0; yy < 8; yy++) {
1622 naddr = (y + yy) * 5 + x;
1623 vram_wrote_table[naddr] = true;
1628 #endif //#if defined(_FM77L4)
1630 void DISPLAY::event_callback(int event_id, int err)
1635 case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
1636 #if defined(_FM77AV_VARIANTS)
1644 case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
1647 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1648 case EVENT_FM7SUB_HDISP:
1649 event_callback_hdisp();
1651 case EVENT_FM7SUB_HBLANK:
1652 event_callback_hblank();
1654 case EVENT_FM7SUB_VSTART: // Call first.
1655 event_callback_vstart();
1657 case EVENT_FM7SUB_VSYNC:
1658 event_callback_vsync();
1661 case EVENT_FM7SUB_DELAY_BUSY:
1665 case EVENT_FM7SUB_CLEAR_DELAY:
1668 case EVENT_FM7SUB_CLR_CRTFLAG:
1671 #if defined(_FM77L4)
1672 case EVENT_FM7SUB_CURSOR_BLINK:
1673 cursor_blink_77l4();
1675 case EVENT_FM7SUB_TEXT_BLINK:
1682 void DISPLAY::event_frame()
1689 //write_access_page = (write_access_page + 1) & 1;
1690 //out_debug_log(_T("DISPLINE=%d"), displine);
1692 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1693 usec = 0.34 * 1000.0;
1695 usec = 1.52 * 1000.0;
1697 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x01, 0xff);
1698 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1699 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1703 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1707 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) lines = 400;
1709 if(need_transfer_line && vram_wrote) {
1710 for(yy = 0; yy < lines; yy++) {
1711 //if(!vram_draw_table[yy]) {
1713 copy_vram_per_line(0, 4);
1721 for(yy = 0; yy < lines; yy++) {
1722 if(vram_draw_table[yy]) {
1728 screen_update_flag = true;
1729 vram_wrote_shadow = true;
1733 frame_skip_count_transfer++;
1735 uint32_t factor = (config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28;
1736 if(frame_skip_count_transfer > factor) {
1737 frame_skip_count_transfer = 0;
1738 need_transfer_line = true;
1740 need_transfer_line = false;
1742 //vram_wrote = false;
1750 void DISPLAY::event_vline(int v, int clock)
1752 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1754 if(need_transfer_line == false) return;
1757 // Not transfer, will transfer at event_frame.
1758 copy_vram_per_line(0, 4);
1762 for(int iii = 0; iii < 5 ; iii++) {
1763 if(vram_wrote_table[displine * 5 + iii]) {
1764 if(begin < 0) begin = iii;
1768 if(end < begin) end = begin;
1769 copy_vram_per_line(begin, end);
1777 copy_vram_per_line(begin, end);
1785 uint32_t DISPLAY::read_signal(int id)
1787 uint32_t retval = 0;
1789 case SIG_FM7_SUB_HALT:
1790 case SIG_DISPLAY_HALT:
1791 retval = (halt_flag) ? 0xffffffff : 0;
1793 case SIG_DISPLAY_BUSY:
1794 retval = (sub_busy) ? 0x80 : 0;
1796 case SIG_DISPLAY_MULTIPAGE:
1797 retval = multimode_accessmask;
1799 case SIG_DISPLAY_PLANES:
1802 #if defined(_FM77AV_VARIANTS)
1803 case SIG_DISPLAY_VSYNC:
1804 retval = (vsync) ? 0x01 : 0x00;
1806 case SIG_DISPLAY_DISPLAY:
1807 retval = (!hblank) ? 0x02: 0x00;
1809 case SIG_FM7_SUB_BANK: // Main: FD13
1810 retval = subrom_bank & 0x03;
1811 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1812 if(monitor_ram) retval |= 0x04;
1816 #if defined(_FM77AV_VARIANTS)
1817 case SIG_DISPLAY_MODE320:
1818 retval = (mode320) ? 0x40: 0x00;
1821 case SIG_DISPLAY_Y_HEIGHT:
1822 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77L4)
1823 retval = ((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) ? 400 : 200;
1828 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1830 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1831 retval |= (kanjisub) ? 0x00 : 0x20;
1832 retval |= (mode256k) ? 0x10 : 0x00;
1833 retval |= (mode400line) ? 0x00 : 0x08;
1834 retval |= (ram_protect) ? 0x00 : 0x04;
1835 #elif defined(_FM77_VARIANTS)
1837 retval |= (kanjisub) ? 0x00 : 0x20;
1838 # if defined(_FM77L4)
1839 retval |= (stat_400linecard) ? 0x00 : 0x08;
1847 case SIG_DISPLAY_X_WIDTH:
1848 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1849 retval = (mode320 || mode256k) ? 320 : 640;
1850 #elif defined(_FM77AV_VARIANTS)
1851 retval = (mode320) ? 320 : 640;
1862 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
1864 bool flag = ((data & mask) != 0);
1868 case SIG_FM7_SUB_HALT:
1873 //call_write_signal(mainio, SIG_FM7_SUB_HALT, data, mask);
1875 case SIG_DISPLAY_HALT:
1879 restart_subsystem();
1882 case SIG_FM7_SUB_CANCEL:
1884 cancel_request = true;
1888 case SIG_DISPLAY_CLOCK:
1892 #if defined(_FM77AV_VARIANTS)
1893 case SIG_FM7_SUB_BANK: // Main: FD13
1894 set_monitor_bank(data & 0xff);
1897 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1898 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1899 //printf("Wrote $FD04: %02x\n", data);
1901 int oldmode = display_mode;
1903 kanjisub = ((data & 0x20) == 0) ? true : false;
1904 mode256k = (((data & 0x10) != 0) && ((data & 0x08) != 0) ) ? true : false;
1905 mode400line = ((data & 0x08) == 0) ? true : false;
1906 ram_protect = ((data & 0x04) == 0) ? true : false;
1907 if((mode400line) && !(mode320)) {
1908 display_mode = DISPLAY_MODE_8_400L;
1909 } else if(mode256k) {
1910 display_mode = DISPLAY_MODE_256k;
1912 display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1914 if(oldmode != display_mode) {
1916 if(mode320 || mode256k) {
1917 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
1918 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1919 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1920 for(y = 0; y < 200; y++) {
1921 pp = emu->get_screen_buffer(y);
1922 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1925 for(y = 0; y < 400; y++) {
1926 pp = emu->get_screen_buffer(y);
1927 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1930 //emu->set_vm_screen_lines(200);
1931 } else if(display_mode == DISPLAY_MODE_8_400L) {
1932 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1933 if(oldmode != DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(55.40);
1934 for(y = 0; y < 400; y++) {
1935 pp = emu->get_screen_buffer(y);
1936 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1939 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
1940 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1941 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1942 for(y = 0; y < 200; y++) {
1943 pp = emu->get_screen_buffer(y);
1944 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
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 //emu->set_vm_screen_lines(200);
1955 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
1956 call_write_signal(alu, SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200, 0xffff);
1957 call_write_signal(alu, SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xff : 0x00, 0xff);
1958 frame_skip_count_draw = 3;
1959 frame_skip_count_transfer = 3;
1960 setup_display_mode();
1963 #elif defined(_FM77_VARIANTS)
1965 int oldmode = display_mode;
1966 kanjisub = ((data & 0x20) == 0) ? true : false;
1967 # if defined(_FM77L4)
1968 stat_400linecard = ((data & 0x08) != 0) ? false : true;
1969 if(mode400line && stat_400linecard) {
1971 uint8_t *regs = l4crtc->get_regs();
1972 display_mode = DISPLAY_MODE_1_400L;
1973 if(event_id_l4_cursor_blink >= 0) {
1974 cancel_event(this, event_id_l4_cursor_blink);
1976 if(event_id_l4_text_blink >= 0) {
1977 cancel_event(this, event_id_l4_text_blink);
1979 event_id_l4_cursor_blink = -1;
1980 event_id_l4_text_blink = -1;
1982 usec = ((regs[10] & 0x20) == 0) ? 160.0 : 320.0;
1983 usec = usec * 1000.0;
1984 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
1985 usec = 160.0 * 1000.0;
1986 register_event(this, EVENT_FM7SUB_TEXT_BLINK, true, usec, &event_id_l4_cursor_blink);
1989 display_mode = DISPLAY_MODE_8_200L;
1991 if(oldmode != display_mode) {
1993 if(display_mode == DISPLAY_MODE_1_400L) {
1994 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1995 for(int y = 0; y < 400; y++) {
1996 pp = emu->get_screen_buffer(y);
1997 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2001 vm->set_vm_frame_rate(FRAMES_PER_SEC);
2002 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2003 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2004 for(int y = 0; y < 200; y++) {
2005 pp = emu->get_screen_buffer(y);
2006 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2009 for(int y = 0; y < 400; y++) {
2010 pp = emu->get_screen_buffer(y);
2011 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2016 setup_display_mode();
2023 #if defined(_FM77AV_VARIANTS)
2024 case SIG_DISPLAY_MODE320: // FD12 bit 6
2025 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2027 //printf("Wrote $FD12: %02x\n", data);
2028 int oldmode = display_mode;
2031 display_mode = DISPLAY_MODE_8_400L;
2032 } else if(mode256k) {
2033 display_mode = DISPLAY_MODE_256k;
2034 } else if(!(mode320) && !(mode256k)) {
2035 //display_mode = (mode400line) ? DISPLAY_MODE_8_400L : DISPLAY_MODE_8_200L;
2036 display_mode = DISPLAY_MODE_8_200L;
2038 display_mode = (mode256k) ? DISPLAY_MODE_256k : DISPLAY_MODE_4096;
2040 if(oldmode != display_mode) {
2042 if(mode320 || mode256k) {
2043 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
2044 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2045 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2046 for(y = 0; y < 200; y++) {
2047 pp = emu->get_screen_buffer(y);
2048 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
2051 for(y = 0; y < 400; y++) {
2052 pp = emu->get_screen_buffer(y);
2053 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2056 //emu->set_vm_screen_lines(200);
2057 } else { // 200 lines, 8 colors.
2058 if(display_mode == DISPLAY_MODE_8_400L) {
2059 if(oldmode != DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(55.40);
2061 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
2063 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2064 int ymax = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
2066 emu->set_vm_screen_size(640, ymax, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2067 for(y = 0; y < ymax; y++) {
2068 pp = emu->get_screen_buffer(y);
2069 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2072 for(y = 0; y < 400; y++) {
2073 pp = emu->get_screen_buffer(y);
2074 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2077 //emu->set_vm_screen_lines(200);
2080 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
2081 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
2082 call_write_signal(alu, SIG_ALU_400LINE, 0x00, 0xff);
2083 setup_display_mode();
2084 //frame_skip_count = 3;
2087 # else /* FM77AV/20/20EX */
2090 if(oldflag != mode320) {
2093 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2094 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2095 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 320 * sizeof(scrntype_t));
2097 for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2099 //emu->set_vm_screen_lines(200);
2101 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2102 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2103 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2105 for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2107 //emu->set_vm_screen_lines(200);
2110 display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
2111 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
2112 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
2113 call_write_signal(alu, SIG_ALU_400LINE, 0, 0xffffffff);
2115 setup_display_mode();
2120 case SIG_DISPLAY_MULTIPAGE:
2121 set_multimode(data);
2123 case SIG_FM7_SUB_KEY_MASK:
2124 if(firq_mask == flag) {
2125 do_firq(!flag && key_firq_req);
2129 case SIG_FM7_SUB_KEY_FIRQ:
2130 do_firq(flag & !(firq_mask));
2131 key_firq_req = flag;
2139 * Vram accessing functions moved to vram.cpp .
2142 uint32_t DISPLAY::read_mmio(uint32_t addr)
2144 uint32_t retval = 0xff;
2146 if(addr < 0xd400) return 0xff;
2148 #if !defined(_FM77AV_VARIANTS)
2149 raddr = (addr - 0xd400) & 0x000f;
2150 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2151 raddr = (addr - 0xd400) & 0x003f;
2152 #else // FM77AV40EX || FM77AV40SX
2153 raddr = (addr - 0xd400) & 0x00ff;
2156 case 0x00: // Read keyboard
2157 retval = (call_read_data8(keyboard, 0x00) != 0) ? 0xff : 0x7f;
2159 case 0x01: // Read keyboard
2160 retval = call_read_data8(keyboard, 0x01) & 0xff;
2162 case 0x02: // Acknowledge
2171 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2172 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2174 if(!kanjisub) return 0xff;
2175 # if !defined(_FM77_VARIANTS)
2177 return (uint8_t)call_read_data8(kanjiclass2, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
2180 if(kanjiclass1 != NULL) retval = call_read_data8(kanjiclass1, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
2183 if(!kanjisub) return 0xff;
2184 # if !defined(_FM77_VARIANTS)
2186 return (uint8_t)call_read_data8(kanjiclass2, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
2189 if(kanjiclass1 != NULL) retval = call_read_data8(kanjiclass1, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
2196 retval = set_vramaccess();
2199 { // If use CLR insn to set busy flag, clear flag at first, then delay and set flag.
2201 // Delay at least 3+ clocks (CLR <$0A )
2204 usec = (4000.0 * 1000.0) / 2000000.0;
2206 usec = (4000.0 * 1000.0) / 999000.0;
2208 register_event(this, EVENT_FM7SUB_CLEAR_DELAY, usec, false, NULL); // NEXT CYCLE_
2212 #if defined(_FM77L4)
2214 if(stat_400linecard) {
2215 retval = l4crtc->read_io8(0);
2219 if(stat_400linecard) {
2220 retval = l4crtc->read_io8(1);
2221 // Update parameters.
2226 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
2228 #if defined(_FM77AV_VARIANTS)
2231 retval = call_read_data8(alu, ALU_CMDREG);
2234 retval = call_read_data8(alu, ALU_LOGICAL_COLOR);
2237 retval = call_read_data8(alu, ALU_WRITE_MASKREG);
2240 retval = call_read_data8(alu, ALU_CMP_STATUS_REG);
2243 retval = call_read_data8(alu, ALU_BANK_DISABLE);
2245 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2246 case 0x2f: // VRAM BANK
2247 retval = 0xfc | (vram_bank & 0x03);
2252 retval = get_miscreg();
2256 retval = call_read_data8(keyboard, 0x31);
2259 retval = call_read_data8(keyboard, 0x32);
2265 return (uint8_t)retval;
2268 uint32_t DISPLAY::read_vram_data8(uint32_t addr)
2272 uint32_t color = (addr >> 14) & 0x03;
2273 #if defined(_FM77L4)
2276 offset = offset_point;
2278 if(multimode_accessflags[2]) return 0xff;
2279 vramaddr = ((addr + offset) & 0x3fff) + 0x8000;
2280 return gvram[vramaddr];
2284 return text_vram[addr & 0x0fff];
2285 } else if(addr < 0xc000) {
2286 return subsys_l4[addr - 0x9800];
2292 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2293 if(display_mode == DISPLAY_MODE_8_400L) {
2294 color = vram_bank & 0x03;
2295 if(color > 2) color = 0;
2297 color = (addr >> 14) & 0x03;
2301 //if((multimode_accessmask & (1 << color)) != 0) return 0xff;
2302 if(multimode_accessflags[color]) return 0xff;
2304 #if defined(_FM77AV_VARIANTS)
2305 if (active_page != 0) {
2306 offset = offset_point_bank1;
2308 offset = offset_point;
2311 offset = offset_point;
2313 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2314 if(vram_active_block != 0) {
2315 if(display_mode != DISPLAY_MODE_256k) offset = 0; // Don't scroll at BLOCK 1.
2318 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2319 if(display_mode == DISPLAY_MODE_8_400L) {
2321 uint32_t page_offset_alt = 0;
2322 if(addr >= 0x8000) return 0xff;
2323 color = vram_bank & 0x03;
2324 if(color > 2) color = 0;
2326 pagemod = 0x8000 * color;
2327 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2328 if(vram_active_block != 0) page_offset = 0x18000;
2330 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2331 return gvram[vramaddr];
2334 uint32_t page_offset_alt;
2335 #if defined(_FM77AV40)
2337 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2339 page_offset_alt = 0; // right?
2342 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2344 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
2345 //page_mask = 0x1fff;
2346 //pagemod = addr & 0xe000;
2348 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2350 return gvram[vramaddr];
2352 #elif defined(_FM77AV_VARIANTS)
2354 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2355 return gvram[vramaddr];
2357 #elif defined(_FM77L4) //_FM77L4
2360 vramaddr = (addr + offset) & 0x7fff;
2361 return gvram[vramaddr];
2363 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2364 return gvram[vramaddr];
2368 #else // Others (77/7/8)
2369 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2370 return gvram[vramaddr];
2374 void DISPLAY::write_dma_data8(uint32_t addr, uint32_t data)
2376 uint32_t raddr = (addr & 0xffff) >> 7;
2377 if(write_dma_func_table[raddr] != NULL) {
2378 (this->*write_dma_func_table[raddr])(addr, (uint8_t) data);
2382 void DISPLAY::write_vram_data8(uint32_t addr, uint8_t data)
2385 uint32_t color = (addr >> 14) & 0x03;
2389 #if defined(_FM77AV_VARIANTS)
2390 if (active_page != 0) {
2391 offset = offset_point_bank1;
2393 offset = offset_point;
2396 offset = offset_point;
2398 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2399 if(vram_active_block != 0) offset = 0; // Don't scroll at BLOCK 1.
2402 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2403 if(display_mode == DISPLAY_MODE_8_400L) {
2405 uint32_t page_offset_alt = 0;
2407 if(addr >= 0x8000) {
2410 color = vram_bank & 0x03;
2411 if(color > 2) color = 0;
2413 pagemod = 0x8000 * color;
2414 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2415 if(vram_active_block != 0) page_offset_alt = 0x18000;
2417 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2418 // Reduce data transfer.
2419 tdata = gvram[vramaddr];
2421 naddr = (addr & 0x7fff) >> 4;
2422 gvram[vramaddr] = data;
2423 vram_wrote_table[naddr] = true;
2425 } else if(display_mode == DISPLAY_MODE_256k) {
2426 uint32_t page_offset_alt;
2428 #if defined(_FM77AV40)
2430 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2432 page_offset_alt = 0; // right?
2435 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2437 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
2438 tdata = gvram[vramaddr];
2440 naddr = (addr & page_mask) >> 3;
2441 gvram[vramaddr] = data;
2442 vram_wrote_table[naddr] = true;
2445 } else if(display_mode == DISPLAY_MODE_4096) {
2447 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2448 tdata = gvram[vramaddr];
2450 naddr = (addr & page_mask) >> 3;
2451 gvram[vramaddr] = data;
2452 vram_wrote_table[naddr] = true;
2456 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2457 tdata = gvram[vramaddr];
2459 naddr = (addr & page_mask) >> 4;
2460 gvram[vramaddr] = data;
2461 vram_wrote_table[naddr] = true;
2464 #elif defined(_FM77AV_VARIANTS)
2465 if(display_mode == DISPLAY_MODE_4096) {
2467 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2468 tdata = gvram[vramaddr];
2470 naddr = (addr & page_mask) >> 3;
2471 gvram[vramaddr] = data;
2472 vram_wrote_table[naddr] = true;
2476 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2477 tdata = gvram[vramaddr];
2479 naddr = (addr & page_mask) >> 4;
2480 gvram[vramaddr] = data;
2481 vram_wrote_table[naddr] = true;
2484 #elif defined(_FM77L4) //_FM77L4
2485 if(display_mode == DISPLAY_MODE_1_400L) {
2488 //if(multimode_accessflags[2]) return;
2489 vramaddr = ((addr + offset) & 0x3fff) + 0x8000;
2490 gvram[vramaddr] = data;
2493 vramaddr = (addr + offset) & 0x7fff;
2494 tdata = gvram[vramaddr];
2496 naddr = (addr & 0x7fff) >> 4;
2497 gvram[vramaddr] = data;
2498 vram_wrote_table[naddr] = true;
2505 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2506 tdata = gvram[vramaddr];
2508 naddr = (addr & 0x3fff) >> 4;
2509 gvram[vramaddr] = data;
2510 vram_wrote_table[naddr] = true;
2513 #else // Others (77/7/8)
2516 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2517 tdata = gvram[vramaddr];
2519 naddr = (addr & 0x3fff) >> 4;
2520 gvram[vramaddr] = data;
2521 vram_wrote_table[naddr] = true;
2527 uint32_t DISPLAY::read_cpu_vram_data8(uint32_t addr)
2530 #if defined(_FM77AV_VARIANTS)
2532 call_read_data8(alu, addr);
2535 return read_vram_data8(addr);
2538 uint32_t DISPLAY::read_dma_vram_data8(uint32_t addr)
2540 return read_vram_data8(addr);
2543 void DISPLAY::init_read_table(void)
2546 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
2547 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cpu_vram_data8;
2548 read_dma_func_table[_at >> 7] = &DISPLAY::read_dma_vram_data8;
2550 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
2551 read_cpu_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2552 read_dma_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2554 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
2555 read_cpu_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2556 read_dma_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2558 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
2559 read_cpu_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2560 read_dma_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2562 #if defined(_FM77AV_VARIANTS)
2563 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
2564 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2565 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2567 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
2568 read_cpu_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2569 read_dma_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2572 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
2573 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2574 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2577 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
2578 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2579 read_dma_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2581 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
2582 read_cpu_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2583 read_dma_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2587 uint32_t DISPLAY::read_console_ram(uint32_t addr)
2589 uint32_t raddr = addr & 0xfff;
2590 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2592 if(console_ram_bank >= 1) {
2593 return submem_console_av40[((console_ram_bank - 1) << 12) + raddr];
2597 return console_ram[raddr];
2600 uint32_t DISPLAY::read_work_ram(uint32_t addr)
2602 addr = addr & 0x3ff;
2603 return work_ram[addr];
2607 uint32_t DISPLAY::read_shared_ram(uint32_t addr)
2609 addr = addr - 0xd380;
2610 return shared_ram[addr];
2613 #if defined(_FM77AV_VARIANTS)
2614 uint32_t DISPLAY::read_hidden_ram(uint32_t addr)
2616 if(addr >= 0xd500) {
2617 return submem_hidden[addr - 0xd500];
2623 uint32_t DISPLAY::read_cgrom(uint32_t addr)
2625 #if defined(_FM77AV_VARIANTS)
2626 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2628 return submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)]; //FIXME
2631 return subsys_cg[(addr - 0xd800) + cgrom_bank * 0x800];
2633 return subsys_c[addr - 0xd800];
2637 uint32_t DISPLAY::read_subsys_monitor(uint32_t addr)
2639 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2641 return subsys_ram[addr - 0xe000];
2644 #if defined(_FM77AV_VARIANTS)
2645 switch(subrom_bank_using & 3) {
2647 return subsys_c[addr - 0xd800];
2650 return subsys_a[addr - 0xe000];
2653 return subsys_b[addr - 0xe000];
2656 return subsys_cg[addr - 0xe000];
2659 #elif defined(_FM77L4)
2661 return subsys_l4[addr - 0xb800];
2663 return subsys_c[addr - 0xd800];
2665 return subsys_c[addr - 0xd800];
2669 uint32_t DISPLAY::read_dma_data8(uint32_t addr)
2671 uint32_t raddr = (addr & 0xffff) >> 7;
2672 if(read_dma_func_table[raddr] != NULL) {
2673 return (this->*read_dma_func_table[raddr])(addr);
2678 uint32_t DISPLAY::read_data8(uint32_t addr)
2680 uint32_t raddr = addr;
2682 if(addr < 0x10000) {
2683 raddr = (addr & 0xffff) >> 7;
2684 if(read_cpu_func_table[raddr] != NULL) {
2685 return (this->*read_cpu_func_table[raddr])(addr);
2690 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2691 return dpalette_data[addr - FM7_SUBMEM_OFFSET_DPALETTE];
2694 #if defined(_FM77AV_VARIANTS)
2696 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2697 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2698 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2699 if(vram_active_block != 0) {
2703 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2704 if(display_mode == DISPLAY_MODE_8_400L) {
2705 uint32_t page_offset_alt = 0;
2708 color = (addr & 0x18000) >> 15;
2709 if(color > 2) color = 0;
2710 pagemod = 0x8000 * color;
2711 if (active_page != 0) {
2712 offset = offset_point_bank1 << 1;
2714 offset = offset_point << 1;
2716 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2717 if(vram_active_block != 0) {
2718 page_offset_alt = 0x18000;
2722 return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset_alt];
2725 return read_vram_data8(addr);
2732 * Vram accessing functions moved to vram.cpp .
2735 void DISPLAY::write_mmio(uint32_t addr, uint8_t data)
2738 uint8_t active_block_old;
2740 if(addr < 0xd400) return;
2742 #if !defined(_FM77AV_VARIANTS)
2743 addr = (addr - 0xd400) & 0x000f;
2744 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2745 addr = (addr - 0xd400) & 0x003f;
2746 #else // FM77AV40EX || FM77AV40SX
2747 addr = (addr - 0xd400) & 0x00ff;
2749 io_w_latch[addr] = (uint8_t)data;
2751 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4)
2754 set_cyclesteal((uint8_t)data);
2755 # if defined(_FM77L4)
2756 setup_400linemode((uint8_t)data);
2760 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2761 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2764 if(!kanjisub) return;
2765 kanjiaddr.w.h = 0x0000;
2766 kanjiaddr.b.h = (uint8_t) data;
2769 if(!kanjisub) return;
2770 kanjiaddr.w.h = 0x0000;
2771 kanjiaddr.b.l = (uint8_t)data;
2784 if(delay_busy) { // If WRITE after READ immediately.Perhaps use CLR insn.
2786 // Delay at least 5+ clocks (CLR $D40A or CLR (INDEX = $D40A))
2788 usec = (6000.0 * 1000.0) / 2000000.0;
2790 usec = (6000.0 * 1000.0) / 999000.0;
2792 register_event(this, EVENT_FM7SUB_DELAY_BUSY, usec, false, NULL); // NEXT CYCLE_
2800 #if defined(_FM77L4)
2802 if(stat_400linecard) {
2803 l4crtc->write_io8(0, data & 0x1f);
2807 if(stat_400linecard) {
2808 l4crtc->write_io8(1, data);
2809 // Update parameters.
2810 uint8_t crtc_addr = l4crtc->read_io8(0);
2811 const uint8_t *regs = l4crtc->get_regs();
2812 switch(crtc_addr & 0x1f) {
2815 cursor_addr.w.l &= 0x0ffc;
2816 cursor_addr.w.l |= (((uint16_t)regs[14]) << 10);
2817 cursor_addr.w.l |= (((uint16_t)regs[15]) << 2);
2819 cursor_addr.w.l += 2;
2821 cursor_addr.w.l &= 0xfff;
2823 if((crtc_addr & 0x1f) == 10) {
2825 if(event_id_l4_cursor_blink >= 0) {
2826 cancel_event(this, event_id_l4_cursor_blink);
2828 usec = ((data & 0x20) == 0) ? 160.0 : 320.0;
2829 usec = usec * 1000.0;
2830 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
2834 text_start_addr.w.l &= 0x03fc;
2835 text_start_addr.w.l |= (((uint16_t)data & 3) << 10);
2836 text_scroll_count++;
2837 if((text_scroll_count & 1) == 0) {
2842 text_start_addr.w.l &= 0xfc00;
2843 text_start_addr.w.l |= ((uint16_t)data << 2);
2844 text_scroll_count++;
2845 if((text_scroll_count & 1) == 0) {
2850 text_scroll_count++;
2851 if((text_scroll_count & 1) == 0) {
2853 cursor_addr.w.l &= 0x0ffc;
2854 cursor_addr.w.l |= (((uint16_t)regs[14]) << 10);
2855 cursor_addr.w.l |= (((uint16_t)regs[15]) << 2);
2857 cursor_addr.w.l += 2;
2859 cursor_addr.w.l &= 0xfff;
2870 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
2875 rval = (uint8_t)data;
2876 if(offset_changed[active_page]) {
2877 #if defined(_FM77AV_VARIANTS)
2878 if(active_page != 0) {
2879 tmp_offset_point[active_page].d = offset_point_bank1;
2881 tmp_offset_point[active_page].d = offset_point;
2884 tmp_offset_point[active_page].d = offset_point;
2887 tmp_offset_point[active_page].w.h = 0x0000;
2889 tmp_offset_point[active_page].b.h = rval;
2891 tmp_offset_point[active_page].b.l = rval;
2893 offset_changed[active_page] = !offset_changed[active_page];
2894 if(offset_changed[active_page]) {
2896 #if defined(_FM77AV_VARIANTS)
2897 if(active_page != 0) {
2899 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fff;
2901 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fe0;
2905 offset_point = tmp_offset_point[active_page].d & 0x007fff;
2907 offset_point = tmp_offset_point[active_page].d & 0x007fe0;
2911 offset_point = tmp_offset_point[active_page].d & 0x7fe0;
2915 #if defined(_FM77AV_VARIANTS)
2918 alu_write_cmdreg(data);
2921 alu_write_logical_color(data);
2924 alu_write_mask_reg(data);
2927 alu_write_disable_reg(data);
2930 alu_write_offsetreg_hi(data);
2933 alu_write_offsetreg_lo(data);
2936 alu_write_linepattern_hi(data);
2939 alu_write_linepattern_lo(data);
2941 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2943 console_ram_bank = (data & 0x18) >> 3;
2944 if(console_ram_bank > 2) console_ram_bank = 0;
2945 cgram_bank = data & 0x07;
2946 kanji_level2 = ((data & 0x80) == 0) ? false : true;
2948 case 0x2f: // VRAM BANK
2949 vram_bank = data & 0x03;
2950 if(vram_bank > 2) vram_bank = 0;
2960 call_write_data8(keyboard, 0x31, data);
2962 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2964 active_block_old = vram_active_block;
2965 vram_active_block = data & 0x01;
2966 if(vram_display_block != (((data & 0x10) != 0) ? 1 : 0)) vram_wrote = true;
2967 vram_display_block = ((data & 0x10) != 0) ? 1 : 0;
2968 if(vram_active_block != active_block_old) setup_display_mode();
2973 tmpvar.d = window_xbegin * 8;
2976 tmpvar.b.h = data & 0x03;
2978 tmpvar.b.l = data & 0xf8;
2980 if(mode320 || mode256k) {
2981 if(tmpvar.d > 320) tmpvar.d = 320;
2983 if(tmpvar.d > 640) tmpvar.d = 640;
2985 window_xbegin = tmpvar.d / 8;
2990 tmpvar.d = window_xend * 8;
2993 tmpvar.b.h = data & 0x03;
2995 tmpvar.b.l = data & 0xf8;
2997 if(mode320 || mode256k) {
2998 if(tmpvar.d > 320) tmpvar.d = 320;
3000 if(tmpvar.d > 640) tmpvar.d = 640;
3002 window_xend = tmpvar.d / 8;
3007 tmpvar.d = window_low;
3010 tmpvar.b.h = data & 0x03;
3012 tmpvar.b.l = data & 0xff;
3014 if(display_mode == DISPLAY_MODE_8_400L) {
3015 if(tmpvar.d > 400) tmpvar.d = 400;
3018 if(tmpvar.d > 400) tmpvar.d = 400;
3020 window_low = tmpvar.d;
3025 tmpvar.d = window_high;
3028 tmpvar.b.h = data & 0x03;
3030 tmpvar.b.l = data & 0xff;
3032 if(display_mode == DISPLAY_MODE_8_400L) {
3033 if(tmpvar.d > 400) tmpvar.d = 400;
3036 if(tmpvar.d > 400) tmpvar.d = 400;
3038 window_high = tmpvar.d;
3044 #if defined(_FM77AV_VARIANTS)
3046 if((addr >= 0x13) && (addr <= 0x1a)) {
3047 alu_write_cmpdata_reg(addr - 0x13, data);
3048 } else if((addr >= 0x1c) && (addr <= 0x1e)) {
3049 alu_write_tilepaint_data(addr, data);
3050 } else if((addr >= 0x24) && (addr <= 0x2b)) {
3051 alu_write_line_position(addr - 0x24, data);
3058 void DISPLAY::init_write_table(void)
3061 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
3062 write_cpu_func_table[_at >> 7] = &DISPLAY::write_cpu_vram_data8;
3063 write_dma_func_table[_at >> 7] = &DISPLAY::write_dma_vram_data8;
3065 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
3066 write_cpu_func_table[_at >> 7] = &DISPLAY::write_console_ram;
3067 write_dma_func_table[_at >> 7] = &DISPLAY::write_console_ram;
3069 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
3070 write_cpu_func_table[_at >> 7] = &DISPLAY::write_work_ram;
3071 write_dma_func_table[_at >> 7] = &DISPLAY::write_work_ram;
3073 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
3074 write_cpu_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
3075 write_dma_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
3077 #if defined(_FM77AV_VARIANTS)
3078 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
3079 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
3080 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
3082 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
3083 write_cpu_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
3084 write_dma_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
3087 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
3088 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
3089 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
3092 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
3093 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
3094 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
3095 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
3097 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
3098 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
3099 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
3102 for(_at = 0xd800; _at < 0x10000; _at += 0x80) {
3103 write_cpu_func_table[_at >> 7] = &DISPLAY::write_dummy;
3104 write_dma_func_table[_at >> 7] = &DISPLAY::write_dummy;
3109 void DISPLAY::write_console_ram(uint32_t addr, uint8_t data)
3111 uint32_t raddr = addr & 0xfff;
3112 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3114 if(console_ram_bank >= 1) {
3115 submem_console_av40[((console_ram_bank - 1) << 12) + raddr] = data;
3120 console_ram[raddr] = data;
3124 void DISPLAY::write_work_ram(uint32_t addr, uint8_t data)
3126 uint32_t raddr = addr & 0xfff;
3127 work_ram[raddr] = data;
3131 void DISPLAY::write_shared_ram(uint32_t addr, uint8_t data)
3133 uint32_t raddr = addr & 0x7f;
3134 shared_ram[raddr] = data;
3138 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
3139 void DISPLAY::write_subsys_cgram(uint32_t addr, uint8_t data)
3141 uint32_t raddr = addr - 0xd800;
3142 if(ram_protect) return;
3143 if(!monitor_ram) return;
3144 submem_cgram[cgram_bank * 0x0800 + raddr] = data; //FIXME
3147 void DISPLAY::write_subsys_ram(uint32_t addr, uint8_t data)
3149 if(ram_protect) return;
3150 if(!monitor_ram) return;
3151 subsys_ram[addr - 0xe000] = data; //FIXME
3155 #if defined(_FM77AV_VARIANTS)
3156 void DISPLAY::write_hidden_ram(uint32_t addr, uint8_t data)
3158 submem_hidden[addr - 0xd500] = data;
3163 void DISPLAY::write_cpu_vram_data8(uint32_t addr, uint8_t data)
3165 uint32_t color = (addr & 0xc000) >> 14;
3166 #if defined(_FM77AV_VARIANTS)
3168 call_read_data8(alu, addr);
3172 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3173 if(display_mode == DISPLAY_MODE_8_400L) {
3174 color = vram_bank & 0x03;
3175 if(color > 2) color = 0;
3178 #if defined(_FM77L4)
3182 if(!(multimode_accessflags[2])) write_vram_data8(addr & 0x7fff, data);
3185 } else if(addr < 0x9800) {
3188 addr = addr & 0x0fff;
3189 if(text_vram[addr] != data) {
3190 text_vram[addr] = data;
3192 x = ((addr / 2) % 40) / 8;
3193 y = (addr / 2) / 40;
3194 } else { // Width 80
3195 x = ((addr / 2) % 80) / 8;
3196 y = (addr / 2) / 80;
3198 for(int yy = 0; yy < 8; yy++) {
3199 naddr = (y + yy) * 5 + x;
3200 vram_wrote_table[naddr] = true;
3210 //if((multimode_accessmask & (1 << color)) != 0) return;
3211 if(multimode_accessflags[color]) return;
3213 write_vram_data8(addr & 0xffff, data);
3216 void DISPLAY::write_dma_vram_data8(uint32_t addr, uint8_t data)
3218 uint32_t color = (addr & 0xc000) >> 14;
3219 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3220 if(display_mode == DISPLAY_MODE_8_400L) {
3221 color = vram_bank & 0x03;
3222 if(color > 2) color = 0;
3226 //if((multimode_accessmask & (1 << color)) != 0) return;
3227 if(multimode_accessflags[color]) return;
3229 write_vram_data8(addr & 0xffff, data);
3232 void DISPLAY::write_dummy(uint32_t addr, uint8_t data)
3236 void DISPLAY::write_data8(uint32_t addr, uint32_t data)
3240 //uint32_t page_offset = 0x0000;
3241 uint8_t val8 = data & 0xff;
3242 uint32_t color = (addr & 0xc000) >> 14;
3245 if(addr < 0x10000) {
3246 void (*_write_func)(uint32_t, uint32_t);
3247 raddr = (addr & 0xffff) >> 7;
3248 if(write_cpu_func_table[raddr] != NULL) {
3249 (this->*write_cpu_func_table[raddr])(addr, (uint8_t)data);
3255 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
3256 set_dpalette(addr - FM7_SUBMEM_OFFSET_DPALETTE, val8);
3260 #if defined(_FM77AV_VARIANTS)
3262 else if(addr == FM7_SUBMEM_OFFSET_APALETTE_R) {
3263 set_apalette_r(val8);
3265 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_G) {
3266 set_apalette_g(val8);
3268 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_B) {
3269 set_apalette_b(val8);
3271 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_HI) {
3272 set_apalette_index_hi(val8);
3274 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_LO) {
3275 set_apalette_index_lo(val8);
3279 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
3280 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
3281 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3282 if(display_mode == DISPLAY_MODE_8_400L) {
3285 uint32_t page_offset_alt = 0;
3287 color = (addr & 0x18000) >> 15;
3288 if(color > 2) color = 0;
3289 if (active_page != 0) {
3290 offset = offset_point_bank1 << 1;
3292 offset = offset_point << 1;
3294 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3295 if(vram_active_block != 0) {
3296 page_offset_alt = 0x18000;
3300 naddr = (addr & 0x7fff) >> 4;
3301 pagemod = 0x8000 * color;
3302 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
3303 tdata = gvram[vramaddr];
3304 if(tdata != (uint8_t)data) {
3305 gvram[vramaddr] = data;
3306 vram_wrote_table[naddr] = true;
3310 write_vram_data8(addr, data);
3312 write_vram_data8(addr, data);
3314 //if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
3321 uint32_t DISPLAY::read_bios(const _TCHAR *name, uint8_t *ptr, uint32_t size)
3327 if((name == NULL) || (ptr == NULL)) return 0;
3328 s = create_local_path(name);
3329 if(s == NULL) return 0;
3331 if(!fio.Fopen(s, FILEIO_READ_BINARY)) return 0;
3332 blocks = fio.Fread(ptr, size, 1);
3335 return blocks * size;
3339 void DISPLAY::initialize()
3344 PrepareBitTransTableUint16((_bit_trans_table_t*)(&(bit_trans_table_0[0][0])), 0x0080, 0x0000);
3345 PrepareBitTransTableUint16((_bit_trans_table_t*)(&(bit_trans_table_1[0][0])), 0x0040, 0x0000);
3346 PrepareBitTransTableUint16((_bit_trans_table_t*)(&(bit_trans_table_2[0][0])), 0x0020, 0x0000);
3347 PrepareBitTransTableUint16((_bit_trans_table_t*)(&(bit_trans_table_3[0][0])), 0x0010, 0x0000);
3348 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3349 PrepareBitTransTableUint16((_bit_trans_table_t*)(&(bit_trans_table_4[0][0])), 0x0008, 0x0000);
3350 PrepareBitTransTableUint16((_bit_trans_table_t*)(&(bit_trans_table_5[0][0])), 0x0004, 0x0000);
3353 for(int i = 0; i < 256; i++) {
3354 uint16_t n = (uint16_t)i;
3355 for(int j = 0; j < 8; j++) {
3356 bit_trans_table_0[i][j] = n & 0x80;
3357 bit_trans_table_1[i][j] = ((n & 0x80) != 0) ? 0x40 : 0;
3358 bit_trans_table_2[i][j] = ((n & 0x80) != 0) ? 0x20 : 0;
3359 bit_trans_table_3[i][j] = ((n & 0x80) != 0) ? 0x10 : 0;
3360 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3361 bit_trans_table_4[i][j] = ((n & 0x80) != 0) ? 0x08 : 0;
3362 bit_trans_table_5[i][j] = ((n & 0x80) != 0) ? 0x04 : 0;
3368 memset(io_w_latch, 0xff, sizeof(io_w_latch));
3369 screen_update_flag = true;
3370 memset(gvram, 0x00, sizeof(gvram));
3371 vram_wrote_shadow = false;
3372 memset(gvram_shadow, 0x00, sizeof(gvram_shadow));
3373 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
3374 for(i = 0; i < 411; i++) vram_draw_table[i] = false;
3375 force_update = false;
3377 memset(console_ram, 0x00, sizeof(console_ram));
3378 memset(work_ram, 0x00, sizeof(work_ram));
3379 memset(shared_ram, 0x00, sizeof(shared_ram));
3380 memset(subsys_c, 0xff, sizeof(subsys_c));
3381 need_transfer_line = true;
3382 frame_skip_count_draw = 3;
3383 frame_skip_count_transfer = 3;
3385 diag_load_subrom_c = false;
3387 if(read_bios(_T(ROM_FM8_SUBSYSTEM), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
3388 this->out_debug_log(_T("SUBSYSTEM ROM READING : %s"), diag_load_subrom_c ? "OK" : "NG");
3390 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_C), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
3391 this->out_debug_log(_T("SUBSYSTEM ROM Type C READING : %s"), diag_load_subrom_c ? "OK" : "NG");
3393 #if defined(_FM77AV_VARIANTS)
3394 memset(subsys_a, 0xff, sizeof(subsys_a));
3395 memset(subsys_b, 0xff, sizeof(subsys_b));
3396 memset(subsys_cg, 0xff, sizeof(subsys_cg));
3397 memset(submem_hidden, 0x00, sizeof(submem_hidden));
3399 diag_load_subrom_a = false;
3400 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_A), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
3401 this->out_debug_log(_T("SUBSYSTEM ROM Type A READING : %s"), diag_load_subrom_a ? "OK" : "NG");
3403 diag_load_subrom_b = false;
3404 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_B), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
3405 this->out_debug_log(_T("SUBSYSTEM ROM Type B READING : %s"), diag_load_subrom_b ? "OK" : "NG");
3407 diag_load_subrom_cg = false;
3408 if(read_bios(_T(ROM_FM7_SUBSYSTEM_CG), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
3409 this->out_debug_log(_T("SUBSYSTEM CG ROM READING : %s"), diag_load_subrom_cg ? "OK" : "NG");
3410 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
3411 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3412 memset(subsys_ram, 0x00, sizeof(subsys_ram));
3413 memset(submem_cgram, 0x00, sizeof(submem_cgram));
3414 memset(submem_console_av40, 0x00, sizeof(submem_console_av40));
3418 #if defined(_FM77L4)
3419 memset(subsys_cg_l4, 0xff, sizeof(subsys_cg_l4));
3420 memset(subsys_l4, 0xff, sizeof(subsys_l4));
3422 read_bios(_T(ROM_FM77_400LINE_ANKCG), subsys_cg_l4, sizeof(subsys_cg_l4));
3423 read_bios(_T(ROM_FM77_400LINE_SUBSYS), subsys_l4, sizeof(subsys_l4));
3424 memset(text_vram, 0x00, sizeof(text_vram));
3425 //memset(crtc_regs, 0x00, sizeof(crtc_regs));
3429 text_width40 = false;
3432 cursor_blink = true;
3434 text_start_addr.d = 0x0000;
3442 text_scroll_count = 0;
3444 event_id_l4_cursor_blink = -1;
3445 event_id_l4_text_blink = -1;
3451 #if defined(_FM77AV_VARIANTS)
3453 apalette_index.d = 0;
3454 for(i = 0; i < 4096; i++) {
3455 analog_palette_r[i] = i & 0x0f0;
3456 analog_palette_g[i] = (i & 0xf00) >> 4;
3457 analog_palette_b[i] = (i & 0x00f) << 4;
3459 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
3462 for(i = 0; i < 8; i++) set_dpalette(i, i);
3463 #if defined(USE_GREEN_DISPLAY)
3464 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3465 use_green_monitor = false;
3468 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3469 //#if defined(_FM77AV_VARIANTS)
3470 hblank_event_id = -1;
3471 hdisp_event_id = -1;
3472 vsync_event_id = -1;
3473 vstart_event_id = -1;
3480 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
3481 is_cyclesteal = true;
3483 is_cyclesteal = false;
3485 multimode_accessmask = multimode_dispmask = 0;
3486 for(i = 0; i < 4; i++) {
3487 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
3488 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
3491 prev_clock = SUBCLOCK_NORMAL;
3495 key_firq_req = false; //firq_mask = true;
3496 frame_skip_count_transfer = 3;
3497 frame_skip_count_draw = 3;
3498 #if !defined(FIXED_FRAMEBUFFER_SIZE)
3499 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
3501 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
3503 emu->set_vm_screen_lines(200);
3504 #if defined(_FM77AV40SX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3505 mode400line = false;
3507 #elif defined(_FM77L4)
3508 mode400line = false;
3511 palette_changed = true;
3512 //#if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
3513 //register_vline_event(this);
3514 register_frame_event(this);
3516 setup_display_mode();
3519 void DISPLAY::release()
3523 #define STATE_VERSION 12
3525 bool DISPLAY::process_state(FILEIO *state_fio, bool loading)
3527 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
3530 if(!state_fio->StateCheckInt32(this_device_id)) {
3535 state_fio->StateValue(delay_busy);
3536 state_fio->StateValue(halt_flag);
3537 state_fio->StateValue(active_page);
3538 state_fio->StateValue(sub_busy);
3539 state_fio->StateValue(crt_flag);
3540 state_fio->StateValue(vram_wrote);
3541 state_fio->StateValue(is_cyclesteal);
3543 state_fio->StateValue(clock_fast);
3545 #if defined(_FM77AV_VARIANTS)
3546 state_fio->StateValue(subcpu_resetreq);
3547 state_fio->StateValue(power_on_reset);
3549 state_fio->StateValue(cancel_request);
3550 state_fio->StateValue(key_firq_req);
3551 state_fio->StateValue(display_mode);
3552 state_fio->StateValue(prev_clock);
3554 state_fio->StateArray(dpalette_data, sizeof(dpalette_data), 1);
3555 state_fio->StateValue(multimode_accessmask);
3556 state_fio->StateValue(multimode_dispmask);
3558 state_fio->StateValue(offset_point);
3559 #if defined(_FM77AV_VARIANTS)
3560 state_fio->StateValue(offset_point_bank1);
3562 //for(i = 0; i < 2; i++) {
3563 state_fio->StateArray(tmp_offset_point, sizeof(tmp_offset_point), 1);
3564 state_fio->StateArray(offset_changed, sizeof(offset_changed), 1);
3566 state_fio->StateValue(offset_77av);
3567 state_fio->StateValue(diag_load_subrom_c);
3568 state_fio->StateArray(io_w_latch, sizeof(io_w_latch), 1);
3569 state_fio->StateArray(console_ram, sizeof(console_ram), 1);
3570 state_fio->StateArray(work_ram, sizeof(work_ram), 1);
3571 state_fio->StateArray(shared_ram, sizeof(shared_ram), 1);
3572 state_fio->StateArray(subsys_c, sizeof(subsys_c), 1);
3573 state_fio->StateArray(gvram, sizeof(gvram), 1);
3574 state_fio->StateArray(gvram_shadow, sizeof(gvram_shadow), 1);
3575 #if defined(_FM77_VARIANTS)
3576 state_fio->StateValue(kanjisub);
3577 state_fio->StateValue(kanjiaddr.d);
3578 # if defined(_FM77L4)
3579 state_fio->StateValue(mode400line);
3580 state_fio->StateValue(stat_400linecard);
3582 #elif defined(_FM77AV_VARIANTS)
3583 state_fio->StateValue(kanjisub);
3584 state_fio->StateValue(kanjiaddr.d);
3585 state_fio->StateValue(mode320);
3586 state_fio->StateValue(cgrom_bank);
3587 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3588 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3589 state_fio->StateValue(vram_bank);
3591 state_fio->StateValue(displine);
3592 state_fio->StateValue(subrom_bank);
3593 state_fio->StateValue(subrom_bank_using);
3594 state_fio->StateValue(nmi_enable);
3595 state_fio->StateValue(use_alu);
3596 state_fio->StateValue(apalette_index.d);
3597 state_fio->StateArray(analog_palette_r, sizeof(analog_palette_r), 1);
3598 state_fio->StateArray(analog_palette_g, sizeof(analog_palette_g), 1);
3599 state_fio->StateArray(analog_palette_b, sizeof(analog_palette_b), 1);
3600 state_fio->StateValue(diag_load_subrom_a);
3601 state_fio->StateValue(diag_load_subrom_b);
3602 state_fio->StateValue(diag_load_subrom_cg);
3604 state_fio->StateArray(subsys_a, sizeof(subsys_a), 1);
3605 state_fio->StateArray(subsys_b, sizeof(subsys_b), 1);
3606 state_fio->StateArray(subsys_cg, sizeof(subsys_cg), 1);
3607 state_fio->StateArray(submem_hidden, sizeof(submem_hidden), 1);
3608 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3609 state_fio->StateValue(mode400line);
3610 state_fio->StateValue(mode256k);
3611 state_fio->StateValue(monitor_ram);
3612 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3613 state_fio->StateValue(window_low);
3614 state_fio->StateValue(window_high);
3615 state_fio->StateValue(window_xbegin);
3616 state_fio->StateValue(window_xend);
3617 state_fio->StateValue(window_opened);
3619 state_fio->StateValue(kanji_level2);
3620 state_fio->StateValue(vram_active_block);
3621 state_fio->StateValue(vram_display_block);
3622 state_fio->StateValue(console_ram_bank);
3623 state_fio->StateValue(ram_protect);
3624 state_fio->StateValue(cgram_bank);
3625 state_fio->StateArray(subsys_ram, sizeof(subsys_ram), 1);
3626 state_fio->StateArray(submem_cgram, sizeof(submem_cgram), 1);
3627 state_fio->StateArray(submem_console_av40, sizeof(submem_console_av40), 1);
3633 state_fio->StateValue(nmi_event_id);
3634 //#if defined(_FM77AV_VARIANTS)
3635 state_fio->StateValue(hblank_event_id);
3636 state_fio->StateValue(hdisp_event_id);
3637 state_fio->StateValue(vsync_event_id);
3638 state_fio->StateValue(vstart_event_id);
3640 state_fio->StateValue(firq_mask);
3641 state_fio->StateValue(vram_accessflag);
3642 state_fio->StateValue(display_page);
3643 state_fio->StateValue(display_page_bak);
3644 state_fio->StateValue(vblank);
3645 state_fio->StateValue(vsync);
3646 state_fio->StateValue(hblank);
3647 state_fio->StateValue(vblank_count);
3649 #if defined(_FM77L4)
3650 state_fio->StateArray(subsys_cg_l4, sizeof(subsys_cg_l4), 1);
3651 state_fio->StateArray(subsys_l4, sizeof(subsys_l4), 1);
3652 state_fio->StateArray(text_vram, sizeof(text_vram), 1);
3653 //state_fio->Fwrite(crtc_regs, sizeof(crtc_regs), 1);
3654 state_fio->StateValue(workram_l4);
3655 state_fio->StateValue(cursor_lsb);
3656 state_fio->StateValue(text_width40);
3658 state_fio->StateValue(text_blink);
3659 state_fio->StateValue(cursor_blink);
3661 state_fio->StateValue(text_start_addr.d);
3662 state_fio->StateValue(text_lines);
3663 state_fio->StateValue(text_xmax);
3665 state_fio->StateValue(cursor_addr.d);
3666 state_fio->StateValue(cursor_start);
3667 state_fio->StateValue(cursor_end);
3668 state_fio->StateValue(cursor_type);
3669 state_fio->StateValue(text_scroll_count);
3671 state_fio->StateValue(event_id_l4_cursor_blink);
3672 state_fio->StateValue(event_id_l4_text_blink);
3678 crt_flag_bak = true;
3679 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
3680 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
3682 for(addr = 0; addr < 8; addr++) set_dpalette(addr, addr);
3683 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3684 #if defined(USE_GREEN_DISPLAY)
3685 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3689 for(addr = 0; addr < 8; addr++) set_dpalette(addr, dpalette_data[addr]);
3690 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3691 #if defined(USE_GREEN_DISPLAY)
3692 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3694 for(i = 0; i < 4; i++) {
3695 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
3696 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
3699 #if defined(_FM77_VARIANTS)
3700 # if defined(_FM77L4)
3702 #elif defined(_FM77AV_VARIANTS)
3703 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3704 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3706 screen_update_flag = true;
3707 for(i = 0; i < 4096; i++) calc_apalette(i);
3708 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
3711 palette_changed = true;
3712 vram_wrote_shadow = true; // Force Draw
3713 this->draw_screen();
3715 frame_skip_count_draw = 3;
3716 frame_skip_count_transfer = 3;
3717 need_transfer_line = true;
3718 #if defined(USE_GREEN_DISPLAY) && defined(USE_MONITOR_TYPE)
3719 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3720 switch(config.monitor_type) {
3721 case FM7_MONITOR_GREEN:
3722 use_green_monitor = true;
3724 case FM7_MONITOR_STANDARD:
3726 use_green_monitor = false;
3730 //use_green_monitor = false;
3732 force_update = true;
3733 setup_display_mode();