diff --git a/src/mame/nec/pc9801.cpp b/src/mame/nec/pc9801.cpp index 07e7a48b3c5..4c1e241cc3a 100644 --- a/src/mame/nec/pc9801.cpp +++ b/src/mame/nec/pc9801.cpp @@ -35,8 +35,7 @@ fixing in some cases; - Export mouse support to an actual PC9871 device; - Implement IF-SEGA/98 support (Sega Saturn peripheral compatibility for Windows, - available DOS C snippet clearly shows reading in direct mode, an actual SMPC - sub-device sounds unlikely but possible); + cfr. BeOS PnP driver); - Incomplete SDIP support: - SDIP never returns a valid state and returns default values even if machine is soft resetted. By logic should read-back the already existing state, instead @@ -84,7 +83,12 @@ TODO (PC-9801BX2) - "SYSTEM SHUTDOWN" at POST, a soft reset fixes it? - A non-fatal "MEMORY ERROR" is always thrown no matter the RAM size afterwards, related? - - unemulated conventional or EMS RAM bank, definitely should have one given the odd minimum RAM size; + - unemulated conventional or EMS RAM bank, definitely should have one given the odd minimum RAM + size; + + TODO: (PC-9801UX) + - "I/O Error" on any 3.5" floppy, specific to this romset (i.e. those works on pc9821). + It never access $4be, it must fail earlier than that. =================================================================================================== @@ -954,6 +958,17 @@ void pc9801vm_state::fdc_mode_w(uint8_t data) // logerror("FDC ctrl called with %02x\n",data); } +TIMER_CALLBACK_MEMBER(pc9801vm_state::fdc_trigger) +{ + // TODO: sorcer/hydlide definitely expects the XTMASK irq to be taken + // NOTE: should probably trigger the FDC irq depending on mode, i.e. use fdc_irq_w fn + if (BIT(m_fdc_2hd_ctrl, 2)) + { + m_pic2->ir2_w(0); + m_pic2->ir2_w(1); + } +} + // TODO: undefined/disallow read/writes if I/F mode doesn't match // (and that applies to FDC mapping too!) // id port 0 -> 2DD @@ -969,17 +984,6 @@ template u8 pc9801vm_state::fdc_2hd_2dd_ctrl_r() return res; } -TIMER_CALLBACK_MEMBER(pc9801vm_state::fdc_trigger) -{ - // TODO: sorcer/hydlide definitely expects the XTMASK irq to be taken - // NOTE: should probably trigger the FDC irq depending on mode, i.e. use fdc_irq_w fn - if (BIT(m_fdc_2hd_ctrl, 2)) - { - m_pic2->ir2_w(0); - m_pic2->ir2_w(1); - } -} - template void pc9801vm_state::fdc_2hd_2dd_ctrl_w(u8 data) { bool prev_trig = false; @@ -1009,6 +1013,74 @@ template void pc9801vm_state::fdc_2hd_2dd_ctrl_w(u8 data) } } +// TODO: some machines (which?) mirror 0x00be to 0x04be +u8 pc9801vm_state::fdc_3mode_r(offs_t offset) +{ + // freebsd21 expects 0-fill rather than the more logical 1-fill + // on 5.25" floppies/ext. drive id checks, open bus? + // TODO: external FDD + if (m_fdc_3mode.dev_sel & 2) + return 0; + + const bool is_35hd = m_fdc_2hd->subdevice(m_fdc_3mode.dev_sel ? "1" : "0")->get_device()->get_form_factor() == floppy_image::FF_35; + + if (!is_35hd) + return 0; + + u8 res = 0xee; + + // Check if drive is in 2HD/1MB mode + if (BIT(m_fdc_mode, 1)) + res |= 1 << 4; + + if (m_fdc_3mode.access_144mb) + res |= 1 << 0; + + return res; +} + +/* + * -xx- ---- Drive specification + * -00- ---- First internal drive + * -01- ---- Second internal drive + * -10- ---- External drive + * ---x ---- Operation mode specification + * ---0 ---- no-op + * ---1 ---- Access Mode valid + * ---- ---x Access Mode specification + * ---- ---0 1MB/640KB + * ---- ---1 1.44MB + */ +void pc9801vm_state::fdc_3mode_w(offs_t offset, uint8_t data) +{ + //logerror("$4be: W %02x\n", data); + m_fdc_3mode.dev_sel = (data & 0x60) >> 5; + + // TODO: external FDD + if (m_fdc_3mode.dev_sel & 2) + return; + + if (BIT(data, 4)) + { + const bool is_35hd = m_fdc_2hd->subdevice(m_fdc_3mode.dev_sel ? "1" : "0")->get_device()->get_form_factor() == floppy_image::FF_35; + + if (!is_35hd) + return; + + floppy_image_device *floppy = m_fdc_2hd->subdevice(m_fdc_3mode.dev_sel ? "1" : "0")->get_device(); + m_fdc_3mode.access_144mb = !!(BIT(data, 0)); + if (m_fdc_3mode.access_144mb) + { + floppy->set_rpm(300); + m_fdc_2hd->set_rate(500000); + } + else + { + fdc_set_density_mode(!!BIT(m_fdc_mode, 1)); + } + } +} + void pc9801vm_state::pc9801rs_video_ff_w(offs_t offset, uint8_t data) { if(offset == 1) @@ -1136,6 +1208,7 @@ void pc9801vm_state::pc9801ux_io(address_map &map) map(0x0439, 0x0439).rw(FUNC(pc9801vm_state::dma_access_ctrl_r), FUNC(pc9801vm_state::dma_access_ctrl_w)); map(0x043c, 0x043f).w(FUNC(pc9801vm_state::pc9801rs_bank_w)); //ROM/RAM bank map(0x04a0, 0x04af).w(FUNC(pc9801vm_state::egc_w)); + map(0x04be, 0x04be).rw(FUNC(pc9801vm_state::fdc_3mode_r), FUNC(pc9801vm_state::fdc_3mode_w)); map(0x3fd8, 0x3fdf).rw(m_pit, FUNC(pit8253_device::read), FUNC(pit8253_device::write)).umask16(0xff00); } @@ -1908,16 +1981,6 @@ void pc9801vm_state::mouse_freq_w(offs_t offset, u8 data) m_mouse.freq_index = 0; } -// standard debug catch-all handler -// I/O mapping is byte smearing party, so logerror can possibly silently hide handler -// accesses if they are partially handled by an umask in the mapping. -uint8_t pc9801_state::unk_r(offs_t offset) -{ -// printf("%04x\n",offset); -// logerror("%s: I/O read access %04x\n",offset); - return 0xff; -} - /**************************************** * * UPD765 interface @@ -2116,6 +2179,8 @@ MACHINE_RESET_MEMBER(pc9801vm_state,pc9801rs) m_gate_a20 = 0; m_fdc_mode = 3; + m_fdc_3mode.dev_sel = 2; + m_fdc_3mode.access_144mb = false; fdc_set_density_mode(true); // 2HD // 0xfb on PC98XL // TODO: breaks UART setup for pc9801rs diff --git a/src/mame/nec/pc9801.h b/src/mame/nec/pc9801.h index 211edb53aea..2a3052060ee 100644 --- a/src/mame/nec/pc9801.h +++ b/src/mame/nec/pc9801.h @@ -213,7 +213,6 @@ protected: uint8_t pc9801_a0_r(offs_t offset); void pc9801_a0_w(offs_t offset, uint8_t data); - u8 unk_r(offs_t offset); uint8_t f0_r(offs_t offset); uint8_t m_nmi_ff = 0; @@ -481,11 +480,19 @@ private: emu_timer *m_fdc_timer = nullptr; u8 m_fdc_mode = 0; + struct { + u8 dev_sel; + bool access_144mb; + } m_fdc_3mode; + u8 fdc_mode_r(); void fdc_mode_w(u8 data); void fdc_set_density_mode(bool is_2hd); - protected: + // $4be, roughly around UV model + u8 fdc_3mode_r(offs_t offset); + void fdc_3mode_w(offs_t offset, uint8_t data); + struct { uint8_t pal_entry = 0; uint8_t r[16]{}, g[16]{}, b[16]{}; diff --git a/src/mame/nec/pc9821.cpp b/src/mame/nec/pc9821.cpp index 0bf40af7cbd..659d70e3257 100644 --- a/src/mame/nec/pc9821.cpp +++ b/src/mame/nec/pc9821.cpp @@ -476,7 +476,7 @@ void pc9821_state::pc9821_io(address_map &map) // map(0x043c, 0x043f) ROM/RAM bank (EPSON) map(0x0460, 0x0463).rw(FUNC(pc9821_state::window_bank_r), FUNC(pc9821_state::window_bank_w)); map(0x04a0, 0x04af).w(FUNC(pc9821_state::pc9821_egc_w)); -// map(0x04be, 0x04be) FDC "RPM" register + map(0x04be, 0x04be).rw(FUNC(pc9821_state::fdc_3mode_r), FUNC(pc9821_state::fdc_3mode_w)); // map(0x0640, 0x064f).rw(FUNC(pc9821_state::ide_cs0_r), FUNC(pc9821_state::ide_cs0_w)); // map(0x0740, 0x074f).rw(FUNC(pc9821_state::ide_cs1_r), FUNC(pc9821_state::ide_cs1_w)); // map(0x08e0, 0x08ea) / EMM SIO registers