OSDN Git Service

a235029ce68177e2e5f74d195f2946f1afd30de4
[csp-qt/common_source_project-fm7.git] / source / src / vm / fm7 / fm8_mainio.cpp
1 /*
2  * FM-7 -> FM-8 Main I/O [fm8_mainio.h]
3  *
4  * Author: K.Ohta <whatisthis.sowhat _at_ gmail.com>
5  * License: GPLv2
6  * History:
7  *   Jan 03, 2015 : Initial
8  *   Jan 25, 2018 : Move some routines from fm7_mainio.h
9  *
10  */
11
12 #include "fm7.h"
13 #include "fm8_mainio.h"
14
15 #include "../mc6809.h"
16 #include "../z80.h"
17
18 #include "../datarec.h"
19 #include "../i8251.h"
20 #if defined(HAS_DMA)
21 #include "hd6844.h"
22 #endif
23 #include "../ym2203.h"
24 #include "../ay_3_891x.h"
25 #include "../pcm1bit.h"
26
27 #include "./fm7_mainmem.h"
28 #include "bubblecasette.h"
29
30 FM8_MAINIO::FM8_MAINIO(VM* parent_vm, EMU* parent_emu) : FM7_MAINIO(parent_vm, parent_emu)
31 {
32     psg = NULL;
33         bubble_casette[0] = NULL;
34         bubble_casette[1] = NULL;
35
36         // FD15/ FD46 / FD51
37         connect_psg = false;
38         {
39                 opn_address[0] = 0x00;
40                 opn_data[0] = 0x00;
41                 opn_cmdreg[0] = 0;
42         }
43 #if defined(HAS_DMA)
44         dmac = NULL;
45 #endif  
46         set_device_name(_T("FM-8 MAIN I/O"));
47 }
48
49 FM8_MAINIO::~FM8_MAINIO()
50 {
51 }
52
53
54 void FM8_MAINIO::initialize()
55 {
56         FM7_MAINIO::initialize();
57 }
58
59 void FM8_MAINIO::reset()
60 {
61         FM7_MAINIO::reset();
62         cancel_event(this, event_timerirq);
63 }
64
65 uint8_t FM8_MAINIO::get_port_fd00(void)
66 {
67         uint8_t ret = 0xfe;
68         if(clock_fast) ret |= 0x01; //0b00000001;
69         return ret;
70 }
71
72 void FM8_MAINIO::set_port_fd02(uint8_t val)
73 {
74         return;
75 }
76
77 uint8_t FM8_MAINIO::get_irqstat_fd03(void)
78 {
79         return 0xff;
80 }
81
82 uint8_t FM8_MAINIO::get_extirq_fd17(void)
83 {
84         uint8_t val = 0xff;
85         return val;
86 }
87
88 void FM8_MAINIO::set_ext_fd17(uint8_t data)
89 {
90 }
91
92 void FM8_MAINIO::set_irq_syndet(bool flag)
93 {
94         bool backup = intstat_syndet;
95         irqreq_syndet = flag;
96         intstat_syndet = flag;
97         if(backup != intstat_syndet) do_irq();
98 }
99
100 void FM8_MAINIO::set_irq_rxrdy(bool flag)
101 {
102         bool backup = intstat_rxrdy;
103         irqreq_rxrdy = flag;
104         intstat_rxrdy = flag;
105         if(backup != intstat_rxrdy) do_irq();
106 }
107
108 void FM8_MAINIO::set_irq_txrdy(bool flag)
109 {
110         bool backup = intstat_txrdy;
111         irqreq_txrdy = flag;
112         intstat_txrdy = flag;
113         if(backup != intstat_txrdy) do_irq();
114 }
115
116
117 void FM8_MAINIO::set_irq_timer(bool flag)
118 {
119 }
120
121 void FM8_MAINIO::set_irq_printer(bool flag)
122 {
123 }
124
125 void FM8_MAINIO::set_irq_mfd(bool flag)
126 {
127         //bool backup = irqstat_fdc;
128         if(!connect_fdc) return;
129         if(flag) {
130                 irqreg_fdc |= 0x40; //0b01000000;
131         } else {
132                 irqreg_fdc &= 0xbf; //0b10111111;
133         }
134         // With FM8, $FD1F is alive and not do_irq(), Thanks to Anna_Wu.
135 }
136
137 void FM8_MAINIO::do_irq(void)
138 {
139         bool intstat;
140         uint32_t nval;
141         intstat = intstat_txrdy | intstat_rxrdy | intstat_syndet;
142         nval = (intstat) ? 0xffffffff : 0;
143         write_signals(&irq_bus, nval);
144 }
145
146 void FM8_MAINIO::write_fd0f(void)
147 {
148         if((config.dipswitch & FM7_DIPSW_FM8_PROTECT_FD0F) != 0) {
149                 return;
150         }
151         bootmode = 1; // DOS : Where BUBBLE?
152         if(config.boot_mode >= 4) {
153                 bootmode = 5;
154         }
155         mainmem->write_signal(FM7_MAINIO_BOOTMODE, bootmode, 0xffffffff);
156         mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0, 0xffffffff);
157         mainmem->write_signal(FM7_MAINIO_PUSH_FD0F, 0, 0xffffffff);
158 }
159
160 uint8_t FM8_MAINIO::read_fd0f(void)
161 {
162         if((config.dipswitch & FM7_DIPSW_FM8_PROTECT_FD0F) != 0) {
163                 return 0xff;
164         }
165         bootmode = 0; // BASIC
166         if(config.boot_mode >= 4) {
167                 bootmode = 4;
168         }
169         mainmem->write_signal(FM7_MAINIO_BOOTMODE, bootmode, 0xffffffff);
170         mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0xffffffff, 0xffffffff);
171         mainmem->write_signal(FM7_MAINIO_PUSH_FD0F, 0xffffffff, 0xffffffff);
172         return 0xff;
173 }
174
175 void FM8_MAINIO::reset_sound(void)
176 {
177         if(psg != NULL) {
178                 psg->reset();
179         }
180         connect_psg = false;
181         if(config.sound_type == 0) {
182                 connect_psg = false;
183         } else {
184                 connect_psg = true;
185         }
186 # if defined(USE_AY_3_8910_AS_PSG)
187         psg->write_signal(SIG_AY_3_891X_MUTE, !connect_psg ? 0xffffffff : 0x00000000, 0xffffffff);
188 # else  
189         psg->write_signal(SIG_YM2203_MUTE, !connect_psg ? 0xffffffff : 0x00000000, 0xffffffff);
190 # endif
191         pcm1bit->write_signal(SIG_PCM1BIT_MUTE, 0x01, 0x01);
192         pcm1bit->write_signal(SIG_PCM1BIT_ON, 0x00, 0x01);
193
194 }
195
196 void FM8_MAINIO::set_psg(uint8_t val)
197 {
198         if(connect_psg) return set_opn(0, val);
199 }
200
201 uint8_t FM8_MAINIO::get_psg(void)
202 {
203         if(connect_psg) return get_opn(0);
204         return 0xff;
205 }
206 /*
207  * $fd0d : After 77AV, this is OPN.
208  */
209 void FM8_MAINIO::set_psg_cmd(uint8_t cmd)
210 {
211         cmd = cmd & 0x03;
212         if(connect_psg) set_opn_cmd(0, cmd);
213         return;
214 }
215 // OPN
216 // Write to FD16, same as 
217 void FM8_MAINIO::write_opn_reg(int index, uint32_t addr, uint32_t data)
218 {
219         if(connect_psg) {
220                 opn_regs[0][addr] = data;
221                 psg->write_io8(0, addr & 0x0f);
222                 psg->write_io8(1, data);
223                 return;
224         }
225 }
226
227 void FM8_MAINIO::set_opn(int index, uint8_t val)
228 {
229         if(!connect_psg) {
230                 return;
231         }
232         if(index != 0) return;
233         if(psg == NULL) return;
234         opn_data[index] = val;
235         switch(opn_cmdreg[index]){
236                 case 0: // High inpedance
237                 case 1: // Read Data
238                         break;
239                 case 2: // Write Data
240                         write_opn_reg(index, opn_address[index], opn_data[index]);
241                         break;
242                 case 3: // Register address
243                         if(index == 3) {
244                                 opn_address[index] = val & 0x0f;
245                         } else {
246                                 opn_address[index] = val;
247                         }
248                         break;
249                 default:
250                         break;
251         }
252 }
253
254 uint8_t FM8_MAINIO::get_opn(int index)
255 {
256         uint8_t val = 0xff;
257         if(!connect_psg) return val;
258         if(index != 0) return val;
259         if(psg == NULL) return val;
260         switch(opn_cmdreg[index]) {
261                 case 0:
262                 case 1:
263                 case 2:
264                 case 3:
265                         val = opn_data[index];
266                         break;
267                 default:
268                         break;
269                 }
270                 return val;
271 }
272   /*
273    * $fd16?
274    */
275 void FM8_MAINIO::set_opn_cmd(int index, uint8_t cmd)
276 {
277         if(!connect_psg) return;
278         if(index != 0) return;
279         if(psg == NULL) return;
280         uint32_t mask[16] = { // Parameter is related by XM7. Thanks Ryu.
281                 0xff, 0x0f, 0xff, 0x0f,
282                 0xff, 0x0f, 0x1f, 0xff,
283                 0x1f, 0x1f, 0x1f, 0xff,
284                 0xff, 0x0f, 0xff, 0xff
285         };
286         opn_cmdreg[index] = cmd & 0x0f;
287         uint8_t val = opn_data[index];
288         switch(opn_cmdreg[index]) {
289                 case 0:
290                         break;
291                 case 1:
292                         if(index == 0) {
293                                 psg->write_io8(0, opn_address[index]);
294                                 opn_data[index] = psg->read_io8(1);
295                         }
296                         if(opn_address[index] <= 0x0f) {
297                                 opn_data[index] &= mask[opn_address[index]];
298                         }
299                         break;
300                 case 2:
301                         write_opn_reg(index, opn_address[index], opn_data[index]);
302                         break;
303                 case 3: // Register address
304                         if(index == 3) {
305                                 opn_address[index] = val & 0x0f;
306                         } else {
307                                 opn_address[index] = val;
308                         }
309
310                         break;
311                 default:
312                         break;
313         }
314         return;
315 }
316 uint8_t FM8_MAINIO::get_extirq_whg(void)
317 {
318         uint8_t val = 0xff;
319         return val;
320 }
321 uint8_t FM8_MAINIO::get_extirq_thg(void)
322 {
323         uint8_t val = 0xff;
324         return val;
325 }
326 void FM8_MAINIO::opn_note_on(int index)
327 {
328 }
329
330 void FM8_MAINIO::write_signal(int id, uint32_t data, uint32_t mask)
331 {
332         bool val_b = ((data & mask) != 0);
333         switch(id) {
334                 case FM7_MAINIO_OPN_IRQ:
335                         return;
336                         break;
337                 case FM7_MAINIO_WHG_IRQ:
338                         return;
339                         break;
340                 case FM7_MAINIO_THG_IRQ:
341                         return;
342                         break;
343                 case FM7_MAINIO_FDC_IRQ:
344                         set_irq_mfd(val_b);
345                         return;
346                         break;
347                 default:
348                         break;
349         }
350         FM7_MAINIO::write_signal(id, data, mask);
351 }
352
353 uint32_t FM8_MAINIO::read_data8(uint32_t addr)
354 {
355         uint32_t retval = 0xff;
356         switch(addr) {
357         case 0x00:
358                 retval = (uint32_t)get_port_fd00();
359                 return retval;
360                 break;
361         case 0x01: // FD01
362                 retval = 0xff;
363                 return retval;
364                 break;
365         case 0x03: // FD03
366                 retval = 0xff;
367                 return retval;
368                 break;
369         case 0x0e: // PSG DATA
370                 retval = (uint32_t) get_psg();
371                 //printf("PSG DATA READ val=%02x\n", retval);
372                 return retval;
373                 break;
374         case 0x0f: // FD0F
375                 read_fd0f();
376                 retval = 0xff;
377                 break;
378         case 0x10:
379         case 0x11:
380         case 0x12:
381         case 0x13:
382         case 0x14:
383         case 0x15:
384         case 0x16:
385         case 0x17:
386                 retval = bubble_casette[0]->read_data8(addr);
387                 return retval;
388                 break;
389         case 0x37: // Multi page
390                 retval = 0xff;
391                 return;
392                 break;
393         default:
394                 break;
395         }
396         if((addr < 0x40) && (addr >= 0x38)) return 0xff; // Palette
397         if((addr < 0x54) && (addr >= 0x45)) return 0xff; // WHG, THG
398         if((addr >= 0x40) && (addr < 0x100)) return 0xff; // Another devices.
399                 
400         return FM7_MAINIO::read_data8(addr);
401 }
402
403 void FM8_MAINIO::write_data8(uint32_t addr, uint32_t data)
404 {
405         switch(addr) {
406         case 0x02:
407                 return set_port_fd02(data);
408                 break;
409         case 0x10:
410         case 0x11:
411         case 0x12:
412         case 0x13:
413         case 0x14:
414         case 0x15:
415         case 0x16:
416         case 0x17:
417                 bubble_casette[0]->write_data8(addr, data);
418                 return;
419                 break;
420         case 0x28:
421         case 0x29:
422         case 0x2a:
423         case 0x2b:
424         case 0x2c:
425         case 0x2d:
426         case 0x2e:
427                 return;
428                 break;
429         case 0x37: // Multi page
430                 return;
431                 break;
432         default:
433                 break;
434         }
435         if((addr < 0x40) && (addr >= 0x38)) return; // palette
436         if((addr < 0x54) && (addr >= 0x45)) return; // WHG, THG
437         if((addr < 0x100) && (addr >= 0x40)) return;
438         FM7_MAINIO::write_data8(addr, data);
439 }
440
441 void FM8_MAINIO::event_callback(int event_id, int err)
442 {
443         if(event_id == EVENT_TIMERIRQ_ON) {
444                 return;
445         }
446         FM7_MAINIO::event_callback(event_id, err);
447 }
448
449 void FM8_MAINIO::update_config()
450 {
451         FM7_MAINIO::update_config();
452         // BASIC
453         if(config.boot_mode == 0) {
454                 mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0xffffffff, 0xffffffff);
455         } else {
456                 mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0, 0xffffffff);
457         }
458         mainmem->write_signal(FM7_MAINIO_PUSH_FD0F, ((config.boot_mode & 3) == 0) ? 1 : 0, 0x01);
459         mainmem->write_signal(FM7_MAINIO_BOOTMODE, bootmode, 0xffffffff);
460 }
461
462 #define STATE_VERSION 11
463
464 void FM8_MAINIO::save_state(FILEIO *state_fio)
465 {
466         int ch;
467         int addr;
468         state_fio->FputUint32_BE(STATE_VERSION);
469         state_fio->FputInt32_BE(this_device_id);
470         this->out_debug_log(_T("Save State: MAINIO(FM8): id=%d ver=%d\n"), this_device_id, STATE_VERSION);
471
472         FM7_MAINIO::save_state_main(state_fio);
473         // FD0B
474         // FD0F
475         state_fio->FputBool(connect_psg);
476         {
477                 state_fio->FputUint32_BE(opn_address[0]);
478                 state_fio->FputUint32_BE(opn_data[0]);
479                 state_fio->FputUint32_BE(opn_stat[0]);
480                 state_fio->FputUint32_BE(opn_cmdreg[0]);
481                 state_fio->FputUint32_BE(opn_ch3mode[0]);
482         }
483 }
484
485 bool FM8_MAINIO::load_state(FILEIO *state_fio)
486 {
487         uint32_t version;
488         
489         version = state_fio->FgetUint32_BE();
490         if(this_device_id != state_fio->FgetInt32_BE()) return false;
491         this->out_debug_log(_T("Load State: MAINIO(FM8): id=%d ver=%d\n"), this_device_id, version);
492
493         if(!FM7_MAINIO::load_state_main(state_fio, version)) return false;
494         connect_psg = state_fio->FgetBool();
495         {
496                 opn_address[0] = state_fio->FgetUint32_BE();
497                 opn_data[0] = state_fio->FgetUint32_BE();
498                 opn_stat[0] = state_fio->FgetUint32_BE();
499                 opn_cmdreg[0] = state_fio->FgetUint32_BE();
500                 opn_ch3mode[0] = state_fio->FgetUint32_BE();
501         }
502         if(version != STATE_VERSION) return false;
503         return true;
504 }