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"
19 #include "fm7_mainio.h"
20 #include "./fm7_keyboard.h"
21 #include "./kanjirom.h"
22 #include "../../statesub.h"
24 DISPLAY::DISPLAY(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
31 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
34 #elif defined(_FM77_VARIANTS)
37 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
38 kanjisub = false; // fix by Ryu Takegami
40 #if defined(_FM77AV_VARIANTS)
46 for(int i = 0; i < 256; i++) {
47 uint16_t n = (uint16_t)i;
48 for(int j = 0; j < 8; j++) {
49 bit_trans_table_0[i][j] = n & 0x80;
50 bit_trans_table_1[i][j] = ((n & 0x80) != 0) ? 0x40 : 0;
51 bit_trans_table_2[i][j] = ((n & 0x80) != 0) ? 0x20 : 0;
52 bit_trans_table_3[i][j] = ((n & 0x80) != 0) ? 0x10 : 0;
53 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
54 bit_trans_table_4[i][j] = ((n & 0x80) != 0) ? 0x08 : 0;
55 bit_trans_table_5[i][j] = ((n & 0x80) != 0) ? 0x04 : 0;
62 #if defined(USE_GREEN_DISPLAY)
63 use_green_monitor = false;
66 set_device_name(_T("DISPLAY SUBSYSTEM"));
74 void DISPLAY::reset_some_devices()
78 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
79 call_write_signal(mainio, SIG_FM7_SUB_HALT, 0x00, 0xff);
82 palette_changed = true;
83 multimode_accessmask = 0;
84 multimode_dispmask = 0;
85 for(i = 0; i < 4; i++) {
86 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
87 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
89 //firq_mask = false; // 20180215 Thanks to Ryu takegami.
90 //cancel_request = false;
91 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
92 switch(config.cpu_type){
101 prev_clock = SUBCLOCK_NORMAL;
103 prev_clock = SUBCLOCK_SLOW;
108 for(i = 0; i < 2; i++) {
109 offset_changed[i] = true;
110 tmp_offset_point[i].d = 0;
113 vram_wrote_shadow = true;
114 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
115 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
119 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
126 if(hblank_event_id >= 0) cancel_event(this, hblank_event_id);
127 if(hdisp_event_id >= 0) cancel_event(this, hdisp_event_id);
129 if(vsync_event_id >= 0) cancel_event(this, vsync_event_id);
130 if(vstart_event_id >= 0) cancel_event(this, vstart_event_id);
131 hblank_event_id = -1;
134 vstart_event_id = -1;
136 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
137 usec = 0.33 * 1000.0;
138 p_vm->set_vm_frame_rate(55.40);
140 usec = 0.51 * 1000.0;
141 p_vm->set_vm_frame_rate(FRAMES_PER_SEC);
144 //register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
145 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
146 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0xff, 0xff);
149 display_page_bak = 0;
151 #if defined(_FM77AV_VARIANTS)
153 offset_point_bank1 = 0;
155 subcpu_resetreq = false;
156 subrom_bank_using = subrom_bank;
161 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
163 vram_display_block = 0;
164 vram_active_block = 0;
166 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
171 window_opened = false;
176 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
177 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
178 call_write_signal(alu, SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400: 200, 0xffff);
179 call_write_signal(alu, SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xffffffff : 0, 0xffffffff);
181 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
182 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
183 call_write_signal(alu, SIG_ALU_400LINE, 0, 0xffffffff);
185 call_write_signal(alu, SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
186 call_write_signal(alu, SIG_ALU_PLANES, 3, 3);
188 for(i = 0; i < 8; i++) set_dpalette(i, i);
189 #if defined(USE_GREEN_DISPLAY)
190 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
192 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
193 //do_firq(!firq_mask && key_firq_req);
195 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
196 //kanjisub = false; // Fixed by Ryu takegami
197 kanjiaddr.d = 0x00000000;
198 # if defined(_FM77L4)
200 stat_400linecard = false;
205 frame_skip_count_draw = 3;
206 frame_skip_count_transfer = 3;
207 need_transfer_line = true;
208 setup_display_mode();
213 void DISPLAY::reset()
218 vram_accessflag = true;
219 display_mode = DISPLAY_MODE_8_200L;
221 crt_flag = false; // Fixed by Ryu Takegami
222 screen_update_flag = true;
223 crt_flag_bak = false;
224 cancel_request = false;
225 #if defined(_FM77AV_VARIANTS)
227 apalette_index.d = 0;
228 for(i = 0; i < 4096; i++) {
229 analog_palette_r[i] = i & 0x0f0;
230 analog_palette_g[i] = (i & 0xf00) >> 4;
231 analog_palette_b[i] = (i & 0x00f) << 4;
233 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
237 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
244 #elif defined(_FM77L4)
246 stat_400linecard = false;
250 text_width40 = false;
255 text_start_addr.d = 0x0000;
263 text_scroll_count = 0;
269 uint8_t *regs = l4crtc->get_regs();
270 display_mode = DISPLAY_MODE_1_400L;
271 if(event_id_l4_cursor_blink >= 0) {
272 cancel_event(this, event_id_l4_cursor_blink);
274 if(event_id_l4_text_blink >= 0) {
275 cancel_event(this, event_id_l4_text_blink);
277 event_id_l4_cursor_blink = -1;
278 event_id_l4_text_blink = -1;
280 usec = ((regs[10] & 0x20) == 0) ? 160.0 : 320.0;
281 usec = usec * 1000.0;
282 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
283 usec = 160.0 * 1000.0;
284 register_event(this, EVENT_FM7SUB_TEXT_BLINK, true, usec, &event_id_l4_cursor_blink);
287 //memset(crtc_regs, 0x00, sizeof(crtc_regs));
290 #if !defined(FIXED_FRAMEBUFFER_SIZE)
291 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
293 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
295 emu->set_vm_screen_lines(200);
297 reset_some_devices();
299 #if defined(_FM77AV_VARIANTS)
300 power_on_reset = false;
301 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
305 for(i = 0; i < 8; i++) set_dpalette(i, i);
308 #if defined(USE_GREEN_DISPLAY) && defined(USE_MONITOR_TYPE)
309 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
310 switch(config.monitor_type) {
311 case FM7_MONITOR_GREEN:
312 use_green_monitor = true;
314 case FM7_MONITOR_STANDARD:
316 use_green_monitor = false;
320 //use_green_monitor = false;
324 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
327 if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
328 register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
331 key_firq_req = false;
336 void DISPLAY::reset_subcpu(bool _check_firq)
338 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0, 1);
339 call_write_signal(subcpu, SIG_CPU_BUSREQ, 0, 1);
342 do_firq(!firq_mask && key_firq_req);
345 void DISPLAY::setup_display_mode(void)
347 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
348 if(display_mode == DISPLAY_MODE_8_400L) {
349 page_offset = 0x0000;
350 pagemod_mask = 0x18000;
352 } else if(display_mode == DISPLAY_MODE_256k) {
353 if(active_page != 0) {
354 page_offset = 0xc000;
356 page_offset = 0x0000;
358 pagemod_mask = 0xe000;
360 } else if(display_mode == DISPLAY_MODE_4096) {
361 if(active_page != 0) {
362 page_offset = 0xc000;
364 page_offset = 0x0000;
366 pagemod_mask = 0xe000;
369 if(active_page != 0) {
370 page_offset = 0xc000;
372 page_offset = 0x0000;
374 pagemod_mask = 0xc000;
377 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
378 if(vram_active_block != 0) page_offset += 0x18000;
380 #elif defined(_FM77AV_VARIANTS)
383 pagemod_mask = 0xe000;
384 } else { // 640x200, 8colors
386 pagemod_mask = 0xc000;
388 if(active_page != 0) {
389 page_offset = 0xc000;
391 page_offset = 0x0000;
393 #elif defined(_FM77L4)
394 if(display_mode == DISPLAY_MODE_1_400L) {
396 pagemod_mask = 0x0000;
397 page_offset = 0x0000;
398 } else { // 640x200, 8colors
400 pagemod_mask = 0xc000;
401 page_offset = 0x0000;
403 page_offset = 0x0000;
405 page_offset = 0x0000;
406 pagemod_mask = 0xc000;
411 void DISPLAY::update_config()
417 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
423 * Vram accessing functions moved to vram.cpp .
426 void DISPLAY::do_irq(bool flag)
428 call_write_signal(subcpu, SIG_CPU_IRQ, flag ? 1: 0, 1);
431 void DISPLAY::do_firq(bool flag)
433 call_write_signal(subcpu, SIG_CPU_FIRQ, flag ? 1: 0, 1);
436 void DISPLAY::do_nmi(bool flag)
438 #if defined(_FM77AV_VARIANTS)
439 if(!nmi_enable) flag = false;
441 call_write_signal(subcpu, SIG_CPU_NMI, flag ? 1 : 0, 1);
444 void DISPLAY::set_multimode(uint8_t val)
447 multimode_accessmask = val & 0x07;
448 multimode_dispmask = (val & 0x70) >> 4;
449 for(int i = 0; i < 4; i++) {
450 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
451 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
454 # if defined(_FM77AV_VARIANTS)
455 call_write_signal(alu, SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
460 uint8_t DISPLAY::get_multimode(void)
466 val = multimode_accessmask & 0x07;
467 val |= ((multimode_dispmask << 4) & 0x70);
473 uint8_t DISPLAY::get_cpuaccessmask(void)
475 return multimode_accessmask & 0x07;
478 void DISPLAY::set_dpalette(uint32_t addr, uint8_t val)
482 dpalette_data[addr] = val | 0xf8; //0b11111000;
483 b = ((val & 0x01) != 0x00)? 255 : 0x00;
484 r = ((val & 0x02) != 0x00)? 255 : 0x00;
485 g = ((val & 0x04) != 0x00)? 255 : 0x00;
487 dpalette_pixel_tmp[addr] = RGB_COLOR(r, g, b);
488 #if defined(USE_GREEN_DISPLAY)
489 static const scrntype_t colortable[8] = {0, 48, 70, 100, 140, 175, 202, 255};
490 g = colortable[val & 0x07];
491 b = r = ((val & 0x07) > 4) ? 48 : 0;
492 dpalette_green_tmp[addr] = RGB_COLOR(r, g, b);
494 palette_changed = true;
497 uint8_t DISPLAY::get_dpalette(uint32_t addr)
505 data = dpalette_data[addr];
510 void DISPLAY::halt_subcpu(void)
512 //call_write_signal(subcpu, SIG_CPU_BUSREQ, 0x01, 0x01);
513 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0x01, 0x01);
516 void DISPLAY::go_subcpu(void)
518 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0x00, 0x01);
521 void DISPLAY::enter_display(void)
526 subclock = SUBCLOCK_NORMAL;
528 subclock = SUBCLOCK_SLOW;
530 if(!(is_cyclesteal) && (vram_accessflag)) {
531 subclock = subclock / 3;
533 if(prev_clock != subclock) {
534 p_vm->set_cpu_clock(subcpu, subclock);
536 prev_clock = subclock;
540 void DISPLAY::leave_display(void)
544 void DISPLAY::halt_subsystem(void)
550 void DISPLAY::restart_subsystem(void)
553 #if defined(_FM77AV_VARIANTS)
554 if(subcpu_resetreq) {
555 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
556 reset_some_devices();
557 power_on_reset = true;
565 void DISPLAY::set_crtflag(void)
572 void DISPLAY::reset_crtflag(void)
579 uint8_t DISPLAY::acknowledge_irq(void)
581 cancel_request = false;
587 uint8_t DISPLAY::beep(void)
589 call_write_signal(mainio, FM7_MAINIO_BEEP, 0x01, 0x01);
590 return 0xff; // True?
595 uint8_t DISPLAY::attention_irq(void)
597 call_write_signal(mainio, FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
602 void DISPLAY::set_cyclesteal(uint8_t val)
605 # if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
609 is_cyclesteal = true;
611 is_cyclesteal = false;
618 void DISPLAY::setup_400linemode(uint8_t val)
622 cursor_lsb = ((val & 0x10) != 0);
623 text_width40 = ((val & 0x08) != 0);
624 workram_l4 = ((val & 0x04) != 0);
625 bool tmpmode = ((val & 0x02) != 0);
626 if(tmpmode != mode400line) {
627 int oldmode = display_mode;
628 mode400line = tmpmode;
629 if(mode400line && stat_400linecard) {
630 display_mode = DISPLAY_MODE_1_400L;
632 display_mode = DISPLAY_MODE_8_200L;
634 if(oldmode != display_mode) {
636 if(display_mode == DISPLAY_MODE_1_400L) {
637 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
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));
644 p_vm->set_vm_frame_rate(FRAMES_PER_SEC);
645 #if !defined(FIXED_FRAMEBUFFER_SIZE)
646 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
647 for(int y = 0; y < 200; y++) {
648 pp = emu->get_screen_buffer(y);
649 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
652 for(int y = 0; y < 400; y++) {
653 pp = emu->get_screen_buffer(y);
654 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
659 setup_display_mode();
667 uint8_t DISPLAY::set_vramaccess(void)
669 vram_accessflag = true;
675 void DISPLAY::reset_vramaccess(void)
677 vram_accessflag = false;
682 uint8_t DISPLAY::reset_subbusy(void)
689 void DISPLAY::set_subbusy(void)
695 #if defined(_FM77AV_VARIANTS)
697 void DISPLAY::alu_write_cmdreg(uint32_t val)
699 call_write_data8(alu, ALU_CMDREG, val);
700 if((val & 0x80) != 0) {
708 void DISPLAY::alu_write_logical_color(uint8_t val)
710 uint32_t data = (uint32_t)val;
711 call_write_data8(alu, ALU_LOGICAL_COLOR, data);
715 void DISPLAY::alu_write_mask_reg(uint8_t val)
717 uint32_t data = (uint32_t)val;
718 call_write_data8(alu, ALU_WRITE_MASKREG, data);
722 void DISPLAY::alu_write_cmpdata_reg(int addr, uint8_t val)
724 uint32_t data = (uint32_t)val;
726 call_write_data8(alu, ALU_CMPDATA_REG + addr, data);
730 void DISPLAY::alu_write_disable_reg(uint8_t val)
732 uint32_t data = (uint32_t)val;
733 call_write_data8(alu, ALU_BANK_DISABLE, data);
737 void DISPLAY::alu_write_tilepaint_data(uint32_t addr, uint8_t val)
739 uint32_t data = (uint32_t)val;
742 call_write_data8(alu, ALU_TILEPAINT_B, data);
745 call_write_data8(alu, ALU_TILEPAINT_R, data);
748 call_write_data8(alu, ALU_TILEPAINT_G, data);
751 //call_write_data8(alu, ALU_TILEPAINT_L, 0xff);
757 void DISPLAY::alu_write_offsetreg_hi(uint8_t val)
759 call_write_data8(alu, ALU_OFFSET_REG_HIGH, val & 0x7f);
763 void DISPLAY::alu_write_offsetreg_lo(uint8_t val)
765 call_write_data8(alu, ALU_OFFSET_REG_LO, val);
769 void DISPLAY::alu_write_linepattern_hi(uint8_t val)
771 call_write_data8(alu, ALU_LINEPATTERN_REG_HIGH, val);
775 void DISPLAY::alu_write_linepattern_lo(uint8_t val)
777 call_write_data8(alu, ALU_LINEPATTERN_REG_LO, val);
781 void DISPLAY::alu_write_line_position(int addr, uint8_t val)
783 uint32_t data = (uint32_t)val;
786 call_write_data8(alu, ALU_LINEPOS_START_X_HIGH, data & 0x03);
789 call_write_data8(alu, ALU_LINEPOS_START_X_LOW, data);
792 call_write_data8(alu, ALU_LINEPOS_START_Y_HIGH, data & 0x01);
795 call_write_data8(alu, ALU_LINEPOS_START_Y_LOW, data);
798 call_write_data8(alu, ALU_LINEPOS_END_X_HIGH, data & 0x03);
801 call_write_data8(alu, ALU_LINEPOS_END_X_LOW, data);
804 call_write_data8(alu, ALU_LINEPOS_END_Y_HIGH, data & 0x01);
807 call_write_data8(alu, ALU_LINEPOS_END_Y_LOW, data);
813 uint8_t DISPLAY::get_miscreg(void)
818 if(!hblank) ret |= 0x80;
819 if(vsync) ret |= 0x04;
820 if(alu->read_signal(SIG_ALU_BUSYSTAT) == 0) ret |= 0x10;
821 if(power_on_reset) ret |= 0x01;
826 void DISPLAY::set_miscreg(uint8_t val)
828 int old_display_page = display_page;
830 nmi_enable = ((val & 0x80) == 0) ? true : false;
831 if(!nmi_enable) do_nmi(false);
833 if((val & 0x40) == 0) {
838 if(display_page != old_display_page) {
841 active_page = ((val & 0x20) == 0) ? 0 : 1;
842 if((val & 0x04) == 0) {
847 cgrom_bank = val & 0x03;
848 setup_display_mode();
852 void DISPLAY::set_monitor_bank(uint8_t var)
854 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
855 if((var & 0x04) != 0){
861 subrom_bank = var & 0x03;
864 subcpu_resetreq = false;
865 power_on_reset = true;
866 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
867 reset_some_devices();
870 subcpu_resetreq = true;
876 void DISPLAY::set_apalette_index_hi(uint8_t val)
878 apalette_index.b.h = val & 0x0f;
882 void DISPLAY::set_apalette_index_lo(uint8_t val)
884 apalette_index.b.l = val;
887 void DISPLAY::calc_apalette(uint16_t idx)
891 g = analog_palette_g[idx];
892 r = analog_palette_r[idx];
893 b = analog_palette_b[idx];
894 if(g != 0) g |= 0x0f;
895 if(r != 0) r |= 0x0f;
896 if(b != 0) b |= 0x0f;
897 analog_palette_pixel_tmp[idx] = RGB_COLOR(r, g, b);
901 void DISPLAY::set_apalette_b(uint8_t val)
905 index = apalette_index.w.l;
906 tmp = (val & 0x0f) << 4;
907 if(analog_palette_b[index] != tmp) {
908 analog_palette_b[index] = tmp;
909 calc_apalette(index);
910 palette_changed = true;
915 void DISPLAY::set_apalette_r(uint8_t val)
919 index = apalette_index.w.l;
920 tmp = (val & 0x0f) << 4;
921 if(analog_palette_r[index] != tmp) {
922 analog_palette_r[index] = tmp;
923 calc_apalette(index);
924 palette_changed = true;
929 void DISPLAY::set_apalette_g(uint8_t val)
933 index = apalette_index.w.l;
934 tmp = (val & 0x0f) << 4;
935 if(analog_palette_g[index] != tmp) {
936 analog_palette_g[index] = tmp;
937 calc_apalette(index);
938 palette_changed = true;
942 #endif // _FM77AV_VARIANTS
945 void DISPLAY::copy_vram_blank_area(void)
949 void DISPLAY::copy_vram_per_line(int begin, int end)
958 uint32_t src_offset_d1;
959 uint32_t src_offset_d2;
960 uint32_t src_offset_d;
965 uint32_t addr_d1, addr_d2;
969 //int dline = (int)displine - 1;
970 int dline = (int)displine;
972 if((begin < 0) || (begin > 4)) return;
973 if((end < 0) || (end > 4)) return;
974 if(begin > end) return;
975 if(dline < 0) return;
977 sectors = end - begin + 1;
979 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)){
980 if(dline >= 400) return;
982 if(dline >= 200) return;
984 #if defined(_FM77AV_VARIANTS)
985 yoff_d1 = offset_point;
986 yoff_d2 = offset_point_bank1;
987 if(display_mode == DISPLAY_MODE_4096) {
988 src_offset = dline * 40 + begin * 8;
989 sectors = sectors * 8;
990 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
993 addr_d1 = (src_offset + yoff_d1) & 0x1fff;
994 addr_d2 = (src_offset + yoff_d2) & 0x1fff;
995 bytes_d1 = 0x2000 - addr_d1;
996 bytes_d2 = 0x2000 - addr_d2;
997 for(k = 0; k < pages; k++) {
999 for(i = 0; i < 3; i++) {
1000 for(j = 0; j < 2; j++) {
1001 uint32_t _addr_base = src_base + src_offset + poff;
1002 if(bytes_d1 < sectors) {
1003 my_memcpy(&gvram_shadow[_addr_base],
1004 &gvram[addr_d1 + src_base + poff],
1006 my_memcpy(&gvram_shadow[_addr_base + bytes_d1],
1007 &gvram[src_base + poff],
1008 sectors - bytes_d1);
1010 my_memcpy(&gvram_shadow[_addr_base],
1011 &gvram[addr_d1 + src_base + poff],
1014 _addr_base += 0xc000;
1015 if(bytes_d2 < sectors) {
1016 my_memcpy(&gvram_shadow[_addr_base],
1017 &gvram[addr_d2 + src_base + poff + 0xc000],
1019 my_memcpy(&gvram_shadow[_addr_base + bytes_d2],
1020 &gvram[src_base + poff + 0xc000],
1021 sectors - bytes_d2);
1023 my_memcpy(&gvram_shadow[_addr_base],
1024 &gvram[addr_d2 + src_base + poff + 0xc000],
1029 src_base = (i + 1) * 0x4000;
1033 vram_draw_table[dline] = true;
1034 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1036 # if defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV40)
1037 else if(display_mode == DISPLAY_MODE_256k) {
1038 src_offset = dline * 40 + begin * 8;
1039 sectors = sectors * 8;
1041 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1043 #elif defined(_FM77AV40)
1048 src_offset_d1 = (src_offset + yoff_d1) & 0x1fff;
1049 src_offset_d2 = (src_offset + yoff_d2) & 0x1fff;
1050 bytes_d1 = 0x2000 - ((src_offset + yoff_d1) & 0x1fff);
1051 bytes_d2 = 0x2000 - ((src_offset + yoff_d2) & 0x1fff);
1052 for(k = 0; k < pages; k++) {
1053 for(i = 0; i < 3; i++) {
1054 for(j = 0; j < 2; j++) {
1056 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
1057 src_offset_d = src_offset_d1;
1060 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
1061 src_offset_d = src_offset_d2;
1064 if(bytes_d < sectors) {
1065 my_memcpy(&gvram_shadow[src_offset + src_base],
1066 &gvram[src_offset_d + src_base],
1068 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1072 my_memcpy(&gvram_shadow[src_offset + src_base],
1073 &gvram[src_offset_d + src_base],
1079 vram_draw_table[dline] = true;
1080 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1082 else if(display_mode == DISPLAY_MODE_8_400L) {
1083 src_offset = dline * 80 + begin * 16;
1084 sectors = sectors * 16;
1085 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1088 if(display_page_bak == 1) { // Is this dirty?
1093 yoff_d = (yoff_d << 1) & 0x7fff;
1094 src_offset_d = (src_offset + yoff_d) & 0x7fff;
1095 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
1096 for(i = 0; i < pages; i++) {
1097 for(j = 0; j < 3; j++) {
1098 src_base = i * 0x18000 + j * 0x8000;
1099 if(bytes_d < sectors) {
1101 my_memcpy(&gvram_shadow[src_offset + src_base],
1102 &gvram[src_offset_d + src_base],
1105 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1109 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1110 &gvram[src_offset_d + src_base],
1115 vram_draw_table[dline] = true;
1116 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1120 src_offset = dline * 80 + begin * 16;
1121 sectors = sectors * 16;
1122 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1124 #elif defined(_FM77AV40)
1126 #elif defined(_FM77AV_VARIANTS)
1132 src_offset_d1 = (src_offset + yoff_d1) & 0x3fff;
1133 src_offset_d2 = (src_offset + yoff_d2) & 0x3fff;
1134 bytes_d1 = 0x4000 - ((src_offset + yoff_d1) & 0x3fff);
1135 bytes_d2 = 0x4000 - ((src_offset + yoff_d2) & 0x3fff);
1136 for(i = 0; i < pages; i++) {
1138 src_offset_d = src_offset_d1;
1141 src_offset_d = src_offset_d2;
1145 for(j = 0; j < 3; j++) {
1146 if(bytes_d < sectors) {
1147 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1148 &gvram[src_offset_d + src_base + poff],
1150 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1151 &gvram[src_base + poff],
1154 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1155 &gvram[src_offset_d + src_base + poff],
1162 vram_draw_table[dline] = true;
1163 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1164 //vram_wrote_table[dline] = false;
1167 #if defined(_FM77L4)
1168 if(display_mode == DISPLAY_MODE_1_400L) {
1169 src_offset = dline * 80 + begin * 16;
1170 sectors = sectors * 16;
1171 yoff_d = (yoff_d1 << 1) & 0x7fff;
1172 src_offset_d = (src_offset + yoff_d) & 0x7fff;
1173 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
1174 if(bytes_d < sectors) {
1176 my_memcpy(&gvram_shadow[src_offset],
1177 &gvram[src_offset_d],
1180 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1184 my_memcpy(&gvram_shadow[src_offset + poff],
1185 &gvram[src_offset_d ],
1188 vram_draw_table[dline] = true;
1189 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1194 src_offset = dline * 80 + begin * 16;
1195 sectors = sectors * 16;
1198 yoff_d = offset_point;
1199 src_offset_d = (src_offset + yoff_d) & 0x3fff;
1200 bytes_d = 0x4000 - ((src_offset + yoff_d) & 0x3fff);
1201 for(j = 0; j < 3; j++) {
1202 src_base = j * 0x4000;
1203 if(bytes_d < sectors) {
1204 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1205 &gvram[src_offset_d + src_base + poff],
1207 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1208 &gvram[src_base + poff],
1211 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1212 &gvram[src_offset_d + src_base + poff],
1216 vram_draw_table[dline] = true;
1217 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1218 //vram_wrote_table[dline] = false;
1224 void DISPLAY::copy_vram_all()
1226 #if defined(_FM77AV_VARIANTS)
1227 uint32_t yoff_d1 = offset_point;
1228 uint32_t yoff_d2 = offset_point_bank1;
1229 uint32_t src_offset_1, src_offset_2;
1231 if(display_mode == DISPLAY_MODE_4096) {
1232 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1237 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1238 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1239 for(int k = 0; k < pages; k++) {
1240 for(int i = 0; i < 3; i++) {
1241 for(int j = 0; j < 2; j++) {
1242 src_offset_1 = i * 0x4000 + j * 0x2000;
1243 src_offset_2 = src_offset_1 + 0xc000;
1244 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1245 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1246 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1247 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1253 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1254 else if(display_mode == DISPLAY_MODE_256k) {
1255 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1256 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
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 src_offset_2 = src_offset_1 + 0xc000;
1261 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1262 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1263 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1264 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1268 for(int i = 0; i < 3; i++) {
1269 for(int j = 0; j < 2; j++) {
1270 src_offset_1 = i * 0x4000 + j * 0x2000;
1271 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1272 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1275 } else if(display_mode == DISPLAY_MODE_8_400L) {
1277 uint32_t yoff_d, bytes_d;
1278 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1281 if(display_page_bak == 1) { // Is this dirty?
1286 yoff_d = (yoff_d << 1) & 0x7fff;
1287 bytes_d = 0x8000 - yoff_d;
1288 for(int i = 0; i < pages; i++) {
1289 for(int j = 0; j < 3; j++) {
1290 uint32_t src_base = i * 0x18000 + j * 0x8000;
1291 my_memcpy(&gvram_shadow[src_base],
1292 &gvram[yoff_d + src_base],
1294 if(bytes_d < 0x8000) {
1295 my_memcpy(&gvram_shadow[bytes_d + src_base],
1304 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1306 #elif defined(_FM77AV40)
1311 uint32_t bytes_d1 = 0x4000 - (yoff_d1 & 0x3fff);
1312 uint32_t bytes_d2 = 0x4000 - (yoff_d2 & 0x3fff);
1313 uint32_t yoff_d, bytes_d;
1314 for(int k = 0; k < pages; k++) {
1315 yoff_d = ((k & 1) == 0) ? (yoff_d1 & 0x3fff) : (yoff_d2 & 0x3fff);
1316 bytes_d = ((k & 1) == 0) ? bytes_d1 : bytes_d2;
1317 for(int j = 0; j < 3; j++) {
1318 src_offset_1 = k * 0xc000 + j * 0x4000;
1319 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1320 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1325 # if defined(_FM77L4)
1326 if(display_mode == DISPLAY_MODE_1_400L) {
1327 uint32_t yoff_d = offset_point & 0x7fff;
1328 uint32_t bytes_d = 0x8000 - (offset_point & 0x7fff);
1329 my_memcpy(&gvram_shadow[0], &gvram[0 + yoff_d], bytes_d);
1330 my_memcpy(&gvram_shadow[0 + bytes_d], &gvram[0], 0x8000 - bytes_d);
1335 uint32_t yoff_d = offset_point & 0x3fff;
1336 uint32_t bytes_d = 0x4000 - (offset_point & 0x3fff);
1337 uint32_t src_offset_1;
1338 for(int j = 0; j < 3; j++) {
1339 src_offset_1 = j * 0x4000;
1340 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1341 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1347 // Timing values from XM7 . Thanks Ryu.
1348 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1349 void DISPLAY::event_callback_hdisp(void)
1354 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x02, 0xff);
1355 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1356 if(displine < 400) f = true;
1358 if(displine < 200) f = true;
1361 hdisp_event_id = -1;
1363 // DO ONLY WHEN SYNC-TO-HSYNC.
1364 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
1366 //copy_vram_per_line(0, 4);
1367 } else if(need_transfer_line) { // Not frame skip.
1370 for(int iii = 0; iii < 5 ; iii++) {
1371 if(vram_wrote_table[iii + displine * 5]) {
1372 if(begin < 0) begin = iii; // Check first.
1377 if(end < begin) end = begin;
1379 copy_vram_per_line(begin, end);
1380 // Prepare to next block.
1386 // Tail of this line.
1389 copy_vram_per_line(begin, end);
1393 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1394 register_event(this, EVENT_FM7SUB_HBLANK, 30.0, false, &hblank_event_id); // NEXT CYCLE_
1396 register_event(this, EVENT_FM7SUB_HBLANK, 39.5, false, &hblank_event_id); // NEXT CYCLE_
1404 void DISPLAY::event_callback_hblank(void)
1411 hblank_event_id = -1;
1413 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1414 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1415 if((displine < 400)) f = true;
1418 if((displine < 200)) f = true;
1422 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id);
1427 void DISPLAY::event_callback_vstart(void)
1434 display_page_bak = display_page;
1436 // Parameter from XM7/VM/display.c , thanks, Ryu.
1437 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1438 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x00, 0xff);
1440 if(vblank_count != 0) {
1441 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1442 usec = (0.98 + 16.4) * 1000.0;
1444 usec = (1.91 + 12.7) * 1000.0;
1446 register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
1448 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1449 usec = 930.0; // 939.0
1451 usec = 1840.0; // 1846.5
1453 vstart_event_id = -1;
1454 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
1455 //register_event(this, EVENT_FM7SUB_HBLANK, usec, false, &hdisp_event_id); // NEXT CYCLE_
1458 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1459 usec = 0.34 * 1000.0;
1461 usec = 1.52 * 1000.0;
1463 vsync_event_id = -1;
1464 hblank_event_id = -1;
1465 hdisp_event_id = -1;
1466 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1470 void DISPLAY::event_callback_vsync(void)
1476 //write_access_page = (write_access_page + 1) & 1;
1479 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1480 usec = 0.33 * 1000.0;
1482 usec = 0.51 * 1000.0;
1484 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x01, 0xff);
1485 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1486 //register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1488 if(palette_changed) {
1489 #if defined(_FM77AV_VARIANTS)
1490 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
1492 #if defined(USE_GREEN_DISPLAY)
1493 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
1495 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
1496 vram_wrote_shadow = true;
1497 for(int yy = 0; yy < 400; yy++) {
1498 vram_draw_table[yy] = true;
1500 palette_changed = false;
1502 // Transfer on VSYNC
1503 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) {
1507 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L))lines = 400;
1508 if(need_transfer_line) {
1509 if(vram_wrote) { // transfer all line
1510 for(displine = 0; displine < lines; displine++) {
1511 //if(!vram_draw_table[displine]) {
1512 copy_vram_per_line(0, 4);
1516 } else { // transfer wrote line
1519 for(displine = 0; displine < lines; displine++) {
1520 //if(!vram_draw_table[displine]) {
1521 for(int iii = 0; iii < 5 ; iii++) {
1522 if(vram_wrote_table[iii + displine * 5]) {
1529 if(end < begin) end = begin;
1530 copy_vram_per_line(begin, end);
1537 if(end < 0) end = 4;
1538 copy_vram_per_line(begin, end);
1546 for(int yy = 0; yy < lines; yy++) {
1547 if(vram_draw_table[yy]) {
1548 vram_wrote_shadow = true;
1549 screen_update_flag = true;
1554 // TRANSFER per HSYNC a.k.a SYNC-TO-HSYNC.
1556 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) lines = 400;
1558 if(need_transfer_line) {
1559 if(vram_wrote) { // Transfer all line.
1560 for(int yy = 0; yy < lines; yy++) {
1562 copy_vram_per_line(0, 4);
1568 for(int yy = 0; yy < lines; yy++) {
1569 if(vram_draw_table[yy]) {
1570 vram_wrote_shadow = true;
1571 screen_update_flag = true;
1575 //vram_wrote = false;
1577 frame_skip_count_transfer++;
1579 // Check frame skip for next frame.
1580 uint32_t factor = ((config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28) & 3;
1581 if((frame_skip_count_transfer > factor) /* || (vram_wrote) */) {
1582 frame_skip_count_transfer = 0;
1583 need_transfer_line = true;
1585 need_transfer_line = false;
1591 #if defined(_FM77L4)
1592 void DISPLAY::cursor_blink_77l4()
1594 if(!(mode400line && stat_400linecard)) return;
1595 uint8_t *regs = l4crtc->get_regs();
1599 if((regs[10] & 0x40) != 0) {
1600 cursor_blink = !cursor_blink;
1601 uint16_t addr = cursor_addr.w.l;
1603 x = ((addr / 2) % 40) / 8;
1604 y = (addr / 2) / 40;
1605 } else { // Width 80
1606 x = ((addr / 2) % 80) / 8;
1607 y = (addr / 2) / 80;
1609 for(int yy = 0; yy < 8; yy++) {
1610 naddr = (y + yy) * 5 + x;
1611 vram_wrote_table[naddr] = true;
1617 void DISPLAY::text_blink_77l4()
1620 uint16_t offset = text_start_addr.w.l;
1623 if(!(mode400line && stat_400linecard)) return;
1624 text_blink = !text_blink;
1625 for(addr = 0; addr < (80 * 50); addr++) {
1626 naddr = ((addr + offset) & 0x0ffe) + 1;
1627 if((text_vram[naddr] & 0x10) != 0) { // ATTR BLINK
1629 x = ((naddr / 2) % 40) / 8;
1630 y = (naddr / 2) / 40;
1631 } else { // Width 80
1632 x = ((naddr / 2) % 80) / 8;
1633 y = (naddr / 2) / 80;
1635 for(int yy = 0; yy < 8; yy++) {
1636 naddr = (y + yy) * 5 + x;
1637 vram_wrote_table[naddr] = true;
1642 #endif //#if defined(_FM77L4)
1644 void DISPLAY::event_callback(int event_id, int err)
1649 case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
1650 #if defined(_FM77AV_VARIANTS)
1658 case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
1661 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1662 case EVENT_FM7SUB_HDISP:
1663 event_callback_hdisp();
1665 case EVENT_FM7SUB_HBLANK:
1666 event_callback_hblank();
1668 case EVENT_FM7SUB_VSTART: // Call first.
1669 event_callback_vstart();
1671 case EVENT_FM7SUB_VSYNC:
1672 event_callback_vsync();
1675 case EVENT_FM7SUB_CLR_BUSY:
1678 case EVENT_FM7SUB_CLR_CRTFLAG:
1681 #if defined(_FM77L4)
1682 case EVENT_FM7SUB_CURSOR_BLINK:
1683 cursor_blink_77l4();
1685 case EVENT_FM7SUB_TEXT_BLINK:
1692 void DISPLAY::event_frame()
1699 //write_access_page = (write_access_page + 1) & 1;
1700 //out_debug_log(_T("DISPLINE=%d"), displine);
1702 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1703 usec = 0.34 * 1000.0;
1705 usec = 1.52 * 1000.0;
1707 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x01, 0xff);
1708 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1709 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1713 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1717 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) lines = 400;
1719 if(need_transfer_line && vram_wrote) {
1720 for(yy = 0; yy < lines; yy++) {
1721 //if(!vram_draw_table[yy]) {
1723 copy_vram_per_line(0, 4);
1731 for(yy = 0; yy < lines; yy++) {
1732 if(vram_draw_table[yy]) {
1738 screen_update_flag = true;
1739 vram_wrote_shadow = true;
1743 frame_skip_count_transfer++;
1745 uint32_t factor = (config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28;
1746 if(frame_skip_count_transfer > factor) {
1747 frame_skip_count_transfer = 0;
1748 need_transfer_line = true;
1750 need_transfer_line = false;
1752 //vram_wrote = false;
1760 void DISPLAY::event_vline(int v, int clock)
1762 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1764 if(need_transfer_line == false) return;
1767 // Not transfer, will transfer at event_frame.
1768 copy_vram_per_line(0, 4);
1772 for(int iii = 0; iii < 5 ; iii++) {
1773 if(vram_wrote_table[displine * 5 + iii]) {
1774 if(begin < 0) begin = iii;
1778 if(end < begin) end = begin;
1779 copy_vram_per_line(begin, end);
1787 copy_vram_per_line(begin, end);
1795 uint32_t DISPLAY::read_signal(int id)
1797 uint32_t retval = 0;
1799 case SIG_FM7_SUB_HALT:
1800 case SIG_DISPLAY_HALT:
1801 retval = (halt_flag) ? 0xffffffff : 0;
1803 case SIG_DISPLAY_BUSY:
1804 retval = (sub_busy) ? 0x80 : 0;
1806 case SIG_DISPLAY_MULTIPAGE:
1807 retval = multimode_accessmask;
1809 case SIG_DISPLAY_PLANES:
1812 #if defined(_FM77AV_VARIANTS)
1813 case SIG_DISPLAY_VSYNC:
1814 retval = (vsync) ? 0x01 : 0x00;
1816 case SIG_DISPLAY_DISPLAY:
1817 retval = (!hblank) ? 0x02: 0x00;
1819 case SIG_FM7_SUB_BANK: // Main: FD13
1820 retval = subrom_bank & 0x03;
1821 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1822 if(monitor_ram) retval |= 0x04;
1826 #if defined(_FM77AV_VARIANTS)
1827 case SIG_DISPLAY_MODE320:
1828 retval = (mode320) ? 0x40: 0x00;
1831 case SIG_DISPLAY_Y_HEIGHT:
1832 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77L4)
1833 retval = ((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) ? 400 : 200;
1838 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1840 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1841 retval |= (kanjisub) ? 0x00 : 0x20;
1842 retval |= (mode256k) ? 0x10 : 0x00;
1843 retval |= (mode400line) ? 0x00 : 0x08;
1844 retval |= (ram_protect) ? 0x00 : 0x04;
1845 #elif defined(_FM77_VARIANTS)
1847 retval |= (kanjisub) ? 0x00 : 0x20;
1848 # if defined(_FM77L4)
1849 retval |= (stat_400linecard) ? 0x00 : 0x08;
1857 case SIG_DISPLAY_X_WIDTH:
1858 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1859 retval = (mode320 || mode256k) ? 320 : 640;
1860 #elif defined(_FM77AV_VARIANTS)
1861 retval = (mode320) ? 320 : 640;
1872 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
1874 bool flag = ((data & mask) != 0);
1878 case SIG_FM7_SUB_HALT:
1883 //call_write_signal(mainio, SIG_FM7_SUB_HALT, data, mask);
1885 case SIG_DISPLAY_HALT:
1889 restart_subsystem();
1892 case SIG_FM7_SUB_CANCEL:
1894 cancel_request = true;
1898 case SIG_DISPLAY_CLOCK:
1902 #if defined(_FM77AV_VARIANTS)
1903 case SIG_FM7_SUB_BANK: // Main: FD13
1904 set_monitor_bank(data & 0xff);
1907 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1908 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1909 //printf("Wrote $FD04: %02x\n", data);
1911 int oldmode = display_mode;
1913 kanjisub = ((data & 0x20) == 0) ? true : false;
1914 mode256k = (((data & 0x10) != 0) && ((data & 0x08) != 0) ) ? true : false;
1915 mode400line = ((data & 0x08) == 0) ? true : false;
1916 ram_protect = ((data & 0x04) == 0) ? true : false;
1917 if((mode400line) && !(mode320)) {
1918 display_mode = DISPLAY_MODE_8_400L;
1919 } else if(mode256k) {
1920 display_mode = DISPLAY_MODE_256k;
1922 display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1924 if(oldmode != display_mode) {
1926 if(mode320 || mode256k) {
1927 if(oldmode == DISPLAY_MODE_8_400L) p_vm->set_vm_frame_rate(FRAMES_PER_SEC);
1928 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1929 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1930 for(y = 0; y < 200; y++) {
1931 pp = emu->get_screen_buffer(y);
1932 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1935 for(y = 0; y < 400; y++) {
1936 pp = emu->get_screen_buffer(y);
1937 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1940 //emu->set_vm_screen_lines(200);
1941 } else if(display_mode == DISPLAY_MODE_8_400L) {
1942 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1943 if(oldmode != DISPLAY_MODE_8_400L) p_vm->set_vm_frame_rate(55.40);
1944 for(y = 0; y < 400; y++) {
1945 pp = emu->get_screen_buffer(y);
1946 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1949 if(oldmode == DISPLAY_MODE_8_400L) p_vm->set_vm_frame_rate(FRAMES_PER_SEC);
1950 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1951 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1952 for(y = 0; y < 200; y++) {
1953 pp = emu->get_screen_buffer(y);
1954 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1957 for(y = 0; y < 400; y++) {
1958 pp = emu->get_screen_buffer(y);
1959 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1962 //emu->set_vm_screen_lines(200);
1965 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
1966 call_write_signal(alu, SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200, 0xffff);
1967 call_write_signal(alu, SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xff : 0x00, 0xff);
1968 frame_skip_count_draw = 3;
1969 frame_skip_count_transfer = 3;
1970 setup_display_mode();
1973 #elif defined(_FM77_VARIANTS)
1975 int oldmode = display_mode;
1976 kanjisub = ((data & 0x20) == 0) ? true : false;
1977 # if defined(_FM77L4)
1978 stat_400linecard = ((data & 0x08) != 0) ? false : true;
1979 if(mode400line && stat_400linecard) {
1981 uint8_t *regs = l4crtc->get_regs();
1982 display_mode = DISPLAY_MODE_1_400L;
1983 if(event_id_l4_cursor_blink >= 0) {
1984 cancel_event(this, event_id_l4_cursor_blink);
1986 if(event_id_l4_text_blink >= 0) {
1987 cancel_event(this, event_id_l4_text_blink);
1989 event_id_l4_cursor_blink = -1;
1990 event_id_l4_text_blink = -1;
1992 usec = ((regs[10] & 0x20) == 0) ? 160.0 : 320.0;
1993 usec = usec * 1000.0;
1994 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
1995 usec = 160.0 * 1000.0;
1996 register_event(this, EVENT_FM7SUB_TEXT_BLINK, true, usec, &event_id_l4_cursor_blink);
1999 display_mode = DISPLAY_MODE_8_200L;
2001 if(oldmode != display_mode) {
2003 if(display_mode == DISPLAY_MODE_1_400L) {
2004 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2005 for(int y = 0; y < 400; y++) {
2006 pp = emu->get_screen_buffer(y);
2007 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2011 p_vm->set_vm_frame_rate(FRAMES_PER_SEC);
2012 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2013 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2014 for(int y = 0; y < 200; y++) {
2015 pp = emu->get_screen_buffer(y);
2016 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2019 for(int y = 0; y < 400; y++) {
2020 pp = emu->get_screen_buffer(y);
2021 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2026 setup_display_mode();
2033 #if defined(_FM77AV_VARIANTS)
2034 case SIG_DISPLAY_MODE320: // FD12 bit 6
2035 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2037 //printf("Wrote $FD12: %02x\n", data);
2038 int oldmode = display_mode;
2041 display_mode = DISPLAY_MODE_8_400L;
2042 } else if(mode256k) {
2043 display_mode = DISPLAY_MODE_256k;
2044 } else if(!(mode320) && !(mode256k)) {
2045 //display_mode = (mode400line) ? DISPLAY_MODE_8_400L : DISPLAY_MODE_8_200L;
2046 display_mode = DISPLAY_MODE_8_200L;
2048 display_mode = (mode256k) ? DISPLAY_MODE_256k : DISPLAY_MODE_4096;
2050 if(oldmode != display_mode) {
2052 if(mode320 || mode256k) {
2053 if(oldmode == DISPLAY_MODE_8_400L) p_vm->set_vm_frame_rate(FRAMES_PER_SEC);
2054 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2055 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2056 for(y = 0; y < 200; y++) {
2057 pp = emu->get_screen_buffer(y);
2058 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
2061 for(y = 0; y < 400; y++) {
2062 pp = emu->get_screen_buffer(y);
2063 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2066 //emu->set_vm_screen_lines(200);
2067 } else { // 200 lines, 8 colors.
2068 if(display_mode == DISPLAY_MODE_8_400L) {
2069 if(oldmode != DISPLAY_MODE_8_400L) p_vm->set_vm_frame_rate(55.40);
2071 if(oldmode == DISPLAY_MODE_8_400L) p_vm->set_vm_frame_rate(FRAMES_PER_SEC);
2073 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2074 int ymax = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
2076 emu->set_vm_screen_size(640, ymax, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2077 for(y = 0; y < ymax; y++) {
2078 pp = emu->get_screen_buffer(y);
2079 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2082 for(y = 0; y < 400; y++) {
2083 pp = emu->get_screen_buffer(y);
2084 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2087 //emu->set_vm_screen_lines(200);
2090 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
2091 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
2092 call_write_signal(alu, SIG_ALU_400LINE, 0x00, 0xff);
2093 setup_display_mode();
2094 //frame_skip_count = 3;
2097 # else /* FM77AV/20/20EX */
2100 if(oldflag != mode320) {
2103 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2104 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2105 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 320 * sizeof(scrntype_t));
2107 for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2109 //emu->set_vm_screen_lines(200);
2111 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2112 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2113 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2115 for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2117 //emu->set_vm_screen_lines(200);
2120 display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
2121 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
2122 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
2123 call_write_signal(alu, SIG_ALU_400LINE, 0, 0xffffffff);
2125 setup_display_mode();
2130 case SIG_DISPLAY_MULTIPAGE:
2131 set_multimode(data);
2133 case SIG_FM7_SUB_KEY_MASK:
2134 if(firq_mask == flag) {
2135 do_firq(!flag && key_firq_req);
2139 case SIG_FM7_SUB_KEY_FIRQ:
2140 do_firq(flag & !(firq_mask));
2141 key_firq_req = flag;
2143 case SIG_FM7_SUB_USE_CLR:
2145 clr_count = data & 0x03;
2156 * Vram accessing functions moved to vram.cpp .
2159 uint32_t DISPLAY::read_mmio(uint32_t addr)
2161 uint32_t retval = 0xff;
2163 if(addr < 0xd400) return 0xff;
2165 #if !defined(_FM77AV_VARIANTS)
2166 raddr = (addr - 0xd400) & 0x000f;
2167 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2168 raddr = (addr - 0xd400) & 0x003f;
2169 #else // FM77AV40EX || FM77AV40SX
2170 raddr = (addr - 0xd400) & 0x00ff;
2173 case 0x00: // Read keyboard
2174 retval = (call_read_data8(keyboard, 0x00) != 0) ? 0xff : 0x7f;
2176 case 0x01: // Read keyboard
2177 retval = call_read_data8(keyboard, 0x01) & 0xff;
2179 case 0x02: // Acknowledge
2188 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2189 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2191 if(!kanjisub) return 0xff;
2192 # if !defined(_FM77_VARIANTS)
2194 return (uint8_t)call_read_data8(kanjiclass2, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
2197 if(kanjiclass1 != NULL) retval = call_read_data8(kanjiclass1, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
2200 if(!kanjisub) return 0xff;
2201 # if !defined(_FM77_VARIANTS)
2203 return (uint8_t)call_read_data8(kanjiclass2, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
2206 if(kanjiclass1 != NULL) retval = call_read_data8(kanjiclass1, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
2213 retval = set_vramaccess();
2218 #if defined(_FM77L4)
2220 if(stat_400linecard) {
2221 retval = l4crtc->read_io8(0);
2225 if(stat_400linecard) {
2226 retval = l4crtc->read_io8(1);
2227 // Update parameters.
2232 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
2234 #if defined(_FM77AV_VARIANTS)
2237 retval = call_read_data8(alu, ALU_CMDREG);
2240 retval = call_read_data8(alu, ALU_LOGICAL_COLOR);
2243 retval = call_read_data8(alu, ALU_WRITE_MASKREG);
2246 retval = call_read_data8(alu, ALU_CMP_STATUS_REG);
2249 retval = call_read_data8(alu, ALU_BANK_DISABLE);
2251 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2252 case 0x2f: // VRAM BANK
2253 retval = 0xfc | (vram_bank & 0x03);
2258 retval = get_miscreg();
2262 retval = call_read_data8(keyboard, 0x31);
2265 retval = call_read_data8(keyboard, 0x32);
2271 return (uint8_t)retval;
2274 uint32_t DISPLAY::read_vram_data8(uint32_t addr)
2278 uint32_t color = (addr >> 14) & 0x03;
2279 #if defined(_FM77L4)
2282 offset = offset_point;
2284 if(multimode_accessflags[2]) return 0xff;
2285 vramaddr = ((addr + offset) & 0x3fff) + 0x8000;
2286 return gvram[vramaddr];
2290 return text_vram[addr & 0x0fff];
2291 } else if(addr < 0xc000) {
2292 return subsys_l4[addr - 0x9800];
2298 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2299 if(display_mode == DISPLAY_MODE_8_400L) {
2300 color = vram_bank & 0x03;
2301 if(color > 2) color = 0;
2303 color = (addr >> 14) & 0x03;
2307 //if((multimode_accessmask & (1 << color)) != 0) return 0xff;
2308 if(multimode_accessflags[color]) return 0xff;
2310 #if defined(_FM77AV_VARIANTS)
2311 if (active_page != 0) {
2312 offset = offset_point_bank1;
2314 offset = offset_point;
2317 offset = offset_point;
2319 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2320 if(vram_active_block != 0) {
2321 if(display_mode != DISPLAY_MODE_256k) offset = 0; // Don't scroll at BLOCK 1.
2324 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2325 if(display_mode == DISPLAY_MODE_8_400L) {
2327 uint32_t page_offset_alt = 0;
2328 if(addr >= 0x8000) return 0xff;
2329 color = vram_bank & 0x03;
2330 if(color > 2) color = 0;
2332 pagemod = 0x8000 * color;
2333 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2334 if(vram_active_block != 0) page_offset = 0x18000;
2336 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2337 return gvram[vramaddr];
2340 uint32_t page_offset_alt;
2341 #if defined(_FM77AV40)
2343 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2345 page_offset_alt = 0; // right?
2348 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2350 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
2351 //page_mask = 0x1fff;
2352 //pagemod = addr & 0xe000;
2354 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2356 return gvram[vramaddr];
2358 #elif defined(_FM77AV_VARIANTS)
2360 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2361 return gvram[vramaddr];
2363 #elif defined(_FM77L4) //_FM77L4
2366 vramaddr = (addr + offset) & 0x7fff;
2367 return gvram[vramaddr];
2369 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2370 return gvram[vramaddr];
2374 #else // Others (77/7/8)
2375 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2376 return gvram[vramaddr];
2380 void DISPLAY::write_dma_data8(uint32_t addr, uint32_t data)
2382 uint32_t raddr = (addr & 0xffff) >> 7;
2383 if(write_dma_func_table[raddr] != NULL) {
2384 (this->*write_dma_func_table[raddr])(addr, (uint8_t) data);
2388 void DISPLAY::write_vram_data8(uint32_t addr, uint8_t data)
2391 uint32_t color = (addr >> 14) & 0x03;
2395 #if defined(_FM77AV_VARIANTS)
2396 if (active_page != 0) {
2397 offset = offset_point_bank1;
2399 offset = offset_point;
2402 offset = offset_point;
2404 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2405 if(vram_active_block != 0) offset = 0; // Don't scroll at BLOCK 1.
2408 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2409 if(display_mode == DISPLAY_MODE_8_400L) {
2411 uint32_t page_offset_alt = 0;
2413 if(addr >= 0x8000) {
2416 color = vram_bank & 0x03;
2417 if(color > 2) color = 0;
2419 pagemod = 0x8000 * color;
2420 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2421 if(vram_active_block != 0) page_offset_alt = 0x18000;
2423 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2424 // Reduce data transfer.
2425 tdata = gvram[vramaddr];
2427 naddr = (addr & 0x7fff) >> 4;
2428 gvram[vramaddr] = data;
2429 vram_wrote_table[naddr] = true;
2431 } else if(display_mode == DISPLAY_MODE_256k) {
2432 uint32_t page_offset_alt;
2434 #if defined(_FM77AV40)
2436 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2438 page_offset_alt = 0; // right?
2441 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2443 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
2444 tdata = gvram[vramaddr];
2446 naddr = (addr & page_mask) >> 3;
2447 gvram[vramaddr] = data;
2448 vram_wrote_table[naddr] = true;
2451 } else if(display_mode == DISPLAY_MODE_4096) {
2453 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2454 tdata = gvram[vramaddr];
2456 naddr = (addr & page_mask) >> 3;
2457 gvram[vramaddr] = data;
2458 vram_wrote_table[naddr] = true;
2462 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2463 tdata = gvram[vramaddr];
2465 naddr = (addr & page_mask) >> 4;
2466 gvram[vramaddr] = data;
2467 vram_wrote_table[naddr] = true;
2470 #elif defined(_FM77AV_VARIANTS)
2471 if(display_mode == DISPLAY_MODE_4096) {
2473 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2474 tdata = gvram[vramaddr];
2476 naddr = (addr & page_mask) >> 3;
2477 gvram[vramaddr] = data;
2478 vram_wrote_table[naddr] = true;
2482 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2483 tdata = gvram[vramaddr];
2485 naddr = (addr & page_mask) >> 4;
2486 gvram[vramaddr] = data;
2487 vram_wrote_table[naddr] = true;
2490 #elif defined(_FM77L4) //_FM77L4
2491 if(display_mode == DISPLAY_MODE_1_400L) {
2494 //if(multimode_accessflags[2]) return;
2495 vramaddr = ((addr + offset) & 0x3fff) + 0x8000;
2496 gvram[vramaddr] = data;
2499 vramaddr = (addr + offset) & 0x7fff;
2500 tdata = gvram[vramaddr];
2502 naddr = (addr & 0x7fff) >> 4;
2503 gvram[vramaddr] = data;
2504 vram_wrote_table[naddr] = true;
2511 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2512 tdata = gvram[vramaddr];
2514 naddr = (addr & 0x3fff) >> 4;
2515 gvram[vramaddr] = data;
2516 vram_wrote_table[naddr] = true;
2519 #else // Others (77/7/8)
2522 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2523 tdata = gvram[vramaddr];
2525 naddr = (addr & 0x3fff) >> 4;
2526 gvram[vramaddr] = data;
2527 vram_wrote_table[naddr] = true;
2533 uint32_t DISPLAY::read_cpu_vram_data8(uint32_t addr)
2536 #if defined(_FM77AV_VARIANTS)
2538 call_read_data8(alu, addr);
2541 return read_vram_data8(addr);
2544 uint32_t DISPLAY::read_dma_vram_data8(uint32_t addr)
2546 return read_vram_data8(addr);
2549 void DISPLAY::init_read_table(void)
2552 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
2553 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cpu_vram_data8;
2554 read_dma_func_table[_at >> 7] = &DISPLAY::read_dma_vram_data8;
2556 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
2557 read_cpu_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2558 read_dma_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2560 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
2561 read_cpu_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2562 read_dma_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2564 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
2565 read_cpu_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2566 read_dma_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2568 #if defined(_FM77AV_VARIANTS)
2569 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
2570 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2571 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2573 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
2574 read_cpu_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2575 read_dma_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2578 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
2579 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2580 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2583 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
2584 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2585 read_dma_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2587 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
2588 read_cpu_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2589 read_dma_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2593 uint32_t DISPLAY::read_console_ram(uint32_t addr)
2595 uint32_t raddr = addr & 0xfff;
2596 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2598 if(console_ram_bank >= 1) {
2599 return submem_console_av40[((console_ram_bank - 1) << 12) + raddr];
2603 return console_ram[raddr];
2606 uint32_t DISPLAY::read_work_ram(uint32_t addr)
2608 addr = addr & 0x3ff;
2609 return work_ram[addr];
2613 uint32_t DISPLAY::read_shared_ram(uint32_t addr)
2615 addr = addr - 0xd380;
2616 return shared_ram[addr];
2619 #if defined(_FM77AV_VARIANTS)
2620 uint32_t DISPLAY::read_hidden_ram(uint32_t addr)
2622 if(addr >= 0xd500) {
2623 return submem_hidden[addr - 0xd500];
2629 uint32_t DISPLAY::read_cgrom(uint32_t addr)
2631 #if defined(_FM77AV_VARIANTS)
2632 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2634 return submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)]; //FIXME
2637 return subsys_cg[(addr - 0xd800) + cgrom_bank * 0x800];
2639 return subsys_c[addr - 0xd800];
2643 uint32_t DISPLAY::read_subsys_monitor(uint32_t addr)
2645 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2647 return subsys_ram[addr - 0xe000];
2650 #if defined(_FM77AV_VARIANTS)
2651 switch(subrom_bank_using & 3) {
2653 return subsys_c[addr - 0xd800];
2656 return subsys_a[addr - 0xe000];
2659 return subsys_b[addr - 0xe000];
2662 return subsys_cg[addr - 0xe000];
2665 #elif defined(_FM77L4)
2667 return subsys_l4[addr - 0xb800];
2669 return subsys_c[addr - 0xd800];
2671 return subsys_c[addr - 0xd800];
2675 uint32_t DISPLAY::read_dma_data8(uint32_t addr)
2677 uint32_t raddr = (addr & 0xffff) >> 7;
2678 if(read_dma_func_table[raddr] != NULL) {
2679 return (this->*read_dma_func_table[raddr])(addr);
2684 uint32_t DISPLAY::read_data8(uint32_t addr)
2686 uint32_t raddr = addr;
2688 if(addr < 0x10000) {
2689 raddr = (addr & 0xffff) >> 7;
2690 if(read_cpu_func_table[raddr] != NULL) {
2691 return (this->*read_cpu_func_table[raddr])(addr);
2696 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2697 return dpalette_data[addr - FM7_SUBMEM_OFFSET_DPALETTE];
2700 #if defined(_FM77AV_VARIANTS)
2702 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2703 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2704 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2705 if(vram_active_block != 0) {
2709 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2710 if(display_mode == DISPLAY_MODE_8_400L) {
2711 uint32_t page_offset_alt = 0;
2714 color = (addr & 0x18000) >> 15;
2715 if(color > 2) color = 0;
2716 pagemod = 0x8000 * color;
2717 if (active_page != 0) {
2718 offset = offset_point_bank1 << 1;
2720 offset = offset_point << 1;
2722 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2723 if(vram_active_block != 0) {
2724 page_offset_alt = 0x18000;
2728 return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset_alt];
2731 return read_vram_data8(addr);
2738 * Vram accessing functions moved to vram.cpp .
2741 void DISPLAY::write_mmio(uint32_t addr, uint8_t data)
2744 uint8_t active_block_old;
2746 if(addr < 0xd400) return;
2748 #if !defined(_FM77AV_VARIANTS)
2749 addr = (addr - 0xd400) & 0x000f;
2750 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2751 addr = (addr - 0xd400) & 0x003f;
2752 #else // FM77AV40EX || FM77AV40SX
2753 addr = (addr - 0xd400) & 0x00ff;
2755 io_w_latch[addr] = (uint8_t)data;
2757 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4)
2760 set_cyclesteal((uint8_t)data);
2761 # if defined(_FM77L4)
2762 setup_400linemode((uint8_t)data);
2766 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2767 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2770 if(!kanjisub) return;
2771 kanjiaddr.w.h = 0x0000;
2772 kanjiaddr.b.h = (uint8_t) data;
2775 if(!kanjisub) return;
2776 kanjiaddr.w.h = 0x0000;
2777 kanjiaddr.b.l = (uint8_t)data;
2790 if(clr_count <= 0) {
2792 } else { // Read once when using clr_foo() to set busy flag.
2795 usec = (1000.0 * 1000.0) / 2000000.0;
2797 usec = (1000.0 * 1000.0) / 999000.0;
2799 if(!(is_cyclesteal) && (vram_accessflag)) usec = usec * 3.0;
2800 usec = (double)clr_count * usec;
2801 register_event(this, EVENT_FM7SUB_CLR_BUSY, usec, false, NULL); // NEXT CYCLE_
2807 #if defined(_FM77L4)
2809 if(stat_400linecard) {
2810 l4crtc->write_io8(0, data & 0x1f);
2814 if(stat_400linecard) {
2815 l4crtc->write_io8(1, data);
2816 // Update parameters.
2817 uint8_t crtc_addr = l4crtc->read_io8(0);
2818 const uint8_t *regs = l4crtc->get_regs();
2819 switch(crtc_addr & 0x1f) {
2822 cursor_addr.w.l &= 0x0ffc;
2823 cursor_addr.w.l |= (((uint16_t)regs[14]) << 10);
2824 cursor_addr.w.l |= (((uint16_t)regs[15]) << 2);
2826 cursor_addr.w.l += 2;
2828 cursor_addr.w.l &= 0xfff;
2830 if((crtc_addr & 0x1f) == 10) {
2832 if(event_id_l4_cursor_blink >= 0) {
2833 cancel_event(this, event_id_l4_cursor_blink);
2835 usec = ((data & 0x20) == 0) ? 160.0 : 320.0;
2836 usec = usec * 1000.0;
2837 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
2841 text_start_addr.w.l &= 0x03fc;
2842 text_start_addr.w.l |= (((uint16_t)data & 3) << 10);
2843 text_scroll_count++;
2844 if((text_scroll_count & 1) == 0) {
2849 text_start_addr.w.l &= 0xfc00;
2850 text_start_addr.w.l |= ((uint16_t)data << 2);
2851 text_scroll_count++;
2852 if((text_scroll_count & 1) == 0) {
2857 text_scroll_count++;
2858 if((text_scroll_count & 1) == 0) {
2860 cursor_addr.w.l &= 0x0ffc;
2861 cursor_addr.w.l |= (((uint16_t)regs[14]) << 10);
2862 cursor_addr.w.l |= (((uint16_t)regs[15]) << 2);
2864 cursor_addr.w.l += 2;
2866 cursor_addr.w.l &= 0xfff;
2877 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
2882 rval = (uint8_t)data;
2883 if(offset_changed[active_page]) {
2884 #if defined(_FM77AV_VARIANTS)
2885 if(active_page != 0) {
2886 tmp_offset_point[active_page].d = offset_point_bank1;
2888 tmp_offset_point[active_page].d = offset_point;
2891 tmp_offset_point[active_page].d = offset_point;
2894 tmp_offset_point[active_page].w.h = 0x0000;
2896 tmp_offset_point[active_page].b.h = rval;
2898 tmp_offset_point[active_page].b.l = rval;
2900 offset_changed[active_page] = !offset_changed[active_page];
2901 if(offset_changed[active_page]) {
2903 #if defined(_FM77AV_VARIANTS)
2904 if(active_page != 0) {
2906 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fff;
2908 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fe0;
2912 offset_point = tmp_offset_point[active_page].d & 0x007fff;
2914 offset_point = tmp_offset_point[active_page].d & 0x007fe0;
2918 offset_point = tmp_offset_point[active_page].d & 0x7fe0;
2922 #if defined(_FM77AV_VARIANTS)
2925 alu_write_cmdreg(data);
2928 alu_write_logical_color(data);
2931 alu_write_mask_reg(data);
2934 alu_write_disable_reg(data);
2937 alu_write_offsetreg_hi(data);
2940 alu_write_offsetreg_lo(data);
2943 alu_write_linepattern_hi(data);
2946 alu_write_linepattern_lo(data);
2948 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2950 console_ram_bank = (data & 0x18) >> 3;
2951 if(console_ram_bank > 2) console_ram_bank = 0;
2952 cgram_bank = data & 0x07;
2953 kanji_level2 = ((data & 0x80) == 0) ? false : true;
2955 case 0x2f: // VRAM BANK
2956 vram_bank = data & 0x03;
2957 if(vram_bank > 2) vram_bank = 0;
2967 call_write_data8(keyboard, 0x31, data);
2969 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2971 active_block_old = vram_active_block;
2972 vram_active_block = data & 0x01;
2973 if(vram_display_block != (((data & 0x10) != 0) ? 1 : 0)) vram_wrote = true;
2974 vram_display_block = ((data & 0x10) != 0) ? 1 : 0;
2975 if(vram_active_block != active_block_old) setup_display_mode();
2980 tmpvar.d = window_xbegin * 8;
2983 tmpvar.b.h = data & 0x03;
2985 tmpvar.b.l = data & 0xf8;
2987 if(mode320 || mode256k) {
2988 if(tmpvar.d > 320) tmpvar.d = 320;
2990 if(tmpvar.d > 640) tmpvar.d = 640;
2992 window_xbegin = tmpvar.d / 8;
2997 tmpvar.d = window_xend * 8;
3000 tmpvar.b.h = data & 0x03;
3002 tmpvar.b.l = data & 0xf8;
3004 if(mode320 || mode256k) {
3005 if(tmpvar.d > 320) tmpvar.d = 320;
3007 if(tmpvar.d > 640) tmpvar.d = 640;
3009 window_xend = tmpvar.d / 8;
3014 tmpvar.d = window_low;
3017 tmpvar.b.h = data & 0x03;
3019 tmpvar.b.l = data & 0xff;
3021 if(display_mode == DISPLAY_MODE_8_400L) {
3022 if(tmpvar.d > 400) tmpvar.d = 400;
3025 if(tmpvar.d > 400) tmpvar.d = 400;
3027 window_low = tmpvar.d;
3032 tmpvar.d = window_high;
3035 tmpvar.b.h = data & 0x03;
3037 tmpvar.b.l = data & 0xff;
3039 if(display_mode == DISPLAY_MODE_8_400L) {
3040 if(tmpvar.d > 400) tmpvar.d = 400;
3043 if(tmpvar.d > 400) tmpvar.d = 400;
3045 window_high = tmpvar.d;
3051 #if defined(_FM77AV_VARIANTS)
3053 if((addr >= 0x13) && (addr <= 0x1a)) {
3054 alu_write_cmpdata_reg(addr - 0x13, data);
3055 } else if((addr >= 0x1c) && (addr <= 0x1e)) {
3056 alu_write_tilepaint_data(addr, data);
3057 } else if((addr >= 0x24) && (addr <= 0x2b)) {
3058 alu_write_line_position(addr - 0x24, data);
3065 void DISPLAY::init_write_table(void)
3068 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
3069 write_cpu_func_table[_at >> 7] = &DISPLAY::write_cpu_vram_data8;
3070 write_dma_func_table[_at >> 7] = &DISPLAY::write_dma_vram_data8;
3072 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
3073 write_cpu_func_table[_at >> 7] = &DISPLAY::write_console_ram;
3074 write_dma_func_table[_at >> 7] = &DISPLAY::write_console_ram;
3076 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
3077 write_cpu_func_table[_at >> 7] = &DISPLAY::write_work_ram;
3078 write_dma_func_table[_at >> 7] = &DISPLAY::write_work_ram;
3080 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
3081 write_cpu_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
3082 write_dma_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
3084 #if defined(_FM77AV_VARIANTS)
3085 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
3086 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
3087 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
3089 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
3090 write_cpu_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
3091 write_dma_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
3094 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
3095 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
3096 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
3099 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
3100 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
3101 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
3102 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
3104 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
3105 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
3106 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
3109 for(_at = 0xd800; _at < 0x10000; _at += 0x80) {
3110 write_cpu_func_table[_at >> 7] = &DISPLAY::write_dummy;
3111 write_dma_func_table[_at >> 7] = &DISPLAY::write_dummy;
3116 void DISPLAY::write_console_ram(uint32_t addr, uint8_t data)
3118 uint32_t raddr = addr & 0xfff;
3119 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3121 if(console_ram_bank >= 1) {
3122 submem_console_av40[((console_ram_bank - 1) << 12) + raddr] = data;
3127 console_ram[raddr] = data;
3131 void DISPLAY::write_work_ram(uint32_t addr, uint8_t data)
3133 uint32_t raddr = addr & 0xfff;
3134 work_ram[raddr] = data;
3138 void DISPLAY::write_shared_ram(uint32_t addr, uint8_t data)
3140 uint32_t raddr = addr & 0x7f;
3141 shared_ram[raddr] = data;
3145 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
3146 void DISPLAY::write_subsys_cgram(uint32_t addr, uint8_t data)
3148 uint32_t raddr = addr - 0xd800;
3149 if(ram_protect) return;
3150 if(!monitor_ram) return;
3151 submem_cgram[cgram_bank * 0x0800 + raddr] = data; //FIXME
3154 void DISPLAY::write_subsys_ram(uint32_t addr, uint8_t data)
3156 if(ram_protect) return;
3157 if(!monitor_ram) return;
3158 subsys_ram[addr - 0xe000] = data; //FIXME
3162 #if defined(_FM77AV_VARIANTS)
3163 void DISPLAY::write_hidden_ram(uint32_t addr, uint8_t data)
3165 submem_hidden[addr - 0xd500] = data;
3170 void DISPLAY::write_cpu_vram_data8(uint32_t addr, uint8_t data)
3172 uint32_t color = (addr & 0xc000) >> 14;
3173 #if defined(_FM77AV_VARIANTS)
3175 call_read_data8(alu, addr);
3179 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3180 if(display_mode == DISPLAY_MODE_8_400L) {
3181 color = vram_bank & 0x03;
3182 if(color > 2) color = 0;
3185 #if defined(_FM77L4)
3189 if(!(multimode_accessflags[2])) write_vram_data8(addr & 0x7fff, data);
3192 } else if(addr < 0x9800) {
3195 addr = addr & 0x0fff;
3196 if(text_vram[addr] != data) {
3197 text_vram[addr] = data;
3199 x = ((addr / 2) % 40) / 8;
3200 y = (addr / 2) / 40;
3201 } else { // Width 80
3202 x = ((addr / 2) % 80) / 8;
3203 y = (addr / 2) / 80;
3205 for(int yy = 0; yy < 8; yy++) {
3206 naddr = (y + yy) * 5 + x;
3207 vram_wrote_table[naddr] = true;
3217 //if((multimode_accessmask & (1 << color)) != 0) return;
3218 if(multimode_accessflags[color]) return;
3220 write_vram_data8(addr & 0xffff, data);
3223 void DISPLAY::write_dma_vram_data8(uint32_t addr, uint8_t data)
3225 uint32_t color = (addr & 0xc000) >> 14;
3226 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3227 if(display_mode == DISPLAY_MODE_8_400L) {
3228 color = vram_bank & 0x03;
3229 if(color > 2) color = 0;
3233 //if((multimode_accessmask & (1 << color)) != 0) return;
3234 if(multimode_accessflags[color]) return;
3236 write_vram_data8(addr & 0xffff, data);
3239 void DISPLAY::write_dummy(uint32_t addr, uint8_t data)
3243 void DISPLAY::write_data8(uint32_t addr, uint32_t data)
3247 //uint32_t page_offset = 0x0000;
3248 uint8_t val8 = data & 0xff;
3249 uint32_t color = (addr & 0xc000) >> 14;
3252 if(addr < 0x10000) {
3253 void (*_write_func)(uint32_t, uint32_t);
3254 raddr = (addr & 0xffff) >> 7;
3255 if(write_cpu_func_table[raddr] != NULL) {
3256 (this->*write_cpu_func_table[raddr])(addr, (uint8_t)data);
3262 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
3263 set_dpalette(addr - FM7_SUBMEM_OFFSET_DPALETTE, val8);
3267 #if defined(_FM77AV_VARIANTS)
3269 else if(addr == FM7_SUBMEM_OFFSET_APALETTE_R) {
3270 set_apalette_r(val8);
3272 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_G) {
3273 set_apalette_g(val8);
3275 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_B) {
3276 set_apalette_b(val8);
3278 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_HI) {
3279 set_apalette_index_hi(val8);
3281 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_LO) {
3282 set_apalette_index_lo(val8);
3286 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
3287 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
3288 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3289 if(display_mode == DISPLAY_MODE_8_400L) {
3292 uint32_t page_offset_alt = 0;
3294 color = (addr & 0x18000) >> 15;
3295 if(color > 2) color = 0;
3296 if (active_page != 0) {
3297 offset = offset_point_bank1 << 1;
3299 offset = offset_point << 1;
3301 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3302 if(vram_active_block != 0) {
3303 page_offset_alt = 0x18000;
3307 naddr = (addr & 0x7fff) >> 4;
3308 pagemod = 0x8000 * color;
3309 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
3310 tdata = gvram[vramaddr];
3311 if(tdata != (uint8_t)data) {
3312 gvram[vramaddr] = data;
3313 vram_wrote_table[naddr] = true;
3317 write_vram_data8(addr, data);
3319 write_vram_data8(addr, data);
3321 //if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
3328 uint32_t DISPLAY::read_bios(const _TCHAR *name, uint8_t *ptr, uint32_t size)
3334 if((name == NULL) || (ptr == NULL)) return 0;
3335 s = create_local_path(name);
3336 if(s == NULL) return 0;
3338 if(!fio.Fopen(s, FILEIO_READ_BINARY)) return 0;
3339 blocks = fio.Fread(ptr, size, 1);
3342 return blocks * size;
3346 void DISPLAY::initialize()
3350 memset(io_w_latch, 0xff, sizeof(io_w_latch));
3351 screen_update_flag = true;
3352 memset(gvram, 0x00, sizeof(gvram));
3353 vram_wrote_shadow = false;
3354 memset(gvram_shadow, 0x00, sizeof(gvram_shadow));
3355 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
3356 for(i = 0; i < 411; i++) vram_draw_table[i] = false;
3357 force_update = false;
3359 memset(console_ram, 0x00, sizeof(console_ram));
3360 memset(work_ram, 0x00, sizeof(work_ram));
3361 memset(shared_ram, 0x00, sizeof(shared_ram));
3362 memset(subsys_c, 0xff, sizeof(subsys_c));
3363 need_transfer_line = true;
3364 frame_skip_count_draw = 3;
3365 frame_skip_count_transfer = 3;
3367 diag_load_subrom_c = false;
3369 if(read_bios(_T(ROM_FM8_SUBSYSTEM), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
3370 this->out_debug_log(_T("SUBSYSTEM ROM READING : %s"), diag_load_subrom_c ? "OK" : "NG");
3372 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_C), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
3373 this->out_debug_log(_T("SUBSYSTEM ROM Type C READING : %s"), diag_load_subrom_c ? "OK" : "NG");
3375 #if defined(_FM77AV_VARIANTS)
3376 memset(subsys_a, 0xff, sizeof(subsys_a));
3377 memset(subsys_b, 0xff, sizeof(subsys_b));
3378 memset(subsys_cg, 0xff, sizeof(subsys_cg));
3379 memset(submem_hidden, 0x00, sizeof(submem_hidden));
3381 diag_load_subrom_a = false;
3382 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_A), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
3383 this->out_debug_log(_T("SUBSYSTEM ROM Type A READING : %s"), diag_load_subrom_a ? "OK" : "NG");
3385 diag_load_subrom_b = false;
3386 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_B), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
3387 this->out_debug_log(_T("SUBSYSTEM ROM Type B READING : %s"), diag_load_subrom_b ? "OK" : "NG");
3389 diag_load_subrom_cg = false;
3390 if(read_bios(_T(ROM_FM7_SUBSYSTEM_CG), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
3391 this->out_debug_log(_T("SUBSYSTEM CG ROM READING : %s"), diag_load_subrom_cg ? "OK" : "NG");
3392 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
3393 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3394 memset(subsys_ram, 0x00, sizeof(subsys_ram));
3395 memset(submem_cgram, 0x00, sizeof(submem_cgram));
3396 memset(submem_console_av40, 0x00, sizeof(submem_console_av40));
3400 #if defined(_FM77L4)
3401 memset(subsys_cg_l4, 0xff, sizeof(subsys_cg_l4));
3402 memset(subsys_l4, 0xff, sizeof(subsys_l4));
3404 read_bios(_T(ROM_FM77_400LINE_ANKCG), subsys_cg_l4, sizeof(subsys_cg_l4));
3405 read_bios(_T(ROM_FM77_400LINE_SUBSYS), subsys_l4, sizeof(subsys_l4));
3406 memset(text_vram, 0x00, sizeof(text_vram));
3407 //memset(crtc_regs, 0x00, sizeof(crtc_regs));
3411 text_width40 = false;
3414 cursor_blink = true;
3416 text_start_addr.d = 0x0000;
3424 text_scroll_count = 0;
3426 event_id_l4_cursor_blink = -1;
3427 event_id_l4_text_blink = -1;
3433 #if defined(_FM77AV_VARIANTS)
3435 apalette_index.d = 0;
3436 for(i = 0; i < 4096; i++) {
3437 analog_palette_r[i] = i & 0x0f0;
3438 analog_palette_g[i] = (i & 0xf00) >> 4;
3439 analog_palette_b[i] = (i & 0x00f) << 4;
3441 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
3444 for(i = 0; i < 8; i++) set_dpalette(i, i);
3445 #if defined(USE_GREEN_DISPLAY)
3446 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3447 use_green_monitor = false;
3450 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3451 //#if defined(_FM77AV_VARIANTS)
3452 hblank_event_id = -1;
3453 hdisp_event_id = -1;
3454 vsync_event_id = -1;
3455 vstart_event_id = -1;
3462 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
3463 is_cyclesteal = true;
3465 is_cyclesteal = false;
3467 multimode_accessmask = multimode_dispmask = 0;
3468 for(i = 0; i < 4; i++) {
3469 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
3470 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
3473 prev_clock = SUBCLOCK_NORMAL;
3477 key_firq_req = false; //firq_mask = true;
3478 frame_skip_count_transfer = 3;
3479 frame_skip_count_draw = 3;
3480 #if !defined(FIXED_FRAMEBUFFER_SIZE)
3481 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
3483 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
3485 emu->set_vm_screen_lines(200);
3486 #if defined(_FM77AV40SX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3487 mode400line = false;
3489 #elif defined(_FM77L4)
3490 mode400line = false;
3493 palette_changed = true;
3494 //#if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
3495 //register_vline_event(this);
3496 register_frame_event(this);
3498 setup_display_mode();
3501 void DISPLAY::release()
3505 #define STATE_VERSION 11
3506 void DISPLAY::decl_state(void)
3508 state_entry = new csp_state_utils(STATE_VERSION, this_device_id, _T("FM7_DISPLAY"));
3509 DECL_STATE_ENTRY_INT(this_device_id);
3512 DECL_STATE_ENTRY_INT32(clr_count);
3513 DECL_STATE_ENTRY_BOOL(halt_flag);
3514 DECL_STATE_ENTRY_INT32(active_page);
3515 DECL_STATE_ENTRY_BOOL(sub_busy);
3516 DECL_STATE_ENTRY_BOOL(crt_flag);
3517 DECL_STATE_ENTRY_BOOL(vram_wrote);
3518 DECL_STATE_ENTRY_BOOL(is_cyclesteal);
3520 DECL_STATE_ENTRY_BOOL(clock_fast);
3522 #if defined(_FM77AV_VARIANTS)
3523 DECL_STATE_ENTRY_BOOL(subcpu_resetreq);
3524 DECL_STATE_ENTRY_BOOL(power_on_reset);
3526 DECL_STATE_ENTRY_BOOL(cancel_request);
3527 DECL_STATE_ENTRY_BOOL(key_firq_req);
3529 DECL_STATE_ENTRY_INT32(display_mode);
3530 DECL_STATE_ENTRY_UINT32(prev_clock);
3533 DECL_STATE_ENTRY_MULTI(void, dpalette_data, sizeof(dpalette_data));
3534 DECL_STATE_ENTRY_UINT8(multimode_accessmask);
3535 DECL_STATE_ENTRY_UINT8(multimode_dispmask);
3537 DECL_STATE_ENTRY_UINT32(offset_point);
3538 #if defined(_FM77AV_VARIANTS)
3539 DECL_STATE_ENTRY_UINT32(offset_point_bank1);
3541 //for(i = 0; i < 2; i++) {
3542 DECL_STATE_ENTRY_PAIR_ARRAY(tmp_offset_point, 2);
3543 DECL_STATE_ENTRY_BOOL_ARRAY(offset_changed, 2);
3545 DECL_STATE_ENTRY_BOOL(offset_77av);
3546 DECL_STATE_ENTRY_BOOL(diag_load_subrom_c);
3549 DECL_STATE_ENTRY_MULTI(void, io_w_latch, sizeof(io_w_latch));
3550 DECL_STATE_ENTRY_MULTI(void, console_ram, sizeof(console_ram));
3551 DECL_STATE_ENTRY_MULTI(void, work_ram, sizeof(work_ram));
3552 DECL_STATE_ENTRY_MULTI(void, shared_ram, sizeof(shared_ram));
3553 DECL_STATE_ENTRY_MULTI(void, subsys_c, sizeof(subsys_c));
3554 DECL_STATE_ENTRY_MULTI(void, gvram, sizeof(gvram));
3555 DECL_STATE_ENTRY_MULTI(void, gvram_shadow, sizeof(gvram_shadow));
3557 #if defined(_FM77_VARIANTS)
3558 DECL_STATE_ENTRY_BOOL(kanjisub);
3559 DECL_STATE_ENTRY_PAIR(kanjiaddr);
3560 # if defined(_FM77L4)
3561 DECL_STATE_ENTRY_BOOL(mode400line);
3562 DECL_STATE_ENTRY_BOOL(stat_400linecard);
3564 #elif defined(_FM77AV_VARIANTS)
3565 DECL_STATE_ENTRY_BOOL(kanjisub);
3566 DECL_STATE_ENTRY_PAIR(kanjiaddr);
3568 DECL_STATE_ENTRY_BOOL(mode320);
3569 DECL_STATE_ENTRY_INT32(cgrom_bank);
3570 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3571 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3572 DECL_STATE_ENTRY_INT32(vram_bank);
3575 DECL_STATE_ENTRY_UINT32(displine);
3576 DECL_STATE_ENTRY_UINT8(subrom_bank);
3577 DECL_STATE_ENTRY_UINT8(subrom_bank_using);
3579 DECL_STATE_ENTRY_BOOL(nmi_enable);
3580 DECL_STATE_ENTRY_BOOL(use_alu);
3582 DECL_STATE_ENTRY_PAIR(apalette_index);
3583 DECL_STATE_ENTRY_MULTI(void, analog_palette_r, sizeof(analog_palette_r));
3584 DECL_STATE_ENTRY_MULTI(void, analog_palette_g, sizeof(analog_palette_g));
3585 DECL_STATE_ENTRY_MULTI(void, analog_palette_b, sizeof(analog_palette_b));
3588 DECL_STATE_ENTRY_BOOL(diag_load_subrom_a);
3589 DECL_STATE_ENTRY_BOOL(diag_load_subrom_b);
3590 DECL_STATE_ENTRY_BOOL(diag_load_subrom_cg);
3592 DECL_STATE_ENTRY_MULTI(void, subsys_a, sizeof(subsys_a));
3593 DECL_STATE_ENTRY_MULTI(void, subsys_b, sizeof(subsys_b));
3594 DECL_STATE_ENTRY_MULTI(void, subsys_cg, sizeof(subsys_cg));
3595 DECL_STATE_ENTRY_MULTI(void, submem_hidden, sizeof(submem_hidden));
3596 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3597 DECL_STATE_ENTRY_BOOL(mode400line);
3598 DECL_STATE_ENTRY_BOOL(mode256k);
3600 DECL_STATE_ENTRY_BOOL(monitor_ram);
3601 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3602 DECL_STATE_ENTRY_UINT16(window_low);
3603 DECL_STATE_ENTRY_UINT16(window_high);
3604 DECL_STATE_ENTRY_UINT16(window_xbegin);
3605 DECL_STATE_ENTRY_UINT16(window_xend);
3606 DECL_STATE_ENTRY_BOOL(window_opened);
3608 DECL_STATE_ENTRY_BOOL(kanji_level2);
3610 DECL_STATE_ENTRY_UINT8(vram_active_block);
3611 DECL_STATE_ENTRY_UINT8(vram_display_block);
3612 DECL_STATE_ENTRY_UINT8(console_ram_bank);
3613 DECL_STATE_ENTRY_BOOL(ram_protect);
3615 DECL_STATE_ENTRY_UINT8(cgram_bank);
3616 DECL_STATE_ENTRY_MULTI(void, subsys_ram, sizeof(subsys_ram));
3617 DECL_STATE_ENTRY_MULTI(void, submem_cgram, sizeof(submem_cgram));
3618 DECL_STATE_ENTRY_MULTI(void, submem_console_av40, sizeof(submem_console_av40));
3624 DECL_STATE_ENTRY_INT32(nmi_event_id);
3625 //#if defined(_FM77AV_VARIANTS)
3626 DECL_STATE_ENTRY_INT32(hblank_event_id);
3627 DECL_STATE_ENTRY_INT32(hdisp_event_id);
3628 DECL_STATE_ENTRY_INT32(vsync_event_id);
3629 DECL_STATE_ENTRY_INT32(vstart_event_id);
3631 DECL_STATE_ENTRY_BOOL(firq_mask);
3632 DECL_STATE_ENTRY_BOOL(vram_accessflag);
3634 DECL_STATE_ENTRY_INT8(display_page);
3635 DECL_STATE_ENTRY_INT8(display_page_bak);
3637 DECL_STATE_ENTRY_BOOL(vblank);
3638 DECL_STATE_ENTRY_BOOL(vsync);
3639 DECL_STATE_ENTRY_BOOL(hblank);
3640 DECL_STATE_ENTRY_INT32(vblank_count);
3642 #if defined(_FM77L4)
3643 DECL_STATE_ENTRY_MULTI(void, subsys_cg_l4, sizeof(subsys_cg_l4));
3644 DECL_STATE_ENTRY_MULTI(void, subsys_l4, sizeof(subsys_l4));
3645 DECL_STATE_ENTRY_MULTI(void, text_vram, sizeof(text_vram));
3646 //state_fio->Fwrite(crtc_regs, sizeof(crtc_regs), 1);
3648 DECL_STATE_ENTRY_BOOL(workram_l4);
3649 DECL_STATE_ENTRY_BOOL(cursor_lsb);
3650 DECL_STATE_ENTRY_BOOL(text_width40);
3652 DECL_STATE_ENTRY_BOOL(text_blink);
3653 DECL_STATE_ENTRY_BOOL(cursor_blink);
3655 DECL_STATE_ENTRY_PAIR(text_start_addr);
3656 DECL_STATE_ENTRY_UINT32(text_lines);
3657 DECL_STATE_ENTRY_UINT32(text_xmax);
3659 DECL_STATE_ENTRY_PAIR(cursor_addr);
3660 DECL_STATE_ENTRY_INT32(cursor_start);
3661 DECL_STATE_ENTRY_INT32(cursor_end);
3662 DECL_STATE_ENTRY_UINT8(cursor_type);
3663 DECL_STATE_ENTRY_UINT8(text_scroll_count);
3665 DECL_STATE_ENTRY_INT32(event_id_l4_cursor_blink);
3666 DECL_STATE_ENTRY_INT32(event_id_l4_text_blink);
3670 void DISPLAY::save_state(FILEIO *state_fio)
3672 if(state_entry != NULL) state_entry->save_state(state_fio);
3675 bool DISPLAY::load_state(FILEIO *state_fio)
3678 if(state_entry != NULL) {
3679 mb = state_entry->load_state(state_fio);
3681 this->out_debug_log(_T("Load State: DISPLAY : id=%d stat=%s"), this_device_id, (mb) ? _T("OK") : _T("NG"));
3682 if(!mb) return false;
3687 crt_flag_bak = true;
3688 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
3689 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
3691 for(addr = 0; addr < 8; addr++) set_dpalette(addr, addr);
3692 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3693 #if defined(USE_GREEN_DISPLAY)
3694 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3698 for(addr = 0; addr < 8; addr++) set_dpalette(addr, dpalette_data[addr]);
3699 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3700 #if defined(USE_GREEN_DISPLAY)
3701 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3703 for(i = 0; i < 4; i++) {
3704 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
3705 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
3708 #if defined(_FM77_VARIANTS)
3709 # if defined(_FM77L4)
3711 #elif defined(_FM77AV_VARIANTS)
3712 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3713 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3715 screen_update_flag = true;
3716 for(i = 0; i < 4096; i++) calc_apalette(i);
3717 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
3720 palette_changed = true;
3721 vram_wrote_shadow = true; // Force Draw
3722 this->draw_screen();
3724 frame_skip_count_draw = 3;
3725 frame_skip_count_transfer = 3;
3726 need_transfer_line = true;
3727 #if defined(USE_GREEN_DISPLAY) && defined(USE_MONITOR_TYPE)
3728 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3729 switch(config.monitor_type) {
3730 case FM7_MONITOR_GREEN:
3731 use_green_monitor = true;
3733 case FM7_MONITOR_STANDARD:
3735 use_green_monitor = false;
3739 //use_green_monitor = false;
3741 force_update = true;
3742 setup_display_mode();