OSDN Git Service

[VM] Add vm_template.h . This class, VM_TEMPLATE:: must be mother of VM:: .See fm7...
[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.h"
12 #include "fm7_mainio.h"
13
14 #include "../mc6809.h"
15 #include "../z80.h"
16
17 #include "../datarec.h"
18 #include "../i8251.h"
19 #if defined(HAS_DMA)
20 #include "hd6844.h"
21 #endif
22 # if defined(_FM77AV20) || defined(_FM77AV40) || defined(_FM77AV20EX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
23 #include "../and.h"
24 #endif
25 #include "./fm7_mainmem.h"
26 #include "./fm7_display.h"
27 #include "./fm7_keyboard.h"
28 #include "./kanjirom.h"
29 #include "./joystick.h"
30 #if defined(CAPABLE_JCOMMCARD)
31 #include "./jcommcard.h"
32 #endif
33 #include "../../statesub.h"
34
35 FM7_MAINIO::FM7_MAINIO(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu)
36 {
37         int i;
38         for(i = 0; i < 3; i++) {
39                 opn[i] = NULL;
40         }
41         for(i = 0; i < 3; i++) {
42                 uart[i] = NULL;
43                 uart_enabled[i] = false;
44         }
45 # if defined(_FM77AV20) || defined(_FM77AV40) || defined(_FM77AV20EX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
46         rs232c_enabled = false;
47         rs232c_dtr = NULL;
48 # else
49         rs232c_enabled = true;
50         rs232c_dcd = false;
51 # endif
52 # if !defined(_FM77AV_VARIANTS)
53         psg = NULL;
54 #endif
55
56         drec = NULL;
57         pcm1bit = NULL;
58         joystick = NULL;
59         fdc = NULL;
60 # if defined(HAS_2HD)
61         fdc_2HD = NULL;
62         event_2hd_nmi = -1;
63         nmi_delay = 300;
64 # endif
65         printer = NULL;
66         
67         kanjiclass1 = NULL;
68         kanjiclass2 = NULL;
69
70         display = NULL;
71         keyboard = NULL;
72         maincpu = NULL;
73         mainmem = NULL;
74         subcpu = NULL;
75 #ifdef WITH_Z80
76         z80 = NULL;
77 #endif  
78 #if defined(CAPABLE_JCOMMCARD)
79         jcommcard = NULL;
80 #endif
81         // FD00
82         clock_fast = true;
83         lpt_strobe = false;  // bit6
84         lpt_slctin = false;  // bit7
85         // FD01
86         lpt_outdata = 0x00;
87         // FD02
88         cmt_indat = true; // bit7
89         cmt_invert = false; // Invert signal
90         irqstat_reg0 = 0xff;
91         
92         // FD04
93 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
94         defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) 
95         stat_kanjirom = true;    //  R/W : bit5, '0' = sub, '1' = main. FM-77 Only.
96 #elif defined(_FM77_VARIANTS)
97         stat_fdmode_2hd = false; //  R/W : bit6, '0' = 2HD, '1' = 2DD. FM-77 Only.
98         stat_kanjirom = true;    //  R/W : bit5, '0' = sub, '1' = main. FM-77 Only.
99 #endif  
100         firq_break_key = false; // bit1, ON = '0'.
101         firq_sub_attention = false; // bit0, ON = '0'.
102         intmode_fdc = false; // bit2, '0' = normal, '1' = SFD.
103 #if defined(HAS_2HD)    
104         drqstat_fdc_2hd = false;
105         irqstat_fdc_2hd = false;
106 #endif
107         // FD05
108         extdet_neg = false;
109         req_z80run = false;
110         z80_run = false;
111         // FD06,07
112         intstat_syndet = false;
113         intstat_rxrdy = false;
114         intstat_txrdy = false;
115         irqstat_timer = false;
116         irqstat_printer = false;
117         irqstat_keyboard = false;
118         // FD0B
119         // FD0D
120         // FD0F
121         // FD15/ FD46 / FD51
122         connect_opn = false;
123         connect_whg = false;
124         connect_thg = false;
125                 
126         for(i = 0; i < 3; i++) {
127                 opn_address[i] = 0x00;
128                 opn_data[i] = 0x00;
129                 opn_cmdreg[i] = 0;
130                 opn_prescaler_type[i] = 1;
131         }
132         intstat_whg = false;
133         intstat_thg = false;
134         // FD17
135         intstat_opn = false;
136         intstat_mouse = false;
137         mouse_enable = false;
138         // FD18-FD1F
139         connect_fdc = false;
140         fdc_statreg = 0x00;
141         fdc_cmdreg = 0x00;
142         fdc_trackreg = 0x00;
143         fdc_sectreg = 0x00;
144         fdc_datareg = 0x00;
145         fdc_headreg = 0x00;
146         fdc_drvsel = 0x00;
147         fdc_motor = false;
148         irqstat_fdc = false;
149         irqreg_fdc = 0xff; //0b11111111;
150         irqmask_syndet = true;
151         irqmask_rxrdy = true;
152         irqmask_txrdy = true;
153         irqmask_mfd = true;
154         irqmask_timer = true;
155         irqmask_printer = true;
156         irqmask_keyboard = true;
157         irqstat_reg0 = 0xff;
158         
159   
160         irqreq_syndet = false;
161         irqreq_rxrdy = false;
162         irqreq_txrdy = false;
163         irqreq_printer = false;
164         irqreq_keyboard = false;
165
166         // FD20, FD21, FD22, FD23
167         connect_kanjiroml1 = false;
168 #if defined(_FM77AV_VARIANTS)
169         // FD2C, FD2D, FD2E, FD2F
170         connect_kanjiroml2 = false;
171 #endif          
172 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
173         boot_ram = false;
174 #endif
175
176 #if defined(HAS_DMA)
177         dmac = NULL;
178 #endif  
179 #if defined(_FM77_VARIANTS) || defined(_FM8)
180         bootmode = config.boot_mode & 7;
181 #else
182         bootmode = config.boot_mode & 3;
183 #endif
184         memset(io_w_latch, 0xff, 0x100);
185         initialize_output_signals(&clock_status);
186         initialize_output_signals(&printer_reset_bus);
187         initialize_output_signals(&printer_strobe_bus);
188         initialize_output_signals(&printer_select_bus);
189         initialize_output_signals(&irq_bus);
190         initialize_output_signals(&firq_bus);
191         initialize_output_signals(&nmi_bus);
192         
193         set_device_name(_T("MAIN I/O"));
194 }
195
196 FM7_MAINIO::~FM7_MAINIO()
197 {
198 }
199
200
201 void FM7_MAINIO::initialize()
202 {
203         event_beep = -1;
204         event_beep_oneshot = -1;
205         event_timerirq = -1;
206         event_fdc_motor = -1;
207         lpt_type = config.printer_type;
208         fdc_cmdreg = 0x00;
209 #if defined(HAS_2HD)
210         event_fdc_motor_2HD = -1;
211 #endif
212 #if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
213         boot_ram = false;
214 # if defined(_FM77_VARIANTS)
215         stat_fdmode_2hd = false;
216         stat_kanjirom = true;
217 # endif 
218 #endif
219 #if defined(_FM77AV_VARIANTS)
220         reg_fd12 = 0xbc; // 0b10111100
221 #endif          
222 #if defined(_FM77_VARIANTS) || defined(_FM8)
223         bootmode = config.boot_mode & 7;
224 #else
225         bootmode = config.boot_mode & 3;
226 #endif
227 #if defined(HAS_2HD)
228         event_2hd_nmi = -1;
229         nmi_delay = 300;
230 #endif
231         //reset_printer();
232 }
233
234 void FM7_MAINIO::reset()
235 {
236         if(event_beep >= 0) cancel_event(this, event_beep);
237         event_beep = -1;
238         if(event_beep_oneshot >= 0) cancel_event(this, event_beep_oneshot);
239         event_beep_oneshot = -1;
240         if(event_timerirq >= 0) cancel_event(this, event_timerirq);
241         beep_snd = true;
242         beep_flag = false;
243         register_event(this, EVENT_BEEP_CYCLE, (1000.0 * 1000.0) / (1200.0 * 2.0), true, &event_beep);
244         // Sound
245 #if defined(HAS_2HD)
246         drqstat_fdc_2hd = false;
247         irqstat_fdc_2hd = false;
248         if(event_2hd_nmi >= 0) cancel_event(this, event_2hd_nmi);
249         event_2hd_nmi = -1;
250 #endif
251 #if defined(_FM77AV_VARIANTS)
252         hotreset = false;
253 #endif
254         // Around boot rom
255 #if defined(_FM77_VARIANTS)
256         boot_ram = false;
257 #elif defined(_FM77AV_VARIANTS)
258         boot_ram = true;
259 #endif
260         // FD05
261         sub_cancel = false; // bit6 : '1' Cancel req.
262         sub_halt = false; // bit6 : '1' Cancel req.
263         sub_cancel_bak = sub_cancel; // bit6 : '1' Cancel req.
264         sub_halt_bak = sub_halt; // bit6 : '1' Cancel req.
265         req_z80run = false; // OK?
266         z80_run = false;
267
268         // FD02
269         cmt_indat = true; // bit7
270         cmt_invert = false; // Invert signal
271         lpt_det2 = true;
272         lpt_det1 = true;
273         lpt_type = config.printer_type;
274         reset_printer();
275         
276 # if defined(_FM77AV20) || defined(_FM77AV40) || defined(_FM77AV20EX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
277         rs232c_enabled = false;
278 # else
279         rs232c_enabled = true;
280 # endif
281
282 #if defined(_FM77AV_VARIANTS)
283         sub_monitor_type = 0x00;
284 #endif
285         if(config.cpu_type == 0) {
286                 clock_fast = true;
287         } else {
288                 clock_fast = false;
289         }
290         write_signals(&clock_status, clock_fast ? 0xffffffff : 0);
291    
292         // FD03
293         irqmask_syndet = true;
294         irqmask_rxrdy = true;
295         irqmask_txrdy = true;
296         irqmask_mfd = true;
297         irqmask_timer = true;
298         irqmask_printer = true;
299         irqmask_keyboard = true;
300         irqstat_reg0 = 0xff;
301         
302         intstat_syndet = false;
303         intstat_rxrdy = false;
304         intstat_txrdy = false;
305         irqstat_timer = false;
306         irqstat_printer = false;
307         irqstat_keyboard = false;
308   
309         irqreq_syndet = false;
310         irqreq_rxrdy = false;
311         irqreq_txrdy = false;
312         irqreq_printer = false;
313         irqreq_keyboard = false;
314
315         modem_irqmask_rxrdy = modem_irqmask_txrdy = true;
316         modem_syndet = modem_rxrdy = modem_txrdy = false;
317         midi_uart_irqmask = midi_syndet = midi_rxrdy = midi_txrdy = false;
318         // FD00
319         if(drec != NULL) {
320                 call_write_signal(drec, SIG_DATAREC_MIC, 0x00, 0x01);
321                 call_write_signal(drec, SIG_DATAREC_REMOTE, 0x00, 0x02);
322         }
323         reset_fdc();
324         reset_sound();
325         
326         // FD04
327         firq_break_key = (keyboard->read_signal(SIG_FM7KEY_BREAK_KEY) != 0x00000000); // bit1, ON = '0'.
328         intmode_fdc = false;
329         set_sub_attention(false);       
330 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
331         defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX) 
332         stat_kanjirom = true;    //  R/W : bit5, '0' = sub, '1' = main. FM-77 Only.
333 #elif defined(_FM77_VARIANTS)
334         stat_fdmode_2hd = false; //  R/W : bit6, '0' = 2HD, '1' = 2DD. FM-77 Only.
335         stat_kanjirom = true;    //  R/W : bit5, '0' = sub, '1' = main. FM-77 Only.
336 #endif
337         write_signals(&firq_bus, 0);
338         
339 #if defined(HAS_DMA)
340         intstat_dma = false;
341         dma_addr = 0;
342 #endif
343 #if defined(_FM77AV_VARIANTS)
344         reg_fd12 = 0xbc; // 0b10111100
345 #endif
346 #if defined(WITH_Z80)
347         if(z80 != NULL) call_write_signal(z80, SIG_CPU_BUSREQ, 0xffffffff, 0xffffffff);
348 #endif
349         call_write_signal(maincpu, SIG_CPU_BUSREQ, 0, 0xffffffff);
350         call_write_signal(maincpu, SIG_CPU_HALTREQ, 0, 0xffffffff);
351         do_irq();
352
353 //#if !defined(_FM8)
354         register_event(this, EVENT_TIMERIRQ_ON, 10000.0 / 4.9152, true, &event_timerirq); // TIMER IRQ
355 //#endif
356 #if defined(_FM77_VARIANTS) || defined(_FM8)
357         bootmode = config.boot_mode & 7;
358 #else
359         bootmode = config.boot_mode & 3;
360 #endif
361         memset(io_w_latch, 0xff, 0x100);
362 }
363
364 void FM7_MAINIO::reset_printer()
365 {
366         lpt_slctin = false;
367         lpt_strobe = false;
368         // FD01
369         lpt_outdata = 0x00;
370         write_signals(&printer_strobe_bus, 0);
371         write_signals(&printer_select_bus, 0xffffffff);
372         write_signals(&printer_reset_bus, 0xffffffff);
373         register_event(this, EVENT_PRINTER_RESET_COMPLETED, 5.0 * 1000.0, false, NULL);
374         if(lpt_type == 0) {
375                 printer->write_signal(SIG_PRINTER_STROBE, 0x00, 0xff);
376         }
377         lpt_busy = false;
378         lpt_error_inv = true;
379         lpt_ackng_inv = true;
380         lpt_pe = false;
381
382 }
383
384 void FM7_MAINIO::set_clockmode(uint8_t flags)
385 {
386         bool f = clock_fast;
387         if((flags & FM7_MAINCLOCK_SLOW) != 0) {
388                 clock_fast = false;
389         } else {
390                 clock_fast = true;
391         }
392         if(f != clock_fast) {
393                 write_signal(FM7_MAINIO_CLOCKMODE, clock_fast ? 1 : 0, 1);
394         }
395 }
396
397 uint8_t FM7_MAINIO::get_clockmode(void)
398 {
399         if(!clock_fast) return FM7_MAINCLOCK_SLOW;
400         return FM7_MAINCLOCK_HIGH;
401 }
402
403
404 uint8_t FM7_MAINIO::get_port_fd00(void)
405 {
406         uint8_t ret           = 0x7e; //0b01111110;
407         if(keyboard->read_data8(0x00) != 0) ret |= 0x80; // High bit.
408         if(clock_fast) ret |= 0x01; //0b00000001;
409         return ret;
410 }
411   
412 void FM7_MAINIO::set_port_fd00(uint8_t data)
413 {
414         if(drec != NULL) {
415                 call_write_signal(drec, SIG_DATAREC_MIC, data, 0x01);
416                 call_write_signal(drec, SIG_DATAREC_REMOTE, data, 0x02);
417         }       
418         lpt_slctin = ((data & 0x80) == 0);
419         lpt_strobe = ((data & 0x40) != 0);
420         write_signals(&printer_strobe_bus, lpt_strobe ? 0xffffffff : 0);
421         write_signals(&printer_select_bus, lpt_slctin ? 0xffffffff : 0);
422         if((lpt_type == 0) && (lpt_slctin)) {
423                 printer->write_signal(SIG_PRINTER_STROBE, lpt_strobe ? 0xff : 0x00, 0xff);
424         }
425 }
426    
427 uint8_t FM7_MAINIO::get_port_fd02(void)
428 {
429         uint8_t ret;
430         bool ack_bak = lpt_ackng_inv;
431
432         ret = (cmt_indat) ? 0xff : 0x7f; // CMT
433         if(lpt_type == 0) {
434                 lpt_busy = (printer->read_signal(SIG_PRINTER_BUSY) != 0);
435                 lpt_error_inv = true;
436                 lpt_ackng_inv = (printer->read_signal(SIG_PRINTER_ACK) != 0);
437                 lpt_pe = false;
438         } else if((lpt_type == 1) || (lpt_type == 2)) {
439                 lpt_pe = (joystick->read_data8(lpt_type + 1) != 0); // check joy port;
440                 lpt_busy = true;
441                 lpt_error_inv = true;
442                 lpt_ackng_inv = true;
443         } else {
444                 lpt_busy = true;
445                 lpt_error_inv = true;
446                 lpt_ackng_inv = true;
447                 lpt_pe = true;
448         }
449         ret &= (lpt_busy)      ? 0xff : ~0x01;
450         ret &= (lpt_error_inv) ? 0xff : ~0x02;
451         ret &= (lpt_ackng_inv) ? 0xff : ~0x04;
452         ret &= (lpt_pe)        ? 0xff : ~0x08;
453         ret &= (lpt_det1)      ? 0xff : ~0x10;
454         ret &= (lpt_det2)      ? 0xff : ~0x20;
455         if((lpt_ackng_inv == true) && (ack_bak == false)) set_irq_printer(true);
456         return ret;
457 }
458
459 void FM7_MAINIO::set_port_fd02(uint8_t val)
460 {
461 //#if !defined(_FM8)    
462         irqmask_reg0 = val;
463         bool syndetirq_bak = irqmask_syndet;
464         //bool rxrdyirq_bak = irqmask_rxrdy;
465         //bool txrdyirq_bak = irqmask_txrdy;
466         
467         bool keyirq_bak = irqmask_keyboard;
468         //bool timerirq_bak = irqmask_timer;
469         //bool printerirq_bak = irqmask_printer;
470         //bool mfdirq_bak = irqmask_mfd;
471         
472         //      if((val & 0b00010000) != 0) {
473         if((val & 0x80) != 0) {
474                 irqmask_syndet = false;
475         } else {
476                 irqmask_syndet = true;
477         }
478         if(syndetirq_bak != irqmask_syndet) {
479                 set_irq_txrdy(irqreq_syndet);
480         }
481         if((val & 0x40) != 0) {
482                 irqmask_rxrdy = false;
483         } else {
484                 irqmask_rxrdy = true;
485         }
486 //      if(rxrdyirq_bak != irqmask_rxrdy) {
487 //              set_irq_rxrdy(irqreq_rxrdy);
488 //      }
489         if((val & 0x20) != 0) {
490                 irqmask_txrdy = false;
491         } else {
492                 irqmask_txrdy = true;
493         }
494 //      if(txrdyirq_bak != irqmask_txrdy) {
495         //              set_irq_txrdy(irqreq_txrdy);
496 //      }
497         
498         if((val & 0x10) != 0) {
499                 irqmask_mfd = false;
500         } else {
501                 irqmask_mfd = true;
502         }
503
504         if((val & 0x04) != 0) {
505                 irqmask_timer = false;
506         } else {
507                 irqmask_timer = true;
508         }
509 //      if(timerirq_bak != irqmask_timer) {
510 //              set_irq_timer(false);
511 //      }
512
513         if((val & 0x02) != 0) {
514                 irqmask_printer = false;
515         } else {
516                 irqmask_printer = true;
517         }
518 //      if(printerirq_bak != irqmask_printer) {
519 //              set_irq_printer(irqreq_printer);
520 //      }
521    
522         if((val & 0x01) != 0) {
523                 irqmask_keyboard = false;
524         } else {
525                 irqmask_keyboard = true;
526         }
527         if(keyirq_bak != irqmask_keyboard) {
528                 call_write_signal(display, SIG_FM7_SUB_KEY_MASK, irqmask_keyboard ? 1 : 0, 1); 
529                 set_irq_keyboard(irqreq_keyboard);
530         }
531 //#endif        
532                 return;
533 }
534
535 void FM7_MAINIO::set_irq_syndet(bool flag)
536 {
537         bool backup = intstat_syndet;
538         irqreq_syndet = flag;
539         if(flag && !(irqmask_syndet)) {
540                 //irqstat_reg0 &= ~0x80; //~0x20;
541                 intstat_syndet = true;     
542         } else {
543                 //      irqstat_reg0 |= 0x80;
544                 intstat_syndet = false;    
545         }
546         if(backup != intstat_syndet) do_irq();
547 }
548
549
550 void FM7_MAINIO::set_irq_rxrdy(bool flag)
551 {
552         bool backup = intstat_rxrdy;
553         irqreq_rxrdy = flag;
554         if(flag && !(irqmask_rxrdy)) {
555                 //irqstat_reg0 &= ~0x40; //~0x20;
556                 intstat_rxrdy = true;      
557         } else {
558                 //irqstat_reg0 |= 0x40;
559                 intstat_rxrdy = false;     
560         }
561         if(backup != intstat_rxrdy) do_irq();
562 }
563
564
565
566 void FM7_MAINIO::set_irq_txrdy(bool flag)
567 {
568         bool backup = intstat_txrdy;
569         irqreq_txrdy = flag;
570         if(flag && !(irqmask_txrdy)) {
571                 //irqstat_reg0 &= ~0x20; //~0x20;
572                 intstat_txrdy = true;      
573         } else {
574                 //irqstat_reg0 |= 0x20;
575                 intstat_txrdy = false;     
576         }
577         if(backup != intstat_txrdy) do_irq();
578 }
579
580
581 void FM7_MAINIO::set_irq_timer(bool flag)
582 {
583         if(flag) {
584                 irqstat_reg0 &= 0xfb; //~0x04;
585                 irqstat_timer = true;      
586         } else {
587                 irqstat_reg0 |= 0x04;
588                 irqstat_timer = false;     
589         }
590         do_irq();
591 }
592
593 void FM7_MAINIO::set_irq_printer(bool flag)
594 {
595         irqreq_printer = flag;
596         if(flag && !(irqmask_printer)) {
597                 irqstat_reg0 &= ~0x02;
598                 irqstat_printer = true;    
599         } else {
600                 irqstat_reg0 |= 0x02;
601                 irqstat_printer = false;           
602         }
603         do_irq();
604 }
605
606 void FM7_MAINIO::set_irq_keyboard(bool flag)
607 {
608         //uint8_t backup = irqstat_reg0;
609         //printf("MAIN: KEYBOARD: IRQ=%d MASK=%d\n", flag ,irqmask_keyboard);
610         irqreq_keyboard = flag;
611         if(flag && !irqmask_keyboard) {
612                 irqstat_reg0 &= 0xfe;
613                 irqstat_keyboard = true;
614         } else {
615                 irqstat_reg0 |= 0x01;
616                 irqstat_keyboard = false;          
617         }
618         do_irq();
619 }
620
621
622 void FM7_MAINIO::do_irq(void)
623 {
624         bool intstat;
625         uint32_t nval;
626         
627         intstat = irqstat_timer | irqstat_keyboard | irqstat_printer;
628         intstat = intstat | intstat_opn | intstat_whg | intstat_thg;
629         intstat = intstat | intstat_txrdy | intstat_rxrdy | intstat_syndet;
630         intstat = intstat | intstat_mouse;
631         intstat = intstat | ((modem_irqmask_txrdy & modem_txrdy) | (modem_irqmask_rxrdy & modem_rxrdy) | modem_syndet);
632         intstat = intstat | ((!midi_uart_irqmask) & (midi_syndet | midi_txrdy | midi_rxrdy));
633 # if defined(HAS_DMA)
634         intstat = intstat | intstat_dma;
635 # endif
636 # if defined(HAS_2HD)
637         if(intmode_fdc) {
638                 intstat = intstat | irqstat_fdc_2hd;
639         } else {
640                 intstat = intstat | irqstat_fdc;
641         }
642 # else
643         intstat = intstat | irqstat_fdc;
644 #endif
645         nval = (intstat) ? 0xffffffff : 0;
646         write_signals(&irq_bus, nval);
647 }
648
649 void FM7_MAINIO::do_firq(void)
650 {
651         bool firq_stat;
652         uint32_t nval;
653         firq_stat = firq_break_key | firq_sub_attention;
654 #if defined(HAS_2HD)
655         if(intmode_fdc) {
656                 firq_stat = drqstat_fdc_2hd;  // 20180226 BREAK KEY AND ATTENTION MUST BE MASK IF FIRQ USING FOR FDC's DRQ.Thanks to Haserin.
657                         //}
658         }
659 #endif
660         nval = (firq_stat) ? 0xffffffff : 0;
661         write_signals(&firq_bus, nval);
662 }
663
664 void FM7_MAINIO::do_nmi(bool flag)
665 {
666         write_signals(&nmi_bus, (flag) ? 0xffffffff : 0);
667 }
668
669
670 void FM7_MAINIO::set_break_key(bool pressed)
671 {
672         firq_break_key = pressed;
673         do_firq();
674 }
675
676 void FM7_MAINIO::set_sub_attention(bool flag)
677 {
678         firq_sub_attention = flag;
679         do_firq();
680 }
681   
682
683 uint8_t FM7_MAINIO::get_fd04(void)
684 {
685         uint8_t val = 0x00;
686         bool f;
687         if(display->read_signal(SIG_DISPLAY_BUSY) != 0) val |= 0x80;
688         
689         //f = keyboard->read_signal(SIG_FM7KEY_BREAK_KEY);
690         f = firq_break_key;
691         if(!f) val |= 0x02;
692         if(!firq_sub_attention) {
693                 val |= 0x01;
694         }
695 #if defined(_FM77_VARIANTS)
696         if(!stat_fdmode_2hd)  val |= 0x40;
697         if(stat_kanjirom)     val |= 0x20;
698         //if(intmode_fdc)      val |= 0x04;  // OK?
699         val |= 0x04;
700 # if defined(_FM77L4)
701         val |= (display->read_signal(SIG_DISPLAY_EXTRA_MODE) & 0x18);
702 # else
703         val |= 0x18; // For NON-77L4, these bit must be '1'.Thanks to Ryu Takegami.
704 # endif
705 #elif defined(_FM8)
706         val |= 0x78;
707         // ToDo: MEMORY PARITY ERRO STATUS (if error, bit3 = '1').
708 #elif defined(_FM77AV_VARIANTS)
709         val |= 0x6c;
710         val |= 0x10; // ToDo: Hack for OS-9 for 77AV.Really need?
711 #else
712         val |= 0x7c;
713 #endif  
714 #if defined(HAS_2HD)
715         if(drqstat_fdc_2hd) {
716                 drqstat_fdc_2hd = false;
717                 if(!firq_sub_attention) do_firq();
718         }
719 #endif
720         if(firq_sub_attention) {
721                 set_sub_attention(false);
722                 //printf("Attention \n");
723         } 
724 #if defined(_FM77AV_VARIANTS)
725         if(hotreset) {
726                 if(mainmem->read_signal(FM7_MAINIO_INITROM_ENABLED) == 0) {
727                         set_break_key(false);
728                         hotreset = false;
729                 }
730         }
731 #endif
732         return val;
733 }
734
735 void FM7_MAINIO::set_fd04(uint8_t val)
736 {
737         // NOOP?
738 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
739         call_write_signal(display, SIG_DISPLAY_EXTRA_MODE, val, 0xff);
740         stat_kanjirom = ((val & 0x20) != 0);
741 #elif defined(_FM77_VARIANTS)
742         call_write_signal(display, SIG_DISPLAY_EXTRA_MODE, val, 0xff);
743         stat_kanjirom    = ((val & 0x20) != 0);
744 #endif
745 #if defined(HAS_2HD)
746         stat_fdmode_2hd  = ((val & 0x40) == 0);
747         intmode_fdc      = ((val & 0x04) == 0); // I/O port definition at Oh!FM 1985-5? is inverted status.
748         bool tmpf        = intmode_fdc;
749         if(tmpf != intmode_fdc) {
750                 do_firq();
751         }
752 #endif  
753 }
754
755 // FD05
756 uint8_t FM7_MAINIO::get_fd05(void)
757 {
758         uint8_t val = 0x7e;
759         if(display->read_signal(SIG_DISPLAY_BUSY) != 0) val |= 0x80;
760         if(!extdet_neg) val |= 0x01;
761         return val;
762 }
763
764 void FM7_MAINIO::set_fd05(uint8_t val)
765 {
766         sub_cancel = ((val & 0x40) != 0) ? true : false;
767         sub_halt   = ((val & 0x80) != 0) ? true : false;
768         //if(sub_halt != sub_halt_bak) {
769         call_write_signal(display, SIG_DISPLAY_HALT,  (sub_halt) ? 0xff : 0x00, 0xff);
770         //}
771         sub_halt_bak = sub_halt;
772
773         //if(sub_cancel != sub_cancel_bak) {
774         call_write_signal(display, SIG_FM7_SUB_CANCEL, (sub_cancel) ? 0xff : 0x00, 0xff); // HACK
775         //}
776         sub_cancel_bak = sub_cancel;
777 #ifdef WITH_Z80
778         if((val & 0x01) != 0) {
779                 call_write_signal(maincpu, SIG_CPU_HALTREQ, 1, 1);
780                 req_z80run = true;
781         } else {
782                 req_z80run = false;
783                 if(z80 != NULL) call_write_signal(z80, SIG_CPU_BUSREQ, 1, 1);
784         }
785 #endif
786 }
787
788 void FM7_MAINIO::set_extdet(bool flag)
789 {
790         extdet_neg = flag;
791 }
792
793 void FM7_MAINIO::write_fd0f(void)
794 {
795         call_write_signal(mainmem, FM7_MAINIO_PUSH_FD0F, 0, 0xffffffff);
796 }
797
798 uint8_t FM7_MAINIO::read_fd0f(void)
799 {
800         call_write_signal(mainmem, FM7_MAINIO_PUSH_FD0F, 0xffffffff, 0xffffffff);
801         return 0xff;
802 }
803
804 bool FM7_MAINIO::get_rommode_fd0f(void)
805 {
806         return (mainmem->read_signal(FM7_MAINIO_PUSH_FD0F) == 0) ? false : true;
807 }
808
809
810 // Kanji ROM, FD20 AND FD21 (or SUBSYSTEM)
811 void FM7_MAINIO::write_kanjiaddr_hi(uint8_t addr)
812 {
813 #if defined(CAPABLE_JCOMMCARD) && !(defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS))
814         if(jcommcard != NULL) {
815                 jcommcard->write_io8(0, (uint32_t)addr);
816                 return;
817         }
818 #endif
819         if(!connect_kanjiroml1) {
820                 return;
821         }
822 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
823     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
824         if(!stat_kanjirom) return;
825 #endif  
826         kanjiclass1->write_data8(KANJIROM_ADDR_HI, addr);
827         return;
828 }
829
830 void FM7_MAINIO::write_kanjiaddr_lo(uint8_t addr)
831 {
832 #if defined(CAPABLE_JCOMMCARD) && !(defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS))
833         if(jcommcard != NULL) {
834                 jcommcard->write_io8(1, (uint32_t)addr);
835                 return;
836         }
837 #endif
838         if(!connect_kanjiroml1) {
839                 return;
840         }
841 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
842     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
843         if(!stat_kanjirom) return;
844 #endif  
845         kanjiclass1->write_data8(KANJIROM_ADDR_LO, addr);
846         return;
847 }
848
849 uint8_t FM7_MAINIO::read_kanjidata_left(void)
850 {
851 #if defined(CAPABLE_JCOMMCARD) && !(defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS))
852         if(jcommcard != NULL) {
853                 return (uint8_t)(jcommcard->read_io8(2));
854         }
855 #endif
856         if(!connect_kanjiroml1) {
857                 return 0xff;
858         }
859 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
860     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
861         if(!stat_kanjirom) return 0xff;
862 #endif  
863         //printf("KANJI MAIN CLASS1 ADDR: %05x\n", kaddress.w.l);
864         if(kanjiclass1) {
865                 return kanjiclass1->read_data8(KANJIROM_DATA_HI);
866         } else {
867                 return 0xff;
868         }
869 }
870
871 uint8_t FM7_MAINIO::read_kanjidata_right(void)
872 {
873 #if defined(CAPABLE_JCOMMCARD) && !(defined(_FM77AV_VARIANTS) || defined(_FM77_VARIANTS))
874         if(jcommcard != NULL) {
875                 return (uint8_t)(jcommcard->read_io8(3));
876         }
877 #endif
878         if(!connect_kanjiroml1) {
879                 return 0xff;
880         }
881 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
882     defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
883         if(!stat_kanjirom) return 0xff;
884 #endif  
885         if(kanjiclass1) {
886                 return kanjiclass1->read_data8(KANJIROM_DATA_LO);
887         } else {
888                 return 0xff;
889         }
890 }
891
892 #ifdef CAPABLE_KANJI_CLASS2
893 // Kanji ROM, FD20 AND FD21 (or SUBSYSTEM)
894 void FM7_MAINIO::write_kanjiaddr_hi_l2(uint8_t addr)
895 {
896         if(!connect_kanjiroml2) return;
897         if(!stat_kanjirom) return;
898         kanjiclass2->write_data8(KANJIROM_ADDR_HI, addr);
899         return;
900 }
901
902 void FM7_MAINIO::write_kanjiaddr_lo_l2(uint8_t addr)
903 {
904         if(!connect_kanjiroml2) return;
905         if(!stat_kanjirom) return;
906         kanjiclass2->write_data8(KANJIROM_ADDR_LO, addr);
907         
908         return;
909 }
910
911 uint8_t FM7_MAINIO::read_kanjidata_left_l2(void)
912 {
913         if(!connect_kanjiroml2) return 0xff;
914         if(!stat_kanjirom) return 0xff;
915         
916         if(kanjiclass2) {
917                 return kanjiclass2->read_data8(KANJIROM_DATA_HI);
918         } else {
919                 return 0xff;
920         }
921 }
922
923 uint8_t FM7_MAINIO::read_kanjidata_right_l2(void)
924 {
925         if(!connect_kanjiroml2) return 0xff;
926         if(!stat_kanjirom) return 0xff;
927         
928         if(kanjiclass2) {
929                 return kanjiclass2->read_data8(KANJIROM_DATA_LO);
930         } else {
931                 return 0xff;
932         }
933 }
934 #endif
935
936 uint32_t FM7_MAINIO::read_signal(int id)
937 {
938         uint32_t retval;
939         switch(id) {
940         case FM7_MAINIO_KEYBOARDIRQ_MASK:
941                 retval = (irqmask_keyboard) ? 0xffffffff : 0x00000000;
942                 break;
943         default:
944                 retval = 0xffffffff;
945                 break;
946         }
947         return retval;
948 }
949
950
951 void FM7_MAINIO::write_signal(int id, uint32_t data, uint32_t mask)
952 {
953         bool val_b;
954         val_b = ((data & mask) != 0);
955   
956         switch(id) {
957                 //case SIG_FM7_SUB_HALT:
958                 //      mainmem->write_signal(SIG_FM7_SUB_HALT, data, mask);
959                 //              break;
960         case FM7_MAINIO_CLOCKMODE: // fd00
961                 if(val_b) {
962                         clock_fast = true;
963                 } else {
964                         clock_fast = false;
965                 }
966                 write_signals(&clock_status, clock_fast ? 0xffffffff : 0);
967                 break;
968         case FM7_MAINIO_CMT_RECV: // FD02
969                 cmt_indat = val_b ^ cmt_invert;
970                 break;
971         case FM7_MAINIO_CMT_INVERT: // FD02
972                 cmt_invert = val_b;
973                 break;
974         case FM7_MAINIO_TIMERIRQ: //
975                 set_irq_timer(val_b);
976                 break;
977         case FM7_MAINIO_LPTIRQ: //
978                 set_irq_printer(val_b);
979                 break;
980         case FM7_MAINIO_LPT_BUSY:
981                 lpt_busy = val_b;
982                 break;
983         case FM7_MAINIO_LPT_ERROR:
984                 lpt_error_inv = val_b;
985                 break;
986         case FM7_MAINIO_LPT_ACK:
987                 {
988                         bool f = lpt_ackng_inv;
989                         lpt_ackng_inv = val_b;
990                         if((lpt_ackng_inv == true) && (f == false)) set_irq_printer(true);
991                 }
992                 break;
993         case FM7_MAINIO_LPT_PAPER_EMPTY:
994                 lpt_busy = val_b;
995                 break;
996         case FM7_MAINIO_LPT_DET1:
997                 lpt_det1 = val_b;
998                 break;
999         case FM7_MAINIO_LPT_DET2:
1000                 lpt_det2 = val_b;
1001                 break;
1002         case FM7_MAINIO_KEYBOARDIRQ: //
1003                 set_irq_keyboard(val_b);
1004                 break;
1005                 // FD04
1006         case FM7_MAINIO_PUSH_BREAK:
1007                 set_break_key(val_b);
1008                 break;
1009 #if defined(FM77AV_VARIANTS)    
1010         case FM7_MAINIO_HOT_RESET:
1011                 hotreset = val_b;
1012                 break;
1013 #endif
1014         case FM7_MAINIO_SUB_ATTENTION:
1015                 if(val_b) set_sub_attention(true);
1016                 break;
1017                 // FD05
1018         case FM7_MAINIO_EXTDET:
1019                 extdet_neg = !val_b;
1020                 break;
1021         case FM7_MAINIO_BEEP:
1022                 set_beep_oneshot();
1023                 break;
1024         case FM7_MAINIO_PSG_IRQ:
1025                 break;
1026 #if defined(WITH_Z80)
1027         case FM7_MAINIO_RUN_Z80:
1028                 if((req_z80run)/*  && (val_b) */) {
1029                         if(z80 != NULL) call_write_signal(z80, SIG_CPU_BUSREQ, 0, 1);
1030                         z80_run = true;
1031                         //z80->reset(); // OK?
1032                 }
1033                 break;
1034         case FM7_MAINIO_RUN_6809:
1035                 if(!(req_z80run) /* && (val_b) */ && (z80_run)) {
1036                         z80_run = false;
1037                         // Wait dead cycle?
1038                         call_write_signal(maincpu, SIG_CPU_HALTREQ, 0, 1);
1039                 }
1040                 break;
1041 #endif
1042         case FM7_MAINIO_UART0_RXRDY:
1043                 set_irq_rxrdy(val_b & rs232c_enabled);
1044                 break;
1045         case FM7_MAINIO_UART0_TXRDY:
1046                 set_irq_txrdy(val_b & rs232c_enabled);
1047                 break;
1048         case FM7_MAINIO_UART0_SYNDET:
1049                 set_irq_syndet(val_b & rs232c_enabled);
1050                 break;
1051         case FM7_MAINIO_UART0_DCD:
1052                 rs232c_dcd = val_b;
1053                 break;
1054         case FM7_MAINIO_MODEM_TXRDY:
1055                 modem_txrdy = val_b;
1056                 do_irq();
1057                 break;
1058         case FM7_MAINIO_MODEM_RXRDY:
1059                 modem_rxrdy = val_b;
1060                 do_irq();
1061                 break;
1062         case FM7_MAINIO_MODEM_SYNDET:
1063                 modem_syndet = val_b;
1064                 do_irq();
1065                 break;
1066         case FM7_MAINIO_MIDI_TXRDY:
1067                 midi_txrdy = val_b;
1068                 do_irq();
1069                 break;
1070         case FM7_MAINIO_MIDI_RXRDY:
1071                 midi_rxrdy = val_b;
1072                 do_irq();
1073                 break;
1074         case FM7_MAINIO_MIDI_SYNDET:
1075                 midi_syndet = val_b;
1076                 do_irq();
1077                 break;
1078                         
1079 //#if !defined(_FM8)                    
1080         case FM7_MAINIO_OPN_IRQ:
1081                 if(!connect_opn) break;
1082                 intstat_opn = val_b;
1083                 do_irq();
1084                 break;
1085         case FM7_MAINIO_WHG_IRQ:
1086                 if(!connect_whg) break;
1087                 intstat_whg = val_b;
1088                 do_irq();
1089                 break;
1090         case FM7_MAINIO_THG_IRQ:
1091                 if(!connect_thg) break;
1092                 intstat_thg = val_b;
1093                 do_irq();
1094                 break;
1095 //#endif                        
1096         case FM7_MAINIO_FDC_DRQ:
1097                 set_drq_mfd(val_b);
1098                 break;
1099         case FM7_MAINIO_FDC_IRQ:
1100                 set_irq_mfd(val_b);
1101                 break;
1102 #if defined(HAS_2HD)
1103         case FM7_MAINIO_FDC_DRQ_2HD:
1104                 set_drq_mfd_2HD(val_b);
1105                 break;
1106         case FM7_MAINIO_FDC_IRQ_2HD:
1107                 set_irq_mfd_2HD(val_b);
1108                 break;
1109 #endif
1110 #if defined(HAS_DMA)
1111         case FM7_MAINIO_DMA_INT:
1112                 intstat_dma = val_b;
1113                 do_irq();
1114                 break;
1115 #endif
1116 #if defined(_FM77AV_VARIANTS)
1117         case SIG_DISPLAY_DISPLAY:
1118                 if(val_b) {
1119                         reg_fd12 |= 0x02;
1120                 } else {
1121                         reg_fd12 &= ~0x02;
1122                 }
1123                 break;
1124         case SIG_DISPLAY_VSYNC:
1125                 if(val_b) {
1126                         reg_fd12 |= 0x01;
1127                 } else {
1128                         reg_fd12 &= ~0x01;
1129                 }
1130                 break;
1131         case SIG_DISPLAY_MODE320:
1132                 if(val_b) {
1133                         reg_fd12 |= 0x40;
1134                 } else {
1135                         reg_fd12 &= ~0x40;
1136                 }
1137                 break;
1138 #endif                  
1139         }
1140 }
1141
1142
1143 uint8_t FM7_MAINIO::get_irqstat_fd03(void)
1144 {
1145         uint8_t val;
1146         bool extirq;
1147         uint8_t backup = irqstat_reg0;
1148    
1149         extirq = intstat_opn | intstat_whg | intstat_thg;
1150         extirq = extirq | intstat_syndet | intstat_rxrdy | intstat_txrdy;
1151 # if defined(HAS_2HD)
1152         if(intmode_fdc) {
1153                 extirq = extirq | irqstat_fdc_2hd;
1154         } else {
1155                 extirq = extirq | irqstat_fdc;
1156         }
1157 # else
1158         extirq = extirq | irqstat_fdc;
1159 # endif
1160 # if defined(HAS_DMA)
1161         extirq = extirq | intstat_dma;
1162 # endif   
1163         if(extirq) {
1164                 irqstat_reg0 &= ~0x08;
1165         } else {
1166                 irqstat_reg0 |= 0x08;
1167         }
1168         val = irqstat_reg0 | 0xf0;
1169         // Not call do_irq() twice. 20151221 
1170         irqstat_timer = false;
1171         irqstat_printer = false;
1172         irqstat_reg0 |= 0x06;
1173         //if(backup != irqstat_reg0) do_irq();
1174         //this->out_debug_log(_T("IO: Check IRQ Status."));
1175         do_irq();
1176         return val;
1177
1178 }
1179
1180 uint8_t FM7_MAINIO::get_extirq_fd17(void)
1181 {
1182         uint8_t val = 0xff;
1183         if(intstat_opn && connect_opn)   val &= ~0x08;
1184         if(intstat_mouse) val &= ~0x04;
1185         return val;
1186 }
1187
1188 void FM7_MAINIO::set_ext_fd17(uint8_t data)
1189 {
1190         if((data & 0x04) != 0) {
1191                 mouse_enable = true;
1192         } else {
1193                 mouse_enable = false;
1194         }
1195 }
1196
1197 #if defined(_FM77AV_VARIANTS)
1198 // FD12
1199 uint8_t FM7_MAINIO::subsystem_read_status(void)
1200 {
1201         return reg_fd12;
1202 }
1203 #endif
1204
1205
1206 uint32_t FM7_MAINIO::read_io8(uint32_t addr)
1207 { // This is only for debug.
1208         addr = addr & 0xfff;
1209         if(addr < 0x100) {
1210                 return io_w_latch[addr];
1211         } else if(addr < 0x500) {
1212                 uint32_t ofset = addr & 0xff;
1213                 uint opnbank = (addr - 0x100) >> 8;
1214                 return opn_regs[opnbank][ofset];
1215         } else if(addr < 0x600) {
1216                 return mainmem->read_data8(addr - 0x500 + FM7_MAINIO_MMR_BANK);
1217         }
1218         return 0xff;
1219 }
1220
1221 uint32_t FM7_MAINIO::read_dma_io8(uint32_t addr)
1222 {
1223         return this->read_data8(addr & 0xff);
1224 }
1225
1226 uint32_t FM7_MAINIO::read_dma_data8(uint32_t addr)
1227 {
1228         return this->read_data8(addr & 0xff);
1229 }
1230
1231 uint32_t FM7_MAINIO::read_data8(uint32_t addr)
1232 {
1233         uint32_t retval;
1234         uint32_t mmr_segment;
1235         if(addr < FM7_MAINIO_IS_BASICROM) {   
1236                 addr = addr & 0xff;
1237                 retval = 0xff;
1238 #if defined(HAS_MMR)
1239                 if((addr < 0x90) && (addr >= 0x80)) {
1240                         mmr_segment = mainmem->read_data8(FM7_MAINIO_MMR_SEGMENT);
1241 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX) || \
1242         defined(_FM77AV20) || defined(_FM77AV20SX) || defined(_FM77AV20EX)
1243                         mmr_segment &= 0x07;
1244 # else             
1245                         mmr_segment &= 0x03;
1246 # endif
1247                         return mainmem->read_data8(addr - 0x80 + FM7_MAINIO_MMR_BANK + mmr_segment * 16);
1248                 }
1249 #endif
1250                 //      if((addr >= 0x0006) && !(addr == 0x1f) && !(addr == 0x0b)) printf("MAINIO: READ: %08x \n", addr);
1251                 switch(addr) {
1252                 case 0x00: // FD00
1253                         retval = (uint32_t) get_port_fd00();
1254                         break;
1255                 case 0x01: // FD01
1256 //#if !defined(_FM8)                    
1257                         retval = keyboard->read_data8(0x01) & 0xff;
1258 //#endif                        
1259                                 break;
1260                 case 0x02: // FD02
1261                         retval = (uint32_t) get_port_fd02();
1262                         break;
1263                 case 0x03: // FD03
1264 //#if !defined(_FM8)
1265                         retval = (uint32_t) get_irqstat_fd03();
1266 //#endif                        
1267                                 break;
1268                 case 0x04: // FD04
1269                         retval = (uint32_t) get_fd04();
1270                         break;
1271                 case 0x05: // FD05
1272                         retval = (uint32_t) get_fd05();
1273                         break;
1274                 case 0x06: // RS-232C
1275                 case 0x07:
1276                         if(uart_enabled[0] && rs232c_enabled) {
1277                                 if(uart[0] != NULL) retval = uart[0]->read_io8(addr & 1);
1278                         }
1279                         break;
1280                 case 0x08: // Light pen
1281                 case 0x09:
1282                 case 0x0a:
1283                         break;
1284 #if defined(_FM77AV_VARIANTS)
1285                 case 0x0b:
1286                         retval = ((config.boot_mode & 3) == 0) ? 0xfe : 0xff;
1287 #if defined(_FM77AV20) || defined(_FM77AV40) || defined(_FM77AV20EX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1288                         retval &= (uint32_t)(~0x04);
1289                         if(!rs232c_dcd) retval |= 0x04;
1290 #endif
1291                         break;
1292 #endif                  
1293                 case 0x0e: // PSG DATA
1294                         retval = (uint32_t) get_psg();
1295                         //printf("PSG DATA READ val=%02x\n", retval);
1296                         break;
1297                 case 0x0f: // FD0F
1298                         read_fd0f();
1299                         retval = 0xff;
1300                         break;
1301 #if defined(_FM77AV_VARIANTS)
1302                 case 0x12:
1303                         retval = subsystem_read_status();  
1304                         break;
1305 #endif
1306                         //printf("OPN CMD READ \n");
1307                         break;
1308                 case 0x16: // OPN DATA
1309                         retval = (uint32_t) get_opn(0);
1310                         break;
1311                 case 0x17:
1312                         retval = (uint32_t) get_extirq_fd17();
1313                         break;
1314
1315 #if defined(HAS_2HD)
1316                 case 0x18: // FDC: STATUS
1317                         if(stat_fdmode_2hd) {
1318                                 retval = (uint32_t) get_fdc_stat_2HD();
1319                         } else {
1320                                 retval = (uint32_t) get_fdc_stat();
1321                         }
1322                     break;
1323                         //printf("FDC: READ STATUS %02x PC=%04x\n", retval, maincpu->get_pc()); 
1324                         break;
1325                 case 0x19: // FDC: Track
1326                         if(stat_fdmode_2hd) {
1327                                 retval = (uint32_t) get_fdc_track_2HD();
1328                         } else {
1329                                 retval = (uint32_t) get_fdc_track();
1330                         }
1331                         //printf("FDC: READ TRACK REG %02x\n", retval); 
1332                         break;
1333                 case 0x1a: // FDC: Sector
1334                         if(stat_fdmode_2hd) {
1335                                 retval = (uint32_t) get_fdc_sector_2HD();
1336                         } else {
1337                                 retval = (uint32_t) get_fdc_sector();
1338                         }
1339                         //printf("FDC: READ SECTOR REG %02x\n", retval); 
1340                         break;
1341                 case 0x1b: // FDC: Data
1342                         if(stat_fdmode_2hd) {
1343                                 retval = (uint32_t) get_fdc_data_2HD();
1344                         } else {
1345                                 retval = (uint32_t) get_fdc_data();
1346                         }
1347                         break;
1348                 case 0x1c:
1349                         if(stat_fdmode_2hd) {
1350                                 retval = (uint32_t) get_fdc_fd1c_2HD();
1351                         } else {
1352                                 retval = (uint32_t) get_fdc_fd1c();
1353                         }
1354                         //printf("FDC: READ HEAD REG %02x\n", retval); 
1355                         break;
1356                 case 0x1d:
1357                         if(stat_fdmode_2hd) {
1358                                 retval = (uint32_t) get_fdc_motor_2HD();
1359                         } else {
1360                                 retval = (uint32_t) get_fdc_motor();
1361                         }
1362                         //printf("FDC: READ MOTOR REG %02x\n", retval); 
1363                         break;
1364                 case 0x1e:
1365                         if(stat_fdmode_2hd) {
1366                                 retval = (uint32_t) get_fdc_fd1e_2HD();
1367                         } else {
1368                                 retval = (uint32_t) get_fdc_fd1e();
1369                         }
1370                         //printf("FDC: READ MOTOR REG %02x\n", retval); 
1371                         break;
1372                 case 0x1f:
1373                         if(stat_fdmode_2hd) {
1374                                 retval = (uint32_t) fdc_getdrqirq_2HD();
1375                         } else {
1376                                 retval = (uint32_t) fdc_getdrqirq();
1377                         }
1378                         break;
1379 #else
1380                 case 0x18: // FDC: STATUS
1381                         retval = (uint32_t) get_fdc_stat();
1382                     break;
1383                         //printf("FDC: READ STATUS %02x PC=%04x\n", retval, maincpu->get_pc()); 
1384                         break;
1385                 case 0x19: // FDC: Track
1386                         retval = (uint32_t) get_fdc_track();
1387                         //printf("FDC: READ TRACK REG %02x\n", retval); 
1388                         break;
1389                 case 0x1a: // FDC: Sector
1390                         retval = (uint32_t) get_fdc_sector();
1391                         //printf("FDC: READ SECTOR REG %02x\n", retval); 
1392                         break;
1393                 case 0x1b: // FDC: Data
1394                         retval = (uint32_t) get_fdc_data();
1395                         break;
1396                 case 0x1c:
1397                         retval = (uint32_t) get_fdc_fd1c();
1398                         //printf("FDC: READ HEAD REG %02x\n", retval); 
1399                         break;
1400                 case 0x1d:
1401                         retval = (uint32_t) get_fdc_motor();
1402                         //printf("FDC: READ MOTOR REG %02x\n", retval); 
1403                         break;
1404                 case 0x1e:
1405                         retval = (uint32_t) get_fdc_fd1e();
1406                         //printf("FDC: READ MOTOR REG %02x\n", retval); 
1407                         break;
1408                 case 0x1f:
1409                         retval = (uint32_t) fdc_getdrqirq();
1410                         break;
1411 #endif
1412                 case 0x22: // Kanji ROM
1413                         retval = (uint32_t) read_kanjidata_left();
1414                         break;
1415                 case 0x23: // Kanji ROM
1416                         retval = (uint32_t) read_kanjidata_right();
1417                         break;
1418 #if defined(CAPABLE_JCOMMCARD)
1419                 case 0x28:
1420                 case 0x29:
1421 # if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
1422                 case 0x2a:
1423                 case 0x2b:
1424 # endif
1425                         if(jcommcard != NULL) {
1426                                 retval = (uint32_t)(jcommcard->read_io8(addr));
1427                         } else {
1428                                 retval = 0xff;
1429                         }
1430                         break;
1431 #endif                  
1432 #if defined(CAPABLE_KANJI_CLASS2)
1433                 case 0x2e: // Kanji ROM Level2
1434                         retval = (uint32_t) read_kanjidata_left_l2();
1435                         break;
1436                 case 0x2f: // Kanji ROM Level2
1437                         retval = (uint32_t) read_kanjidata_right_l2();
1438                         break;
1439 #endif
1440 //#if !defined(_FM8)                    
1441                 case 0x37: // Multi page
1442                         //retval = (uint32_t)display->read_data8(DISPLAY_ADDR_MULTIPAGE);
1443                         break;
1444                 case 0x40: // MODEM
1445                 case 0x41:
1446                         if(uart_enabled[1]) {
1447                                 if(uart[1] != NULL) retval = uart[1]->read_io8(addr & 1);
1448                         }
1449                         break;
1450                 case 0x42:
1451                         break;
1452                 case 0x45: // WHG CMD
1453                         break;
1454                 case 0x46: // WHG DATA
1455                         retval = (uint32_t) get_opn(1);
1456                         break;
1457                 case 0x47:
1458                         retval = (uint32_t) get_extirq_whg();
1459                         break;
1460                 case 0x51: // THG CMD
1461                         break;
1462                 case 0x52: // THG DATA
1463                         retval = (uint32_t) get_opn(2);
1464                         break;
1465                 case 0x53:
1466                         retval = (uint32_t) get_extirq_thg();
1467                         break;
1468 //#endif                        
1469 #if defined(HAS_MMR)
1470                 case 0x93:
1471                         retval = 0x3e;
1472                         //retval = 0x00;
1473                         if(mainmem->read_signal(FM7_MAINIO_BOOTRAM_RW) != 0)     retval |= 0x01;
1474                         if(mainmem->read_signal(FM7_MAINIO_WINDOW_ENABLED) != 0) retval |= 0x40;
1475                         if(mainmem->read_signal(FM7_MAINIO_MMR_ENABLED) != 0)    retval |= 0x80;
1476                         break;
1477 #endif
1478 #if defined(_FM77AV40SX) || defined(_FM77AV40EX)
1479                 case 0x95:
1480                         retval = 0x77;
1481                         if(mainmem->read_signal(FM7_MAINIO_FASTMMR_ENABLED) != 0) retval |= 0x08;
1482                         if(mainmem->read_signal(FM7_MAINIO_EXTROM)  != 0) retval |= 0x80;
1483                         break;
1484 #endif                  
1485 #if defined(HAS_DMA)
1486                 case 0x98:
1487                         retval = dma_addr;
1488                         break;
1489                 case 0x99:
1490                         retval = dmac->read_data8(dma_addr);
1491                         break;
1492 #endif                  
1493                 case 0xea: // MIDI
1494                 case 0xeb:
1495                         if(uart_enabled[2]) {
1496                                 if(uart[2] != NULL) retval = uart[2]->read_io8(addr & 1);
1497                         }
1498                         break;
1499                 default:
1500                         break;
1501                 }
1502 //#if !defined(_FM8)                    
1503                         if((addr < 0x40) && (addr >= 0x38)) {
1504                                 addr = (addr - 0x38) + FM7_SUBMEM_OFFSET_DPALETTE;
1505                                 return (uint32_t) display->read_data8(addr);
1506                         }
1507 //#endif                
1508                                 // Another:
1509                         return retval;
1510         } else if(addr == FM7_MAINIO_CLOCKMODE) {
1511                 return (uint32_t)get_clockmode();
1512         }
1513 #if defined(_FM77AV_VARIANTS)
1514         else if(addr == FM7_MAINIO_SUBMONITOR_ROM) {
1515                 retval = sub_monitor_type & 0x03;
1516                 return retval;
1517         }  else if(addr == FM7_MAINIO_SUBMONITOR_RAM) {
1518 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX) || \
1519     defined(_FM77AV20) || defined(_FM77AV20SX) || defined(_FM77AV20EX)
1520                 retval = ((sub_monitor_type & 0x04) != 0) ? 0xffffffff : 0x00000000;
1521 #else
1522                 retval = 0;
1523 #endif
1524                 return retval;
1525         }
1526 #endif
1527         //if((addr >= 0x0006) && (addr != 0x1f)) printf("MAINIO: READ: %08x DATA=%08x\n", addr);
1528         return 0xff;
1529 }
1530
1531 void FM7_MAINIO::write_dma_io8(uint32_t addr, uint32_t data)
1532 {
1533         this->write_data8(addr & 0xff, data);
1534 }
1535
1536 void FM7_MAINIO::write_dma_data8(uint32_t addr, uint32_t data)
1537 {
1538         this->write_data8(addr & 0xff, data);
1539 }
1540
1541
1542 void FM7_MAINIO::write_data8(uint32_t addr, uint32_t data)
1543 {
1544         bool flag;
1545         uint32_t mmr_segment;
1546         if(addr < FM7_MAINIO_IS_BASICROM) {
1547                 addr = addr & 0xff;
1548                 io_w_latch[addr] = data;
1549 #if defined(HAS_MMR)
1550                 if((addr < 0x90) && (addr >= 0x80)) {
1551                         mmr_segment = mainmem->read_data8(FM7_MAINIO_MMR_SEGMENT);
1552 # if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX) || \
1553         defined(_FM77AV20) || defined(_FM77AV20SX) || defined(_FM77AV20EX)
1554                         mmr_segment &= 0x07;
1555 # else             
1556                         mmr_segment &= 0x03;
1557 # endif
1558                         mainmem->write_data8(FM7_MAINIO_MMR_BANK + mmr_segment * 16 + addr - 0x80, data);
1559                         return;
1560                 }
1561 #endif
1562                 switch(addr) {
1563                 case 0x00: // FD00
1564                         set_port_fd00((uint8_t)data);
1565                         return;
1566                         break;
1567                 case 0x01: // FD01
1568                         lpt_outdata = (uint8_t)data;
1569                         switch(lpt_type) {
1570                         case 0: // Write to file
1571                                 printer->write_signal(SIG_PRINTER_DATA, data, 0xff);
1572                                 break;
1573                         case 1:
1574                         case 2:
1575                                 joystick->write_data8(0x01, data);
1576                                 break;
1577                         }
1578                         break;
1579                 case 0x02: // FD02
1580                         set_port_fd02((uint8_t)data);
1581                         break;
1582                 case 0x03: // FD03
1583                         set_beep(data);
1584                         break;
1585                 case 0x04: // FD04
1586                         set_fd04(data);
1587                         break;
1588                 case 0x05: // FD05
1589                         set_fd05((uint8_t)data);
1590                         break;
1591                 case 0x06: // RS-232C
1592                 case 0x07:
1593                         if(uart_enabled[0] && rs232c_enabled) {
1594                                 if(uart[0] != NULL) uart[0]->write_io8(addr & 1, data);
1595                         }
1596                         break;
1597                 case 0x08: // Light pen
1598                 case 0x09:
1599                 case 0x0a:
1600                         break;
1601                 case 0x0c:
1602 #if defined(_FM77AV20) || defined(_FM77AV40) || defined(_FM77AV20EX) || defined(_FM77AV40EX) || defined(_FM77AV40SX)
1603                         if(rs232c_dtr != NULL) {
1604                                 if((data & 0x04) != 0) {
1605                                         rs232c_dtr->write_signal(SIG_AND_BIT_1, 0, 1);
1606                                 } else {
1607                                         rs232c_dtr->write_signal(SIG_AND_BIT_1, 1, 1);
1608                                 }
1609                         }
1610                         rs232c_enabled = ((data & 0x01) != 0) ? true : false;
1611 #endif
1612                         break;
1613                 case 0x0d:
1614                         //printf("PSG CMD WRITE val=%02x\n", data);
1615                         set_psg_cmd(data);
1616                         break;
1617                 case 0x0e:
1618                         //printf("PSG DATA WRITE val=%02x\n", data);
1619                         set_psg(data);
1620                         break;
1621                 case 0x0f: // FD0F
1622                         write_fd0f();
1623                         break;
1624 #if defined(_FM77AV_VARIANTS)
1625                 case 0x10:
1626                         flag = ((data & 0x02) == 0) ? true : false;
1627                         call_write_signal(mainmem, FM7_MAINIO_INITROM_ENABLED, (flag) ? 0xffffffff : 0 , 0xffffffff);
1628                         break;
1629                 case 0x12:
1630                         call_write_signal(display, SIG_DISPLAY_MODE320, data,  0x40);
1631                         reg_fd12 &= ~0x40;
1632                         reg_fd12 |= (data & 0x40);
1633                         break;
1634                 case 0x13:
1635                         sub_monitor_type = data & 0x07;
1636                         call_write_signal(display, SIG_FM7_SUB_BANK, sub_monitor_type, 0x07);
1637                         break;
1638 #endif
1639                 case 0x15: // OPN CMD
1640                         //printf("OPN CMD WRITE val=%02x\n", data);
1641                         set_opn_cmd(0, data);
1642                         break;
1643                 case 0x16: // OPN DATA
1644                         //printf("OPN DATA WRITE val=%02x\n", data);
1645                         set_opn(0, data);
1646                         break;
1647                 case 0x17:
1648                         set_ext_fd17((uint8_t)data);
1649                         break;
1650 #if defined(HAS_2HD)
1651                 case 0x18: // FDC: COMMAND
1652                         if(stat_fdmode_2hd) {
1653                                 set_fdc_cmd_2HD((uint8_t)data);
1654                         } else {
1655                                 set_fdc_cmd((uint8_t)data);
1656                         }
1657                         //printf("FDC: WRITE CMD %02x\n", data); 
1658                         break;
1659                 case 0x19: // FDC: Track
1660                         if(stat_fdmode_2hd) {
1661                                 set_fdc_track_2HD((uint8_t)data);
1662                         } else {
1663                                 set_fdc_track((uint8_t)data);
1664                         }
1665                         //printf("FDC: WRITE TRACK REG %02x\n", data); 
1666                         break;
1667                 case 0x1a: // FDC: Sector
1668                         if(stat_fdmode_2hd) {
1669                                 set_fdc_sector_2HD((uint8_t)data);
1670                         } else {
1671                                 set_fdc_sector((uint8_t)data);
1672                         }
1673                         //printf("FDC: WRITE SECTOR REG %02x\n", data); 
1674                         break;
1675                 case 0x1b: // FDC: Data
1676                         if(stat_fdmode_2hd) {
1677                                 set_fdc_data_2HD((uint8_t)data);
1678                         } else {
1679                                 set_fdc_data((uint8_t)data);
1680                         }
1681                         break;
1682                 case 0x1c:
1683                         if(stat_fdmode_2hd) {
1684                                 set_fdc_fd1c_2HD((uint8_t)data);
1685                         } else {
1686                                 set_fdc_fd1c((uint8_t)data);
1687                         }
1688                         //printf("FDC: WRITE HEAD REG %02x\n", data); 
1689                         break;
1690                 case 0x1d:
1691                         if(stat_fdmode_2hd) {
1692                                 set_fdc_fd1d_2HD((uint8_t)data);
1693                         } else {
1694                                 set_fdc_fd1d((uint8_t)data);
1695                         }
1696                         //printf("FDC: WRITE MOTOR REG %02x\n", data); 
1697                         break;
1698                 case 0x1e:
1699                         if(stat_fdmode_2hd) {
1700                                 set_fdc_fd1e_2HD((uint8_t)data);
1701                         } else {
1702                                 set_fdc_fd1e((uint8_t)data);
1703                         }
1704                         break;
1705                 case 0x1f: // ??
1706                         return;
1707                         break;
1708 #else
1709                 case 0x18: // FDC: COMMAND
1710                         set_fdc_cmd((uint8_t)data);
1711                         //printf("FDC: WRITE CMD %02x\n", data); 
1712                         break;
1713                 case 0x19: // FDC: Track
1714                         set_fdc_track((uint8_t)data);
1715                         //printf("FDC: WRITE TRACK REG %02x\n", data); 
1716                         break;
1717                 case 0x1a: // FDC: Sector
1718                         set_fdc_sector((uint8_t)data);
1719                         //printf("FDC: WRITE SECTOR REG %02x\n", data); 
1720                         break;
1721                 case 0x1b: // FDC: Data
1722                         set_fdc_data((uint8_t)data);
1723                         break;
1724                 case 0x1c:
1725                         set_fdc_fd1c((uint8_t)data);
1726                         //printf("FDC: WRITE HEAD REG %02x\n", data); 
1727                         break;
1728                 case 0x1d:
1729                         set_fdc_fd1d((uint8_t)data);
1730                         //printf("FDC: WRITE MOTOR REG %02x\n", data); 
1731                         break;
1732                 case 0x1e:
1733                         set_fdc_fd1e((uint8_t)data);
1734                         break;
1735                 case 0x1f: // ??
1736                         return;
1737                         break;
1738 #endif
1739                 case 0x20: // Kanji ROM
1740                         write_kanjiaddr_hi((uint8_t)data);
1741                         break;
1742
1743                 case 0x21: // Kanji ROM
1744                         write_kanjiaddr_lo((uint8_t)data);
1745                         break;
1746 #if defined(CAPABLE_JCOMMCARD)
1747 # if defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
1748                 case 0x28:
1749                 case 0x29:
1750 # endif
1751                 case 0x2a:
1752                 case 0x2b:
1753                         if(jcommcard != NULL) jcommcard->write_io8(addr, data);
1754                         break;
1755 #endif                  
1756                 case 0x2c: // Kanji ROM(DUP)
1757 #if defined(CAPABLE_KANJI_CLASS2)
1758                         write_kanjiaddr_hi_l2((uint8_t)data);
1759 #else                   
1760                         //write_kanjiaddr_hi((uint8_t)data);
1761 #endif
1762                         break;
1763                 case 0x2d: // Kanji ROM(DUP)
1764 #if defined(CAPABLE_KANJI_CLASS2)
1765                         write_kanjiaddr_lo_l2((uint8_t)data);
1766 #else
1767                         //write_kanjiaddr_lo((uint8_t)data);
1768 #endif
1769                         break;
1770 #if defined(CAPABLE_DICTROM)
1771                 case 0x2e: // 
1772                         call_write_signal(mainmem, FM7_MAINIO_EXTBANK, data, 0xff);
1773                         break;
1774 #endif                  
1775 #if defined(_FM77AV_VARIANTS)
1776                 case 0x30:
1777                         display->write_data8(FM7_SUBMEM_OFFSET_APALETTE_HI, data);
1778                         break;
1779                 case 0x31:
1780                         display->write_data8(FM7_SUBMEM_OFFSET_APALETTE_LO, data);
1781                         break;
1782                 case 0x32:
1783                         display->write_data8(FM7_SUBMEM_OFFSET_APALETTE_B, data);
1784                         break;
1785                 case 0x33:
1786                         display->write_data8(FM7_SUBMEM_OFFSET_APALETTE_R, data);
1787                         break;
1788                 case 0x34:
1789                         display->write_data8(FM7_SUBMEM_OFFSET_APALETTE_G, data);
1790                         break;
1791 #endif
1792 //#if !defined(_FM8)                    
1793                 case 0x37: // Multi page
1794                         call_write_signal(display, SIG_DISPLAY_MULTIPAGE, data, 0x00ff);
1795                         break;
1796                 case 0x40: // MODEM
1797                 case 0x41:
1798                         if(uart_enabled[1]) {
1799                                 if(uart[1] != NULL) uart[1]->write_io8(addr & 1, data);
1800                         }
1801                         break;
1802                 case 0x42:
1803                         modem_irqmask_txrdy = ((data & 0x20) != 0);
1804                         modem_irqmask_rxrdy = ((data & 0x40) != 0);
1805                         do_irq();
1806                         break;
1807                         
1808                 case 0x45: // WHG CMD
1809                         set_opn_cmd(1, data);
1810                         break;
1811                 case 0x46: // WHG DATA
1812                         set_opn(1, data);
1813                         break;
1814                 case 0x47:
1815                         break;
1816                 case 0x51: // THG CMD
1817                         set_opn_cmd(2, data);
1818                         break;
1819                 case 0x52: // THG DATA
1820                         set_opn(2, data);
1821                         break;
1822                 case 0x53:
1823                         break;
1824 //#endif                        
1825 #if defined(HAS_MMR)
1826                 case 0x90:
1827 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX) || \
1828     defined(_FM77AV20) || defined(_FM77AV20SX) || defined(_FM77AV20EX)
1829                         mmr_segment = data & 7;
1830 #else
1831                         //                      printf("MMR SEGMENT: %02x\n", data & 3);
1832                         mmr_segment = data & 3;
1833 #endif                  
1834                         mainmem->write_data8(FM7_MAINIO_MMR_SEGMENT, (uint32_t)mmr_segment);
1835                         break;
1836                 case 0x92:
1837                         mainmem->write_data8(FM7_MAINIO_WINDOW_OFFSET, (uint32_t)(data & 0x00ff));
1838                         break;
1839                 case 0x93:
1840                         call_write_signal(mainmem, FM7_MAINIO_BOOTRAM_RW, data, 0x01);
1841                         call_write_signal(mainmem, FM7_MAINIO_WINDOW_ENABLED, data , 0x40);
1842                         //this->write_signal(FM7_MAINIO_CLOCKMODE, clock_fast ? 1 : 0, 1);
1843                         //mainmem->write_signal(FM7_MAINIO_CLOCKMODE, clock_fast ? 1 : 0, 1);
1844                         call_write_signal(mainmem, FM7_MAINIO_MMR_ENABLED, data, 0x80);
1845                         //}
1846                         break;
1847 #endif
1848 #if defined(_FM77AV40) || defined(_FM77AV40SX) || defined(_FM77AV40EX) || \
1849     defined(_FM77AV20) || defined(_FM77AV20SX) || defined(_FM77AV20EX)
1850                 case 0x94:
1851                         call_write_signal(mainmem, FM7_MAINIO_MMR_EXTENDED, data, 0x80);
1852                         call_write_signal(mainmem, FM7_MAINIO_MEM_REFRESH_FAST, data, 0x04);
1853                         call_write_signal(mainmem, FM7_MAINIO_WINDOW_FAST , data, 0x01);
1854
1855                         break;
1856 # if defined(_FM77AV40SX) || defined(_FM77AV40EX)
1857                 case 0x95:
1858                         call_write_signal(mainmem, FM7_MAINIO_FASTMMR_ENABLED, data, 0x08);
1859                         call_write_signal(mainmem, FM7_MAINIO_EXTROM, data , 0x80);
1860                         break;
1861 # endif
1862 #endif                  
1863 #if defined(HAS_DMA)
1864                 case 0x98:
1865                         dma_addr = data & 0x1f;
1866                         break;
1867                 case 0x99:
1868                         dmac->write_data8(dma_addr, data);
1869                         //this->out_debug_log(_T("IO: Wrote DMA %02x to reg %02x\n"), data, dma_addr);
1870                         break;
1871 #endif
1872                         // MIDI
1873                 case 0xea: 
1874                 case 0xeb:
1875                         if(uart_enabled[2]) {
1876                                 if(uart[2] != NULL) uart[2]->write_io8(addr & 1, data);
1877                         }
1878                         break;
1879                 default:
1880                         //printf("MAIN: Write I/O Addr=%08x DATA=%02x\n", addr, data); 
1881                         break;
1882                 }
1883                 if((addr < 0x40) && (addr >= 0x38)) {
1884                         addr = (addr - 0x38) | FM7_SUBMEM_OFFSET_DPALETTE;
1885                         display->write_data8(addr, (uint8_t)data);
1886                         return;
1887                 }// Another:
1888                 return;
1889         } else if(addr == FM7_MAINIO_CLOCKMODE) {
1890                 set_clockmode((uint8_t)data);
1891                 return;
1892         }
1893         //if((addr >= 0x0006) && !(addr == 0x1f)) printf("MAINIO: WRITE: %08x DATA=%08x\n", addr, data);
1894 }
1895
1896 void FM7_MAINIO::event_callback(int event_id, int err)
1897 {
1898 //      printf("MAIN EVENT id=%d\n", event_id);
1899         switch(event_id) {
1900         case EVENT_BEEP_OFF:
1901                 event_beep_off();
1902                 break;
1903         case EVENT_BEEP_CYCLE:
1904                 event_beep_cycle();
1905                 break;
1906         case EVENT_UP_BREAK:
1907                 call_write_signal(keyboard, SIG_FM7KEY_OVERRIDE_PRESS_BREAK, 0, 0xffffffff);
1908                 set_break_key(false);
1909                 break;
1910 //#if !defined(_FM8)
1911         case EVENT_TIMERIRQ_ON:
1912                 //if(!irqmask_timer) set_irq_timer(true);
1913                 set_irq_timer(!irqmask_timer);
1914                 break;
1915 //#endif                        
1916         case EVENT_FD_MOTOR_ON:
1917                 set_fdc_motor(true);
1918                 event_fdc_motor = -1;
1919                 break;
1920         case EVENT_FD_MOTOR_OFF:
1921                 set_fdc_motor(false);
1922                 event_fdc_motor = -1;
1923                 break;
1924 #if defined(HAS_2HD)
1925         case EVENT_FD_MOTOR_ON_2HD:
1926                 set_fdc_motor_2HD(true);
1927                 event_fdc_motor_2HD = -1;
1928                 break;
1929         case EVENT_FD_MOTOR_OFF_2HD:
1930                 set_fdc_motor_2HD(false);
1931                 event_fdc_motor_2HD = -1;
1932                 break;
1933         case EVENT_FD_NMI_2HD:
1934                 do_nmi(true);
1935                 event_2hd_nmi = -1;
1936                 break;
1937 #endif
1938         case EVENT_PRINTER_RESET_COMPLETED:                     
1939                 write_signals(&printer_reset_bus, 0x00);
1940                 break;
1941         default:
1942                 break;
1943         }
1944 }
1945
1946
1947 void FM7_MAINIO::update_config()
1948 {
1949         switch(config.cpu_type){
1950         case 0:
1951                 clock_fast = true;
1952                 break;
1953         case 1:
1954                 clock_fast = false;
1955                 break;
1956         }
1957         write_signals(&clock_status, clock_fast ? 0xffffffff : 0);
1958 }
1959
1960 void FM7_MAINIO::event_vline(int v, int clock)
1961 {
1962 }
1963
1964
1965 #define STATE_VERSION 16
1966 #include "../../statesub.h"
1967
1968 void FM7_MAINIO::decl_state(void)
1969 {
1970         enter_decl_state(STATE_VERSION);
1971
1972         DECL_STATE_ENTRY_MULTI(void, io_w_latch, sizeof(io_w_latch));
1973         
1974         DECL_STATE_ENTRY_BOOL(clock_fast);
1975         DECL_STATE_ENTRY_BOOL(lpt_strobe);
1976         DECL_STATE_ENTRY_BOOL(lpt_slctin);
1977         DECL_STATE_ENTRY_BOOL(beep_flag);
1978         DECL_STATE_ENTRY_BOOL(beep_snd);
1979         
1980                 // FD01
1981         DECL_STATE_ENTRY_UINT8(lpt_outdata);
1982         // FD02
1983         DECL_STATE_ENTRY_BOOL(cmt_indat);
1984         DECL_STATE_ENTRY_BOOL(cmt_invert);
1985         DECL_STATE_ENTRY_BOOL(lpt_det2);
1986         DECL_STATE_ENTRY_BOOL(lpt_det1);
1987         DECL_STATE_ENTRY_BOOL(lpt_pe);
1988         DECL_STATE_ENTRY_BOOL(lpt_ackng_inv);
1989         DECL_STATE_ENTRY_BOOL(lpt_error_inv);
1990         DECL_STATE_ENTRY_UINT8(irqmask_reg0);
1991         
1992         DECL_STATE_ENTRY_BOOL(irqmask_syndet);
1993         DECL_STATE_ENTRY_BOOL(irqmask_rxrdy);
1994         DECL_STATE_ENTRY_BOOL(irqmask_txrdy);
1995         DECL_STATE_ENTRY_BOOL(irqmask_mfd);
1996         DECL_STATE_ENTRY_BOOL(irqmask_timer);
1997         DECL_STATE_ENTRY_BOOL(irqmask_printer);
1998         DECL_STATE_ENTRY_BOOL(irqmask_keyboard);
1999
2000         DECL_STATE_ENTRY_BOOL(irqreq_syndet);
2001         DECL_STATE_ENTRY_BOOL(irqreq_rxrdy);
2002         DECL_STATE_ENTRY_BOOL(irqreq_txrdy);
2003         DECL_STATE_ENTRY_BOOL(irqreq_printer);
2004         DECL_STATE_ENTRY_BOOL(irqreq_keyboard);
2005         DECL_STATE_ENTRY_UINT8(irqstat_reg0);
2006                 
2007         DECL_STATE_ENTRY_BOOL(irqstat_timer);
2008         DECL_STATE_ENTRY_BOOL(irqstat_printer);
2009         DECL_STATE_ENTRY_BOOL(irqstat_keyboard);
2010                 
2011                 // FD04
2012 #if defined(_FM77_VARIANTS)
2013         DECL_STATE_ENTRY_BOOL(stat_fdmode_2hd);
2014         DECL_STATE_ENTRY_BOOL(stat_kanjirom);
2015 #elif defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX) || \
2016         defined(_FM77AV20) || defined(_FM77AV20EX) || defined(_FM77AV20SX)
2017         DECL_STATE_ENTRY_BOOL(stat_kanjirom);
2018 #endif
2019         DECL_STATE_ENTRY_BOOL(firq_break_key);
2020         DECL_STATE_ENTRY_BOOL(firq_sub_attention);
2021         
2022         DECL_STATE_ENTRY_BOOL(intmode_fdc);
2023         // FD05
2024         DECL_STATE_ENTRY_BOOL(extdet_neg);
2025         DECL_STATE_ENTRY_BOOL(sub_halt);
2026         DECL_STATE_ENTRY_BOOL(sub_cancel);
2027         // FD06, 07
2028         DECL_STATE_ENTRY_BOOL(intstat_syndet);
2029         DECL_STATE_ENTRY_BOOL(intstat_rxrdy);
2030         DECL_STATE_ENTRY_BOOL(intstat_txrdy);
2031         
2032         
2033         DECL_STATE_ENTRY_BOOL(intstat_opn);
2034         DECL_STATE_ENTRY_BOOL(intstat_mouse);
2035         DECL_STATE_ENTRY_BOOL(mouse_enable);
2036         
2037         DECL_STATE_ENTRY_BOOL(intstat_whg);
2038         DECL_STATE_ENTRY_BOOL(intstat_thg);
2039         
2040         // FDC
2041         DECL_STATE_ENTRY_BOOL(connect_fdc);
2042         DECL_STATE_ENTRY_UINT8(fdc_statreg);
2043         DECL_STATE_ENTRY_UINT8(fdc_cmdreg);
2044         DECL_STATE_ENTRY_UINT8(fdc_trackreg);
2045         DECL_STATE_ENTRY_UINT8(fdc_sectreg);
2046         DECL_STATE_ENTRY_UINT8(fdc_datareg);
2047         DECL_STATE_ENTRY_UINT8(fdc_headreg);
2048         DECL_STATE_ENTRY_UINT8(fdc_drvsel);
2049         DECL_STATE_ENTRY_UINT8(irqreg_fdc);
2050         DECL_STATE_ENTRY_BOOL(fdc_motor);
2051         DECL_STATE_ENTRY_BOOL(irqstat_fdc);
2052         // KANJI ROM
2053         DECL_STATE_ENTRY_BOOL(connect_kanjiroml1);
2054 #if defined(_FM77AV_VARIANTS)
2055         DECL_STATE_ENTRY_BOOL(connect_kanjiroml2);
2056         
2057         DECL_STATE_ENTRY_BOOL(boot_ram);
2058         DECL_STATE_ENTRY_BOOL(hotreset);
2059                 // FD13
2060         DECL_STATE_ENTRY_UINT8(sub_monitor_type);
2061 #endif  
2062                 // MMR
2063         //V2
2064         {
2065                 DECL_STATE_ENTRY_INT(event_beep);
2066                 DECL_STATE_ENTRY_INT(event_beep_oneshot);
2067                 DECL_STATE_ENTRY_INT(event_timerirq);
2068         }               
2069         { // V3
2070                 DECL_STATE_ENTRY_INT(event_fdc_motor);
2071 #if defined(_FM77AV40) || defined(_FM77AV40EX) || defined(_FM77AV40SX)|| \
2072     defined(_FM77AV20) || defined(_FM77AV20SX) || defined(_FM77AV20EX)
2073                 DECL_STATE_ENTRY_UINT8_ARRAY(fdc_drive_table, 4);
2074                 DECL_STATE_ENTRY_UINT8(fdc_reg_fd1e);
2075 #endif  
2076 #if defined(HAS_DMA)
2077                 DECL_STATE_ENTRY_BOOL(intstat_dma);
2078                 DECL_STATE_ENTRY_UINT8(dma_addr);
2079 #endif                  
2080 #if defined(_FM77AV_VARIANTS)
2081                 DECL_STATE_ENTRY_UINT8(reg_fd12);
2082 #endif          
2083         }
2084 // FD05
2085         DECL_STATE_ENTRY_BOOL(req_z80run);
2086         DECL_STATE_ENTRY_BOOL(z80_run);
2087
2088         // UART
2089         DECL_STATE_ENTRY_BOOL(rs232c_enabled);
2090         DECL_STATE_ENTRY_BOOL(rs232c_dcd);
2091         DECL_STATE_ENTRY_BOOL_ARRAY(uart_enabled, 3);
2092         
2093         DECL_STATE_ENTRY_BOOL(modem_irqmask_rxrdy);
2094         DECL_STATE_ENTRY_BOOL(modem_irqmask_txrdy);
2095         DECL_STATE_ENTRY_BOOL(modem_syndet);
2096         DECL_STATE_ENTRY_BOOL(modem_rxrdy);
2097         DECL_STATE_ENTRY_BOOL(modem_txrdy);
2098
2099         DECL_STATE_ENTRY_BOOL(midi_uart_irqmask);
2100         DECL_STATE_ENTRY_BOOL(midi_syndet);
2101         DECL_STATE_ENTRY_BOOL(midi_rxrdy);
2102         DECL_STATE_ENTRY_BOOL(midi_txrdy);
2103 #if defined(HAS_2HD)
2104         DECL_STATE_ENTRY_INT(event_fdc_motor_2HD);
2105         DECL_STATE_ENTRY_BOOL(connect_fdc_2HD);
2106         DECL_STATE_ENTRY_UINT8(fdc_2HD_statreg);
2107         DECL_STATE_ENTRY_UINT8(fdc_2HD_cmdreg);
2108         DECL_STATE_ENTRY_UINT8(fdc_2HD_trackreg);
2109         DECL_STATE_ENTRY_UINT8(fdc_2HD_sectreg);
2110         DECL_STATE_ENTRY_UINT8(fdc_2HD_datareg);
2111         DECL_STATE_ENTRY_UINT8(fdc_2HD_headreg);
2112         DECL_STATE_ENTRY_UINT8(fdc_2HD_drvsel);
2113         DECL_STATE_ENTRY_UINT8(irqreg_fdc_2HD);
2114         DECL_STATE_ENTRY_BOOL(fdc_2HD_motor);
2115         //state_fio->FputBool(irqstat_fdc);
2116         DECL_STATE_ENTRY_INT(event_2hd_nmi);
2117         DECL_STATE_ENTRY_UINT32(nmi_delay);
2118         DECL_STATE_ENTRY_BOOL(irqstat_fdc_2hd);
2119         DECL_STATE_ENTRY_BOOL(drqstat_fdc_2hd);
2120 #endif
2121         
2122         decl_state_opn();
2123         
2124         leave_decl_state();
2125 }
2126 void FM7_MAINIO::save_state(FILEIO *state_fio)
2127 {
2128         if(state_entry != NULL) state_entry->save_state(state_fio);
2129 #if 0
2130         // Debug
2131         for(int i = 0; i < 3; i++) {
2132                 out_debug_log("OPN#%d registers (to Save)", i);
2133                 out_debug_log("ADDR: +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f");
2134                 for(int ladr = 0; ladr < 0x100; ladr += 0x10) {
2135                         out_debug_log("+%02x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
2136                                                   ladr,
2137                                                   opn_regs[i][ladr + 0],  opn_regs[i][ladr + 1],  opn_regs[i][ladr + 2],  opn_regs[i][ladr + 3],
2138                                                   opn_regs[i][ladr + 4],  opn_regs[i][ladr + 5],  opn_regs[i][ladr + 6],  opn_regs[i][ladr + 7],
2139                                                   opn_regs[i][ladr + 8],  opn_regs[i][ladr + 9],  opn_regs[i][ladr + 10], opn_regs[i][ladr + 11],
2140                                                   opn_regs[i][ladr + 12], opn_regs[i][ladr + 13], opn_regs[i][ladr + 14], opn_regs[i][ladr + 15]);
2141                 }
2142         }
2143 #endif  
2144 }
2145
2146 bool FM7_MAINIO::load_state(FILEIO *state_fio)
2147 {
2148         int ch;
2149         int addr;
2150         //bool stat = false;
2151         uint32_t version;
2152         bool mb = false;
2153         if(state_entry != NULL) {
2154                 mb = state_entry->load_state(state_fio);
2155                 if(mb) {
2156 #if defined(HAS_DMA)
2157                         dma_addr = dma_addr & 0x1f;
2158 #endif
2159                 }
2160         }
2161 #if 0
2162         for(int i = 0; i < 3; i++) {
2163                 out_debug_log("OPN#%d registers (Loaded)", i);
2164                 out_debug_log("ADDR: +0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +a +b +c +d +e +f");
2165                 for(int ladr = 0; ladr < 0x100; ladr += 0x10) {
2166                         out_debug_log("+%02x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
2167                                                   ladr,
2168                                                   opn_regs[i][ladr + 0],  opn_regs[i][ladr + 1],  opn_regs[i][ladr + 2],  opn_regs[i][ladr + 3],
2169                                                   opn_regs[i][ladr + 4],  opn_regs[i][ladr + 5],  opn_regs[i][ladr + 6],  opn_regs[i][ladr + 7],
2170                                                   opn_regs[i][ladr + 8],  opn_regs[i][ladr + 9],  opn_regs[i][ladr + 10], opn_regs[i][ladr + 11],
2171                                                   opn_regs[i][ladr + 12], opn_regs[i][ladr + 13], opn_regs[i][ladr + 14], opn_regs[i][ladr + 15]);
2172                 }
2173         }
2174 #endif
2175         this->out_debug_log(_T("Load State: MAINIO: id=%d stat=%s\n"), this_device_id, (mb) ? _T("OK") : _T("NG"));
2176         return mb;
2177 }
2178