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 DISPLAY::DISPLAY(VM* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
23 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
26 #elif defined(_FM77_VARIANTS)
29 #if defined(_FM77AV_VARIANTS)
35 for(int i = 0; i < 256; i++) {
36 uint16_t n = (uint16_t)i;
37 for(int j = 0; j < 8; j++) {
38 bit_trans_table_0[i][j] = n & 0x80;
39 bit_trans_table_1[i][j] = ((n & 0x80) != 0) ? 0x40 : 0;
40 bit_trans_table_2[i][j] = ((n & 0x80) != 0) ? 0x20 : 0;
41 bit_trans_table_3[i][j] = ((n & 0x80) != 0) ? 0x10 : 0;
42 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
43 bit_trans_table_4[i][j] = ((n & 0x80) != 0) ? 0x08 : 0;
44 bit_trans_table_5[i][j] = ((n & 0x80) != 0) ? 0x04 : 0;
51 set_device_name(_T("DISPLAY SUBSYSTEM"));
59 void DISPLAY::reset_cpuonly()
63 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
64 mainio->write_signal(SIG_FM7_SUB_HALT, 0x00, 0xff);
67 palette_changed = true;
68 multimode_accessmask = 0;
69 multimode_dispmask = 0;
71 //cancel_request = false;
72 switch(config.cpu_type){
83 for(i = 0; i < 2; i++) {
84 offset_changed[i] = true;
85 tmp_offset_point[i].d = 0;
88 vram_wrote_shadow = true;
89 for(i = 0; i < 411; i++) vram_wrote_table[i] = true;
90 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
94 #if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
100 if(hblank_event_id >= 0) cancel_event(this, hblank_event_id);
101 if(hdisp_event_id >= 0) cancel_event(this, hdisp_event_id);
102 if(vsync_event_id >= 0) cancel_event(this, vsync_event_id);
103 if(vstart_event_id >= 0) cancel_event(this, vstart_event_id);
104 hblank_event_id = -1;
107 vstart_event_id = -1;
108 if(display_mode == DISPLAY_MODE_8_400L) {
109 usec = 0.33 * 1000.0;
111 usec = 0.51 * 1000.0;
114 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
115 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
116 mainio->write_signal(SIG_DISPLAY_VSYNC, 0xff, 0xff);
118 #if defined(_FM77AV_VARIANTS)
120 offset_point_bank1 = 0;
122 display_page_bak = 0;
124 subcpu_resetreq = false;
125 subrom_bank_using = subrom_bank;
130 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
132 vram_display_block = 0;
133 vram_active_block = 0;
135 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
140 window_opened = false;
145 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
146 alu->write_signal(SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
147 alu->write_signal(SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400: 200, 0xffff);
148 alu->write_signal(SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xffffffff : 0, 0xffffffff);
150 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
151 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
152 alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
154 alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
155 alu->write_signal(SIG_ALU_PLANES, 3, 3);
158 for(i = 0; i < 8; i++) set_dpalette(i, i);
159 do_firq(!firq_mask && key_firq_req);
161 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
163 kanjiaddr.d = 0x00000000;
164 # if defined(_FM77L4)
166 stat_400linecard = false;
171 frame_skip_count_draw = 3;
172 frame_skip_count_transfer = 3;
173 need_transfer_line = true;
174 setup_display_mode();
178 void DISPLAY::reset()
181 memset(io_w_latch, 0xff, sizeof(io_w_latch));
183 vram_accessflag = true;
184 display_mode = DISPLAY_MODE_8_200L;
186 screen_update_flag = true;
189 cancel_request = false;
190 #if defined(_FM77AV_VARIANTS)
192 apalette_index.d = 0;
193 for(i = 0; i < 4096; i++) {
194 analog_palette_r[i] = i & 0x0f0;
195 analog_palette_g[i] = (i & 0xf00) >> 4;
196 analog_palette_b[i] = (i & 0x00f) << 4;
201 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
208 #elif defined(_FM77L4)
211 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
212 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
213 key_firq_req = false; //firq_mask = true;
217 #if defined(_FM77AV_VARIANTS)
218 power_on_reset = false;
219 for(i = 0; i < 411; i++) vram_wrote_table[i] = false;
223 for(i = 0; i < 8; i++) set_dpalette(i, i);
224 multimode_accessmask = 0x00;
225 multimode_dispmask = 0x00;
230 if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
231 register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
232 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
236 void DISPLAY::setup_display_mode(void)
238 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
239 if(display_mode == DISPLAY_MODE_8_400L) {
240 page_offset = 0x0000;
241 pagemod_mask = 0x18000;
243 } else if(display_mode == DISPLAY_MODE_256k) {
244 if(active_page != 0) {
245 page_offset = 0xc000;
247 page_offset = 0x0000;
249 pagemod_mask = 0xe000;
251 } else if(display_mode == DISPLAY_MODE_4096) {
252 if(active_page != 0) {
253 page_offset = 0xc000;
255 page_offset = 0x0000;
257 pagemod_mask = 0xe000;
260 if(active_page != 0) {
261 page_offset = 0xc000;
263 page_offset = 0x0000;
265 pagemod_mask = 0xc000;
268 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
269 if(vram_active_block != 0) page_offset += 0x18000;
271 #elif defined(_FM77AV_VARIANTS)
274 pagemod_mask = 0xe000;
275 } else { // 640x200, 8colors
277 pagemod_mask = 0xc000;
279 if(active_page != 0) {
280 page_offset = 0xc000;
282 page_offset = 0x0000;
284 #elif defined(_FM77L4)
285 if(display_mode == DISPLAY_MODE_8_400L) {
287 pagemod_mask = 0xe000;
288 } else { // 640x200, 8colors
290 pagemod_mask = 0xc000;
292 page_offset = 0x0000;
294 page_offset = 0x0000;
295 pagemod_mask = 0xc000;
299 void DISPLAY::update_config()
303 is_cyclesteal = ((config.dipswitch & FM7_DIPSW_CYCLESTEAL) != 0) ? true : false;
309 * Vram accessing functions moved to vram.cpp .
312 void DISPLAY::do_irq(bool flag)
314 subcpu->write_signal(SIG_CPU_IRQ, flag ? 1: 0, 1);
317 void DISPLAY::do_firq(bool flag)
319 subcpu->write_signal(SIG_CPU_FIRQ, flag ? 1: 0, 1);
322 void DISPLAY::do_nmi(bool flag)
324 #if defined(_FM77AV_VARIANTS)
325 if(!nmi_enable) flag = false;
327 subcpu->write_signal(SIG_CPU_NMI, flag ? 1 : 0, 1);
330 void DISPLAY::set_multimode(uint8_t val)
333 multimode_accessmask = val & 0x07;
334 multimode_dispmask = (val & 0x70) >> 4;
336 # if defined(_FM77AV_VARIANTS)
337 alu->write_signal(SIG_ALU_MULTIPAGE, multimode_accessmask, 0x07);
342 uint8_t DISPLAY::get_multimode(void)
348 val = multimode_accessmask & 0x07;
349 val |= ((multimode_dispmask << 4) & 0x70);
355 uint8_t DISPLAY::get_cpuaccessmask(void)
357 return multimode_accessmask & 0x07;
360 void DISPLAY::set_dpalette(uint32_t addr, uint8_t val)
364 dpalette_data[addr] = val | 0xf8; //0b11111000;
365 b = ((val & 0x01) != 0x00)? 255 : 0x00;
366 r = ((val & 0x02) != 0x00)? 255 : 0x00;
367 g = ((val & 0x04) != 0x00)? 255 : 0x00;
369 dpalette_pixel[addr] = RGB_COLOR(r, g, b);
370 palette_changed = true;
373 uint8_t DISPLAY::get_dpalette(uint32_t addr)
381 data = dpalette_data[addr];
386 void DISPLAY::halt_subcpu(void)
388 subcpu->write_signal(SIG_CPU_BUSREQ, 0x01, 0x01);
391 void DISPLAY::go_subcpu(void)
393 subcpu->write_signal(SIG_CPU_BUSREQ, 0x00, 0x01);
396 void DISPLAY::enter_display(void)
400 subclock = SUBCLOCK_NORMAL;
402 subclock = SUBCLOCK_SLOW;
404 if(!is_cyclesteal && vram_accessflag) {
405 subclock = subclock / 3;
407 if(prev_clock != subclock) p_vm->set_cpu_clock(subcpu, subclock);
408 prev_clock = subclock;
411 void DISPLAY::leave_display(void)
415 void DISPLAY::halt_subsystem(void)
421 void DISPLAY::restart_subsystem(void)
424 #if defined(_FM77AV_VARIANTS)
425 if(subcpu_resetreq) {
426 firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
428 power_on_reset = true;
429 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
431 do_firq(!firq_mask && key_firq_req);
438 void DISPLAY::set_crtflag(void)
445 void DISPLAY::reset_crtflag(void)
452 uint8_t DISPLAY::acknowledge_irq(void)
454 cancel_request = false;
460 uint8_t DISPLAY::beep(void)
462 mainio->write_signal(FM7_MAINIO_BEEP, 0x01, 0x01);
463 return 0xff; // True?
468 uint8_t DISPLAY::attention_irq(void)
470 mainio->write_signal(FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
475 void DISPLAY::set_cyclesteal(uint8_t val)
478 # if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
482 is_cyclesteal = true;
484 is_cyclesteal = false;
492 uint8_t DISPLAY::set_vramaccess(void)
494 vram_accessflag = true;
499 void DISPLAY::reset_vramaccess(void)
501 vram_accessflag = false;
505 uint8_t DISPLAY::reset_subbusy(void)
512 void DISPLAY::set_subbusy(void)
518 #if defined(_FM77AV_VARIANTS)
520 void DISPLAY::alu_write_cmdreg(uint32_t val)
522 alu->write_data8(ALU_CMDREG, val);
523 if((val & 0x80) != 0) {
531 void DISPLAY::alu_write_logical_color(uint8_t val)
533 uint32_t data = (uint32_t)val;
534 alu->write_data8(ALU_LOGICAL_COLOR, data);
538 void DISPLAY::alu_write_mask_reg(uint8_t val)
540 uint32_t data = (uint32_t)val;
541 alu->write_data8(ALU_WRITE_MASKREG, data);
545 void DISPLAY::alu_write_cmpdata_reg(int addr, uint8_t val)
547 uint32_t data = (uint32_t)val;
549 alu->write_data8(ALU_CMPDATA_REG + addr, data);
553 void DISPLAY::alu_write_disable_reg(uint8_t val)
555 uint32_t data = (uint32_t)val;
556 alu->write_data8(ALU_BANK_DISABLE, data);
560 void DISPLAY::alu_write_tilepaint_data(uint32_t addr, uint8_t val)
562 uint32_t data = (uint32_t)val;
565 alu->write_data8(ALU_TILEPAINT_B, data);
568 alu->write_data8(ALU_TILEPAINT_R, data);
571 alu->write_data8(ALU_TILEPAINT_G, data);
574 //alu->write_data8(ALU_TILEPAINT_L, 0xff);
580 void DISPLAY::alu_write_offsetreg_hi(uint8_t val)
582 alu->write_data8(ALU_OFFSET_REG_HIGH, val & 0x7f);
586 void DISPLAY::alu_write_offsetreg_lo(uint8_t val)
588 alu->write_data8(ALU_OFFSET_REG_LO, val);
592 void DISPLAY::alu_write_linepattern_hi(uint8_t val)
594 alu->write_data8(ALU_LINEPATTERN_REG_HIGH, val);
598 void DISPLAY::alu_write_linepattern_lo(uint8_t val)
600 alu->write_data8(ALU_LINEPATTERN_REG_LO, val);
604 void DISPLAY::alu_write_line_position(int addr, uint8_t val)
606 uint32_t data = (uint32_t)val;
609 alu->write_data8(ALU_LINEPOS_START_X_HIGH, data & 0x03);
612 alu->write_data8(ALU_LINEPOS_START_X_LOW, data);
615 alu->write_data8(ALU_LINEPOS_START_Y_HIGH, data & 0x01);
618 alu->write_data8(ALU_LINEPOS_START_Y_LOW, data);
621 alu->write_data8(ALU_LINEPOS_END_X_HIGH, data & 0x03);
624 alu->write_data8(ALU_LINEPOS_END_X_LOW, data);
627 alu->write_data8(ALU_LINEPOS_END_Y_HIGH, data & 0x01);
630 alu->write_data8(ALU_LINEPOS_END_Y_LOW, data);
636 uint8_t DISPLAY::get_miscreg(void)
641 if(!hblank) ret |= 0x80;
642 if(vsync) ret |= 0x04;
643 if(alu->read_signal(SIG_ALU_BUSYSTAT) == 0) ret |= 0x10;
644 if(power_on_reset) ret |= 0x01;
649 void DISPLAY::set_miscreg(uint8_t val)
651 int old_display_page = display_page;
653 nmi_enable = ((val & 0x80) == 0) ? true : false;
654 if(!nmi_enable) do_nmi(false);
656 if((val & 0x40) == 0) {
661 if(display_page != old_display_page) {
664 active_page = ((val & 0x20) == 0) ? 0 : 1;
665 if((val & 0x04) == 0) {
670 cgrom_bank = val & 0x03;
671 setup_display_mode();
675 void DISPLAY::set_monitor_bank(uint8_t var)
677 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
678 if((var & 0x04) != 0){
684 subrom_bank = var & 0x03;
687 subcpu_resetreq = false;
688 power_on_reset = true;
689 firq_mask = (mainio->read_signal(FM7_MAINIO_KEYBOARDIRQ_MASK) != 0) ? false : true;
691 subcpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
693 do_firq(!firq_mask && key_firq_req);
695 subcpu_resetreq = true;
701 void DISPLAY::set_apalette_index_hi(uint8_t val)
703 apalette_index.b.h = val & 0x0f;
707 void DISPLAY::set_apalette_index_lo(uint8_t val)
709 apalette_index.b.l = val;
712 void DISPLAY::calc_apalette(uint16_t idx)
716 g = analog_palette_g[idx];
717 r = analog_palette_r[idx];
718 b = analog_palette_b[idx];
719 if(g != 0) g |= 0x0f;
720 if(r != 0) r |= 0x0f;
721 if(b != 0) b |= 0x0f;
722 analog_palette_pixel[idx] = RGB_COLOR(r, g, b);
726 void DISPLAY::set_apalette_b(uint8_t val)
730 index = apalette_index.w.l;
731 tmp = (val & 0x0f) << 4;
732 if(analog_palette_b[index] != tmp) {
733 analog_palette_b[index] = tmp;
734 calc_apalette(index);
735 palette_changed = true;
740 void DISPLAY::set_apalette_r(uint8_t val)
744 index = apalette_index.w.l;
745 tmp = (val & 0x0f) << 4;
746 if(analog_palette_r[index] != tmp) {
747 analog_palette_r[index] = tmp;
748 calc_apalette(index);
749 palette_changed = true;
754 void DISPLAY::set_apalette_g(uint8_t val)
758 index = apalette_index.w.l;
759 tmp = (val & 0x0f) << 4;
760 if(analog_palette_g[index] != tmp) {
761 analog_palette_g[index] = tmp;
762 calc_apalette(index);
763 palette_changed = true;
767 #endif // _FM77AV_VARIANTS
770 void DISPLAY::copy_vram_blank_area(void)
774 void DISPLAY::copy_vram_per_line(void)
783 uint32_t src_offset_d1;
784 uint32_t src_offset_d2;
785 uint32_t src_offset_d;
790 uint32_t addr_d1, addr_d2;
793 //int dline = (int)displine - 1;
794 int dline = (int)displine;
796 if(dline < 0) return;
797 if(display_mode == DISPLAY_MODE_8_400L) {
798 if(dline >= 400) return;
800 if(dline >= 200) return;
802 #if defined(_FM77AV_VARIANTS)
803 yoff_d1 = offset_point;
804 yoff_d2 = offset_point_bank1;
805 if(display_mode == DISPLAY_MODE_4096) {
806 src_offset = dline * 40;
807 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
810 addr_d1 = (src_offset + yoff_d1) & 0x1fff;
811 addr_d2 = (src_offset + yoff_d2) & 0x1fff;
812 bytes_d1 = 0x2000 - addr_d1;
813 bytes_d2 = 0x2000 - addr_d2;
814 for(k = 0; k < pages; k++) {
816 for(i = 0; i < 3; i++) {
817 for(j = 0; j < 2; j++) {
818 uint32_t _addr_base = src_base + src_offset + poff;
820 memcpy(&gvram_shadow[_addr_base],
821 &gvram[addr_d1 + src_base + poff],
823 memcpy(&gvram_shadow[_addr_base + bytes_d1],
824 &gvram[src_base + poff],
827 memcpy(&gvram_shadow[_addr_base],
828 &gvram[addr_d1 + src_base + poff],
831 _addr_base += 0xc000;
833 memcpy(&gvram_shadow[_addr_base],
834 &gvram[addr_d2 + src_base + poff + 0xc000],
836 memcpy(&gvram_shadow[_addr_base + bytes_d2],
837 &gvram[src_base + poff + 0xc000],
840 memcpy(&gvram_shadow[_addr_base],
841 &gvram[addr_d2 + src_base + poff + 0xc000],
846 src_base = (i + 1) * 0x4000;
850 vram_draw_table[dline] = true;
851 vram_wrote_table[dline] = false;
853 # if defined(_FM77AV40EX) || defined(_FM77AV40SX) || defined(_FM77AV40)
854 else if(display_mode == DISPLAY_MODE_256k) {
855 src_offset = dline * 40;
857 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
859 #elif defined(_FM77AV40)
864 src_offset_d1 = (src_offset + yoff_d1) & 0x1fff;
865 src_offset_d2 = (src_offset + yoff_d2) & 0x1fff;
866 bytes_d1 = 0x2000 - ((src_offset + yoff_d1) & 0x1fff);
867 bytes_d2 = 0x2000 - ((src_offset + yoff_d2) & 0x1fff);
868 for(k = 0; k < pages; k++) {
869 for(i = 0; i < 3; i++) {
870 for(j = 0; j < 2; j++) {
872 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
873 src_offset_d = src_offset_d1;
876 src_base = i * 0x4000 + j * 0x2000 + k * 0xc000;
877 src_offset_d = src_offset_d2;
881 memcpy(&gvram_shadow[src_offset + src_base],
882 &gvram[src_offset_d + src_base],
884 memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
888 memcpy(&gvram_shadow[src_offset + src_base],
889 &gvram[src_offset_d + src_base],
895 vram_draw_table[dline] = true;
896 vram_wrote_table[dline] = false;
898 else if(display_mode == DISPLAY_MODE_8_400L) {
899 src_offset = dline * 80;
900 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
903 if(display_page_bak == 1) { // Is this dirty?
908 yoff_d = (yoff_d << 1) & 0x7fff;
909 src_offset_d = (src_offset + yoff_d) & 0x7fff;
910 bytes_d = 0x8000 - ((src_offset + yoff_d) & 0x7fff);
911 for(i = 0; i < pages; i++) {
912 for(j = 0; j < 3; j++) {
913 src_base = i * 0x18000 + j * 0x8000;
916 memcpy(&gvram_shadow[src_offset + src_base],
917 &gvram[src_offset_d + src_base],
920 memcpy(&gvram_shadow[src_offset + bytes_d + src_base],
924 memcpy(&gvram_shadow[src_offset + src_base + poff],
925 &gvram[src_offset_d + src_base],
930 vram_draw_table[dline] = true;
931 vram_wrote_table[dline] = false;
935 src_offset = dline * 80;
936 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
938 #elif defined(_FM77AV40)
940 #elif defined(_FM77AV_VARIANTS)
946 src_offset_d1 = (src_offset + yoff_d1) & 0x3fff;
947 src_offset_d2 = (src_offset + yoff_d2) & 0x3fff;
948 bytes_d1 = 0x4000 - ((src_offset + yoff_d1) & 0x3fff);
949 bytes_d2 = 0x4000 - ((src_offset + yoff_d2) & 0x3fff);
950 for(i = 0; i < pages; i++) {
952 src_offset_d = src_offset_d1;
955 src_offset_d = src_offset_d2;
959 for(j = 0; j < 3; j++) {
961 memcpy(&gvram_shadow[src_offset + src_base + poff],
962 &gvram[src_offset_d + src_base + poff],
964 memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
965 &gvram[src_base + poff],
968 memcpy(&gvram_shadow[src_offset + src_base + poff],
969 &gvram[src_offset_d + src_base + poff],
976 vram_draw_table[dline] = true;
977 vram_wrote_table[dline] = false;
981 src_offset = dline * 80;
984 yoff_d = offset_point;
985 src_offset_d = (src_offset + yoff_d) & 0x3fff;
986 bytes_d = 0x4000 - ((src_offset + yoff_d) & 0x3fff);
987 for(j = 0; j < 3; j++) {
988 src_base = j * 0x4000;
990 memcpy(&gvram_shadow[src_offset + src_base + poff],
991 &gvram[src_offset_d + src_base + poff],
993 memcpy(&gvram_shadow[src_offset + bytes_d + src_base + poff],
994 &gvram[src_base + poff],
997 memcpy(&gvram_shadow[src_offset + src_base + poff],
998 &gvram[src_offset_d + src_base + poff],
1002 vram_draw_table[dline] = true;
1003 vram_wrote_table[dline] = false;
1009 void DISPLAY::copy_vram_all()
1011 #if defined(_FM77AV_VARIANTS)
1012 uint32_t yoff_d1 = offset_point;
1013 uint32_t yoff_d2 = offset_point_bank1;
1014 uint32_t src_offset_1, src_offset_2;
1016 if(display_mode == DISPLAY_MODE_4096) {
1017 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1022 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1023 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1024 for(int k = 0; k < pages; k++) {
1025 for(int i = 0; i < 3; i++) {
1026 for(int j = 0; j < 2; j++) {
1027 src_offset_1 = i * 0x4000 + j * 0x2000;
1028 src_offset_2 = src_offset_1 + 0xc000;
1029 memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1030 memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1031 memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1032 memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1038 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1039 else if(display_mode == DISPLAY_MODE_256k) {
1040 uint32_t bytes_d1 = 0x2000 - (yoff_d1 & 0x1fff);
1041 uint32_t bytes_d2 = 0x2000 - (yoff_d2 & 0x1fff);
1042 for(int i = 0; i < 3; i++) {
1043 for(int j = 0; j < 2; j++) {
1044 src_offset_1 = i * 0x4000 + j * 0x2000;
1045 src_offset_2 = src_offset_1 + 0xc000;
1046 memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1047 memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1048 memcpy(&gvram_shadow[src_offset_2 + poff], &gvram[src_offset_2 + (yoff_d2 & 0x1fff) + poff], bytes_d2);
1049 memcpy(&gvram_shadow[src_offset_2 + bytes_d2 + poff], &gvram[src_offset_2 + poff], 0x2000 - bytes_d2);
1053 for(int i = 0; i < 3; i++) {
1054 for(int j = 0; j < 2; j++) {
1055 src_offset_1 = i * 0x4000 + j * 0x2000;
1056 memcpy(&gvram_shadow[src_offset_1 + poff], &gvram[src_offset_1 + (yoff_d1 & 0x1fff) + poff], bytes_d1);
1057 memcpy(&gvram_shadow[src_offset_1 + bytes_d1 + poff], &gvram[src_offset_1 + poff], 0x2000 - bytes_d1);
1060 } else if(display_mode == DISPLAY_MODE_8_400L) {
1062 uint32_t yoff_d, bytes_d;
1063 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1066 if(display_page_bak == 1) { // Is this dirty?
1071 yoff_d = (yoff_d << 1) & 0x7fff;
1072 bytes_d = 0x8000 - yoff_d;
1073 for(int i = 0; i < pages; i++) {
1074 for(int j = 0; j < 3; j++) {
1075 uint32_t src_base = i * 0x18000 + j * 0x8000;
1076 memcpy(&gvram_shadow[src_base],
1077 &gvram[yoff_d + src_base],
1079 if(bytes_d < 0x8000) {
1080 memcpy(&gvram_shadow[bytes_d + src_base],
1089 #if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1091 #elif defined(_FM77AV40)
1096 uint32_t bytes_d1 = 0x4000 - (yoff_d1 & 0x3fff);
1097 uint32_t bytes_d2 = 0x4000 - (yoff_d2 & 0x3fff);
1098 uint32_t yoff_d, bytes_d;
1099 for(int k = 0; k < pages; k++) {
1100 yoff_d = ((k & 1) == 0) ? (yoff_d1 & 0x3fff) : (yoff_d2 & 0x3fff);
1101 bytes_d = ((k & 1) == 0) ? bytes_d1 : bytes_d2;
1102 for(int j = 0; j < 3; j++) {
1103 src_offset_1 = k * 0xc000 + j * 0x4000;
1104 memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1105 memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1111 uint32_t yoff_d = offset_point & 0x3fff;
1112 uint32_t bytes_d = 0x4000 - (offset_point & 0x3fff);
1113 uint32_t src_offset_1;
1114 for(int j = 0; j < 3; j++) {
1115 src_offset_1 = j * 0x4000;
1116 memcpy(&gvram_shadow[src_offset_1], &gvram[src_offset_1 + yoff_d], bytes_d);
1117 memcpy(&gvram_shadow[src_offset_1 + bytes_d], &gvram[src_offset_1], 0x4000 - bytes_d);
1123 // Timing values from XM7 . Thanks Ryu.
1124 void DISPLAY::event_callback(int event_id, int err)
1129 case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
1130 #if defined(_FM77AV_VARIANTS)
1140 case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
1143 #if defined(_FM77AV_VARIANTS) || defined(_FM77L4)
1144 case EVENT_FM7SUB_HDISP:
1147 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x02, 0xff);
1148 if(display_mode == DISPLAY_MODE_8_400L) {
1149 if(displine < 400) f = true;
1151 if(displine < 200) f = true;
1154 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) != 0) {
1155 if((vram_wrote_table[displine] || vram_wrote) && need_transfer_line/*|| vram_wrote */) copy_vram_per_line();
1157 if(display_mode == DISPLAY_MODE_8_400L) {
1158 register_event(this, EVENT_FM7SUB_HBLANK, 30.0, false, &hblank_event_id); // NEXT CYCLE_
1160 register_event(this, EVENT_FM7SUB_HBLANK, 39.5, false, &hblank_event_id); // NEXT CYCLE_
1168 case EVENT_FM7SUB_HBLANK:
1170 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1172 if(display_mode == DISPLAY_MODE_8_400L) {
1173 if((displine < 400)) f = true;
1175 if((displine < 200)) f = true;
1178 if(display_mode == DISPLAY_MODE_8_400L) {
1183 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id);
1187 case EVENT_FM7SUB_VSTART: // Call first.
1192 display_page_bak = display_page;
1193 // Parameter from XM7/VM/display.c , thanks, Ryu.
1194 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1195 mainio->write_signal(SIG_DISPLAY_VSYNC, 0x00, 0xff);
1196 if(vblank_count != 0) {
1197 if(display_mode == DISPLAY_MODE_8_400L) {
1198 usec = (0.98 + 16.4) * 1000.0;
1200 usec = (1.91 + 12.7) * 1000.0;
1202 register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id);
1204 if(display_mode == DISPLAY_MODE_8_400L) {
1205 usec = 930.0; // 939.0
1207 usec = 1840.0; // 1846.5
1209 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
1213 if(display_mode == DISPLAY_MODE_8_400L) {
1214 usec = 0.34 * 1000.0;
1216 usec = 1.52 * 1000.0;
1218 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1223 case EVENT_FM7SUB_VSYNC:
1227 //write_access_page = (write_access_page + 1) & 1;
1229 if(display_mode == DISPLAY_MODE_8_400L) {
1230 usec = 0.33 * 1000.0;
1232 usec = 0.51 * 1000.0;
1234 mainio->write_signal(SIG_DISPLAY_VSYNC, 0x01, 0xff);
1235 mainio->write_signal(SIG_DISPLAY_DISPLAY, 0x00, 0xff);
1236 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
1237 if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) {
1240 if(need_transfer_line) {
1242 if(display_mode == DISPLAY_MODE_8_400L) lines = 400;
1243 for(int yy = 0; yy < lines; yy++) {
1244 if(vram_wrote_table[yy]) {
1245 vram_wrote_table[yy] = false;
1251 if(need_transfer_line) ff = true;
1254 for(int yy = 0; yy < 400; yy++) vram_draw_table[yy] = true;
1256 vram_wrote_shadow = true;
1257 screen_update_flag = true;
1261 if(need_transfer_line) {
1263 for(int yy = 0; yy < 400; yy++) {
1264 if(!vram_draw_table[yy]) {
1266 copy_vram_per_line();
1273 for(int yy = 0; yy < 400; yy++) {
1274 if(vram_draw_table[yy]) {
1275 vram_wrote_shadow = true;
1276 screen_update_flag = true;
1280 //vram_wrote = false;
1282 frame_skip_count_transfer++;
1284 uint32_t factor = ((config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28) & 3;
1285 if((frame_skip_count_transfer > factor) /* || (vram_wrote) */) {
1286 frame_skip_count_transfer = 0;
1287 need_transfer_line = true;
1289 need_transfer_line = false;
1294 case EVENT_FM7SUB_CLR_BUSY:
1297 case EVENT_FM7SUB_CLR_CRTFLAG:
1303 void DISPLAY::event_frame()
1305 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1308 if(need_transfer_line && vram_wrote) {
1309 for(yy = 0; yy < 400; yy++) {
1310 if(!vram_draw_table[yy]) {
1312 copy_vram_per_line();
1319 for(yy = 0; yy < 400; yy++) {
1320 if(vram_draw_table[yy]) {
1326 screen_update_flag = true;
1327 vram_wrote_shadow = true;
1331 frame_skip_count_transfer++;
1333 uint32_t factor = (config.dipswitch & FM7_DIPSW_FRAMESKIP) >> 28;
1334 if(frame_skip_count_transfer > factor) {
1335 frame_skip_count_transfer = 0;
1336 need_transfer_line = true;
1338 need_transfer_line = false;
1340 //vram_wrote = false;
1347 void DISPLAY::event_vline(int v, int clock)
1349 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
1350 if(need_transfer_line == false) return;
1352 if(vram_wrote_table[displine] || vram_wrote) {
1353 copy_vram_per_line();
1360 uint32_t DISPLAY::read_signal(int id)
1362 uint32_t retval = 0;
1364 case SIG_FM7_SUB_HALT:
1365 case SIG_DISPLAY_HALT:
1366 retval = (halt_flag) ? 0xffffffff : 0;
1368 case SIG_DISPLAY_BUSY:
1369 retval = (sub_busy) ? 0x80 : 0;
1371 case SIG_DISPLAY_MULTIPAGE:
1372 retval = multimode_accessmask;
1374 case SIG_DISPLAY_PLANES:
1377 #if defined(_FM77AV_VARIANTS)
1378 case SIG_DISPLAY_VSYNC:
1379 retval = (vsync) ? 0x01 : 0x00;
1381 case SIG_DISPLAY_DISPLAY:
1382 retval = (!hblank) ? 0x02: 0x00;
1384 case SIG_FM7_SUB_BANK: // Main: FD13
1385 retval = subrom_bank & 0x03;
1386 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1387 if(monitor_ram) retval |= 0x04;
1391 #if defined(_FM77AV_VARIANTS)
1392 case SIG_DISPLAY_MODE320:
1393 retval = (mode320) ? 0x40: 0x00;
1396 case SIG_DISPLAY_Y_HEIGHT:
1397 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1398 retval = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
1403 case SIG_DISPLAY_X_WIDTH:
1404 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1405 retval = (mode320 || mode256k) ? 320 : 640;
1406 #elif defined(_FM77AV_VARIANTS)
1407 retval = (mode320) ? 320 : 640;
1418 void DISPLAY::write_signal(int id, uint32_t data, uint32_t mask)
1420 bool flag = ((data & mask) != 0);
1424 case SIG_FM7_SUB_HALT:
1429 //mainio->write_signal(SIG_FM7_SUB_HALT, data, mask);
1431 case SIG_DISPLAY_HALT:
1435 restart_subsystem();
1438 case SIG_FM7_SUB_CANCEL:
1440 cancel_request = true;
1444 case SIG_DISPLAY_CLOCK:
1448 #if defined(_FM77AV_VARIANTS)
1449 case SIG_FM7_SUB_BANK: // Main: FD13
1450 set_monitor_bank(data & 0xff);
1453 case SIG_DISPLAY_EXTRA_MODE: // FD04 bit 4, 3
1454 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1455 //printf("Wrote $FD04: %02x\n", data);
1457 int oldmode = display_mode;
1459 kanjisub = ((data & 0x20) == 0) ? true : false;
1460 mode256k = (((data & 0x10) != 0) && ((data & 0x08) != 0) ) ? true : false;
1461 mode400line = ((data & 0x08) == 0) ? true : false;
1462 ram_protect = ((data & 0x04) == 0) ? true : false;
1463 if(mode400line && !mode320) {
1464 display_mode = DISPLAY_MODE_8_400L;
1465 } else if(mode256k) {
1466 display_mode = DISPLAY_MODE_256k;
1468 display_mode = (mode320) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1470 if(oldmode != display_mode) {
1472 if(mode320 || mode256k) {
1473 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1474 for(y = 0; y < 200; y++) {
1475 pp = emu->get_screen_buffer(y);
1476 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1478 } else if(display_mode == DISPLAY_MODE_8_400L) {
1479 emu->set_vm_screen_size(640, 400, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1480 for(y = 0; y < 400; y++) {
1481 pp = emu->get_screen_buffer(y);
1482 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1485 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1486 for(y = 0; y < 200; y++) {
1487 pp = emu->get_screen_buffer(y);
1488 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1492 alu->write_signal(SIG_ALU_X_WIDTH, (mode320 || mode256k) ? 40 : 80, 0xffff);
1493 alu->write_signal(SIG_ALU_Y_HEIGHT, (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200, 0xffff);
1494 alu->write_signal(SIG_ALU_400LINE, (display_mode == DISPLAY_MODE_8_400L) ? 0xff : 0x00, 0xff);
1495 frame_skip_count_draw = 3;
1496 frame_skip_count_transfer = 3;
1497 setup_display_mode();
1500 #elif defined(_FM77_VARIANTS)
1502 int oldmode = display_mode;
1503 kanjisub = ((data & 0x20) == 0) ? true : false;
1504 # if defined(_FM77L4)
1505 stat_400linecard = ((data & 0x20) != 0) ? true : false;
1506 mode400line = ((data & 0x08) != 0) ? false : true;
1507 if(mode400line && stat_400linecard) {
1508 display_mode = DISPLAY_MODE_8_400L_TEXT;
1509 } else if(stat_400linecard) {
1510 display_mode = DISPLAY_MODE_8_200L_TEXT;
1512 display_mode = DISPLAY_MODE_8_200L;
1515 setup_display_mode();
1519 #if defined(_FM77AV_VARIANTS)
1520 case SIG_DISPLAY_MODE320: // FD12 bit 6
1521 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1523 //printf("Wrote $FD12: %02x\n", data);
1524 int oldmode = display_mode;
1526 if(!mode320 && !mode256k) {
1527 //display_mode = (mode400line) ? DISPLAY_MODE_8_400L : DISPLAY_MODE_8_200L;
1528 display_mode = DISPLAY_MODE_8_200L;
1530 display_mode = (mode256k) ? DISPLAY_MODE_256k : DISPLAY_MODE_4096;
1532 if(oldmode != display_mode) {
1534 if(mode320 || mode256k) {
1535 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1536 for(y = 0; y < 200; y++) {
1537 pp = emu->get_screen_buffer(y);
1538 if(pp != NULL) memset(pp, 0x00, 320 * sizeof(scrntype_t));
1540 } else { // 200 lines, 8 colors.
1541 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1542 for(y = 0; y < 200; y++) {
1543 pp = emu->get_screen_buffer(y);
1544 if(pp != NULL) memset(pp, 0x00, 640 * sizeof(scrntype_t));
1548 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
1549 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
1550 alu->write_signal(SIG_ALU_400LINE, 0x00, 0xff);
1551 setup_display_mode();
1552 //frame_skip_count = 3;
1561 emu->set_vm_screen_size(320, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1562 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 320 * sizeof(scrntype_t));
1564 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
1565 for(y = 0; y < 200; y++) memset(emu->get_screen_buffer(y), 0x00, 640 * sizeof(scrntype_t));
1568 display_mode = (mode320 == true) ? DISPLAY_MODE_4096 : DISPLAY_MODE_8_200L;
1569 alu->write_signal(SIG_ALU_X_WIDTH, (mode320) ? 40 : 80, 0xffff);
1570 alu->write_signal(SIG_ALU_Y_HEIGHT, 200, 0xffff);
1571 alu->write_signal(SIG_ALU_400LINE, 0, 0xffffffff);
1573 if(mode320 != oldflag) setup_display_mode();
1577 case SIG_DISPLAY_MULTIPAGE:
1578 set_multimode(data);
1580 case SIG_FM7_SUB_KEY_MASK:
1581 if(firq_mask == flag) {
1582 do_firq(!flag && key_firq_req);
1586 case SIG_FM7_SUB_KEY_FIRQ:
1587 do_firq(flag & !(firq_mask));
1588 key_firq_req = flag;
1590 case SIG_FM7_SUB_USE_CLR:
1592 clr_count = data & 0x03;
1603 * Vram accessing functions moved to vram.cpp .
1606 uint32_t DISPLAY::read_mmio(uint32_t addr)
1608 uint32_t retval = 0xff;
1610 if(addr < 0xd400) return 0xff;
1612 #if !defined(_FM77AV_VARIANTS)
1613 raddr = (addr - 0xd400) & 0x000f;
1614 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
1615 raddr = (addr - 0xd400) & 0x003f;
1616 #else // FM77AV40EX || FM77AV40SX
1617 raddr = (addr - 0xd400) & 0x00ff;
1620 case 0x00: // Read keyboard
1621 retval = (keyboard->read_data8(0x00) != 0) ? 0xff : 0x7f;
1623 case 0x01: // Read keyboard
1624 retval = keyboard->read_data8(0x01) & 0xff;
1626 case 0x02: // Acknowledge
1635 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
1636 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
1638 if(!kanjisub) return 0xff;
1639 # if !defined(_FM77_VARIANTS)
1641 return (uint8_t)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1644 if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff));
1647 if(!kanjisub) return 0xff;
1648 # if !defined(_FM77_VARIANTS)
1650 return (uint8_t)kanjiclass2->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1653 if(kanjiclass1 != NULL) retval = kanjiclass1->read_data8(KANJIROM_DIRECTADDR + ((kanjiaddr.d << 1) & 0x1ffff) + 1);
1660 retval = set_vramaccess();
1666 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
1668 #if defined(_FM77AV_VARIANTS)
1671 retval = alu->read_data8(ALU_CMDREG);
1674 retval = alu->read_data8(ALU_LOGICAL_COLOR);
1677 retval = alu->read_data8(ALU_WRITE_MASKREG);
1680 retval = alu->read_data8(ALU_CMP_STATUS_REG);
1683 retval = alu->read_data8(ALU_BANK_DISABLE);
1685 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1686 case 0x2f: // VRAM BANK
1687 retval = 0xfc | (vram_bank & 0x03);
1692 retval = get_miscreg();
1696 retval = keyboard->read_data8(0x31);
1699 retval = keyboard->read_data8(0x32);
1705 return (uint8_t)retval;
1708 uint32_t DISPLAY::read_vram_data8(uint32_t addr)
1712 uint32_t color = (addr >> 14) & 0x03;
1714 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1715 if(display_mode == DISPLAY_MODE_8_400L) {
1716 color = vram_bank & 0x03;
1717 if(color > 2) color = 0;
1719 color = (addr >> 14) & 0x03;
1723 if((multimode_accessmask & (1 << color)) != 0) return 0xff;
1725 #if defined(_FM77AV_VARIANTS)
1726 if (active_page != 0) {
1727 offset = offset_point_bank1;
1729 offset = offset_point;
1732 offset = offset_point;
1735 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1736 if(display_mode == DISPLAY_MODE_8_400L) {
1738 uint32_t page_offset_alt = 0;
1739 if(addr >= 0x8000) return 0xff;
1740 color = vram_bank & 0x03;
1741 if(color > 2) color = 0;
1743 pagemod = 0x8000 * color;
1744 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1745 if(vram_active_block != 0) page_offset = 0x18000;
1747 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
1748 return gvram[vramaddr];
1751 uint32_t page_offset_alt;
1752 #if defined(_FM77AV40)
1754 page_offset_alt = 0xc000 * (vram_bank & 0x03);
1756 page_offset_alt = 0; // right?
1759 page_offset_alt = 0xc000 * (vram_bank & 0x03);
1761 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
1762 //page_mask = 0x1fff;
1763 //pagemod = addr & 0xe000;
1765 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1767 return gvram[vramaddr];
1769 #elif defined(_FM77AV_VARIANTS)
1771 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1772 return gvram[vramaddr];
1774 #elif defined(_FM77L4) //_FM77L4
1776 if(display_mode == DISPLAY_MODE_8_400L) {
1777 return (uint32_t)read_vram_l4_400l(addr, offset);
1779 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1780 return gvram[vramaddr];
1784 #else // Others (77/7/8)
1785 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1786 return gvram[vramaddr];
1790 void DISPLAY::write_dma_data8(uint32_t addr, uint32_t data)
1792 uint32_t raddr = (addr & 0xffff) >> 7;
1793 if(write_dma_func_table[raddr] != NULL) {
1794 (this->*write_dma_func_table[raddr])(addr, (uint8_t) data);
1798 void DISPLAY::write_vram_data8(uint32_t addr, uint8_t data)
1801 uint32_t color = (addr >> 14) & 0x03;
1805 #if defined(_FM77AV_VARIANTS)
1806 if (active_page != 0) {
1807 offset = offset_point_bank1;
1809 offset = offset_point;
1812 offset = offset_point;
1815 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1816 if(display_mode == DISPLAY_MODE_8_400L) {
1818 uint32_t page_offset_alt = 0;
1819 if(addr >= 0x8000) {
1822 color = vram_bank & 0x03;
1823 if(color > 2) color = 0;
1825 pagemod = 0x8000 * color;
1826 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
1827 if(vram_active_block != 0) page_offset_alt = 0x18000;
1829 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
1830 // Reduce data transfer.
1831 tdata = gvram[vramaddr];
1833 gvram[vramaddr] = data;
1834 vram_wrote_table[(addr & 0x7fff) / 80] = true;
1836 } else if(display_mode == DISPLAY_MODE_256k) {
1837 uint32_t page_offset_alt;
1838 #if defined(_FM77AV40)
1840 page_offset_alt = 0xc000 * (vram_bank & 0x03);
1842 page_offset_alt = 0; // right?
1845 page_offset_alt = 0xc000 * (vram_bank & 0x03);
1847 //pagemod = addr & pagemod_mask;
1848 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset_alt;
1849 tdata = gvram[vramaddr];
1851 gvram[vramaddr] = data;
1852 vram_wrote_table[(addr & page_mask) / 40] = true;
1855 } else if(display_mode == DISPLAY_MODE_4096) {
1856 //if(active_page != 0) {
1857 // page_offset += 0xc000;
1859 //page_mask = 0x1fff;
1860 //pagemod = addr & 0xe000;
1861 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1862 tdata = gvram[vramaddr];
1864 gvram[vramaddr] = data;
1865 vram_wrote_table[(addr & page_mask) / 40] = true;
1868 //if(active_page != 0) {
1869 // page_offset += 0xc000;
1871 //page_mask = 0x3fff;
1872 //pagemod = addr & 0xc000;
1873 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1874 tdata = gvram[vramaddr];
1876 gvram[vramaddr] = data;
1877 vram_wrote_table[(addr & page_mask) / 80] = true;
1880 #elif defined(_FM77AV_VARIANTS)
1881 if(display_mode == DISPLAY_MODE_4096) {
1882 //if(active_page != 0) {
1883 // page_offset = 0xc000;
1885 //page_mask = 0x1fff;
1886 //pagemod = addr & 0xe000;
1887 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1888 tdata = gvram[vramaddr];
1890 gvram[vramaddr] = data;
1891 vram_wrote_table[(addr & page_mask) / 40] = true;
1894 //if(active_page != 0) {
1895 // page_offset = 0xc000;
1897 //page_mask = 0x3fff;
1898 //pagemod = addr & 0xc000;
1899 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1900 tdata = gvram[vramaddr];
1902 gvram[vramaddr] = data;
1903 vram_wrote_table[(addr & page_mask) / 80] = true;
1906 #elif defined(_FM77L4) //_FM77L4
1908 if(display_mode == DISPLAY_MODE_8_400L) {
1909 write_vram_l4_400l(addr, data, offset);
1911 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1912 tdata = gvram[vramaddr];
1914 gvram[vramaddr] = data;
1915 vram_wrote_table[(addr & 0x3fff) / 80] = true;
1919 #else // Others (77/7/8)
1921 vramaddr = (((addr + offset) & page_mask) | (pagemod_mask & addr)) + page_offset;
1922 tdata = gvram[vramaddr];
1924 gvram[vramaddr] = data;
1925 vram_wrote_table[(addr & 0x3fff) / 80] = true;
1931 uint32_t DISPLAY::read_cpu_vram_data8(uint32_t addr)
1934 #if defined(_FM77AV_VARIANTS)
1936 alu->read_data8(addr + ALU_WRITE_PROXY);
1939 return read_vram_data8(addr);
1942 uint32_t DISPLAY::read_dma_vram_data8(uint32_t addr)
1944 return read_vram_data8(addr);
1947 void DISPLAY::init_read_table(void)
1950 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
1951 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cpu_vram_data8;
1952 read_dma_func_table[_at >> 7] = &DISPLAY::read_dma_vram_data8;
1954 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
1955 read_cpu_func_table[_at >> 7] = &DISPLAY::read_console_ram;
1956 read_dma_func_table[_at >> 7] = &DISPLAY::read_console_ram;
1958 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
1959 read_cpu_func_table[_at >> 7] = &DISPLAY::read_work_ram;
1960 read_dma_func_table[_at >> 7] = &DISPLAY::read_work_ram;
1962 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
1963 read_cpu_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
1964 read_dma_func_table[_at >> 7] = &DISPLAY::read_shared_ram;
1966 #if defined(_FM77AV_VARIANTS)
1967 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
1968 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
1969 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
1971 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
1972 read_cpu_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
1973 read_dma_func_table[_at >> 7] = &DISPLAY::read_hidden_ram;
1976 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
1977 read_cpu_func_table[_at >> 7] = &DISPLAY::read_mmio;
1978 read_dma_func_table[_at >> 7] = &DISPLAY::read_mmio;
1981 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
1982 read_cpu_func_table[_at >> 7] = &DISPLAY::read_cgrom;
1983 read_dma_func_table[_at >> 7] = &DISPLAY::read_cgrom;
1985 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
1986 read_cpu_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
1987 read_dma_func_table[_at >> 7] = &DISPLAY::read_subsys_monitor;
1991 uint32_t DISPLAY::read_console_ram(uint32_t addr)
1993 uint32_t raddr = addr & 0xfff;
1994 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1996 if(console_ram_bank >= 1) {
1997 return submem_console_av40[((console_ram_bank - 1) << 12) + raddr];
2001 return console_ram[raddr];
2004 uint32_t DISPLAY::read_work_ram(uint32_t addr)
2006 addr = addr & 0x3ff;
2007 return work_ram[addr];
2011 uint32_t DISPLAY::read_shared_ram(uint32_t addr)
2013 addr = addr - 0xd380;
2014 return shared_ram[addr];
2017 #if defined(_FM77AV_VARIANTS)
2018 uint32_t DISPLAY::read_hidden_ram(uint32_t addr)
2020 if(addr >= 0xd500) {
2021 return submem_hidden[addr - 0xd500];
2026 uint32_t DISPLAY::read_cgrom(uint32_t addr)
2028 #if defined(_FM77AV_VARIANTS)
2029 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2031 return submem_cgram[cgram_bank * 0x0800 + (addr - 0xd800)]; //FIXME
2034 return subsys_cg[(addr - 0xd800) + cgrom_bank * 0x800];
2036 return subsys_c[addr - 0xd800];
2040 uint32_t DISPLAY::read_subsys_monitor(uint32_t addr)
2042 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2044 return subsys_ram[addr - 0xe000];
2047 #if defined(_FM77AV_VARIANTS)
2048 switch(subrom_bank_using & 3) {
2050 return subsys_c[addr - 0xd800];
2053 return subsys_a[addr - 0xe000];
2056 return subsys_b[addr - 0xe000];
2059 return subsys_cg[addr - 0xe000];
2063 return subsys_c[addr - 0xd800];
2067 uint32_t DISPLAY::read_dma_data8(uint32_t addr)
2069 uint32_t raddr = (addr & 0xffff) >> 7;
2070 if(read_dma_func_table[raddr] != NULL) {
2071 return (this->*read_dma_func_table[raddr])(addr);
2076 uint32_t DISPLAY::read_data8(uint32_t addr)
2078 uint32_t raddr = addr;
2080 if(addr < 0x10000) {
2081 raddr = (addr & 0xffff) >> 7;
2082 if(read_cpu_func_table[raddr] != NULL) {
2083 return (this->*read_cpu_func_table[raddr])(addr);
2088 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2089 return dpalette_data[addr - FM7_SUBMEM_OFFSET_DPALETTE];
2092 #if defined(_FM77AV_VARIANTS)
2094 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2095 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2096 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2097 if(display_mode == DISPLAY_MODE_8_400L) {
2098 uint32_t page_offset_alt = 0;
2099 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2100 if(vram_active_block != 0) page_offset_alt = 0x18000;
2104 color = (addr & 0x18000) >> 15;
2105 if(color > 2) color = 0;
2106 pagemod = 0x8000 * color;
2107 if (active_page != 0) {
2108 offset = offset_point_bank1 << 1;
2110 offset = offset_point << 1;
2112 return gvram[(((addr + offset) & 0x7fff) | pagemod) + page_offset_alt];
2115 return read_vram_data8(addr);
2122 * Vram accessing functions moved to vram.cpp .
2125 void DISPLAY::write_mmio(uint32_t addr, uint8_t data)
2128 uint8_t active_block_old;
2130 if(addr < 0xd400) return;
2132 #if !defined(_FM77AV_VARIANTS)
2133 addr = (addr - 0xd400) & 0x000f;
2134 #elif !defined(_FM77AV40SX) && !defined(_FM77AV40EX)
2135 addr = (addr - 0xd400) & 0x003f;
2136 #else // FM77AV40EX || FM77AV40SX
2137 addr = (addr - 0xd400) & 0x00ff;
2139 io_w_latch[addr] = (uint8_t)data;
2141 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4)
2144 set_cyclesteal((uint8_t)data);
2147 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2148 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) || defined(_FM77_VARIANTS) // _FM77L4
2151 if(!kanjisub) return;
2152 kanjiaddr.w.h = 0x0000;
2153 kanjiaddr.b.h = (uint8_t) data;
2156 if(!kanjisub) return;
2157 kanjiaddr.w.h = 0x0000;
2158 kanjiaddr.b.l = (uint8_t)data;
2171 if(clr_count <= 0) {
2173 } else { // Read once when using clr_foo() to set busy flag.
2176 usec = (1000.0 * 1000.0) / 2000000.0;
2178 usec = (1000.0 * 1000.0) / 999000.0;
2180 if(!is_cyclesteal && vram_accessflag) usec = usec * 3.0;
2181 usec = (double)clr_count * usec;
2182 register_event(this, EVENT_FM7SUB_CLR_BUSY, usec, false, NULL); // NEXT CYCLE_
2189 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
2194 rval = (uint8_t)data;
2195 if(offset_changed[active_page]) {
2196 #if defined(_FM77AV_VARIANTS)
2197 if(active_page != 0) {
2198 tmp_offset_point[active_page].d = offset_point_bank1;
2200 tmp_offset_point[active_page].d = offset_point;
2203 tmp_offset_point[active_page].d = offset_point;
2206 tmp_offset_point[active_page].w.h = 0x0000;
2208 tmp_offset_point[active_page].b.h = rval;
2210 tmp_offset_point[active_page].b.l = rval;
2212 offset_changed[active_page] = !offset_changed[active_page];
2213 if(offset_changed[active_page]) {
2215 #if defined(_FM77AV_VARIANTS)
2216 if(active_page != 0) {
2218 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fff;
2220 offset_point_bank1 = tmp_offset_point[active_page].d & 0x007fe0;
2224 offset_point = tmp_offset_point[active_page].d & 0x007fff;
2226 offset_point = tmp_offset_point[active_page].d & 0x007fe0;
2230 offset_point = tmp_offset_point[active_page].d & 0x7fe0;
2234 #if defined(_FM77AV_VARIANTS)
2237 alu_write_cmdreg(data);
2240 alu_write_logical_color(data);
2243 alu_write_mask_reg(data);
2246 alu_write_disable_reg(data);
2249 alu_write_offsetreg_hi(data);
2252 alu_write_offsetreg_lo(data);
2255 alu_write_linepattern_hi(data);
2258 alu_write_linepattern_lo(data);
2260 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2262 console_ram_bank = (data & 0x18) >> 3;
2263 if(console_ram_bank > 2) console_ram_bank = 0;
2264 cgram_bank = data & 0x07;
2265 kanji_level2 = ((data & 0x80) == 0) ? false : true;
2267 case 0x2f: // VRAM BANK
2268 vram_bank = data & 0x03;
2269 if(vram_bank > 2) vram_bank = 0;
2279 keyboard->write_data8(0x31, data);
2281 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2283 active_block_old = vram_active_block;
2284 vram_active_block = data & 0x01;
2285 if(vram_display_block != (((data & 0x10) != 0) ? 1 : 0)) vram_wrote = true;
2286 vram_display_block = ((data & 0x10) != 0) ? 1 : 0;
2287 if(vram_active_block != active_block_old) setup_display_mode();
2292 tmpvar.d = window_xbegin * 8;
2295 tmpvar.b.h = data & 0x03;
2297 tmpvar.b.l = data & 0xf8;
2299 if(mode320 || mode256k) {
2300 if(tmpvar.d > 320) tmpvar.d = 320;
2302 if(tmpvar.d > 640) tmpvar.d = 640;
2304 window_xbegin = tmpvar.d / 8;
2309 tmpvar.d = window_xend * 8;
2312 tmpvar.b.h = data & 0x03;
2314 tmpvar.b.l = data & 0xf8;
2316 if(mode320 || mode256k) {
2317 if(tmpvar.d > 320) tmpvar.d = 320;
2319 if(tmpvar.d > 640) tmpvar.d = 640;
2321 window_xend = tmpvar.d / 8;
2326 tmpvar.d = window_low;
2329 tmpvar.b.h = data & 0x03;
2331 tmpvar.b.l = data & 0xff;
2333 if(display_mode == DISPLAY_MODE_8_400L) {
2334 if(tmpvar.d > 400) tmpvar.d = 400;
2337 if(tmpvar.d > 400) tmpvar.d = 400;
2339 window_low = tmpvar.d;
2344 tmpvar.d = window_high;
2347 tmpvar.b.h = data & 0x03;
2349 tmpvar.b.l = data & 0xff;
2351 if(display_mode == DISPLAY_MODE_8_400L) {
2352 if(tmpvar.d > 400) tmpvar.d = 400;
2355 if(tmpvar.d > 400) tmpvar.d = 400;
2357 window_high = tmpvar.d;
2363 #if defined(_FM77AV_VARIANTS)
2365 if((addr >= 0x13) && (addr <= 0x1a)) {
2366 alu_write_cmpdata_reg(addr - 0x13, data);
2367 } else if((addr >= 0x1c) && (addr <= 0x1e)) {
2368 alu_write_tilepaint_data(addr, data);
2369 } else if((addr >= 0x24) && (addr <= 0x2b)) {
2370 alu_write_line_position(addr - 0x24, data);
2377 void DISPLAY::init_write_table(void)
2380 for(_at = 0 ; _at < 0xc000; _at += 0x80) {
2381 write_cpu_func_table[_at >> 7] = &DISPLAY::write_cpu_vram_data8;
2382 write_dma_func_table[_at >> 7] = &DISPLAY::write_dma_vram_data8;
2384 for(_at = 0xc000; _at < 0xd000; _at += 0x80) {
2385 write_cpu_func_table[_at >> 7] = &DISPLAY::write_console_ram;
2386 write_dma_func_table[_at >> 7] = &DISPLAY::write_console_ram;
2388 for(_at = 0xd000; _at < 0xd380; _at += 0x80) {
2389 write_cpu_func_table[_at >> 7] = &DISPLAY::write_work_ram;
2390 write_dma_func_table[_at >> 7] = &DISPLAY::write_work_ram;
2392 for(_at = 0xd380; _at < 0xd400; _at += 0x80) {
2393 write_cpu_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
2394 write_dma_func_table[_at >> 7] = &DISPLAY::write_shared_ram;
2396 #if defined(_FM77AV_VARIANTS)
2397 for(_at = 0xd400; _at < 0xd500; _at += 0x80) {
2398 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
2399 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
2401 for(_at = 0xd500; _at < 0xd800; _at += 0x80) {
2402 write_cpu_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
2403 write_dma_func_table[_at >> 7] = &DISPLAY::write_hidden_ram;
2406 for(_at = 0xd400; _at < 0xd800; _at += 0x80) {
2407 write_cpu_func_table[_at >> 7] = &DISPLAY::write_mmio;
2408 write_dma_func_table[_at >> 7] = &DISPLAY::write_mmio;
2411 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2412 for(_at = 0xd800; _at < 0xe000; _at += 0x80) {
2413 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
2414 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_cgram;
2416 for(_at = 0xe000; _at < 0x10000; _at += 0x80) {
2417 write_cpu_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
2418 write_dma_func_table[_at >> 7] = &DISPLAY::write_subsys_ram;
2421 for(_at = 0xd800; _at < 0x10000; _at += 0x80) {
2422 write_cpu_func_table[_at >> 7] = &DISPLAY::write_dummy;
2423 write_dma_func_table[_at >> 7] = &DISPLAY::write_dummy;
2428 void DISPLAY::write_console_ram(uint32_t addr, uint8_t data)
2430 uint32_t raddr = addr & 0xfff;
2431 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2433 if(console_ram_bank >= 1) {
2434 submem_console_av40[((console_ram_bank - 1) << 12) + raddr] = data;
2439 console_ram[raddr] = data;
2443 void DISPLAY::write_work_ram(uint32_t addr, uint8_t data)
2445 uint32_t raddr = addr & 0xfff;
2446 work_ram[raddr] = data;
2450 void DISPLAY::write_shared_ram(uint32_t addr, uint8_t data)
2452 uint32_t raddr = addr & 0x7f;
2453 shared_ram[raddr] = data;
2457 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
2458 void DISPLAY::write_subsys_cgram(uint32_t addr, uint8_t data)
2460 uint32_t raddr = addr - 0xd800;
2461 if(ram_protect) return;
2462 if(!monitor_ram) return;
2463 submem_cgram[cgram_bank * 0x0800 + raddr] = data; //FIXME
2466 void DISPLAY::write_subsys_ram(uint32_t addr, uint8_t data)
2468 if(ram_protect) return;
2469 if(!monitor_ram) return;
2470 subsys_ram[addr - 0xe000] = data; //FIXME
2474 #if defined(_FM77AV_VARIANTS)
2475 void DISPLAY::write_hidden_ram(uint32_t addr, uint8_t data)
2477 submem_hidden[addr - 0xd500] = data;
2482 void DISPLAY::write_cpu_vram_data8(uint32_t addr, uint8_t data)
2484 uint32_t color = (addr & 0xc000) >> 14;
2485 #if defined(_FM77AV_VARIANTS)
2487 alu->read_data8(addr + ALU_WRITE_PROXY);
2491 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2492 if(display_mode == DISPLAY_MODE_8_400L) {
2493 color = vram_bank & 0x03;
2494 if(color > 2) color = 0;
2498 if((multimode_accessmask & (1 << color)) != 0) return;
2500 write_vram_data8(addr & 0xffff, data);
2503 void DISPLAY::write_dma_vram_data8(uint32_t addr, uint8_t data)
2505 uint32_t color = (addr & 0xc000) >> 14;
2506 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2507 if(display_mode == DISPLAY_MODE_8_400L) {
2508 color = vram_bank & 0x03;
2509 if(color > 2) color = 0;
2513 if((multimode_accessmask & (1 << color)) != 0) return;
2515 write_vram_data8(addr & 0xffff, data);
2518 void DISPLAY::write_dummy(uint32_t addr, uint8_t data)
2522 void DISPLAY::write_data8(uint32_t addr, uint32_t data)
2526 //uint32_t page_offset = 0x0000;
2527 uint8_t val8 = data & 0xff;
2528 uint32_t color = (addr & 0xc000) >> 14;
2531 if(addr < 0x10000) {
2532 void (*_write_func)(uint32_t, uint32_t);
2533 raddr = (addr & 0xffff) >> 7;
2534 if(write_cpu_func_table[raddr] != NULL) {
2535 (this->*write_cpu_func_table[raddr])(addr, (uint8_t)data);
2541 else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
2542 set_dpalette(addr - FM7_SUBMEM_OFFSET_DPALETTE, val8);
2546 #if defined(_FM77AV_VARIANTS)
2548 else if(addr == FM7_SUBMEM_OFFSET_APALETTE_R) {
2549 set_apalette_r(val8);
2551 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_G) {
2552 set_apalette_g(val8);
2554 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_B) {
2555 set_apalette_b(val8);
2557 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_HI) {
2558 set_apalette_index_hi(val8);
2560 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_LO) {
2561 set_apalette_index_lo(val8);
2565 else if((addr >= DISPLAY_VRAM_DIRECT_ACCESS) && (addr < (DISPLAY_VRAM_DIRECT_ACCESS + 0x18000))) {
2566 addr = addr - DISPLAY_VRAM_DIRECT_ACCESS;
2567 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2568 if(display_mode == DISPLAY_MODE_8_400L) {
2570 uint32_t page_offset_alt = 0;
2572 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2573 if(vram_active_block != 0) page_offset_alt = 0x18000;
2575 color = (addr & 0x18000) >> 15;
2576 if(color > 2) color = 0;
2577 if (active_page != 0) {
2578 offset = offset_point_bank1 << 1;
2580 offset = offset_point << 1;
2582 pagemod = 0x8000 * color;
2583 vramaddr = (((addr + offset) & 0x7fff) | pagemod) + page_offset_alt;
2584 tdata = gvram[vramaddr];
2585 if(tdata != (uint8_t)data) {
2586 gvram[vramaddr] = data;
2587 vram_wrote_table[(addr & 0x7fff) / 80] = true;
2591 write_vram_data8(addr, data);
2593 write_vram_data8(addr, data);
2595 //if((config.dipswitch & FM7_DIPSW_SYNC_TO_HSYNC) == 0) vram_wrote = true;
2602 uint32_t DISPLAY::read_bios(const _TCHAR *name, uint8_t *ptr, uint32_t size)
2608 if((name == NULL) || (ptr == NULL)) return 0;
2609 s = create_local_path(name);
2610 if(s == NULL) return 0;
2612 if(!fio.Fopen(s, FILEIO_READ_BINARY)) return 0;
2613 blocks = fio.Fread(ptr, size, 1);
2616 return blocks * size;
2620 void DISPLAY::initialize()
2624 screen_update_flag = true;
2625 memset(gvram, 0x00, sizeof(gvram));
2626 vram_wrote_shadow = false;
2627 memset(gvram_shadow, 0x00, sizeof(gvram_shadow));
2628 for(i = 0; i < 411; i++) vram_wrote_table[i] = false;
2629 for(i = 0; i < 411; i++) vram_draw_table[i] = false;
2631 memset(console_ram, 0x00, sizeof(console_ram));
2632 memset(work_ram, 0x00, sizeof(work_ram));
2633 memset(shared_ram, 0x00, sizeof(shared_ram));
2634 memset(subsys_c, 0xff, sizeof(subsys_c));
2635 need_transfer_line = true;
2636 frame_skip_count_draw = 3;
2637 frame_skip_count_transfer = 3;
2639 diag_load_subrom_c = false;
2641 if(read_bios(_T("SUBSYS_8.ROM"), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2642 this->out_debug_log(_T("SUBSYSTEM ROM READING : %s"), diag_load_subrom_c ? "OK" : "NG");
2644 if(read_bios(_T("SUBSYS_C.ROM"), subsys_c, 0x2800) >= 0x2800) diag_load_subrom_c = true;
2645 this->out_debug_log(_T("SUBSYSTEM ROM Type C READING : %s"), diag_load_subrom_c ? "OK" : "NG");
2647 #if defined(_FM77AV_VARIANTS)
2648 memset(subsys_a, 0xff, sizeof(subsys_a));
2649 memset(subsys_b, 0xff, sizeof(subsys_b));
2650 memset(subsys_cg, 0xff, sizeof(subsys_cg));
2651 memset(submem_hidden, 0x00, sizeof(submem_hidden));
2653 diag_load_subrom_a = false;
2654 if(read_bios(_T("SUBSYS_A.ROM"), subsys_a, 0x2000) >= 0x2000) diag_load_subrom_a = true;
2655 this->out_debug_log(_T("SUBSYSTEM ROM Type A READING : %s"), diag_load_subrom_a ? "OK" : "NG");
2657 diag_load_subrom_b = false;
2658 if(read_bios(_T("SUBSYS_B.ROM"), subsys_b, 0x2000) >= 0x2000) diag_load_subrom_b = true;
2659 this->out_debug_log(_T("SUBSYSTEM ROM Type B READING : %s"), diag_load_subrom_b ? "OK" : "NG");
2661 diag_load_subrom_cg = false;
2662 if(read_bios(_T("SUBSYSCG.ROM"), subsys_cg, 0x2000) >= 0x2000) diag_load_subrom_cg = true;
2663 this->out_debug_log(_T("SUBSYSTEM CG ROM READING : %s"), diag_load_subrom_cg ? "OK" : "NG");
2664 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2665 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2666 memset(subsys_ram, 0x00, sizeof(subsys_ram));
2667 memset(submem_cgram, 0x00, sizeof(submem_cgram));
2668 memset(submem_console_av40, 0x00, sizeof(submem_console_av40));
2675 #if defined(_FM77AV_VARIANTS)
2677 apalette_index.d = 0;
2678 for(i = 0; i < 4096; i++) {
2679 analog_palette_r[i] = i & 0x0f0;
2680 analog_palette_g[i] = (i & 0xf00) >> 4;
2681 analog_palette_b[i] = (i & 0x00f) << 4;
2685 #if defined(_FM77AV_VARIANTS)
2686 hblank_event_id = -1;
2687 hdisp_event_id = -1;
2688 vsync_event_id = -1;
2689 vstart_event_id = -1;
2696 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
2697 is_cyclesteal = true;
2699 is_cyclesteal = false;
2701 // emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2702 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2706 key_firq_req = false; //firq_mask = true;
2707 frame_skip_count_transfer = 3;
2708 frame_skip_count_draw = 3;
2709 emu->set_vm_screen_size(640, 200, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_WIDTH_ASPECT, WINDOW_HEIGHT_ASPECT);
2710 palette_changed = true;
2711 #if !defined(_FM77AV_VARIANTS) && !defined(_FM77L4)
2712 //register_vline_event(this);
2713 //register_frame_event(this);
2715 setup_display_mode();
2718 void DISPLAY::release()
2722 #define STATE_VERSION 8
2723 void DISPLAY::save_state(FILEIO *state_fio)
2725 state_fio->FputUint32_BE(STATE_VERSION);
2726 state_fio->FputInt32_BE(this_device_id);
2727 this->out_debug_log(_T("Save State: DISPLAY : id=%d ver=%d\n"), this_device_id, STATE_VERSION);
2731 state_fio->FputInt32_BE(clr_count);
2732 state_fio->FputBool(halt_flag);
2733 state_fio->FputInt32_BE(active_page);
2734 state_fio->FputBool(sub_busy);
2735 state_fio->FputBool(crt_flag);
2736 state_fio->FputBool(vram_wrote);
2737 state_fio->FputBool(is_cyclesteal);
2739 state_fio->FputBool(clock_fast);
2741 #if defined(_FM77AV_VARIANTS)
2742 state_fio->FputBool(subcpu_resetreq);
2743 state_fio->FputBool(power_on_reset);
2745 state_fio->FputBool(cancel_request);
2746 state_fio->FputBool(key_firq_req);
2748 state_fio->FputInt32_BE(display_mode);
2749 state_fio->FputUint32_BE(prev_clock);
2752 state_fio->Fwrite(dpalette_data, sizeof(dpalette_data), 1);
2753 state_fio->FputUint8(multimode_accessmask);
2754 state_fio->FputUint8(multimode_dispmask);
2756 state_fio->FputUint32_BE(offset_point);
2757 #if defined(_FM77AV_VARIANTS)
2758 state_fio->FputUint32_BE(offset_point_bank1);
2760 for(i = 0; i < 2; i++) {
2761 state_fio->FputUint32_BE(tmp_offset_point[i].d);
2762 state_fio->FputBool(offset_changed[i]);
2764 state_fio->FputBool(offset_77av);
2765 state_fio->FputBool(diag_load_subrom_c);
2768 state_fio->Fwrite(io_w_latch, sizeof(io_w_latch), 1);
2769 state_fio->Fwrite(console_ram, sizeof(console_ram), 1);
2770 state_fio->Fwrite(work_ram, sizeof(work_ram), 1);
2771 state_fio->Fwrite(shared_ram, sizeof(shared_ram), 1);
2772 state_fio->Fwrite(subsys_c, sizeof(subsys_c), 1);
2773 state_fio->Fwrite(gvram, sizeof(gvram), 1);
2774 state_fio->Fwrite(gvram_shadow, sizeof(gvram_shadow), 1);
2776 #if defined(_FM77_VARIANTS)
2777 state_fio->FputBool(kanjisub);
2778 state_fio->FputUint16_BE(kanjiaddr.w.l);
2779 # if defined(_FM77L4)
2780 state_fio->FputBool(mode400line);
2781 state_fio->FputBool(stat_400linecard);
2783 #elif defined(_FM77AV_VARIANTS)
2784 state_fio->FputBool(kanjisub);
2785 state_fio->FputUint16_BE(kanjiaddr.w.l);
2787 state_fio->FputBool(vblank);
2788 state_fio->FputBool(vsync);
2789 state_fio->FputBool(hblank);
2790 state_fio->FputInt32_BE(vblank_count);
2792 state_fio->FputBool(mode320);
2793 state_fio->FputInt8(display_page);
2794 state_fio->FputInt8(display_page_bak);
2795 state_fio->FputInt32_BE(cgrom_bank);
2796 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
2797 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2798 state_fio->FputInt32_BE(vram_bank);
2801 state_fio->FputUint32_BE(displine);
2802 state_fio->FputUint8(subrom_bank);
2803 state_fio->FputUint8(subrom_bank_using);
2805 state_fio->FputBool(nmi_enable);
2806 state_fio->FputBool(use_alu);
2808 state_fio->FputUint8(apalette_index.b.l);
2809 state_fio->FputUint8(apalette_index.b.h);
2810 state_fio->Fwrite(analog_palette_r, sizeof(analog_palette_r), 1);
2811 state_fio->Fwrite(analog_palette_g, sizeof(analog_palette_g), 1);
2812 state_fio->Fwrite(analog_palette_b, sizeof(analog_palette_b), 1);
2815 state_fio->FputBool(diag_load_subrom_a);
2816 state_fio->FputBool(diag_load_subrom_b);
2817 state_fio->FputBool(diag_load_subrom_cg);
2819 state_fio->Fwrite(subsys_a, sizeof(subsys_a), 1);
2820 state_fio->Fwrite(subsys_b, sizeof(subsys_b), 1);
2821 state_fio->Fwrite(subsys_cg, sizeof(subsys_cg), 1);
2822 state_fio->Fwrite(submem_hidden, sizeof(submem_hidden), 1);
2823 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2824 state_fio->FputBool(mode400line);
2825 state_fio->FputBool(mode256k);
2827 state_fio->FputBool(monitor_ram);
2828 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2829 state_fio->FputUint16_BE(window_low);
2830 state_fio->FputUint16_BE(window_high);
2831 state_fio->FputUint16_BE(window_xbegin);
2832 state_fio->FputUint16_BE(window_xend);
2833 state_fio->FputBool(window_opened);
2835 state_fio->FputBool(kanji_level2);
2837 state_fio->FputUint8(vram_active_block);
2838 state_fio->FputUint8(vram_display_block);
2839 state_fio->FputUint8(console_ram_bank);
2840 state_fio->FputBool(ram_protect);
2842 state_fio->FputUint32_BE(cgram_bank);
2843 state_fio->Fwrite(subsys_ram, sizeof(subsys_ram), 1);
2844 state_fio->Fwrite(submem_cgram, sizeof(submem_cgram), 1);
2845 state_fio->Fwrite(submem_console_av40, sizeof(submem_console_av40), 1);
2851 state_fio->FputInt32_BE(nmi_event_id);
2852 #if defined(_FM77AV_VARIANTS)
2853 state_fio->FputInt32_BE(hblank_event_id);
2854 state_fio->FputInt32_BE(hdisp_event_id);
2855 state_fio->FputInt32_BE(vsync_event_id);
2856 state_fio->FputInt32_BE(vstart_event_id);
2858 state_fio->FputBool(firq_mask);
2859 state_fio->FputBool(vram_accessflag);
2863 bool DISPLAY::load_state(FILEIO *state_fio)
2866 uint32_t version = state_fio->FgetUint32_BE();
2867 if(this_device_id != state_fio->FgetInt32_BE()) {
2870 this->out_debug_log(_T("Load State: DISPLAY : id=%d ver=%d\n"), this_device_id, version);
2875 clr_count = state_fio->FgetInt32_BE();
2876 halt_flag = state_fio->FgetBool();
2877 active_page = state_fio->FgetInt32_BE();
2878 sub_busy = state_fio->FgetBool();
2879 crt_flag = state_fio->FgetBool();
2880 vram_wrote = state_fio->FgetBool();
2881 crt_flag_bak = true;
2882 for(i = 0; i < 411; i++) vram_wrote_table[i] = true;
2883 for(i = 0; i < 411; i++) vram_draw_table[i] = true;
2884 is_cyclesteal = state_fio->FgetBool();
2886 clock_fast = state_fio->FgetBool();
2888 #if defined(_FM77AV_VARIANTS)
2889 subcpu_resetreq = state_fio->FgetBool();
2890 power_on_reset = state_fio->FgetBool();
2892 cancel_request = state_fio->FgetBool();
2893 key_firq_req = state_fio->FgetBool();
2895 display_mode = state_fio->FgetInt32_BE();
2896 prev_clock = state_fio->FgetUint32_BE();
2899 for(addr = 0; addr < 8; addr++) set_dpalette(addr, addr);
2901 state_fio->Fread(dpalette_data, sizeof(dpalette_data), 1);
2902 for(addr = 0; addr < 8; addr++) set_dpalette(addr, dpalette_data[addr]);
2903 multimode_accessmask = state_fio->FgetUint8();
2904 multimode_dispmask = state_fio->FgetUint8();
2906 offset_point = state_fio->FgetUint32_BE();
2907 #if defined(_FM77AV_VARIANTS)
2908 offset_point_bank1 = state_fio->FgetUint32_BE();
2910 for(i = 0; i < 2; i++) {
2911 tmp_offset_point[i].d = state_fio->FgetUint32_BE();
2912 offset_changed[i] = state_fio->FgetBool();
2914 offset_77av = state_fio->FgetBool();
2915 diag_load_subrom_c = state_fio->FgetBool();
2917 state_fio->Fread(io_w_latch, sizeof(io_w_latch), 1);
2918 state_fio->Fread(console_ram, sizeof(console_ram), 1);
2919 state_fio->Fread(work_ram, sizeof(work_ram), 1);
2920 state_fio->Fread(shared_ram, sizeof(shared_ram), 1);
2921 state_fio->Fread(subsys_c, sizeof(subsys_c), 1);
2922 state_fio->Fread(gvram, sizeof(gvram), 1);
2923 state_fio->Fread(gvram_shadow, sizeof(gvram_shadow), 1);
2924 #if defined(_FM77_VARIANTS)
2925 kanjisub = state_fio->FgetBool();
2927 kanjiaddr.w.l = state_fio->FgetUint16_BE();
2928 # if defined(_FM77L4)
2929 mode400line = state_fio->FgetBool();
2930 stat_400linecard = state_fio->FgetBool();
2932 #elif defined(_FM77AV_VARIANTS)
2933 kanjisub = state_fio->FgetBool();
2935 kanjiaddr.w.l = state_fio->FgetUint16_BE();
2937 vblank = state_fio->FgetBool();
2938 vsync = state_fio->FgetBool();
2939 hblank = state_fio->FgetBool();
2940 vblank_count = state_fio->FgetInt32_BE();
2942 mode320 = state_fio->FgetBool();
2943 display_page = state_fio->FgetInt8();
2944 display_page_bak = state_fio->FgetInt8();
2945 cgrom_bank = state_fio->FgetInt32_BE();
2946 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX) || \
2947 defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2948 vram_bank = state_fio->FgetInt32_BE();
2950 screen_update_flag = true;
2951 displine = state_fio->FgetUint32_BE();
2952 subrom_bank = state_fio->FgetUint8();
2953 subrom_bank_using = state_fio->FgetUint8();
2955 nmi_enable = state_fio->FgetBool();
2956 use_alu = state_fio->FgetBool();
2958 apalette_index.b.l = state_fio->FgetUint8();
2959 apalette_index.b.h = state_fio->FgetUint8();
2961 state_fio->Fread(analog_palette_r, sizeof(analog_palette_r), 1);
2962 state_fio->Fread(analog_palette_g, sizeof(analog_palette_g), 1);
2963 state_fio->Fread(analog_palette_b, sizeof(analog_palette_b), 1);
2964 for(i = 0; i < 4096; i++) calc_apalette(i);
2966 diag_load_subrom_a = state_fio->FgetBool();
2967 diag_load_subrom_b = state_fio->FgetBool();
2968 diag_load_subrom_cg = state_fio->FgetBool();
2970 state_fio->Fread(subsys_a, sizeof(subsys_a), 1);
2971 state_fio->Fread(subsys_b, sizeof(subsys_b), 1);
2972 state_fio->Fread(subsys_cg, sizeof(subsys_cg), 1);
2973 state_fio->Fread(submem_hidden, sizeof(submem_hidden), 1);
2975 # if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
2976 mode400line = state_fio->FgetBool();
2977 mode256k = state_fio->FgetBool();
2979 monitor_ram = state_fio->FgetBool();
2980 # if defined(_FM77AV40EX) || defined(_FM77AV40SX)
2981 window_low = state_fio->FgetUint16_BE();
2982 window_high = state_fio->FgetUint16_BE();
2983 window_xbegin = state_fio->FgetUint16_BE();
2984 window_xend = state_fio->FgetUint16_BE();
2985 window_opened = state_fio->FgetBool();
2987 kanji_level2 = state_fio->FgetBool();
2989 vram_active_block = state_fio->FgetUint8();
2990 vram_display_block = state_fio->FgetUint8();
2991 console_ram_bank = state_fio->FgetUint8();
2992 ram_protect = state_fio->FgetBool();
2994 cgram_bank = state_fio->FgetUint32_BE();
2995 state_fio->Fread(subsys_ram, sizeof(subsys_ram), 1);
2996 state_fio->Fread(submem_cgram, sizeof(submem_cgram), 1);
2997 state_fio->Fread(submem_console_av40, sizeof(submem_console_av40), 1);
3000 palette_changed = true;
3001 vram_wrote_shadow = true; // Force Draw
3002 this->draw_screen();
3003 if(version == 1) return true;
3005 if(version >= 2) { //V2
3006 nmi_event_id = state_fio->FgetInt32_BE();
3007 #if defined(_FM77AV_VARIANTS)
3008 hblank_event_id = state_fio->FgetInt32_BE();
3009 hdisp_event_id = state_fio->FgetInt32_BE();
3010 vsync_event_id = state_fio->FgetInt32_BE();
3011 vstart_event_id = state_fio->FgetInt32_BE();
3013 firq_mask = state_fio->FgetBool();
3014 vram_accessflag = state_fio->FgetBool();
3015 frame_skip_count_draw = 3;
3016 frame_skip_count_transfer = 3;
3017 need_transfer_line = true;
3019 if(version == STATE_VERSION) return true;
3020 setup_display_mode();