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"));
49 FM8_MAINIO::~FM8_MAINIO()
54 void FM8_MAINIO::initialize()
56 FM7_MAINIO::initialize();
59 void FM8_MAINIO::reset()
62 cancel_event(this, event_timerirq);
65 uint8_t FM8_MAINIO::get_port_fd00(void)
68 if(clock_fast) ret |= 0x01; //0b00000001;
72 void FM8_MAINIO::set_port_fd02(uint8_t val)
77 uint8_t FM8_MAINIO::get_irqstat_fd03(void)
82 uint8_t FM8_MAINIO::get_extirq_fd17(void)
88 void FM8_MAINIO::set_ext_fd17(uint8_t data)
92 void FM8_MAINIO::set_irq_syndet(bool flag)
94 bool backup = intstat_syndet;
96 intstat_syndet = flag;
97 if(backup != intstat_syndet) do_irq();
100 void FM8_MAINIO::set_irq_rxrdy(bool flag)
102 bool backup = intstat_rxrdy;
104 intstat_rxrdy = flag;
105 if(backup != intstat_rxrdy) do_irq();
108 void FM8_MAINIO::set_irq_txrdy(bool flag)
110 bool backup = intstat_txrdy;
112 intstat_txrdy = flag;
113 if(backup != intstat_txrdy) do_irq();
117 void FM8_MAINIO::set_irq_timer(bool flag)
121 void FM8_MAINIO::set_irq_printer(bool flag)
125 void FM8_MAINIO::set_irq_mfd(bool flag)
127 //bool backup = irqstat_fdc;
128 if(!connect_fdc) return;
130 irqreg_fdc |= 0x40; //0b01000000;
132 irqreg_fdc &= 0xbf; //0b10111111;
134 // With FM8, $FD1F is alive and not do_irq(), Thanks to Anna_Wu.
137 void FM8_MAINIO::do_irq(void)
141 intstat = intstat_txrdy | intstat_rxrdy | intstat_syndet;
142 nval = (intstat) ? 0xffffffff : 0;
143 write_signals(&irq_bus, nval);
146 void FM8_MAINIO::write_fd0f(void)
148 if((config.dipswitch & FM7_DIPSW_FM8_PROTECT_FD0F) != 0) {
151 bootmode = 1; // DOS : Where BUBBLE?
152 if(config.boot_mode >= 4) {
155 mainmem->write_signal(FM7_MAINIO_BOOTMODE, bootmode, 0xffffffff);
156 mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0, 0xffffffff);
157 mainmem->write_signal(FM7_MAINIO_PUSH_FD0F, 0, 0xffffffff);
160 uint8_t FM8_MAINIO::read_fd0f(void)
162 if((config.dipswitch & FM7_DIPSW_FM8_PROTECT_FD0F) != 0) {
165 bootmode = 0; // BASIC
166 if(config.boot_mode >= 4) {
169 mainmem->write_signal(FM7_MAINIO_BOOTMODE, bootmode, 0xffffffff);
170 mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0xffffffff, 0xffffffff);
171 mainmem->write_signal(FM7_MAINIO_PUSH_FD0F, 0xffffffff, 0xffffffff);
175 void FM8_MAINIO::reset_sound(void)
181 if(config.sound_type == 0) {
186 # if defined(USE_AY_3_8910_AS_PSG)
187 psg->write_signal(SIG_AY_3_891X_MUTE, !connect_psg ? 0xffffffff : 0x00000000, 0xffffffff);
189 psg->write_signal(SIG_YM2203_MUTE, !connect_psg ? 0xffffffff : 0x00000000, 0xffffffff);
191 pcm1bit->write_signal(SIG_PCM1BIT_MUTE, 0x01, 0x01);
192 pcm1bit->write_signal(SIG_PCM1BIT_ON, 0x00, 0x01);
196 void FM8_MAINIO::set_psg(uint8_t val)
198 if(connect_psg) return set_opn(0, val);
201 uint8_t FM8_MAINIO::get_psg(void)
203 if(connect_psg) return get_opn(0);
207 * $fd0d : After 77AV, this is OPN.
209 void FM8_MAINIO::set_psg_cmd(uint8_t cmd)
212 if(connect_psg) set_opn_cmd(0, cmd);
216 // Write to FD16, same as
217 void FM8_MAINIO::write_opn_reg(int index, uint32_t addr, uint32_t data)
220 opn_regs[0][addr] = data;
221 psg->write_io8(0, addr & 0x0f);
222 psg->write_io8(1, data);
227 void FM8_MAINIO::set_opn(int index, uint8_t val)
232 if(index != 0) return;
233 if(psg == NULL) return;
234 opn_data[index] = val;
235 switch(opn_cmdreg[index]){
236 case 0: // High inpedance
239 case 2: // Write Data
240 write_opn_reg(index, opn_address[index], opn_data[index]);
242 case 3: // Register address
244 opn_address[index] = val & 0x0f;
246 opn_address[index] = val;
254 uint8_t FM8_MAINIO::get_opn(int index)
257 if(!connect_psg) return val;
258 if(index != 0) return val;
259 if(psg == NULL) return val;
260 switch(opn_cmdreg[index]) {
265 val = opn_data[index];
275 void FM8_MAINIO::set_opn_cmd(int index, uint8_t cmd)
277 if(!connect_psg) return;
278 if(index != 0) return;
279 if(psg == NULL) return;
280 uint32_t mask[16] = { // Parameter is related by XM7. Thanks Ryu.
281 0xff, 0x0f, 0xff, 0x0f,
282 0xff, 0x0f, 0x1f, 0xff,
283 0x1f, 0x1f, 0x1f, 0xff,
284 0xff, 0x0f, 0xff, 0xff
286 opn_cmdreg[index] = cmd & 0x0f;
287 uint8_t val = opn_data[index];
288 switch(opn_cmdreg[index]) {
293 psg->write_io8(0, opn_address[index]);
294 opn_data[index] = psg->read_io8(1);
296 if(opn_address[index] <= 0x0f) {
297 opn_data[index] &= mask[opn_address[index]];
301 write_opn_reg(index, opn_address[index], opn_data[index]);
303 case 3: // Register address
305 opn_address[index] = val & 0x0f;
307 opn_address[index] = val;
316 uint8_t FM8_MAINIO::get_extirq_whg(void)
321 uint8_t FM8_MAINIO::get_extirq_thg(void)
326 void FM8_MAINIO::opn_note_on(int index)
330 void FM8_MAINIO::write_signal(int id, uint32_t data, uint32_t mask)
332 bool val_b = ((data & mask) != 0);
334 case FM7_MAINIO_OPN_IRQ:
337 case FM7_MAINIO_WHG_IRQ:
340 case FM7_MAINIO_THG_IRQ:
343 case FM7_MAINIO_FDC_IRQ:
350 FM7_MAINIO::write_signal(id, data, mask);
353 uint32_t FM8_MAINIO::read_data8(uint32_t addr)
355 uint32_t retval = 0xff;
358 retval = (uint32_t)get_port_fd00();
369 case 0x0e: // PSG DATA
370 retval = (uint32_t) get_psg();
371 //printf("PSG DATA READ val=%02x\n", retval);
386 retval = bubble_casette[0]->read_data8(addr);
389 case 0x37: // Multi page
396 if((addr < 0x40) && (addr >= 0x38)) return 0xff; // Palette
397 if((addr < 0x54) && (addr >= 0x45)) return 0xff; // WHG, THG
398 if((addr >= 0x40) && (addr < 0x100)) return 0xff; // Another devices.
400 return FM7_MAINIO::read_data8(addr);
403 void FM8_MAINIO::write_data8(uint32_t addr, uint32_t data)
407 return set_port_fd02(data);
417 bubble_casette[0]->write_data8(addr, data);
429 case 0x37: // Multi page
435 if((addr < 0x40) && (addr >= 0x38)) return; // palette
436 if((addr < 0x54) && (addr >= 0x45)) return; // WHG, THG
437 if((addr < 0x100) && (addr >= 0x40)) return;
438 FM7_MAINIO::write_data8(addr, data);
441 void FM8_MAINIO::event_callback(int event_id, int err)
443 if(event_id == EVENT_TIMERIRQ_ON) {
446 FM7_MAINIO::event_callback(event_id, err);
449 void FM8_MAINIO::update_config()
451 FM7_MAINIO::update_config();
453 if(config.boot_mode == 0) {
454 mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0xffffffff, 0xffffffff);
456 mainmem->write_signal(FM7_MAINIO_IS_BASICROM, 0, 0xffffffff);
458 mainmem->write_signal(FM7_MAINIO_PUSH_FD0F, ((config.boot_mode & 3) == 0) ? 1 : 0, 0x01);
459 mainmem->write_signal(FM7_MAINIO_BOOTMODE, bootmode, 0xffffffff);
462 #define STATE_VERSION 11
464 void FM8_MAINIO::save_state(FILEIO *state_fio)
468 state_fio->FputUint32_BE(STATE_VERSION);
469 state_fio->FputInt32_BE(this_device_id);
470 this->out_debug_log(_T("Save State: MAINIO(FM8): id=%d ver=%d\n"), this_device_id, STATE_VERSION);
472 FM7_MAINIO::save_state_main(state_fio);
475 state_fio->FputBool(connect_psg);
477 state_fio->FputUint32_BE(opn_address[0]);
478 state_fio->FputUint32_BE(opn_data[0]);
479 state_fio->FputUint32_BE(opn_stat[0]);
480 state_fio->FputUint32_BE(opn_cmdreg[0]);
481 state_fio->FputUint32_BE(opn_ch3mode[0]);
485 bool FM8_MAINIO::load_state(FILEIO *state_fio)
489 version = state_fio->FgetUint32_BE();
490 if(this_device_id != state_fio->FgetInt32_BE()) return false;
491 this->out_debug_log(_T("Load State: MAINIO(FM8): id=%d ver=%d\n"), this_device_id, version);
493 if(!FM7_MAINIO::load_state_main(state_fio, version)) return false;
494 connect_psg = state_fio->FgetBool();
496 opn_address[0] = state_fio->FgetUint32_BE();
497 opn_data[0] = state_fio->FgetUint32_BE();
498 opn_stat[0] = state_fio->FgetUint32_BE();
499 opn_cmdreg[0] = state_fio->FgetUint32_BE();
500 opn_ch3mode[0] = state_fio->FgetUint32_BE();
502 if(version != STATE_VERSION) return false;