diff options
| author | 2025-08-26 05:43:48 +0200 | |
|---|---|---|
| committer | 2025-08-26 08:57:52 +0200 | |
| commit | 0e279a2e36e70e76870aaed8ebf1c3064db5859a (patch) | |
| tree | fc78bd46cad3da8b4b8fc7c7b251503a31b87676 | |
| parent | 972a55924424a3201179a4f16c6d04f20debaa65 (diff) | |
bus/coleco/cartridge: Initial support for the 'Super Game Cartridge'
New working software list items (coleco_homebrew.xml)
-----------------------------------------------------
Gradius [Dirk Best, TechZombie/archive.org]
| -rw-r--r-- | hash/coleco_homebrew.xml | 14 | ||||
| -rw-r--r-- | scripts/src/bus.lua | 2 | ||||
| -rw-r--r-- | src/devices/bus/coleco/cartridge/exp.cpp | 7 | ||||
| -rw-r--r-- | src/devices/bus/coleco/cartridge/exp.h | 1 | ||||
| -rw-r--r-- | src/devices/bus/coleco/cartridge/sgc.cpp | 206 | ||||
| -rw-r--r-- | src/devices/bus/coleco/cartridge/sgc.h | 83 |
6 files changed, 313 insertions, 0 deletions
diff --git a/hash/coleco_homebrew.xml b/hash/coleco_homebrew.xml index 2d1ad2e5f4b..4b73cd9d75c 100644 --- a/hash/coleco_homebrew.xml +++ b/hash/coleco_homebrew.xml @@ -746,6 +746,20 @@ Unoffical software releases for the Coleco Colecovision </part> </software> + <!-- There is also a newer 2023 version --> + <software name="gradius"> + <description>Gradius</description> + <year>2016</year> + <publisher>Opcode Games</publisher> + <info name="usage" value="req. Super Game Module" /> + <part name="cart" interface="coleco_cart"> + <feature name="slot" value="sgc_1mbit" /> + <dataarea name="rom" size="131072"> + <rom name="gradius.rom" size="131072" crc="30d337e4" sha1="20a3204faf796fe8284eab0e47cb17738219c999" /> + </dataarea> + </part> + </software> + <software name="gulkave"> <description>Gulkave</description> <year>2010</year> diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 4911089d8c2..8b2297835e1 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -1223,6 +1223,8 @@ if (BUSES["COLECO_CART"]~=null) then MAME_DIR .. "src/devices/bus/coleco/cartridge/activision.h", MAME_DIR .. "src/devices/bus/coleco/cartridge/megacart.cpp", MAME_DIR .. "src/devices/bus/coleco/cartridge/megacart.h", + MAME_DIR .. "src/devices/bus/coleco/cartridge/sgc.cpp", + MAME_DIR .. "src/devices/bus/coleco/cartridge/sgc.h", MAME_DIR .. "src/devices/bus/coleco/cartridge/std.cpp", MAME_DIR .. "src/devices/bus/coleco/cartridge/std.h", MAME_DIR .. "src/devices/bus/coleco/cartridge/xin1.h", diff --git a/src/devices/bus/coleco/cartridge/exp.cpp b/src/devices/bus/coleco/cartridge/exp.cpp index 21fcfd9708a..3b5d35b9b49 100644 --- a/src/devices/bus/coleco/cartridge/exp.cpp +++ b/src/devices/bus/coleco/cartridge/exp.cpp @@ -92,6 +92,9 @@ std::pair<std::error_condition, std::string> colecovision_cartridge_slot_device: // TODO 8000/a000/c000/e000 memcpy(m_card->m_rom, get_software_region("rom"), size); } + + // signal cartridge that rom data is now available + m_card->load_done(); } return std::make_pair(std::error_condition(), std::string()); @@ -152,6 +155,7 @@ void colecovision_cartridge_slot_device::write(offs_t offset, uint8_t data, int #include "activision.h" #include "megacart.h" +#include "sgc.h" #include "std.h" #include "xin1.h" @@ -162,6 +166,9 @@ void colecovision_cartridges(device_slot_interface &device) device.option_add_internal("activision_256b", COLECOVISION_ACTIVISION_256B); device.option_add_internal("activision_32k", COLECOVISION_ACTIVISION_32K); device.option_add_internal("megacart", COLECOVISION_MEGACART); + device.option_add_internal("sgc_1mbit", COLECOVISION_SGC_1MBIT); + device.option_add_internal("sgc_2mbit", COLECOVISION_SGC_2MBIT); + device.option_add_internal("sgc_4mbit", COLECOVISION_SGC_4MBIT); device.option_add_internal("standard", COLECOVISION_STANDARD); device.option_add_internal("xin1", COLECOVISION_XIN1); } diff --git a/src/devices/bus/coleco/cartridge/exp.h b/src/devices/bus/coleco/cartridge/exp.h index 59362fff11b..2c396794a63 100644 --- a/src/devices/bus/coleco/cartridge/exp.h +++ b/src/devices/bus/coleco/cartridge/exp.h @@ -93,6 +93,7 @@ class device_colecovision_cartridge_interface : public device_interface friend class colecovision_cartridge_slot_device; public: + virtual void load_done() { }; virtual uint8_t read(offs_t offset, int _8000, int _a000, int _c000, int _e000) { return 0xff; } virtual void write(offs_t offset, uint8_t data, int _8000, int _a000, int _c000, int _e000) { } diff --git a/src/devices/bus/coleco/cartridge/sgc.cpp b/src/devices/bus/coleco/cartridge/sgc.cpp new file mode 100644 index 00000000000..23d707abb6b --- /dev/null +++ b/src/devices/bus/coleco/cartridge/sgc.cpp @@ -0,0 +1,206 @@ +// license: BSD-3-Clause +// copyright-holders: Dirk Best +/********************************************************************** + + ColecoVision 'Super Game Cartridge' emulation + + Cartridge designed by Opcode Games + + Hardware: + - Flash ROM for storage + - ATF1502AS CPLD + + Notes: + - Emulated here is what gradius needs. Other games might use + more or different features. + +**********************************************************************/ + +#include "emu.h" +#include "sgc.h" + +#define LOG_WRITES (1U << 1) +#define LOG_FLASH (1U << 2) + +#define VERBOSE (LOG_GENERAL | LOG_WRITES | LOG_FLASH) + +#include "logmacro.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +DEFINE_DEVICE_TYPE(COLECOVISION_SGC_1MBIT, colecovision_sgc_1mbit_cartridge_device, "coleco_sgc_1mbit", "ColecoVision Super Game Cartridge (1 MBit)") +DEFINE_DEVICE_TYPE(COLECOVISION_SGC_2MBIT, colecovision_sgc_2mbit_cartridge_device, "coleco_sgc_2mbit", "ColecoVision Super Game Cartridge (2 MBit)") +DEFINE_DEVICE_TYPE(COLECOVISION_SGC_4MBIT, colecovision_sgc_4mbit_cartridge_device, "coleco_sgc_4mbit", "ColecoVision Super Game Cartridge (4 MBit)") + +colecovision_sgc_cartridge_device::colecovision_sgc_cartridge_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), + device_colecovision_cartridge_interface(mconfig, *this), + m_flash(*this, "flash"), + m_flash_region(*this, "flash"), + m_slot0_bank(0), + m_slot1_bank(0), + m_slot2_bank(0), + m_slot3_bank(0), + m_flash_a16(0) +{ +} + +colecovision_sgc_1mbit_cartridge_device::colecovision_sgc_1mbit_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + colecovision_sgc_cartridge_device(mconfig, COLECOVISION_SGC_1MBIT, tag, owner, clock) +{ +} + +colecovision_sgc_2mbit_cartridge_device::colecovision_sgc_2mbit_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + colecovision_sgc_cartridge_device(mconfig, COLECOVISION_SGC_2MBIT, tag, owner, clock) +{ +} + +colecovision_sgc_4mbit_cartridge_device::colecovision_sgc_4mbit_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + colecovision_sgc_cartridge_device(mconfig, COLECOVISION_SGC_4MBIT, tag, owner, clock) +{ +} + + +//************************************************************************** +// MEMORY REGIONS +//************************************************************************** + +ROM_START( sgc_1mbit_flash ) + ROM_REGION(0x20000, "flash", ROMREGION_ERASEFF) +ROM_END + +const tiny_rom_entry *colecovision_sgc_1mbit_cartridge_device::device_rom_region() const +{ + return ROM_NAME( sgc_1mbit_flash ); +} + +ROM_START( sgc_2mbit_flash ) + ROM_REGION(0x40000, "flash", ROMREGION_ERASEFF) +ROM_END + +const tiny_rom_entry *colecovision_sgc_2mbit_cartridge_device::device_rom_region() const +{ + return ROM_NAME( sgc_2mbit_flash ); +} + +ROM_START( sgc_4mbit_flash ) + ROM_REGION(0x80000, "flash", ROMREGION_ERASEFF) +ROM_END + +const tiny_rom_entry *colecovision_sgc_4mbit_cartridge_device::device_rom_region() const +{ + return ROM_NAME( sgc_4mbit_flash ); +} + + +//************************************************************************** +// MACHINE DEFINITIONS +//************************************************************************** + +void colecovision_sgc_1mbit_cartridge_device::device_add_mconfig(machine_config &config) +{ + SST_39SF010(config, m_flash); +} + +void colecovision_sgc_2mbit_cartridge_device::device_add_mconfig(machine_config &config) +{ + SST_39SF020(config, m_flash); +} + +void colecovision_sgc_4mbit_cartridge_device::device_add_mconfig(machine_config &config) +{ + SST_39SF040(config, m_flash); +} + + +//************************************************************************** +// MACHINE EMULATION +//************************************************************************** + +void colecovision_sgc_cartridge_device::device_start() +{ + // register for save states + save_item(NAME(m_slot0_bank)); + save_item(NAME(m_slot1_bank)); + save_item(NAME(m_slot2_bank)); + save_item(NAME(m_slot3_bank)); + save_item(NAME(m_flash_a16)); +} + +void colecovision_sgc_cartridge_device::device_reset() +{ + m_slot0_bank = 0; + m_slot1_bank = 0; + m_slot2_bank = 0; + m_slot3_bank = 0; + m_flash_a16 = 0; +} + +void colecovision_sgc_cartridge_device::load_done() +{ + if (m_rom_size > m_flash_region->bytes()) + fatalerror("SGC: ROM size %u larger than flash size %u\n", m_rom_size, m_flash_region->bytes()); + + // initialize flash with provided rom data + memcpy(m_flash_region->base(), m_rom, m_rom_size); +} + +offs_t colecovision_sgc_cartridge_device::banked_address(offs_t offset) +{ + if (offset < 0xa000) + return m_slot0_bank << 13 | (offset & 0x1fff); + else if (offset < 0xc000) + return m_slot1_bank << 13 | (offset & 0x1fff); + else if (offset < 0xe000) + return m_slot2_bank << 13 | (offset & 0x1fff); + else + return m_slot3_bank << 13 | (offset & 0x1fff); +} + +uint8_t colecovision_sgc_cartridge_device::read(offs_t offset, int _8000, int _a000, int _c000, int _e000) +{ + return m_flash->read(banked_address(0x8000 | offset)); +} + +void colecovision_sgc_cartridge_device::write(offs_t offset, uint8_t data, int _8000, int _a000, int _c000, int _e000) +{ + offset |= 0x8000; + uint8_t max_banks = m_rom_size / 0x2000; + + LOGMASKED(LOG_WRITES, "write: %04x = %02x\n", offset, data); + + switch (offset) + { + case 0xfffc: + if (data < max_banks) + m_slot1_bank = data; + break; + + case 0xfffd: + if (data < max_banks) + m_slot2_bank = data; + break; + + case 0xfffe: + // gradius writes 0xaa here once, purpose? + if (data < max_banks) + m_slot3_bank = data; + break; + + case 0xffff: + // bit 0 = flash memory a16 (only when writing?) + // other bits unknown (if actually used) + m_flash_a16 = data; + break; + + default: + // write to flash + offs_t addr = (BIT(m_flash_a16, 0) << 16) | banked_address(offset); + LOGMASKED(LOG_FLASH, "flash write: %05x = %02x\n", addr, data); + m_flash->write(addr, data); + break; + } +} diff --git a/src/devices/bus/coleco/cartridge/sgc.h b/src/devices/bus/coleco/cartridge/sgc.h new file mode 100644 index 00000000000..2185a8dbb10 --- /dev/null +++ b/src/devices/bus/coleco/cartridge/sgc.h @@ -0,0 +1,83 @@ +// license: BSD-3-Clause +// copyright-holders: Dirk Best +/********************************************************************** + + ColecoVision 'Super Game Cartridge' emulation + +**********************************************************************/ + +#ifndef MAME_BUS_COLECO_CARTRIDGE_SGC_H +#define MAME_BUS_COLECO_CARTRIDGE_SGC_H + +#pragma once + +#include "exp.h" +#include "machine/intelfsh.h" + + +//************************************************************************** +// TYPE DEFINITIONS +//************************************************************************** + +class colecovision_sgc_cartridge_device : public device_t, public device_colecovision_cartridge_interface +{ +protected: + colecovision_sgc_cartridge_device(const machine_config &mconfig, device_type type, const char* tag, device_t* owner, uint32_t clock); + + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + + // cartridge interface + virtual void load_done() override; + virtual uint8_t read(offs_t offset, int _8000, int _a000, int _c000, int _e000) override; + virtual void write(offs_t offset, uint8_t data, int _8000, int _a000, int _c000, int _e000) override; + + required_device<intelfsh8_device> m_flash; + required_memory_region m_flash_region; + +private: + uint8_t m_slot0_bank; + uint8_t m_slot1_bank; + uint8_t m_slot2_bank; + uint8_t m_slot3_bank; + uint8_t m_flash_a16; + + offs_t banked_address(offs_t offset); +}; + +class colecovision_sgc_1mbit_cartridge_device : public colecovision_sgc_cartridge_device +{ +public: + colecovision_sgc_1mbit_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD; + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; +}; + +class colecovision_sgc_2mbit_cartridge_device : public colecovision_sgc_cartridge_device +{ +public: + colecovision_sgc_2mbit_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD; + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; +}; + +class colecovision_sgc_4mbit_cartridge_device : public colecovision_sgc_cartridge_device +{ +public: + colecovision_sgc_4mbit_cartridge_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD; + virtual void device_add_mconfig(machine_config &config) override ATTR_COLD; +}; + +// device type declaration +DECLARE_DEVICE_TYPE(COLECOVISION_SGC_1MBIT, colecovision_sgc_1mbit_cartridge_device) +DECLARE_DEVICE_TYPE(COLECOVISION_SGC_2MBIT, colecovision_sgc_2mbit_cartridge_device) +DECLARE_DEVICE_TYPE(COLECOVISION_SGC_4MBIT, colecovision_sgc_4mbit_cartridge_device) + +#endif // MAME_BUS_COLECO_CARTRIDGE_SGC_H |
