From 6e43812f6032b779d5732e166b09e630cd115efc Mon Sep 17 00:00:00 2001 From: etabeta78 Date: Tue, 17 May 2016 12:35:54 +0200 Subject: [PATCH] gba.cpp: Added preliminary support for the 3D Matrix Memory Controller used by 64MB video cartridges. Disney Collection 2 works, while other dumps still fail (possibly due to reason unrelated to the mapper emulation...) [Fabio Priuli] --- hash/gba.xml | 12 ++--- src/devices/bus/gba/gba_slot.cpp | 9 ++++ src/devices/bus/gba/gba_slot.h | 10 ++++- src/devices/bus/gba/rom.cpp | 75 ++++++++++++++++++++++++++++++++ src/devices/bus/gba/rom.h | 21 +++++++++ src/mame/drivers/gba.cpp | 11 ++++- 6 files changed, 130 insertions(+), 8 deletions(-) diff --git a/hash/gba.xml b/hash/gba.xml index 516975a1b92..bb0e67d0abc 100644 --- a/hash/gba.xml +++ b/hash/gba.xml @@ -15503,13 +15503,13 @@ Note: In the AGB-E05-XX and AGB-E06-XX pcbs, the chip name is hidden under the b - - + Game Boy Advance Video - Disney Channel Collection - Volume 2 (USA) 2004? Majesco + @@ -15612,52 +15612,52 @@ Note: In the AGB-E05-XX and AGB-E06-XX pcbs, the chip name is hidden under the b - Game Boy Advance Video - Shrek (USA) 2004? Nintendo + - Game Boy Advance Video - Shrek 2 (USA) 2004? Nintendo + - Game Boy Advance Video - Shark Tale (USA, Rev. 6) 2004? Nintendo + - Game Boy Advance Video - Shark Tale (USA, Rev. 5) 2004? Nintendo + diff --git a/src/devices/bus/gba/gba_slot.cpp b/src/devices/bus/gba/gba_slot.cpp index b32c6c21af4..5ed54717275 100644 --- a/src/devices/bus/gba/gba_slot.cpp +++ b/src/devices/bus/gba/gba_slot.cpp @@ -54,7 +54,10 @@ void device_gba_cart_interface::rom_alloc(UINT32 size, const char *tag) // we always alloc 32MB of rom region! m_rom = (UINT32 *)device().machine().memory().region_alloc(std::string(tag).append(GBASLOT_ROM_REGION_TAG).c_str(), 0x2000000, 4, ENDIANNESS_LITTLE)->base(); else + { m_rom = (UINT32 *)device().machine().memory().region_alloc(std::string(tag).append(GBASLOT_ROM_REGION_TAG).c_str(), 0x4000000, 4, ENDIANNESS_LITTLE)->base(); + m_romhlp = (UINT32 *)device().machine().memory().region_alloc(std::string(tag).append(GBAHELP_ROM_REGION_TAG).c_str(), 0x2000000, 4, ENDIANNESS_LITTLE)->base(); + } m_rom_size = size; } } @@ -137,6 +140,7 @@ static const gba_slot slot_list[] = { GBA_FLASH, "gba_flash" }, { GBA_FLASH512, "gba_flash_512" }, { GBA_FLASH1M, "gba_flash_1m" }, + { GBA_3DMATRIX, "gba_3dmatrix" }, }; static int gba_get_pcb_id(const char *slot) @@ -219,6 +223,8 @@ bool gba_cart_slot_device::call_load() memcpy(ROM + 0x1000000, ROM, 0x1000000); break; } + if (size == 0x4000000) + memcpy((UINT8 *)m_cart->get_romhlp_base(), ROM, 0x2000000); if (m_cart->get_nvram_size()) battery_load(m_cart->get_nvram_base(), m_cart->get_nvram_size(), 0x00); @@ -397,6 +403,9 @@ int gba_cart_slot_device::get_cart_type(UINT8 *ROM, UINT32 len) break; } + if (len == 0x4000000) + type = GBA_3DMATRIX; + return type; } /*------------------------------------------------- diff --git a/src/devices/bus/gba/gba_slot.h b/src/devices/bus/gba/gba_slot.h index 11810ecd960..a3908730180 100644 --- a/src/devices/bus/gba/gba_slot.h +++ b/src/devices/bus/gba/gba_slot.h @@ -18,7 +18,8 @@ enum GBA_EEPROM64, GBA_FLASH, GBA_FLASH512, - GBA_FLASH1M + GBA_FLASH1M, + GBA_3DMATRIX }; @@ -35,12 +36,15 @@ public: virtual DECLARE_READ32_MEMBER(read_rom) { return 0xffffffff; } virtual DECLARE_READ32_MEMBER(read_ram) { return 0xffffffff; } virtual DECLARE_WRITE32_MEMBER(write_ram) {}; + virtual DECLARE_WRITE32_MEMBER(write_mapper) {}; void rom_alloc(UINT32 size, const char *tag); void nvram_alloc(UINT32 size); UINT32* get_rom_base() { return m_rom; } + UINT32* get_romhlp_base() { return m_romhlp; } UINT32* get_nvram_base() { return &m_nvram[0]; } UINT32 get_rom_size() { return m_rom_size; } + UINT32 get_romhlp_size() { return m_romhlp_size; } UINT32 get_nvram_size() { return m_nvram.size()*sizeof(UINT32); } void set_rom_size(UINT32 val) { m_rom_size = val; } @@ -49,6 +53,8 @@ public: // internal state UINT32 *m_rom; // this points to the cart rom region UINT32 m_rom_size; // this is the actual game size, not the rom region size! + UINT32 *m_romhlp; + UINT32 m_romhlp_size; std::vector m_nvram; }; @@ -98,6 +104,7 @@ public: virtual DECLARE_READ32_MEMBER(read_rom); virtual DECLARE_READ32_MEMBER(read_ram); virtual DECLARE_WRITE32_MEMBER(write_ram); + virtual DECLARE_WRITE32_MEMBER(write_mapper) { if (m_cart) return m_cart->write_mapper(space, offset, data, mem_mask); }; protected: @@ -117,6 +124,7 @@ extern const device_type GBA_CART_SLOT; ***************************************************************************/ #define GBASLOT_ROM_REGION_TAG ":cart:rom" +#define GBAHELP_ROM_REGION_TAG ":cart:romhlp" #define MCFG_GBA_CARTRIDGE_ADD(_tag,_slot_intf,_def_slot) \ MCFG_DEVICE_ADD(_tag, GBA_CART_SLOT, 0) \ diff --git a/src/devices/bus/gba/rom.cpp b/src/devices/bus/gba/rom.cpp index 8e857dfe004..b4b2899024f 100644 --- a/src/devices/bus/gba/rom.cpp +++ b/src/devices/bus/gba/rom.cpp @@ -27,6 +27,7 @@ const device_type GBA_ROM_EEPROM = &device_creator; const device_type GBA_ROM_EEPROM64 = &device_creator; const device_type GBA_ROM_FLASH = &device_creator; const device_type GBA_ROM_FLASH1M = &device_creator; +const device_type GBA_ROM_3DMATRIX = &device_creator; gba_rom_device::gba_rom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) @@ -68,6 +69,11 @@ gba_rom_flash1m_device::gba_rom_flash1m_device(const machine_config &mconfig, co { } +gba_rom_3dmatrix_device::gba_rom_3dmatrix_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : gba_rom_device(mconfig, GBA_ROM_3DMATRIX, "GBA Carts + 3D Matrix Memory Mapper", tag, owner, clock, "gba_3dmatrix", __FILE__) +{ +} + //------------------------------------------------- // mapper specific start/reset @@ -106,6 +112,20 @@ void gba_rom_eeprom64_device::device_start() m_eeprom = std::make_unique(machine(), (UINT8*)get_nvram_base(), get_nvram_size(), 14); } +void gba_rom_3dmatrix_device::device_start() +{ + save_item(NAME(m_src)); + save_item(NAME(m_dst)); + save_item(NAME(m_nblock)); +} + +void gba_rom_3dmatrix_device::device_reset() +{ + m_src = 0; + m_dst = 0; + m_nblock = 0; +} + /*------------------------------------------------- mapper specific handlers @@ -436,3 +456,58 @@ WRITE32_MEMBER(gba_rom_eeprom64_device::write_ram) m_eeprom->write(data); } + + +/*------------------------------------------------- + Carts with 3D Matrix Memory controller + + Used by Video carts with 64MB ROM chips + Emulation based on the reverse engineering efforts + by endrift + + The Memory controller basically behaves like a DMA + chip by writing first source and destination address, + then the number of 512K blocks to copy and finally + by issuing the transfer command. + Disney Collection 2 carts uses command 0x01 to start + the transfer, other carts might use 0x11 but currently + they die before getting to the mapper communication + (CPU emulation issue? cart mapping issue? still unknown) + + To investigate: + - why the other carts fail + - which addresses might be used by the mapper + (Disney Collection 2 uses 0x08800180-0x0880018f + but it might well be possible to issue commands + in an extended range...) + - which bus addresses can be used by the mapper + (currently we restrict the mapping in the range + 0x08000000-0x09ffffff but maybe also the rest of + the cart "range" is accessible...) + -------------------------------------------------*/ + +WRITE32_MEMBER(gba_rom_3dmatrix_device::write_mapper) +{ + //printf("mapper write 0x%.8X - 0x%X\n", offset, data); + switch (offset & 3) + { + case 0: + if (data == 0x1) // transfer data + memcpy((UINT8 *)m_romhlp + m_dst, (UINT8 *)m_rom + m_src, m_nblock * 0x200); + else + printf("Unknown mapper command 0x%X\n", data); + break; + case 1: + m_src = data; + break; + case 2: + if (data >= 0xa000000) + printf("Unknown transfer destination 0x%X\n", data); + m_dst = (data & 0x1ffffff); + break; + case 3: + default: + m_nblock = data; + break; + } +} diff --git a/src/devices/bus/gba/rom.h b/src/devices/bus/gba/rom.h index f9a3c16cb2e..b43875af862 100644 --- a/src/devices/bus/gba/rom.h +++ b/src/devices/bus/gba/rom.h @@ -161,6 +161,26 @@ private: }; +// ======================> gba_rom_3dmatrix_device + +class gba_rom_3dmatrix_device : public gba_rom_device +{ +public: + // construction/destruction + gba_rom_3dmatrix_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // reading and writing + virtual DECLARE_WRITE32_MEMBER(write_mapper) override; + +private: + UINT32 m_src, m_dst, m_nblock; +}; + + // device type definition extern const device_type GBA_ROM_STD; extern const device_type GBA_ROM_SRAM; @@ -168,6 +188,7 @@ extern const device_type GBA_ROM_EEPROM; extern const device_type GBA_ROM_EEPROM64; extern const device_type GBA_ROM_FLASH; extern const device_type GBA_ROM_FLASH1M; +extern const device_type GBA_ROM_3DMATRIX; diff --git a/src/mame/drivers/gba.cpp b/src/mame/drivers/gba.cpp index 5998a83d2c2..64620d1f156 100644 --- a/src/mame/drivers/gba.cpp +++ b/src/mame/drivers/gba.cpp @@ -2109,7 +2109,7 @@ void gba_state::machine_start() m_maincpu->space(AS_PROGRAM).install_read_bank(0x08000000, 0x09ffffff, 0, 0, "rom1"); m_maincpu->space(AS_PROGRAM).install_read_bank(0x0a000000, 0x0bffffff, 0, 0, "rom2"); m_maincpu->space(AS_PROGRAM).install_read_bank(0x0c000000, 0x0cffffff, 0, 0, "rom3"); - + std::string region_tag; memory_region *cart_rom = memregion(region_tag.assign(m_cart->tag()).append(GBASLOT_ROM_REGION_TAG).c_str()); @@ -2118,6 +2118,7 @@ void gba_state::machine_start() membank("rom2")->set_base(cart_rom->base()); membank("rom3")->set_base(cart_rom->base()); + // add nvram to save state m_cart->save_nvram(); @@ -2144,6 +2145,13 @@ void gba_state::machine_start() m_maincpu->space(AS_PROGRAM).install_read_handler(0xe000000, 0xe01ffff, read32_delegate(FUNC(gba_cart_slot_device::read_ram),(gba_cart_slot_device*)m_cart)); m_maincpu->space(AS_PROGRAM).install_write_handler(0xe000000, 0xe01ffff, write32_delegate(FUNC(gba_cart_slot_device::write_ram),(gba_cart_slot_device*)m_cart)); } + if (m_cart->get_type() == GBA_3DMATRIX) + { + m_maincpu->space(AS_PROGRAM).install_write_handler(0x08800000, 0x088001ff, write32_delegate(FUNC(gba_cart_slot_device::write_mapper),(gba_cart_slot_device*)m_cart)); + memory_region *cart_romhlp = memregion(region_tag.assign(m_cart->tag()).append(GBAHELP_ROM_REGION_TAG).c_str()); + membank("rom1")->set_base(cart_romhlp->base()); + } + } save_item(NAME(m_DISPSTAT)); @@ -2245,6 +2253,7 @@ static SLOT_INTERFACE_START(gba_cart) SLOT_INTERFACE_INTERNAL("gba_flash", GBA_ROM_FLASH) // Panasonic SLOT_INTERFACE_INTERNAL("gba_flash_512", GBA_ROM_FLASH) // Panasonic SLOT_INTERFACE_INTERNAL("gba_flash_1m", GBA_ROM_FLASH1M) // Sanyo + SLOT_INTERFACE_INTERNAL("gba_3dmatrix", GBA_ROM_3DMATRIX) SLOT_INTERFACE_END