OSDN Git Service

896366d017c39214505b67c7d78f4c8f3f784232
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / fm7_mainio.cpp
1 /*
2  * FM-7 Main I/O [fm7_mainio.h]
3  *
4  * Author: K.Ohta <whatisthis.sowhat _at_ gmail.com>
5  * License: GPLv2
6  * History:
7  *   Jan 03, 2015 : Initial
8  *
9  */
10
11
12 #include "fm7_mainio.h"
13
14
15 void FM7_MAINIO::initialize(void)
16 {
17 #if defined(_FM8)
18         clock_fast = false;
19 #else
20         clock_fast = true;
21 #endif
22         //      connect_fdc = true;
23         event_beep = -1;
24         event_timerirq = -1;
25         bootmode = config.boot_mode & 3;
26         register_event(this, EVENT_TIMERIRQ_ON, 4069.0, true, &event_timerirq); // TIMER IRQ
27 }
28
29 void FM7_MAINIO::reset(void)
30 {
31         if(event_beep >= 0) cancel_event(this, event_beep);
32         if(event_timerirq >= 0) cancel_event(this, event_timerirq);
33         event_beep = -1;
34         register_event(this, EVENT_TIMERIRQ_ON, 4069.0, true, &event_timerirq); // TIMER IRQ
35         if(connect_fdc) fdc->reset();
36         if(connect_opn) opn[0]->reset();
37         if(connect_whg) opn[1]->reset();
38         if(connect_thg) opn[2]->reset();
39 #if !defined(_FM77AV_VARIANTS)
40         if(psg != NULL) psg->reset();
41 #endif
42         stat_romrammode = true;
43         bootmode = config.boot_mode & 3;
44 //   maincpu->reset();
45 }
46
47
48 void FM7_MAINIO::set_clockmode(uint8 flags)
49 {
50         if(flags == FM7_MAINCLOCK_SLOW) {
51                 clock_fast = false;
52         } else {
53                 clock_fast = true;
54         }
55 }
56
57 uint8 FM7_MAINIO::get_clockmode(void)
58 {
59         if(clock_fast) return FM7_MAINCLOCK_SLOW;
60         return FM7_MAINCLOCK_HIGH;
61 }
62
63
64 uint8 FM7_MAINIO::get_port_fd00(void)
65 {
66         uint8 ret = 0;
67         if(kbd_bit8) ret |= 0x80;
68         if(clock_fast) ret |= 0x01;
69         return ret;
70 }
71   
72 void FM7_MAINIO::set_port_fd00(uint8 data)
73 {
74        drec->write_signal(SIG_DATAREC_OUT, data, 0x01);
75        drec->write_signal(SIG_DATAREC_REMOTE, data, 0x02);
76 }
77    
78 uint8 FM7_MAINIO::get_port_fd02(void)
79 {
80         uint8 ret;
81         // Still unimplemented printer.
82         ret = (cmt_indat) ? 0x80 : 0x00; // CMT 
83         return ret;
84 }
85
86 void FM7_MAINIO::set_port_fd02(uint8 val)
87 {
88         irqmask_reg0 = val;
89         if((val & 0b00010000) != 0) {
90                 irqmask_mfd = false;
91         } else {
92                 irqmask_mfd = true;
93         }
94         if((val & 0b00000100) != 0) {
95                 irqmask_timer = false;
96         } else {
97                 irqmask_timer = true;
98         }
99         if((val & 0b00000010) != 0) {
100                 irqmask_printer = false;
101         } else {
102                 irqmask_printer = true;
103         }
104         if((val & 0b00000001) != 0) {
105                 irqmask_keyboard = false;
106         } else {
107                 irqmask_keyboard = true;
108         }
109         return;
110 }
111
112
113 uint32 FM7_MAINIO::get_keyboard(void)
114 {
115         uint32 kbd_data = (uint32) kbd_bit7_0;
116         kbd_data &= 0x0ff;
117         if(kbd_bit8) kbd_data |= 0x0100;
118         return kbd_data;
119 }
120
121 void FM7_MAINIO::do_irq(bool flag)
122 {
123         if(flag) {
124                 maincpu->write_signal(SIG_CPU_IRQ, 1, 1);
125         } else {
126                 maincpu->write_signal(SIG_CPU_IRQ, 0, 1);
127         }
128 }
129
130
131 void FM7_MAINIO::set_beep(uint32 data) // fd03
132 {
133         beep_flag = ((data & 0xc0) != 0);
134         beep_flag &= ((data & 0x01) != 0); 
135         //beep->write_signal(SIG_BEEP_ON, data, 0b11000000);
136         //beep->write_signal(SIG_BEEP_MUTE, ~data , 0b00000001);
137         if(beep_flag) {
138                 beep_snd = true;
139                 if(event_beep < 0) register_event(this, EVENT_BEEP_CYCLE, (1000.0 * 1000.0) / (1200.0 * 2.0), true, &event_beep);
140                 pcm1bit->write_signal(SIG_PCM1BIT_ON, 1, 1);
141         } else {
142                 if(event_beep >= 0) cancel_event(this, event_beep);
143                 event_beep = -1;
144                 pcm1bit->write_signal(SIG_PCM1BIT_ON, 0, 1);
145         }
146         if((data & 0x40) != 0) {
147                 // BEEP ON, after 205ms, BEEP OFF.  
148                 register_event(this, EVENT_BEEP_OFF, 205.0 * 1000.0, false, NULL); // NEXT CYCLE
149         }
150 }
151
152 void FM7_MAINIO::set_irq_timer(bool flag)
153 {
154         if(flag) {
155                 irqstat_reg0 &= 0b11111011;
156                 if(!irqmask_timer) do_irq(true);
157         } else {
158                 irqstat_reg0 |= 0b00000100;
159                 if(!irqmask_timer) do_irq(false);
160         }
161         //printf("IRQ TIMER: %d MASK=%d\n", flag, irqmask_timer);
162 }
163
164 void FM7_MAINIO::set_irq_printer(bool flag)
165 {
166         if(flag && !irqmask_printer) {
167                 irqstat_reg0 &= 0b11111101;
168                 do_irq(true);
169                 return;
170         }
171         if(flag == false) {
172                 irqstat_reg0 |= 0b00000010;
173         }
174         do_irq(false);
175 }
176
177 void FM7_MAINIO::set_irq_keyboard(bool flag)
178 {
179         if(flag) {
180                 irqstat_reg0 &= 0b11111110;
181                 if(!irqmask_keyboard) do_irq(true);
182                 return;
183         } else {
184                 irqstat_reg0 |= 0b00000001;
185                 if(!irqmask_keyboard) do_irq(false);
186         }
187 }
188
189 void FM7_MAINIO::set_irq_mfd(bool flag)
190 {
191         fdc_irq = flag;
192         if(flag &&  connect_fdc) {
193                 irqstat_fdc |= 0b01000000;
194         }
195         if((flag == false) && connect_fdc){
196                 irqstat_fdc &= 0b10111111;
197         }
198         if(!irqmask_mfd) do_irq(flag);
199         return;
200 }
201
202 void FM7_MAINIO::set_drq_mfd(bool flag)
203 {
204         fdc_irq = flag;
205         if(flag &&  connect_fdc) {
206                 irqstat_fdc |= 0b10000000;
207         }
208         if((flag == false) && connect_fdc){
209                 irqstat_fdc &= 0b01111111;
210         }
211         if(!irqmask_mfd) do_irq(flag);
212         return;
213 }
214
215
216  void FM7_MAINIO::set_keyboard(uint32 data)
217 {
218         if((data & 0x100) != 0){
219                 kbd_bit8 = true;
220         } else {
221                 kbd_bit8 = false;
222         }
223         kbd_bit7_0 = (data & 0xff);
224 }
225
226 void FM7_MAINIO::do_firq(bool flag)
227 {
228         if(flag) {
229                 maincpu->write_signal(SIG_CPU_FIRQ, 1, 1);
230         } else {
231                 maincpu->write_signal(SIG_CPU_FIRQ, 0, 1);
232         }      
233 }
234
235 void FM7_MAINIO::set_break_key(bool pressed)
236 {
237         firq_break_key = pressed;
238         do_firq(pressed);
239 }
240 void FM7_MAINIO::set_sub_attention(bool flag)
241 {
242         firq_sub_attention = flag;
243         do_firq(flag); 
244 }
245   
246
247 uint8 FM7_MAINIO::get_fd04(void)
248 {
249         uint8 val = 0b11111100;
250         if(!firq_break_key)     val |= 0b00000010;
251         if(!firq_sub_attention) val |= 0b00000001;
252         if(firq_sub_attention) {
253                 firq_sub_attention = false;
254         }
255 //      do_firq(false);
256         return val;
257 }
258
259 void FM7_MAINIO::set_fd04(uint8 val)
260 {
261         // NOOP?
262 }
263
264   // FD05
265  uint8 FM7_MAINIO::get_fd05(void)
266 {
267         uint8 val = 0b01111110;
268         if(sub_busy)    val |= 0b10000000;
269         if(!extdet_neg) val |= 0b00000001;
270         return val;
271 }
272
273  void FM7_MAINIO::set_fd05(uint8 val)
274 {
275         display->write_signal(SIG_FM7_SUB_HALT, val, 0b10000000);
276         display->write_signal(SIG_FM7_SUB_CANCEL, val, 0b01000000);
277         if((val & 0b10000000) == 0) {
278                 sub_haltreq = false;
279         } else {
280                 sub_haltreq = true;
281         }
282 #ifdef WITH_Z80
283         if((val & 0b00000001) != 0) {
284                 maincpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
285                 //z80->write_signal(SIG_CPU_BUSREQ, 0, 1);
286         } else {
287                 maincpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
288                 //z80->write_signal(SIG_CPU_BUSREQ, 1, 1);
289         }
290 #endif
291 }
292
293
294
295 void FM7_MAINIO::set_extdet(bool flag)
296 {
297         extdet_neg = flag;
298 }
299
300 void FM7_MAINIO::set_psg(uint8 val)
301 {
302         if(psg == NULL) return set_opn(val, 0); // 77AV ETC
303         switch(psg_cmdreg & 0x03){
304                 case 0: // High inpedance
305                         return;
306                         break;
307                 case 1: // Read Data
308                         //psg_data = psg->read_io8(1);
309                         break;
310                 case 2: // Write Data
311                         psg->write_io8(1, val & 0x00ff);
312                         psg->write_signal(SIG_YM2203_MUTE, 0x01, 0x01); // Okay?
313                         break;
314                 case 3: // Register address
315                         psg_address = val & 0x0f;
316                         psg->write_io8(0, psg_address);
317                         break;
318         }
319 }
320
321 uint8 FM7_MAINIO::get_psg(void)
322 {
323         uint8 val = 0xff;
324         if(psg == NULL) return get_opn(0); // 77AV ETC
325         switch(psg_cmdreg & 0x03) {
326                 case 0:
327                         val = 0xff;
328                         break;
329                 case 1:
330                         val = psg->read_io8(1);
331                         psg_data = val & 0x00ff;
332                         break;
333                 case 2:
334                         val = 0xff; // Write conflict
335                         break;
336                 case 3:
337                         val = psg->read_io8(1);
338                         psg_address = val;
339                         break;
340         }
341         return val;
342 }
343
344 /*
345  * $fd0d : After 77AV, this is OPN.
346  */
347 void FM7_MAINIO::set_psg_cmd(uint32 cmd)
348 {
349         if(opn_psg_77av) {
350                 set_opn_cmd(cmd);
351                 return;
352         }
353         psg_cmdreg = (uint8)(cmd & 0b00000011);
354         return;
355 }
356
357 uint8 FM7_MAINIO::get_psg_cmd(void)
358 {
359         if(opn_psg_77av) return get_opn_cmd(); 
360         return ((psg_cmdreg & 0b00000011) | 0b11111100);
361 }
362
363
364
365 // Kanji ROM, FD20 AND FD21 (or SUBSYSTEM)
366 void FM7_MAINIO::write_kanjiaddr_hi(uint8 addr)
367 {
368         if(!connect_kanjiroml1) return;
369         kaddress_hi = addr;
370         return;
371 }
372
373 void FM7_MAINIO::write_kanjiaddr_lo(uint8 addr)
374 {
375         if(!connect_kanjiroml1) return;
376         kaddress_lo = addr;
377         return;
378 }
379
380 uint8 FM7_MAINIO::read_kanjidata_left(void)
381 {
382         uint32 addr;
383     
384         if(!connect_kanjiroml1) return 0xff;
385         addr = ((uint32)kaddress_hi << 8) | (uint32)kaddress_lo;
386         addr = addr << 1;
387         if(kanjiclass1) {
388                 return kanjiclass1->read_data8(addr);
389         } else {
390                 return 0xff;
391         }
392 }
393
394 uint8 FM7_MAINIO::read_kanjidata_right(void)
395 {
396         uint32 addr;
397     
398         if(!connect_kanjiroml1) return 0xff;
399         addr = ((uint32)kaddress_hi << 8) | (uint32)kaddress_lo;
400         addr = (addr << 1) | 1;
401         if(kanjiclass1) {
402                 return kanjiclass1->read_data8(addr);
403         } else {
404                 return 0xff;
405         }
406 }
407
408 #ifdef _FM77AV_VARIANTS
409 // Kanji ROM, FD20 AND FD21 (or SUBSYSTEM)
410 void FM7_MAINIO::write_kanjiaddr_hi_l2(uint8 addr)
411 {
412         if(!connect_kanjiroml2) return;
413         kaddress_hi_l2 = addr;
414         return;
415 }
416
417 void FM7_MAINIO::write_kanjiaddr_lo_l2(uint8 addr)
418 {
419         if(!connect_kanjiroml2) return;
420         kaddress_lo_l2 = addr;
421         return;
422 }
423
424 uint8 FM7_MAINIO::read_kanjidata_left_l2(void)
425 {
426         uint32 addr;
427     
428         if(!connect_kanjiroml2) return 0xff;
429         addr = ((uint32)kaddress_hi_l2 << 8) | (uint32)kaddress_lo_l2;
430         addr = addr << 1;
431         if(kanjiclass2) {
432                 return kanjiclass2->read_data8(addr);
433         } else {
434                 return 0xff;
435         }
436 }
437
438 uint8 FM7_MAINIO::read_kanjidata_right_l2(void)
439 {
440         uint32 addr;
441     
442         if(!connect_kanjiroml2) return 0xff;
443         addr = ((uint32)kaddress_hi_l2 << 8) | (uint32)kaddress_lo_l2;
444         addr = (addr << 1) | 0x01;
445         if(kanjiclass2) {
446                 return kanjiclass2->read_data8(addr);
447         } else {
448                 return 0xff;
449         }
450 }
451 #endif
452 // OPN
453 // Write to FD16, same as 
454 void FM7_MAINIO::set_opn(uint8 val, int index)
455 {
456         if((index > 2) || (index < 0)) return;
457         if(opn[index] == NULL) return;
458         if((opn_cmdreg[index] & 0b00001000) != 0) {
459                 // Read Joystick
460                 return;
461         }
462         if((opn_cmdreg[index] & 0b00000100) != 0) {
463                 // Read Status
464                 return;
465         }
466         switch(opn_cmdreg[index] & 0x03){
467                 case 0: // High inpedance
468                         return;
469                         break;
470                 case 1: // Read Data
471                         //psg_data = psg->read_io8(1);
472                         break;
473                 case 2: // Write Data
474                         opn_data[index] = val & 0x00ff;
475                         opn[index]->write_io8(1, val & 0x00ff);
476                         opn[index]->write_signal(SIG_YM2203_MUTE, 0x01, 0x01); // Okay?
477                         break;
478                 case 3: // Register address
479                         opn_address[index] = val & 0x0f;
480                         opn[index]->write_io8(0, psg_address);
481                         break;
482         }
483 }
484
485  uint8 FM7_MAINIO::get_opn(int index)
486 {
487         uint8 val = 0xff;
488         if((index > 2) || (index < 0)) return val;
489         if(opn[index] == NULL) return val;
490         if((opn_cmdreg[index] & 0b00001000) != 0) {
491                 // Read Joystick
492                 val = opn[index]->read_io8(1); // opn->joystick?
493                 opn_data[index] = val & 0x00ff;
494                 return val;
495         }
496         if((opn_cmdreg[index] & 0b00000100) != 0) {
497                 // Read Status
498                 val = opn[index]->read_io8(0);
499                 opn_stat[index] = val & 0x00ff;
500                 return val;
501         }
502         switch(opn_cmdreg[index] & 0x03) {
503                 case 0:
504                         val = 0xff;
505                         break;
506                 case 1:
507                         val = opn[index]->read_io8(1);
508                         opn_data[index] = val & 0x00ff;
509                         break;
510                 case 2:
511                         val = 0xff; // Write conflict
512                         break;
513                 case 3:
514                         val = opn[index]->read_io8(1);
515                         opn_address[index] = val;
516                         break;
517         }
518         return val;
519 }
520   /*
521    * $fd16?
522    */
523 void FM7_MAINIO::set_opn_cmd(uint32 cmd)
524 {
525         if(!connect_opn) return;
526         opn_cmdreg[0] = (uint8)(cmd & 0b00001111);
527         return;
528 }
529
530 uint8 FM7_MAINIO::get_opn_cmd(void)
531 {
532         if(!connect_opn) return 0xff;
533         return ((opn_cmdreg[0] & 0b00001111) | 0b11110000);
534 }
535
536 void FM7_MAINIO::set_whg_cmd(uint32 cmd)
537 {
538         if(!connect_whg) return;
539         opn_cmdreg[1] = (uint8)(cmd & 0b00001111);
540         return;
541 }
542
543 uint8 FM7_MAINIO::get_whg_cmd(void)
544 {
545         if(!connect_whg) return 0xff;
546         return ((opn_cmdreg[1] & 0b00001111) | 0b11110000);
547 }
548
549 void FM7_MAINIO::set_thg_cmd(uint32 cmd)
550 {
551         if(!connect_thg) return;
552         opn_cmdreg[2] = (uint8)(cmd & 0b00001111);
553         return;
554 }
555
556 uint8 FM7_MAINIO::get_thg_cmd(void)
557 {
558         if(!connect_thg) return 0xff;
559         return ((opn_cmdreg[2] & 0b00001111) | 0b11110000);
560 }
561
562 void FM7_MAINIO::write_signal(int id, uint32 data, uint32 mask)
563 {
564         bool val_b;
565         val_b = ((data & mask) != 0);
566   
567         switch(id) {
568                 case FM7_MAINIO_CLOCKMODE: // fd00
569                         if(val_b) {
570                                 clock_fast = true;
571                         } else {
572                                 clock_fast = false;
573                         }
574                         {
575                                 uint32 clocks;
576                                 uint32 subclocks;
577 #if defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS)
578                                 if(mmr_enabled) {
579                                         if(mmr_fast) {
580                                                 if(clock_fast) {
581                                                         clocks = 2016000; // Hz
582                                                 } else {
583                                                         clocks = 1230502; // (2016 * 1095 / 1794)[KHz]
584                                                 }
585                                         } else {
586                                                 if(clock_fast) {
587                                                         clocks = 1565000; // Hz
588                                                 } else {
589                                                         clocks =  955226; // (1565 * 1095 / 1794)[KHz]
590                                                 }
591                                         }
592                                 } else {
593                                         if(clock_fast) {
594                                                 clocks = 1794000; // Hz 
595                                         } else {
596                                                 clocks = 1095000; // Hz
597                                         }
598                                 }
599 #else // 7/8
600                                 if(clock_fast) {
601                                         clocks = 1794000; // Hz 
602                                 } else {
603                                         clocks = 1095000; // Hz
604                                 }
605 #endif
606                                 if(clock_fast) {
607                                         subclocks = 2000000; // Hz
608                                 } else {
609                                         subclocks =  999000; // Hz
610                                 }
611                                 p_vm->set_cpu_clock(this->maincpu, clocks);
612                                 p_vm->set_cpu_clock(this->subcpu,  subclocks);
613                         }
614                         break;
615                 case FM7_MAINIO_CMT_RECV: // FD02
616                         cmt_indat = val_b ^ cmt_invert;
617                         break;
618                 case FM7_MAINIO_CMT_INVERT: // FD02
619                         cmt_invert = val_b;
620                         break;
621                 case FM7_MAINIO_TIMERIRQ: //
622                         //set_irq_timer(val_b);
623                         break;
624                 case FM7_MAINIO_LPTIRQ: //
625                         set_irq_printer(val_b);
626                         break;
627                 case FM7_MAINIO_KEYBOARDIRQ: //
628                         set_irq_keyboard(val_b);
629                         break;
630                 case FM7_MAINIO_PUSH_KEYBOARD:
631                         set_keyboard(data & 0x1ff);
632                         break;
633                         // FD04
634                 case FM7_MAINIO_PUSH_BREAK:
635                         set_break_key(val_b);
636                         break;
637                 case FM7_MAINIO_SUB_ATTENTION:
638                         set_sub_attention(val_b);
639                         break;
640                         // FD05
641                 case FM7_MAINIO_SUB_BUSY:
642                         sub_busy = val_b;
643                         break;
644                 case FM7_MAINIO_EXTDET:
645                         extdet_neg = !val_b;
646                         break;
647                 case FM7_MAINIO_BEEP:
648                         beep_flag = true;
649                         beep_snd = true;
650                         register_event(this, EVENT_BEEP_CYCLE, (1000.0 * 1000.0) / (1200.0 * 2.0), true, &event_beep);
651                         pcm1bit->write_signal(SIG_PCM1BIT_ON, 1, 1);
652                         register_event(this, EVENT_BEEP_OFF, 205.0 * 1000.0, false, NULL); // NEXT CYCLE
653                         break;
654                 case FM7_MAINIO_OPNPORTA_CHANGED:
655                         opnport_a = data & mask;
656                         break;
657                 case FM7_MAINIO_OPNPORTB_CHANGED:
658                         opnport_a = data & mask;
659                         break;
660                 case FM7_MAINIO_PSG_IRQ:
661                         break;
662                 case FM7_MAINIO_OPN_IRQ:
663                         intstat_opn = val_b;
664                         do_irq(val_b);
665                         break;
666                 case FM7_MAINIO_WHG_IRQ:
667                         intstat_whg = val_b;
668                         do_irq(val_b);
669                         break;
670                 case FM7_MAINIO_THG_IRQ:
671                         intstat_thg = val_b;
672                         do_irq(val_b);
673                         break;
674                 case FM7_MAINIO_FDC_DRQ:
675                         set_drq_mfd(val_b);
676                         break;
677                 case FM7_MAINIO_FDC_IRQ:
678                         set_irq_mfd(val_b);
679                         break;
680         }
681         
682 }
683
684
685 uint8 FM7_MAINIO::fdc_getdrqirq(void)
686 {
687         return irqstat_fdc;
688 }
689
690  uint8 FM7_MAINIO::get_irqstat_fd03(void)
691 {
692         uint8 val = 0b11111000;
693         bool extirq = false;
694         
695         extirq = intstat_opn | intstat_mouse | fdc_irq;
696         extirq = extirq | intstat_thg | intstat_whg;
697         //extirq = extirq | intstat_syndet | intstat_rxrdy | intstat_txrdy;
698         if(extirq) val &= 0b11110111;
699         val &= irqstat_reg0;
700         return val;
701 }
702
703 uint8 FM7_MAINIO::get_extirq_fd17(void)
704 {
705         uint8 val = 0xff;
706         if(intstat_opn)   val &= 0b11110111;
707         if(intstat_mouse) val &= 0b11111011;
708         return val;
709 }
710
711 void FM7_MAINIO::set_ext_fd17(uint8 data)
712 {
713         if((data & 0b00000100) != 0) {
714                 mouse_enable = true;
715         } else {
716                 mouse_enable = false;
717         }
718    
719 }
720
721 /* FDD */
722
723 void FM7_MAINIO::set_fdc_cmd(uint8 val)
724 {
725         if(!connect_fdc) return;
726         fdc_cmdreg = val;
727         fdc->write_io8(0, val & 0x00ff);
728 }
729
730 uint8 FM7_MAINIO::get_fdc_stat(void)
731 {
732         if(!connect_fdc) return 0xff;
733         this->write_signal(FM7_MAINIO_FDC_IRQ, 0, 1);
734         fdc_statreg =  fdc->read_io8(0);
735         return fdc_statreg;
736 }
737
738 void FM7_MAINIO::set_fdc_track(uint8 val)
739 {
740         if(!connect_fdc) return;
741         // if mode is 2DD and type-of-image = 2D then val >>= 1;
742         fdc_trackreg = val;
743         fdc->write_io8(1, val & 0x00ff);
744 }
745
746 uint8 FM7_MAINIO::get_fdc_track(void)
747 {
748         if(!connect_fdc) return 0xff;
749         fdc_trackreg = fdc->read_io8(1);
750         return fdc_trackreg;
751 }
752
753 void FM7_MAINIO::set_fdc_sector(uint8 val)
754 {
755         if(!connect_fdc) return;
756         fdc_sectreg = val;
757         fdc->write_io8(2, val & 0x00ff);
758 }
759
760 uint8 FM7_MAINIO::get_fdc_sector(void)
761 {
762         if(!connect_fdc) return 0xff;
763         fdc_sectreg = fdc->read_io8(2);
764         return fdc_sectreg;
765 }
766   
767 void FM7_MAINIO::set_fdc_data(uint8 val)
768 {
769         if(!connect_fdc) return;
770         fdc_datareg = val;
771         fdc->write_io8(3, val & 0x00ff);
772 }
773
774 uint8 FM7_MAINIO::get_fdc_data(void)
775 {
776         if(!connect_fdc) return 0xff;
777         fdc_datareg = fdc->read_io8(3);
778         return fdc_datareg;
779 }
780
781 uint8 FM7_MAINIO::get_fdc_motor(void)
782 {
783         uint8 val = 0x00;
784         if(!connect_fdc) return 0xff;
785         if(fdc_motor) val = 0x80;
786         val = val | (fdc_drvsel & 0x03);
787         return val;
788 }
789   
790 void FM7_MAINIO::set_fdc_fd1c(uint8 val)
791 {
792         if(!connect_fdc) return;
793         fdc_headreg = (val & 0x01) | 0xfe;
794         fdc->write_signal(SIG_MB8877_SIDEREG, val, 0x01);
795 }
796
797 uint8 FM7_MAINIO::get_fdc_fd1c(void)
798 {
799         if(!connect_fdc) return 0xff;
800         return fdc_headreg;
801 }
802
803 void FM7_MAINIO::set_fdc_fd1d(uint8 val)
804 {
805         if(!connect_fdc) return;
806         if((val & 0x80) != 0) {
807                 fdc_motor = true;
808         } else {
809                 fdc_motor = false;
810         }
811         //      fdc->write_signal(SIG_MB8877_DRIVEREG, val, 0x07);
812         fdc->write_signal(SIG_MB8877_DRIVEREG, val, 0x03);
813         fdc->write_signal(SIG_MB8877_MOTOR, val, 0x80);
814         fdc_drvsel = val;
815 }
816    
817 uint32 FM7_MAINIO::read_signal(uint32 addr)
818 {
819         uint32 retval = 0xffffffff;
820         switch(addr) {
821         }
822         return retval;
823 }
824
825 uint32 FM7_MAINIO::read_data8(uint32 addr)
826 {
827         if(addr == FM7_MAINIO_IS_BASICROM) {
828                 uint32 retval = 0;
829                 if(stat_bootsw_basic) retval = 0xffffffff;
830                 return retval;
831         } else if(addr == FM7_MAINIO_BOOTMODE) {
832                 uint32 retval = bootmode & 0x03;
833 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4) || defined(_FM77AV_VARIANTS)
834                 if(bootram) retval = 4;
835 #endif
836                 return retval;
837         } else if(addr == FM7_MAINIO_READ_FD0F) {
838                 if(stat_romrammode) return 0xffffffff;
839                 return 0;
840         } else if(addr == FM7_MAINIO_CLOCKMODE) {
841                 return (uint32)get_clockmode();
842         }
843 #if defined(HAS_MMR)    
844         else if(addr == FM7_MAINIO_MMR_ENABLED) {
845                 uint32 retval = (mmr_enabled) ? 0xffffffff:0x00000000;
846                 return retval;
847         } else if(addr == FM7_MAINIO_WINDOW_ENABLED) {
848                 uint32 retval = (window_enabled) ? 0xffffffff:0x00000000;
849                 return retval;
850         } else if(addr == FM7_MAINIO_MMR_SEGMENT) {
851                 uint32 retval = (uint32) mmr_segment;
852                 return retval;
853         } else if((addr >= FM7_MAINIO_MMR_BANK) &&  (addr < (FM7_MAINIO_MMR_BANK + 64))) {
854                 uint32 retval = (uint32)mmr_table[addr - FM7_MAINIO_MMR_BANK];
855                 return retval;
856         }
857 #endif
858 #if defined(_FM77AV_VARIANTS)
859         else if(addr == FM7_MAINIO_INITROM_ENABLED) {
860         }
861 #endif
862 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX)
863         else if(addr == FM7_MAINIO_EXTBANK) {
864         } else if(addr == FM7_MAINIO_EXTROM) {
865         }
866 #endif
867         //addr = addr & 0xff; //
868         //      printf("Main I/O READ: %04x\n", addr);
869         switch(addr) {
870                 case 0x00: // FD00
871                 case 0x100: // D400 (SUB)
872                         return (uint32) get_port_fd00();
873                         break;
874                 case 0x01: // FD01
875                 case 0x101: // D401
876                         display->write_signal(SIG_FM7_SUB_KEY_FIRQ, 0, 1);
877                         set_irq_keyboard(false);
878                         return (uint32) kbd_bit7_0;
879                         break;
880                 case 0x02: // FD02
881                         return (uint32) get_port_fd02();
882                         break;
883                 case 0x03: // FD03
884                         return (uint32) get_irqstat_fd03();
885                         break;
886                 case 0x04: // FD04
887                         return (uint32) get_fd04();
888                         break;
889                 case 0x05: // FD05
890                         return (uint32) get_fd05();
891                         break;
892                 case 0x06: // RS-232C
893                 case 0x07:
894                         return 0xff;
895                         break;
896                 case 0x08: // Light pen
897                 case 0x09:
898                 case 0x0a:
899                         return 0xff;
900                         break;
901                 case 0x0d:
902                         return (uint32) get_psg_cmd();
903                         break;
904                 case 0x0e:
905                         return (uint32) get_psg();
906                         break;
907                 case 0x0f: // FD0F
908                         read_fd0f();
909                         return 0x00ff;
910                         break;
911                 case 0x15: // OPN CMD
912                         return (uint32) get_opn_cmd();
913                         break;
914                 case 0x16: // OPN DATA
915                         return (uint32) get_opn(0);
916                         break;
917                 case 0x17:
918                         return (uint32) get_extirq_fd17();
919                         break;
920                 case 0x18: // FDC: STATUS
921                         return (uint32) get_fdc_stat();
922                         break;
923                 case 0x19: // FDC: Track
924                         return (uint32) get_fdc_track();
925                         break;
926                 case 0x1a: // FDC: Sector
927                         return (uint32) get_fdc_sector();
928                         break;
929                 case 0x1b: // FDC: Data
930                         return (uint32) get_fdc_data();
931                         break;
932                 case 0x1c:
933                         return (uint32) get_fdc_fd1c();
934                         break;
935                 case 0x1d:
936                         return (uint32) get_fdc_motor();
937                         break;
938                 case 0x1f:
939                         return (uint32) fdc_getdrqirq();
940                         break;
941                 case 0x22: // Kanji ROM
942                         return (uint32) read_kanjidata_left();
943                         break;
944                 case 0x23: // Kanji ROM
945                         return (uint32) read_kanjidata_right();
946                         break;
947 #if defined(_FM77AV_VARIANTS)
948                 case 0x2e: // Kanji ROM Level2
949                         return (uint32) read_kanjidata_left_l2();
950                         break;
951                 case 0x2f: // Kanji ROM Level2
952                         return (uint32) read_kanjidata_right_l2();
953                         break;
954 #endif
955                 case 0x37: // Multi page
956                         return (uint32)display->read_data8(DISPLAY_ADDR_MULTIPAGE);
957                         break;
958                 default:
959                         break;
960         }
961         if((addr < 0x40) && (addr >= 0x38)) {
962                 addr = (addr - 0x38) + FM7_SUBMEM_OFFSET_DPALETTE;
963                 return (uint32) display->read_data8(addr);
964         }
965         // Another:
966         return 0xff;
967 }
968
969 void FM7_MAINIO::write_data8(uint32 addr, uint32 data)
970 {
971         if(addr == FM7_MAINIO_BOOTMODE) {
972                 bootmode = data & 0x03;
973                 return;
974         } else if(addr == FM7_MAINIO_CLOCKMODE) {
975                 set_clockmode((uint8)data);
976                 return;
977         }
978         addr = addr & 0xff; //
979         data = data & 0xff;
980         switch(addr) {
981                 case 0x00: // FD00
982                         set_port_fd00((uint8)data);
983                         return;
984                         break;
985                 case 0x01: // FD01
986                         // set_lptdata_fd01((uint8)data);
987                         break;
988                 case 0x02: // FD02
989                         set_port_fd02((uint8)data);
990                         break;
991                 case 0x03: // FD03
992                         set_beep(data);
993                         break;
994                 case 0x04: // FD04
995
996                         // set_flags_fd04(data);
997                         break;
998                 case 0x05: // FD05
999                         set_fd05((uint8)data);
1000                         break;
1001                 case 0x06: // RS-232C
1002                 case 0x07:
1003                         break;
1004                 case 0x08: // Light pen
1005                 case 0x09:
1006                 case 0x0a:
1007                         break;
1008                 case 0x0d:
1009                         set_psg_cmd((uint8)data);
1010                         break;
1011                 case 0x0e:
1012                         set_psg((uint8)data);
1013                         break;
1014                 case 0x0f: // FD0F
1015                         write_fd0f();
1016                         break;
1017                 case 0x15: // OPN CMD
1018                         set_opn_cmd((uint8)data);
1019                         break;
1020                 case 0x16: // OPN DATA
1021                         set_opn(0, (uint8)data);
1022                         break;
1023                 case 0x17:
1024                         set_ext_fd17((uint8)data);
1025                         break;
1026                 case 0x18: // FDC: COMMAND
1027                         set_fdc_cmd((uint8)data);
1028                         break;
1029                 case 0x19: // FDC: Track
1030                         set_fdc_track((uint8)data);
1031                         break;
1032                 case 0x1a: // FDC: Sector
1033                         set_fdc_sector((uint8)data);
1034                         break;
1035                 case 0x1b: // FDC: Data
1036                         set_fdc_data((uint8)data);
1037                         break;
1038                 case 0x1c:
1039                         set_fdc_fd1c((uint8)data);
1040                         break;
1041                 case 0x1d:
1042                         set_fdc_fd1d((uint8)data);
1043                         break;
1044                 case 0x1f: // ??
1045                         return;
1046                         break;
1047                 case 0x20: // Kanji ROM
1048                         write_kanjiaddr_hi((uint8)data);
1049                         break;
1050                 case 0x21: // Kanji ROM
1051                         write_kanjiaddr_lo((uint8)data);
1052                         break;
1053 #if defined(_FM77AV_VARIANTS)
1054                 case 0x2c: // Kanji ROM
1055                         write_kanjiaddr_hi_l2((uint8)data);
1056                         break;
1057                 case 0x2d: // Kanji ROM
1058                         write_kanjiaddr_lo_l2((uint8)data);
1059                         break;
1060 #endif
1061                 case 0x37: // Multi page
1062                         display->write_signal(SIG_FM7_SUB_MULTIPAGE, data, 0x00ff);
1063                         break;
1064 #if defined(_FM77) || defined(_FM77L2) || defined(_FM77L4) || defined(_FM77AV_VARIANTS)
1065                 case 0x93:
1066                         if((data & 0x01) == 0) {
1067                                 boot_ram = false;
1068                         } else {
1069                                 boot_ram = true;
1070                         }         
1071                         if((data & 0x40) == 0) {
1072                                 window_enabled = false;
1073                         } else {
1074                                 window_enabled = true;
1075                         }         
1076                         if((data & 0x80) == 0) {
1077                                 mmr_enabled = false;
1078                         } else {
1079                                 mmr_enabled = true;
1080                         }
1081                         break;
1082 #endif
1083                 default:
1084                         break;
1085         }
1086         if((addr < 0x40) && (addr >= 0x38)) {
1087                 addr = (addr - 0x38) | FM7_SUBMEM_OFFSET_DPALETTE;
1088                 display->write_data8(addr, (uint8)data);
1089                 return;
1090         }       // Another:
1091         return;
1092 }
1093
1094 void FM7_MAINIO::event_callback(int event_id, int err)
1095 {
1096 //      printf("MAIN EVENT id=%d\n", event_id);
1097         switch(event_id) {
1098                 case EVENT_BEEP_OFF:
1099                         //beep->write_signal(SIG_BEEP_ON, 0x00, 0x01);
1100                         beep_flag = false;
1101                         beep_snd = false;
1102                         if(event_beep >= 0) {
1103                                 cancel_event(this, event_beep);
1104                                 event_beep = -1;
1105                         }
1106                         pcm1bit->write_signal(SIG_PCM1BIT_ON, 0, 1);
1107                         break;
1108                 case EVENT_BEEP_CYCLE:
1109                         beep_snd = !beep_snd;
1110                         pcm1bit->write_signal(SIG_PCM1BIT_ON, beep_snd ? 1 : 0, 1);
1111                         break;
1112                 case EVENT_UP_BREAK:
1113                         set_break_key(false);
1114                         break;
1115                 case EVENT_TIMERIRQ_ON:
1116                         set_irq_timer(true);
1117                         register_event(this, EVENT_TIMERIRQ_OFF, 2034, false, NULL); // TIMER OFF
1118                         break;
1119                 case EVENT_TIMERIRQ_OFF:
1120                         set_irq_timer(false);
1121                         //register_event(this, EVENT_TIMERIRQ_ON, 2035, false, NULL); // TIMER ON
1122                         break;
1123                 default:
1124                         break;
1125         }
1126 }
1127
1128