OSDN Git Service

[VM][FM-7] Incl. memory emulation.
[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 #define EVENT_UPDATE_T77 3
15
16 int FM7_CMT::load_t77_image(void)
17 {
18         uint8 tmpbuf[17];
19    
20         total_count = 0;
21         total_length = 0;
22         // Check Length
23         memset(tmpbuf, 0x00, 17);
24         play_fio->Fseek(0, FILEIO_SEEK_END);
25         buffer_length = drec->play_fio->Ftell();
26         if(buffer_length < 18) goto _error_2;
27         // Check MAGIC
28         play_fio->Fseek(0, FILEIO_SEEK_SET);
29         play_fio->Fread(tmpbuf, 16, 1);
30         tmpbuf[16] = '\0';
31         if(strcmp(tmpbuf, "XM7 TAPE IMAGE 0") != 0) goto _error_2;
32         buffer_ptr = 0;
33         buffer_length = buffer_length - 16;
34         // MAGIC Ok.
35         is_t77 = true;
36         buffer = (uint8 *)malloc(buffer_length);
37         if(buffer == NULL) goto _error_2;
38         // OK, Now Read.
39         play_fio->Fread(buffer, buffer_length, 1);
40         play_fio->Fclose();
41         
42         {
43                 int tptr;
44                 uint8 lo, hi;
45                 uint64 val;
46                 for(tptr = 0; tptr < buffer_length; tptr += 2) {
47                         hi = buffer[tptr];
48                         lo = buffer[tptr + 1];
49                         val = (hi * 256 + lo) & 0x7fff;
50                         total_length += val;
51                 }
52         }
53         parse_t77();
54         return buffer_length;
55 }
56
57 int FM7_CMT::get_tape_ptr(void)
58 {
59         if(!is_t77) {
60                 if((buffer_length == 0) || (buffer == NULL)) return -1;
61                 return (100 * buffer_ptr) / buffer_length;
62         } else { // T77
63                 if(total_count == 0) return -1;
64                 return ((total_count * 100) / total_length);
65         }
66 }
67
68 void FM7_CMT::event_callback(int event_id, int err)
69 {
70         if(event_id == EVENT_UPDATE_T77) {
71                 this->parse_t77();
72                 return;
73         }
74         drec->event_callback(event_id, err);
75 }
76
77
78 void FM7_CMT::parse_t77(void)
79 {
80         uint8 hi, lo;
81         double usec;
82         if(!is_t77) return;
83         
84         if(buffer == NULL) {
85           return;
86         }
87         do {
88                 if(buffer_length <= buffer_ptr) {
89                         return;
90                 }
91                 hi = buffer[buffer_ptr++];
92                 lo = buffer[buffer_ptr++];
93                 rawdata = hi * 256 + lo;
94                 total_count += (rawdata & 0x7fff);
95         } while((rawdata & 0x7fff) != 0x0000);
96         
97         if((rawdata & 0x8000) == 0) {
98                 in_signal = false;
99                 this->write_signal(SIG_DATAREC_OUT, 0x00, 0x01);
100         } else {
101                 in_signal = true;
102                 this->write_signal(SIG_DATAREC_OUT, 0x01, 0x01);
103         }
104         usec = (double)(rawdata & 0x7fff);
105         usec = usec * 9;
106         register_event(this, EVENT_UPDATE_T77, usec, false, NULL); // NEXT CYCLE
107         update_event();
108 }
109
110
111 void FM7_MAINIO::set_port_fd00(uint8 data)
112 {
113         cmt->write_data8(0x00, data);
114 }
115
116 FM7_MAINIO::FM7_MAINIO(VM *parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
117 {
118         int i;
119         cmt = new FM7_CMT;
120         keyboard = new FM7_KEYBOARD;
121 }  
122
123 void FM7_MAINIO::set_clockmode(uint8 flags)
124 {
125         if(flags == FM7_MAINCLOCK_SLOW) {
126                 clock_fast = false;
127         } else {
128                 clock_fast = true;
129         }
130 }
131
132 uint8 FM7_MAINIO::get_clockmode(void)
133 {
134         if(clock_fast) return FM7_MAINCLOCK_SLOW;
135         return FM7_MAINCLOCK_HIGH;
136 }
137
138
139 uint8 FM7_MAINIO::get_port_fd00(void)
140 {
141         uint8 ret = 0;
142         if(kbd_bit8) ret |= 0x80;
143         if(clock_fast) ret |= 0x01;
144         return ret;
145 }
146   
147 void FM7_MAINIO::set_port_fd00(uint8 data)
148 {
149         if(cmt != NULL) cmt->write_data8(0x00, data);
150 }
151    
152 uint8 FM7_MAINIO::get_port_fd02(void)
153 {
154         uint8 ret = 0x00;
155         // Still unimplemented printer.
156         ret |= cmt->read_data8(0x02); // CMT 
157         return ret;
158 }
159
160 void FM7_MAINIO::set_port_fd02(uint8 val)
161 {
162         irqmask_reg0 = val;
163         if((val & 0b00010000) != 0) {
164                 irqmask_mfd = false;
165         } else {
166                 irqmask_mfd = true;
167         }
168         if((val & 0b00000100) != 0) {
169                 irqmask_timer = false;
170         } else {
171                 irqmask_timer = true;
172         }
173         if((val & 0b00000010) != 0) {
174                 irqmask_printer = false;
175         } else {
176                 irqmask_printer = true;
177         }
178         if((val & 0b00000001) != 0) {
179                 irqmask_keyboard = false;
180         } else {
181                 irqmask_keyboard = true;
182         }
183         return;
184 }
185
186
187 uint32 FM7_MAINIO::get_keyboard(void)
188 {
189         uint32 kbd_data = (uint32) kbd_bit7_0;
190         kbd_data &= 0x0ff;
191         if(kbd_bit8) kbd_data |= 0x0100;
192         return kbd_data;
193 }
194
195 void FM7_MAINIO::do_irq(bool flag)
196 {
197         if(flag) {
198                 maincpu->write_signal(SIG_CPU_IRQ, 1, 1);
199         } else {
200                 maincpu->write_signal(SIG_CPU_IRQ, 0, 1);
201         }
202 }
203
204
205 void FM7_MAINIO::set_beep(uint32 data) // fd03
206 {
207         beep->write_signal(SIG_BEEP_ON, data, 0b11000000);
208         beep->write_signal(SIG_BEEP_MUTE, data , 0b00000001);
209         if((data & 0x40) != 0) {
210           //            beep->write_signal(SIG_BEEP_ON, 0b01000000, 0b01000000);
211                 // BEEP ON, after 200ms, BEEP OFF.  
212                 register_event(this, EVENT_BEEP_OFF, 200.0 * 1000.0, false, NULL); // NEXT CYCLE
213         }
214 }
215
216 void FM7_MAINIO::set_irq_timer(bool flag)
217 {
218         if(flag && !irqmask_timer) {
219                 irqstat_reg0 &= 0b11111011;
220                 do_irq(true);
221                 return;
222         }
223         //
224         if(flag == false) {
225                 irqstat_reg0 |= 0b00000100;
226         }
227         do_irq(false);
228 }
229
230 void FM7_MAINIO::set_irq_printer(bool flag)
231 {
232         if(flag && !irqmask_printer) {
233                 irqstat_reg0 &= 0b11111101;
234                 do_irq(true);
235                 return;
236         }
237         if(flag == false) {
238                 irqstat_reg0 |= 0b00000010;
239         }
240         do_irq(false);
241 }
242
243 void FM7_MAINIO::set_irq_keyboard(bool flag)
244 {
245         if(flag && !irqmask_keyboard) {
246                 irqstat_reg0 &= 0b11111110;
247                 do_irq(true);
248                 return;
249         }
250         if(flag == false) {
251                 irqstat_reg0 |= 0b00000001;
252         }
253         do_irq(false);
254 }
255
256 void FM7_MAINIO::set_irq_mfd(bool flag)
257 {
258         fdc_irq = flag;
259         if(flag && !irqmask_mfd && fdc_connected) {
260                 irqstat_fdc |= 0b01000000;
261                 do_irq(true);
262                 return;
263         }
264         if((flag == false) && fdc_connected){
265                 irqstat_fdc &= 0b10111111;
266         }
267         return;
268 }
269
270
271  void FM7_MAINIO::set_keyboard(uint32 data)
272 {
273         if((data & 0x100) != 0){
274                 kbd_bit8 = true;
275         } else {
276                 kbd_bit8 = false;
277         }
278         kbd_bit7_0 = (data & 0xff);
279 }
280
281 void FM7_MAINIO::do_firq(bool flag)
282 {
283         if(flag) {
284                 maincpu->write_signal(SIG_CPU_FIRQ, 1, 1);
285         } else {
286                 maincpu->write_signal(SIG_CPU_FIRQ, 0, 1);
287         }      
288 }
289
290 void FM7_MAINIO::set_break_key(bool pressed)
291 {
292         firq_break_key = pressed;
293         do_firq(pressed);
294 }
295 void FM7_MAINIO::set_sub_attention(bool flag)
296 {
297         firq_sub_attention = flag;
298         do_firq(flag); 
299 }
300   
301
302 uint8 FM7_MAINIO::get_fd04(void)
303 {
304         uint8 val = 0b11111100;
305         if(!firq_break_key)     val |= 0b00000010;
306         if(!firq_sub_attention) val |= 0b00000001;
307         return val;
308 }
309
310 void FM7_MAINIO::set_fd04(uint8 val)
311 {
312         // NOOP?
313 }
314
315   // FD05
316  uint8 FM7_MAINIO::get_fd05(void)
317 {
318         uint8 val = 0b01111110;
319         if(sub_busy)    val |= 0b10000000;
320         if(!extdet_neg) val |= 0b00000001;
321 }
322
323  void FM7_MAINIO::set_fd05(uint8 val)
324 {
325         subio->write_signal(SIG_SUBIO_HALT, val, 0b10000000);
326         subio->write_signal(SIG_SUBIO_IRQ, val, 0b01000000);
327         if((val & 0b10000000) == 0) {
328                 sub_haltreq = false;
329         } else {
330                 sub_haltreq = true;
331         }
332         if((val & 0b00000001) != 0) {
333                 maincpu->write_signal(SIG_CPU_BUSREQ, 1, 1);
334                 //z80->write_signal(SIG_CPU_BUSREQ, 0, 1);
335         } else {
336                 maincpu->write_signal(SIG_CPU_BUSREQ, 0, 1);
337                 //z80->write_signal(SIG_CPU_BUSREQ, 1, 1);
338         }
339 }
340
341 void FM7_MAINIO::set_extdet(bool flag)
342 {
343         extdet_neg = flag;
344 }
345
346 void FM7_MAINIO::set_psg(uint8 val)
347 {
348         switch(psg_cmdreg & 0x03){
349                 case 0: // High inpedance
350                         return;
351                         break;
352                 case 1: // Read Data
353                         //psg_data = psg->read_io8(1);
354                         break;
355                 case 2: // Write Data
356                         psg->write_io(1, val & 0x00ff);
357                         psg->write_signal(SIG_YM2203_MUTE, 0x01, 0x01); // Okay?
358                         break;
359                 case 3: // Register address
360                         psg_address = val & 0x0f;
361                         psg->write_io8(0, psg_address);
362                         break;
363         }
364 }
365
366 uint8 FM7_MAINIO::get_psg(void)
367 {
368         uint8 val = 0xff;
369         switch(psg_cmdreg & 0x03) {
370                 case 0:
371                         val = 0xff;
372                         break;
373                 case 1:
374                         val = psg->read_io8(1);
375                         psg_data = val & 0x00ff;
376                         break;
377                 case 2:
378                         val = 0xff; // Write conflict
379                         break;
380                 case 3:
381                         val = psg->read_io8(1);
382                         psg_address = val;
383                         break;
384         }
385         return val;
386 }
387
388 /*
389  * $fd0d : After 77AV, this is OPN.
390  */
391 void FM7_MAINIO::set_psg_cmd(uint32 cmd)
392 {
393         if(opn_psg_77av) {
394                 set_opn_cmd(cmd);
395                 return;
396         }
397         psg_cmdreg = (uint8)(cmd & 0b00000011);
398         return;
399 }
400
401 uint8 FM7_MAINIO::get_psg_cmd(void)
402 {
403         if(opn_psg_77av) return get_opn_cmd(); 
404         return ((psg_cmdreg & 0b00000011) | 0b11111100);
405 }
406
407
408
409 // Kanji ROM, FD20 AND FD21 (or SUBSYSTEM)
410 void FM7_MAINIO::write_kanjiaddr_hi(uint8 addr)
411 {
412         if(!connect_kanjirom1) return;
413         kaddress_hi = addr;
414         return;
415 }
416
417 void FM7_MAINIO::write_kanjiaddr_lo(uint8 addr)
418 {
419         if(!connect_kanjirom1) return;
420         kaddress_lo = addr;
421         return;
422 }
423
424 uint8 FM7_MAINIO::read_kanjidata_left(void)
425 {
426         uint32 addr;
427     
428         if(!connect_kanjirom1) return;
429         addr = ((kaddress_hi & 0xff) * 256) + (kaddress_lo * 0xff);
430         addr = addr * 2;
431         if(kanjiclass1) {
432                 return kanjiclass1->read_data8(addr);
433         } else {
434                 return 0xff;
435         }
436 }
437
438 uint8 FM7_MAINIO::read_kanjidata_right(void)
439 {
440         uint32 addr;
441     
442         if(!connect_kanjirom1) return;
443         addr = ((kaddress_hi & 0xff) * 256) + (kaddress_lo * 0xff);
444         addr = addr * 2 + 1;
445         if(kanjiclass1) {
446                 return kanjiclass1->read_data8(addr);
447         } else {
448                 return 0xff;
449         }
450 }
451
452 // OPN
453 // Write to FD16, same as 
454  void FM7_MAINIO::set_opn(uint8 val, int index)
455 {
456         switch(index) {
457                 case 0: // OPN
458                         if(!opn_connected) return;
459                         break;
460                 case 1: // WHG
461                         if(!whg_connected) return;
462                         break;
463                 case 2: // THG
464                         if(!thg_connected) return;
465                         break;
466                 default:
467                         return;
468                         break;
469         }
470         if((opn_cmdreg[index] & 0b00001000) != 0) {
471                 // Read Joystick
472                 return;
473         }
474         if((opn_cmdreg[index] & 0b00000100) != 0) {
475                 // Read Status
476                 return;
477         }
478         switch(opn_cmdreg[index] & 0x03){
479                 case 0: // High inpedance
480                         return;
481                         break;
482                 case 1: // Read Data
483                         //psg_data = psg->read_io8(1);
484                         break;
485                 case 2: // Write Data
486                         opn_data[index] = val & 0x00ff;
487                         opn[index]->write_io(1, val & 0x00ff);
488                         opn[index]->write_signal(SIG_YM2203_MUTE, 0x01, 0x01); // Okay?
489                         break;
490                 case 3: // Register address
491                         opn_address[index] = val & 0x0f;
492                         opn[index]->write_io8(0, psg_address);
493                         break;
494         }
495 }
496
497  uint8 FM7_MAINIO::get_opn(int index)
498 {
499         uint8 val = 0xff;
500         switch(index) {
501                 case 0: // OPN
502                         if(!opn_connected) return val;
503                         break;
504                 case 1: // WHG
505                         if(!whg_connected) return val;
506                         break;
507                 case 2: // THG
508                         if(!thg_connected) return val;
509                         break;
510                 default:
511                         return val;
512                         break;
513         }
514         if((opn_cmdreg[index] & 0b00001000) != 0) {
515                 // Read Joystick
516                 val = opn[index]->read_io8(1); // opn->joystick?
517                 opn_data[index] = val & 0x00ff;
518                 return val;
519         }
520         if((opn_cmdreg[index] & 0b00000100) != 0) {
521                 // Read Status
522                 val = opn[index]->read_io8(0);
523                 opn_stat[index] = val & 0b00ff;
524                 return val;
525         }
526         switch(opn_cmdreg[index] & 0x03) {
527                 case 0:
528                         val = 0xff;
529                         break;
530                 case 1:
531                         val = opn[index]->read_io8(1);
532                         opn_data[index] = val & 0x00ff;
533                         break;
534                 case 2:
535                         val = 0xff; // Write conflict
536                         break;
537                 case 3:
538                         val = opn[index]->read_io8(1);
539                         opn_address[index] = val;
540                         break;
541         }
542         return val;
543 }
544   /*
545    * $fd16?
546    */
547 void FM7_MAINIO::set_opn_cmd(uint32 cmd)
548 {
549         if(!connect_opn) return;
550         opn_cmdreg[0] = (uint8)(cmd & 0b00001111);
551         return;
552 }
553
554 uint8 FM7_MAINIO::get_opn_cmd(void)
555 {
556         if(!connect_opn) return 0xff;
557         return ((opn_cmdreg[0] & 0b00001111) | 0b11110000);
558 }
559
560 void FM7_MAINIO::wait()
561 {
562         int waitfactor; // If MMR of TWR enabled, factor = 3.
563                             // If memory, factor = 2?
564         if(!ioaccess_wait) {
565                 waitfactor = 2;
566                 ioaccess_wait = true;
567         } else { // Not MMR, TWR or enabled FAST MMR mode
568                 waitfactor = 2; // If(MMR or TWR) and NOT FAST MMR factor = 3, else factor = 2
569                 ioaccess_wait =false;
570         } 
571           
572         if(waitfactor <= 0) return;
573         if(!clock_fast) return;
574         waitcount++;
575         if(waitcount >= waitfactor) {
576                 maincpu->set_extra_icount(1);
577                 waitcount = 0;
578         }
579 }
580
581 void FM7_MAINIO::write_signals(int id, uint32 data, uint32 mask)
582 {
583         bool val_b;
584         val_b = ((data & mask) != 0);
585   
586         switch(id) {
587                 case FM7_MAINIO_CLOCKMODE: // fd00
588                         if(val_b) {
589                                 clock_fast = true;
590                         } else {
591                                 clock_fast = false;
592                         }
593                         break;
594                 case FM7_MAINIO_CMTIN: // fd02
595                         cmt_rdata = val_b;
596                         return;
597                 case FM7_MAINIO_TIMERIRQ: //
598                         set_irq_timer(val_b);
599                         break;
600                 case FM7_MAINIO_LPTIRQ: //
601                         set_irq_printer(val_b);
602                         break;
603                 case FM7_MAINIO_KEYBOARDIRQ: //
604                         set_irq_keyboard(val_b);
605                         break;
606                 case FM7_MAINIO_PUSH_KEYBOARD:
607                         set_keyboard(data & 0x1ff);
608                         break;
609                         // FD04
610                 case FM7_MAINIO_PUSH_BREAK:
611                         set_break_key(val_b);
612                         break;
613                 case FM7_MAINIO_SUB_ATTENTION:
614                         set_sub_attention(val_b);
615                         break;
616                         // FD05
617                 case FM7_SUB_BUSY:
618                         sub_busy = val_b;
619                         break;
620                 case FM7_MAINIO_EXTDET:
621                         extdet_neg = !val_b;
622                         break;
623                 case FM7_MAINIO_BEEP:
624                         beep->write_signal(SIG_BEEP_ON, data, mask);
625                         break;
626                 case FM7_MAINIO_OPNPORTA_CHANGED:
627                         opnport_a = data & mask;
628                         break;
629                 case FM7_MAINIO_OPNPORTB_CHANGED:
630                         opnport_a = data & mask;
631                         break;
632                 case FM7_MAINIO_PSG_IRQ:
633                         break;
634                 case FM7_MAINIO_OPN_IRQ:
635                         intstat_opn = val_b;
636                         do_irq(val_b);
637                         break;
638                 case FM7_MAINIO_WHG_IRQ:
639                         intstat_whg = val_b;
640                         do_irq(val_b);
641                         break;
642                 case FM7_MAINIO_THG_IRQ:
643                         intstat_thg = val_b;
644                         do_irq(val_b);
645                         break;
646                 case FM7_MAINIO_FDC_DRQ:
647                         fdc_drq = val_b;
648                         if(fdc_drq) {
649                                 irqstat_fdc |= 0b10000000;
650                         } else {
651                                 irqstat_fdc &= 0b01111111;
652                         }
653                         break;
654                 case FM7_MAINIO_FDC_IRQ:
655                         if(val_b) {
656                                 irqstat_fdc |= 0b01000000;
657                         } else {
658                                 irqstat_fdc &= 0b10111111;
659                         }
660                         set_irq_mfd(val_b);
661                         break;
662                 case FM7_MAINIO_MPUCLOCK:
663                         if(val_b) {
664                                 maincpu->set_context_cpu(maincpu, 2000000); // 2MHz
665                         } else {
666                                 maincpu->set_context_cpu(maincpu, 1200000); // 1.2MHz
667                         }
668                         break;
669         }
670         
671 }
672
673 uint8 FM7_MAINIO::fdc_getdrqirq(void)
674 {
675         return irqstat_fdc;
676 }
677
678  uint8 FM7_MAINIO::get_irqstat_fd03(void)
679 {
680         uint8 val = 0b11111000;
681         bool extirq = false;
682         
683         extirq = instat_opn | intstat_mouse | fdc_irq;
684         extirq = extirq | intstat_thg | intstat_whg;
685         //extirq = extirq | intstat_syndet | intstat_rxrdy | intstat_txrdy;
686         if(extirq) val &= 0b11110111;
687         val &= irqstat_reg0;
688         return val;
689 }
690
691  uint8 FM7_MAINIO::get_extirq_fd17(void)
692 {
693         uint8 val = 0xff;
694         if(intstat_opn)   val &= 0b11110111;
695         if(intstat_mouse) val &= 0b11111011;
696         return val;
697 }
698
699  void FM7_MAINIO::set_ext_fd17(uint8 data)
700 {
701         if((data & 0b00000100) != 0) {
702                 mouse_enable = true;
703         } else {
704                 mouse_enable = false;
705         }
706    
707 }
708
709 /* FDD */
710
711 void FM7_MAINIO::set_fdc_stat(uint8 val)
712 {
713         if(!connect_fdc) return;
714         fdc_statreg = val;
715         fdc->write_io8(0, val & 0x00ff);
716 }
717
718 uint8 FM7_MAINIO::get_fdc_stat(void)
719 {
720         if(!connect_fdc) return 0xff;
721         this->write_signals(FM7_MAINIO_FDC_IRQ, 0, 1);
722         fdc_statreg =  fdc->read_io8(0);
723         return fdc_statreg;
724 }
725
726 void FM7_MAINIO::set_fdc_track(uint8 val)
727 {
728         if(!connect_fdc) return;
729         // if mode is 2DD and type-of-image = 2D then val >>= 1;
730         fdc_trackreg = val;
731         fdc->write_io8(1, val & 0x00ff);
732 }
733
734 uint8 FM7_MAINIO::get_fdc_track(void)
735 {
736         if(!connect_fdc) return 0xff;
737         fdc_trackreg = fdc->read_io8(1);
738         return fdc_trackreg;
739 }
740
741 void FM7_MAINIO::set_fdc_sector(uint8 val)
742 {
743         if(!connect_fdc) return;
744         fdc_sectreg = val;
745         fdc->write_io8(2, val & 0x00ff);
746 }
747
748 uint8 FM7_MAINIO::get_fdc_sector(void)
749 {
750         if(!connect_fdc) return 0xff;
751         fdc_sectreg = fdc->read_io8(2);
752         return fdc_sectreg;
753 }
754   
755 void FM7_MAINIO::set_fdc_data(uint8 val)
756 {
757         if(!connect_fdc) return;
758         fdc_datareg = val;
759         fdc->write_io8(3, val & 0x00ff);
760 }
761
762 uint8 FM7_MAINIO::get_fdc_data(void)
763 {
764         if(!connect_fdc) return 0xff;
765         fdc_datareg = fdc->read_io(3);
766         return fdc_datareg;
767 }
768
769 uint8 FM7_MAINIO::get_fdc_motor(void)
770 {
771         uint8 val = 0x00;
772         if(fdc_motor) val = 0x80;
773         val = val | (fdc_drvsel & 0x03);
774         return val;
775 }
776   
777 void FM7_MAINIO::set_fdc_fd1c(uint8 val)
778 {
779         fdc_headreg = (val & 0x01) | 0xfe;
780         fdc->write_signal(SIG_MB8877_SIDEREG, val, 0x01);
781 }
782
783 uint8 FM7_MAINIO::get_fdc_fd1c(void)
784 {
785         return fdc_headreg;
786 }
787
788 void FM7_MAINIO::set_fdc_fd1d(uint8 val)
789 {
790         if((val & 0x80) != 0) {
791                 fdc_motor = true;
792         } else {
793                 fdc_motor = false;
794         }
795         fdc->write_signal(SIG_MB8877_DRIVEREG, val, 0x07);
796         fdc->write_signal(SIG_MB8877_MOTOR, val, 0x80);
797         fdc_drvsel = val;
798 }
799    
800
801 uint32 FM7_MAINIO::read_data8(uint32 addr)
802 {
803
804         addr = addr & 0xff; //
805         this->wait();
806         switch(addr) {
807                 case 0x00: // FD00
808                         return (uint32) get_port_fd00();
809                         break;
810                 case 0x01: // FD01
811                         return (uint32) kbd_bit7_0;
812                         break;
813                 case 0x02: // FD02
814                         return (uint32) get_port_fd02();
815                         break;
816                 case 0x03: // FD03
817                         return (uint32) get_irqstat_fd03();
818                         break;
819                 case 0x04: // FD04
820                         return (uint32) get_fd04();
821                         break;
822                 case 0x05: // FD05
823                         return (uint32) get_fd05();
824                         break;
825                 case 0x06: // RS-232C
826                 case 0x07:
827                         return 0xff;
828                         break;
829                 case 0x08: // Light pen
830                 case 0x09:
831                 case 0x0a:
832                         return 0xff;
833                         break;
834                 case 0x0d:
835                         return (uint32) get_psg_cmd();
836                         break;
837                 case 0x0e:
838                         return (uint32) get_psg();
839                         break;
840                 case 0x0f: // FD0F
841                         read_fd0f();
842                         return 0x00ff;
843                         break;
844                 case 0x15: // OPN CMD
845                         return (uint32) get_opn_cmd();
846                         break;
847                 case 0x16: // OPN DATA
848                         return (uint32) get_opn();
849                         break;
850                 case 0x17:
851                         return (uint32) get_extirq_fd17();
852                         break;
853                 case 0x18: // FDC: STATUS
854                         return (uint32) get_fdc_stat();
855                         break;
856                 case 0x19: // FDC: Track
857                         return (uint32) get_fdc_track();
858                         break;
859                 case 0x1a: // FDC: Sector
860                         return (uint32) get_fdc_sector();
861                         break;
862                 case 0x1b: // FDC: Data
863                         return (uint32) get_fdc_data();
864                         break;
865                 case 0x1c:
866                         return (uint32) get_fdc_fd1c();
867                         break;
868                 case 0x1d:
869                         return (uint32) get_fdc_motor();
870                         break;
871                 case 0x1f:
872                         return (uint32) irqstat_fdc;
873                         break;
874                 case 0x20: // Kanji ROM
875                         return (uint32) read_kanjidata_left();
876                         break;
877                 case 0x21: // Kanji ROM
878                         return (uint32) read_kanjidata_right();
879                         break;
880                 case 0x37: // Multi page
881                         return (uint32)display->read_data8(DISPLAY_ADDR_MULTIPAGE);
882                         break;
883                 default:
884                         break;
885         }
886         if((addr < 0x40) && (addr >= 0x38)) {
887                 addr = (addr - 0x38) + DISPLAY_ADDR_DPALETTE;
888                 return (uint32) display->read_data8(addr);
889         }
890         // Another:
891         return 0xff;
892 }
893
894 void FM7_MAINIO::write_data8(uint32 addr, uint32 data)
895 {
896
897         this->wait();
898         addr = addr & 0xff; //
899         data = data & 0xff;
900
901         switch(addr) {
902                 case 0x00: // FD00
903                         set_port_fd00((uint8)data);
904                         return;
905                         break;
906                 case 0x01: // FD01
907                         // set_lptdata_fd01((uint8)data);
908                         return;
909                         break;
910                 case 0x02: // FD02
911                         set_port_fd02((uint8)data);
912                         return;
913                         break;
914                 case 0x03: // FD03
915                         set_beep(data);
916                         return;
917                         break;
918                 case 0x04: // FD04
919                         // set_flags_fd04(data);
920                         return;
921                         break;
922                 case 0x05: // FD05
923                         set_fd05((uint8)data);
924                         return;
925                         break;
926                 case 0x06: // RS-232C
927                 case 0x07:
928                         return;
929                         break;
930                 case 0x08: // Light pen
931                 case 0x09:
932                 case 0x0a:
933                         return;
934                         break;
935                 case 0x0d:
936                         set_psg_cmd((uint8)data);
937                         return;
938                         break;
939                 case 0x0e:
940                         set_psg((uint8)data);
941                         return;
942                         break;
943                 case 0x0f: // FD0F
944                         write_fd0f();
945                         return;
946                         break;
947                 case 0x15: // OPN CMD
948                         return set_opn_cmd((uint8)data);
949                         break;
950                 case 0x16: // OPN DATA
951                         return set_opn((uint8)data);
952                         break;
953                 case 0x17:
954                         set_ext_fd17((uint8)data);
955                         return;
956                         break;
957                 case 0x18: // FDC: STATUS
958                         return set_fdc_stat((uint8)data);
959                         break;
960                 case 0x19: // FDC: Track
961                         return set_fdc_track((uint8)data);
962                         break;
963                 case 0x1a: // FDC: Sector
964                         return set_fdc_sector((uint8)data);
965                         break;
966                 case 0x1b: // FDC: Data
967                         return set_fdc_data((uint8)data);
968                         break;
969                 case 0x1c:
970                         return set_fdc_fd1c((uint8)data);
971                         break;
972                 case 0x1d:
973                         return set_fdc_motor((uint8)data);
974                         break;
975                 case 0x1f: // ??
976                         return;
977                         break;
978                 case 0x20: // Kanji ROM
979                         return write_kanjiaddr_hi((uint8)data);
980                         break;
981                 case 0x21: // Kanji ROM
982                         return write_kanjiaddr_lo((uint8)data);
983                         break;
984                 case 0x37: // Multi page
985                         return display->write_data8(DISPLAY_ADDR_MULTIPAGE, (uint8)data);
986                         break;
987                 default:
988                         break;
989         }
990         if((addr < 0x40) && (addr >= 0x38)) {
991                 addr = (addr - 0x38) + DISPLAY_ADDR_DPALETTE;
992                 display->write_data8(addr, (uint8)data);
993                 return;
994         }
995         // Another:
996         return;
997 }
998
999 void VM::connect_bus(void)
1000 {
1001         int i;
1002         
1003         /*
1004          * CLASS CONSTRUCTION
1005          *
1006          * VM 
1007          *  |-> MAINCPU -> MAINMEM -> MAINIO -> MAIN DEVICES
1008          *  |             |        |      
1009          *  | -> SUBCPU  -> SUBMEM  -> SUBIO -> SUB DEVICES
1010          *  | -> DISPLAY
1011          *  | -> KEYBOARD
1012          *
1013          *  MAINMEM can access SUBMEM/IO, when SUBCPU is halted.
1014          *  MAINMEM and SUBMEM can access DISPLAY and KEYBOARD with exclusive.
1015          *  MAINCPU can access MAINMEM.
1016          *  SUBCPU  can access SUBMEM.
1017          *  DISPLAY : R/W from MAINCPU and SUBCPU.
1018          *  KEYBOARD : R/W
1019          *
1020          */                     
1021         event->set_context_cpu(maincpu);
1022         event->set_context_cpu(subcpu);
1023
1024         if((!opn_psg_77av) || (!opn_connected)) {
1025                 event->set_context_sound(psg);
1026         }
1027         if(opn_connected) {
1028                 event->set_context_sound(opn[0]);
1029         }
1030         if(whg_connected) {
1031                 event->set_context_sound(opn[1]);
1032         }
1033         if(thg_connected) {
1034                 event->set_context_sound(opn[2]);
1035         }
1036         // CMT
1037         cmt->set_context_out(mainio, FM7_MAINIO_CMTIN, 0x0001);
1038   
1039         keyboard->set_context_mainio(mainio);
1040         keyboard->set_context_subio(subio);
1041   
1042         mainmem->set_context_submem(submem);
1043         //  mainmem->set_context_cpu(maincpu);
1044  
1045         mainio->set_context_maincpu(maincpu);
1046         mainio->set_context_subio(subio);
1047   
1048         subio->set_context_mainio(mainio);
1049         subio->set_context_subcpu(subcpu);
1050   
1051         // Palette, VSYNC, HSYNC, Multi-page, display mode. 
1052         mainio->set_context_display(display);
1053         subio->set_context_display(display);
1054         display->set_context_submem(submem); // For VRAM?  
1055         display->set_context_subcpu(subcpu); // For VRAM?  
1056
1057   
1058         fdc->set_context_irq(mainio, FM7_MAINIO_FDC_IRQ, 0xffffffff);
1059         fdc->set_context_drq(mainio, FM7_MAINIO_FDC_DRQ, 0xffffffff);
1060
1061         psg->set_context_irq(mainio, FM7_MAINIO_PSG_IRQ, 0xffffffff);
1062         opn[0]->set_context_irq(mainio, FM7_MAINIO_OPN_IRQ, 0xffffffff);
1063         opn[1]->set_context_irq(mainio, FM7_MAINIO_WHG_IRQ, 0xffffffff);
1064         opn[2]->set_context_irq(mainio, FM7_MAINIO_THG_IRQ, 0xffffffff);
1065
1066         opn[0]->set_context_port_a(mainio, SIG_FM7_OPN_JOY_A, 0xff);
1067         opn[0]->set_context_port_b(mainio, SIG_FM7_OPN_JOY_B, 0xff);
1068
1069         maincpu->set_context_mem(mainmem);
1070         subcpu->set_context_mem(submem);
1071 }