OSDN Git Service

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