bus/spectrum: Added ZXBUS and NeoGS card. (#11032)

This commit is contained in:
holub 2023-04-04 14:34:27 -04:00 committed by GitHub
parent a0b859e452
commit 2a1ba144a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 344 additions and 104 deletions

View File

@ -4507,6 +4507,20 @@ if (BUSES["SPECTRUM"]~=null) then
}
end
---------------------------------------------------
--
--@src/devices/bus/spectrum/zxbus.h,BUSES["ZXBUS"] = true
---------------------------------------------------
if (BUSES["ZXBUS"]~=null) then
files {
MAME_DIR .. "src/devices/bus/spectrum/zxbus.cpp",
MAME_DIR .. "src/devices/bus/spectrum/zxbus.h",
MAME_DIR .. "src/devices/bus/spectrum/neogs.cpp",
MAME_DIR .. "src/devices/bus/spectrum/neogs.h",
}
end
---------------------------------------------------
--
--@src/devices/bus/uts_kbd/uts_kbd.h,BUSES["UTS_KBD"] = true

View File

@ -2,7 +2,7 @@
// copyright-holders:Andrei I. Holub
/*******************************************************************************************
Sound card NeoGS appropriate for playing trackers (MOD) and compressed (MP3) music on
Sound card NeoGS appropriate for playing trackers (MOD) and compressed (MP3) music on
Spectrum-compatible computers with ZXBUS slot.
Hardware:
@ -19,12 +19,11 @@ Hardware:
- Parallel working (NeoGS play music independently from ZX).
Refs:
http://nedopc.com/gs/ngs_eng.php
https://github.com/psbhlw/gs-firmware
https://8bit.yarek.pl/interface/zx.generalsound/index.html
http://nedopc.com/gs/ngs_eng.php
https://github.com/psbhlw/gs-firmware
https://8bit.yarek.pl/interface/zx.generalsound/index.html
TODO:
- ZXBUS
- SPI
- DMA
- MP3
@ -34,10 +33,15 @@ TODO:
#include "emu.h"
#include "neogs.h"
#include "cpu/z80/z80.h"
#include "machine/ram.h"
#include "sound/dac.h"
#include "speaker.h"
DEFINE_DEVICE_TYPE(NEOGS, neogs_device, "neogs", "NeoGS / General Sound")
namespace bus::spectrum::zxbus {
namespace {
ROM_START( neogs )
ROM_REGION(0x80000, "maincpu", 0)
@ -50,6 +54,64 @@ ROM_START( neogs )
ROMX_LOAD( "testrom_muchkin.rom", 0x0000, 0x80000, CRC(8ab10a88) SHA1(cff3ca96489e517568146a00412107259360d01e), ROM_BIOS(1))
ROM_END
class neogs_device : public device_t, public device_zxbus_card_interface
{
public:
neogs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, ZXBUS_NEOGS, tag, owner, clock)
, device_zxbus_card_interface(mconfig, *this)
, m_maincpu(*this, "maincpu")
, m_ram(*this, RAM_TAG)
, m_rom(*this, "maincpu")
, m_bank_rom(*this, "bank_rom")
, m_bank_ram(*this, "bank_ram")
, m_view(*this, "view")
, m_dac(*this, "dac%u", 0U)
{ }
protected:
// device_t implementation
void device_start() override;
void device_reset() override;
const tiny_rom_entry *device_rom_region() const override;
void device_add_mconfig(machine_config &config) override;
void neogsmap(address_map &map);
INTERRUPT_GEN_MEMBER(irq0_line_assert);
void map_memory(address_map &map);
void map_io(address_map &map);
void update_config();
required_device<z80_device> m_maincpu;
required_device<ram_device> m_ram;
required_region_ptr<u8> m_rom;
memory_bank_creator m_bank_rom;
memory_bank_creator m_bank_ram;
memory_view m_view;
required_device_array<dac_word_interface, 8> m_dac;
private:
template <u8 Bank> u8 ram_bank_r(offs_t offset);
template <u8 Bank> void ram_bank_w(offs_t offset, u8 data);
u8 status_r() { return m_status; }
void command_w(u8 data) { m_status |= 0x01; m_command_in = data; }
u8 data_r() { m_status &= ~0x80; return m_data_out; }
void data_w(u8 data) { m_status |= 0x80; m_data_in = data; }
void ctrl_w(u8 data);
u8 m_data_in;
u8 m_data_out;
u8 m_command_in;
u8 m_status;
u8 m_mpag;
u8 m_mpagx;
u8 m_gscfg0;
u8 m_vol[8];
};
void neogs_device::update_config()
{
@ -63,7 +125,7 @@ void neogs_device::update_config()
}
else
{
m_bank_rom->set_entry(m_mpag % (memregion("maincpu")->bytes() / 0x8000));
m_bank_rom->set_entry(m_mpag % (m_rom.bytes() / 0x8000));
m_view.disable();
}
@ -163,27 +225,36 @@ const tiny_rom_entry *neogs_device::device_rom_region() const
return ROM_NAME( neogs );
}
void neogs_device::neogsmap(address_map &map)
{
map(0x00bb, 0x00bb).mirror(0xff00).rw(FUNC(neogs_device::status_r), FUNC(neogs_device::command_w));
map(0x00b3, 0x00b3).mirror(0xff00).rw(FUNC(neogs_device::data_r), FUNC(neogs_device::data_w));
map(0x0033, 0x0033).mirror(0xff00).w(FUNC(neogs_device::ctrl_w));
}
void neogs_device::device_start()
{
if (!m_ram->started())
throw device_missing_dependencies();
throw device_missing_dependencies();
memory_region *rom = memregion("maincpu");
m_bank_rom->configure_entries(0, rom->bytes() / 0x8000, rom->base(), 0x8000);
m_bank_rom->configure_entries(0, m_rom.bytes() / 0x8000, &m_rom[0], 0x8000);
m_bank_ram->configure_entries(0, m_ram->size() / 0x8000, m_ram->pointer(), 0x8000);
m_maincpu->space(AS_PROGRAM).install_read_tap(0x6000, 0x7fff, "dac_w", [this](offs_t offset, u8 &data, u8 mem_mask)
{
if (!machine().side_effects_disabled())
{
const u8 chanel = BIT(offset, 8, BIT(m_gscfg0, 2) ? 3 : 2); // 8CHANS
const u8 sample = data ^ (m_gscfg0 & 0x80); // INV7B
const s16 out = (sample - 0x80) * (m_vol[chanel] << 2);
m_dac[chanel]->data_w(out);
if (BIT(m_gscfg0, 2) && BIT(m_gscfg0, 6)) // PAN4CH
;
}
});
m_maincpu->space(AS_PROGRAM).install_read_tap(0x6000, 0x7fff, "dac_w",
[this](offs_t offset, u8 &data, u8 mem_mask)
{
if (!machine().side_effects_disabled())
{
const u8 chanel = BIT(offset, 8, BIT(m_gscfg0, 2) ? 3 : 2); // 8CHANS
const u8 sample = data ^ (m_gscfg0 & 0x80); // INV7B
const s16 out = (sample - 0x80) * (m_vol[chanel] << 2);
m_dac[chanel]->data_w(out);
if (BIT(m_gscfg0, 2) && BIT(m_gscfg0, 6)) // PAN4CH
;
}
});
m_zxbus->install_device(0x0000, 0xffff, *this, &neogs_device::neogsmap);
}
void neogs_device::device_reset()
@ -193,3 +264,10 @@ void neogs_device::device_reset()
m_mpag = 0;
update_config();
}
} // anonymous namespace
} // namespace bus::spectrum::zxbus
DEFINE_DEVICE_TYPE_PRIVATE(ZXBUS_NEOGS, device_zxbus_card_interface, bus::spectrum::zxbus::neogs_device, "neogs", "NeoGS / General Sound")

View File

@ -0,0 +1,14 @@
// license:BSD-3-Clause
// copyright-holders:Andrei I. Holub
#ifndef MAME_SINCLAIR_NEOGS_H
#define MAME_SINCLAIR_NEOGS_H
#pragma once
#include "zxbus.h"
DECLARE_DEVICE_TYPE(ZXBUS_NEOGS, device_zxbus_card_interface)
#endif // MAME_SINCLAIR_NEOGS_H

View File

@ -0,0 +1,79 @@
// license:BSD-3-Clause
// copyright-holders:Andrei I. Holub
/*******************************************************************************************
ZXBUS device
*******************************************************************************************/
#include "emu.h"
#include "zxbus.h"
DEFINE_DEVICE_TYPE(ZXBUS_SLOT, zxbus_slot_device, "zxbus_slot", "ZXBUS slot")
zxbus_slot_device::zxbus_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: zxbus_slot_device(mconfig, ZXBUS_SLOT, tag, owner, clock)
{
}
zxbus_slot_device::zxbus_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
: device_t(mconfig, type, tag, owner, clock)
, device_single_card_slot_interface<device_zxbus_card_interface>(mconfig, *this)
, m_zxbus_bus(*this, finder_base::DUMMY_TAG)
{
}
void zxbus_slot_device::device_start()
{
device_zxbus_card_interface *const intf(get_card_device());
if (intf) intf->set_zxbusbus(*m_zxbus_bus);
m_zxbus_bus->add_slot(*this);
}
DEFINE_DEVICE_TYPE(ZXBUS, zxbus_device, "zxbus", "ZXBUS bus")
zxbus_device::zxbus_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: zxbus_device(mconfig, ZXBUS, tag, owner, clock)
{
}
zxbus_device::zxbus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, type, tag, owner, clock)
, m_iospace(*this, finder_base::DUMMY_TAG, -1)
{
}
void zxbus_device::device_start()
{
}
void zxbus_device::add_slot(zxbus_slot_device &slot)
{
m_slot_list.push_front(&slot);
}
device_zxbus_card_interface::device_zxbus_card_interface(const machine_config &mconfig, device_t &device)
: device_interface(device, "zxbus")
, m_zxbus(nullptr)
{
}
device_zxbus_card_interface::~device_zxbus_card_interface()
{
}
void device_zxbus_card_interface::interface_pre_start()
{
if (!m_zxbus)
throw device_missing_dependencies();
}
#include "neogs.h"
void zxbus_cards(device_slot_interface &device)
{
device.option_add("neogs", ZXBUS_NEOGS);
}

