diff options
| author | 2025-07-19 01:25:58 +0200 | |
|---|---|---|
| committer | 2025-07-19 01:25:58 +0200 | |
| commit | ce9d7e7c0af05898ef4e8ee3891c865b2f5b4c2b (patch) | |
| tree | 7555694cad255e5d4269df0601ed8ea75ff86b4c | |
| parent | d7b502021065ef33769369b27a7c3e9f240f5ee9 (diff) | |
sharp/mz5500.cpp: add DMAC, first Z80CTC, AY8912, attempt to hookup FDC signals
| -rw-r--r-- | src/mame/sharp/mz5500.cpp | 146 |
1 files changed, 131 insertions, 15 deletions
diff --git a/src/mame/sharp/mz5500.cpp b/src/mame/sharp/mz5500.cpp index bf3cccc44ba..f5ba568c164 100644 --- a/src/mame/sharp/mz5500.cpp +++ b/src/mame/sharp/mz5500.cpp @@ -1,23 +1,29 @@ // license:BSD-3-Clause // copyright-holders:Robbbert -/*************************************************************************** +/************************************************************************************************** Sharp MZ-6500 +TODO: +- Fix FDC boot (error 12 in selftest, tanks performance, never output a meaningful byte from DMAC) -****************************************************************************/ +**************************************************************************************************/ #include "emu.h" #include "cpu/i86/i86.h" #include "cpu/i86/i286.h" #include "imagedev/floppy.h" +#include "machine/am9517a.h" #include "machine/pic8259.h" #include "machine/upd765.h" +#include "machine/z80ctc.h" +#include "sound/ay8910.h" #include "video/upd7220.h" #include "emupal.h" #include "screen.h" #include "softlist_dev.h" +#include "speaker.h" namespace { @@ -28,21 +34,30 @@ public: : driver_device(mconfig, type, tag) , m_maincpu(*this, "maincpu") , m_pic(*this, "pic_%u", 1U) + , m_dmac(*this, "dmac") + , m_ctc(*this, "ctc") , m_hgdc(*this, "upd7220") , m_vram(*this, "videoram") , m_palette(*this, "palette") , m_fdc(*this, "fdc") + , m_floppy(*this, "fdc:%u", 0U) + , m_psg(*this, "psg") { } void mz6500(machine_config &config); + DECLARE_INPUT_CHANGED_MEMBER(nmi_reset_cb); protected: required_device<cpu_device> m_maincpu; required_device_array<pic8259_device, 2> m_pic; + required_device<am9517a_device> m_dmac; + required_device<z80ctc_device> m_ctc; required_device<upd7220_device> m_hgdc; required_shared_ptr<u16> m_vram; required_device<palette_device> m_palette; required_device<upd765a_device> m_fdc; + optional_device_array<floppy_connector, 4> m_floppy; + required_device<ay8912_device> m_psg; void io_map(address_map &map) ATTR_COLD; virtual void mem_map(address_map &map) ATTR_COLD; @@ -54,6 +69,15 @@ private: void machine_start() override ATTR_COLD; UPD7220_DISPLAY_PIXELS_MEMBER( hgdc_display_pixels ); void upd7220_map(address_map &map) ATTR_COLD; + + void psg_porta_w(u8 data); + + u8 dma_read_byte(offs_t offset); + void dma_write_byte(offs_t offset, u8 data); + void set_dma_channel(int channel, int state); + + u8 m_dma_offset[4]; + u8 m_dma_channel; }; class mz6550_state : public mz6500_state @@ -108,12 +132,16 @@ void mz6500_state::mem_map(address_map &map) void mz6500_state::io_map(address_map &map) { map.unmap_value_high(); -// map(0x0000, 0x000f) i8237 dma + map(0x0000, 0x000f).rw(m_dmac, FUNC(am9517a_device::read), FUNC(am9517a_device::write)); // map(0x0010, 0x001f) i8255 map(0x0020, 0x0021).mirror(0xe).m(m_fdc, FUNC(upd765a_device::map)); map(0x0030, 0x0033).mirror(0xc).rw(m_pic[0], FUNC(pic8259_device::read), FUNC(pic8259_device::write)).umask16(0x00ff); map(0x0040, 0x0043).mirror(0xc).rw(m_pic[1], FUNC(pic8259_device::read), FUNC(pic8259_device::write)).umask16(0x00ff); -// map(0x0050, 0x0050) segment byte for DMA + map(0x0050, 0x005f).lw8(NAME([this] (u8 data) { + // TODO: no way to select different segments? + for (int ch = 0; ch < 4; ch ++) + m_dma_offset[ch] = data >> 4; + })); map(0x0060, 0x0061).portr("SYSA"); // map(0x0070, 0x0070) system port C // map(0x00cd, 0x00cd) MZ-1R32 @@ -123,9 +151,10 @@ void mz6500_state::io_map(address_map &map) // map(0x0130, 0x013f) video register // map(0x0140, 0x015f) palette pens // map(0x0200, 0x020f) z80sio -// map(0x0210, 0x021f) z80ctc + // TODO: second ctc at 0x214-0x217, just one for MZ-5500 + map(0x0210, 0x0213).mirror(0x8).rw(m_ctc, FUNC(z80ctc_device::read), FUNC(z80ctc_device::write)); // map(0x0220, 0x022f) rp5c01 -// map(0x0230, 0x023f) ay-3-8912 + map(0x0230, 0x0231).mirror(0xe).rw(m_psg, FUNC(ay8912_device::data_r), FUNC(ay8912_device::data_address_w)); // map(0x0240, 0x0240) z80ctc vector ack // map(0x0250, 0x0250) z80sio vector ack // map(0x0270, 0x0270) system port B @@ -139,6 +168,12 @@ void mz6550_state::mem_map(address_map &map) map(0xff8000, 0xffffff).rom().region("ipl", 0); } +INPUT_CHANGED_MEMBER(mz6500_state::nmi_reset_cb) +{ + if (newval) + m_maincpu->pulse_input_line(INPUT_LINE_NMI, attotime::zero); +} + // TODO: mz5500 is slightly different // (SW3-4-5 was originally a drive selection option) @@ -147,9 +182,8 @@ static INPUT_PORTS_START( mz6500 ) PORT_DIPNAME( 0x01, 0x01, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x00, DEF_STR( On ) ) + // /RSTSW, front panel + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_CHANGED_MEMBER(DEVICE_SELF, FUNC(mz6500_state::nmi_reset_cb), 0) PORT_NAME("Reset Switch") PORT_DIPNAME( 0x04, 0x04, "Display resolution" ) PORT_DIPLOCATION("SW:1") PORT_DIPSETTING( 0x04, "High resolution (400)" ) PORT_DIPSETTING( 0x00, "Medium resolution (200)" ) @@ -176,6 +210,14 @@ INPUT_PORTS_END void mz6500_state::machine_start() { + m_fdc->set_rate(500000); + for (int sl_i = 0; sl_i < 4; sl_i++) + { + if (m_floppy[sl_i]->get_device() != nullptr) + { + m_floppy[sl_i]->get_device()->set_rpm(300); + } + } } void mz6500_state::machine_reset() @@ -193,11 +235,58 @@ void mz6500_state::upd7220_map(address_map &map) map(0x00000, 0x3ffff).ram().share("videoram"); } +uint8_t mz6500_state::dma_read_byte(offs_t offset) +{ + address_space &program = m_maincpu->space(AS_PROGRAM); + offs_t addr = (m_dma_offset[m_dma_channel] << 16) | offset; + return program.read_byte(addr); +} + + +void mz6500_state::dma_write_byte(offs_t offset, uint8_t data) +{ + address_space &program = m_maincpu->space(AS_PROGRAM); + offs_t addr = (m_dma_offset[m_dma_channel] << 16) | offset; +// printf("%05x %d -> %02x\n", addr, m_dma_channel, data); + program.write_byte(addr, data); +} + +void mz6500_state::set_dma_channel(int channel, int state) +{ + if (!state) m_dma_channel = channel; +} + + +void mz6500_state::psg_porta_w(u8 data) +{ + // SL0-SL3 + for (int sl_i = 0; sl_i < 4; sl_i ++) + { + // TODO: can it multiselect? + if (BIT(data, sl_i)) + { + if (m_floppy[sl_i]->get_device() != nullptr) + { + // MON + //m_fdc->set_floppy(m_floppy[sl_i]->get_device()); + m_floppy[sl_i]->get_device()->mon_w(BIT(data, 4)); + } + break; + } + } + + // TODO: MA0-MA2 memory banking + MA0-MA1 trap ir7 + // m_pic[0]->ir7_w(BIT(!data, 5)); + // m_pic[1]->ir7_w(BIT(!data, 6)); + // set_bank((data & 0xe0) >> 5); +} + void mz6500_state::mz6500(machine_config &config) { // MZ-5500: 5 MHz // MZ-5600 onward: 8 or 5 MHz modes, user settable + // TODO: clocks for peripherals I8086(config, m_maincpu, 8000000); m_maincpu->set_addrmap(AS_PROGRAM, &mz6500_state::mem_map); m_maincpu->set_addrmap(AS_IO, &mz6500_state::io_map); @@ -212,6 +301,25 @@ void mz6500_state::mz6500(machine_config &config) m_pic[1]->out_int_callback().set(m_pic[0], FUNC(pic8259_device::ir6_w)); m_pic[1]->in_sp_callback().set_constant(0); + AM9517A(config, m_dmac, 5000000); +// m_dmac->dreq_active_low(); + m_dmac->out_hreq_callback().set([this] (int state) { + m_maincpu->set_input_line(INPUT_LINE_HALT, state ? ASSERT_LINE : CLEAR_LINE); + m_dmac->hack_w(state); + }); + m_dmac->out_eop_callback().set([this] (int state) { m_fdc->tc_w(state);}); + m_dmac->in_memr_callback().set(FUNC(mz6500_state::dma_read_byte)); + m_dmac->out_memw_callback().set(FUNC(mz6500_state::dma_write_byte)); + m_dmac->in_ior_callback<1>().set(m_fdc, FUNC(upd765a_device::dma_r)); + m_dmac->out_iow_callback<1>().set(m_fdc, FUNC(upd765a_device::dma_w)); + m_dmac->out_dack_callback<0>().set([this] (int state) { set_dma_channel(0, state); }); + m_dmac->out_dack_callback<1>().set([this] (int state) { set_dma_channel(1, state); }); + m_dmac->out_dack_callback<2>().set([this] (int state) { set_dma_channel(2, state); }); + m_dmac->out_dack_callback<3>().set([this] (int state) { set_dma_channel(3, state); }); + + Z80CTC(config, m_ctc, 8000000 / 2); + m_ctc->intr_callback().set(m_pic[0], FUNC(pic8259_device::ir5_w)); + screen_device &screen(SCREEN(config, "screen", SCREEN_TYPE_RASTER)); screen.set_refresh_hz(50); screen.set_vblank_time(ATTOSECONDS_IN_USEC(2500)); /* not accurate */ @@ -220,19 +328,27 @@ void mz6500_state::mz6500(machine_config &config) screen.set_visarea(0, 640-1, 0, 480-1); PALETTE(config, "palette").set_entries(8); - UPD7220(config, m_hgdc, 8000000 / 3); // unk clock + UPD7220(config, m_hgdc, 5000000 / 2); m_hgdc->set_addrmap(0, &mz6500_state::upd7220_map); m_hgdc->set_display_pixels(FUNC(mz6500_state::hgdc_display_pixels)); m_hgdc->vsync_wr_callback().set(m_pic[0], FUNC(pic8259_device::ir0_w)); - UPD765A(config, m_fdc, 8000000, true, true); + UPD765A(config, m_fdc, 8000000, false, true); m_fdc->intrq_wr_callback().set(m_pic[1], FUNC(pic8259_device::ir1_w)); -// m_fdc->drq_wr_callback().set(m_dmac, FUNC(am9517a_device::dreq1_w)); + m_fdc->drq_wr_callback().set(m_dmac, FUNC(am9517a_device::dreq1_w)); FLOPPY_CONNECTOR(config, "fdc:0", mz6500_floppies, "525hd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true); FLOPPY_CONNECTOR(config, "fdc:1", mz6500_floppies, "525hd", floppy_image_device::default_mfm_floppy_formats).enable_sound(true); - + FLOPPY_CONNECTOR(config, "fdc:2", mz6500_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats).enable_sound(true); + FLOPPY_CONNECTOR(config, "fdc:3", mz6500_floppies, nullptr, floppy_image_device::default_mfm_floppy_formats).enable_sound(true); SOFTWARE_LIST(config, "flop_list").set_original("mz5500_flop"); + + SPEAKER(config, "mono").front_center(); + + // TODO: clock, discrete mixing + AY8912(config, m_psg, 3.579545_MHz_XTAL / 2); + m_psg->port_a_write_callback().set(FUNC(mz6500_state::psg_porta_w)); + m_psg->add_route(ALL_OUTPUTS, "mono", 0.25); } void mz6550_state::mz6550(machine_config &config) @@ -275,5 +391,5 @@ ROM_END // MZ-5500 should fit here // Released as MZ-5600 in U.K. -COMP( 1984, mz6500, 0, 0, mz6500, mz6500, mz6500_state, empty_init, "Sharp", "MZ-6500", MACHINE_NOT_WORKING | MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE ) -COMP( 1985, mz6550, mz6500, 0, mz6550, mz6500, mz6550_state, empty_init, "Sharp", "MZ-6550", MACHINE_NOT_WORKING | MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE ) +COMP( 1984, mz6500, 0, 0, mz6500, mz6500, mz6500_state, empty_init, "Sharp", "MZ-6500", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND ) +COMP( 1985, mz6550, mz6500, 0, mz6550, mz6500, mz6550_state, empty_init, "Sharp", "MZ-6550", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND ) |
