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_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
29 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
32 #elif defined(_FM77_VARIANTS)
35 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
36 kanjisub = false; // fix by Ryu Takegami
38 #if defined(_FM77AV_VARIANTS)
44 for(int i = 0; i < 256; i++) {
45 uint16_t n = (uint16_t)i;
46 for(int j = 0; j < 8; j++) {
47 bit_trans_table_0[i][j] = n & 0x80;
48 bit_trans_table_1[i][j] = ((n & 0x80) != 0) ? 0x40 : 0;
49 bit_trans_table_2[i][j] = ((n & 0x80) != 0) ? 0x20 : 0;
50 bit_trans_table_3[i][j] = ((n & 0x80) != 0) ? 0x10 : 0;
51 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
52 bit_trans_table_4[i][j] = ((n & 0x80) != 0) ? 0x08 : 0;
53 bit_trans_table_5[i][j] = ((n & 0x80) != 0) ? 0x04 : 0;
60 #if defined(USE_GREEN_DISPLAY)
61 use_green_monitor = false;
64 set_device_name(_T("DISPLAY SUBSYSTEM"));
72 void DISPLAY::reset_some_devices()
76 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
77 call_write_signal(mainio, SIG_FM7_SUB_HALT, 0x00, 0xff);
80 palette_changed = true;
81 multimode_accessmask = 0;
82 multimode_dispmask = 0;
83 for(i = 0; i < 4; i++) {
84 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
85 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
87 //firq_mask = false; // 20180215 Thanks to Ryu takegami.
88 //cancel_request = false;
89 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
90 switch(config.cpu_type){
99 prev_clock = SUBCLOCK_NORMAL;
101 prev_clock = SUBCLOCK_SLOW;
106 for(i = 0; i < 2; i++) {
107 offset_changed[i] = true;
108 tmp_offset_point[i].d = 0;
111 vram_wrote_shadow = true;
112 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
113 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
117 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
124 if(hblank_event_id >= 0) cancel_event(this, hblank_event_id);
125 if(hdisp_event_id >= 0) cancel_event(this, hdisp_event_id);
127 if(vsync_event_id >= 0) cancel_event(this, vsync_event_id);
128 if(vstart_event_id >= 0) cancel_event(this, vstart_event_id);
129 hblank_event_id = -1;
132 vstart_event_id = -1;
134 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
135 usec = 0.33 * 1000.0;
136 vm->set_vm_frame_rate(55.40);
138 usec = 0.51 * 1000.0;
139 vm->set_vm_frame_rate(FRAMES_PER_SEC);
142 //register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
143 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
144 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0xff, 0xff);
147 display_page_bak = 0;
149 #if defined(_FM77AV_VARIANTS)
151 offset_point_bank1 = 0;
153 subcpu_resetreq = false;
154 subrom_bank_using = subrom_bank;
159 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
161 vram_display_block = 0;
162 vram_active_block = 0;
164 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
169 window_opened = false;
174 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
175 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
176 call_write_signal(alu, SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400: 200, 0xffff);
177 call_write_signal(alu, SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xffffffff : 0, 0xffffffff);
179 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
180 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
181 call_write_signal(alu, SIG_ALU_400LINE, 0, 0xffffffff);
183 call_write_signal(alu, SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
184 call_write_signal(alu, SIG_ALU_PLANES, 3, 3);
186 for(i = 0; i < 8; i++) set_dpalette(i, i);
187 #if defined(USE_GREEN_DISPLAY)
188 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
190 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
191 //do_firq(!firq_mask && key_firq_req);
193 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
194 //kanjisub = false; // Fixed by Ryu takegami
195 kanjiaddr.d = 0x00000000;
196 # if defined(_FM77L4)
198 stat_400linecard = false;
203 frame_skip_count_draw = 3;
204 frame_skip_count_transfer = 3;
205 need_transfer_line = true;
206 setup_display_mode();
211 void DISPLAY::reset()
216 vram_accessflag = true;
217 display_mode = DISPLAY_MODE_8_200L;
219 crt_flag = false; // Fixed by Ryu Takegami
220 screen_update_flag = true;
221 crt_flag_bak = false;
222 cancel_request = false;
223 #if defined(_FM77AV_VARIANTS)
225 apalette_index.d = 0;
226 for(i = 0; i < 4096; i++) {
227 analog_palette_r[i] = i & 0x0f0;
228 analog_palette_g[i] = (i & 0xf00) >> 4;
229 analog_palette_b[i] = (i & 0x00f) << 4;
231 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
235 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
242 #elif defined(_FM77L4)
244 stat_400linecard = false;
248 text_width40 = false;
253 text_start_addr.d = 0x0000;
261 text_scroll_count = 0;
267 uint8_t *regs = l4crtc->get_regs();
268 display_mode = DISPLAY_MODE_1_400L;
269 if(event_id_l4_cursor_blink >= 0) {
270 cancel_event(this, event_id_l4_cursor_blink);
272 if(event_id_l4_text_blink >= 0) {
273 cancel_event(this, event_id_l4_text_blink);
275 event_id_l4_cursor_blink = -1;
276 event_id_l4_text_blink = -1;
278 usec = ((regs[10] & 0x20) == 0) ? 160.0 : 320.0;
279 usec = usec * 1000.0;
280 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
281 usec = 160.0 * 1000.0;
282 register_event(this, EVENT_FM7SUB_TEXT_BLINK, true, usec, &event_id_l4_cursor_blink);
285 //memset(crtc_regs, 0x00, sizeof(crtc_regs));
288 #if !defined(FIXED_FRAMEBUFFER_SIZE)
289 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
291 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
293 emu->set_vm_screen_lines(200);
295 reset_some_devices();
297 #if defined(_FM77AV_VARIANTS)
298 power_on_reset = false;
299 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
303 for(i = 0; i < 8; i++) set_dpalette(i, i);
306 #if defined(USE_GREEN_DISPLAY) && defined(USE_MONITOR_TYPE)
307 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
308 switch(config.monitor_type) {
309 case FM7_MONITOR_GREEN:
310 use_green_monitor = true;
312 case FM7_MONITOR_STANDARD:
314 use_green_monitor = false;
318 //use_green_monitor = false;
322 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
325 if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
326 register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
329 key_firq_req = false;
334 void DISPLAY::reset_subcpu(bool _check_firq)
336 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0, 1);
337 call_write_signal(subcpu, SIG_CPU_BUSREQ, 0, 1);
340 do_firq(!firq_mask && key_firq_req);
343 void DISPLAY::setup_display_mode(void)
345 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
346 if(display_mode == DISPLAY_MODE_8_400L) {
347 page_offset = 0x0000;
348 pagemod_mask = 0x18000;
350 } else if(display_mode == DISPLAY_MODE_256k) {
351 if(active_page != 0) {
352 page_offset = 0xc000;
354 page_offset = 0x0000;
356 pagemod_mask = 0xe000;
358 } else if(display_mode == DISPLAY_MODE_4096) {
359 if(active_page != 0) {
360 page_offset = 0xc000;
362 page_offset = 0x0000;
364 pagemod_mask = 0xe000;
367 if(active_page != 0) {
368 page_offset = 0xc000;
370 page_offset = 0x0000;
372 pagemod_mask = 0xc000;
375 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
376 if(vram_active_block != 0) page_offset += 0x18000;
378 #elif defined(_FM77AV_VARIANTS)
381 pagemod_mask = 0xe000;
382 } else { // 640x200, 8colors
384 pagemod_mask = 0xc000;
386 if(active_page != 0) {
387 page_offset = 0xc000;
389 page_offset = 0x0000;
391 #elif defined(_FM77L4)
392 if(display_mode == DISPLAY_MODE_1_400L) {
394 pagemod_mask = 0x0000;
395 page_offset = 0x0000;
396 } else { // 640x200, 8colors
398 pagemod_mask = 0xc000;
399 page_offset = 0x0000;
401 page_offset = 0x0000;
403 page_offset = 0x0000;
404 pagemod_mask = 0xc000;
409 void DISPLAY::update_config()
415 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
421 * Vram accessing functions moved to vram.cpp .
424 void DISPLAY::do_irq(bool flag)
426 call_write_signal(subcpu, SIG_CPU_IRQ, flag ? 1: 0, 1);
429 void DISPLAY::do_firq(bool flag)
431 call_write_signal(subcpu, SIG_CPU_FIRQ, flag ? 1: 0, 1);
434 void DISPLAY::do_nmi(bool flag)
436 #if defined(_FM77AV_VARIANTS)
437 if(!nmi_enable) flag = false;
439 call_write_signal(subcpu, SIG_CPU_NMI, flag ? 1 : 0, 1);
442 void DISPLAY::set_multimode(uint8_t val)
445 multimode_accessmask = val & 0x07;
446 multimode_dispmask = (val & 0x70) >> 4;
447 for(int i = 0; i < 4; i++) {
448 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
449 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
452 # if defined(_FM77AV_VARIANTS)
453 call_write_signal(alu, SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
458 uint8_t DISPLAY::get_multimode(void)
464 val = multimode_accessmask & 0x07;
465 val |= ((multimode_dispmask << 4) & 0x70);
471 uint8_t DISPLAY::get_cpuaccessmask(void)
473 return multimode_accessmask & 0x07;
476 void DISPLAY::set_dpalette(uint32_t addr, uint8_t val)
480 dpalette_data[addr] = val | 0xf8; //0b11111000;
481 b = ((val & 0x01) != 0x00)? 255 : 0x00;
482 r = ((val & 0x02) != 0x00)? 255 : 0x00;
483 g = ((val & 0x04) != 0x00)? 255 : 0x00;
485 dpalette_pixel_tmp[addr] = RGB_COLOR(r, g, b);
486 #if defined(USE_GREEN_DISPLAY)
487 static const scrntype_t colortable[8] = {0, 48, 70, 100, 140, 175, 202, 255};
488 g = colortable[val & 0x07];
489 b = r = ((val & 0x07) > 4) ? 48 : 0;
490 dpalette_green_tmp[addr] = RGB_COLOR(r, g, b);
492 palette_changed = true;
495 uint8_t DISPLAY::get_dpalette(uint32_t addr)
503 data = dpalette_data[addr];
508 void DISPLAY::halt_subcpu(void)
510 //call_write_signal(subcpu, SIG_CPU_BUSREQ, 0x01, 0x01);
511 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0x01, 0x01);
514 void DISPLAY::go_subcpu(void)
516 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0x00, 0x01);
519 void DISPLAY::enter_display(void)
524 subclock = SUBCLOCK_NORMAL;
526 subclock = SUBCLOCK_SLOW;
528 if(!(is_cyclesteal) && (vram_accessflag)) {
529 subclock = subclock / 3;
531 if(prev_clock != subclock) {
532 vm->set_cpu_clock(subcpu, subclock);
534 prev_clock = subclock;
538 void DISPLAY::leave_display(void)
542 void DISPLAY::halt_subsystem(void)
548 void DISPLAY::restart_subsystem(void)
551 #if defined(_FM77AV_VARIANTS)
552 if(subcpu_resetreq) {
553 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
554 reset_some_devices();
555 power_on_reset = true;
563 void DISPLAY::set_crtflag(void)
570 void DISPLAY::reset_crtflag(void)
577 uint8_t DISPLAY::acknowledge_irq(void)
579 cancel_request = false;
585 uint8_t DISPLAY::beep(void)
587 call_write_signal(mainio, FM7_MAINIO_BEEP, 0x01, 0x01);
588 return 0xff; // True?
593 uint8_t DISPLAY::attention_irq(void)
595 call_write_signal(mainio, FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
600 void DISPLAY::set_cyclesteal(uint8_t val)
603 # if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
607 is_cyclesteal = true;
609 is_cyclesteal = false;
616 void DISPLAY::setup_400linemode(uint8_t val)
620 cursor_lsb = ((val & 0x10) != 0);
621 text_width40 = ((val & 0x08) != 0);
622 workram_l4 = ((val & 0x04) != 0);
623 bool tmpmode = ((val & 0x02) != 0);
624 if(tmpmode != mode400line) {
625 int oldmode = display_mode;
626 mode400line = tmpmode;
627 if(mode400line && stat_400linecard) {
628 display_mode = DISPLAY_MODE_1_400L;
630 display_mode = DISPLAY_MODE_8_200L;
632 if(oldmode != display_mode) {
634 if(display_mode == DISPLAY_MODE_1_400L) {
635 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
636 for(int y = 0; y < 400; y++) {
637 pp = emu->get_screen_buffer(y);
638 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
642 vm->set_vm_frame_rate(FRAMES_PER_SEC);
643 #if !defined(FIXED_FRAMEBUFFER_SIZE)
644 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
645 for(int y = 0; y < 200; y++) {
646 pp = emu->get_screen_buffer(y);
647 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
650 for(int y = 0; y < 400; y++) {
651 pp = emu->get_screen_buffer(y);
652 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
657 setup_display_mode();
665 uint8_t DISPLAY::set_vramaccess(void)
667 vram_accessflag = true;
673 void DISPLAY::reset_vramaccess(void)
675 vram_accessflag = false;
680 uint8_t DISPLAY::reset_subbusy(void)
687 void DISPLAY::set_subbusy(void)
693 #if defined(_FM77AV_VARIANTS)
695 void DISPLAY::alu_write_cmdreg(uint32_t val)
697 call_write_data8(alu, ALU_CMDREG, val);
698 if((val & 0x80) != 0) {
706 void DISPLAY::alu_write_logical_color(uint8_t val)
708 uint32_t data = (uint32_t)val;
709 call_write_data8(alu, ALU_LOGICAL_COLOR, data);
713 void DISPLAY::alu_write_mask_reg(uint8_t val)
715 uint32_t data = (uint32_t)val;
716 call_write_data8(alu, ALU_WRITE_MASKREG, data);
720 void DISPLAY::alu_write_cmpdata_reg(int addr, uint8_t val)
722 uint32_t data = (uint32_t)val;
724 call_write_data8(alu, ALU_CMPDATA_REG + addr, data);
728 void DISPLAY::alu_write_disable_reg(uint8_t val)
730 uint32_t data = (uint32_t)val;
731 call_write_data8(alu, ALU_BANK_DISABLE, data);
735 void DISPLAY::alu_write_tilepaint_data(uint32_t addr, uint8_t val)
737 uint32_t data = (uint32_t)val;
740 call_write_data8(alu, ALU_TILEPAINT_B, data);
743 call_write_data8(alu, ALU_TILEPAINT_R, data);
746 call_write_data8(alu, ALU_TILEPAINT_G, data);
749 //call_write_data8(alu, ALU_TILEPAINT_L, 0xff);
755 void DISPLAY::alu_write_offsetreg_hi(uint8_t val)
757 call_write_data8(alu, ALU_OFFSET_REG_HIGH, val & 0x7f);
761 void DISPLAY::alu_write_offsetreg_lo(uint8_t val)
763 call_write_data8(alu, ALU_OFFSET_REG_LO, val);
767 void DISPLAY::alu_write_linepattern_hi(uint8_t val)
769 call_write_data8(alu, ALU_LINEPATTERN_REG_HIGH, val);
773 void DISPLAY::alu_write_linepattern_lo(uint8_t val)
775 call_write_data8(alu, ALU_LINEPATTERN_REG_LO, val);
779 void DISPLAY::alu_write_line_position(int addr, uint8_t val)
781 uint32_t data = (uint32_t)val;
784 call_write_data8(alu, ALU_LINEPOS_START_X_HIGH, data & 0x03);
787 call_write_data8(alu, ALU_LINEPOS_START_X_LOW, data);
790 call_write_data8(alu, ALU_LINEPOS_START_Y_HIGH, data & 0x01);
793 call_write_data8(alu, ALU_LINEPOS_START_Y_LOW, data);
796 call_write_data8(alu, ALU_LINEPOS_END_X_HIGH, data & 0x03);
799 call_write_data8(alu, ALU_LINEPOS_END_X_LOW, data);
802 call_write_data8(alu, ALU_LINEPOS_END_Y_HIGH, data & 0x01);
805 call_write_data8(alu, ALU_LINEPOS_END_Y_LOW, data);
811 uint8_t DISPLAY::get_miscreg(void)
816 if(!hblank) ret |= 0x80;
817 if(vsync) ret |= 0x04;
818 if(alu->read_signal(SIG_ALU_BUSYSTAT) == 0) ret |= 0x10;
819 if(power_on_reset) ret |= 0x01;
824 void DISPLAY::set_miscreg(uint8_t val)
826 int old_display_page = display_page;
828 nmi_enable = ((val & 0x80) == 0) ? true : false;
829 if(!nmi_enable) do_nmi(false);
831 if((val & 0x40) == 0) {
836 if(display_page != old_display_page) {
839 active_page = ((val & 0x20) == 0) ? 0 : 1;
840 if((val & 0x04) == 0) {
845 cgrom_bank = val & 0x03;
846 setup_display_mode();
850 void DISPLAY::set_monitor_bank(uint8_t var)
852 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
853 if((var & 0x04) != 0){
859 subrom_bank = var & 0x03;
862 subcpu_resetreq = false;
863 power_on_reset = true;
864 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
865 reset_some_devices();
868 subcpu_resetreq = true;
874 void DISPLAY::set_apalette_index_hi(uint8_t val)
876 apalette_index.b.h = val & 0x0f;
880 void DISPLAY::set_apalette_index_lo(uint8_t val)
882 apalette_index.b.l = val;
885 void DISPLAY::calc_apalette(uint16_t idx)
889 g = analog_palette_g[idx];
890 r = analog_palette_r[idx];
891 b = analog_palette_b[idx];
892 if(g != 0) g |= 0x0f;
893 if(r != 0) r |= 0x0f;
894 if(b != 0) b |= 0x0f;
895 analog_palette_pixel_tmp[idx] = RGB_COLOR(r, g, b);
899 void DISPLAY::set_apalette_b(uint8_t val)
903 index = apalette_index.w.l;
904 tmp = (val & 0x0f) << 4;
905 if(analog_palette_b[index] != tmp) {
906 analog_palette_b[index] = tmp;
907 calc_apalette(index);
908 palette_changed = true;
913 void DISPLAY::set_apalette_r(uint8_t val)
917 index = apalette_index.w.l;
918 tmp = (val & 0x0f) << 4;
919 if(analog_palette_r[index] != tmp) {
920 analog_palette_r[index] = tmp;
921 calc_apalette(index);
922 palette_changed = true;
927 void DISPLAY::set_apalette_g(uint8_t val)
931 index = apalette_index.w.l;
932 tmp = (val & 0x0f) << 4;
933 if(analog_palette_g[index] != tmp) {
934 analog_palette_g[index] = tmp;
935 calc_apalette(index);
936 palette_changed = true;
940 #endif // _FM77AV_VARIANTS
943 void DISPLAY::copy_vram_blank_area(void)
947 void DISPLAY::copy_vram_per_line(int begin, int end)
956 uint32_t src_offset_d1;
957 uint32_t src_offset_d2;
958 uint32_t src_offset_d;
963 uint32_t addr_d1, addr_d2;
967 //int dline = (int)displine - 1;
968 int dline = (int)displine;
970 if((begin < 0) || (begin > 4)) return;
971 if((end < 0) || (end > 4)) return;
972 if(begin > end) return;
973 if(dline < 0) return;
975 sectors = end - begin + 1;
977 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)){
978 if(dline >= 400) return;
980 if(dline >= 200) return;
982 #if defined(_FM77AV_VARIANTS)
983 yoff_d1 = offset_point;
984 yoff_d2 = offset_point_bank1;
985 if(display_mode == DISPLAY_MODE_4096) {
986 src_offset = dline * 40 + begin * 8;
987 sectors = sectors * 8;
988 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
991 addr_d1 = (src_offset + yoff_d1) & 0x1fff;
992 addr_d2 = (src_offset + yoff_d2) & 0x1fff;
993 bytes_d1 = 0x2000 - addr_d1;
994 bytes_d2 = 0x2000 - addr_d2;
995 for(k = 0; k < pages; k++) {
997 for(i = 0; i < 3; i++) {
998 for(j = 0; j < 2; j++) {
999 uint32_t _addr_base = src_base + src_offset + poff;
1000 if(bytes_d1 < sectors) {
1001 my_memcpy(&gvram_shadow[_addr_base],
1002 &gvram[addr_d1 + src_base + poff],
1004 my_memcpy(&gvram_shadow[_addr_base + bytes_d1],
1005 &gvram[src_base + poff],
1006 sectors - bytes_d1);
1008 my_memcpy(&gvram_shadow[_addr_base],
1009 &gvram[addr_d1 + src_base + poff],
1012 _addr_base += 0xc000;
1013 if(bytes_d2 < sectors) {
1014 my_memcpy(&gvram_shadow[_addr_base],
1015 &gvram[addr_d2 + src_base + poff + 0xc000],
1017 my_memcpy(&gvram_shadow[_addr_base + bytes_d2],
1018 &gvram[src_base + poff + 0xc000],
1019 sectors - bytes_d2);
1021 my_memcpy(&gvram_shadow[_addr_base],
1022 &gvram[addr_d2 + src_base + poff + 0xc000],
1027 src_base = (i + 1) * 0x4000;
1031 vram_draw_table[dline] = true;
1032 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1034 # if defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV40)
1035 else if(display_mode == DISPLAY_MODE_256k) {
1036 src_offset = dline * 40 + begin * 8;
1037 sectors = sectors * 8;
1039 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1041 #elif defined(_FM77AV40)
1046 src_offset_d1 = (src_offset + yoff_d1) & 0x1fff;
1047 src_offset_d2 = (src_offset + yoff_d2) & 0x1fff;
1048 bytes_d1 = 0x2000 - ((src_offset + yoff_d1) & 0x1fff);
1049 bytes_d2 = 0x2000 - ((src_offset + yoff_d2) & 0x1fff);
1050 for(k = 0; k < pages; k++) {
1051 for(i = 0; i < 3; i++) {
1052 for(j = 0; j < 2; j++) {
1054 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
1055 src_offset_d = src_offset_d1;
1058 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
1059 src_offset_d = src_offset_d2;
1062 if(bytes_d < sectors) {
1063 my_memcpy(&gvram_shadow[src_offset + src_base],
1064 &gvram[src_offset_d + src_base],
1066 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1070 my_memcpy(&gvram_shadow[src_offset + src_base],
1071 &gvram[src_offset_d + src_base],
1077 vram_draw_table[dline] = true;
1078 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1080 else if(display_mode == DISPLAY_MODE_8_400L) {
1081 src_offset = dline * 80 + begin * 16;
1082 sectors = sectors * 16;
1083 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1086 if(display_page_bak == 1) { // Is this dirty?
1091 yoff_d = (yoff_d << 1) & 0x7fff;
1092 src_offset_d = (src_offset + yoff_d) & 0x7fff;
1093 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
1094 for(i = 0; i < pages; i++) {
1095 for(j = 0; j < 3; j++) {
1096 src_base = i * 0x18000 + j * 0x8000;
1097 if(bytes_d < sectors) {
1099 my_memcpy(&gvram_shadow[src_offset + src_base],
1100 &gvram[src_offset_d + src_base],
1103 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1107 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1108 &gvram[src_offset_d + src_base],
1113 vram_draw_table[dline] = true;
1114 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1118 src_offset = dline * 80 + begin * 16;
1119 sectors = sectors * 16;
1120 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1122 #elif defined(_FM77AV40)
1124 #elif defined(_FM77AV_VARIANTS)
1130 src_offset_d1 = (src_offset + yoff_d1) & 0x3fff;
1131 src_offset_d2 = (src_offset + yoff_d2) & 0x3fff;
1132 bytes_d1 = 0x4000 - ((src_offset + yoff_d1) & 0x3fff);
1133 bytes_d2 = 0x4000 - ((src_offset + yoff_d2) & 0x3fff);
1134 for(i = 0; i < pages; i++) {
1136 src_offset_d = src_offset_d1;
1139 src_offset_d = src_offset_d2;
1143 for(j = 0; j < 3; j++) {
1144 if(bytes_d < sectors) {
1145 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1146 &gvram[src_offset_d + src_base + poff],
1148 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1149 &gvram[src_base + poff],
1152 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1153 &gvram[src_offset_d + src_base + poff],
1160 vram_draw_table[dline] = true;
1161 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1162 //vram_wrote_table[dline] = false;
1165 #if defined(_FM77L4)
1166 if(display_mode == DISPLAY_MODE_1_400L) {
1167 src_offset = dline * 80 + begin * 16;
1168 sectors = sectors * 16;
1169 yoff_d = (yoff_d1 << 1) & 0x7fff;
1170 src_offset_d = (src_offset + yoff_d) & 0x7fff;
1171 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
1172 if(bytes_d < sectors) {
1174 my_memcpy(&gvram_shadow[src_offset],
1175 &gvram[src_offset_d],
1178 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1182 my_memcpy(&gvram_shadow[src_offset + poff],
1183 &gvram[src_offset_d ],
1186 vram_draw_table[dline] = true;
1187 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1192 src_offset = dline * 80 + begin * 16;
1193 sectors = sectors * 16;
1196 yoff_d = offset_point;
1197 src_offset_d = (src_offset + yoff_d) & 0x3fff;
1198 bytes_d = 0x4000 - ((src_offset + yoff_d) & 0x3fff);
1199 for(j = 0; j < 3; j++) {
1200 src_base = j * 0x4000;
1201 if(bytes_d < sectors) {
1202 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1203 &gvram[src_offset_d + src_base + poff],
1205 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1206 &gvram[src_base + poff],
1209 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1210 &gvram[src_offset_d + src_base + poff],
1214 vram_draw_table[dline] = true;
1215 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1216 //vram_wrote_table[dline] = false;
1222 void DISPLAY::copy_vram_all()
1224 #if defined(_FM77AV_VARIANTS)
1225 uint32_t yoff_d1 = offset_point;
1226 uint32_t yoff_d2 = offset_point_bank1;
1227 uint32_t src_offset_1, src_offset_2;
1229 if(display_mode == DISPLAY_MODE_4096) {
1230 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1235 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1236 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1237 for(int k = 0; k < pages; k++) {
1238 for(int i = 0; i < 3; i++) {
1239 for(int j = 0; j < 2; j++) {
1240 src_offset_1 = i * 0x4000 + j * 0x2000;
1241 src_offset_2 = src_offset_1 + 0xc000;
1242 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1243 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1244 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1245 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1251 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1252 else if(display_mode == DISPLAY_MODE_256k) {
1253 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1254 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1255 for(int i = 0; i < 3; i++) {
1256 for(int j = 0; j < 2; j++) {
1257 src_offset_1 = i * 0x4000 + j * 0x2000;
1258 src_offset_2 = src_offset_1 + 0xc000;
1259 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1260 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1261 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1262 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1266 for(int i = 0; i < 3; i++) {
1267 for(int j = 0; j < 2; j++) {
1268 src_offset_1 = i * 0x4000 + j * 0x2000;
1269 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1270 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1273 } else if(display_mode == DISPLAY_MODE_8_400L) {
1275 uint32_t yoff_d, bytes_d;
1276 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1279 if(display_page_bak == 1) { // Is this dirty?
1284 yoff_d = (yoff_d << 1) & 0x7fff;
1285 bytes_d = 0x8000 - yoff_d;
1286 for(int i = 0; i < pages; i++) {
1287 for(int j = 0; j < 3; j++) {
1288 uint32_t src_base = i * 0x18000 + j * 0x8000;
1289 my_memcpy(&gvram_shadow[src_base],
1290 &gvram[yoff_d + src_base],
1292 if(bytes_d < 0x8000) {
1293 my_memcpy(&gvram_shadow[bytes_d + src_base],
1302 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1304 #elif defined(_FM77AV40)
1309 uint32_t bytes_d1 = 0x4000 - (yoff_d1 & 0x3fff);
1310 uint32_t bytes_d2 = 0x4000 - (yoff_d2 & 0x3fff);
1311 uint32_t yoff_d, bytes_d;
1312 for(int k = 0; k < pages; k++) {
1313 yoff_d = ((k & 1) == 0) ? (yoff_d1 & 0x3fff) : (yoff_d2 & 0x3fff);
1314 bytes_d = ((k & 1) == 0) ? bytes_d1 : bytes_d2;
1315 for(int j = 0; j < 3; j++) {
1316 src_offset_1 = k * 0xc000 + j * 0x4000;
1317 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1318 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1323 # if defined(_FM77L4)
1324 if(display_mode == DISPLAY_MODE_1_400L) {
1325 uint32_t yoff_d = offset_point & 0x7fff;
1326 uint32_t bytes_d = 0x8000 - (offset_point & 0x7fff);
1327 my_memcpy(&gvram_shadow[0], &gvram[0 + yoff_d], bytes_d);
1328 my_memcpy(&gvram_shadow[0 + bytes_d], &gvram[0], 0x8000 - bytes_d);
1333 uint32_t yoff_d = offset_point & 0x3fff;
1334 uint32_t bytes_d = 0x4000 - (offset_point & 0x3fff);
1335 uint32_t src_offset_1;
1336 for(int j = 0; j < 3; j++) {
1337 src_offset_1 = j * 0x4000;
1338 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1339 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1345 // Timing values from XM7 . Thanks Ryu.
1346 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1347 void DISPLAY::event_callback_hdisp(void)
1352 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x02, 0xff);
1353 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1354 if(displine < 400) f = true;
1356 if(displine < 200) f = true;
1359 hdisp_event_id = -1;
1361 // DO ONLY WHEN SYNC-TO-HSYNC.
1362 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
1364 //copy_vram_per_line(0, 4);
1365 } else if(need_transfer_line) { // Not frame skip.
1368 for(int iii = 0; iii < 5 ; iii++) {
1369 if(vram_wrote_table[iii + displine * 5]) {
1370 if(begin < 0) begin = iii; // Check first.
1375 if(end < begin) end = begin;
1377 copy_vram_per_line(begin, end);
1378 // Prepare to next block.
1384 // Tail of this line.
1387 copy_vram_per_line(begin, end);
1391 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1392 register_event(this, EVENT_FM7SUB_HBLANK, 30.0, false, &hblank_event_id); // NEXT CYCLE_
1394 register_event(this, EVENT_FM7SUB_HBLANK, 39.5, false, &hblank_event_id); // NEXT CYCLE_
1402 void DISPLAY::event_callback_hblank(void)
1409 hblank_event_id = -1;
1411 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1412 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1413 if((displine < 400)) f = true;
1416 if((displine < 200)) f = true;
1420 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id);
1425 void DISPLAY::event_callback_vstart(void)
1432 display_page_bak = display_page;
1434 // Parameter from XM7/VM/display.c , thanks, Ryu.
1435 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1436 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x00, 0xff);
1438 if(vblank_count != 0) {
1439 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1440 usec = (0.98 + 16.4) * 1000.0;
1442 usec = (1.91 + 12.7) * 1000.0;
1444 register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
1446 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1447 usec = 930.0; // 939.0
1449 usec = 1840.0; // 1846.5
1451 vstart_event_id = -1;
1452 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
1453 //register_event(this, EVENT_FM7SUB_HBLANK, usec, false, &hdisp_event_id); // NEXT CYCLE_
1456 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1457 usec = 0.34 * 1000.0;
1459 usec = 1.52 * 1000.0;
1461 vsync_event_id = -1;
1462 hblank_event_id = -1;
1463 hdisp_event_id = -1;
1464 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1468 void DISPLAY::event_callback_vsync(void)
1474 //write_access_page = (write_access_page + 1) & 1;
1477 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1478 usec = 0.33 * 1000.0;
1480 usec = 0.51 * 1000.0;
1482 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x01, 0xff);
1483 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1484 //register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1486 if(palette_changed) {
1487 #if defined(_FM77AV_VARIANTS)
1488 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
1490 #if defined(USE_GREEN_DISPLAY)
1491 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
1493 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
1494 vram_wrote_shadow = true;
1495 for(int yy = 0; yy < 400; yy++) {
1496 vram_draw_table[yy] = true;
1498 palette_changed = false;
1500 // Transfer on VSYNC
1501 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) {
1505 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L))lines = 400;
1506 if(need_transfer_line) {
1507 if(vram_wrote) { // transfer all line
1508 for(displine = 0; displine < lines; displine++) {
1509 //if(!vram_draw_table[displine]) {
1510 copy_vram_per_line(0, 4);
1514 } else { // transfer wrote line
1517 for(displine = 0; displine < lines; displine++) {
1518 //if(!vram_draw_table[displine]) {
1519 for(int iii = 0; iii < 5 ; iii++) {
1520 if(vram_wrote_table[iii + displine * 5]) {
1527 if(end < begin) end = begin;
1528 copy_vram_per_line(begin, end);
1535 if(end < 0) end = 4;
1536 copy_vram_per_line(begin, end);
1544 for(int yy = 0; yy < lines; yy++) {
1545 if(vram_draw_table[yy]) {
1546 vram_wrote_shadow = true;
1547 screen_update_flag = true;
1552 // TRANSFER per HSYNC a.k.a SYNC-TO-HSYNC.
1554 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) lines = 400;
1556 if(need_transfer_line) {
1557 if(vram_wrote) { // Transfer all line.
1558 for(int yy = 0; yy < lines; yy++) {
1560 copy_vram_per_line(0, 4);
1566 for(int yy = 0; yy < lines; yy++) {
1567 if(vram_draw_table[yy]) {
1568 vram_wrote_shadow = true;
1569 screen_update_flag = true;
1573 //vram_wrote = false;
1575 frame_skip_count_transfer++;
1577 // Check frame skip for next frame.
1578 uint32_t factor = ((config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28) & 3;
1579 if((frame_skip_count_transfer > factor) /* || (vram_wrote) */) {
1580 frame_skip_count_transfer = 0;
1581 need_transfer_line = true;
1583 need_transfer_line = false;
1589 #if defined(_FM77L4)
1590 void DISPLAY::cursor_blink_77l4()
1592 if(!(mode400line && stat_400linecard)) return;
1593 uint8_t *regs = l4crtc->get_regs();
1597 if((regs[10] & 0x40) != 0) {
1598 cursor_blink = !cursor_blink;
1599 uint16_t addr = cursor_addr.w.l;
1601 x = ((addr / 2) % 40) / 8;
1602 y = (addr / 2) / 40;
1603 } else { // Width 80
1604 x = ((addr / 2) % 80) / 8;
1605 y = (addr / 2) / 80;
1607 for(int yy = 0; yy < 8; yy++) {
1608 naddr = (y + yy) * 5 + x;
1609 vram_wrote_table[naddr] = true;
1615 void DISPLAY::text_blink_77l4()
1618 uint16_t offset = text_start_addr.w.l;
1621 if(!(mode400line && stat_400linecard)) return;
1622 text_blink = !text_blink;
1623 for(addr = 0; addr < (80 * 50); addr++) {
1624 naddr = ((addr + offset) & 0x0ffe) + 1;
1625 if((text_vram[naddr] & 0x10) != 0) { // ATTR BLINK
1627 x = ((naddr / 2) % 40) / 8;
1628 y = (naddr / 2) / 40;
1629 } else { // Width 80
1630 x = ((naddr / 2) % 80) / 8;
1631 y = (naddr / 2) / 80;
1633 for(int yy = 0; yy < 8; yy++) {
1634 naddr = (y + yy) * 5 + x;
1635 vram_wrote_table[naddr] = true;
1640 #endif //#if defined(_FM77L4)
1642 void DISPLAY::event_callback(int event_id, int err)
1647 case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
1648 #if defined(_FM77AV_VARIANTS)
1656 case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
1659 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1660 case EVENT_FM7SUB_HDISP:
1661 event_callback_hdisp();
1663 case EVENT_FM7SUB_HBLANK:
1664 event_callback_hblank();
1666 case EVENT_FM7SUB_VSTART: // Call first.
1667 event_callback_vstart();
1669 case EVENT_FM7SUB_VSYNC:
1670 event_callback_vsync();
1673 case EVENT_FM7SUB_DELAY_BUSY:
1677 case EVENT_FM7SUB_CLEAR_DELAY:
1680 case EVENT_FM7SUB_CLR_CRTFLAG:
1683 #if defined(_FM77L4)
1684 case EVENT_FM7SUB_CURSOR_BLINK:
1685 cursor_blink_77l4();
1687 case EVENT_FM7SUB_TEXT_BLINK:
1694 void DISPLAY::event_frame()
1701 //write_access_page = (write_access_page + 1) & 1;
1702 //out_debug_log(_T("DISPLINE=%d"), displine);
1704 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1705 usec = 0.34 * 1000.0;
1707 usec = 1.52 * 1000.0;
1709 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x01, 0xff);
1710 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1711 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1715 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1719 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) lines = 400;
1721 if(need_transfer_line && vram_wrote) {
1722 for(yy = 0; yy < lines; yy++) {
1723 //if(!vram_draw_table[yy]) {
1725 copy_vram_per_line(0, 4);
1733 for(yy = 0; yy < lines; yy++) {
1734 if(vram_draw_table[yy]) {
1740 screen_update_flag = true;
1741 vram_wrote_shadow = true;
1745 frame_skip_count_transfer++;
1747 uint32_t factor = (config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28;
1748 if(frame_skip_count_transfer > factor) {
1749 frame_skip_count_transfer = 0;
1750 need_transfer_line = true;
1752 need_transfer_line = false;
1754 //vram_wrote = false;
1762 void DISPLAY::event_vline(int v, int clock)
1764 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1766 if(need_transfer_line == false) return;
1769 // Not transfer, will transfer at event_frame.
1770 copy_vram_per_line(0, 4);
1774 for(int iii = 0; iii < 5 ; iii++) {
1775 if(vram_wrote_table[displine * 5 + iii]) {
1776 if(begin < 0) begin = iii;
1780 if(end < begin) end = begin;
1781 copy_vram_per_line(begin, end);
1789 copy_vram_per_line(begin, end);
1797 uint32_t DISPLAY::read_signal(int id)
1799 uint32_t retval = 0;
1801 case SIG_FM7_SUB_HALT:
1802 case SIG_DISPLAY_HALT:
1803 retval = (halt_flag) ? 0xffffffff : 0;
1805 case SIG_DISPLAY_BUSY:
1806 retval = (sub_busy) ? 0x80 : 0;
1808 case SIG_DISPLAY_MULTIPAGE:
1809 retval = multimode_accessmask;
1811 case SIG_DISPLAY_PLANES:
1814 #if defined(_FM77AV_VARIANTS)
1815 case SIG_DISPLAY_VSYNC:
1816 retval = (vsync) ? 0x01 : 0x00;
1818 case SIG_DISPLAY_DISPLAY:
1819 retval = (!hblank) ? 0x02: 0x00;
1821 case SIG_FM7_SUB_BANK: // Main: FD13
1822 retval = subrom_bank & 0x03;
1823 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1824 if(monitor_ram) retval |= 0x04;
1828 #if defined(_FM77AV_VARIANTS)
1829 case SIG_DISPLAY_MODE320:
1830 retval = (mode320) ? 0x40: 0x00;
1833 case SIG_DISPLAY_Y_HEIGHT:
1834 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77L4)
1835 retval = ((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) ? 400 : 200;
1840 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1842 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1843 retval |= (kanjisub) ? 0x00 : 0x20;
1844 retval |= (mode256k) ? 0x10 : 0x00;
1845 retval |= (mode400line) ? 0x00 : 0x08;
1846 retval |= (ram_protect) ? 0x00 : 0x04;
1847 #elif defined(_FM77_VARIANTS)
1849 retval |= (kanjisub) ? 0x00 : 0x20;
1850 # if defined(_FM77L4)
1851 retval |= (stat_400linecard) ? 0x00 : 0x08;
1859 case SIG_DISPLAY_X_WIDTH:
1860 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1861 retval = (mode320 || mode256k) ? 320 : 640;
1862 #elif defined(_FM77AV_VARIANTS)
1863 retval = (mode320) ? 320 : 640;
1874 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
1876 bool flag = ((data & mask) != 0);
1880 case SIG_FM7_SUB_HALT:
1885 //call_write_signal(mainio, SIG_FM7_SUB_HALT, data, mask);
1887 case SIG_DISPLAY_HALT:
1891 restart_subsystem();
1894 case SIG_FM7_SUB_CANCEL:
1896 cancel_request = true;
1900 case SIG_DISPLAY_CLOCK:
1904 #if defined(_FM77AV_VARIANTS)
1905 case SIG_FM7_SUB_BANK: // Main: FD13
1906 set_monitor_bank(data & 0xff);
1909 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1910 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1911 //printf("Wrote $FD04: %02x\n", data);
1913 int oldmode = display_mode;
1915 kanjisub = ((data & 0x20) == 0) ? true : false;
1916 mode256k = (((data & 0x10) != 0) && ((data & 0x08) != 0) ) ? true : false;
1917 mode400line = ((data & 0x08) == 0) ? true : false;
1918 ram_protect = ((data & 0x04) == 0) ? true : false;
1919 if((mode400line) && !(mode320)) {
1920 display_mode = DISPLAY_MODE_8_400L;
1921 } else if(mode256k) {
1922 display_mode = DISPLAY_MODE_256k;
1924 display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1926 if(oldmode != display_mode) {
1928 if(mode320 || mode256k) {
1929 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
1930 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1931 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1932 for(y = 0; y < 200; y++) {
1933 pp = emu->get_screen_buffer(y);
1934 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1937 for(y = 0; y < 400; y++) {
1938 pp = emu->get_screen_buffer(y);
1939 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1942 //emu->set_vm_screen_lines(200);
1943 } else if(display_mode == DISPLAY_MODE_8_400L) {
1944 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1945 if(oldmode != DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(55.40);
1946 for(y = 0; y < 400; y++) {
1947 pp = emu->get_screen_buffer(y);
1948 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1951 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
1952 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1953 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1954 for(y = 0; y < 200; y++) {
1955 pp = emu->get_screen_buffer(y);
1956 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1959 for(y = 0; y < 400; y++) {
1960 pp = emu->get_screen_buffer(y);
1961 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1964 //emu->set_vm_screen_lines(200);
1967 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
1968 call_write_signal(alu, SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200, 0xffff);
1969 call_write_signal(alu, SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xff : 0x00, 0xff);
1970 frame_skip_count_draw = 3;
1971 frame_skip_count_transfer = 3;
1972 setup_display_mode();
1975 #elif defined(_FM77_VARIANTS)
1977 int oldmode = display_mode;
1978 kanjisub = ((data & 0x20) == 0) ? true : false;
1979 # if defined(_FM77L4)
1980 stat_400linecard = ((data & 0x08) != 0) ? false : true;
1981 if(mode400line && stat_400linecard) {
1983 uint8_t *regs = l4crtc->get_regs();
1984 display_mode = DISPLAY_MODE_1_400L;
1985 if(event_id_l4_cursor_blink >= 0) {
1986 cancel_event(this, event_id_l4_cursor_blink);
1988 if(event_id_l4_text_blink >= 0) {
1989 cancel_event(this, event_id_l4_text_blink);
1991 event_id_l4_cursor_blink = -1;
1992 event_id_l4_text_blink = -1;
1994 usec = ((regs[10] & 0x20) == 0) ? 160.0 : 320.0;
1995 usec = usec * 1000.0;
1996 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
1997 usec = 160.0 * 1000.0;
1998 register_event(this, EVENT_FM7SUB_TEXT_BLINK, true, usec, &event_id_l4_cursor_blink);
2001 display_mode = DISPLAY_MODE_8_200L;
2003 if(oldmode != display_mode) {
2005 if(display_mode == DISPLAY_MODE_1_400L) {
2006 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2007 for(int y = 0; y < 400; y++) {
2008 pp = emu->get_screen_buffer(y);
2009 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2013 vm->set_vm_frame_rate(FRAMES_PER_SEC);
2014 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2015 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2016 for(int y = 0; y < 200; y++) {
2017 pp = emu->get_screen_buffer(y);
2018 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2021 for(int y = 0; y < 400; y++) {
2022 pp = emu->get_screen_buffer(y);
2023 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2028 setup_display_mode();
2035 #if defined(_FM77AV_VARIANTS)
2036 case SIG_DISPLAY_MODE320: // FD12 bit 6
2037 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2039 //printf("Wrote $FD12: %02x\n", data);
2040 int oldmode = display_mode;
2043 display_mode = DISPLAY_MODE_8_400L;
2044 } else if(mode256k) {
2045 display_mode = DISPLAY_MODE_256k;
2046 } else if(!(mode320) && !(mode256k)) {
2047 //display_mode = (mode400line) ? DISPLAY_MODE_8_400L : DISPLAY_MODE_8_200L;
2048 display_mode = DISPLAY_MODE_8_200L;
2050 display_mode = (mode256k) ? DISPLAY_MODE_256k : DISPLAY_MODE_4096;
2052 if(oldmode != display_mode) {
2054 if(mode320 || mode256k) {
2055 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
2056 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2057 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2058 for(y = 0; y < 200; y++) {
2059 pp = emu->get_screen_buffer(y);
2060 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
2063 for(y = 0; y < 400; y++) {
2064 pp = emu->get_screen_buffer(y);
2065 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2068 //emu->set_vm_screen_lines(200);
2069 } else { // 200 lines, 8 colors.
2070 if(display_mode == DISPLAY_MODE_8_400L) {
2071 if(oldmode != DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(55.40);
2073 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
2075 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2076 int ymax = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
2078 emu->set_vm_screen_size(640, ymax, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2079 for(y = 0; y < ymax; y++) {
2080 pp = emu->get_screen_buffer(y);
2081 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2084 for(y = 0; y < 400; y++) {
2085 pp = emu->get_screen_buffer(y);
2086 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2089 //emu->set_vm_screen_lines(200);
2092 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
2093 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
2094 call_write_signal(alu, SIG_ALU_400LINE, 0x00, 0xff);
2095 setup_display_mode();
2096 //frame_skip_count = 3;
2099 # else /* FM77AV/20/20EX */
2102 if(oldflag != mode320) {
2105 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2106 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2107 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 320 * sizeof(scrntype_t));
2109 for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2111 //emu->set_vm_screen_lines(200);
2113 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2114 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2115 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2117 for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2119 //emu->set_vm_screen_lines(200);
2122 display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
2123 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
2124 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
2125 call_write_signal(alu, SIG_ALU_400LINE, 0, 0xffffffff);
2127 setup_display_mode();
2132 case SIG_DISPLAY_MULTIPAGE:
2133 set_multimode(data);
2135 case SIG_FM7_SUB_KEY_MASK:
2136 if(firq_mask == flag) {
2137 do_firq(!flag && key_firq_req);
2141 case SIG_FM7_SUB_KEY_FIRQ:
2142 do_firq(flag & !(firq_mask));
2143 key_firq_req = flag;
2151 * Vram accessing functions moved to vram.cpp .
2154 uint32_t DISPLAY::read_mmio(uint32_t addr)
2156 uint32_t retval = 0xff;
2158 if(addr < 0xd400) return 0xff;
2160 #if !defined(_FM77AV_VARIANTS)
2161 raddr = (addr - 0xd400) & 0x000f;
2162 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2163 raddr = (addr - 0xd400) & 0x003f;
2164 #else // FM77AV40EX || FM77AV40SX
2165 raddr = (addr - 0xd400) & 0x00ff;
2168 case 0x00: // Read keyboard
2169 retval = (call_read_data8(keyboard, 0x00) != 0) ? 0xff : 0x7f;
2171 case 0x01: // Read keyboard
2172 retval = call_read_data8(keyboard, 0x01) & 0xff;
2174 case 0x02: // Acknowledge
2183 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2184 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2186 if(!kanjisub) return 0xff;
2187 # if !defined(_FM77_VARIANTS)
2189 return (uint8_t)call_read_data8(kanjiclass2, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
2192 if(kanjiclass1 != NULL) retval = call_read_data8(kanjiclass1, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
2195 if(!kanjisub) return 0xff;
2196 # if !defined(_FM77_VARIANTS)
2198 return (uint8_t)call_read_data8(kanjiclass2, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
2201 if(kanjiclass1 != NULL) retval = call_read_data8(kanjiclass1, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
2208 retval = set_vramaccess();
2211 { // If use CLR insn to set busy flag, clear flag at first, then delay and set flag.
2213 // Delay at least 3+ clocks (CLR <$0A )
2216 usec = (4000.0 * 1000.0) / 2000000.0;
2218 usec = (4000.0 * 1000.0) / 999000.0;
2220 register_event(this, EVENT_FM7SUB_CLEAR_DELAY, usec, false, NULL); // NEXT CYCLE_
2224 #if defined(_FM77L4)
2226 if(stat_400linecard) {
2227 retval = l4crtc->read_io8(0);
2231 if(stat_400linecard) {
2232 retval = l4crtc->read_io8(1);
2233 // Update parameters.
2238 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
2240 #if defined(_FM77AV_VARIANTS)
2243 retval = call_read_data8(alu, ALU_CMDREG);
2246 retval = call_read_data8(alu, ALU_LOGICAL_COLOR);
2249 retval = call_read_data8(alu, ALU_WRITE_MASKREG);
2252 retval = call_read_data8(alu, ALU_CMP_STATUS_REG);
2255 retval = call_read_data8(alu, ALU_BANK_DISABLE);
2257 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2258 case 0x2f: // VRAM BANK
2259 retval = 0xfc | (vram_bank & 0x03);
2264 retval = get_miscreg();
2268 retval = call_read_data8(keyboard, 0x31);
2271 retval = call_read_data8(keyboard, 0x32);
2277 return (uint8_t)retval;
2280 uint32_t DISPLAY::read_vram_data8(uint32_t addr)
2284 uint32_t color = (addr >> 14) & 0x03;
2285 #if defined(_FM77L4)
2288 offset = offset_point;
2290 if(multimode_accessflags[2]) return 0xff;
2291 vramaddr = ((addr + offset) & 0x3fff) + 0x8000;
2292 return gvram[vramaddr];
2296 return text_vram[addr & 0x0fff];
2297 } else if(addr < 0xc000) {
2298 return subsys_l4[addr - 0x9800];
2304 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2305 if(display_mode == DISPLAY_MODE_8_400L) {
2306 color = vram_bank & 0x03;
2307 if(color > 2) color = 0;
2309 color = (addr >> 14) & 0x03;
2313 //if((multimode_accessmask & (1 << color)) != 0) return 0xff;
2314 if(multimode_accessflags[color]) return 0xff;
2316 #if defined(_FM77AV_VARIANTS)
2317 if (active_page != 0) {
2318 offset = offset_point_bank1;
2320 offset = offset_point;
2323 offset = offset_point;
2325 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2326 if(vram_active_block != 0) {
2327 if(display_mode != DISPLAY_MODE_256k) offset = 0; // Don't scroll at BLOCK 1.
2330 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2331 if(display_mode == DISPLAY_MODE_8_400L) {
2333 uint32_t page_offset_alt = 0;
2334 if(addr >= 0x8000) return 0xff;
2335 color = vram_bank & 0x03;
2336 if(color > 2) color = 0;
2338 pagemod = 0x8000 * color;
2339 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2340 if(vram_active_block != 0) page_offset = 0x18000;
2342 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2343 return gvram[vramaddr];
2346 uint32_t page_offset_alt;
2347 #if defined(_FM77AV40)
2349 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2351 page_offset_alt = 0; // right?
2354 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2356 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
2357 //page_mask = 0x1fff;
2358 //pagemod = addr & 0xe000;
2360 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2362 return gvram[vramaddr];
2364 #elif defined(_FM77AV_VARIANTS)
2366 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2367 return gvram[vramaddr];
2369 #elif defined(_FM77L4) //_FM77L4
2372 vramaddr = (addr + offset) & 0x7fff;
2373 return gvram[vramaddr];
2375 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2376 return gvram[vramaddr];
2380 #else // Others (77/7/8)
2381 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2382 return gvram[vramaddr];
2386 void DISPLAY::write_dma_data8(uint32_t addr, uint32_t data)
2388 uint32_t raddr = (addr & 0xffff) >> 7;
2389 if(write_dma_func_table[raddr] != NULL) {
2390 (this->*write_dma_func_table[raddr])(addr, (uint8_t) data);
2394 void DISPLAY::write_vram_data8(uint32_t addr, uint8_t data)
2397 uint32_t color = (addr >> 14) & 0x03;
2401 #if defined(_FM77AV_VARIANTS)
2402 if (active_page != 0) {
2403 offset = offset_point_bank1;
2405 offset = offset_point;
2408 offset = offset_point;
2410 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2411 if(vram_active_block != 0) offset = 0; // Don't scroll at BLOCK 1.
2414 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2415 if(display_mode == DISPLAY_MODE_8_400L) {
2417 uint32_t page_offset_alt = 0;
2419 if(addr >= 0x8000) {
2422 color = vram_bank & 0x03;
2423 if(color > 2) color = 0;
2425 pagemod = 0x8000 * color;
2426 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2427 if(vram_active_block != 0) page_offset_alt = 0x18000;
2429 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2430 // Reduce data transfer.
2431 tdata = gvram[vramaddr];
2433 naddr = (addr & 0x7fff) >> 4;
2434 gvram[vramaddr] = data;
2435 vram_wrote_table[naddr] = true;
2437 } else if(display_mode == DISPLAY_MODE_256k) {
2438 uint32_t page_offset_alt;
2440 #if defined(_FM77AV40)
2442 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2444 page_offset_alt = 0; // right?
2447 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2449 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
2450 tdata = gvram[vramaddr];
2452 naddr = (addr & page_mask) >> 3;
2453 gvram[vramaddr] = data;
2454 vram_wrote_table[naddr] = true;
2457 } else if(display_mode == DISPLAY_MODE_4096) {
2459 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2460 tdata = gvram[vramaddr];
2462 naddr = (addr & page_mask) >> 3;
2463 gvram[vramaddr] = data;
2464 vram_wrote_table[naddr] = true;
2468 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2469 tdata = gvram[vramaddr];
2471 naddr = (addr & page_mask) >> 4;
2472 gvram[vramaddr] = data;
2473 vram_wrote_table[naddr] = true;
2476 #elif defined(_FM77AV_VARIANTS)
2477 if(display_mode == DISPLAY_MODE_4096) {
2479 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2480 tdata = gvram[vramaddr];
2482 naddr = (addr & page_mask) >> 3;
2483 gvram[vramaddr] = data;
2484 vram_wrote_table[naddr] = true;
2488 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2489 tdata = gvram[vramaddr];
2491 naddr = (addr & page_mask) >> 4;
2492 gvram[vramaddr] = data;
2493 vram_wrote_table[naddr] = true;
2496 #elif defined(_FM77L4) //_FM77L4
2497 if(display_mode == DISPLAY_MODE_1_400L) {
2500 //if(multimode_accessflags[2]) return;
2501 vramaddr = ((addr + offset) & 0x3fff) + 0x8000;
2502 gvram[vramaddr] = data;
2505 vramaddr = (addr + offset) & 0x7fff;
2506 tdata = gvram[vramaddr];
2508 naddr = (addr & 0x7fff) >> 4;
2509 gvram[vramaddr] = data;
2510 vram_wrote_table[naddr] = true;
2517 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2518 tdata = gvram[vramaddr];
2520 naddr = (addr & 0x3fff) >> 4;
2521 gvram[vramaddr] = data;
2522 vram_wrote_table[naddr] = true;
2525 #else // Others (77/7/8)
2528 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2529 tdata = gvram[vramaddr];
2531 naddr = (addr & 0x3fff) >> 4;
2532 gvram[vramaddr] = data;
2533 vram_wrote_table[naddr] = true;
2539 uint32_t DISPLAY::read_cpu_vram_data8(uint32_t addr)
2542 #if defined(_FM77AV_VARIANTS)
2544 call_read_data8(alu, addr);
2547 return read_vram_data8(addr);
2550 uint32_t DISPLAY::read_dma_vram_data8(uint32_t addr)
2552 return read_vram_data8(addr);
2555 void DISPLAY::init_read_table(void)
2558 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
2559 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cpu_vram_data8;
2560 read_dma_func_table[_at >> 7] = &DISPLAY::read_dma_vram_data8;
2562 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
2563 read_cpu_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2564 read_dma_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2566 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
2567 read_cpu_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2568 read_dma_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2570 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
2571 read_cpu_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2572 read_dma_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2574 #if defined(_FM77AV_VARIANTS)
2575 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
2576 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2577 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2579 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
2580 read_cpu_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2581 read_dma_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2584 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
2585 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2586 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2589 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
2590 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2591 read_dma_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2593 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
2594 read_cpu_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2595 read_dma_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2599 uint32_t DISPLAY::read_console_ram(uint32_t addr)
2601 uint32_t raddr = addr & 0xfff;
2602 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2604 if(console_ram_bank >= 1) {
2605 return submem_console_av40[((console_ram_bank - 1) << 12) + raddr];
2609 return console_ram[raddr];
2612 uint32_t DISPLAY::read_work_ram(uint32_t addr)
2614 addr = addr & 0x3ff;
2615 return work_ram[addr];
2619 uint32_t DISPLAY::read_shared_ram(uint32_t addr)
2621 addr = addr - 0xd380;
2622 return shared_ram[addr];
2625 #if defined(_FM77AV_VARIANTS)
2626 uint32_t DISPLAY::read_hidden_ram(uint32_t addr)
2628 if(addr >= 0xd500) {
2629 return submem_hidden[addr - 0xd500];
2635 uint32_t DISPLAY::read_cgrom(uint32_t addr)
2637 #if defined(_FM77AV_VARIANTS)
2638 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2640 return submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)]; //FIXME
2643 return subsys_cg[(addr - 0xd800) + cgrom_bank * 0x800];
2645 return subsys_c[addr - 0xd800];
2649 uint32_t DISPLAY::read_subsys_monitor(uint32_t addr)
2651 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2653 return subsys_ram[addr - 0xe000];
2656 #if defined(_FM77AV_VARIANTS)
2657 switch(subrom_bank_using & 3) {
2659 return subsys_c[addr - 0xd800];
2662 return subsys_a[addr - 0xe000];
2665 return subsys_b[addr - 0xe000];
2668 return subsys_cg[addr - 0xe000];
2671 #elif defined(_FM77L4)
2673 return subsys_l4[addr - 0xb800];
2675 return subsys_c[addr - 0xd800];
2677 return subsys_c[addr - 0xd800];
2681 uint32_t DISPLAY::read_dma_data8(uint32_t addr)
2683 uint32_t raddr = (addr & 0xffff) >> 7;
2684 if(read_dma_func_table[raddr] != NULL) {
2685 return (this->*read_dma_func_table[raddr])(addr);
2690 uint32_t DISPLAY::read_data8(uint32_t addr)
2692 uint32_t raddr = addr;
2694 if(addr < 0x10000) {
2695 raddr = (addr & 0xffff) >> 7;
2696 if(read_cpu_func_table[raddr] != NULL) {
2697 return (this->*read_cpu_func_table[raddr])(addr);
2702 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2703 return dpalette_data[addr - FM7_SUBMEM_OFFSET_DPALETTE];
2706 #if defined(_FM77AV_VARIANTS)
2708 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2709 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2710 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2711 if(vram_active_block != 0) {
2715 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2716 if(display_mode == DISPLAY_MODE_8_400L) {
2717 uint32_t page_offset_alt = 0;
2720 color = (addr & 0x18000) >> 15;
2721 if(color > 2) color = 0;
2722 pagemod = 0x8000 * color;
2723 if (active_page != 0) {
2724 offset = offset_point_bank1 << 1;
2726 offset = offset_point << 1;
2728 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2729 if(vram_active_block != 0) {
2730 page_offset_alt = 0x18000;
2734 return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset_alt];
2737 return read_vram_data8(addr);
2744 * Vram accessing functions moved to vram.cpp .
2747 void DISPLAY::write_mmio(uint32_t addr, uint8_t data)
2750 uint8_t active_block_old;
2752 if(addr < 0xd400) return;
2754 #if !defined(_FM77AV_VARIANTS)
2755 addr = (addr - 0xd400) & 0x000f;
2756 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2757 addr = (addr - 0xd400) & 0x003f;
2758 #else // FM77AV40EX || FM77AV40SX
2759 addr = (addr - 0xd400) & 0x00ff;
2761 io_w_latch[addr] = (uint8_t)data;
2763 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4)
2766 set_cyclesteal((uint8_t)data);
2767 # if defined(_FM77L4)
2768 setup_400linemode((uint8_t)data);
2772 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2773 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2776 if(!kanjisub) return;
2777 kanjiaddr.w.h = 0x0000;
2778 kanjiaddr.b.h = (uint8_t) data;
2781 if(!kanjisub) return;
2782 kanjiaddr.w.h = 0x0000;
2783 kanjiaddr.b.l = (uint8_t)data;
2796 if(delay_busy) { // If WRITE after READ immediately.Perhaps use CLR insn.
2798 // Delay at least 5+ clocks (CLR $D40A or CLR (INDEX = $D40A))
2800 usec = (6000.0 * 1000.0) / 2000000.0;
2802 usec = (6000.0 * 1000.0) / 999000.0;
2804 register_event(this, EVENT_FM7SUB_DELAY_BUSY, usec, false, NULL); // NEXT CYCLE_
2812 #if defined(_FM77L4)
2814 if(stat_400linecard) {
2815 l4crtc->write_io8(0, data & 0x1f);
2819 if(stat_400linecard) {
2820 l4crtc->write_io8(1, data);
2821 // Update parameters.
2822 uint8_t crtc_addr = l4crtc->read_io8(0);
2823 const uint8_t *regs = l4crtc->get_regs();
2824 switch(crtc_addr & 0x1f) {
2827 cursor_addr.w.l &= 0x0ffc;
2828 cursor_addr.w.l |= (((uint16_t)regs[14]) << 10);
2829 cursor_addr.w.l |= (((uint16_t)regs[15]) << 2);
2831 cursor_addr.w.l += 2;
2833 cursor_addr.w.l &= 0xfff;
2835 if((crtc_addr & 0x1f) == 10) {
2837 if(event_id_l4_cursor_blink >= 0) {
2838 cancel_event(this, event_id_l4_cursor_blink);
2840 usec = ((data & 0x20) == 0) ? 160.0 : 320.0;
2841 usec = usec * 1000.0;
2842 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
2846 text_start_addr.w.l &= 0x03fc;
2847 text_start_addr.w.l |= (((uint16_t)data & 3) << 10);
2848 text_scroll_count++;
2849 if((text_scroll_count & 1) == 0) {
2854 text_start_addr.w.l &= 0xfc00;
2855 text_start_addr.w.l |= ((uint16_t)data << 2);
2856 text_scroll_count++;
2857 if((text_scroll_count & 1) == 0) {
2862 text_scroll_count++;
2863 if((text_scroll_count & 1) == 0) {
2865 cursor_addr.w.l &= 0x0ffc;
2866 cursor_addr.w.l |= (((uint16_t)regs[14]) << 10);
2867 cursor_addr.w.l |= (((uint16_t)regs[15]) << 2);
2869 cursor_addr.w.l += 2;
2871 cursor_addr.w.l &= 0xfff;
2882 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
2887 rval = (uint8_t)data;
2888 if(offset_changed[active_page]) {
2889 #if defined(_FM77AV_VARIANTS)
2890 if(active_page != 0) {
2891 tmp_offset_point[active_page].d = offset_point_bank1;
2893 tmp_offset_point[active_page].d = offset_point;
2896 tmp_offset_point[active_page].d = offset_point;
2899 tmp_offset_point[active_page].w.h = 0x0000;
2901 tmp_offset_point[active_page].b.h = rval;
2903 tmp_offset_point[active_page].b.l = rval;
2905 offset_changed[active_page] = !offset_changed[active_page];
2906 if(offset_changed[active_page]) {
2908 #if defined(_FM77AV_VARIANTS)
2909 if(active_page != 0) {
2911 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fff;
2913 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fe0;
2917 offset_point = tmp_offset_point[active_page].d & 0x007fff;
2919 offset_point = tmp_offset_point[active_page].d & 0x007fe0;
2923 offset_point = tmp_offset_point[active_page].d & 0x7fe0;
2927 #if defined(_FM77AV_VARIANTS)
2930 alu_write_cmdreg(data);
2933 alu_write_logical_color(data);
2936 alu_write_mask_reg(data);
2939 alu_write_disable_reg(data);
2942 alu_write_offsetreg_hi(data);
2945 alu_write_offsetreg_lo(data);
2948 alu_write_linepattern_hi(data);
2951 alu_write_linepattern_lo(data);
2953 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2955 console_ram_bank = (data & 0x18) >> 3;
2956 if(console_ram_bank > 2) console_ram_bank = 0;
2957 cgram_bank = data & 0x07;
2958 kanji_level2 = ((data & 0x80) == 0) ? false : true;
2960 case 0x2f: // VRAM BANK
2961 vram_bank = data & 0x03;
2962 if(vram_bank > 2) vram_bank = 0;
2972 call_write_data8(keyboard, 0x31, data);
2974 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2976 active_block_old = vram_active_block;
2977 vram_active_block = data & 0x01;
2978 if(vram_display_block != (((data & 0x10) != 0) ? 1 : 0)) vram_wrote = true;
2979 vram_display_block = ((data & 0x10) != 0) ? 1 : 0;
2980 if(vram_active_block != active_block_old) setup_display_mode();
2985 tmpvar.d = window_xbegin * 8;
2988 tmpvar.b.h = data & 0x03;
2990 tmpvar.b.l = data & 0xf8;
2992 if(mode320 || mode256k) {
2993 if(tmpvar.d > 320) tmpvar.d = 320;
2995 if(tmpvar.d > 640) tmpvar.d = 640;
2997 window_xbegin = tmpvar.d / 8;
3002 tmpvar.d = window_xend * 8;
3005 tmpvar.b.h = data & 0x03;
3007 tmpvar.b.l = data & 0xf8;
3009 if(mode320 || mode256k) {
3010 if(tmpvar.d > 320) tmpvar.d = 320;
3012 if(tmpvar.d > 640) tmpvar.d = 640;
3014 window_xend = tmpvar.d / 8;
3019 tmpvar.d = window_low;
3022 tmpvar.b.h = data & 0x03;
3024 tmpvar.b.l = data & 0xff;
3026 if(display_mode == DISPLAY_MODE_8_400L) {
3027 if(tmpvar.d > 400) tmpvar.d = 400;
3030 if(tmpvar.d > 400) tmpvar.d = 400;
3032 window_low = tmpvar.d;
3037 tmpvar.d = window_high;
3040 tmpvar.b.h = data & 0x03;
3042 tmpvar.b.l = data & 0xff;
3044 if(display_mode == DISPLAY_MODE_8_400L) {
3045 if(tmpvar.d > 400) tmpvar.d = 400;
3048 if(tmpvar.d > 400) tmpvar.d = 400;
3050 window_high = tmpvar.d;
3056 #if defined(_FM77AV_VARIANTS)
3058 if((addr >= 0x13) && (addr <= 0x1a)) {
3059 alu_write_cmpdata_reg(addr - 0x13, data);
3060 } else if((addr >= 0x1c) && (addr <= 0x1e)) {
3061 alu_write_tilepaint_data(addr, data);
3062 } else if((addr >= 0x24) && (addr <= 0x2b)) {
3063 alu_write_line_position(addr - 0x24, data);
3070 void DISPLAY::init_write_table(void)
3073 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
3074 write_cpu_func_table[_at >> 7] = &DISPLAY::write_cpu_vram_data8;
3075 write_dma_func_table[_at >> 7] = &DISPLAY::write_dma_vram_data8;
3077 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
3078 write_cpu_func_table[_at >> 7] = &DISPLAY::write_console_ram;
3079 write_dma_func_table[_at >> 7] = &DISPLAY::write_console_ram;
3081 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
3082 write_cpu_func_table[_at >> 7] = &DISPLAY::write_work_ram;
3083 write_dma_func_table[_at >> 7] = &DISPLAY::write_work_ram;
3085 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
3086 write_cpu_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
3087 write_dma_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
3089 #if defined(_FM77AV_VARIANTS)
3090 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
3091 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
3092 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
3094 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
3095 write_cpu_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
3096 write_dma_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
3099 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
3100 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
3101 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
3104 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
3105 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
3106 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
3107 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
3109 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
3110 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
3111 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
3114 for(_at = 0xd800; _at < 0x10000; _at += 0x80) {
3115 write_cpu_func_table[_at >> 7] = &DISPLAY::write_dummy;
3116 write_dma_func_table[_at >> 7] = &DISPLAY::write_dummy;
3121 void DISPLAY::write_console_ram(uint32_t addr, uint8_t data)
3123 uint32_t raddr = addr & 0xfff;
3124 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3126 if(console_ram_bank >= 1) {
3127 submem_console_av40[((console_ram_bank - 1) << 12) + raddr] = data;
3132 console_ram[raddr] = data;
3136 void DISPLAY::write_work_ram(uint32_t addr, uint8_t data)
3138 uint32_t raddr = addr & 0xfff;
3139 work_ram[raddr] = data;
3143 void DISPLAY::write_shared_ram(uint32_t addr, uint8_t data)
3145 uint32_t raddr = addr & 0x7f;
3146 shared_ram[raddr] = data;
3150 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
3151 void DISPLAY::write_subsys_cgram(uint32_t addr, uint8_t data)
3153 uint32_t raddr = addr - 0xd800;
3154 if(ram_protect) return;
3155 if(!monitor_ram) return;
3156 submem_cgram[cgram_bank * 0x0800 + raddr] = data; //FIXME
3159 void DISPLAY::write_subsys_ram(uint32_t addr, uint8_t data)
3161 if(ram_protect) return;
3162 if(!monitor_ram) return;
3163 subsys_ram[addr - 0xe000] = data; //FIXME
3167 #if defined(_FM77AV_VARIANTS)
3168 void DISPLAY::write_hidden_ram(uint32_t addr, uint8_t data)
3170 submem_hidden[addr - 0xd500] = data;
3175 void DISPLAY::write_cpu_vram_data8(uint32_t addr, uint8_t data)
3177 uint32_t color = (addr & 0xc000) >> 14;
3178 #if defined(_FM77AV_VARIANTS)
3180 call_read_data8(alu, addr);
3184 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3185 if(display_mode == DISPLAY_MODE_8_400L) {
3186 color = vram_bank & 0x03;
3187 if(color > 2) color = 0;
3190 #if defined(_FM77L4)
3194 if(!(multimode_accessflags[2])) write_vram_data8(addr & 0x7fff, data);
3197 } else if(addr < 0x9800) {
3200 addr = addr & 0x0fff;
3201 if(text_vram[addr] != data) {
3202 text_vram[addr] = data;
3204 x = ((addr / 2) % 40) / 8;
3205 y = (addr / 2) / 40;
3206 } else { // Width 80
3207 x = ((addr / 2) % 80) / 8;
3208 y = (addr / 2) / 80;
3210 for(int yy = 0; yy < 8; yy++) {
3211 naddr = (y + yy) * 5 + x;
3212 vram_wrote_table[naddr] = true;
3222 //if((multimode_accessmask & (1 << color)) != 0) return;
3223 if(multimode_accessflags[color]) return;
3225 write_vram_data8(addr & 0xffff, data);
3228 void DISPLAY::write_dma_vram_data8(uint32_t addr, uint8_t data)
3230 uint32_t color = (addr & 0xc000) >> 14;
3231 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3232 if(display_mode == DISPLAY_MODE_8_400L) {
3233 color = vram_bank & 0x03;
3234 if(color > 2) color = 0;
3238 //if((multimode_accessmask & (1 << color)) != 0) return;
3239 if(multimode_accessflags[color]) return;
3241 write_vram_data8(addr & 0xffff, data);
3244 void DISPLAY::write_dummy(uint32_t addr, uint8_t data)
3248 void DISPLAY::write_data8(uint32_t addr, uint32_t data)
3252 //uint32_t page_offset = 0x0000;
3253 uint8_t val8 = data & 0xff;
3254 uint32_t color = (addr & 0xc000) >> 14;
3257 if(addr < 0x10000) {
3258 void (*_write_func)(uint32_t, uint32_t);
3259 raddr = (addr & 0xffff) >> 7;
3260 if(write_cpu_func_table[raddr] != NULL) {
3261 (this->*write_cpu_func_table[raddr])(addr, (uint8_t)data);
3267 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
3268 set_dpalette(addr - FM7_SUBMEM_OFFSET_DPALETTE, val8);
3272 #if defined(_FM77AV_VARIANTS)
3274 else if(addr == FM7_SUBMEM_OFFSET_APALETTE_R) {
3275 set_apalette_r(val8);
3277 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_G) {
3278 set_apalette_g(val8);
3280 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_B) {
3281 set_apalette_b(val8);
3283 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_HI) {
3284 set_apalette_index_hi(val8);
3286 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_LO) {
3287 set_apalette_index_lo(val8);
3291 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
3292 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
3293 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3294 if(display_mode == DISPLAY_MODE_8_400L) {
3297 uint32_t page_offset_alt = 0;
3299 color = (addr & 0x18000) >> 15;
3300 if(color > 2) color = 0;
3301 if (active_page != 0) {
3302 offset = offset_point_bank1 << 1;
3304 offset = offset_point << 1;
3306 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3307 if(vram_active_block != 0) {
3308 page_offset_alt = 0x18000;
3312 naddr = (addr & 0x7fff) >> 4;
3313 pagemod = 0x8000 * color;
3314 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
3315 tdata = gvram[vramaddr];
3316 if(tdata != (uint8_t)data) {
3317 gvram[vramaddr] = data;
3318 vram_wrote_table[naddr] = true;
3322 write_vram_data8(addr, data);
3324 write_vram_data8(addr, data);
3326 //if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
3333 uint32_t DISPLAY::read_bios(const _TCHAR *name, uint8_t *ptr, uint32_t size)
3339 if((name == NULL) || (ptr == NULL)) return 0;
3340 s = create_local_path(name);
3341 if(s == NULL) return 0;
3343 if(!fio.Fopen(s, FILEIO_READ_BINARY)) return 0;
3344 blocks = fio.Fread(ptr, size, 1);
3347 return blocks * size;
3351 void DISPLAY::initialize()
3355 memset(io_w_latch, 0xff, sizeof(io_w_latch));
3356 screen_update_flag = true;
3357 memset(gvram, 0x00, sizeof(gvram));
3358 vram_wrote_shadow = false;
3359 memset(gvram_shadow, 0x00, sizeof(gvram_shadow));
3360 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
3361 for(i = 0; i < 411; i++) vram_draw_table[i] = false;
3362 force_update = false;
3364 memset(console_ram, 0x00, sizeof(console_ram));
3365 memset(work_ram, 0x00, sizeof(work_ram));
3366 memset(shared_ram, 0x00, sizeof(shared_ram));
3367 memset(subsys_c, 0xff, sizeof(subsys_c));
3368 need_transfer_line = true;
3369 frame_skip_count_draw = 3;
3370 frame_skip_count_transfer = 3;
3372 diag_load_subrom_c = false;
3374 if(read_bios(_T(ROM_FM8_SUBSYSTEM), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
3375 this->out_debug_log(_T("SUBSYSTEM ROM READING : %s"), diag_load_subrom_c ? "OK" : "NG");
3377 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_C), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
3378 this->out_debug_log(_T("SUBSYSTEM ROM Type C READING : %s"), diag_load_subrom_c ? "OK" : "NG");
3380 #if defined(_FM77AV_VARIANTS)
3381 memset(subsys_a, 0xff, sizeof(subsys_a));
3382 memset(subsys_b, 0xff, sizeof(subsys_b));
3383 memset(subsys_cg, 0xff, sizeof(subsys_cg));
3384 memset(submem_hidden, 0x00, sizeof(submem_hidden));
3386 diag_load_subrom_a = false;
3387 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_A), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
3388 this->out_debug_log(_T("SUBSYSTEM ROM Type A READING : %s"), diag_load_subrom_a ? "OK" : "NG");
3390 diag_load_subrom_b = false;
3391 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_B), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
3392 this->out_debug_log(_T("SUBSYSTEM ROM Type B READING : %s"), diag_load_subrom_b ? "OK" : "NG");
3394 diag_load_subrom_cg = false;
3395 if(read_bios(_T(ROM_FM7_SUBSYSTEM_CG), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
3396 this->out_debug_log(_T("SUBSYSTEM CG ROM READING : %s"), diag_load_subrom_cg ? "OK" : "NG");
3397 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
3398 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3399 memset(subsys_ram, 0x00, sizeof(subsys_ram));
3400 memset(submem_cgram, 0x00, sizeof(submem_cgram));
3401 memset(submem_console_av40, 0x00, sizeof(submem_console_av40));
3405 #if defined(_FM77L4)
3406 memset(subsys_cg_l4, 0xff, sizeof(subsys_cg_l4));
3407 memset(subsys_l4, 0xff, sizeof(subsys_l4));
3409 read_bios(_T(ROM_FM77_400LINE_ANKCG), subsys_cg_l4, sizeof(subsys_cg_l4));
3410 read_bios(_T(ROM_FM77_400LINE_SUBSYS), subsys_l4, sizeof(subsys_l4));
3411 memset(text_vram, 0x00, sizeof(text_vram));
3412 //memset(crtc_regs, 0x00, sizeof(crtc_regs));
3416 text_width40 = false;
3419 cursor_blink = true;
3421 text_start_addr.d = 0x0000;
3429 text_scroll_count = 0;
3431 event_id_l4_cursor_blink = -1;
3432 event_id_l4_text_blink = -1;
3438 #if defined(_FM77AV_VARIANTS)
3440 apalette_index.d = 0;
3441 for(i = 0; i < 4096; i++) {
3442 analog_palette_r[i] = i & 0x0f0;
3443 analog_palette_g[i] = (i & 0xf00) >> 4;
3444 analog_palette_b[i] = (i & 0x00f) << 4;
3446 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
3449 for(i = 0; i < 8; i++) set_dpalette(i, i);
3450 #if defined(USE_GREEN_DISPLAY)
3451 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3452 use_green_monitor = false;
3455 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3456 //#if defined(_FM77AV_VARIANTS)
3457 hblank_event_id = -1;
3458 hdisp_event_id = -1;
3459 vsync_event_id = -1;
3460 vstart_event_id = -1;
3467 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
3468 is_cyclesteal = true;
3470 is_cyclesteal = false;
3472 multimode_accessmask = multimode_dispmask = 0;
3473 for(i = 0; i < 4; i++) {
3474 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
3475 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
3478 prev_clock = SUBCLOCK_NORMAL;
3482 key_firq_req = false; //firq_mask = true;
3483 frame_skip_count_transfer = 3;
3484 frame_skip_count_draw = 3;
3485 #if !defined(FIXED_FRAMEBUFFER_SIZE)
3486 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
3488 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
3490 emu->set_vm_screen_lines(200);
3491 #if defined(_FM77AV40SX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3492 mode400line = false;
3494 #elif defined(_FM77L4)
3495 mode400line = false;
3498 palette_changed = true;
3499 //#if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
3500 //register_vline_event(this);
3501 register_frame_event(this);
3503 setup_display_mode();
3506 void DISPLAY::release()
3510 #define STATE_VERSION 12
3511 void DISPLAY::decl_state(void)
3513 enter_decl_state(STATE_VERSION);
3514 DECL_STATE_ENTRY_INT(this_device_id);
3517 DECL_STATE_ENTRY_BOOL(delay_busy);
3518 DECL_STATE_ENTRY_BOOL(halt_flag);
3519 DECL_STATE_ENTRY_INT32(active_page);
3520 DECL_STATE_ENTRY_BOOL(sub_busy);
3521 DECL_STATE_ENTRY_BOOL(crt_flag);
3522 DECL_STATE_ENTRY_BOOL(vram_wrote);
3523 DECL_STATE_ENTRY_BOOL(is_cyclesteal);
3525 DECL_STATE_ENTRY_BOOL(clock_fast);
3527 #if defined(_FM77AV_VARIANTS)
3528 DECL_STATE_ENTRY_BOOL(subcpu_resetreq);
3529 DECL_STATE_ENTRY_BOOL(power_on_reset);
3531 DECL_STATE_ENTRY_BOOL(cancel_request);
3532 DECL_STATE_ENTRY_BOOL(key_firq_req);
3534 DECL_STATE_ENTRY_INT32(display_mode);
3535 DECL_STATE_ENTRY_UINT32(prev_clock);
3538 DECL_STATE_ENTRY_MULTI(void, dpalette_data, sizeof(dpalette_data));
3539 DECL_STATE_ENTRY_UINT8(multimode_accessmask);
3540 DECL_STATE_ENTRY_UINT8(multimode_dispmask);
3542 DECL_STATE_ENTRY_UINT32(offset_point);
3543 #if defined(_FM77AV_VARIANTS)
3544 DECL_STATE_ENTRY_UINT32(offset_point_bank1);
3546 //for(i = 0; i < 2; i++) {
3547 DECL_STATE_ENTRY_PAIR_ARRAY(tmp_offset_point, 2);
3548 DECL_STATE_ENTRY_BOOL_ARRAY(offset_changed, 2);
3550 DECL_STATE_ENTRY_BOOL(offset_77av);
3551 DECL_STATE_ENTRY_BOOL(diag_load_subrom_c);
3554 DECL_STATE_ENTRY_MULTI(void, io_w_latch, sizeof(io_w_latch));
3555 DECL_STATE_ENTRY_MULTI(void, console_ram, sizeof(console_ram));
3556 DECL_STATE_ENTRY_MULTI(void, work_ram, sizeof(work_ram));
3557 DECL_STATE_ENTRY_MULTI(void, shared_ram, sizeof(shared_ram));
3558 DECL_STATE_ENTRY_MULTI(void, subsys_c, sizeof(subsys_c));
3559 DECL_STATE_ENTRY_MULTI(void, gvram, sizeof(gvram));
3560 DECL_STATE_ENTRY_MULTI(void, gvram_shadow, sizeof(gvram_shadow));
3562 #if defined(_FM77_VARIANTS)
3563 DECL_STATE_ENTRY_BOOL(kanjisub);
3564 DECL_STATE_ENTRY_PAIR(kanjiaddr);
3565 # if defined(_FM77L4)
3566 DECL_STATE_ENTRY_BOOL(mode400line);
3567 DECL_STATE_ENTRY_BOOL(stat_400linecard);
3569 #elif defined(_FM77AV_VARIANTS)
3570 DECL_STATE_ENTRY_BOOL(kanjisub);
3571 DECL_STATE_ENTRY_PAIR(kanjiaddr);
3573 DECL_STATE_ENTRY_BOOL(mode320);
3574 DECL_STATE_ENTRY_INT32(cgrom_bank);
3575 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3576 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3577 DECL_STATE_ENTRY_INT32(vram_bank);
3580 DECL_STATE_ENTRY_UINT32(displine);
3581 DECL_STATE_ENTRY_UINT8(subrom_bank);
3582 DECL_STATE_ENTRY_UINT8(subrom_bank_using);
3584 DECL_STATE_ENTRY_BOOL(nmi_enable);
3585 DECL_STATE_ENTRY_BOOL(use_alu);
3587 DECL_STATE_ENTRY_PAIR(apalette_index);
3588 DECL_STATE_ENTRY_MULTI(void, analog_palette_r, sizeof(analog_palette_r));
3589 DECL_STATE_ENTRY_MULTI(void, analog_palette_g, sizeof(analog_palette_g));
3590 DECL_STATE_ENTRY_MULTI(void, analog_palette_b, sizeof(analog_palette_b));
3593 DECL_STATE_ENTRY_BOOL(diag_load_subrom_a);
3594 DECL_STATE_ENTRY_BOOL(diag_load_subrom_b);
3595 DECL_STATE_ENTRY_BOOL(diag_load_subrom_cg);
3597 DECL_STATE_ENTRY_MULTI(void, subsys_a, sizeof(subsys_a));
3598 DECL_STATE_ENTRY_MULTI(void, subsys_b, sizeof(subsys_b));
3599 DECL_STATE_ENTRY_MULTI(void, subsys_cg, sizeof(subsys_cg));
3600 DECL_STATE_ENTRY_MULTI(void, submem_hidden, sizeof(submem_hidden));
3601 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3602 DECL_STATE_ENTRY_BOOL(mode400line);
3603 DECL_STATE_ENTRY_BOOL(mode256k);
3605 DECL_STATE_ENTRY_BOOL(monitor_ram);
3606 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3607 DECL_STATE_ENTRY_UINT16(window_low);
3608 DECL_STATE_ENTRY_UINT16(window_high);
3609 DECL_STATE_ENTRY_UINT16(window_xbegin);
3610 DECL_STATE_ENTRY_UINT16(window_xend);
3611 DECL_STATE_ENTRY_BOOL(window_opened);
3613 DECL_STATE_ENTRY_BOOL(kanji_level2);
3615 DECL_STATE_ENTRY_UINT8(vram_active_block);
3616 DECL_STATE_ENTRY_UINT8(vram_display_block);
3617 DECL_STATE_ENTRY_UINT8(console_ram_bank);
3618 DECL_STATE_ENTRY_BOOL(ram_protect);
3620 DECL_STATE_ENTRY_UINT8(cgram_bank);
3621 DECL_STATE_ENTRY_MULTI(void, subsys_ram, sizeof(subsys_ram));
3622 DECL_STATE_ENTRY_MULTI(void, submem_cgram, sizeof(submem_cgram));
3623 DECL_STATE_ENTRY_MULTI(void, submem_console_av40, sizeof(submem_console_av40));
3629 DECL_STATE_ENTRY_INT32(nmi_event_id);
3630 //#if defined(_FM77AV_VARIANTS)
3631 DECL_STATE_ENTRY_INT32(hblank_event_id);
3632 DECL_STATE_ENTRY_INT32(hdisp_event_id);
3633 DECL_STATE_ENTRY_INT32(vsync_event_id);
3634 DECL_STATE_ENTRY_INT32(vstart_event_id);
3636 DECL_STATE_ENTRY_BOOL(firq_mask);
3637 DECL_STATE_ENTRY_BOOL(vram_accessflag);
3639 DECL_STATE_ENTRY_INT8(display_page);
3640 DECL_STATE_ENTRY_INT8(display_page_bak);
3642 DECL_STATE_ENTRY_BOOL(vblank);
3643 DECL_STATE_ENTRY_BOOL(vsync);
3644 DECL_STATE_ENTRY_BOOL(hblank);
3645 DECL_STATE_ENTRY_INT32(vblank_count);
3647 #if defined(_FM77L4)
3648 DECL_STATE_ENTRY_MULTI(void, subsys_cg_l4, sizeof(subsys_cg_l4));
3649 DECL_STATE_ENTRY_MULTI(void, subsys_l4, sizeof(subsys_l4));
3650 DECL_STATE_ENTRY_MULTI(void, text_vram, sizeof(text_vram));
3651 //state_fio->Fwrite(crtc_regs, sizeof(crtc_regs), 1);
3653 DECL_STATE_ENTRY_BOOL(workram_l4);
3654 DECL_STATE_ENTRY_BOOL(cursor_lsb);
3655 DECL_STATE_ENTRY_BOOL(text_width40);
3657 DECL_STATE_ENTRY_BOOL(text_blink);
3658 DECL_STATE_ENTRY_BOOL(cursor_blink);
3660 DECL_STATE_ENTRY_PAIR(text_start_addr);
3661 DECL_STATE_ENTRY_UINT32(text_lines);
3662 DECL_STATE_ENTRY_UINT32(text_xmax);
3664 DECL_STATE_ENTRY_PAIR(cursor_addr);
3665 DECL_STATE_ENTRY_INT32(cursor_start);
3666 DECL_STATE_ENTRY_INT32(cursor_end);
3667 DECL_STATE_ENTRY_UINT8(cursor_type);
3668 DECL_STATE_ENTRY_UINT8(text_scroll_count);
3670 DECL_STATE_ENTRY_INT32(event_id_l4_cursor_blink);
3671 DECL_STATE_ENTRY_INT32(event_id_l4_text_blink);
3676 void DISPLAY::save_state(FILEIO *state_fio)
3678 if(state_entry != NULL) state_entry->save_state(state_fio);
3681 bool DISPLAY::load_state(FILEIO *state_fio)
3684 if(state_entry != NULL) {
3685 mb = state_entry->load_state(state_fio);
3687 this->out_debug_log(_T("Load State: DISPLAY : id=%d stat=%s"), this_device_id, (mb) ? _T("OK") : _T("NG"));
3688 if(!mb) return false;
3693 crt_flag_bak = true;
3694 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
3695 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
3697 for(addr = 0; addr < 8; addr++) set_dpalette(addr, addr);
3698 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3699 #if defined(USE_GREEN_DISPLAY)
3700 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3704 for(addr = 0; addr < 8; addr++) set_dpalette(addr, dpalette_data[addr]);
3705 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3706 #if defined(USE_GREEN_DISPLAY)
3707 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3709 for(i = 0; i < 4; i++) {
3710 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
3711 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
3714 #if defined(_FM77_VARIANTS)
3715 # if defined(_FM77L4)
3717 #elif defined(_FM77AV_VARIANTS)
3718 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3719 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3721 screen_update_flag = true;
3722 for(i = 0; i < 4096; i++) calc_apalette(i);
3723 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
3726 palette_changed = true;
3727 vram_wrote_shadow = true; // Force Draw
3728 this->draw_screen();
3730 frame_skip_count_draw = 3;
3731 frame_skip_count_transfer = 3;
3732 need_transfer_line = true;
3733 #if defined(USE_GREEN_DISPLAY) && defined(USE_MONITOR_TYPE)
3734 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3735 switch(config.monitor_type) {
3736 case FM7_MONITOR_GREEN:
3737 use_green_monitor = true;
3739 case FM7_MONITOR_STANDARD:
3741 use_green_monitor = false;
3745 //use_green_monitor = false;
3747 force_update = true;
3748 setup_display_mode();