View File

@ -0,0 +1,127 @@
// license:BSD-3-Clause
// copyright-holders:Andrei I. Holub
/*******************************************************************************************
ZXBUS device
B A
*5 A15 1 1 A14 *4
*3 A13 2 2 A12 *2
*13 D7 3 3 +5V (guaranteed +5V only here ! )
BLK (CSDS) 4 4 DOS (DCDOS)
-not-used- 5 5 KAY = 14Mhz / SCORPION = +12V
*14 D0 6 6 GND
*15 D1 7 7 GND
*12 D2 8 8 CLK Z80 (SCORPION aka /RAS 3.5Mhz ONLY ! )
*10 D6 9 9 A0 *30
*9 D5 10 10 A1 *31
*8 D3 11 11 A2
*7 D4 12 12 A3
- 13 13 IOGE (IORQCE)
*17 NMI 14 14 GND
- 15 15 RDR(RDROM) (CSROMCE)
*19 MREQ 16 16 RS (BIT_4 OF #7FFD)
*20 IORQ 17 17 -not-used-
*21 RD 18 18 -not-used-
*22 WR 19 19 BUSRQ
-not-used- 20 20 RES *26
*24 WAIT 21 21 A7 *37
-not-used- 22 22 A6 *36
-not-used- 23 23 A5 *35
*27 M1 24 24 A4
RFRSH 25 25 CSR (CSROM)
*38 A8 26 26 BUSAK
*40 A10 27 27 A9 *39
KAY=+5V n.u. 28 28 A11 *1
KAY=+12V n.u. 29 29 n.u. KAY=+5V
GND 30 30 GND
B A
'-' - not used
'*' - Z80 CPU out
*******************************************************************************************/
#ifndef MAME_BUS_SPECTRUM_ZXBUS_H
#define MAME_BUS_SPECTRUM_ZXBUS_H
#pragma once
class zxbus_device;
class device_zxbus_card_interface;
class zxbus_slot_device : public device_t, public device_single_card_slot_interface<device_zxbus_card_interface>
{
public:
zxbus_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
template <typename T, typename U>
zxbus_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, T &&zxbus_tag, U &&slot_options, const char *dflt)
: zxbus_slot_device(mconfig, tag, owner, clock)
{
option_reset();
slot_options(*this);
set_default_option(dflt);
set_fixed(false);
m_zxbus_bus.set_tag(std::forward<T>(zxbus_tag));
}
protected:
zxbus_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
virtual void device_start() override;
required_device<zxbus_device> m_zxbus_bus;
};
DECLARE_DEVICE_TYPE(ZXBUS_SLOT, zxbus_slot_device)
class zxbus_device : public device_t
{
public:
zxbus_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
template <typename T> void set_iospace(T &&tag, int spacenum) { m_iospace.set_tag(std::forward<T>(tag), spacenum); }
template<typename T> void install_device(offs_t addrstart, offs_t addrend, T &device, void (T::*map)(class address_map &map), uint64_t unitmask = ~u64(0))
{
m_iospace->install_device(addrstart, addrend, device, map, unitmask);
}
void add_slot(zxbus_slot_device &slot);
protected:
zxbus_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
virtual void device_start() override;
required_address_space m_iospace;
std::forward_list<zxbus_slot_device *> m_slot_list;
};
DECLARE_DEVICE_TYPE(ZXBUS, zxbus_device)
class device_zxbus_card_interface : public device_interface
{
public:
virtual ~device_zxbus_card_interface();
void set_zxbusbus(zxbus_device &bus) { assert(!device().started()); m_zxbus = &bus; }
protected:
device_zxbus_card_interface(const machine_config &mconfig, device_t &device);
virtual void interface_pre_start() override;
zxbus_device *m_zxbus;
};
void zxbus_cards(device_slot_interface &device);
#endif // MAME_BUS_SPECTRUM_ZXBUS_H

