OSDN Git Service

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