OSDN Git Service

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