View File

@ -1,70 +0,0 @@
// license:BSD-3-Clause
// copyright-holders:Andrei I. Holub
#ifndef MAME_SINCLAIR_NEOGS_H
#define MAME_SINCLAIR_NEOGS_H
#pragma once
#include "cpu/z80/z80.h"
#include "machine/ram.h"
#include "sound/dac.h"
DECLARE_DEVICE_TYPE(NEOGS, neogs_device)
class neogs_device : public device_t
{
public:
neogs_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0)
: device_t(mconfig, NEOGS, tag, owner, clock)
, m_maincpu(*this, "maincpu")
, m_ram(*this, RAM_TAG)
, m_bank_rom(*this, "bank_rom")
, m_bank_ram(*this, "bank_ram")
, m_view(*this, "view")
, m_dac(*this, "dac%u", 0U)
{ }
u8 status_r() { return m_status; };
void command_w(u8 data) { m_status |= 0x01; m_command_in = data; };
u8 data_r() { m_status &= ~0x80; return m_data_out; };
void data_w(u8 data) { m_status |= 0x80; m_data_in = data; };
void ctrl_w(u8 data);
protected:
// device-level overrides
void device_start() override;
void device_reset() override;
const tiny_rom_entry *device_rom_region() const override;
void device_add_mconfig(machine_config &config) override;
INTERRUPT_GEN_MEMBER(irq0_line_assert);
void map_memory(address_map &map);
void map_io(address_map &map);
void update_config();
required_device<z80_device> m_maincpu;
required_device<ram_device> m_ram;
memory_bank_creator m_bank_rom;
memory_bank_creator m_bank_ram;
memory_view m_view;
required_device_array<dac_word_interface, 8> m_dac;
private:
template <u8 Bank> u8 ram_bank_r(offs_t offset);
template <u8 Bank> void ram_bank_w(offs_t offset, u8 data);
u8 m_data_in;
u8 m_data_out;
u8 m_command_in;
u8 m_status;
u8 m_mpag;
u8 m_mpagx;
u8 m_gscfg0;
u8 m_vol[8];
};
#endif // MAME_SINCLAIR_NEOGS_H

