OSDN Git Service

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