OSDN Git Service

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