summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Dirk Best <mail@dirk-best.de>2025-08-26 05:43:48 +0200
committer Dirk Best <mail@dirk-best.de>2025-08-26 08:57:52 +0200
commit0e279a2e36e70e76870aaed8ebf1c3064db5859a (patch)
treefc78bd46cad3da8b4b8fc7c7b251503a31b87676
parent972a55924424a3201179a4f16c6d04f20debaa65 (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.xml14
-rw-r--r--scripts/src/bus.lua2
-rw-r--r--src/devices/bus/coleco/cartridge/exp.cpp7
-rw-r--r--src/devices/bus/coleco/cartridge/exp.h1
-rw-r--r--src/devices/bus/coleco/cartridge/sgc.cpp206
-rw-r--r--src/devices/bus/coleco/cartridge/sgc.h83
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