OSDN Git Service

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