OSDN Git Service

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