2 * FM-7 -> FM-8 Main I/O [fm8_mainio.h]
4 * Author: K.Ohta <whatisthis.sowhat _at_ gmail.com>
7 * Jan 03, 2015 : Initial
8 * Jan 25, 2018 : Move some routines from fm7_mainio.h
13 #include "fm8_mainio.h"
15 #include "../mc6809.h"
18 #include "../datarec.h"
23 #include "../ym2203.h"
24 #include "../ay_3_891x.h"
25 #include "../pcm1bit.h"
27 #include "./fm7_mainmem.h"
28 #include "./bubblecasette.h"
31 FM8_MAINIO::FM8_MAINIO(VM_TEMPLATE* parent_vm, EMU_TEMPLATE* parent_emu) : FM7_MAINIO(parent_vm, parent_emu)
34 bubble_casette[0] = NULL;
35 bubble_casette[1] = NULL;
40 opn_address[0] = 0x00;
47 set_device_name(_T("FM-8 MAIN I/O"));
51 FM8_MAINIO::~FM8_MAINIO()
56 void FM8_MAINIO::initialize()
58 FM7_MAINIO::initialize();
61 void FM8_MAINIO::reset()
64 cancel_event(this, event_timerirq);
68 uint8_t FM8_MAINIO::get_port_fd00(void)
71 if(clock_fast) ret |= 0x01; //0b00000001;
75 void FM8_MAINIO::set_port_fd02(uint8_t val)
80 uint8_t FM8_MAINIO::get_irqstat_fd03(void)
85 uint8_t FM8_MAINIO::get_extirq_fd17(void)
91 void FM8_MAINIO::set_ext_fd17(uint8_t data)
95 void FM8_MAINIO::set_irq_syndet(bool flag)
97 bool backup = intstat_syndet;
99 intstat_syndet = flag;
100 if(backup != intstat_syndet) do_irq();
103 void FM8_MAINIO::set_irq_rxrdy(bool flag)
105 bool backup = intstat_rxrdy;
107 intstat_rxrdy = flag;
108 if(backup != intstat_rxrdy) do_irq();
111 void FM8_MAINIO::set_irq_txrdy(bool flag)
113 bool backup = intstat_txrdy;
115 intstat_txrdy = flag;
116 if(backup != intstat_txrdy) do_irq();
120 void FM8_MAINIO::set_irq_timer(bool flag)
124 void FM8_MAINIO::set_irq_printer(bool flag)
128 void FM8_MAINIO::set_irq_mfd(bool flag)
130 //bool backup = irqstat_fdc;
131 if(!connect_fdc) return;
133 irqreg_fdc |= 0x40; //0b01000000;
135 irqreg_fdc &= 0xbf; //0b10111111;
137 // With FM8, $FD1F is alive and not do_irq(), Thanks to Anna_Wu.
140 void FM8_MAINIO::do_irq(void)
144 intstat = intstat_txrdy | intstat_rxrdy | intstat_syndet;
145 nval = (intstat) ? 0xffffffff : 0;
146 write_signals(&irq_bus, nval);
149 void FM8_MAINIO::write_fd0f(void)
151 if((config.dipswitch & FM7_DIPSW_FM8_PROTECT_FD0F) != 0) {
154 bootmode = 1; // DOS : Where BUBBLE?
155 if(config.boot_mode >= 4) {
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);
163 uint8_t FM8_MAINIO::read_fd0f(void)
165 if((config.dipswitch & FM7_DIPSW_FM8_PROTECT_FD0F) != 0) {
168 bootmode = 0; // BASIC
169 if(config.boot_mode >= 4) {
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);
178 void FM8_MAINIO::reset_sound(void)
184 if(config.sound_type == 0) {
189 # if defined(USE_AY_3_8910_AS_PSG)
190 psg->write_signal(SIG_AY_3_891X_MUTE, !connect_psg ? 0xffffffff : 0x00000000, 0xffffffff);
192 psg->write_signal(SIG_YM2203_MUTE, !connect_psg ? 0xffffffff : 0x00000000, 0xffffffff);
194 pcm1bit->write_signal(SIG_PCM1BIT_MUTE, 0x01, 0x01);
195 pcm1bit->write_signal(SIG_PCM1BIT_ON, 0x00, 0x01);
199 void FM8_MAINIO::set_psg(uint8_t val)
201 if(connect_psg) return set_opn(0, val);
204 uint8_t FM8_MAINIO::get_psg(void)
206 if(connect_psg) return get_opn(0);
210 * $fd0d : After 77AV, this is OPN.
212 void FM8_MAINIO::set_psg_cmd(uint8_t cmd)
215 if(connect_psg) set_opn_cmd(0, cmd);
219 // Write to FD16, same as
220 void FM8_MAINIO::write_opn_reg(int index, uint32_t addr, uint32_t data)
223 opn_regs[0][addr] = data;
224 psg->write_io8(0, addr & 0x0f);
225 psg->write_io8(1, data);
230 void FM8_MAINIO::set_opn(int index, uint8_t val)
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
242 case 2: // Write Data
243 write_opn_reg(index, opn_address[index], opn_data[index]);
245 case 3: // Register address
247 opn_address[index] = val & 0x0f;
249 opn_address[index] = val;
257 uint8_t FM8_MAINIO::get_opn(int index)
260 if(!connect_psg) return val;
261 if(index != 0) return val;
262 if(psg == NULL) return val;
263 switch(opn_cmdreg[index]) {
268 val = opn_data[index];
278 void FM8_MAINIO::set_opn_cmd(int index, uint8_t cmd)
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
289 opn_cmdreg[index] = cmd & 0x0f;
290 uint8_t val = opn_data[index];
291 switch(opn_cmdreg[index]) {
296 psg->write_io8(0, opn_address[index]);
297 opn_data[index] = psg->read_io8(1);
299 if(opn_address[index] <= 0x0f) {
300 opn_data[index] &= mask[opn_address[index]];
304 write_opn_reg(index, opn_address[index], opn_data[index]);
306 case 3: // Register address
308 opn_address[index] = val & 0x0f;
310 opn_address[index] = val;
319 uint8_t FM8_MAINIO::get_extirq_whg(void)
324 uint8_t FM8_MAINIO::get_extirq_thg(void)
329 void FM8_MAINIO::write_signal(int id, uint32_t data, uint32_t mask)
331 bool val_b = ((data & mask) != 0);
333 case FM7_MAINIO_OPN_IRQ:
336 case FM7_MAINIO_WHG_IRQ:
339 case FM7_MAINIO_THG_IRQ:
342 case FM7_MAINIO_FDC_IRQ:
349 FM7_MAINIO::write_signal(id, data, mask);
352 uint32_t FM8_MAINIO::read_data8(uint32_t addr)
354 uint32_t retval = 0xff;
357 retval = (uint32_t)get_port_fd00();
368 case 0x0e: // PSG DATA
369 retval = (uint32_t) get_psg();
370 //out_debug_log("PSG DATA READ val=%02x\n", retval);
385 retval = bubble_casette[0]->read_data8(addr);
388 case 0x37: // Multi page
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.
399 return FM7_MAINIO::read_data8(addr);
402 void FM8_MAINIO::write_data8(uint32_t addr, uint32_t data)
406 return set_port_fd02(data);
416 bubble_casette[0]->write_data8(addr, data);
428 case 0x37: // Multi page
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);
440 void FM8_MAINIO::event_callback(int event_id, int err)
442 if(event_id == EVENT_TIMERIRQ_ON) {
445 FM7_MAINIO::event_callback(event_id, err);
448 void FM8_MAINIO::update_config()
450 FM7_MAINIO::update_config();
452 if(config.boot_mode == 0) {
453 mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0xffffffff, 0xffffffff);
455 mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0, 0xffffffff);
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);
461 bool FM8_MAINIO::process_state(FILEIO *state_fio, bool loading)
463 if(!FM7_MAINIO::process_state(state_fio, loading)) {
466 state_fio->StateValue(connect_psg);