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)
19 bootmode = config.boot_mode & 3;
20 #if defined(_FM77AV_VARIANTS)
27 void FM7_MAINIO::reset(void)
31 if(event_beep >= 0) cancel_event(this, event_beep);
32 if(event_timerirq >= 0) cancel_event(this, event_timerirq);
38 stat_romrammode = true;
39 bootmode = config.boot_mode & 3;
40 if(bootmode == 0) { // IF BASIC BOOT THEN ROM
41 stat_romrammode = true;
43 stat_romrammode = false;
47 if(config.cpu_type == 0) clock_fast = true;
49 pcm1bit->write_signal(SIG_PCM1BIT_MUTE, 0x01, 0x01);
50 pcm1bit->write_signal(SIG_PCM1BIT_ON, 0x00, 0x01);
55 connect_opn = connect_whg = connect_thg = false;
56 if(opn_psg_77av) connect_opn = true;
61 irqmask_timer = false;
62 irqmask_printer = false;
63 irqmask_keyboard = false;
66 //firq_break_key = false; // bit1, ON = '0'.
67 firq_sub_attention = false; // bit0, ON = '0'.
71 sub_cancel = false; // bit6 : '1' Cancel req.
73 switch(config.sound_device_type) {
104 // Parameters from XM7.
105 for (i = 0; i < 14; i++) {
107 for(j = 0; j < 3; j++) {
108 opn[j]->write_io8(0, i);
109 opn[j]->write_io8(1, 0xff);
111 psg->write_io8(0, i);
112 psg->write_io8(1, 0xff);
114 for(j = 0; j < 3; j++) {
115 opn[j]->write_io8(0, i);
116 opn[j]->write_io8(1, 0x0);
118 psg->write_io8(0, i);
119 psg->write_io8(1, 0x0);
124 for (i = 0x30; i < 0x40; i++) {
125 if ((i & 0x03) == 3) {
128 for(j = 0; j < 3; j++) {
129 opn[j]->write_io8(0, i);
130 opn[j]->write_io8(1, 0x0);
132 psg->write_io8(0, i);
133 psg->write_io8(1, 0x0);
137 for (i = 0x40; i < 0x50; i++) {
138 if ((i & 0x03) == 3) {
141 for(j = 0; j < 3; j++) {
142 opn[j]->write_io8(0, i);
143 opn[j]->write_io8(1, 0x7f);
145 psg->write_io8(0, i);
146 psg->write_io8(1, 0x7f);
150 for (i = 0x50; i < 0x60; i++) {
151 if ((i & 0x03) == 3) {
154 for(j = 0; j < 3; j++) {
155 opn[j]->write_io8(0, i);
156 opn[j]->write_io8(1, 0x1f);
158 psg->write_io8(0, i);
159 psg->write_io8(1, 0x1f);
163 for (i = 0x60; i < 0xb4; i++) {
164 if ((i & 0x03) == 3) {
167 for(j = 0; j < 3; j++) {
168 opn[j]->write_io8(0, i);
169 opn[j]->write_io8(1, 0x00);
171 psg->write_io8(0, i);
172 psg->write_io8(1, 0x00);
176 for (i = 0x80; i < 0x90; i++) {
177 if ((i & 0x03) == 3) {
180 for(j = 0; j < 3; j++) {
181 opn[j]->write_io8(0, i);
182 opn[j]->write_io8(1, 0xff);
184 psg->write_io8(0, i);
185 psg->write_io8(1, 0xff);
189 for (i = 0; i < 3; i++) {
190 for(j = 0; j < 3; j++) {
191 opn[j]->write_io8(0, 0x28);
192 opn[j]->write_io8(1, i);
194 psg->write_io8(0, 0x28);
195 psg->write_io8(1, i);
199 for(j = 0; j < 3; j++) {
200 opn[j]->write_io8(0, 0x27);
201 opn[j]->write_io8(1, 0);
203 psg->write_io8(0, 0x27);
204 psg->write_io8(1, 0);
222 if(connect_fdc) extdet_neg = true;
224 register_event(this, EVENT_TIMERIRQ_ON, 4069.0 / 2.0, true, &event_timerirq); // TIMER IRQ
230 void FM7_MAINIO::set_clockmode(uint8 flags)
232 if(flags == FM7_MAINCLOCK_SLOW) {
239 uint8 FM7_MAINIO::get_clockmode(void)
241 if(clock_fast) return FM7_MAINCLOCK_SLOW;
242 return FM7_MAINCLOCK_HIGH;
246 uint8 FM7_MAINIO::get_port_fd00(void)
248 uint8 ret = 0b01111110;
249 if(kbd_bit8) ret |= 0b10000000;
250 if(clock_fast) ret |= 0b00000001;
254 void FM7_MAINIO::set_port_fd00(uint8 data)
256 drec->write_signal(SIG_DATAREC_OUT, data, 0x01);
257 drec->write_signal(SIG_DATAREC_REMOTE, data, 0x02);
260 uint8 FM7_MAINIO::get_port_fd02(void)
263 // Still unimplemented printer.
264 ret = (cmt_indat) ? 0xff : 0x7f; // CMT
268 void FM7_MAINIO::set_port_fd02(uint8 val)
271 if((val & 0b00010000) != 0) {
276 if((val & 0b00000100) != 0) {
277 irqmask_timer = false;
279 irqmask_timer = true;
281 if((val & 0b00000010) != 0) {
282 irqmask_printer = false;
284 irqmask_printer = true;
286 if((val & 0b00000001) != 0) {
287 irqmask_keyboard = false;
289 irqmask_keyboard = true;
295 uint32 FM7_MAINIO::get_keyboard(void)
297 uint32 kbd_data = (uint32) kbd_bit7_0;
299 if(kbd_bit8) kbd_data |= 0x0100;
304 void FM7_MAINIO::set_beep(uint32 data) // fd03
306 beep_flag = ((data & 0xc0) != 0);
307 pcm1bit->write_signal(SIG_PCM1BIT_MUTE, ~data, 0b00000001);
310 if(event_beep < 0) register_event(this, EVENT_BEEP_CYCLE, (1000.0 * 1000.0) / (1200.0 * 2.0), true, &event_beep);
311 pcm1bit->write_signal(SIG_PCM1BIT_SIGNAL, 1, 1);
312 pcm1bit->write_signal(SIG_PCM1BIT_ON, 1, 1);
314 if(event_beep >= 0) cancel_event(this, event_beep);
316 pcm1bit->write_signal(SIG_PCM1BIT_SIGNAL, 0, 1);
317 pcm1bit->write_signal(SIG_PCM1BIT_ON, 0, 1);
319 if((data & 0x40) != 0) {
320 // BEEP ON, after 205ms, BEEP OFF.
321 register_event(this, EVENT_BEEP_OFF, 205.0 * 1000.0, false, NULL); // NEXT CYCLE
325 void FM7_MAINIO::set_irq_timer(bool flag)
327 uint8 backup = irqstat_reg0;
329 irqstat_reg0 &= 0b11111011;
330 if(!irqmask_timer && ((backup & 0b00000100) != 0)) do_irq(true);
332 irqstat_reg0 |= 0b00000100;
335 //printf("IRQ TIMER: %d MASK=%d\n", flag, irqmask_timer);
338 void FM7_MAINIO::set_irq_printer(bool flag)
340 uint8 backup = irqstat_reg0;
342 irqstat_reg0 &= 0b11111101;
343 if(!irqmask_printer && ((backup & 0b00000010) != 0)) do_irq(true);
345 irqstat_reg0 |= 0b00000010;
350 void FM7_MAINIO::set_irq_keyboard(bool flag)
352 uint8 backup = irqstat_reg0;
354 irqstat_reg0 &= 0b11111110;
355 if(!irqmask_keyboard && ((backup & 0b00000001) != 0)) do_irq(true);
357 irqstat_reg0 |= 0b00000001;
362 void FM7_MAINIO::set_irq_mfd(bool flag)
365 if(flag && connect_fdc) {
366 irqstat_fdc |= 0b01000000;
368 if((flag == false) && connect_fdc){
369 irqstat_fdc &= 0b10111111;
371 if(!irqmask_mfd) do_irq(flag);
375 void FM7_MAINIO::set_drq_mfd(bool flag)
378 if(flag && connect_fdc) {
379 irqstat_fdc |= 0b10000000;
381 if((flag == false) && connect_fdc){
382 irqstat_fdc &= 0b01111111;
384 //if(!irqmask_mfd) do_irq(flag);
389 void FM7_MAINIO::set_keyboard(uint32 data)
391 if((data & 0x100) != 0){
396 kbd_bit7_0 = (data & 0xff);
400 void FM7_MAINIO::do_irq(bool flag)
403 if(irq_count >= 0x7ffffffe) {
404 irq_count = 0x7ffffffe;
408 if(irq_count <= 1) maincpu->write_signal(SIG_CPU_IRQ, 1, 1);
415 if(irq_count == 0) maincpu->write_signal(SIG_CPU_IRQ, 0, 1);
419 void FM7_MAINIO::do_firq(bool flag)
422 if(firq_count >= 0x7ffffffe) {
423 firq_count = 0x7ffffffe;
427 if(firq_count <= 1) maincpu->write_signal(SIG_CPU_FIRQ, 1, 1);
429 if(firq_count <= 0) {
434 if(firq_count == 0) maincpu->write_signal(SIG_CPU_FIRQ, 0, 1);
438 void FM7_MAINIO::do_nmi(bool flag)
441 if(nmi_count >= 0x7ffffffe) {
442 nmi_count = 0x7ffffffe;
446 if(nmi_count <= 1) maincpu->write_signal(SIG_CPU_NMI, 1, 1);
453 if(nmi_count == 0) maincpu->write_signal(SIG_CPU_NMI, 0, 1);
458 void FM7_MAINIO::set_break_key(bool pressed)
460 firq_break_key = pressed;
463 void FM7_MAINIO::set_sub_attention(bool flag)
465 firq_sub_attention = flag;
470 uint8 FM7_MAINIO::get_fd04(void)
472 uint8 val = 0b01111100;
473 if(sub_busy) val |= 0b10000000;
474 if(!firq_break_key) val |= 0b00000010;
475 if(!firq_sub_attention) val |= 0b00000001;
476 if(firq_sub_attention) {
477 firq_sub_attention = false;
482 void FM7_MAINIO::set_fd04(uint8 val)
488 uint8 FM7_MAINIO::get_fd05(void)
490 uint8 val = 0b01111110;
491 if(sub_busy) val |= 0b10000000;
492 if(!extdet_neg) val |= 0b00000001;
496 void FM7_MAINIO::set_fd05(uint8 val)
498 subcpu->write_signal(SIG_CPU_BUSREQ, val, 0b10000000);
499 // display->write_signal(SIG_DISPLAY_HALT, val, 0b10000000);
500 display->write_signal(SIG_FM7_SUB_CANCEL, val, 0b01000000);
502 if((val & 0b00000001) != 0) {
503 maincpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
504 //z80->write_signal(SIG_CPU_BUSREQ, 0, 1);
506 maincpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
507 //z80->write_signal(SIG_CPU_BUSREQ, 1, 1);
514 void FM7_MAINIO::set_extdet(bool flag)
519 void FM7_MAINIO::set_psg(uint8 val)
521 if(opn_psg_77av) return set_opn(0, val); // 77AV ETC
524 case 0: // High inpedance
528 case 2: // Write Data
529 printf("PSG WRITE 2 DATA %02x to REG ADDR=%02x\n", psg_data, psg_address);
530 psg->write_io8(0, psg_address & 0x0f);
531 psg->write_io8(1, psg_data);
532 //psg->write_signal(SIG_YM2203_MUTE, 0x00, 0x01); // Okay?
534 case 3: // Register address
535 psg_address = val & 0x0f;
536 //psg->write_io8(0, psg_address & 0x0f);
541 uint8 FM7_MAINIO::get_psg(void)
561 * $fd0d : After 77AV, this is OPN.
563 void FM7_MAINIO::set_psg_cmd(uint8 cmd)
569 uint32 mask[16] = { // Parameter is related by XM7. Thanks Ryu.
570 0xff, 0x0f, 0xff, 0x0f,
571 0xff, 0x0f, 0x1f, 0xff,
572 0x1f, 0x1f, 0x1f, 0xff,
573 0xff, 0x0f, 0xff, 0xff
575 psg_cmdreg = (uint8)(cmd & 0b00000011);
580 psg->write_io8(0, psg_address & 0x0f);
581 psg_data = psg->read_io8(1); // & mask[psg_address];
582 printf("PSG READ DATA %02x from REG ADDR=%02x\n", psg_data, psg_address);
585 printf("PSG WRITE DATA %02x to REG ADDR=%02x\n", psg_data, psg_address);
586 psg->write_io8(0, psg_address & 0x0f);
587 psg->write_io8(1, psg_data);
588 //psg->write_signal(SIG_YM2203_MUTE, 0x00, 0x01); // Okay?
591 psg_address = psg_data & 0x0f;
592 //psg->write_io8(0, psg_address & 0x0f);
593 printf("PSG REG ADDR=%02x\n", psg_address);
605 // Kanji ROM, FD20 AND FD21 (or SUBSYSTEM)
606 void FM7_MAINIO::write_kanjiaddr_hi(uint8 addr)
608 if(!connect_kanjiroml1) return;
613 void FM7_MAINIO::write_kanjiaddr_lo(uint8 addr)
615 if(!connect_kanjiroml1) return;
620 uint8 FM7_MAINIO::read_kanjidata_left(void)
624 if(!connect_kanjiroml1) return 0xff;
625 addr = ((uint32)kaddress_hi << 8) | (uint32)kaddress_lo;
628 return kanjiclass1->read_data8(addr);
634 uint8 FM7_MAINIO::read_kanjidata_right(void)
638 if(!connect_kanjiroml1) return 0xff;
639 addr = ((uint32)kaddress_hi << 8) | (uint32)kaddress_lo;
640 addr = (addr << 1) | 1;
642 return kanjiclass1->read_data8(addr);
648 #ifdef _FM77AV_VARIANTS
649 // Kanji ROM, FD20 AND FD21 (or SUBSYSTEM)
650 void FM7_MAINIO::write_kanjiaddr_hi_l2(uint8 addr)
652 if(!connect_kanjiroml2) return;
653 kaddress_hi_l2 = addr;
657 void FM7_MAINIO::write_kanjiaddr_lo_l2(uint8 addr)
659 if(!connect_kanjiroml2) return;
660 kaddress_lo_l2 = addr;
664 uint8 FM7_MAINIO::read_kanjidata_left_l2(void)
668 if(!connect_kanjiroml2) return 0xff;
669 addr = ((uint32)kaddress_hi_l2 << 8) | (uint32)kaddress_lo_l2;
672 return kanjiclass2->read_data8(addr);
678 uint8 FM7_MAINIO::read_kanjidata_right_l2(void)
682 if(!connect_kanjiroml2) return 0xff;
683 addr = ((uint32)kaddress_hi_l2 << 8) | (uint32)kaddress_lo_l2;
684 addr = (addr << 1) | 0x01;
686 return kanjiclass2->read_data8(addr);
693 // Write to FD16, same as
694 void FM7_MAINIO::set_opn(int index, uint8 val)
696 //printf("OPN %d WRITE %02x \n", index, val);
697 if((index > 2) || (index < 0)) return;
698 if((index == 0) && (!connect_opn)) return;
699 if((index == 1) && (!connect_whg)) return;
700 if((index == 2) && (!connect_thg)) return;
702 if(opn[index] == NULL) return;
704 opn_data[index] = val;
705 switch(opn_cmdreg[index]){
706 case 0: // High inpedance
709 //opn[index]->write_io8(0, opn_address[index]);
710 //opn_data[index] = opn[index]->read_io8(1);
712 case 2: // Write Data
713 printf("OPN %d WRITE DATA %02x to REG ADDR=%02x\n", index, val, opn_address[index]);
714 opn[index]->write_io8(0, opn_address[index]);
715 opn[index]->write_io8(1, val & 0x00ff);
716 //opn[index]->write_signal(SIG_YM2203_MUTE, 0x00, 0x01); // Okay?
718 case 3: // Register address
719 opn_address[index] = val & 0xff;
720 //opn[index]->write_io8(0, opn_address[index]);
721 //printf("OPN %d REG ADDR=%02x\n", index, opn_address[index]);
722 if((val > 0x2c) && (val < 0x30)) {
724 opn[index]->write_io8(0, opn_address[index]);
725 opn[index]->write_io8(1, 0);
732 uint32 FM7_MAINIO::update_joystatus(int index)
734 uint32 *joybuf = p_emu->joy_buffer();
736 if((joybuf[index] & 0x01) != 0) val &= ~0x01;
737 if((joybuf[index] & 0x02) != 0) val &= ~0x02;
738 if((joybuf[index] & 0x04) != 0) val &= ~0x04;
739 if((joybuf[index] & 0x08) != 0) val &= ~0x08;
740 if((joybuf[index] & 0x10) != 0) val &= ~0x10;
741 if((joybuf[index] & 0x20) != 0) val &= ~0x20;
742 if((joybuf[index] & 0x40) != 0) val &= ~0x10;
743 if((joybuf[index] & 0x80) != 0) val &= ~0x20;
747 uint8 FM7_MAINIO::get_opn(int index)
750 if((index > 2) || (index < 0)) return 0xff;
751 if((index == 0) && (!connect_opn)) return 0xff;
752 if((index == 1) && (!connect_whg)) return 0xff;
753 if((index == 2) && (!connect_thg)) return 0xff;
755 if(opn[index] == NULL) return 0xff;
757 if(opn_cmdreg[index] == 0b00001001) {
758 //printf("OPN: JOY PORT ADDR=%02x\n", opn_address[index]);
760 if(opn_address[index] == 0x0e) {
761 joyport_a = update_joystatus(0);
762 joyport_b = update_joystatus(1);
763 opn[index]->write_io8(0, 0x0f);
764 val = opn[index]->read_io8(1);
765 //printf("JOY: A=%02x B=%02x Reg15=%02x\n", val, joyport_a, joyport_b);
766 if((val & 0x20) == 0x20) return joyport_a;
767 if((val & 0x50) == 0x50) return joyport_b;
772 if(opn_cmdreg[index] == 0b00000100) {
774 opn_stat[index] = opn[index]->read_io8(0) & 0x03;
775 return opn_stat[index];
777 switch(opn_cmdreg[index]) {
784 val = opn_data[index];
792 void FM7_MAINIO::set_opn_cmd(int index, uint8 cmd)
794 if((index > 2) || (index < 0)) return;
795 if((index == 0) && (!connect_opn)) return;
796 if((index == 1) && (!connect_whg)) return;
797 if((index == 2) && (!connect_thg)) return;
798 uint32 mask[16] = { // Parameter is related by XM7. Thanks Ryu.
799 0xff, 0x0f, 0xff, 0x0f,
800 0xff, 0x0f, 0x1f, 0xff,
801 0x1f, 0x1f, 0x1f, 0xff,
802 0xff, 0x0f, 0xff, 0xff
804 opn_cmdreg[index] = cmd & 0b00001111;
805 switch(opn_cmdreg[index]) {
809 //if(opn_address[index] > 0x0f) {
810 // opn_data[index] = 0xff;
813 opn[index]->write_io8(0, opn_address[index]);
814 opn_data[index] = opn[index]->read_io8(1) & mask[opn_address[index]];
815 printf("OPN %d READ DATA %02x from REG ADDR=%02x\n", index, opn_data[index], opn_address[index]);
818 printf("OPN %d WRITE DATA %02x to REG ADDR=%02x\n", index, opn_data[index], opn_address[index]);
819 //if(((opn_address[index] > 0x0d) && (opn_address[index] < 0x27)) ||
820 // ((opn_address[index] > 0x28) && (opn_address[index] < 0x2d))) break;
821 opn[index]->write_io8(0, opn_address[index]);
822 opn[index]->write_io8(1, opn_data[index]);
823 //opn[index]->write_signal(SIG_YM2203_MUTE, 0x00, 0x01); // Okay?
826 opn_address[index] = opn_data[index];
827 printf("OPN %d REG ADDR=%02x\n", index, opn_address[index]);
828 //opn[index]->write_io8(0, opn_address[index]);
829 if((opn_data[index] > 0x2c) && (opn_data[index] < 0x30)) {
831 opn[index]->write_io8(0, opn_address[index]);
832 opn[index]->write_io8(1, 0);
839 //printf("OPN %d SET REG ADDR=%02x\n", index, opn_cmdreg[index]);
845 void FM7_MAINIO::write_signal(int id, uint32 data, uint32 mask)
848 val_b = ((data & mask) != 0);
851 case FM7_MAINIO_CLOCKMODE: // fd00
860 #if defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS)
864 clocks = 2016000; // Hz
866 clocks = 1230502; // (2016 * 1095 / 1794)[KHz]
870 clocks = 1565000; // Hz
872 clocks = 955226; // (1565 * 1095 / 1794)[KHz]
877 clocks = 1794000; // Hz
879 clocks = 1095000; // Hz
884 clocks = 1794000; // Hz
886 clocks = 1095000; // Hz
890 subclocks = 2000000; // Hz
892 subclocks = 999000; // Hz
894 p_vm->set_cpu_clock(this->maincpu, clocks);
895 p_vm->set_cpu_clock(this->subcpu, subclocks);
898 case FM7_MAINIO_CMT_RECV: // FD02
899 cmt_indat = val_b ^ cmt_invert;
901 case FM7_MAINIO_CMT_INVERT: // FD02
904 case FM7_MAINIO_TIMERIRQ: //
905 set_irq_timer(val_b);
907 case FM7_MAINIO_LPTIRQ: //
908 set_irq_printer(val_b);
910 case FM7_MAINIO_KEYBOARDIRQ: //
911 set_irq_keyboard(val_b);
913 case FM7_MAINIO_PUSH_KEYBOARD:
914 set_keyboard(data & 0x1ff);
917 case FM7_MAINIO_PUSH_BREAK:
918 set_break_key(val_b);
920 case FM7_MAINIO_SUB_ATTENTION:
921 set_sub_attention(val_b);
924 case FM7_MAINIO_SUB_BUSY:
927 case FM7_MAINIO_EXTDET:
930 case FM7_MAINIO_BEEP:
932 if(event_beep < 0) register_event(this, EVENT_BEEP_CYCLE, (1000.0 * 1000.0) / (1200.0 * 2.0), true, &event_beep);
933 pcm1bit->write_signal(SIG_PCM1BIT_ON, 1, 1);
934 register_event(this, EVENT_BEEP_OFF, 205.0 * 1000.0, false, NULL); // NEXT CYCLE
936 case FM7_MAINIO_JOYPORTA_CHANGED:
937 joyport_a = data & mask;
939 case FM7_MAINIO_JOYPORTB_CHANGED:
940 joyport_b = data & mask;
942 case FM7_MAINIO_PSG_IRQ:
944 case FM7_MAINIO_OPN_IRQ:
948 case FM7_MAINIO_WHG_IRQ:
952 case FM7_MAINIO_THG_IRQ:
956 case FM7_MAINIO_FDC_DRQ:
959 case FM7_MAINIO_FDC_IRQ:
967 uint8 FM7_MAINIO::fdc_getdrqirq(void)
972 uint8 FM7_MAINIO::get_irqstat_fd03(void)
977 extirq = fdc_irq | intstat_opn | intstat_whg | intstat_thg;
979 //extirq = extirq | intstat_syndet | intstat_rxrdy | intstat_txrdy;
981 irqstat_reg0 &= 0b11110111;
984 irqstat_reg0 |= 0b00001000;
986 set_irq_timer(false);
987 set_irq_printer(false);
992 uint8 FM7_MAINIO::get_extirq_fd17(void)
995 if(intstat_opn) val &= 0b11110111;
996 if(intstat_mouse) val &= 0b11111011;
997 //if(intstat_opn || intstat_mouse) do_irq(false);
1001 void FM7_MAINIO::set_ext_fd17(uint8 data)
1003 if((data & 0b00000100) != 0) {
1004 mouse_enable = true;
1006 mouse_enable = false;
1012 uint8 FM7_MAINIO::get_extirq_whg(void)
1015 if(intstat_whg) val &= ~0x08;
1019 uint8 FM7_MAINIO::get_extirq_thg(void)
1022 if(intstat_thg) val &= ~0x08;
1029 void FM7_MAINIO::set_fdc_cmd(uint8 val)
1031 if(!connect_fdc) return;
1033 fdc->write_io8(0, val & 0x00ff);
1036 uint8 FM7_MAINIO::get_fdc_stat(void)
1038 if(!connect_fdc) return 0xff;
1039 //this->write_signal(FM7_MAINIO_FDC_IRQ, 0, 1);
1040 fdc_statreg = fdc->read_io8(0);
1044 void FM7_MAINIO::set_fdc_track(uint8 val)
1046 if(!connect_fdc) return;
1047 // if mode is 2DD and type-of-image = 2D then val >>= 1;
1049 fdc->write_io8(1, val & 0x00ff);
1052 uint8 FM7_MAINIO::get_fdc_track(void)
1054 if(!connect_fdc) return 0xff;
1055 fdc_trackreg = fdc->read_io8(1);
1056 return fdc_trackreg;
1059 void FM7_MAINIO::set_fdc_sector(uint8 val)
1061 if(!connect_fdc) return;
1063 fdc->write_io8(2, val & 0x00ff);
1066 uint8 FM7_MAINIO::get_fdc_sector(void)
1068 if(!connect_fdc) return 0xff;
1069 fdc_sectreg = fdc->read_io8(2);
1073 void FM7_MAINIO::set_fdc_data(uint8 val)
1075 if(!connect_fdc) return;
1077 fdc->write_io8(3, val & 0x00ff);
1080 uint8 FM7_MAINIO::get_fdc_data(void)
1082 if(!connect_fdc) return 0xff;
1083 fdc_datareg = fdc->read_io8(3);
1087 uint8 FM7_MAINIO::get_fdc_motor(void)
1090 if(!connect_fdc) return 0xff;
1091 if(fdc_motor) val = 0x80;
1092 val = val | (fdc_drvsel & 0x03);
1096 void FM7_MAINIO::set_fdc_fd1c(uint8 val)
1098 if(!connect_fdc) return;
1099 fdc_headreg = (val & 0x01) | 0xfe;
1100 fdc->write_signal(SIG_MB8877_SIDEREG, val, 0x01);
1103 uint8 FM7_MAINIO::get_fdc_fd1c(void)
1105 if(!connect_fdc) return 0xff;
1109 void FM7_MAINIO::set_fdc_fd1d(uint8 val)
1111 if(!connect_fdc) return;
1112 if((val & 0x80) != 0) {
1117 // fdc->write_signal(SIG_MB8877_DRIVEREG, val, 0x07);
1118 fdc->write_signal(SIG_MB8877_DRIVEREG, val, 0x03);
1119 fdc->write_signal(SIG_MB8877_MOTOR, val, 0x80);
1123 uint32 FM7_MAINIO::read_signal(uint32 addr)
1125 uint32 retval = 0xffffffff;
1131 uint32 FM7_MAINIO::read_data8(uint32 addr)
1133 if(addr == FM7_MAINIO_IS_BASICROM) {
1135 if(stat_bootsw_basic) retval = 0xffffffff;
1137 } else if(addr == FM7_MAINIO_BOOTMODE) {
1138 uint32 retval = bootmode & 0x03;
1139 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4) || defined(_FM77AV_VARIANTS)
1140 if(bootram) retval = 4;
1143 } else if(addr == FM7_MAINIO_READ_FD0F) {
1144 if(stat_romrammode) return 0xffffffff;
1146 } else if(addr == FM7_MAINIO_CLOCKMODE) {
1147 return (uint32)get_clockmode();
1149 #if defined(HAS_MMR)
1150 else if(addr == FM7_MAINIO_MMR_ENABLED) {
1151 uint32 retval = (mmr_enabled) ? 0xffffffff:0x00000000;
1153 } else if(addr == FM7_MAINIO_WINDOW_ENABLED) {
1154 uint32 retval = (window_enabled) ? 0xffffffff:0x00000000;
1156 } else if(addr == FM7_MAINIO_MMR_SEGMENT) {
1157 uint32 retval = (uint32) mmr_segment;
1159 } else if((addr >= FM7_MAINIO_MMR_BANK) && (addr < (FM7_MAINIO_MMR_BANK + 64))) {
1160 uint32 retval = (uint32)mmr_table[addr - FM7_MAINIO_MMR_BANK];
1164 #if defined(_FM77AV_VARIANTS)
1165 else if(addr == FM7_MAINIO_INITROM_ENABLED) {
1168 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
1169 else if(addr == FM7_MAINIO_EXTBANK) {
1170 } else if(addr == FM7_MAINIO_EXTROM) {
1173 //addr = addr & 0xff; //
1174 // printf("Main I/O READ: %04x\n", addr);
1177 case 0x100: // D400 (SUB)
1178 return (uint32) get_port_fd00();
1182 display->write_signal(SIG_FM7_SUB_KEY_FIRQ, 0, 1);
1183 set_irq_keyboard(false);
1184 return (uint32) kbd_bit7_0;
1187 return (uint32) get_port_fd02();
1190 return (uint32) get_irqstat_fd03();
1193 return (uint32) get_fd04();
1196 return (uint32) get_fd05();
1198 case 0x06: // RS-232C
1202 case 0x08: // Light pen
1211 return (uint32) get_psg();
1217 case 0x15: // OPN CMD
1218 return (uint32) 0xff;
1220 case 0x16: // OPN DATA
1221 return (uint32) get_opn(0);
1224 return (uint32) get_extirq_fd17();
1226 case 0x18: // FDC: STATUS
1227 return (uint32) get_fdc_stat();
1229 case 0x19: // FDC: Track
1230 return (uint32) get_fdc_track();
1232 case 0x1a: // FDC: Sector
1233 return (uint32) get_fdc_sector();
1235 case 0x1b: // FDC: Data
1236 return (uint32) get_fdc_data();
1239 return (uint32) get_fdc_fd1c();
1242 return (uint32) get_fdc_motor();
1245 return (uint32) fdc_getdrqirq();
1247 case 0x22: // Kanji ROM
1248 return (uint32) read_kanjidata_left();
1250 case 0x23: // Kanji ROM
1251 return (uint32) read_kanjidata_right();
1253 #if defined(_FM77AV_VARIANTS)
1254 case 0x2e: // Kanji ROM Level2
1255 return (uint32) read_kanjidata_left_l2();
1257 case 0x2f: // Kanji ROM Level2
1258 return (uint32) read_kanjidata_right_l2();
1261 case 0x37: // Multi page
1262 return (uint32)display->read_data8(DISPLAY_ADDR_MULTIPAGE);
1264 case 0x45: // WHG CMD
1265 return (uint32) 0xff;
1267 case 0x46: // WHG DATA
1268 return (uint32) get_opn(1);
1271 return (uint32) get_extirq_whg();
1273 case 0x51: // THG CMD
1274 return (uint32) 0xff;
1276 case 0x52: // THG DATA
1277 return (uint32) get_opn(2);
1280 return (uint32) get_extirq_thg();
1285 if((addr < 0x40) && (addr >= 0x38)) {
1286 addr = (addr - 0x38) + FM7_SUBMEM_OFFSET_DPALETTE;
1287 return (uint32) display->read_data8(addr);
1293 void FM7_MAINIO::write_data8(uint32 addr, uint32 data)
1295 if(addr == FM7_MAINIO_BOOTMODE) {
1296 bootmode = data & 0x03;
1298 } else if(addr == FM7_MAINIO_CLOCKMODE) {
1299 set_clockmode((uint8)data);
1302 addr = addr & 0xff; //
1306 set_port_fd00((uint8)data);
1310 // set_lptdata_fd01((uint8)data);
1313 set_port_fd02((uint8)data);
1319 // set_flags_fd04(data);
1322 set_fd05((uint8)data);
1324 case 0x06: // RS-232C
1327 case 0x08: // Light pen
1340 case 0x15: // OPN CMD
1341 set_opn_cmd(0, data);
1343 case 0x16: // OPN DATA
1347 set_ext_fd17((uint8)data);
1349 case 0x18: // FDC: COMMAND
1350 set_fdc_cmd((uint8)data);
1352 case 0x19: // FDC: Track
1353 set_fdc_track((uint8)data);
1355 case 0x1a: // FDC: Sector
1356 set_fdc_sector((uint8)data);
1358 case 0x1b: // FDC: Data
1359 set_fdc_data((uint8)data);
1362 set_fdc_fd1c((uint8)data);
1365 set_fdc_fd1d((uint8)data);
1370 case 0x20: // Kanji ROM
1371 write_kanjiaddr_hi((uint8)data);
1373 case 0x21: // Kanji ROM
1374 write_kanjiaddr_lo((uint8)data);
1376 #if defined(_FM77AV_VARIANTS)
1377 case 0x2c: // Kanji ROM
1378 write_kanjiaddr_hi_l2((uint8)data);
1380 case 0x2d: // Kanji ROM
1381 write_kanjiaddr_lo_l2((uint8)data);
1384 case 0x37: // Multi page
1385 display->write_signal(SIG_FM7_SUB_MULTIPAGE, data, 0x00ff);
1387 case 0x45: // WHG CMD
1388 set_opn_cmd(1, data);
1390 case 0x46: // WHG DATA
1395 case 0x51: // THG CMD
1396 set_opn_cmd(2, data);
1398 case 0x52: // THG DATA
1403 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4) || defined(_FM77AV_VARIANTS)
1405 if((data & 0x01) == 0) {
1410 if((data & 0x40) == 0) {
1411 window_enabled = false;
1413 window_enabled = true;
1415 if((data & 0x80) == 0) {
1416 mmr_enabled = false;
1425 if((addr < 0x40) && (addr >= 0x38)) {
1426 addr = (addr - 0x38) | FM7_SUBMEM_OFFSET_DPALETTE;
1427 display->write_data8(addr, (uint8)data);
1433 void FM7_MAINIO::event_callback(int event_id, int err)
1435 // printf("MAIN EVENT id=%d\n", event_id);
1437 case EVENT_BEEP_OFF:
1440 if(event_beep >= 0) cancel_event(this, event_beep);
1442 pcm1bit->write_signal(SIG_PCM1BIT_ON, 0, 1);
1444 case EVENT_BEEP_CYCLE:
1445 beep_snd = !beep_snd;
1446 pcm1bit->write_signal(SIG_PCM1BIT_SIGNAL, beep_snd ? 1 : 0, 1);
1448 case EVENT_UP_BREAK:
1449 set_break_key(false);
1451 case EVENT_TIMERIRQ_ON:
1452 set_irq_timer(true);
1453 //register_event(this, EVENT_TIMERIRQ_OFF, 2035.0 / 2.0, false, NULL); // TIMER OFF
1455 case EVENT_TIMERIRQ_OFF:
1456 set_irq_timer(false);
1457 //register_event(this, EVENT_TIMERIRQ_ON, 2035, false, NULL); // TIMER ON