2 * Common source code project -> FM-7 -> Display
3 * (C) 2015 K.Ohta <whatisthis.sowhat _at_ gmail.com>
5 * Feb 10, 2015 : Initial.
10 #include "../../fileio.h"
11 #include "fm7_display.h"
12 #if defined(_FM77AV_VARIANTS)
13 # include "mb61vh010.h"
16 #include "../hd46505.h"
19 #include "fm7_mainio.h"
20 #include "./fm7_keyboard.h"
21 #include "./kanjirom.h"
25 DISPLAY::DISPLAY(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
30 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
33 #elif defined(_FM77_VARIANTS)
36 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
37 kanjisub = false; // fix by Ryu Takegami
39 #if defined(_FM77AV_VARIANTS)
46 PrepareBitTransTableUint16((_bit_trans_table_t*)(&(bit_trans_table_0[0][0])), 0x0080, 0x0000);
47 PrepareBitTransTableUint16((_bit_trans_table_t*)(&(bit_trans_table_1[0][0])), 0x0040, 0x0000);
48 PrepareBitTransTableUint16((_bit_trans_table_t*)(&(bit_trans_table_2[0][0])), 0x0020, 0x0000);
49 PrepareBitTransTableUint16((_bit_trans_table_t*)(&(bit_trans_table_3[0][0])), 0x0010, 0x0000);
50 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
51 PrepareBitTransTableUint16((_bit_trans_table_t*)(&(bit_trans_table_4[0][0])), 0x0008, 0x0000);
52 PrepareBitTransTableUint16((_bit_trans_table_t*)(&(bit_trans_table_5[0][0])), 0x0004, 0x0000);
55 for(int i = 0; i < 256; i++) {
56 uint16_t n = (uint16_t)i;
57 for(int j = 0; j < 8; j++) {
58 bit_trans_table_0[i][j] = n & 0x80;
59 bit_trans_table_1[i][j] = ((n & 0x80) != 0) ? 0x40 : 0;
60 bit_trans_table_2[i][j] = ((n & 0x80) != 0) ? 0x20 : 0;
61 bit_trans_table_3[i][j] = ((n & 0x80) != 0) ? 0x10 : 0;
62 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
63 bit_trans_table_4[i][j] = ((n & 0x80) != 0) ? 0x08 : 0;
64 bit_trans_table_5[i][j] = ((n & 0x80) != 0) ? 0x04 : 0;
72 #if defined(USE_GREEN_DISPLAY)
73 use_green_monitor = false;
76 set_device_name(_T("DISPLAY SUBSYSTEM"));
84 void DISPLAY::reset_some_devices()
88 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
89 call_write_signal(mainio, SIG_FM7_SUB_HALT, 0x00, 0xff);
92 palette_changed = true;
93 multimode_accessmask = 0;
94 multimode_dispmask = 0;
95 for(i = 0; i < 4; i++) {
96 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
97 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
99 //firq_mask = false; // 20180215 Thanks to Ryu takegami.
100 //cancel_request = false;
101 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
102 switch(config.cpu_type){
111 prev_clock = SUBCLOCK_NORMAL;
113 prev_clock = SUBCLOCK_SLOW;
118 for(i = 0; i < 2; i++) {
119 offset_changed[i] = true;
120 tmp_offset_point[i].d = 0;
123 vram_wrote_shadow = true;
124 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
125 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
129 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
136 if(hblank_event_id >= 0) cancel_event(this, hblank_event_id);
137 if(hdisp_event_id >= 0) cancel_event(this, hdisp_event_id);
139 if(vsync_event_id >= 0) cancel_event(this, vsync_event_id);
140 if(vstart_event_id >= 0) cancel_event(this, vstart_event_id);
141 hblank_event_id = -1;
144 vstart_event_id = -1;
146 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
147 usec = 0.33 * 1000.0;
148 vm->set_vm_frame_rate(55.40);
150 usec = 0.51 * 1000.0;
151 vm->set_vm_frame_rate(FRAMES_PER_SEC);
154 //register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
155 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
156 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0xff, 0xff);
159 display_page_bak = 0;
161 #if defined(_FM77AV_VARIANTS)
163 offset_point_bank1 = 0;
165 subcpu_resetreq = false;
166 subrom_bank_using = subrom_bank;
171 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
173 vram_display_block = 0;
174 vram_active_block = 0;
176 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
181 window_opened = false;
186 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
187 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
188 call_write_signal(alu, SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400: 200, 0xffff);
189 call_write_signal(alu, SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xffffffff : 0, 0xffffffff);
191 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
192 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
193 call_write_signal(alu, SIG_ALU_400LINE, 0, 0xffffffff);
195 call_write_signal(alu, SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
196 call_write_signal(alu, SIG_ALU_PLANES, 3, 3);
198 for(i = 0; i < 8; i++) set_dpalette(i, i);
199 #if defined(USE_GREEN_DISPLAY)
200 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
202 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
203 //do_firq(!firq_mask && key_firq_req);
205 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
206 //kanjisub = false; // Fixed by Ryu takegami
207 kanjiaddr.d = 0x00000000;
208 # if defined(_FM77L4)
210 stat_400linecard = false;
215 frame_skip_count_draw = 3;
216 frame_skip_count_transfer = 3;
217 need_transfer_line = true;
218 setup_display_mode();
223 void DISPLAY::reset()
227 vram_accessflag = true;
228 display_mode = DISPLAY_MODE_8_200L;
230 crt_flag = false; // Fixed by Ryu Takegami
231 screen_update_flag = true;
232 crt_flag_bak = false;
233 cancel_request = false;
234 #if defined(_FM77AV_VARIANTS)
236 apalette_index.d = 0;
237 for(i = 0; i < 4096; i++) {
238 analog_palette_r[i] = i & 0x0f0;
239 analog_palette_g[i] = (i & 0xf00) >> 4;
240 analog_palette_b[i] = (i & 0x00f) << 4;
242 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
246 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
253 #elif defined(_FM77L4)
255 stat_400linecard = false;
259 text_width40 = false;
264 text_start_addr.d = 0x0000;
272 text_scroll_count = 0;
278 uint8_t *regs = l4crtc->get_regs();
279 display_mode = DISPLAY_MODE_1_400L;
280 if(event_id_l4_cursor_blink >= 0) {
281 cancel_event(this, event_id_l4_cursor_blink);
283 if(event_id_l4_text_blink >= 0) {
284 cancel_event(this, event_id_l4_text_blink);
286 event_id_l4_cursor_blink = -1;
287 event_id_l4_text_blink = -1;
289 usec = ((regs[10] & 0x20) == 0) ? 160.0 : 320.0;
290 usec = usec * 1000.0;
291 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
292 usec = 160.0 * 1000.0;
293 register_event(this, EVENT_FM7SUB_TEXT_BLINK, true, usec, &event_id_l4_cursor_blink);
296 //memset(crtc_regs, 0x00, sizeof(crtc_regs));
299 #if !defined(FIXED_FRAMEBUFFER_SIZE)
300 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
302 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
304 emu->set_vm_screen_lines(200);
306 reset_some_devices();
308 #if defined(_FM77AV_VARIANTS)
309 power_on_reset = false;
310 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
314 for(i = 0; i < 8; i++) set_dpalette(i, i);
317 #if defined(USE_GREEN_DISPLAY) && defined(USE_MONITOR_TYPE)
318 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
319 switch(config.monitor_type) {
320 case FM7_MONITOR_GREEN:
321 use_green_monitor = true;
323 case FM7_MONITOR_STANDARD:
325 use_green_monitor = false;
329 //use_green_monitor = false;
333 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
336 if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
337 register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
340 key_firq_req = false;
345 void DISPLAY::reset_subcpu(bool _check_firq)
347 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0, 1);
348 call_write_signal(subcpu, SIG_CPU_BUSREQ, 0, 1);
351 do_firq(!firq_mask && key_firq_req);
354 void DISPLAY::setup_display_mode(void)
356 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
357 if(display_mode == DISPLAY_MODE_8_400L) {
358 page_offset = 0x0000;
359 pagemod_mask = 0x18000;
361 } else if(display_mode == DISPLAY_MODE_256k) {
362 if(active_page != 0) {
363 page_offset = 0xc000;
365 page_offset = 0x0000;
367 pagemod_mask = 0xe000;
369 } else if(display_mode == DISPLAY_MODE_4096) {
370 if(active_page != 0) {
371 page_offset = 0xc000;
373 page_offset = 0x0000;
375 pagemod_mask = 0xe000;
378 if(active_page != 0) {
379 page_offset = 0xc000;
381 page_offset = 0x0000;
383 pagemod_mask = 0xc000;
386 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
387 if(vram_active_block != 0) page_offset += 0x18000;
389 #elif defined(_FM77AV_VARIANTS)
392 pagemod_mask = 0xe000;
393 } else { // 640x200, 8colors
395 pagemod_mask = 0xc000;
397 if(active_page != 0) {
398 page_offset = 0xc000;
400 page_offset = 0x0000;
402 #elif defined(_FM77L4)
403 if(display_mode == DISPLAY_MODE_1_400L) {
405 pagemod_mask = 0x0000;
406 page_offset = 0x0000;
407 } else { // 640x200, 8colors
409 pagemod_mask = 0xc000;
410 page_offset = 0x0000;
412 page_offset = 0x0000;
414 page_offset = 0x0000;
415 pagemod_mask = 0xc000;
420 void DISPLAY::update_config()
426 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
432 * Vram accessing functions moved to vram.cpp .
435 void DISPLAY::do_irq(bool flag)
437 call_write_signal(subcpu, SIG_CPU_IRQ, flag ? 1: 0, 1);
440 void DISPLAY::do_firq(bool flag)
442 call_write_signal(subcpu, SIG_CPU_FIRQ, flag ? 1: 0, 1);
445 void DISPLAY::do_nmi(bool flag)
447 #if defined(_FM77AV_VARIANTS)
448 if(!nmi_enable) flag = false;
450 call_write_signal(subcpu, SIG_CPU_NMI, flag ? 1 : 0, 1);
453 void DISPLAY::set_multimode(uint8_t val)
456 multimode_accessmask = val & 0x07;
457 multimode_dispmask = (val & 0x70) >> 4;
458 for(int i = 0; i < 4; i++) {
459 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
460 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
463 # if defined(_FM77AV_VARIANTS)
464 call_write_signal(alu, SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
469 uint8_t DISPLAY::get_multimode(void)
475 val = multimode_accessmask & 0x07;
476 val |= ((multimode_dispmask << 4) & 0x70);
482 uint8_t DISPLAY::get_cpuaccessmask(void)
484 return multimode_accessmask & 0x07;
487 void DISPLAY::set_dpalette(uint32_t addr, uint8_t val)
491 if(dpalette_data[addr] != (val | 0xf8)) {
492 dpalette_data[addr] = val | 0xf8; //0b11111000;
493 b = ((val & 0x01) != 0x00)? 255 : 0x00;
494 r = ((val & 0x02) != 0x00)? 255 : 0x00;
495 g = ((val & 0x04) != 0x00)? 255 : 0x00;
497 dpalette_pixel_tmp[addr] = RGB_COLOR(r, g, b);
498 #if defined(USE_GREEN_DISPLAY)
499 static const scrntype_t colortable[8] = {0, 48, 70, 100, 140, 175, 202, 255};
500 g = colortable[val & 0x07];
501 b = r = ((val & 0x07) > 4) ? 48 : 0;
502 dpalette_green_tmp[addr] = RGB_COLOR(r, g, b);
504 palette_changed = true;
508 uint8_t DISPLAY::get_dpalette(uint32_t addr)
516 data = dpalette_data[addr];
521 void DISPLAY::halt_subcpu(void)
523 //call_write_signal(subcpu, SIG_CPU_BUSREQ, 0x01, 0x01);
524 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0x01, 0x01);
527 void DISPLAY::go_subcpu(void)
529 call_write_signal(subcpu, SIG_CPU_HALTREQ, 0x00, 0x01);
532 void DISPLAY::enter_display(void)
537 subclock = SUBCLOCK_NORMAL;
539 subclock = SUBCLOCK_SLOW;
541 if(!(is_cyclesteal) && (vram_accessflag)) {
542 subclock = subclock / 3;
544 if(prev_clock != subclock) {
545 vm->set_cpu_clock(subcpu, subclock);
547 prev_clock = subclock;
551 void DISPLAY::leave_display(void)
555 void DISPLAY::halt_subsystem(void)
561 void DISPLAY::restart_subsystem(void)
564 #if defined(_FM77AV_VARIANTS)
565 if(subcpu_resetreq) {
566 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
567 reset_some_devices();
568 power_on_reset = true;
576 void DISPLAY::set_crtflag(void)
583 void DISPLAY::reset_crtflag(void)
590 uint8_t DISPLAY::acknowledge_irq(void)
592 cancel_request = false;
598 uint8_t DISPLAY::beep(void)
600 call_write_signal(mainio, FM7_MAINIO_BEEP, 0x01, 0x01);
601 return 0xff; // True?
606 uint8_t DISPLAY::attention_irq(void)
608 call_write_signal(mainio, FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
613 void DISPLAY::set_cyclesteal(uint8_t val)
616 # if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
620 is_cyclesteal = true;
622 is_cyclesteal = false;
629 void DISPLAY::setup_400linemode(uint8_t val)
633 cursor_lsb = ((val & 0x10) != 0);
634 text_width40 = ((val & 0x08) != 0);
635 workram_l4 = ((val & 0x04) != 0);
636 bool tmpmode = ((val & 0x02) != 0);
637 if(tmpmode != mode400line) {
638 int oldmode = display_mode;
639 mode400line = tmpmode;
640 if(mode400line && stat_400linecard) {
641 display_mode = DISPLAY_MODE_1_400L;
643 display_mode = DISPLAY_MODE_8_200L;
645 if(oldmode != display_mode) {
647 if(display_mode == DISPLAY_MODE_1_400L) {
648 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
649 for(int y = 0; y < 400; y++) {
650 pp = emu->get_screen_buffer(y);
651 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
655 vm->set_vm_frame_rate(FRAMES_PER_SEC);
656 #if !defined(FIXED_FRAMEBUFFER_SIZE)
657 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
658 for(int y = 0; y < 200; y++) {
659 pp = emu->get_screen_buffer(y);
660 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
663 for(int y = 0; y < 400; y++) {
664 pp = emu->get_screen_buffer(y);
665 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
670 setup_display_mode();
678 uint8_t DISPLAY::set_vramaccess(void)
680 vram_accessflag = true;
686 void DISPLAY::reset_vramaccess(void)
688 vram_accessflag = false;
693 uint8_t DISPLAY::reset_subbusy(void)
700 void DISPLAY::set_subbusy(void)
706 #if defined(_FM77AV_VARIANTS)
708 void DISPLAY::alu_write_cmdreg(uint32_t val)
710 call_write_data8(alu, ALU_CMDREG, val);
711 if((val & 0x80) != 0) {
719 void DISPLAY::alu_write_logical_color(uint8_t val)
721 uint32_t data = (uint32_t)val;
722 call_write_data8(alu, ALU_LOGICAL_COLOR, data);
726 void DISPLAY::alu_write_mask_reg(uint8_t val)
728 uint32_t data = (uint32_t)val;
729 call_write_data8(alu, ALU_WRITE_MASKREG, data);
733 void DISPLAY::alu_write_cmpdata_reg(int addr, uint8_t val)
735 uint32_t data = (uint32_t)val;
737 call_write_data8(alu, ALU_CMPDATA_REG + addr, data);
741 void DISPLAY::alu_write_disable_reg(uint8_t val)
743 uint32_t data = (uint32_t)val;
744 call_write_data8(alu, ALU_BANK_DISABLE, data);
748 void DISPLAY::alu_write_tilepaint_data(uint32_t addr, uint8_t val)
750 uint32_t data = (uint32_t)val;
753 call_write_data8(alu, ALU_TILEPAINT_B, data);
756 call_write_data8(alu, ALU_TILEPAINT_R, data);
759 call_write_data8(alu, ALU_TILEPAINT_G, data);
762 //call_write_data8(alu, ALU_TILEPAINT_L, 0xff);
768 void DISPLAY::alu_write_offsetreg_hi(uint8_t val)
770 call_write_data8(alu, ALU_OFFSET_REG_HIGH, val & 0x7f);
774 void DISPLAY::alu_write_offsetreg_lo(uint8_t val)
776 call_write_data8(alu, ALU_OFFSET_REG_LO, val);
780 void DISPLAY::alu_write_linepattern_hi(uint8_t val)
782 call_write_data8(alu, ALU_LINEPATTERN_REG_HIGH, val);
786 void DISPLAY::alu_write_linepattern_lo(uint8_t val)
788 call_write_data8(alu, ALU_LINEPATTERN_REG_LO, val);
792 void DISPLAY::alu_write_line_position(int addr, uint8_t val)
794 uint32_t data = (uint32_t)val;
797 call_write_data8(alu, ALU_LINEPOS_START_X_HIGH, data & 0x03);
800 call_write_data8(alu, ALU_LINEPOS_START_X_LOW, data);
803 call_write_data8(alu, ALU_LINEPOS_START_Y_HIGH, data & 0x01);
806 call_write_data8(alu, ALU_LINEPOS_START_Y_LOW, data);
809 call_write_data8(alu, ALU_LINEPOS_END_X_HIGH, data & 0x03);
812 call_write_data8(alu, ALU_LINEPOS_END_X_LOW, data);
815 call_write_data8(alu, ALU_LINEPOS_END_Y_HIGH, data & 0x01);
818 call_write_data8(alu, ALU_LINEPOS_END_Y_LOW, data);
824 uint8_t DISPLAY::get_miscreg(void)
829 if(!hblank) ret |= 0x80;
830 if(vsync) ret |= 0x04;
831 if(alu->read_signal(SIG_ALU_BUSYSTAT) == 0) ret |= 0x10;
832 if(power_on_reset) ret |= 0x01;
837 void DISPLAY::set_miscreg(uint8_t val)
839 int old_display_page = display_page;
841 nmi_enable = ((val & 0x80) == 0) ? true : false;
842 if(!nmi_enable) do_nmi(false);
844 if((val & 0x40) == 0) {
849 if(display_page != old_display_page) {
852 active_page = ((val & 0x20) == 0) ? 0 : 1;
853 if((val & 0x04) == 0) {
858 cgrom_bank = val & 0x03;
859 setup_display_mode();
863 void DISPLAY::set_monitor_bank(uint8_t var)
865 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
866 if((var & 0x04) != 0){
872 subrom_bank = var & 0x03;
875 subcpu_resetreq = false;
876 power_on_reset = true;
877 //firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
878 reset_some_devices();
881 subcpu_resetreq = true;
887 void DISPLAY::set_apalette_index_hi(uint8_t val)
889 apalette_index.b.h = val & 0x0f;
893 void DISPLAY::set_apalette_index_lo(uint8_t val)
895 apalette_index.b.l = val;
898 void DISPLAY::calc_apalette(uint16_t idx)
902 g = analog_palette_g[idx];
903 r = analog_palette_r[idx];
904 b = analog_palette_b[idx];
905 if(g != 0) g |= 0x0f;
906 if(r != 0) r |= 0x0f;
907 if(b != 0) b |= 0x0f;
908 analog_palette_pixel_tmp[idx] = RGB_COLOR(r, g, b);
912 void DISPLAY::set_apalette_b(uint8_t val)
916 index = apalette_index.w.l;
917 tmp = (val & 0x0f) << 4;
918 if(analog_palette_b[index] != tmp) {
919 analog_palette_b[index] = tmp;
920 calc_apalette(index);
921 palette_changed = true;
926 void DISPLAY::set_apalette_r(uint8_t val)
930 index = apalette_index.w.l;
931 tmp = (val & 0x0f) << 4;
932 if(analog_palette_r[index] != tmp) {
933 analog_palette_r[index] = tmp;
934 calc_apalette(index);
935 palette_changed = true;
940 void DISPLAY::set_apalette_g(uint8_t val)
944 index = apalette_index.w.l;
945 tmp = (val & 0x0f) << 4;
946 if(analog_palette_g[index] != tmp) {
947 analog_palette_g[index] = tmp;
948 calc_apalette(index);
949 palette_changed = true;
953 #endif // _FM77AV_VARIANTS
956 void DISPLAY::copy_vram_blank_area(void)
960 void DISPLAY::copy_vram_per_line(int begin, int end)
963 uint32_t yoff_d1 = 0;
964 uint32_t yoff_d2 = 0;
969 uint32_t src_offset_d1;
970 uint32_t src_offset_d2;
971 uint32_t src_offset_d;
976 uint32_t addr_d1, addr_d2;
980 //int dline = (int)displine - 1;
981 int dline = (int)displine;
983 if((begin < 0) || (begin > 4)) return;
984 if((end < 0) || (end > 4)) return;
985 if(begin > end) return;
986 if(dline < 0) return;
988 sectors = end - begin + 1;
990 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)){
991 if(dline >= 400) return;
993 if(dline >= 200) return;
995 #if defined(_FM77AV_VARIANTS)
996 yoff_d1 = offset_point;
997 yoff_d2 = offset_point_bank1;
998 if(display_mode == DISPLAY_MODE_4096) {
999 src_offset = dline * 40 + begin * 8;
1000 sectors = sectors * 8;
1001 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1004 addr_d1 = (src_offset + yoff_d1) & 0x1fff;
1005 addr_d2 = (src_offset + yoff_d2) & 0x1fff;
1006 bytes_d1 = 0x2000 - addr_d1;
1007 bytes_d2 = 0x2000 - addr_d2;
1008 for(k = 0; k < pages; k++) {
1010 for(i = 0; i < 3; i++) {
1011 for(j = 0; j < 2; j++) {
1012 uint32_t _addr_base = src_base + src_offset + poff;
1013 if(bytes_d1 < sectors) {
1014 my_memcpy(&gvram_shadow[_addr_base],
1015 &gvram[addr_d1 + src_base + poff],
1017 my_memcpy(&gvram_shadow[_addr_base + bytes_d1],
1018 &gvram[src_base + poff],
1019 sectors - bytes_d1);
1021 my_memcpy(&gvram_shadow[_addr_base],
1022 &gvram[addr_d1 + src_base + poff],
1025 _addr_base += 0xc000;
1026 if(bytes_d2 < sectors) {
1027 my_memcpy(&gvram_shadow[_addr_base],
1028 &gvram[addr_d2 + src_base + poff + 0xc000],
1030 my_memcpy(&gvram_shadow[_addr_base + bytes_d2],
1031 &gvram[src_base + poff + 0xc000],
1032 sectors - bytes_d2);
1034 my_memcpy(&gvram_shadow[_addr_base],
1035 &gvram[addr_d2 + src_base + poff + 0xc000],
1040 src_base = (i + 1) * 0x4000;
1044 vram_draw_table[dline] = true;
1045 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1047 # if defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV40)
1048 else if(display_mode == DISPLAY_MODE_256k) {
1049 src_offset = dline * 40 + begin * 8;
1050 sectors = sectors * 8;
1052 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1054 #elif defined(_FM77AV40)
1059 src_offset_d1 = (src_offset + yoff_d1) & 0x1fff;
1060 src_offset_d2 = (src_offset + yoff_d2) & 0x1fff;
1061 bytes_d1 = 0x2000 - ((src_offset + yoff_d1) & 0x1fff);
1062 bytes_d2 = 0x2000 - ((src_offset + yoff_d2) & 0x1fff);
1063 for(k = 0; k < pages; k++) {
1064 for(i = 0; i < 3; i++) {
1065 for(j = 0; j < 2; j++) {
1067 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
1068 src_offset_d = src_offset_d1;
1071 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
1072 src_offset_d = src_offset_d2;
1075 if(bytes_d < sectors) {
1076 my_memcpy(&gvram_shadow[src_offset + src_base],
1077 &gvram[src_offset_d + src_base],
1079 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1083 my_memcpy(&gvram_shadow[src_offset + src_base],
1084 &gvram[src_offset_d + src_base],
1090 vram_draw_table[dline] = true;
1091 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1093 else if(display_mode == DISPLAY_MODE_8_400L) {
1094 src_offset = dline * 80 + begin * 16;
1095 sectors = sectors * 16;
1096 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1099 if(display_page_bak == 1) { // Is this dirty?
1104 yoff_d = (yoff_d << 1) & 0x7fff;
1105 src_offset_d = (src_offset + yoff_d) & 0x7fff;
1106 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
1107 for(i = 0; i < pages; i++) {
1108 for(j = 0; j < 3; j++) {
1109 src_base = i * 0x18000 + j * 0x8000;
1110 if(bytes_d < sectors) {
1112 my_memcpy(&gvram_shadow[src_offset + src_base],
1113 &gvram[src_offset_d + src_base],
1116 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1120 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1121 &gvram[src_offset_d + src_base],
1126 vram_draw_table[dline] = true;
1127 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1131 src_offset = dline * 80 + begin * 16;
1132 sectors = sectors * 16;
1133 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1135 #elif defined(_FM77AV40)
1137 #elif defined(_FM77AV_VARIANTS)
1143 src_offset_d1 = (src_offset + yoff_d1) & 0x3fff;
1144 src_offset_d2 = (src_offset + yoff_d2) & 0x3fff;
1145 bytes_d1 = 0x4000 - ((src_offset + yoff_d1) & 0x3fff);
1146 bytes_d2 = 0x4000 - ((src_offset + yoff_d2) & 0x3fff);
1147 for(i = 0; i < pages; i++) {
1149 src_offset_d = src_offset_d1;
1152 src_offset_d = src_offset_d2;
1156 for(j = 0; j < 3; j++) {
1157 if(bytes_d < sectors) {
1158 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1159 &gvram[src_offset_d + src_base + poff],
1161 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1162 &gvram[src_base + poff],
1165 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1166 &gvram[src_offset_d + src_base + poff],
1173 vram_draw_table[dline] = true;
1174 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1175 //vram_wrote_table[dline] = false;
1178 #if defined(_FM77L4)
1179 if(display_mode == DISPLAY_MODE_1_400L) {
1180 src_offset = dline * 80 + begin * 16;
1181 sectors = sectors * 16;
1182 yoff_d = (yoff_d1 << 1) & 0x7fff;
1183 src_offset_d = (src_offset + yoff_d) & 0x7fff;
1184 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
1185 if(bytes_d < sectors) {
1187 my_memcpy(&gvram_shadow[src_offset],
1188 &gvram[src_offset_d],
1191 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
1195 my_memcpy(&gvram_shadow[src_offset + poff],
1196 &gvram[src_offset_d ],
1199 vram_draw_table[dline] = true;
1200 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1205 src_offset = dline * 80 + begin * 16;
1206 sectors = sectors * 16;
1209 yoff_d = offset_point;
1210 src_offset_d = (src_offset + yoff_d) & 0x3fff;
1211 bytes_d = 0x4000 - ((src_offset + yoff_d) & 0x3fff);
1212 for(j = 0; j < 3; j++) {
1213 src_base = j * 0x4000;
1214 if(bytes_d < sectors) {
1215 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1216 &gvram[src_offset_d + src_base + poff],
1218 my_memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
1219 &gvram[src_base + poff],
1222 my_memcpy(&gvram_shadow[src_offset + src_base + poff],
1223 &gvram[src_offset_d + src_base + poff],
1227 vram_draw_table[dline] = true;
1228 for(int ii = begin; ii <= end; ii++) vram_wrote_table[(dline * 5) + ii] = false;
1229 //vram_wrote_table[dline] = false;
1235 void DISPLAY::copy_vram_all()
1237 #if defined(_FM77AV_VARIANTS)
1238 uint32_t yoff_d1 = offset_point;
1239 uint32_t yoff_d2 = offset_point_bank1;
1240 uint32_t src_offset_1, src_offset_2;
1242 if(display_mode == DISPLAY_MODE_4096) {
1243 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1248 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1249 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1250 for(int k = 0; k < pages; k++) {
1251 for(int i = 0; i < 3; i++) {
1252 for(int j = 0; j < 2; j++) {
1253 src_offset_1 = i * 0x4000 + j * 0x2000;
1254 src_offset_2 = src_offset_1 + 0xc000;
1255 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1256 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1257 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1258 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1264 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1265 else if(display_mode == DISPLAY_MODE_256k) {
1266 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1267 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
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 src_offset_2 = src_offset_1 + 0xc000;
1272 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1273 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1274 my_memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1275 my_memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1279 for(int i = 0; i < 3; i++) {
1280 for(int j = 0; j < 2; j++) {
1281 src_offset_1 = i * 0x4000 + j * 0x2000;
1282 my_memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1283 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1286 } else if(display_mode == DISPLAY_MODE_8_400L) {
1288 uint32_t yoff_d, bytes_d;
1289 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1292 if(display_page_bak == 1) { // Is this dirty?
1297 yoff_d = (yoff_d << 1) & 0x7fff;
1298 bytes_d = 0x8000 - yoff_d;
1299 for(int i = 0; i < pages; i++) {
1300 for(int j = 0; j < 3; j++) {
1301 uint32_t src_base = i * 0x18000 + j * 0x8000;
1302 my_memcpy(&gvram_shadow[src_base],
1303 &gvram[yoff_d + src_base],
1305 if(bytes_d < 0x8000) {
1306 my_memcpy(&gvram_shadow[bytes_d + src_base],
1315 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1317 #elif defined(_FM77AV40)
1322 uint32_t bytes_d1 = 0x4000 - (yoff_d1 & 0x3fff);
1323 uint32_t bytes_d2 = 0x4000 - (yoff_d2 & 0x3fff);
1324 uint32_t yoff_d, bytes_d;
1325 for(int k = 0; k < pages; k++) {
1326 yoff_d = ((k & 1) == 0) ? (yoff_d1 & 0x3fff) : (yoff_d2 & 0x3fff);
1327 bytes_d = ((k & 1) == 0) ? bytes_d1 : bytes_d2;
1328 for(int j = 0; j < 3; j++) {
1329 src_offset_1 = k * 0xc000 + j * 0x4000;
1330 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1331 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1336 # if defined(_FM77L4)
1337 if(display_mode == DISPLAY_MODE_1_400L) {
1338 uint32_t yoff_d = offset_point & 0x7fff;
1339 uint32_t bytes_d = 0x8000 - (offset_point & 0x7fff);
1340 my_memcpy(&gvram_shadow[0], &gvram[0 + yoff_d], bytes_d);
1341 my_memcpy(&gvram_shadow[0 + bytes_d], &gvram[0], 0x8000 - bytes_d);
1346 uint32_t yoff_d = offset_point & 0x3fff;
1347 uint32_t bytes_d = 0x4000 - (offset_point & 0x3fff);
1348 uint32_t src_offset_1;
1349 for(int j = 0; j < 3; j++) {
1350 src_offset_1 = j * 0x4000;
1351 my_memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1352 my_memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1358 // Timing values from XM7 . Thanks Ryu.
1359 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1360 void DISPLAY::event_callback_hdisp(void)
1365 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x02, 0xff);
1366 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1367 if(displine < 400) f = true;
1369 if(displine < 200) f = true;
1372 hdisp_event_id = -1;
1374 // DO ONLY WHEN SYNC-TO-HSYNC.
1375 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
1377 //copy_vram_per_line(0, 4);
1378 } else if(need_transfer_line) { // Not frame skip.
1381 for(int iii = 0; iii < 5 ; iii++) {
1382 if(vram_wrote_table[iii + displine * 5]) {
1383 if(begin < 0) begin = iii; // Check first.
1388 if(end < begin) end = begin;
1390 copy_vram_per_line(begin, end);
1391 // Prepare to next block.
1397 // Tail of this line.
1400 copy_vram_per_line(begin, end);
1404 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1405 register_event(this, EVENT_FM7SUB_HBLANK, 30.0, false, &hblank_event_id); // NEXT CYCLE_
1407 register_event(this, EVENT_FM7SUB_HBLANK, 39.5, false, &hblank_event_id); // NEXT CYCLE_
1415 void DISPLAY::event_callback_hblank(void)
1422 hblank_event_id = -1;
1424 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1425 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1426 if((displine < 400)) f = true;
1429 if((displine < 200)) f = true;
1433 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id);
1438 void DISPLAY::event_callback_vstart(void)
1445 display_page_bak = display_page;
1447 // Parameter from XM7/VM/display.c , thanks, Ryu.
1448 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1449 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x00, 0xff);
1451 if(vblank_count != 0) {
1452 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1453 usec = (0.98 + 16.4) * 1000.0;
1455 usec = (1.91 + 12.7) * 1000.0;
1457 register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
1459 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1460 usec = 930.0; // 939.0
1462 usec = 1840.0; // 1846.5
1464 vstart_event_id = -1;
1465 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
1466 //register_event(this, EVENT_FM7SUB_HBLANK, usec, false, &hdisp_event_id); // NEXT CYCLE_
1469 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1470 usec = 0.34 * 1000.0;
1472 usec = 1.52 * 1000.0;
1474 vsync_event_id = -1;
1475 hblank_event_id = -1;
1476 hdisp_event_id = -1;
1477 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1481 void DISPLAY::event_callback_vsync(void)
1487 //write_access_page = (write_access_page + 1) & 1;
1490 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x01, 0xff);
1491 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1492 //if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1493 // usec = 0.33 * 1000.0;
1495 // usec = 0.51 * 1000.0;
1497 //register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1498 vsync_event_id = -1; // Fix for logging "[EVENT] EVENT: device (name=DISPLAY SUBSYSTEM, id=25) tries to cancel event 6 that is not its own (owned by (name=PRINTER I/F id=20))!!!"
1499 if(palette_changed) {
1500 #if defined(_FM77AV_VARIANTS)
1501 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
1503 #if defined(USE_GREEN_DISPLAY)
1504 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
1506 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
1507 vram_wrote_shadow = true;
1508 for(int yy = 0; yy < 400; yy++) {
1509 vram_draw_table[yy] = true;
1511 palette_changed = false;
1513 // Transfer on VSYNC
1514 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) {
1518 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L))lines = 400;
1519 if(need_transfer_line) {
1520 if(vram_wrote) { // transfer all line
1521 for(displine = 0; displine < lines; displine++) {
1522 //if(!vram_draw_table[displine]) {
1523 copy_vram_per_line(0, 4);
1527 } else { // transfer wrote line
1530 for(displine = 0; displine < lines; displine++) {
1531 //if(!vram_draw_table[displine]) {
1532 for(int iii = 0; iii < 5 ; iii++) {
1533 if(vram_wrote_table[iii + displine * 5]) {
1540 if(end < begin) end = begin;
1541 copy_vram_per_line(begin, end);
1548 if(end < 0) end = 4;
1549 copy_vram_per_line(begin, end);
1557 for(int yy = 0; yy < lines; yy++) {
1558 if(vram_draw_table[yy]) {
1559 vram_wrote_shadow = true;
1560 screen_update_flag = true;
1565 // TRANSFER per HSYNC a.k.a SYNC-TO-HSYNC.
1567 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) lines = 400;
1569 if(need_transfer_line) {
1570 if(vram_wrote) { // Transfer all line.
1571 for(int yy = 0; yy < lines; yy++) {
1573 copy_vram_per_line(0, 4);
1579 for(int yy = 0; yy < lines; yy++) {
1580 if(vram_draw_table[yy]) {
1581 vram_wrote_shadow = true;
1582 screen_update_flag = true;
1586 //vram_wrote = false;
1588 frame_skip_count_transfer++;
1590 // Check frame skip for next frame.
1591 uint32_t factor = ((config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28) & 3;
1592 if((frame_skip_count_transfer > factor) /* || (vram_wrote) */) {
1593 frame_skip_count_transfer = 0;
1594 need_transfer_line = true;
1596 need_transfer_line = false;
1602 #if defined(_FM77L4)
1603 void DISPLAY::cursor_blink_77l4()
1605 if(!(mode400line && stat_400linecard)) return;
1606 uint8_t *regs = l4crtc->get_regs();
1610 if((regs[10] & 0x40) != 0) {
1611 cursor_blink = !cursor_blink;
1612 uint16_t addr = cursor_addr.w.l;
1614 x = ((addr / 2) % 40) / 8;
1615 y = (addr / 2) / 40;
1616 } else { // Width 80
1617 x = ((addr / 2) % 80) / 8;
1618 y = (addr / 2) / 80;
1620 for(int yy = 0; yy < 8; yy++) {
1621 naddr = (y + yy) * 5 + x;
1622 vram_wrote_table[naddr] = true;
1628 void DISPLAY::text_blink_77l4()
1631 uint16_t offset = text_start_addr.w.l;
1634 if(!(mode400line && stat_400linecard)) return;
1635 text_blink = !text_blink;
1636 for(addr = 0; addr < (80 * 50); addr++) {
1637 naddr = ((addr + offset) & 0x0ffe) + 1;
1638 if((text_vram[naddr] & 0x10) != 0) { // ATTR BLINK
1640 x = ((naddr / 2) % 40) / 8;
1641 y = (naddr / 2) / 40;
1642 } else { // Width 80
1643 x = ((naddr / 2) % 80) / 8;
1644 y = (naddr / 2) / 80;
1646 for(int yy = 0; yy < 8; yy++) {
1647 naddr = (y + yy) * 5 + x;
1648 vram_wrote_table[naddr] = true;
1653 #endif //#if defined(_FM77L4)
1655 void DISPLAY::event_callback(int event_id, int err)
1660 case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
1661 #if defined(_FM77AV_VARIANTS)
1669 case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
1672 //#if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1673 case EVENT_FM7SUB_HDISP:
1674 event_callback_hdisp();
1676 case EVENT_FM7SUB_HBLANK:
1677 event_callback_hblank();
1679 case EVENT_FM7SUB_VSTART: // Call first.
1680 event_callback_vstart();
1682 case EVENT_FM7SUB_VSYNC:
1683 event_callback_vsync();
1686 case EVENT_FM7SUB_DELAY_BUSY:
1690 case EVENT_FM7SUB_CLEAR_DELAY:
1693 case EVENT_FM7SUB_CLR_CRTFLAG:
1696 #if defined(_FM77L4)
1697 case EVENT_FM7SUB_CURSOR_BLINK:
1698 cursor_blink_77l4();
1700 case EVENT_FM7SUB_TEXT_BLINK:
1707 void DISPLAY::event_frame()
1714 //write_access_page = (write_access_page + 1) & 1;
1715 //out_debug_log(_T("DISPLINE=%d"), displine);
1717 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) {
1718 usec = 0.34 * 1000.0;
1720 usec = 1.52 * 1000.0;
1722 call_write_signal(mainio, SIG_DISPLAY_VSYNC, 0x01, 0xff);
1723 call_write_signal(mainio, SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1724 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1728 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1732 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) lines = 400;
1734 if(need_transfer_line && vram_wrote) {
1735 for(yy = 0; yy < lines; yy++) {
1736 //if(!vram_draw_table[yy]) {
1738 copy_vram_per_line(0, 4);
1746 for(yy = 0; yy < lines; yy++) {
1747 if(vram_draw_table[yy]) {
1753 screen_update_flag = true;
1754 vram_wrote_shadow = true;
1758 frame_skip_count_transfer++;
1760 uint32_t factor = (config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28;
1761 if(frame_skip_count_transfer > factor) {
1762 frame_skip_count_transfer = 0;
1763 need_transfer_line = true;
1765 need_transfer_line = false;
1767 //vram_wrote = false;
1775 void DISPLAY::event_vline(int v, int clock)
1777 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1779 if(need_transfer_line == false) return;
1782 // Not transfer, will transfer at event_frame.
1783 copy_vram_per_line(0, 4);
1787 for(int iii = 0; iii < 5 ; iii++) {
1788 if(vram_wrote_table[displine * 5 + iii]) {
1789 if(begin < 0) begin = iii;
1793 if(end < begin) end = begin;
1794 copy_vram_per_line(begin, end);
1802 copy_vram_per_line(begin, end);
1810 uint32_t DISPLAY::read_signal(int id)
1812 uint32_t retval = 0;
1814 case SIG_FM7_SUB_HALT:
1815 case SIG_DISPLAY_HALT:
1816 retval = (halt_flag) ? 0xffffffff : 0;
1818 case SIG_DISPLAY_BUSY:
1819 retval = (sub_busy) ? 0x80 : 0;
1821 case SIG_DISPLAY_MULTIPAGE:
1822 retval = multimode_accessmask;
1824 case SIG_DISPLAY_PLANES:
1827 #if defined(_FM77AV_VARIANTS)
1828 case SIG_DISPLAY_VSYNC:
1829 retval = (vsync) ? 0x01 : 0x00;
1831 case SIG_DISPLAY_DISPLAY:
1832 retval = (!hblank) ? 0x02: 0x00;
1834 case SIG_FM7_SUB_BANK: // Main: FD13
1835 retval = subrom_bank & 0x03;
1836 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1837 if(monitor_ram) retval |= 0x04;
1841 #if defined(_FM77AV_VARIANTS)
1842 case SIG_DISPLAY_MODE320:
1843 retval = (mode320) ? 0x40: 0x00;
1846 case SIG_DISPLAY_Y_HEIGHT:
1847 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77L4)
1848 retval = ((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_1_400L)) ? 400 : 200;
1853 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1855 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1856 retval |= (kanjisub) ? 0x00 : 0x20;
1857 retval |= (mode256k) ? 0x10 : 0x00;
1858 retval |= (mode400line) ? 0x00 : 0x08;
1859 retval |= (ram_protect) ? 0x00 : 0x04;
1860 #elif defined(_FM77_VARIANTS)
1862 retval |= (kanjisub) ? 0x00 : 0x20;
1863 # if defined(_FM77L4)
1864 retval |= (stat_400linecard) ? 0x00 : 0x08;
1872 case SIG_DISPLAY_X_WIDTH:
1873 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1874 retval = (mode320 || mode256k) ? 320 : 640;
1875 #elif defined(_FM77AV_VARIANTS)
1876 retval = (mode320) ? 320 : 640;
1887 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
1889 bool flag = ((data & mask) != 0);
1893 case SIG_FM7_SUB_HALT:
1898 //call_write_signal(mainio, SIG_FM7_SUB_HALT, data, mask);
1900 case SIG_DISPLAY_HALT:
1904 restart_subsystem();
1907 case SIG_FM7_SUB_CANCEL:
1909 cancel_request = true;
1913 case SIG_DISPLAY_CLOCK:
1917 #if defined(_FM77AV_VARIANTS)
1918 case SIG_FM7_SUB_BANK: // Main: FD13
1919 set_monitor_bank(data & 0xff);
1922 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1923 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1924 //printf("Wrote $FD04: %02x\n", data);
1926 int oldmode = display_mode;
1928 kanjisub = ((data & 0x20) == 0) ? true : false;
1929 mode256k = (((data & 0x10) != 0) && ((data & 0x08) != 0) ) ? true : false;
1930 mode400line = ((data & 0x08) == 0) ? true : false;
1931 ram_protect = ((data & 0x04) == 0) ? true : false;
1932 if((mode400line) && !(mode320)) {
1933 display_mode = DISPLAY_MODE_8_400L;
1934 } else if(mode256k) {
1935 display_mode = DISPLAY_MODE_256k;
1937 display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1939 if(oldmode != display_mode) {
1941 if(mode320 || mode256k) {
1942 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
1943 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1944 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1945 for(y = 0; y < 200; y++) {
1946 pp = emu->get_screen_buffer(y);
1947 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1950 for(y = 0; y < 400; y++) {
1951 pp = emu->get_screen_buffer(y);
1952 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1955 //emu->set_vm_screen_lines(200);
1956 } else if(display_mode == DISPLAY_MODE_8_400L) {
1957 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1958 if(oldmode != DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(55.40);
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 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
1965 #if !defined(FIXED_FRAMEBUFFER_SIZE)
1966 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1967 for(y = 0; y < 200; y++) {
1968 pp = emu->get_screen_buffer(y);
1969 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1972 for(y = 0; y < 400; y++) {
1973 pp = emu->get_screen_buffer(y);
1974 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1977 //emu->set_vm_screen_lines(200);
1980 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
1981 call_write_signal(alu, SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200, 0xffff);
1982 call_write_signal(alu, SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xff : 0x00, 0xff);
1983 frame_skip_count_draw = 3;
1984 frame_skip_count_transfer = 3;
1985 setup_display_mode();
1988 #elif defined(_FM77_VARIANTS)
1990 int oldmode = display_mode;
1991 kanjisub = ((data & 0x20) == 0) ? true : false;
1992 # if defined(_FM77L4)
1993 stat_400linecard = ((data & 0x08) != 0) ? false : true;
1994 if(mode400line && stat_400linecard) {
1996 uint8_t *regs = l4crtc->get_regs();
1997 display_mode = DISPLAY_MODE_1_400L;
1998 if(event_id_l4_cursor_blink >= 0) {
1999 cancel_event(this, event_id_l4_cursor_blink);
2001 if(event_id_l4_text_blink >= 0) {
2002 cancel_event(this, event_id_l4_text_blink);
2004 event_id_l4_cursor_blink = -1;
2005 event_id_l4_text_blink = -1;
2007 usec = ((regs[10] & 0x20) == 0) ? 160.0 : 320.0;
2008 usec = usec * 1000.0;
2009 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
2010 usec = 160.0 * 1000.0;
2011 register_event(this, EVENT_FM7SUB_TEXT_BLINK, true, usec, &event_id_l4_cursor_blink);
2014 display_mode = DISPLAY_MODE_8_200L;
2016 if(oldmode != display_mode) {
2018 if(display_mode == DISPLAY_MODE_1_400L) {
2019 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2020 for(int y = 0; y < 400; y++) {
2021 pp = emu->get_screen_buffer(y);
2022 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2026 vm->set_vm_frame_rate(FRAMES_PER_SEC);
2027 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2028 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2029 for(int y = 0; y < 200; y++) {
2030 pp = emu->get_screen_buffer(y);
2031 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2034 for(int y = 0; y < 400; y++) {
2035 pp = emu->get_screen_buffer(y);
2036 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2041 setup_display_mode();
2048 #if defined(_FM77AV_VARIANTS)
2049 case SIG_DISPLAY_MODE320: // FD12 bit 6
2050 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2052 //printf("Wrote $FD12: %02x\n", data);
2053 int oldmode = display_mode;
2056 display_mode = DISPLAY_MODE_8_400L;
2057 } else if(mode256k) {
2058 display_mode = DISPLAY_MODE_256k;
2059 } else if(!(mode320) && !(mode256k)) {
2060 //display_mode = (mode400line) ? DISPLAY_MODE_8_400L : DISPLAY_MODE_8_200L;
2061 display_mode = DISPLAY_MODE_8_200L;
2063 display_mode = (mode256k) ? DISPLAY_MODE_256k : DISPLAY_MODE_4096;
2065 if(oldmode != display_mode) {
2067 if(mode320 || mode256k) {
2068 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
2069 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2070 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2071 for(y = 0; y < 200; y++) {
2072 pp = emu->get_screen_buffer(y);
2073 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
2076 for(y = 0; y < 400; y++) {
2077 pp = emu->get_screen_buffer(y);
2078 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2081 //emu->set_vm_screen_lines(200);
2082 } else { // 200 lines, 8 colors.
2083 if(display_mode == DISPLAY_MODE_8_400L) {
2084 if(oldmode != DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(55.40);
2086 if(oldmode == DISPLAY_MODE_8_400L) vm->set_vm_frame_rate(FRAMES_PER_SEC);
2088 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2089 int ymax = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
2091 emu->set_vm_screen_size(640, ymax, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2092 for(y = 0; y < ymax; y++) {
2093 pp = emu->get_screen_buffer(y);
2094 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2097 for(y = 0; y < 400; y++) {
2098 pp = emu->get_screen_buffer(y);
2099 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
2102 //emu->set_vm_screen_lines(200);
2105 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
2106 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
2107 call_write_signal(alu, SIG_ALU_400LINE, 0x00, 0xff);
2108 setup_display_mode();
2109 //frame_skip_count = 3;
2112 # else /* FM77AV/20/20EX */
2115 if(oldflag != mode320) {
2118 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2119 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2120 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 320 * sizeof(scrntype_t));
2122 for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2124 //emu->set_vm_screen_lines(200);
2126 #if !defined(FIXED_FRAMEBUFFER_SIZE)
2127 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2128 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2130 for(y = 0; y < 400; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
2132 //emu->set_vm_screen_lines(200);
2135 display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
2136 call_write_signal(alu, SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
2137 call_write_signal(alu, SIG_ALU_Y_HEIGHT, 200, 0xffff);
2138 call_write_signal(alu, SIG_ALU_400LINE, 0, 0xffffffff);
2140 setup_display_mode();
2145 case SIG_DISPLAY_MULTIPAGE:
2146 set_multimode(data);
2148 case SIG_FM7_SUB_KEY_MASK:
2149 if(firq_mask == flag) {
2150 do_firq(!flag && key_firq_req);
2154 case SIG_FM7_SUB_KEY_FIRQ:
2155 do_firq(flag & !(firq_mask));
2156 key_firq_req = flag;
2164 * Vram accessing functions moved to vram.cpp .
2167 uint32_t DISPLAY::read_mmio(uint32_t addr)
2169 uint32_t retval = 0xff;
2171 if(addr < 0xd400) return 0xff;
2173 #if !defined(_FM77AV_VARIANTS)
2174 raddr = (addr - 0xd400) & 0x000f;
2175 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2176 raddr = (addr - 0xd400) & 0x003f;
2177 #else // FM77AV40EX || FM77AV40SX
2178 raddr = (addr - 0xd400) & 0x00ff;
2181 case 0x00: // Read keyboard
2182 retval = (call_read_data8(keyboard, 0x00) != 0) ? 0xff : 0x7f;
2184 case 0x01: // Read keyboard
2185 retval = call_read_data8(keyboard, 0x01) & 0xff;
2187 case 0x02: // Acknowledge
2196 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2197 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2199 if(!kanjisub) return 0xff;
2200 # if !defined(_FM77_VARIANTS)
2202 return (uint8_t)call_read_data8(kanjiclass2, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
2205 if(kanjiclass1 != NULL) retval = call_read_data8(kanjiclass1, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
2208 if(!kanjisub) return 0xff;
2209 # if !defined(_FM77_VARIANTS)
2211 return (uint8_t)call_read_data8(kanjiclass2, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
2214 if(kanjiclass1 != NULL) retval = call_read_data8(kanjiclass1, KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
2221 retval = set_vramaccess();
2224 { // If use CLR insn to set busy flag, clear flag at first, then delay and set flag.
2226 // Delay at least 3+ clocks (CLR <$0A )
2229 usec = (4000.0 * 1000.0) / 2000000.0;
2231 usec = (4000.0 * 1000.0) / 999000.0;
2233 register_event(this, EVENT_FM7SUB_CLEAR_DELAY, usec, false, NULL); // NEXT CYCLE_
2237 #if defined(_FM77L4)
2239 if(stat_400linecard) {
2240 retval = l4crtc->read_io8(0);
2244 if(stat_400linecard) {
2245 retval = l4crtc->read_io8(1);
2246 // Update parameters.
2251 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
2253 #if defined(_FM77AV_VARIANTS)
2256 retval = call_read_data8(alu, ALU_CMDREG);
2259 retval = call_read_data8(alu, ALU_LOGICAL_COLOR);
2262 retval = call_read_data8(alu, ALU_WRITE_MASKREG);
2265 retval = call_read_data8(alu, ALU_CMP_STATUS_REG);
2268 retval = call_read_data8(alu, ALU_BANK_DISABLE);
2270 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2271 case 0x2f: // VRAM BANK
2272 retval = 0xfc | (vram_bank & 0x03);
2277 retval = get_miscreg();
2281 retval = call_read_data8(keyboard, 0x31);
2284 retval = call_read_data8(keyboard, 0x32);
2290 return (uint8_t)retval;
2293 uint32_t DISPLAY::read_vram_data8(uint32_t addr)
2297 uint32_t color = (addr >> 14) & 0x03;
2298 #if defined(_FM77L4)
2301 offset = offset_point;
2303 if(multimode_accessflags[2]) return 0xff;
2304 vramaddr = ((addr + offset) & 0x3fff) + 0x8000;
2305 return gvram[vramaddr];
2309 return text_vram[addr & 0x0fff];
2310 } else if(addr < 0xc000) {
2311 return subsys_l4[addr - 0x9800];
2317 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2318 if(display_mode == DISPLAY_MODE_8_400L) {
2319 color = vram_bank & 0x03;
2320 if(color > 2) color = 0;
2322 color = (addr >> 14) & 0x03;
2326 //if((multimode_accessmask & (1 << color)) != 0) return 0xff;
2327 if(multimode_accessflags[color]) return 0xff;
2329 #if defined(_FM77AV_VARIANTS)
2330 if (active_page != 0) {
2331 offset = offset_point_bank1;
2333 offset = offset_point;
2336 offset = offset_point;
2338 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2339 if(vram_active_block != 0) {
2340 if(display_mode != DISPLAY_MODE_256k) offset = 0; // Don't scroll at BLOCK 1.
2343 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2344 if(display_mode == DISPLAY_MODE_8_400L) {
2346 uint32_t page_offset_alt = 0;
2347 if(addr >= 0x8000) return 0xff;
2348 color = vram_bank & 0x03;
2349 if(color > 2) color = 0;
2351 pagemod = 0x8000 * color;
2352 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2353 if(vram_active_block != 0) page_offset = 0x18000;
2355 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2356 return gvram[vramaddr];
2359 uint32_t page_offset_alt;
2360 #if defined(_FM77AV40)
2362 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2364 page_offset_alt = 0; // right?
2367 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2369 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
2370 //page_mask = 0x1fff;
2371 //pagemod = addr & 0xe000;
2373 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2375 return gvram[vramaddr];
2377 #elif defined(_FM77AV_VARIANTS)
2379 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2380 return gvram[vramaddr];
2382 #elif defined(_FM77L4) //_FM77L4
2385 vramaddr = (addr + offset) & 0x7fff;
2386 return gvram[vramaddr];
2388 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2389 return gvram[vramaddr];
2393 #else // Others (77/7/8)
2394 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2395 return gvram[vramaddr];
2399 void DISPLAY::write_dma_data8(uint32_t addr, uint32_t data)
2401 uint32_t raddr = (addr & 0xffff) >> 7;
2402 if(write_dma_func_table[raddr] != NULL) {
2403 (this->*write_dma_func_table[raddr])(addr, (uint8_t) data);
2407 void DISPLAY::write_vram_data8(uint32_t addr, uint8_t data)
2410 uint32_t color = (addr >> 14) & 0x03;
2414 #if defined(_FM77AV_VARIANTS)
2415 if (active_page != 0) {
2416 offset = offset_point_bank1;
2418 offset = offset_point;
2421 offset = offset_point;
2423 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2424 if(vram_active_block != 0) offset = 0; // Don't scroll at BLOCK 1.
2427 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2428 if(display_mode == DISPLAY_MODE_8_400L) {
2430 uint32_t page_offset_alt = 0;
2432 if(addr >= 0x8000) {
2435 color = vram_bank & 0x03;
2436 if(color > 2) color = 0;
2438 pagemod = 0x8000 * color;
2439 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2440 if(vram_active_block != 0) page_offset_alt = 0x18000;
2442 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2443 // Reduce data transfer.
2444 tdata = gvram[vramaddr];
2446 naddr = (addr & 0x7fff) >> 4;
2447 gvram[vramaddr] = data;
2448 vram_wrote_table[naddr] = true;
2450 } else if(display_mode == DISPLAY_MODE_256k) {
2451 uint32_t page_offset_alt;
2453 #if defined(_FM77AV40)
2455 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2457 page_offset_alt = 0; // right?
2460 page_offset_alt = 0xc000 * (vram_bank & 0x03);
2462 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
2463 tdata = gvram[vramaddr];
2465 naddr = (addr & page_mask) >> 3;
2466 gvram[vramaddr] = data;
2467 vram_wrote_table[naddr] = true;
2470 } else if(display_mode == DISPLAY_MODE_4096) {
2472 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2473 tdata = gvram[vramaddr];
2475 naddr = (addr & page_mask) >> 3;
2476 gvram[vramaddr] = data;
2477 vram_wrote_table[naddr] = true;
2481 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2482 tdata = gvram[vramaddr];
2484 naddr = (addr & page_mask) >> 4;
2485 gvram[vramaddr] = data;
2486 vram_wrote_table[naddr] = true;
2489 #elif defined(_FM77AV_VARIANTS)
2490 if(display_mode == DISPLAY_MODE_4096) {
2492 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2493 tdata = gvram[vramaddr];
2495 naddr = (addr & page_mask) >> 3;
2496 gvram[vramaddr] = data;
2497 vram_wrote_table[naddr] = true;
2501 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2502 tdata = gvram[vramaddr];
2504 naddr = (addr & page_mask) >> 4;
2505 gvram[vramaddr] = data;
2506 vram_wrote_table[naddr] = true;
2509 #elif defined(_FM77L4) //_FM77L4
2510 if(display_mode == DISPLAY_MODE_1_400L) {
2513 //if(multimode_accessflags[2]) return;
2514 vramaddr = ((addr + offset) & 0x3fff) + 0x8000;
2515 gvram[vramaddr] = data;
2518 vramaddr = (addr + offset) & 0x7fff;
2519 tdata = gvram[vramaddr];
2521 naddr = (addr & 0x7fff) >> 4;
2522 gvram[vramaddr] = data;
2523 vram_wrote_table[naddr] = true;
2530 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2531 tdata = gvram[vramaddr];
2533 naddr = (addr & 0x3fff) >> 4;
2534 gvram[vramaddr] = data;
2535 vram_wrote_table[naddr] = true;
2538 #else // Others (77/7/8)
2541 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
2542 tdata = gvram[vramaddr];
2544 naddr = (addr & 0x3fff) >> 4;
2545 gvram[vramaddr] = data;
2546 vram_wrote_table[naddr] = true;
2552 uint32_t DISPLAY::read_cpu_vram_data8(uint32_t addr)
2555 #if defined(_FM77AV_VARIANTS)
2557 call_read_data8(alu, addr);
2560 return read_vram_data8(addr);
2563 uint32_t DISPLAY::read_dma_vram_data8(uint32_t addr)
2565 return read_vram_data8(addr);
2568 void DISPLAY::init_read_table(void)
2571 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
2572 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cpu_vram_data8;
2573 read_dma_func_table[_at >> 7] = &DISPLAY::read_dma_vram_data8;
2575 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
2576 read_cpu_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2577 read_dma_func_table[_at >> 7] = &DISPLAY::read_console_ram;
2579 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
2580 read_cpu_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2581 read_dma_func_table[_at >> 7] = &DISPLAY::read_work_ram;
2583 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
2584 read_cpu_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2585 read_dma_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
2587 #if defined(_FM77AV_VARIANTS)
2588 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
2589 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2590 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2592 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
2593 read_cpu_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2594 read_dma_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
2597 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
2598 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
2599 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
2602 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
2603 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2604 read_dma_func_table[_at >> 7] = &DISPLAY::read_cgrom;
2606 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
2607 read_cpu_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2608 read_dma_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
2612 uint32_t DISPLAY::read_console_ram(uint32_t addr)
2614 uint32_t raddr = addr & 0xfff;
2615 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2617 if(console_ram_bank >= 1) {
2618 return submem_console_av40[((console_ram_bank - 1) << 12) + raddr];
2622 return console_ram[raddr];
2625 uint32_t DISPLAY::read_work_ram(uint32_t addr)
2627 addr = addr & 0x3ff;
2628 return work_ram[addr];
2632 uint32_t DISPLAY::read_shared_ram(uint32_t addr)
2634 addr = addr - 0xd380;
2635 return shared_ram[addr];
2638 #if defined(_FM77AV_VARIANTS)
2639 uint32_t DISPLAY::read_hidden_ram(uint32_t addr)
2641 if(addr >= 0xd500) {
2642 return submem_hidden[addr - 0xd500];
2648 uint32_t DISPLAY::read_cgrom(uint32_t addr)
2650 #if defined(_FM77AV_VARIANTS)
2651 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2653 return submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)]; //FIXME
2656 return subsys_cg[(addr - 0xd800) + cgrom_bank * 0x800];
2658 return subsys_c[addr - 0xd800];
2662 uint32_t DISPLAY::read_subsys_monitor(uint32_t addr)
2664 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2666 return subsys_ram[addr - 0xe000];
2669 #if defined(_FM77AV_VARIANTS)
2670 switch(subrom_bank_using & 3) {
2672 return subsys_c[addr - 0xd800];
2675 return subsys_a[addr - 0xe000];
2678 return subsys_b[addr - 0xe000];
2681 return subsys_cg[addr - 0xe000];
2684 #elif defined(_FM77L4)
2686 return subsys_l4[addr - 0xb800];
2688 return subsys_c[addr - 0xd800];
2690 return subsys_c[addr - 0xd800];
2694 uint32_t DISPLAY::read_dma_data8(uint32_t addr)
2696 uint32_t raddr = (addr & 0xffff) >> 7;
2697 if(read_dma_func_table[raddr] != NULL) {
2698 return (this->*read_dma_func_table[raddr])(addr);
2703 uint32_t DISPLAY::read_data8(uint32_t addr)
2705 uint32_t raddr = addr;
2707 if(addr < 0x10000) {
2708 raddr = (addr & 0xffff) >> 7;
2709 if(read_cpu_func_table[raddr] != NULL) {
2710 return (this->*read_cpu_func_table[raddr])(addr);
2715 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2716 return dpalette_data[addr - FM7_SUBMEM_OFFSET_DPALETTE];
2719 #if defined(_FM77AV_VARIANTS)
2721 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2722 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2723 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2724 if(vram_active_block != 0) {
2728 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2729 if(display_mode == DISPLAY_MODE_8_400L) {
2730 uint32_t page_offset_alt = 0;
2733 color = (addr & 0x18000) >> 15;
2734 if(color > 2) color = 0;
2735 pagemod = 0x8000 * color;
2736 if (active_page != 0) {
2737 offset = offset_point_bank1 << 1;
2739 offset = offset_point << 1;
2741 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2742 if(vram_active_block != 0) {
2743 page_offset_alt = 0x18000;
2747 return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset_alt];
2750 return read_vram_data8(addr);
2757 * Vram accessing functions moved to vram.cpp .
2760 void DISPLAY::write_mmio(uint32_t addr, uint8_t data)
2763 uint8_t active_block_old;
2765 if(addr < 0xd400) return;
2767 #if !defined(_FM77AV_VARIANTS)
2768 addr = (addr - 0xd400) & 0x000f;
2769 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2770 addr = (addr - 0xd400) & 0x003f;
2771 #else // FM77AV40EX || FM77AV40SX
2772 addr = (addr - 0xd400) & 0x00ff;
2774 io_w_latch[addr] = (uint8_t)data;
2776 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4)
2779 set_cyclesteal((uint8_t)data);
2780 # if defined(_FM77L4)
2781 setup_400linemode((uint8_t)data);
2785 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2786 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2789 if(!kanjisub) return;
2790 kanjiaddr.w.h = 0x0000;
2791 kanjiaddr.b.h = (uint8_t) data;
2794 if(!kanjisub) return;
2795 kanjiaddr.w.h = 0x0000;
2796 kanjiaddr.b.l = (uint8_t)data;
2809 if(delay_busy) { // If WRITE after READ immediately.Perhaps use CLR insn.
2811 // Delay at least 5+ clocks (CLR $D40A or CLR (INDEX = $D40A))
2813 usec = (6000.0 * 1000.0) / 2000000.0;
2815 usec = (6000.0 * 1000.0) / 999000.0;
2817 register_event(this, EVENT_FM7SUB_DELAY_BUSY, usec, false, NULL); // NEXT CYCLE_
2825 #if defined(_FM77L4)
2827 if(stat_400linecard) {
2828 l4crtc->write_io8(0, data & 0x1f);
2832 if(stat_400linecard) {
2833 l4crtc->write_io8(1, data);
2834 // Update parameters.
2835 uint8_t crtc_addr = l4crtc->read_io8(0);
2836 const uint8_t *regs = l4crtc->get_regs();
2837 switch(crtc_addr & 0x1f) {
2840 cursor_addr.w.l &= 0x0ffc;
2841 cursor_addr.w.l |= (((uint16_t)regs[14]) << 10);
2842 cursor_addr.w.l |= (((uint16_t)regs[15]) << 2);
2844 cursor_addr.w.l += 2;
2846 cursor_addr.w.l &= 0xfff;
2848 if((crtc_addr & 0x1f) == 10) {
2850 if(event_id_l4_cursor_blink >= 0) {
2851 cancel_event(this, event_id_l4_cursor_blink);
2853 usec = ((data & 0x20) == 0) ? 160.0 : 320.0;
2854 usec = usec * 1000.0;
2855 register_event(this, EVENT_FM7SUB_CURSOR_BLINK, true, usec, &event_id_l4_cursor_blink);
2859 text_start_addr.w.l &= 0x03fc;
2860 text_start_addr.w.l |= (((uint16_t)data & 3) << 10);
2861 text_scroll_count++;
2862 if((text_scroll_count & 1) == 0) {
2867 text_start_addr.w.l &= 0xfc00;
2868 text_start_addr.w.l |= ((uint16_t)data << 2);
2869 text_scroll_count++;
2870 if((text_scroll_count & 1) == 0) {
2875 text_scroll_count++;
2876 if((text_scroll_count & 1) == 0) {
2878 cursor_addr.w.l &= 0x0ffc;
2879 cursor_addr.w.l |= (((uint16_t)regs[14]) << 10);
2880 cursor_addr.w.l |= (((uint16_t)regs[15]) << 2);
2882 cursor_addr.w.l += 2;
2884 cursor_addr.w.l &= 0xfff;
2895 call_write_signal(keyboard, SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
2900 rval = (uint8_t)data;
2901 if(offset_changed[active_page]) {
2902 #if defined(_FM77AV_VARIANTS)
2903 if(active_page != 0) {
2904 tmp_offset_point[active_page].d = offset_point_bank1;
2906 tmp_offset_point[active_page].d = offset_point;
2909 tmp_offset_point[active_page].d = offset_point;
2912 tmp_offset_point[active_page].w.h = 0x0000;
2914 tmp_offset_point[active_page].b.h = rval;
2916 tmp_offset_point[active_page].b.l = rval;
2918 offset_changed[active_page] = !offset_changed[active_page];
2919 if(offset_changed[active_page]) {
2921 #if defined(_FM77AV_VARIANTS)
2922 if(active_page != 0) {
2924 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fff;
2926 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fe0;
2930 offset_point = tmp_offset_point[active_page].d & 0x007fff;
2932 offset_point = tmp_offset_point[active_page].d & 0x007fe0;
2936 offset_point = tmp_offset_point[active_page].d & 0x7fe0;
2940 #if defined(_FM77AV_VARIANTS)
2943 alu_write_cmdreg(data);
2946 alu_write_logical_color(data);
2949 alu_write_mask_reg(data);
2952 alu_write_disable_reg(data);
2955 alu_write_offsetreg_hi(data);
2958 alu_write_offsetreg_lo(data);
2961 alu_write_linepattern_hi(data);
2964 alu_write_linepattern_lo(data);
2966 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2968 console_ram_bank = (data & 0x18) >> 3;
2969 if(console_ram_bank > 2) console_ram_bank = 0;
2970 cgram_bank = data & 0x07;
2971 kanji_level2 = ((data & 0x80) == 0) ? false : true;
2973 case 0x2f: // VRAM BANK
2974 vram_bank = data & 0x03;
2975 if(vram_bank > 2) vram_bank = 0;
2985 call_write_data8(keyboard, 0x31, data);
2987 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2989 active_block_old = vram_active_block;
2990 vram_active_block = data & 0x01;
2991 if(vram_display_block != (((data & 0x10) != 0) ? 1 : 0)) vram_wrote = true;
2992 vram_display_block = ((data & 0x10) != 0) ? 1 : 0;
2993 if(vram_active_block != active_block_old) setup_display_mode();
2998 tmpvar.d = window_xbegin * 8;
3001 tmpvar.b.h = data & 0x03;
3003 tmpvar.b.l = data & 0xf8;
3005 if(mode320 || mode256k) {
3006 if(tmpvar.d > 320) tmpvar.d = 320;
3008 if(tmpvar.d > 640) tmpvar.d = 640;
3010 window_xbegin = tmpvar.d / 8;
3015 tmpvar.d = window_xend * 8;
3018 tmpvar.b.h = data & 0x03;
3020 tmpvar.b.l = data & 0xf8;
3022 if(mode320 || mode256k) {
3023 if(tmpvar.d > 320) tmpvar.d = 320;
3025 if(tmpvar.d > 640) tmpvar.d = 640;
3027 window_xend = tmpvar.d / 8;
3032 tmpvar.d = window_low;
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_low = tmpvar.d;
3050 tmpvar.d = window_high;
3053 tmpvar.b.h = data & 0x03;
3055 tmpvar.b.l = data & 0xff;
3057 if(display_mode == DISPLAY_MODE_8_400L) {
3058 if(tmpvar.d > 400) tmpvar.d = 400;
3061 if(tmpvar.d > 400) tmpvar.d = 400;
3063 window_high = tmpvar.d;
3069 #if defined(_FM77AV_VARIANTS)
3071 if((addr >= 0x13) && (addr <= 0x1a)) {
3072 alu_write_cmpdata_reg(addr - 0x13, data);
3073 } else if((addr >= 0x1c) && (addr <= 0x1e)) {
3074 alu_write_tilepaint_data(addr, data);
3075 } else if((addr >= 0x24) && (addr <= 0x2b)) {
3076 alu_write_line_position(addr - 0x24, data);
3083 void DISPLAY::init_write_table(void)
3086 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
3087 write_cpu_func_table[_at >> 7] = &DISPLAY::write_cpu_vram_data8;
3088 write_dma_func_table[_at >> 7] = &DISPLAY::write_dma_vram_data8;
3090 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
3091 write_cpu_func_table[_at >> 7] = &DISPLAY::write_console_ram;
3092 write_dma_func_table[_at >> 7] = &DISPLAY::write_console_ram;
3094 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
3095 write_cpu_func_table[_at >> 7] = &DISPLAY::write_work_ram;
3096 write_dma_func_table[_at >> 7] = &DISPLAY::write_work_ram;
3098 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
3099 write_cpu_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
3100 write_dma_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
3102 #if defined(_FM77AV_VARIANTS)
3103 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
3104 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
3105 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
3107 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
3108 write_cpu_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
3109 write_dma_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
3112 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
3113 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
3114 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
3117 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
3118 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
3119 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
3120 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
3122 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
3123 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
3124 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
3127 for(_at = 0xd800; _at < 0x10000; _at += 0x80) {
3128 write_cpu_func_table[_at >> 7] = &DISPLAY::write_dummy;
3129 write_dma_func_table[_at >> 7] = &DISPLAY::write_dummy;
3134 void DISPLAY::write_console_ram(uint32_t addr, uint8_t data)
3136 uint32_t raddr = addr & 0xfff;
3137 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3139 if(console_ram_bank >= 1) {
3140 submem_console_av40[((console_ram_bank - 1) << 12) + raddr] = data;
3145 console_ram[raddr] = data;
3149 void DISPLAY::write_work_ram(uint32_t addr, uint8_t data)
3151 uint32_t raddr = addr & 0xfff;
3152 work_ram[raddr] = data;
3156 void DISPLAY::write_shared_ram(uint32_t addr, uint8_t data)
3158 uint32_t raddr = addr & 0x7f;
3159 shared_ram[raddr] = data;
3163 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
3164 void DISPLAY::write_subsys_cgram(uint32_t addr, uint8_t data)
3166 uint32_t raddr = addr - 0xd800;
3167 if(ram_protect) return;
3168 if(!monitor_ram) return;
3169 submem_cgram[cgram_bank * 0x0800 + raddr] = data; //FIXME
3172 void DISPLAY::write_subsys_ram(uint32_t addr, uint8_t data)
3174 if(ram_protect) return;
3175 if(!monitor_ram) return;
3176 subsys_ram[addr - 0xe000] = data; //FIXME
3180 #if defined(_FM77AV_VARIANTS)
3181 void DISPLAY::write_hidden_ram(uint32_t addr, uint8_t data)
3183 submem_hidden[addr - 0xd500] = data;
3188 void DISPLAY::write_cpu_vram_data8(uint32_t addr, uint8_t data)
3190 uint32_t color = (addr & 0xc000) >> 14;
3191 #if defined(_FM77AV_VARIANTS)
3193 call_read_data8(alu, addr);
3197 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3198 if(display_mode == DISPLAY_MODE_8_400L) {
3199 color = vram_bank & 0x03;
3200 if(color > 2) color = 0;
3203 #if defined(_FM77L4)
3207 if(!(multimode_accessflags[2])) write_vram_data8(addr & 0x7fff, data);
3210 } else if(addr < 0x9800) {
3213 addr = addr & 0x0fff;
3214 if(text_vram[addr] != data) {
3215 text_vram[addr] = data;
3217 x = ((addr / 2) % 40) / 8;
3218 y = (addr / 2) / 40;
3219 } else { // Width 80
3220 x = ((addr / 2) % 80) / 8;
3221 y = (addr / 2) / 80;
3223 for(int yy = 0; yy < 8; yy++) {
3224 naddr = (y + yy) * 5 + x;
3225 vram_wrote_table[naddr] = true;
3235 //if((multimode_accessmask & (1 << color)) != 0) return;
3236 if(multimode_accessflags[color]) return;
3238 write_vram_data8(addr & 0xffff, data);
3241 void DISPLAY::write_dma_vram_data8(uint32_t addr, uint8_t data)
3243 uint32_t color = (addr & 0xc000) >> 14;
3244 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3245 if(display_mode == DISPLAY_MODE_8_400L) {
3246 color = vram_bank & 0x03;
3247 if(color > 2) color = 0;
3251 //if((multimode_accessmask & (1 << color)) != 0) return;
3252 if(multimode_accessflags[color]) return;
3254 write_vram_data8(addr & 0xffff, data);
3257 void DISPLAY::write_dummy(uint32_t addr, uint8_t data)
3261 void DISPLAY::write_data8(uint32_t addr, uint32_t data)
3265 //uint32_t page_offset = 0x0000;
3266 uint8_t val8 = data & 0xff;
3267 uint32_t color = (addr & 0xc000) >> 14;
3270 if(addr < 0x10000) {
3271 void (*_write_func)(uint32_t, uint32_t);
3272 raddr = (addr & 0xffff) >> 7;
3273 if(write_cpu_func_table[raddr] != NULL) {
3274 (this->*write_cpu_func_table[raddr])(addr, (uint8_t)data);
3280 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
3281 set_dpalette(addr - FM7_SUBMEM_OFFSET_DPALETTE, val8);
3285 #if defined(_FM77AV_VARIANTS)
3287 else if(addr == FM7_SUBMEM_OFFSET_APALETTE_R) {
3288 set_apalette_r(val8);
3290 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_G) {
3291 set_apalette_g(val8);
3293 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_B) {
3294 set_apalette_b(val8);
3296 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_HI) {
3297 set_apalette_index_hi(val8);
3299 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_LO) {
3300 set_apalette_index_lo(val8);
3304 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
3305 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
3306 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3307 if(display_mode == DISPLAY_MODE_8_400L) {
3310 uint32_t page_offset_alt = 0;
3312 color = (addr & 0x18000) >> 15;
3313 if(color > 2) color = 0;
3314 if (active_page != 0) {
3315 offset = offset_point_bank1 << 1;
3317 offset = offset_point << 1;
3319 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3320 if(vram_active_block != 0) {
3321 page_offset_alt = 0x18000;
3325 naddr = (addr & 0x7fff) >> 4;
3326 pagemod = 0x8000 * color;
3327 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
3328 tdata = gvram[vramaddr];
3329 if(tdata != (uint8_t)data) {
3330 gvram[vramaddr] = data;
3331 vram_wrote_table[naddr] = true;
3335 write_vram_data8(addr, data);
3337 write_vram_data8(addr, data);
3339 //if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
3346 uint32_t DISPLAY::read_bios(const _TCHAR *name, uint8_t *ptr, uint32_t size)
3352 if((name == NULL) || (ptr == NULL)) return 0;
3353 s = create_local_path(name);
3354 if(s == NULL) return 0;
3356 if(!fio.Fopen(s, FILEIO_READ_BINARY)) return 0;
3357 blocks = fio.Fread(ptr, size, 1);
3360 return blocks * size;
3364 void DISPLAY::initialize()
3368 memset(io_w_latch, 0xff, sizeof(io_w_latch));
3369 screen_update_flag = true;
3370 memset(gvram, 0x00, sizeof(gvram));
3371 vram_wrote_shadow = false;
3372 memset(gvram_shadow, 0x00, sizeof(gvram_shadow));
3373 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = false;
3374 for(i = 0; i < 411; i++) vram_draw_table[i] = false;
3375 force_update = false;
3377 memset(console_ram, 0x00, sizeof(console_ram));
3378 memset(work_ram, 0x00, sizeof(work_ram));
3379 memset(shared_ram, 0x00, sizeof(shared_ram));
3380 memset(subsys_c, 0xff, sizeof(subsys_c));
3381 need_transfer_line = true;
3382 frame_skip_count_draw = 3;
3383 frame_skip_count_transfer = 3;
3385 diag_load_subrom_c = false;
3387 if(read_bios(_T(ROM_FM8_SUBSYSTEM), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
3388 this->out_debug_log(_T("SUBSYSTEM ROM READING : %s"), diag_load_subrom_c ? "OK" : "NG");
3390 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_C), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
3391 this->out_debug_log(_T("SUBSYSTEM ROM Type C READING : %s"), diag_load_subrom_c ? "OK" : "NG");
3393 #if defined(_FM77AV_VARIANTS)
3394 memset(subsys_a, 0xff, sizeof(subsys_a));
3395 memset(subsys_b, 0xff, sizeof(subsys_b));
3396 memset(subsys_cg, 0xff, sizeof(subsys_cg));
3397 memset(submem_hidden, 0x00, sizeof(submem_hidden));
3399 diag_load_subrom_a = false;
3400 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_A), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
3401 this->out_debug_log(_T("SUBSYSTEM ROM Type A READING : %s"), diag_load_subrom_a ? "OK" : "NG");
3403 diag_load_subrom_b = false;
3404 if(read_bios(_T(ROM_FM7_SUBSYSTEM_TYPE_B), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
3405 this->out_debug_log(_T("SUBSYSTEM ROM Type B READING : %s"), diag_load_subrom_b ? "OK" : "NG");
3407 diag_load_subrom_cg = false;
3408 if(read_bios(_T(ROM_FM7_SUBSYSTEM_CG), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
3409 this->out_debug_log(_T("SUBSYSTEM CG ROM READING : %s"), diag_load_subrom_cg ? "OK" : "NG");
3410 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
3411 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3412 memset(subsys_ram, 0x00, sizeof(subsys_ram));
3413 memset(submem_cgram, 0x00, sizeof(submem_cgram));
3414 memset(submem_console_av40, 0x00, sizeof(submem_console_av40));
3418 #if defined(_FM77L4)
3419 memset(subsys_cg_l4, 0xff, sizeof(subsys_cg_l4));
3420 memset(subsys_l4, 0xff, sizeof(subsys_l4));
3422 read_bios(_T(ROM_FM77_400LINE_ANKCG), subsys_cg_l4, sizeof(subsys_cg_l4));
3423 read_bios(_T(ROM_FM77_400LINE_SUBSYS), subsys_l4, sizeof(subsys_l4));
3424 memset(text_vram, 0x00, sizeof(text_vram));
3425 //memset(crtc_regs, 0x00, sizeof(crtc_regs));
3429 text_width40 = false;
3432 cursor_blink = true;
3434 text_start_addr.d = 0x0000;
3442 text_scroll_count = 0;
3444 event_id_l4_cursor_blink = -1;
3445 event_id_l4_text_blink = -1;
3451 #if defined(_FM77AV_VARIANTS)
3453 apalette_index.d = 0;
3454 for(i = 0; i < 4096; i++) {
3455 analog_palette_r[i] = i & 0x0f0;
3456 analog_palette_g[i] = (i & 0xf00) >> 4;
3457 analog_palette_b[i] = (i & 0x00f) << 4;
3459 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
3462 for(i = 0; i < 8; i++) set_dpalette(i, i);
3463 #if defined(USE_GREEN_DISPLAY)
3464 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3465 use_green_monitor = false;
3468 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3469 //#if defined(_FM77AV_VARIANTS)
3470 hblank_event_id = -1;
3471 hdisp_event_id = -1;
3472 vsync_event_id = -1;
3473 vstart_event_id = -1;
3480 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
3481 is_cyclesteal = true;
3483 is_cyclesteal = false;
3485 multimode_accessmask = multimode_dispmask = 0;
3486 for(i = 0; i < 4; i++) {
3487 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
3488 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
3491 prev_clock = SUBCLOCK_NORMAL;
3495 key_firq_req = false; //firq_mask = true;
3496 frame_skip_count_transfer = 3;
3497 frame_skip_count_draw = 3;
3498 #if !defined(FIXED_FRAMEBUFFER_SIZE)
3499 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
3501 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
3503 emu->set_vm_screen_lines(200);
3504 #if defined(_FM77AV40SX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3505 mode400line = false;
3507 #elif defined(_FM77L4)
3508 mode400line = false;
3511 palette_changed = true;
3512 //#if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
3513 //register_vline_event(this);
3514 register_frame_event(this);
3516 setup_display_mode();
3519 void DISPLAY::release()
3523 #define STATE_VERSION 12
3525 bool DISPLAY::process_state(FILEIO *state_fio, bool loading)
3527 if(!state_fio->StateCheckUint32(STATE_VERSION)) {
3530 if(!state_fio->StateCheckInt32(this_device_id)) {
3535 state_fio->StateValue(delay_busy);
3536 state_fio->StateValue(halt_flag);
3537 state_fio->StateValue(active_page);
3538 state_fio->StateValue(sub_busy);
3539 state_fio->StateValue(crt_flag);
3540 state_fio->StateValue(vram_wrote);
3541 state_fio->StateValue(is_cyclesteal);
3543 state_fio->StateValue(clock_fast);
3545 #if defined(_FM77AV_VARIANTS)
3546 state_fio->StateValue(subcpu_resetreq);
3547 state_fio->StateValue(power_on_reset);
3549 state_fio->StateValue(cancel_request);
3550 state_fio->StateValue(key_firq_req);
3551 state_fio->StateValue(display_mode);
3552 state_fio->StateValue(prev_clock);
3554 state_fio->StateArray(dpalette_data, sizeof(dpalette_data), 1);
3555 state_fio->StateValue(multimode_accessmask);
3556 state_fio->StateValue(multimode_dispmask);
3558 state_fio->StateValue(offset_point);
3559 #if defined(_FM77AV_VARIANTS)
3560 state_fio->StateValue(offset_point_bank1);
3562 //for(i = 0; i < 2; i++) {
3563 state_fio->StateArray(tmp_offset_point, sizeof(tmp_offset_point), 1);
3564 state_fio->StateArray(offset_changed, sizeof(offset_changed), 1);
3566 state_fio->StateValue(offset_77av);
3567 state_fio->StateValue(diag_load_subrom_c);
3568 state_fio->StateArray(io_w_latch, sizeof(io_w_latch), 1);
3569 state_fio->StateArray(console_ram, sizeof(console_ram), 1);
3570 state_fio->StateArray(work_ram, sizeof(work_ram), 1);
3571 state_fio->StateArray(shared_ram, sizeof(shared_ram), 1);
3572 state_fio->StateArray(subsys_c, sizeof(subsys_c), 1);
3573 state_fio->StateArray(gvram, sizeof(gvram), 1);
3574 state_fio->StateArray(gvram_shadow, sizeof(gvram_shadow), 1);
3575 #if defined(_FM77_VARIANTS)
3576 state_fio->StateValue(kanjisub);
3577 state_fio->StateValue(kanjiaddr.d);
3578 # if defined(_FM77L4)
3579 state_fio->StateValue(mode400line);
3580 state_fio->StateValue(stat_400linecard);
3582 #elif defined(_FM77AV_VARIANTS)
3583 state_fio->StateValue(kanjisub);
3584 state_fio->StateValue(kanjiaddr.d);
3585 state_fio->StateValue(mode320);
3586 state_fio->StateValue(cgrom_bank);
3587 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3588 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3589 state_fio->StateValue(vram_bank);
3591 state_fio->StateValue(displine);
3592 state_fio->StateValue(subrom_bank);
3593 state_fio->StateValue(subrom_bank_using);
3594 state_fio->StateValue(nmi_enable);
3595 state_fio->StateValue(use_alu);
3596 state_fio->StateValue(apalette_index.d);
3597 state_fio->StateArray(analog_palette_r, sizeof(analog_palette_r), 1);
3598 state_fio->StateArray(analog_palette_g, sizeof(analog_palette_g), 1);
3599 state_fio->StateArray(analog_palette_b, sizeof(analog_palette_b), 1);
3600 state_fio->StateValue(diag_load_subrom_a);
3601 state_fio->StateValue(diag_load_subrom_b);
3602 state_fio->StateValue(diag_load_subrom_cg);
3604 state_fio->StateArray(subsys_a, sizeof(subsys_a), 1);
3605 state_fio->StateArray(subsys_b, sizeof(subsys_b), 1);
3606 state_fio->StateArray(subsys_cg, sizeof(subsys_cg), 1);
3607 state_fio->StateArray(submem_hidden, sizeof(submem_hidden), 1);
3608 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
3609 state_fio->StateValue(mode400line);
3610 state_fio->StateValue(mode256k);
3611 state_fio->StateValue(monitor_ram);
3612 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
3613 state_fio->StateValue(window_low);
3614 state_fio->StateValue(window_high);
3615 state_fio->StateValue(window_xbegin);
3616 state_fio->StateValue(window_xend);
3617 state_fio->StateValue(window_opened);
3619 state_fio->StateValue(kanji_level2);
3620 state_fio->StateValue(vram_active_block);
3621 state_fio->StateValue(vram_display_block);
3622 state_fio->StateValue(console_ram_bank);
3623 state_fio->StateValue(ram_protect);
3624 state_fio->StateValue(cgram_bank);
3625 state_fio->StateArray(subsys_ram, sizeof(subsys_ram), 1);
3626 state_fio->StateArray(submem_cgram, sizeof(submem_cgram), 1);
3627 state_fio->StateArray(submem_console_av40, sizeof(submem_console_av40), 1);
3633 state_fio->StateValue(nmi_event_id);
3634 //#if defined(_FM77AV_VARIANTS)
3635 state_fio->StateValue(hblank_event_id);
3636 state_fio->StateValue(hdisp_event_id);
3637 state_fio->StateValue(vsync_event_id);
3638 state_fio->StateValue(vstart_event_id);
3640 state_fio->StateValue(firq_mask);
3641 state_fio->StateValue(vram_accessflag);
3642 state_fio->StateValue(display_page);
3643 state_fio->StateValue(display_page_bak);
3644 state_fio->StateValue(vblank);
3645 state_fio->StateValue(vsync);
3646 state_fio->StateValue(hblank);
3647 state_fio->StateValue(vblank_count);
3649 #if defined(_FM77L4)
3650 state_fio->StateArray(subsys_cg_l4, sizeof(subsys_cg_l4), 1);
3651 state_fio->StateArray(subsys_l4, sizeof(subsys_l4), 1);
3652 state_fio->StateArray(text_vram, sizeof(text_vram), 1);
3653 //state_fio->Fwrite(crtc_regs, sizeof(crtc_regs), 1);
3654 state_fio->StateValue(workram_l4);
3655 state_fio->StateValue(cursor_lsb);
3656 state_fio->StateValue(text_width40);
3658 state_fio->StateValue(text_blink);
3659 state_fio->StateValue(cursor_blink);
3661 state_fio->StateValue(text_start_addr.d);
3662 state_fio->StateValue(text_lines);
3663 state_fio->StateValue(text_xmax);
3665 state_fio->StateValue(cursor_addr.d);
3666 state_fio->StateValue(cursor_start);
3667 state_fio->StateValue(cursor_end);
3668 state_fio->StateValue(cursor_type);
3669 state_fio->StateValue(text_scroll_count);
3671 state_fio->StateValue(event_id_l4_cursor_blink);
3672 state_fio->StateValue(event_id_l4_text_blink);
3678 crt_flag_bak = true;
3679 for(i = 0; i < 411 * 5; i++) vram_wrote_table[i] = true;
3680 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
3682 for(addr = 0; addr < 8; addr++) set_dpalette(addr, addr);
3683 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3684 #if defined(USE_GREEN_DISPLAY)
3685 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3689 for(addr = 0; addr < 8; addr++) set_dpalette(addr, dpalette_data[addr]);
3690 memcpy(dpalette_pixel, dpalette_pixel_tmp, sizeof(dpalette_pixel));
3691 #if defined(USE_GREEN_DISPLAY)
3692 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3694 for(i = 0; i < 4; i++) {
3695 multimode_accessflags[i] = ((multimode_accessmask & (1 << i)) != 0) ? true : false;
3696 multimode_dispflags[i] = ((multimode_dispmask & (1 << i)) != 0) ? true : false;
3699 #if defined(_FM77_VARIANTS)
3700 # if defined(_FM77L4)
3702 #elif defined(_FM77AV_VARIANTS)
3703 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
3704 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
3706 screen_update_flag = true;
3707 for(i = 0; i < 4096; i++) calc_apalette(i);
3708 memcpy(analog_palette_pixel, analog_palette_pixel_tmp, sizeof(analog_palette_pixel));
3711 palette_changed = true;
3712 vram_wrote_shadow = true; // Force Draw
3713 this->draw_screen();
3715 frame_skip_count_draw = 3;
3716 frame_skip_count_transfer = 3;
3717 need_transfer_line = true;
3718 #if defined(USE_GREEN_DISPLAY) && defined(USE_MONITOR_TYPE)
3719 memcpy(dpalette_pixel_green, dpalette_green_tmp, sizeof(dpalette_pixel_green));
3720 switch(config.monitor_type) {
3721 case FM7_MONITOR_GREEN:
3722 use_green_monitor = true;
3724 case FM7_MONITOR_STANDARD:
3726 use_green_monitor = false;
3730 //use_green_monitor = false;
3732 force_update = true;
3733 setup_display_mode();