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"
30 FM8_MAINIO::FM8_MAINIO(VM* parent_vm, EMU* parent_emu) : FM7_MAINIO(parent_vm, parent_emu)
33 bubble_casette[0] = NULL;
34 bubble_casette[1] = NULL;
39 opn_address[0] = 0x00;
46 set_device_name(_T("FM-8 MAIN I/O"));
50 FM8_MAINIO::~FM8_MAINIO()
55 void FM8_MAINIO::initialize()
57 FM7_MAINIO::initialize();
60 void FM8_MAINIO::reset()
63 cancel_event(this, event_timerirq);
66 uint8_t FM8_MAINIO::get_port_fd00(void)
69 if(clock_fast) ret |= 0x01; //0b00000001;
73 void FM8_MAINIO::set_port_fd02(uint8_t val)
78 uint8_t FM8_MAINIO::get_irqstat_fd03(void)
83 uint8_t FM8_MAINIO::get_extirq_fd17(void)
89 void FM8_MAINIO::set_ext_fd17(uint8_t data)
93 void FM8_MAINIO::set_irq_syndet(bool flag)
95 bool backup = intstat_syndet;
97 intstat_syndet = flag;
98 if(backup != intstat_syndet) do_irq();
101 void FM8_MAINIO::set_irq_rxrdy(bool flag)
103 bool backup = intstat_rxrdy;
105 intstat_rxrdy = flag;
106 if(backup != intstat_rxrdy) do_irq();
109 void FM8_MAINIO::set_irq_txrdy(bool flag)
111 bool backup = intstat_txrdy;
113 intstat_txrdy = flag;
114 if(backup != intstat_txrdy) do_irq();
118 void FM8_MAINIO::set_irq_timer(bool flag)
122 void FM8_MAINIO::set_irq_printer(bool flag)
126 void FM8_MAINIO::set_irq_mfd(bool flag)
128 //bool backup = irqstat_fdc;
129 if(!connect_fdc) return;
131 irqreg_fdc |= 0x40; //0b01000000;
133 irqreg_fdc &= 0xbf; //0b10111111;
135 // With FM8, $FD1F is alive and not do_irq(), Thanks to Anna_Wu.
138 void FM8_MAINIO::do_irq(void)
142 intstat = intstat_txrdy | intstat_rxrdy | intstat_syndet;
143 nval = (intstat) ? 0xffffffff : 0;
144 write_signals(&irq_bus, nval);
147 void FM8_MAINIO::write_fd0f(void)
149 if((config.dipswitch & FM7_DIPSW_FM8_PROTECT_FD0F) != 0) {
152 bootmode = 1; // DOS : Where BUBBLE?
153 if(config.boot_mode >= 4) {
156 mainmem->write_signal(FM7_MAINIO_BOOTMODE, bootmode, 0xffffffff);
157 mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0, 0xffffffff);
158 mainmem->write_signal(FM7_MAINIO_PUSH_FD0F, 0, 0xffffffff);
161 uint8_t FM8_MAINIO::read_fd0f(void)
163 if((config.dipswitch & FM7_DIPSW_FM8_PROTECT_FD0F) != 0) {
166 bootmode = 0; // BASIC
167 if(config.boot_mode >= 4) {
170 mainmem->write_signal(FM7_MAINIO_BOOTMODE, bootmode, 0xffffffff);
171 mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0xffffffff, 0xffffffff);
172 mainmem->write_signal(FM7_MAINIO_PUSH_FD0F, 0xffffffff, 0xffffffff);
176 void FM8_MAINIO::reset_sound(void)
182 if(config.sound_type == 0) {
187 # if defined(USE_AY_3_8910_AS_PSG)
188 psg->write_signal(SIG_AY_3_891X_MUTE, !connect_psg ? 0xffffffff : 0x00000000, 0xffffffff);
190 psg->write_signal(SIG_YM2203_MUTE, !connect_psg ? 0xffffffff : 0x00000000, 0xffffffff);
192 pcm1bit->write_signal(SIG_PCM1BIT_MUTE, 0x01, 0x01);
193 pcm1bit->write_signal(SIG_PCM1BIT_ON, 0x00, 0x01);
197 void FM8_MAINIO::set_psg(uint8_t val)
199 if(connect_psg) return set_opn(0, val);
202 uint8_t FM8_MAINIO::get_psg(void)
204 if(connect_psg) return get_opn(0);
208 * $fd0d : After 77AV, this is OPN.
210 void FM8_MAINIO::set_psg_cmd(uint8_t cmd)
213 if(connect_psg) set_opn_cmd(0, cmd);
217 // Write to FD16, same as
218 void FM8_MAINIO::write_opn_reg(int index, uint32_t addr, uint32_t data)
221 opn_regs[0][addr] = data;
222 psg->write_io8(0, addr & 0x0f);
223 psg->write_io8(1, data);
228 void FM8_MAINIO::set_opn(int index, uint8_t val)
233 if(index != 0) return;
234 if(psg == NULL) return;
235 opn_data[index] = val;
236 switch(opn_cmdreg[index]){
237 case 0: // High inpedance
240 case 2: // Write Data
241 write_opn_reg(index, opn_address[index], opn_data[index]);
243 case 3: // Register address
245 opn_address[index] = val & 0x0f;
247 opn_address[index] = val;
255 uint8_t FM8_MAINIO::get_opn(int index)
258 if(!connect_psg) return val;
259 if(index != 0) return val;
260 if(psg == NULL) return val;
261 switch(opn_cmdreg[index]) {
266 val = opn_data[index];
276 void FM8_MAINIO::set_opn_cmd(int index, uint8_t cmd)
278 if(!connect_psg) return;
279 if(index != 0) return;
280 if(psg == NULL) return;
281 uint32_t mask[16] = { // Parameter is related by XM7. Thanks Ryu.
282 0xff, 0x0f, 0xff, 0x0f,
283 0xff, 0x0f, 0x1f, 0xff,
284 0x1f, 0x1f, 0x1f, 0xff,
285 0xff, 0x0f, 0xff, 0xff
287 opn_cmdreg[index] = cmd & 0x0f;
288 uint8_t val = opn_data[index];
289 switch(opn_cmdreg[index]) {
294 psg->write_io8(0, opn_address[index]);
295 opn_data[index] = psg->read_io8(1);
297 if(opn_address[index] <= 0x0f) {
298 opn_data[index] &= mask[opn_address[index]];
302 write_opn_reg(index, opn_address[index], opn_data[index]);
304 case 3: // Register address
306 opn_address[index] = val & 0x0f;
308 opn_address[index] = val;
317 uint8_t FM8_MAINIO::get_extirq_whg(void)
322 uint8_t FM8_MAINIO::get_extirq_thg(void)
327 void FM8_MAINIO::opn_note_on(int index)
331 void FM8_MAINIO::write_signal(int id, uint32_t data, uint32_t mask)
333 bool val_b = ((data & mask) != 0);
335 case FM7_MAINIO_OPN_IRQ:
338 case FM7_MAINIO_WHG_IRQ:
341 case FM7_MAINIO_THG_IRQ:
344 case FM7_MAINIO_FDC_IRQ:
351 FM7_MAINIO::write_signal(id, data, mask);
354 uint32_t FM8_MAINIO::read_data8(uint32_t addr)
356 uint32_t retval = 0xff;
359 retval = (uint32_t)get_port_fd00();
370 case 0x0e: // PSG DATA
371 retval = (uint32_t) get_psg();
372 //printf("PSG DATA READ val=%02x\n", retval);
387 retval = bubble_casette[0]->read_data8(addr);
390 case 0x37: // Multi page
397 if((addr < 0x40) && (addr >= 0x38)) return 0xff; // Palette
398 if((addr < 0x54) && (addr >= 0x45)) return 0xff; // WHG, THG
399 if((addr >= 0x40) && (addr < 0x100)) return 0xff; // Another devices.
401 return FM7_MAINIO::read_data8(addr);
404 void FM8_MAINIO::write_data8(uint32_t addr, uint32_t data)
408 return set_port_fd02(data);
418 bubble_casette[0]->write_data8(addr, data);
430 case 0x37: // Multi page
436 if((addr < 0x40) && (addr >= 0x38)) return; // palette
437 if((addr < 0x54) && (addr >= 0x45)) return; // WHG, THG
438 if((addr < 0x100) && (addr >= 0x40)) return;
439 FM7_MAINIO::write_data8(addr, data);
442 void FM8_MAINIO::event_callback(int event_id, int err)
444 if(event_id == EVENT_TIMERIRQ_ON) {
447 FM7_MAINIO::event_callback(event_id, err);
450 void FM8_MAINIO::update_config()
452 FM7_MAINIO::update_config();
454 if(config.boot_mode == 0) {
455 mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0xffffffff, 0xffffffff);
457 mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0, 0xffffffff);
459 mainmem->write_signal(FM7_MAINIO_PUSH_FD0F, ((config.boot_mode & 3) == 0) ? 1 : 0, 0x01);
460 mainmem->write_signal(FM7_MAINIO_BOOTMODE, bootmode, 0xffffffff);
464 #include "../../statesub.h"
465 void FM8_MAINIO::decl_state(void)
467 FM7_MAINIO::decl_state();
468 DECL_STATE_ENTRY_BOOL(connect_psg);
471 void FM8_MAINIO::save_state(FILEIO *state_fio)
473 FM7_MAINIO::save_state(state_fio);
476 bool FM8_MAINIO::load_state(FILEIO *state_fio)
479 mb = FM7_MAINIO::load_state(state_fio);