OSDN Git Service

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