2 * FM-7 Main I/O [fm7_mainio.h]
4 * Author: K.Ohta <whatisthis.sowhat _at_ gmail.com>
7 * Jan 03, 2015 : Initial
12 #include "fm7_mainio.h"
15 void FM7_MAINIO::initialize(void)
25 void FM7_MAINIO::set_clockmode(uint8 flags)
27 if(flags == FM7_MAINCLOCK_SLOW) {
34 uint8 FM7_MAINIO::get_clockmode(void)
36 if(clock_fast) return FM7_MAINCLOCK_SLOW;
37 return FM7_MAINCLOCK_HIGH;
41 uint8 FM7_MAINIO::get_port_fd00(void)
44 if(kbd_bit8) ret |= 0x80;
45 if(clock_fast) ret |= 0x01;
49 void FM7_MAINIO::set_port_fd00(uint8 data)
51 drec->write_signal(SIG_DATAREC_OUT, data, 0x01);
52 drec->write_signal(SIG_DATAREC_REMOTE, data, 0x02);
55 uint8 FM7_MAINIO::get_port_fd02(void)
58 // Still unimplemented printer.
59 ret = (cmt_indat) ? 0x80 : 0x00; // CMT
63 void FM7_MAINIO::set_port_fd02(uint8 val)
66 if((val & 0b00010000) != 0) {
71 if((val & 0b00000100) != 0) {
72 irqmask_timer = false;
76 if((val & 0b00000010) != 0) {
77 irqmask_printer = false;
79 irqmask_printer = true;
81 if((val & 0b00000001) != 0) {
82 irqmask_keyboard = false;
84 irqmask_keyboard = true;
90 uint32 FM7_MAINIO::get_keyboard(void)
92 uint32 kbd_data = (uint32) kbd_bit7_0;
94 if(kbd_bit8) kbd_data |= 0x0100;
98 void FM7_MAINIO::do_irq(bool flag)
101 maincpu->write_signal(SIG_CPU_IRQ, 1, 1);
103 maincpu->write_signal(SIG_CPU_IRQ, 0, 1);
108 void FM7_MAINIO::set_beep(uint32 data) // fd03
110 beep->write_signal(SIG_BEEP_ON, data, 0b11000000);
111 beep->write_signal(SIG_BEEP_MUTE, data , 0b00000001);
112 if((data & 0x40) != 0) {
113 // BEEP ON, after 205ms, BEEP OFF.
114 register_event(this, EVENT_BEEP_OFF, 205.0 * 1000.0, false, NULL); // NEXT CYCLE
118 void FM7_MAINIO::set_irq_timer(bool flag)
120 if(flag && !irqmask_timer) {
121 irqstat_reg0 &= 0b11111011;
127 irqstat_reg0 |= 0b00000100;
132 void FM7_MAINIO::set_irq_printer(bool flag)
134 if(flag && !irqmask_printer) {
135 irqstat_reg0 &= 0b11111101;
140 irqstat_reg0 |= 0b00000010;
145 void FM7_MAINIO::set_irq_keyboard(bool flag)
147 if(flag && !irqmask_keyboard) {
148 irqstat_reg0 &= 0b11111110;
153 irqstat_reg0 |= 0b00000001;
158 void FM7_MAINIO::set_irq_mfd(bool flag)
161 if(flag && !irqmask_mfd && connect_fdc) {
162 irqstat_fdc |= 0b01000000;
166 if((flag == false) && connect_fdc){
167 irqstat_fdc &= 0b10111111;
173 void FM7_MAINIO::set_keyboard(uint32 data)
175 if((data & 0x100) != 0){
180 kbd_bit7_0 = (data & 0xff);
183 void FM7_MAINIO::do_firq(bool flag)
186 maincpu->write_signal(SIG_CPU_FIRQ, 1, 1);
188 maincpu->write_signal(SIG_CPU_FIRQ, 0, 1);
192 void FM7_MAINIO::set_break_key(bool pressed)
194 firq_break_key = pressed;
197 void FM7_MAINIO::set_sub_attention(bool flag)
199 firq_sub_attention = flag;
204 uint8 FM7_MAINIO::get_fd04(void)
206 uint8 val = 0b11111100;
207 if(!firq_break_key) val |= 0b00000010;
208 if(!firq_sub_attention) val |= 0b00000001;
212 void FM7_MAINIO::set_fd04(uint8 val)
218 uint8 FM7_MAINIO::get_fd05(void)
220 uint8 val = 0b01111110;
221 if(sub_busy) val |= 0b10000000;
222 if(!extdet_neg) val |= 0b00000001;
225 void FM7_MAINIO::set_fd05(uint8 val)
227 display->write_signal(SIG_FM7_SUB_HALT, val, 0b10000000);
228 display->write_signal(SIG_FM7_SUB_CANCEL, val, 0b01000000);
229 if((val & 0b10000000) == 0) {
234 if((val & 0b00000001) != 0) {
235 maincpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
236 //z80->write_signal(SIG_CPU_BUSREQ, 0, 1);
238 maincpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
239 //z80->write_signal(SIG_CPU_BUSREQ, 1, 1);
245 void FM7_MAINIO::set_extdet(bool flag)
250 void FM7_MAINIO::set_psg(uint8 val)
252 if(psg == NULL) return set_opn(val, 0); // 77AV ETC
253 switch(psg_cmdreg & 0x03){
254 case 0: // High inpedance
258 //psg_data = psg->read_io8(1);
260 case 2: // Write Data
261 psg->write_io8(1, val & 0x00ff);
262 psg->write_signal(SIG_YM2203_MUTE, 0x01, 0x01); // Okay?
264 case 3: // Register address
265 psg_address = val & 0x0f;
266 psg->write_io8(0, psg_address);
271 uint8 FM7_MAINIO::get_psg(void)
274 if(psg == NULL) return get_opn(0); // 77AV ETC
275 switch(psg_cmdreg & 0x03) {
280 val = psg->read_io8(1);
281 psg_data = val & 0x00ff;
284 val = 0xff; // Write conflict
287 val = psg->read_io8(1);
295 * $fd0d : After 77AV, this is OPN.
297 void FM7_MAINIO::set_psg_cmd(uint32 cmd)
303 psg_cmdreg = (uint8)(cmd & 0b00000011);
307 uint8 FM7_MAINIO::get_psg_cmd(void)
309 if(opn_psg_77av) return get_opn_cmd();
310 return ((psg_cmdreg & 0b00000011) | 0b11111100);
315 // Kanji ROM, FD20 AND FD21 (or SUBSYSTEM)
316 void FM7_MAINIO::write_kanjiaddr_hi(uint8 addr)
318 if(!connect_kanjiroml1) return;
323 void FM7_MAINIO::write_kanjiaddr_lo(uint8 addr)
325 if(!connect_kanjiroml1) return;
330 uint8 FM7_MAINIO::read_kanjidata_left(void)
334 if(!connect_kanjiroml1) return 0xff;
335 addr = ((kaddress_hi & 0xff) * 256) + (kaddress_lo * 0xff);
338 return kanjiclass1->read_data8(addr);
344 uint8 FM7_MAINIO::read_kanjidata_right(void)
348 if(!connect_kanjiroml1) return 0xff;
349 addr = ((kaddress_hi & 0xff) * 256) + (kaddress_lo * 0xff);
352 return kanjiclass1->read_data8(addr);
358 #ifdef _FM77AV_VARIANTS
359 // Kanji ROM, FD20 AND FD21 (or SUBSYSTEM)
360 void FM7_MAINIO::write_kanjiaddr_hi_l2(uint8 addr)
362 if(!connect_kanjiroml2) return;
363 kaddress_hi_l2 = addr;
367 void FM7_MAINIO::write_kanjiaddr_lo_l2(uint8 addr)
369 if(!connect_kanjiroml2) return;
370 kaddress_lo_l2 = addr;
374 uint8 FM7_MAINIO::read_kanjidata_left_l2(void)
378 if(!connect_kanjiroml2) return 0xff;
379 addr = ((kaddress_hi_l2 & 0xff) * 256) + (kaddress_lo_l2 * 0xff);
382 return kanjiclass2->read_data8(addr);
388 uint8 FM7_MAINIO::read_kanjidata_right_l2(void)
392 if(!connect_kanjiroml2) return 0xff;
393 addr = ((kaddress_hi_l2 & 0xff) * 256) + (kaddress_lo_l2 * 0xff);
396 return kanjiclass2->read_data8(addr);
403 // Write to FD16, same as
404 void FM7_MAINIO::set_opn(uint8 val, int index)
408 if(!connect_opn) return;
411 if(!connect_whg) return;
414 if(!connect_thg) return;
420 if((opn_cmdreg[index] & 0b00001000) != 0) {
424 if((opn_cmdreg[index] & 0b00000100) != 0) {
428 switch(opn_cmdreg[index] & 0x03){
429 case 0: // High inpedance
433 //psg_data = psg->read_io8(1);
435 case 2: // Write Data
436 opn_data[index] = val & 0x00ff;
437 opn[index]->write_io8(1, val & 0x00ff);
438 opn[index]->write_signal(SIG_YM2203_MUTE, 0x01, 0x01); // Okay?
440 case 3: // Register address
441 opn_address[index] = val & 0x0f;
442 opn[index]->write_io8(0, psg_address);
447 uint8 FM7_MAINIO::get_opn(int index)
452 if(!connect_opn) return val;
455 if(!connect_whg) return val;
458 if(!connect_thg) return val;
464 if((opn_cmdreg[index] & 0b00001000) != 0) {
466 val = opn[index]->read_io8(1); // opn->joystick?
467 opn_data[index] = val & 0x00ff;
470 if((opn_cmdreg[index] & 0b00000100) != 0) {
472 val = opn[index]->read_io8(0);
473 opn_stat[index] = val & 0x00ff;
476 switch(opn_cmdreg[index] & 0x03) {
481 val = opn[index]->read_io8(1);
482 opn_data[index] = val & 0x00ff;
485 val = 0xff; // Write conflict
488 val = opn[index]->read_io8(1);
489 opn_address[index] = val;
497 void FM7_MAINIO::set_opn_cmd(uint32 cmd)
499 if(!connect_opn) return;
500 opn_cmdreg[0] = (uint8)(cmd & 0b00001111);
504 uint8 FM7_MAINIO::get_opn_cmd(void)
506 if(!connect_opn) return 0xff;
507 return ((opn_cmdreg[0] & 0b00001111) | 0b11110000);
511 void FM7_MAINIO::write_signal(int id, uint32 data, uint32 mask)
514 val_b = ((data & mask) != 0);
517 case FM7_MAINIO_CLOCKMODE: // fd00
526 #if defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS)
530 clocks = 2016000; // Hz
532 clocks = 1230502; // (2016 * 1095 / 1794)[KHz]
536 clocks = 1565000; // Hz
538 clocks = 955226; // (1565 * 1095 / 1794)[KHz]
543 clocks = 1794000; // Hz
545 clocks = 1095000; // Hz
550 clocks = 1794000; // Hz
552 clocks = 1095000; // Hz
556 subclocks = 2000000; // Hz
558 subclocks = 999000; // Hz
560 p_vm->set_cpu_clock(this->maincpu, clocks);
561 p_vm->set_cpu_clock(this->subcpu, subclocks);
564 case FM7_MAINIO_CMT_RECV: // FD02
565 cmt_indat = val_b ^ cmt_invert;
567 case FM7_MAINIO_CMT_INVERT: // FD02
570 case FM7_MAINIO_TIMERIRQ: //
571 set_irq_timer(val_b);
573 case FM7_MAINIO_LPTIRQ: //
574 set_irq_printer(val_b);
576 case FM7_MAINIO_KEYBOARDIRQ: //
577 set_irq_keyboard(val_b);
579 case FM7_MAINIO_PUSH_KEYBOARD:
580 set_keyboard(data & 0x1ff);
583 case FM7_MAINIO_PUSH_BREAK:
584 set_break_key(val_b);
586 case FM7_MAINIO_SUB_ATTENTION:
587 set_sub_attention(val_b);
590 case FM7_MAINIO_SUB_BUSY:
593 case FM7_MAINIO_EXTDET:
596 case FM7_MAINIO_BEEP:
597 beep->write_signal(SIG_BEEP_ON, data, mask);
598 register_event(this, EVENT_BEEP_OFF, 205.0 * 1000.0, false, NULL); // NEXT CYCLE
600 case FM7_MAINIO_OPNPORTA_CHANGED:
601 opnport_a = data & mask;
603 case FM7_MAINIO_OPNPORTB_CHANGED:
604 opnport_a = data & mask;
606 case FM7_MAINIO_PSG_IRQ:
608 case FM7_MAINIO_OPN_IRQ:
612 case FM7_MAINIO_WHG_IRQ:
616 case FM7_MAINIO_THG_IRQ:
620 case FM7_MAINIO_FDC_DRQ:
623 irqstat_fdc |= 0b10000000;
625 irqstat_fdc &= 0b01111111;
629 case FM7_MAINIO_FDC_IRQ:
632 irqstat_fdc |= 0b01000000;
634 irqstat_fdc &= 0b10111111;
643 uint8 FM7_MAINIO::fdc_getdrqirq(void)
648 uint8 FM7_MAINIO::get_irqstat_fd03(void)
650 uint8 val = 0b11111000;
653 extirq = intstat_opn | intstat_mouse | fdc_irq;
654 extirq = extirq | intstat_thg | intstat_whg;
655 //extirq = extirq | intstat_syndet | intstat_rxrdy | intstat_txrdy;
656 if(extirq) val &= 0b11110111;
661 uint8 FM7_MAINIO::get_extirq_fd17(void)
664 if(intstat_opn) val &= 0b11110111;
665 if(intstat_mouse) val &= 0b11111011;
669 void FM7_MAINIO::set_ext_fd17(uint8 data)
671 if((data & 0b00000100) != 0) {
674 mouse_enable = false;
681 void FM7_MAINIO::set_fdc_stat(uint8 val)
683 if(fdc == NULL) return;
685 fdc->write_io8(0, val & 0x00ff);
688 uint8 FM7_MAINIO::get_fdc_stat(void)
690 if(fdc == NULL) return 0xff;
691 this->write_signal(FM7_MAINIO_FDC_IRQ, 0, 1);
692 fdc_statreg = fdc->read_io8(0);
696 void FM7_MAINIO::set_fdc_track(uint8 val)
698 if(fdc == NULL) return;
699 // if mode is 2DD and type-of-image = 2D then val >>= 1;
701 fdc->write_io8(1, val & 0x00ff);
704 uint8 FM7_MAINIO::get_fdc_track(void)
706 if(fdc == NULL) return 0xff;
707 fdc_trackreg = fdc->read_io8(1);
711 void FM7_MAINIO::set_fdc_sector(uint8 val)
713 if(fdc == NULL) return;
715 fdc->write_io8(2, val & 0x00ff);
718 uint8 FM7_MAINIO::get_fdc_sector(void)
720 if(fdc == NULL) return 0xff;
721 fdc_sectreg = fdc->read_io8(2);
725 void FM7_MAINIO::set_fdc_data(uint8 val)
727 if(!connect_fdc) return;
729 fdc->write_io8(3, val & 0x00ff);
732 uint8 FM7_MAINIO::get_fdc_data(void)
734 if(!connect_fdc) return 0xff;
735 fdc_datareg = fdc->read_io8(3);
739 uint8 FM7_MAINIO::get_fdc_motor(void)
742 if(fdc == NULL) return 0xff;
743 if(fdc_motor) val = 0x80;
744 val = val | (fdc_drvsel & 0x03);
748 void FM7_MAINIO::set_fdc_fd1c(uint8 val)
750 if(fdc == NULL) return;
751 fdc_headreg = (val & 0x01) | 0xfe;
752 fdc->write_signal(SIG_MB8877_SIDEREG, val, 0x01);
755 uint8 FM7_MAINIO::get_fdc_fd1c(void)
757 if(fdc == NULL) return 0xff;
761 void FM7_MAINIO::set_fdc_fd1d(uint8 val)
763 if(fdc == NULL) return;
764 if((val & 0x80) != 0) {
769 fdc->write_signal(SIG_MB8877_DRIVEREG, val, 0x07);
770 fdc->write_signal(SIG_MB8877_MOTOR, val, 0x80);
774 uint32 FM7_MAINIO::read_signal(uint32 addr)
776 uint32 retval = 0xffffffff;
782 uint32 FM7_MAINIO::read_data8(uint32 addr)
784 if(addr == FM7_MAINIO_IS_BASICROM) {
786 if(stat_bootsw_basic) retval = 0xffffffff;
788 } else if(addr == FM7_MAINIO_BOOTMODE) {
789 uint32 retval = bootmode & 0x03;
790 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4) || defined(_FM77AV_VARIANTS)
791 if(bootram) retval = 4;
794 } else if(addr == FM7_MAINIO_READ_FD0F) {
795 if(stat_romrammode) return 0xffffffff;
797 } else if(addr == FM7_MAINIO_CLOCKMODE) {
798 return (uint32)get_clockmode();
801 else if(addr == FM7_MAINIO_MMR_ENABLED) {
802 uint32 retval = (mmr_enabled) ? 0xffffffff:0x00000000;
804 } else if(addr == FM7_MAINIO_WINDOW_ENABLED) {
805 uint32 retval = (window_enabled) ? 0xffffffff:0x00000000;
807 } else if(addr == FM7_MAINIO_MMR_SEGMENT) {
808 uint32 retval = (uint32) mmr_segment;
810 } else if((addr >= FM7_MAINIO_MMR_BANK) && (addr < (FM7_MAINIO_MMR_BANK + 64))) {
811 uint32 retval = (uint32)mmr_table[addr - FM7_MAINIO_MMR_BANK];
815 #if defined(_FM77AV_VARIANTS)
816 else if(addr == FM7_MAINIO_INITROM_ENABLED) {
819 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
820 else if(addr == FM7_MAINIO_EXTBANK) {
821 } else if(addr == FM7_MAINIO_EXTROM) {
824 //addr = addr & 0xff; //
827 case 0x100: // D400 (SUB)
828 return (uint32) get_port_fd00();
832 return (uint32) kbd_bit7_0;
835 return (uint32) get_port_fd02();
838 return (uint32) get_irqstat_fd03();
841 return (uint32) get_fd04();
844 return (uint32) get_fd05();
846 case 0x06: // RS-232C
850 case 0x08: // Light pen
856 return (uint32) get_psg_cmd();
859 return (uint32) get_psg();
865 case 0x15: // OPN CMD
866 return (uint32) get_opn_cmd();
868 case 0x16: // OPN DATA
869 return (uint32) get_opn(0);
872 return (uint32) get_extirq_fd17();
874 case 0x18: // FDC: STATUS
875 return (uint32) get_fdc_stat();
877 case 0x19: // FDC: Track
878 return (uint32) get_fdc_track();
880 case 0x1a: // FDC: Sector
881 return (uint32) get_fdc_sector();
883 case 0x1b: // FDC: Data
884 return (uint32) get_fdc_data();
887 return (uint32) get_fdc_fd1c();
890 return (uint32) get_fdc_motor();
893 return (uint32) irqstat_fdc;
895 case 0x22: // Kanji ROM
896 return (uint32) read_kanjidata_left();
898 case 0x23: // Kanji ROM
899 return (uint32) read_kanjidata_right();
901 #if defined(_FM77AV_VARIANTS)
902 case 0x2e: // Kanji ROM Level2
903 return (uint32) read_kanjidata_left_l2();
905 case 0x2f: // Kanji ROM Level2
906 return (uint32) read_kanjidata_right_l2();
909 case 0x37: // Multi page
910 return (uint32)display->read_data8(DISPLAY_ADDR_MULTIPAGE);
915 if((addr < 0x40) && (addr >= 0x38)) {
916 addr = (addr - 0x38) + FM7_SUBMEM_OFFSET_DPALETTE;
917 return (uint32) display->read_data8(addr);
923 void FM7_MAINIO::write_data8(uint32 addr, uint32 data)
925 if(addr == FM7_MAINIO_BOOTMODE) {
926 bootmode = data & 0x03;
928 } else if(addr == FM7_MAINIO_CLOCKMODE) {
929 set_clockmode((uint8)data);
932 addr = addr & 0xff; //
937 set_port_fd00((uint8)data);
941 // set_lptdata_fd01((uint8)data);
944 set_port_fd02((uint8)data);
951 // set_flags_fd04(data);
954 set_fd05((uint8)data);
956 case 0x06: // RS-232C
959 case 0x08: // Light pen
964 set_psg_cmd((uint8)data);
967 set_psg((uint8)data);
972 case 0x15: // OPN CMD
973 set_opn_cmd((uint8)data);
975 case 0x16: // OPN DATA
976 set_opn(0, (uint8)data);
979 set_ext_fd17((uint8)data);
981 case 0x18: // FDC: STATUS
982 set_fdc_stat((uint8)data);
984 case 0x19: // FDC: Track
985 set_fdc_track((uint8)data);
987 case 0x1a: // FDC: Sector
988 set_fdc_sector((uint8)data);
990 case 0x1b: // FDC: Data
991 set_fdc_data((uint8)data);
994 set_fdc_fd1c((uint8)data);
997 set_fdc_fd1d((uint8)data);
1002 case 0x20: // Kanji ROM
1003 write_kanjiaddr_hi((uint8)data);
1005 case 0x21: // Kanji ROM
1006 write_kanjiaddr_lo((uint8)data);
1008 #if defined(_FM77AV_VARIANTS)
1009 case 0x2c: // Kanji ROM
1010 write_kanjiaddr_hi_l2((uint8)data);
1012 case 0x2d: // Kanji ROM
1013 write_kanjiaddr_lo_l2((uint8)data);
1016 case 0x37: // Multi page
1017 display->write_signal(SIG_FM7_SUB_MULTIPAGE, data, 0x00ff);
1019 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4) || defined(_FM77AV_VARIANTS)
1021 if((data & 0x01) == 0) {
1026 if((data & 0x40) == 0) {
1027 window_enabled = false;
1029 window_enabled = true;
1031 if((data & 0x80) == 0) {
1032 mmr_enabled = false;
1041 if((addr < 0x40) && (addr >= 0x38)) {
1042 addr = (addr - 0x38) | FM7_SUBMEM_OFFSET_DPALETTE;
1043 display->write_data8(addr, (uint8)data);
1049 void FM7_MAINIO::event_callback(int event_id, int err)
1052 case EVENT_BEEP_OFF:
1053 beep->write_signal(SIG_BEEP_ON, 0x00, 0x01);