View File

@ -108,9 +108,6 @@ void tsconf_state::tsconf_io(address_map &map)
map(0xffdf, 0xffdf).lr8(NAME([this]() { return ~m_io_mouse[1]->read(); }));
map(0x8000, 0x8000).mirror(0x3ffd).w("ay8912", FUNC(ay8910_device::data_w));
map(0xc000, 0xc000).mirror(0x3ffd).rw("ay8912", FUNC(ay8910_device::data_r), FUNC(ay8910_device::address_w));
map(0x00bb, 0x00bb).mirror(0xff00).rw(m_gs, FUNC(neogs_device::status_r), FUNC(neogs_device::command_w));
map(0x00b3, 0x00b3).mirror(0xff00).rw(m_gs, FUNC(neogs_device::data_r), FUNC(neogs_device::data_w));
map(0x0033, 0x0033).mirror(0xff00).w(m_gs, FUNC(neogs_device::ctrl_w));
}
void tsconf_state::tsconf_switch(address_map &map)
@ -277,6 +274,11 @@ void tsconf_state::tsconf(machine_config &config)
m_maincpu->set_vblank_int("screen", FUNC(tsconf_state::tsconf_vblank_interrupt));
zxbus_device &zxbus(ZXBUS(config, "zxbus", 0));
zxbus.set_iospace("maincpu", AS_IO);
ZXBUS_SLOT(config, "zxbus1", 0, "zxbus", zxbus_cards, "neogs");
//ZXBUS_SLOT(config, "zxbus2", 0, "zxbus", zxbus_cards, nullptr);
m_ram->set_default_size("4096K");
GLUKRS(config, m_glukrs);
@ -302,8 +304,6 @@ void tsconf_state::tsconf(machine_config &config)
.add_route(1, "rspeaker", 0.25)
.add_route(2, "rspeaker", 0.50);
NEOGS(config, m_gs);
PALETTE(config, "palette", FUNC(tsconf_state::tsconf_palette), 256);
m_screen->set_raw(14_MHz_XTAL / 2, 448, with_hblank(0), 448, 320, with_vblank(0), 320);
subdevice<gfxdecode_device>("gfxdecode")->set_info(gfx_tsconf);

View File

@ -12,13 +12,13 @@
#include "spec128.h"
#include "beta_m.h"
#include "glukrs.h"
#include "tsconfdma.h"
#include "beta_m.h"
#include "bus/spectrum/zxbus.h"
#include "machine/pckeybrd.h"
#include "machine/spi_sdcard.h"
#include "neogs.h"
#include "tsconfdma.h"
#include "tilemap.h"
@ -38,8 +38,7 @@ public:
m_palette(*this, "palette"),
m_gfxdecode(*this, "gfxdecode"),
m_cram(*this, "cram"),
m_sfile(*this, "sfile"),
m_gs(*this, "gs")
m_sfile(*this, "sfile")
{
}
@ -215,7 +214,6 @@ private:
tilemap_t *m_ts_tilemap[3]{};
required_device<ram_device> m_cram;
required_device<ram_device> m_sfile;
required_device<neogs_device> m_gs;
};
/*----------- defined in drivers/tsconf.c -----------*/