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* 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);
67 uint8_t FM8_MAINIO::get_port_fd00(void)
70 if(clock_fast) ret |= 0x01; //0b00000001;
74 void FM8_MAINIO::set_port_fd02(uint8_t val)
79 uint8_t FM8_MAINIO::get_irqstat_fd03(void)
84 uint8_t FM8_MAINIO::get_extirq_fd17(void)
90 void FM8_MAINIO::set_ext_fd17(uint8_t data)
94 void FM8_MAINIO::set_irq_syndet(bool flag)
96 bool backup = intstat_syndet;
98 intstat_syndet = flag;
99 if(backup != intstat_syndet) do_irq();
102 void FM8_MAINIO::set_irq_rxrdy(bool flag)
104 bool backup = intstat_rxrdy;
106 intstat_rxrdy = flag;
107 if(backup != intstat_rxrdy) do_irq();
110 void FM8_MAINIO::set_irq_txrdy(bool flag)
112 bool backup = intstat_txrdy;
114 intstat_txrdy = flag;
115 if(backup != intstat_txrdy) do_irq();
119 void FM8_MAINIO::set_irq_timer(bool flag)
123 void FM8_MAINIO::set_irq_printer(bool flag)
127 void FM8_MAINIO::set_irq_mfd(bool flag)
129 //bool backup = irqstat_fdc;
130 if(!connect_fdc) return;
132 irqreg_fdc |= 0x40; //0b01000000;
134 irqreg_fdc &= 0xbf; //0b10111111;
136 // With FM8, $FD1F is alive and not do_irq(), Thanks to Anna_Wu.
139 void FM8_MAINIO::do_irq(void)
143 intstat = intstat_txrdy | intstat_rxrdy | intstat_syndet;
144 nval = (intstat) ? 0xffffffff : 0;
145 write_signals(&irq_bus, nval);
148 void FM8_MAINIO::write_fd0f(void)
150 if((config.dipswitch & FM7_DIPSW_FM8_PROTECT_FD0F) != 0) {
153 bootmode = 1; // DOS : Where BUBBLE?
154 if(config.boot_mode >= 4) {
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);
162 uint8_t FM8_MAINIO::read_fd0f(void)
164 if((config.dipswitch & FM7_DIPSW_FM8_PROTECT_FD0F) != 0) {
167 bootmode = 0; // BASIC
168 if(config.boot_mode >= 4) {
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);
177 void FM8_MAINIO::reset_sound(void)
183 if(config.sound_type == 0) {
188 # if defined(USE_AY_3_8910_AS_PSG)
189 psg->write_signal(SIG_AY_3_891X_MUTE, !connect_psg ? 0xffffffff : 0x00000000, 0xffffffff);
191 psg->write_signal(SIG_YM2203_MUTE, !connect_psg ? 0xffffffff : 0x00000000, 0xffffffff);
193 pcm1bit->write_signal(SIG_PCM1BIT_MUTE, 0x01, 0x01);
194 pcm1bit->write_signal(SIG_PCM1BIT_ON, 0x00, 0x01);
198 void FM8_MAINIO::set_psg(uint8_t val)
200 if(connect_psg) return set_opn(0, val);
203 uint8_t FM8_MAINIO::get_psg(void)
205 if(connect_psg) return get_opn(0);
209 * $fd0d : After 77AV, this is OPN.
211 void FM8_MAINIO::set_psg_cmd(uint8_t cmd)
214 if(connect_psg) set_opn_cmd(0, cmd);
218 // Write to FD16, same as
219 void FM8_MAINIO::write_opn_reg(int index, uint32_t addr, uint32_t data)
222 opn_regs[0][addr] = data;
223 psg->write_io8(0, addr & 0x0f);
224 psg->write_io8(1, data);
229 void FM8_MAINIO::set_opn(int index, uint8_t val)
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
241 case 2: // Write Data
242 write_opn_reg(index, opn_address[index], opn_data[index]);
244 case 3: // Register address
246 opn_address[index] = val & 0x0f;
248 opn_address[index] = val;
256 uint8_t FM8_MAINIO::get_opn(int index)
259 if(!connect_psg) return val;
260 if(index != 0) return val;
261 if(psg == NULL) return val;
262 switch(opn_cmdreg[index]) {
267 val = opn_data[index];
277 void FM8_MAINIO::set_opn_cmd(int index, uint8_t cmd)
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
288 opn_cmdreg[index] = cmd & 0x0f;
289 uint8_t val = opn_data[index];
290 switch(opn_cmdreg[index]) {
295 psg->write_io8(0, opn_address[index]);
296 opn_data[index] = psg->read_io8(1);
298 if(opn_address[index] <= 0x0f) {
299 opn_data[index] &= mask[opn_address[index]];
303 write_opn_reg(index, opn_address[index], opn_data[index]);
305 case 3: // Register address
307 opn_address[index] = val & 0x0f;
309 opn_address[index] = val;
318 uint8_t FM8_MAINIO::get_extirq_whg(void)
323 uint8_t FM8_MAINIO::get_extirq_thg(void)
328 void FM8_MAINIO::write_signal(int id, uint32_t data, uint32_t mask)
330 bool val_b = ((data & mask) != 0);
332 case FM7_MAINIO_OPN_IRQ:
335 case FM7_MAINIO_WHG_IRQ:
338 case FM7_MAINIO_THG_IRQ:
341 case FM7_MAINIO_FDC_IRQ:
348 FM7_MAINIO::write_signal(id, data, mask);
351 uint32_t FM8_MAINIO::read_data8(uint32_t addr)
353 uint32_t retval = 0xff;
356 retval = (uint32_t)get_port_fd00();
367 case 0x0e: // PSG DATA
368 retval = (uint32_t) get_psg();
369 //printf("PSG DATA READ val=%02x\n", retval);
384 retval = bubble_casette[0]->read_data8(addr);
387 case 0x37: // Multi page
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.
398 return FM7_MAINIO::read_data8(addr);
401 void FM8_MAINIO::write_data8(uint32_t addr, uint32_t data)
405 return set_port_fd02(data);
415 bubble_casette[0]->write_data8(addr, data);
427 case 0x37: // Multi page
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);
439 void FM8_MAINIO::event_callback(int event_id, int err)
441 if(event_id == EVENT_TIMERIRQ_ON) {
444 FM7_MAINIO::event_callback(event_id, err);
447 void FM8_MAINIO::update_config()
449 FM7_MAINIO::update_config();
451 if(config.boot_mode == 0) {
452 mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0xffffffff, 0xffffffff);
454 mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0, 0xffffffff);
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);
460 bool FM8_MAINIO::decl_state(FILEIO *state_fio, bool loading)
462 if(!FM7_MAINIO::decl_state(state_fio, loading)) {
465 state_fio->StateBool(connect_psg);
470 void FM8_MAINIO::save_state(FILEIO *state_fio)
472 decl_state(state_fio, false);
475 bool FM8_MAINIO::load_state(FILEIO *state_fio)
477 bool mb = decl_state(state_fio, true);