OSDN Git Service

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