2 * Common source code project -> FM-7 -> Display
3 * (C) 2015 K.Ohta <whatisthis.sowhat _at_ gmail.com>
5 * Feb 10, 2015 : Initial.
8 #include "fm7_display.h"
12 extern void initvramtbl_4096_vec(void);
13 extern void detachvramtbl_4096_vec(void);
14 extern void PutBlank(uint32 *p, int height);
15 extern void CreateVirtualVram8_Line(uint8 *src, uint32 *p, int ybegin, uint32 *pal);
16 extern void CreateVirtualVram8_WindowedLine(uint8 *vram_1, uint8 *vram_w, Uint32 *p, int ybegin, int xbegin, int xend, uint32 *pal);
20 DISPLAY::DISPLAY(VM* parent_vm, EMU* parent_emu) : MEMORY(parent_vm, parent_emu)
24 // initvramtbl_4096_vec();
32 void DISPLAY::reset(void)
36 if(nmi_event_id >= 0) cancel_event(this, nmi_event_id);
37 if(hblank_event_id >= 0) cancel_event(this, hblank_event_id);
38 if(hdisp_event_id >= 0) cancel_event(this, hdisp_event_id);
39 if(vsync_event_id >= 0) cancel_event(this, vsync_event_id);
40 if(vstart_event_id >= 0) cancel_event(this, vstart_event_id);
41 if(halt_event_id >= 0) cancel_event(this, halt_event_id);
46 for(i = 0; i < 8; i++) set_dpalette(i, i);
51 vram_accessflag = false;
52 display_mode = DISPLAY_MODE_8_200L;
55 multimode_accessmask = 0;
56 multimode_dispmask = 0;
64 set_cyclesteal(config.dipswitch & 0x01); // CYCLE STEAL = bit0.
73 window_opened = false;
74 subcpu_resetreq = false;
75 is_cyclesteal = false;
78 offset_changed = true;
81 if((config.dipswitch & 0x01) != 0) is_cyclesteal = true;
83 register_event(this, EVENT_FM7SUB_VSTART, 1.0 * 1000.0, false, &vstart_event_id);
84 register_event(this, EVENT_FM7SUB_DISPLAY_NMI, 20000.0, true, &nmi_event_id); // NEXT CYCLE_
88 void DISPLAY::update_config(void)
90 set_cyclesteal(config.dipswitch & 0x01); // CYCLE STEAL = bit0.
93 inline int DISPLAY::GETVRAM_8_200L(int yoff, scrntype *p, uint32 rgbmask)
95 register uint8 b, r, g;
99 r = gvram[yoff + 0x4000];
100 g = gvram[yoff + 0x8000];
102 dot = ((g & 0x80) >> 5) | ((r & 0x80) >> 6) | ((b & 0x80) >> 7);
103 *p++ = dpalette_pixel[dot & rgbmask];
104 dot = ((g & 0x40) >> 4) | ((r & 0x40) >> 5) | ((b & 0x40) >> 6);
105 *p++ = dpalette_pixel[dot & rgbmask];
106 dot = ((g & 0x20) >> 3) | ((r & 0x20) >> 4) | ((b & 0x20) >> 5);
107 *p++ = dpalette_pixel[dot & rgbmask];
108 dot = ((g & 0x10) >> 2) | ((r & 0x10) >> 3) | ((b & 0x10) >> 4);
109 *p++ = dpalette_pixel[dot & rgbmask];
111 dot = ((g & 0x8) >> 1) | ((r & 0x8) >> 2) | ((b & 0x8) >> 3);
112 *p++ = dpalette_pixel[dot & rgbmask];
113 dot = (g & 0x4) | ((r & 0x4) >> 1) | ((b & 0x4) >> 2);
114 *p++ = dpalette_pixel[dot & rgbmask];
115 dot = ((g & 0x2) << 1) | (r & 0x2) | ((b & 0x2) >> 1);
116 *p++ = dpalette_pixel[dot & rgbmask];
117 dot = ((g & 0x1) << 2) | ((r & 0x1) << 1) | (b & 0x1);
118 *p = dpalette_pixel[dot & rgbmask];
123 void DISPLAY::draw_screen(void)
128 int height = (display_mode == DISPLAY_MODE_8_400L) ? 400 : 200;
129 scrntype *p, *pp, *q;
131 Uint32 planesize = 0x4000;
133 register uint32 rgbmask;
134 if(!vram_wrote) return;
136 #if defined(_FM77AV_VARIANTS)
138 offset = offset_point;
140 offset = offset_point & 0x7fe0;
143 offset = offset_point & 0x7fe0;
145 if((display_mode == DISPLAY_MODE_8_400L) || (display_mode == DISPLAY_MODE_8_400L_TEXT)) {
147 } else if((display_mode == DISPLAY_MODE_8_200L) || (display_mode == DISPLAY_MODE_8_200L_TEXT)) {
148 offset = offset & 0x3fff;
149 } else if((display_mode == DISPLAY_MODE_4096) || (display_mode == DISPLAY_MODE_256k)) {
151 offset = offset & 0x1fff;
158 for(y = 0; y < 400; y++) {
159 memset(emu->screen_buffer(y), 0x00, 640 * sizeof(scrntype));
161 } else if((display_mode == DISPLAY_MODE_8_200L) || (display_mode == DISPLAY_MODE_8_200L_TEXT)) {
163 yoff = offset & 0x3fff;
164 rgbmask = ~multimode_dispmask & 0x07;
165 for(y = 0; y < 400; y += 2) {
166 p = emu->screen_buffer(y);
168 for(x = 0; x < 10; x++) {
169 yoff = GETVRAM_8_200L(yoff, p, rgbmask);
172 yoff = GETVRAM_8_200L(yoff, p, rgbmask);
175 yoff = GETVRAM_8_200L(yoff, p, rgbmask);
178 yoff = GETVRAM_8_200L(yoff, p, rgbmask);
181 yoff = GETVRAM_8_200L(yoff, p, rgbmask);
184 yoff = GETVRAM_8_200L(yoff, p, rgbmask);
187 yoff = GETVRAM_8_200L(yoff, p, rgbmask);
190 yoff = GETVRAM_8_200L(yoff, p, rgbmask);
193 if(config.scan_line == 0) {
194 memcpy((void *)emu->screen_buffer(y + 1), pp, 640 * sizeof(scrntype));
196 memset((void *)emu->screen_buffer(y + 1), 0x00, 640 * sizeof(scrntype));
202 #if defined(_FM77AV_VARIANTS)
203 else if(display_mode == DISPLAY_MODE_4096) {
204 for(y = 0; y < height; y++) {
205 p = &pvram[y * pitch];
206 if(((y < window_low) && (y > window_high)) || (!window_opened)) {
207 CreateVirtualVram4096_Line(p, y, offset, apalette_pixel, multimode_dispmask);
209 CreateVirtualVram4096_WindowedLine(p, y, window_xbegin, window_xend,
210 offset, apalette_pixel, multimode_dispmask);
214 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
216 for(y = 0; y < height; y++) {
217 p = &pvram[y * pitch];
218 if(((y < window_low) && (y > window_high)) || (!window_opened)) {
219 CreateVirtualVram256k_Line(p, y, offset, multimode_dispmask);
221 CreateVirtualVram256k_WindowedLine(p, y, offset, window_xbegin, window_xend,
227 #endif //_FM77AV_VARIANTS
230 void DISPLAY::do_irq(bool flag)
233 if(irq_count >= 0x7ffffffe) {
234 irq_count = 0x7ffffffe;
238 if(irq_count <= 1) subcpu->write_signal(SIG_CPU_IRQ, 1, 1);
245 if(irq_count == 0) subcpu->write_signal(SIG_CPU_IRQ, 0, 1);
249 void DISPLAY::do_firq(bool flag)
252 if(firq_count >= 0x7ffffffe) {
253 firq_count = 0x7ffffffe;
257 if(firq_count <= 1) subcpu->write_signal(SIG_CPU_FIRQ, 1, 1);
259 if(firq_count <= 0) {
264 if(firq_count == 0) subcpu->write_signal(SIG_CPU_FIRQ, 0, 1);
268 void DISPLAY::do_nmi(bool flag)
271 if(nmi_count >= 0x7ffffffe) {
272 nmi_count = 0x7ffffffe;
276 if(nmi_count <= 1) subcpu->write_signal(SIG_CPU_NMI, 1, 1);
283 if(nmi_count == 0) subcpu->write_signal(SIG_CPU_NMI, 0, 1);
287 void DISPLAY::set_multimode(uint8 val)
289 multimode_accessmask = val & 0x07;
290 multimode_dispmask = (val & 0x70) >> 4;
294 uint8 DISPLAY::get_multimode(void)
297 val = multimode_accessmask & 0x07;
298 val |= ((multimode_dispmask << 4) & 0x70);
303 uint8 DISPLAY::get_cpuaccessmask(void)
305 return multimode_accessmask & 0x07;
308 void DISPLAY::set_dpalette(uint32 addr, uint8 val)
312 dpalette_data[addr] = val | 0b11110000;
314 b = ((val & 0x01) != 0x00)? 255 : 0x00;
315 r = ((val & 0x02) != 0x00)? 255 : 0x00;
316 g = ((val & 0x04) != 0x00)? 255 : 0x00;
318 dpalette_pixel[addr] = RGB_COLOR(r, g, b);
321 uint8 DISPLAY::get_dpalette(uint32 addr)
326 data = dpalette_data[addr];
330 void DISPLAY::halt_subcpu(void)
333 printf("SUB HALT\n");
334 if(halt_count == 0) subcpu->write_signal(SIG_CPU_BUSREQ, 0x01, 0x01);
337 if(halt_count >= 0x7ffffff0) halt_count = 0x7ffffff0;
338 if(halt_count <= 0) halt_count = 0;
341 void DISPLAY::go_subcpu(void)
343 if((sub_run) && (halt_count > 0)) {
346 if(halt_count == 0) subcpu->write_signal(SIG_CPU_BUSREQ, 0x00, 0x01);
348 if(halt_count < 0) halt_count = 0;
351 void DISPLAY::enter_display(void)
362 void DISPLAY::leave_display(void)
369 void DISPLAY::halt_subsystem(void)
373 if(halt_event_id >= 0) cancel_event(this, halt_event_id);
374 register_event_by_clock(this, EVENT_FM7SUB_HALT, 10, true, &halt_event_id);
375 //mainio->write_signal(FM7_MAINIO_SUB_BUSY, 0x00, 0x01);
378 void DISPLAY::restart_subsystem(void)
383 if(halt_event_id >= 0) cancel_event(this, halt_event_id);
386 mainio->write_signal(FM7_MAINIO_SUB_BUSY, 0x01, 0x01); // BUSY
389 // mainio->write_signal(FM7_MAINIO_SUB_BUSY, 0x01, 0x01); // BUSY
393 void DISPLAY::set_crtflag(void)
400 void DISPLAY::reset_crtflag(void)
407 uint8 DISPLAY::acknowledge_irq(void)
410 //mainio->write_signal(FM7_MAINIO_SUB_BUSY, 0x00, 0x01);
415 uint8 DISPLAY::beep(void)
417 mainio->write_signal(FM7_MAINIO_BEEP, 0x01, 0x01);
418 return 0xff; // True?
423 uint8 DISPLAY::attention_irq(void)
425 mainio->write_signal(FM7_MAINIO_SUB_ATTENTION, 0x01, 0x01);
430 void DISPLAY::set_cyclesteal(uint8 val)
436 is_cyclesteal = true;
438 is_cyclesteal = false;
444 uint8 DISPLAY::set_vramaccess(void)
446 vram_accessflag = true;
451 void DISPLAY::reset_vramaccess(void)
453 vram_accessflag = false;
458 uint8 DISPLAY::reset_subbusy(void)
460 mainio->write_signal(FM7_MAINIO_SUB_BUSY, 0x00, 0x01);
466 void DISPLAY::set_subbusy(void)
468 mainio->write_signal(FM7_MAINIO_SUB_BUSY, 0x01, 0x01);
472 #if defined(_FM77AV_VARIANTS)
474 void DISPLAY::alu_write_cmdreg(uint8 val)
477 uint32 data = (uint32)val;
478 busyflag = alu->read_signal(SIG_FM7_ALU_BUSYSTAT) ? true : false;
479 if(busyflag) return; // DISCARD
480 alu->write_signal(SIG_FM7_ALU_CMDREG, data, 0x07);
481 alu->write_signal(SIG_FM7_ALU_MBITS, (data & 0x60) >> 5, 0x03);
482 alu->write_signal(SIG_FM7_ALU_EXEC, data, 0x80);
486 void DISPLAY::alu_write_logical_color(uint8 val)
489 uint32 data = (uint32)val;
490 busyflag = alu->read_signal(SIG_FM7_ALU_BUSYSTAT) ? true : false;
491 if(busyflag) return; // DISCARD
492 alu->write_signal(SIG_FM7_ALU_LOGICAL_COLOR, data, 0x03);
496 void DISPLAY::alu_write_mask_reg(uint8 val)
499 uint32 data = (uint32)val;
500 busyflag = alu->read_signal(SIG_FM7_ALU_BUSYSTAT) ? true : false;
501 if(busyflag) return; // DISCARD
502 alu->write_signal(SIG_FM7_ALU_WRITE_MASKREG, data, 0xff);
506 void DISPLAY::alu_write_mask_reg(int addr, uint8 val)
509 uint32 data = (uint32)val;
511 busyflag = alu->read_signal(SIG_FM7_ALU_BUSYSTAT) ? true : false;
512 if(busyflag) return; // DISCARD
513 alu->write_signal(SIG_FM7_ALU_WRITE_CMPREG_ADDR, data, 0x07);
517 void DISPLAY::alu_write_disable_reg(uint8 val)
520 uint32 data = (uint32)val;
522 busyflag = alu->read_signal(SIG_FM7_ALU_BUSYSTAT) ? true : false;
523 if(busyflag) return; // DISCARD
524 data = data & 0x07 | 0x08;
525 alu->write_signal(SIG_FM7_ALU_BANK_DISABLE, data, 0xff);
529 void DISPLAY::alu_write_tilepaint_data(int addr, uint8 val)
532 uint32 data = (uint32)val;
533 busyflag = alu->read_signal(SIG_FM7_ALU_BUSYSTAT) ? true : false;
534 if(busyflag) return; // DISCARD
537 alu->write_signal(SIG_FM7_ALU_TILEPAINT_B, data, 0xff);
540 alu->write_signal(SIG_FM7_ALU_TILEPAINT_R, data, 0xff);
543 alu->write_signal(SIG_FM7_ALU_TILEPAINT_G, data, 0xff);
546 //alu->write_signal(SIG_FM7_ALU_TILEPAINT_L, data, 0xff);
547 alu->write_signal(SIG_FM7_ALU_TILEPAINT_L, 0xff, 0xff);
553 void DISPLAY::alu_write_offsetreg_hi(uint8 val)
556 uint32 data = (uint32)val;
558 busyflag = alu->read_signal(SIG_FM7_ALU_BUSYSTAT) ? true : false;
559 if(busyflag) return; // DISCARD
560 addr = alu->read_signal(SIG_FM7_ALU_OFFSET_REG);
561 addr = addr & 0x00ff;
564 alu->write_signal(SIG_FM7_ALU_OFFSET_REG, data, 0x1fff);
568 void DISPLAY::alu_write_offsetreg_lo(uint8 val)
571 uint32 data = (uint32)val;
573 busyflag = alu->read_signal(SIG_FM7_ALU_BUSYSTAT) ? true : false;
574 if(busyflag) return; // DISCARD
575 addr = alu->read_signal(SIG_FM7_ALU_OFFSET_REG);
576 addr = addr & 0xff00;
578 alu->write_signal(SIG_FM7_ALU_OFFSET_REG, data, 0x1fff);
582 void DISPLAY::alu_write_linepattern_hi(uint8 val)
585 uint32 data = (uint32)val;
587 busyflag = alu->read_signal(SIG_FM7_ALU_BUSYSTAT) ? true : false;
588 if(busyflag) return; // DISCARD
589 addr = alu->read_signal(SIG_FM7_ALU_LINEPATTERN_REG);
590 addr = addr & 0x00ff;
593 alu->write_signal(SIG_FM7_ALU_LINEPATTERN_REG, data, 0xffff);
597 void DISPLAY::alu_write_linepattern_lo(uint8 val)
600 uint32 data = (uint32)val;
602 busyflag = alu->read_signal(SIG_FM7_ALU_BUSYSTAT) ? true : false;
603 if(busyflag) return; // DISCARD
604 addr = alu->read_signal(SIG_FM7_ALU_LINEPATTERN_REG);
605 addr = addr & 0xff00;
607 alu->write_signal(SIG_FM7_ALU_LINEPATTERN_REG, data, 0xffff);
611 void DISPLAY::alu_write_line_position(int addr, uint8 val)
614 uint32 data = (uint32)val;
615 busyflag = alu->read_signal(SIG_FM7_ALU_BUSYSTAT) ? true : false;
616 if(busyflag) return; // DISCARD
619 alu->write_signal(SIG_FM7_ALU_LINEPOS_START_X_HIGH, data, 0x03);
622 alu->write_signal(SIG_FM7_ALU_LINEPOS_START_X_LOW, data, 0xff);
625 alu->write_signal(SIG_FM7_ALU_LINEPOS_START_Y_HIGH, data, 0x01);
628 alu->write_signal(SIG_FM7_ALU_LINEPOS_START_Y_LOW, data, 0xff);
631 alu->write_signal(SIG_FM7_ALU_LINEPOS_END_X_HIGH, data, 0x03);
634 alu->write_signal(SIG_FM7_ALU_LINEPOS_END_X_LOW, data, 0xff);
637 alu->write_signal(SIG_FM7_ALU_LINEPOS_END_Y_HIGH, data, 0x01);
640 alu->write_signal(SIG_FM7_ALU_LINEPOS_END_Y_LOW, data, 0xff);
646 void DISPLAY::select_sub_bank(uint8 val)
648 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX)
649 kanji_level2 = ((val & 0x80) == 0) ? false : true;
650 // submem->write_signal(SIG_FM7_SUBMEM_SELECT_BANK val, 0x1f);
655 void DISPLAY::select_vram_bank_av40(uint8 val)
657 // submem->write_signal(SIG_FM7_SUBMEM_AV40_SELECT_BANK val, 0x03);
662 uint8 DISPLAY::get_miscreg(void)
665 #if defined(_FM77AV_VARIANTS)
667 if(!hblank && !vblank) ret |= 0x80;
668 if(vsync) ret |= 0x40;
669 if(alu->read_signal(SIG_ALU_BUSY) == 0) ret |= 0x10;
670 if(subreset) ret |= 0x01;
671 #else // 77 or older.
677 void DISPLAY::set_miscreg(uint8 val)
680 #if defined(_FM77AV40) || defined(_FM77AV40EX) || || defined(_FM77AV40SX)
681 nmi_enable = ((val & 0x80) == 0) ? true : false;
683 if((val & 0x40) == 0) {
684 if(display_page != 0) {
689 if(display_page == 0) {
694 active_page = ((val & 0x20) == 0) ? 0 : 1;
695 if((val & 0x04) == 0) {
700 submem->write_signal(SIG_FM7SUBMEM_CGROM, val, 0x03);
704 void DISPLAY::set_monitor_bank(uint8 var)
706 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
707 if((var & 0x04) != 0){
713 subrom_bank = var & 0x03;
714 subcpu_resetreq = true;
715 mainio->write_signal(FM7_MAINIO_SUB_BUSY, 0x01, 0x01);
720 void DISPLAY::set_apalette_index_hi(uint8 val)
722 uint32 index = (uint32)val;
724 index <<= 8; // right?
726 apalette_index = (apalette_index & 0xff) | index;
730 void DISPLAY::set_apalette_index_lo(uint8 val)
732 uint32 index = (uint32)val;
735 apalette_index = (apalette_index & 0xf00) | index;
738 void DISPLAY::calc_apalette(uint32 index)
742 r = (apalette_r[index] == 0)? 0 : apalette_r[index] << 4; // + 0x0f?
743 g = (apalette_g[index] == 0)? 0 : apalette_g[index] << 4; // + 0x0f?
744 b = (apalette_b[index] == 0)? 0 : apalette_b[index] << 4; // + 0x0f?
745 apalette_pixel[index] = RGB_COLOR(r, g, b);
749 void DISPLAY::set_apalette_b(uint8 val)
752 index = apalette_index & 0xfff;
753 analog_palette_b[index] = val & 0x0f;
754 calc_apalette(index);
758 void DISPLAY::set_apalette_r(uint8 val)
761 index = apalette_index & 0xfff;
762 analog_palette_r[index] = val & 0x0f;
763 calc_apalette(index);
767 void DISPLAY::set_apalette_g(uint8 val)
770 index = apalette_index & 0xfff;
771 analog_palette_g[index] = val & 0x0f;
772 calc_apalette(index);
775 #endif // _FM77AV_VARIANTS
777 // Timing values from XM7 . Thanks Ryu.
778 void DISPLAY::event_callback(int event_id, int err)
784 case EVENT_FM7SUB_DISPLAY_NMI: // per 20.00ms
786 register_event(this, EVENT_FM7SUB_DISPLAY_NMI_OFF, 10.0 * 1000.0, false, NULL); // NEXT CYCLE_
788 case EVENT_FM7SUB_DISPLAY_NMI_OFF: // per 20.00ms
791 case EVENT_FM7SUB_HDISP:
794 if(display_mode == DISPLAY_MODE_8_400L) usec = 30.0;
795 register_event(this, EVENT_FM7SUB_HBLANK, usec, false, &hblank_event_id); // NEXT CYCLE_
798 case EVENT_FM7SUB_HBLANK:
802 //if(!is_cyclesteal && vram_accessflag) leave_display();
804 if(display_mode == DISPLAY_MODE_8_400L) {
806 if(displine < 400) f = true;
809 if(displine < 200) f = true;
812 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
817 if(display_mode == DISPLAY_MODE_8_400L) {
818 usec = 0.31 * 1000.0;
820 usec = 0.51 * 1000.0;
822 register_event(this, EVENT_FM7SUB_VSYNC, usec, false, &vsync_event_id); // NEXT CYCLE_
825 case EVENT_FM7SUB_VSTART: // Call first.
831 if(display_mode == DISPLAY_MODE_8_400L) {
836 register_event(this, EVENT_FM7SUB_HDISP, usec, false, &hdisp_event_id); // NEXT CYCLE_
838 case EVENT_FM7SUB_VSYNC:
841 if(display_mode == DISPLAY_MODE_8_400L) {
842 usec = 0.98 * 1000.0;
844 usec = 1.91 * 1000.0;
846 register_event(this, EVENT_FM7SUB_VSTART, usec, false, &vstart_event_id); // NEXT CYCLE_
848 case EVENT_FM7SUB_HALT:
851 mainio->write_signal(FM7_MAINIO_SUB_BUSY, 0x01, 0x01); // BUSY
852 cancel_event(this, halt_event_id);
860 void DISPLAY::event_frame()
865 void DISPLAY::event_vline(int v, int clock)
869 uint32 DISPLAY::read_signal(int id)
872 case SIG_FM7_SUB_HALT:
873 case SIG_DISPLAY_HALT:
874 return (halt_flag) ? 0 : 0xffffffff;
883 void DISPLAY::write_signal(int id, uint32 data, uint32 mask)
885 bool flag = ((data & mask) != 0);
887 case SIG_DISPLAY_HALT:
888 case SIG_FM7_SUB_HALT:
890 if(sub_run) halt_subsystem();
894 if(subcpu_resetreq) {
897 subcpu_resetreq = false;
901 case SIG_FM7_SUB_CANCEL:
902 if(flag) do_irq(true);
904 #if defined(_FM77AV_VARIANTS)
905 case SIG_FM7_SUB_BANK: // Main: FD13
906 set_monitor_bank(data & 0xff);
908 #endif // _FM77AV_VARIANTS
909 case SIG_FM7_SUB_MULTIPAGE:
910 set_multimode(data & 0xff);
912 case SIG_FM7_SUB_KEY_FIRQ:
921 uint32 DISPLAY::read_data8(uint32 addr)
923 uint32 raddr = addr;;
924 uint32 mask = 0x3fff;
926 // addr = addr & 0x00ffffff;
928 #if defined(_FM77AV_VARIANTS)
930 offset = offset_point;
932 offset = offset_point & 0x7fe0;
935 offset = offset_point & 0x7fe0;
940 if(!(is_cyclesteal | vram_accessflag)) return 0xff;
942 if(display_mode == DISPLAY_MODE_8_400L) {
945 raddr = addr & 0x3fff;
946 if((multimode_accessmask & 0x04) == 0) {
947 return gvram[0x8000 + (raddr + offset) & mask];
951 pagemod = addr & 0x4000;
952 return gvram[((addr + offset) & mask) | pagemod];
953 } else if(addr < 0x9800) {
954 return textvram[addr & 0x0fff];
955 } else { // $9800-$bfff
956 return subrom_l4[addr - 0x9800];
959 #elif defined(_FM77AV_VARIANTS)
961 # if defined(_FM77AV40) || if defined(_FM77AV40EX) || if defined(_FM77AV40SX)
962 if(display_mode == DISPLAY_MODE_8_400L) {
964 // Fixme:Read via ALU
966 pagemod = addr >> 14;
968 addr = (addr + offset) & mask;
969 if((multimode_accessmask & (1 << vram_bank)) == 0) {
975 return gvram_1[addr];
978 return gvram_2[addr];
987 } else if(display_mode == DISPLAY_MODE_256k) {
991 if(display_mode == DISPLAY_MODE_4096) {
997 pagemod = addr >> 14;
998 if((multimode_accessmask & (1 << pagemod)) != 0) {
1001 return gvram_1[((addr + offset) & mask) | (pagemod << 14)];
1005 pagemod = addr >> 14;
1006 if((multimode_accessmask & (1 << pagemod)) != 0) {
1009 pagemod = addr & 0xc000;
1010 return gvram[((addr + offset) & mask) | pagemod];
1012 } else if(addr < 0xd000) {
1013 raddr = addr - 0xc000;
1014 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1015 if(submon_bank == 4) {
1016 if(cgram_bank >= 1) {
1017 return (uint32)submem_cgram[((cgram_bank - 1) << 12) | raddr];
1021 return console_ram[raddr];
1022 } else if(addr < 0xd380) {
1023 raddr = addr - 0xd000;
1024 return work_ram[raddr];
1025 } else if(addr < 0xd400) {
1026 raddr = addr - 0xd380;
1027 return shared_ram[raddr];
1028 } else if(addr < 0xd800) {
1029 uint32 retval = 0xff;
1030 #if !defined(_FM77AV_VARIANTS)
1031 raddr = (addr - 0xd400) & 0x000f;
1033 raddr = (addr - 0xd400) & 0x003f;
1036 case 0x00: // Read keyboard
1037 retval = (keyboard->read_data8(0x0) & 0x80) | 0x7f;
1039 case 0x01: // Read keyboard
1040 this->do_firq(false);
1041 mainio->write_signal(FM7_MAINIO_KEYBOARDIRQ, 0, 1);
1042 retval = keyboard->read_data8(1);
1044 case 0x02: // Acknowledge
1054 #if defined(_FM77L4) || defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1056 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX)
1058 retval = kanjiclass2->read_data8(kanji2_addr);
1060 retval = kanjiclass1->read_data8(kanji1_addr);
1063 retval = kanjiclass1->read_data8(kanji1_addr);
1067 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX)
1069 retval = kanjiclass2->read_data8(kanji2_addr + 1);
1071 retval = kanjiclass1->read_data8(kanji1_addr + 1);
1074 retval = kanjiclass1->read_data8(kanji1_addr + 1);
1089 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x01, 0x01);
1095 } else if(addr < 0x10000) {
1096 #if !defined(_FM77AV_VARIANTS)
1097 return subsys_c[addr - 0xd800];
1099 } else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
1100 return dpalette_data[addr - FM7_SUBMEM_OFFSET_DPALETTE];
1105 void DISPLAY::write_data8(uint32 addr, uint32 data)
1107 uint32 mask = 0x3fff;
1108 uint8 val8 = data & 0xff;
1111 // addr = addr & 0x00ffffff;
1113 #if defined(_FM77AV_VARIANTS)
1115 offset = offset_point;
1117 offset = offset_point & 0x7fe0;
1120 offset = offset_point & 0x7fe0;
1124 if(!(is_cyclesteal | vram_accessflag)) return;
1125 #if defined(_FM77L4)
1126 if(display_mode == DISPLAY_MODE_8_400L) {
1129 addr = addr & 0x3fff;
1130 if((multimode_accessmask & 0x04) == 0) {
1131 gvram[0x8000 + (addr + offset) & mask] = val8;
1135 pagemod = addr & 0x4000;
1136 gvram[((addr + offset) & mask) | pagemod] = val8;
1137 } else if(addr < 0x9800) {
1138 textvram[addr & 0x0fff] = val8;
1139 } else { // $9800-$bfff
1140 subrom_l4[addr - 0x9800] = val8;
1144 #elif defined(_FM77AV_VARIANTS)
1146 # if defined(_FM77AV40) || if defined(_FM77AV40EX) || if defined(_FM77AV40SX)
1147 if(display_mode == DISPLAY_MODE_8_400L) {
1149 // Fixme:Read via ALU
1151 pagemod = addr >> 14;
1153 addr = (addr + offset) & mask;
1154 if((multimode_accessmask & (1 << vram_bank)) == 0) {
1160 gvram_1[addr] = val8;
1163 gvram_2[addr] = val8;
1170 } else if(display_mode == DISPLAY_MODE_256k) {
1174 if(display_mode == DISPLAY_MODE_4096) {
1180 pagemod = addr >> 14;
1181 if((multimode_accessmask & (1 << pagemod)) == 0) {
1182 gvram_1[((addr + offset) & mask) | (pagemod << 14)] = val8;
1183 if(crt_flag && ((multimode_dispmask & (1 << pagemod)) == 0)) vram_wrote = true;
1188 pagemod = addr >> 14;
1189 if((multimode_accessmask & (1 << pagemod)) == 0) {
1190 pagemod = addr & 0xc000;
1191 gvram[((addr + offset) & mask) | pagemod] = val8;
1192 if(crt_flag && ((multimode_dispmask & (1 << pagemod)) == 0)) vram_wrote = true;
1195 } else if(addr < 0xd000) {
1196 addr = addr - 0xc000;
1197 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1198 if(submon_bank == 4) {
1199 if(cgram_bank >= 1) {
1200 submem_cgram[((cgram_bank - 1) << 12) | addr] = val8;
1205 console_ram[addr] = val8;
1207 } else if(addr < 0xd380) {
1209 work_ram[addr] = val8;
1211 } else if(addr < 0xd400) {
1213 shared_ram[addr] = val8;
1215 } else if(addr < 0xd800) {
1216 uint32 retval = 0xff;
1217 #if !defined(_FM77AV_VARIANTS)
1218 addr = (addr - 0xd400) & 0x000f;
1220 addr = (addr - 0xd400) & 0x003f;
1223 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4) || defined(_FM77AV_VARIANTS)
1225 set_cyclesteal(val8);
1230 data = data & 0x1fe00;
1231 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX)
1233 kanji2_addr = data | (kanji2_addr & 0x001fe);
1235 kanji1_addr = data | (kanji1_addr & 0x001fe);
1237 #elif defined(_FM77L4)
1238 kanji1_addr = data | (kanji1_addr & 0x001fe);
1243 data = data & 0x001fe;
1244 #if defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX)
1246 kanji2_addr = data | (kanji2_addr & 0x1fe00);
1248 kanji1_addr = data | (kanji1_addr & 0x1fe00);
1250 #elif defined(_FM77L4)
1251 kanji1_addr = data | (kanji1_addr & 0x1fe00);
1270 keyboard->write_signal(SIG_FM7KEY_SET_INSLED, 0x00, 0x01);
1273 #if defined(_FM77L4) || defined(_FM77AV40) || defined(_FM77AV40SX)|| defined(_FM77AV40SX)
1274 rval = (data & 0x7f) << 8;
1275 if(display_mode != DISPLAY_MODE_8_400L) rval = rval & 0x3fff;
1277 rval = (data & 0x3f) << 8;
1279 tmp_offset_point = (tmp_offset_point & 0x00ff) | rval;
1280 offset_changed = !offset_changed;
1281 if(offset_changed) {
1282 offset_point = tmp_offset_point;
1287 #if defined(_FM77AV_VARIANTS)
1288 rval = data & 0x00ff;
1289 if(!offset_77av) rval = rval & 0xe0;
1291 rval = data & 0x00e0;
1293 tmp_offset_point = (tmp_offset_point & 0x7f00) | rval;
1294 offset_changed = !offset_changed;
1295 if(offset_changed) {
1296 offset_point = tmp_offset_point;
1304 } else if(addr < 0x10000) {
1305 #if defined(_FM77AV_VARIANTS)
1306 //subrom_cg[addr - 0xd800] = val8;
1309 } else if((addr >= FM7_SUBMEM_OFFSET_DPALETTE) && (addr < (FM7_SUBMEM_OFFSET_DPALETTE + 8))) {
1310 set_dpalette(addr - FM7_SUBMEM_OFFSET_DPALETTE, val8);
1313 #if defined(_FM77AV_VARIANTS)
1314 else if(addr == FM7_SUBMEM_OFFSET_APALETTE_R) {
1315 set_apalette_r(val8);
1317 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_G) {
1318 set_apalette_g(val8);
1320 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_B) {
1321 set_apalette_b(val8);
1323 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_HI) {
1324 set_apalette_index_hi(val8);
1326 } else if(addr == FM7_SUBMEM_OFFSET_APALETTE_LO) {
1327 set_apalette_index_lo(val8);
1335 void DISPLAY::initialize()
1339 memset(gvram, 0xff, sizeof(gvram));
1340 memset(console_ram, 0x00, sizeof(console_ram));
1341 memset(work_ram, 0x00, sizeof(work_ram));
1342 memset(shared_ram, 0x00, sizeof(shared_ram));
1343 memset(subsys_c, 0x00, sizeof(subsys_c));
1345 read_bios("SUBSYS_C.ROM", subsys_c, 0x2800);
1348 #if defined(_FM77AV_VARIANTS)