diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua index f0af50fd870..9a5fed7b765 100644 --- a/scripts/target/mame/arcade.lua +++ b/scripts/target/mame/arcade.lua @@ -1950,6 +1950,8 @@ files { MAME_DIR .. "src/mame/drivers/pgm2.cpp", MAME_DIR .. "src/mame/video/pgm2.cpp", MAME_DIR .. "src/mame/includes/pgm2.h", + MAME_DIR .. "src/mame/machine/pgm2_memcard.cpp", + MAME_DIR .. "src/mame/machine/pgm2_memcard.h", MAME_DIR .. "src/mame/drivers/pgm3.cpp", MAME_DIR .. "src/mame/drivers/spoker.cpp", MAME_DIR .. "src/mame/machine/igs036crypt.cpp", diff --git a/src/mame/drivers/pgm2.cpp b/src/mame/drivers/pgm2.cpp index f7e9dba632e..794de03f295 100644 --- a/src/mame/drivers/pgm2.cpp +++ b/src/mame/drivers/pgm2.cpp @@ -144,26 +144,14 @@ TIMER_DEVICE_CALLBACK_MEMBER(pgm2_state::igs_interrupt2) m_arm_aic->set_irq(0x46); } -static const uint8_t orleg2_china_card[32] = { - 0xA2, 0x13, 0x10, 0x91, 0x05, 0x0C, 0x81, 0x15, 0x10, 0x00, 0x00, 0x03, 0x00, 0x49, 0x47, 0x53, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xD2, 0x76, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -#ifdef UNUSED_DEFINITION -static const uint8_t kov2nl_china_card[32] = { - 0xA2, 0x13, 0x10, 0x91, 0x05, 0x0C, 0x81, 0x15, 0x06, 0x00, 0x00, 0x04, 0x00, 0x49, 0x47, 0x53, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xD2, 0x76, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; -#endif - // "MPU" MCU HLE starts here -// TODO: make data cards using image_interface -// command delays is far not correct, might not work in other games -// command results probably either incorrect (except for explicit checked bytes) -void pgm2_state::mcu_command(bool is_command) +// command delays are far from correct, might not work in other games +// command results probably incorrect (except for explicit checked bytes) +void pgm2_state::mcu_command(address_space &space, bool is_command) { uint8_t cmd = m_mcu_regs[0] & 0xff; -// if (is_command && cmd != 0xf6) -// logerror("MCU command %08x %08x\n", m_mcu_regs[0], m_mcu_regs[1]); + // if (is_command && cmd != 0xf6) + // logerror("MCU command %08x %08x\n", m_mcu_regs[0], m_mcu_regs[1]); if (is_command) { @@ -199,11 +187,11 @@ void pgm2_state::mcu_command(bool is_command) m_mcu_result0 = cmd; m_mcu_result1 = 0; } - break; - // unknown / unimplemented, all C0-C9 commands is IC Card RW related - // (m_mcu_regs[0] >> 8) & 0xff - target RW unit (player) + break; + // unknown / unimplemented, all C0-C9 commands is IC Card RW related + // (m_mcu_regs[0] >> 8) & 0xff - target RW unit (player) case 0xc0: // insert card or/and check card presence. result: F7 - ok, F4 - no card - if (!m_have_card[arg1]) + if (m_memcard_device[arg1 & 3]->present() == -1) status = 0xf4; m_mcu_result0 = cmd; break; @@ -211,11 +199,20 @@ void pgm2_state::mcu_command(bool is_command) m_mcu_result0 = cmd; break; case 0xc2: // read data to shared ram, args - offset, len - memcpy(&m_shareram[(~m_share_bank & 1) * 128], &m_card_data[arg1][arg2], arg3); + for (int i = 0; i < arg3; i++) + { + if (m_memcard_device[arg1 & 3]->present() != -1) + m_shareram[i + (~m_share_bank & 1) * 128] = m_memcard_device[arg1 & 3]->read(space, arg2 + i); + } + m_mcu_result0 = cmd; break; case 0xc3: // save data from shared ram, args - offset, len - memcpy(&m_card_data[arg1][arg2], &m_shareram[(~m_share_bank & 1) * 128], arg3); + for (int i = 0; i < arg3; i++) + { + if (m_memcard_device[arg1 & 3]->present() != -1) + m_memcard_device[arg1 & 3]->write(space, arg2 + i, m_shareram[i + (~m_share_bank & 1) * 128]); + } m_mcu_result0 = cmd; break; case 0xc7: // get card ID?, no args, result1 expected to be fixed value for new card @@ -223,7 +220,9 @@ void pgm2_state::mcu_command(bool is_command) m_mcu_result0 = cmd; break; case 0xc8: // write byte, args - offset, data byte - m_card_data[arg1][arg2] = arg3; + if (m_memcard_device[arg1 & 3]->present() != -1) + m_memcard_device[arg1 & 3]->write(space, arg2, arg3); + m_mcu_result0 = cmd; break; case 0xc4: // not used @@ -262,9 +261,9 @@ WRITE32_MEMBER(pgm2_state::mcu_w) COMBINE_DATA(&m_mcu_regs[reg]); if (reg == 2 && m_mcu_regs[2]) // irq to mcu - mcu_command(true); + mcu_command(space, true); if (reg == 5 && m_mcu_regs[5]) // ack to mcu (written at the end of irq handler routine) - mcu_command(false); + mcu_command(space, false); } static ADDRESS_MAP_START( pgm2_map, AS_PROGRAM, 32, pgm2_state ) @@ -428,6 +427,11 @@ void pgm2_state::machine_start() save_item(NAME(m_mcu_last_cmd)); save_item(NAME(m_shareram)); save_item(NAME(m_share_bank)); + + m_memcard_device[0] = m_memcard0; + m_memcard_device[1] = m_memcard1; + m_memcard_device[2] = m_memcard2; + m_memcard_device[3] = m_memcard3; } void pgm2_state::machine_reset() @@ -436,11 +440,6 @@ void pgm2_state::machine_reset() m_realspritekey = 0; m_mcu_last_cmd = 0; m_share_bank = 0; - - m_have_card[0] = true; - m_have_card[1] = m_have_card[2] = m_have_card[3] = false; - memcpy(m_card_data[0], orleg2_china_card, sizeof(orleg2_china_card)); -// memcpy(m_card_data[0], kov2nl_china_card, sizeof(kov2nl_china_card)); } static const gfx_layout tiles8x8_layout = @@ -516,6 +515,13 @@ static MACHINE_CONFIG_START( pgm2 ) MCFG_YMZ774_ADD("ymz774", 16384000) // is clock correct ? MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) + + MCFG_PGM2_MEMCARD_ADD("memcard_p1") + MCFG_PGM2_MEMCARD_ADD("memcard_p2") + MCFG_PGM2_MEMCARD_ADD("memcard_p3") + MCFG_PGM2_MEMCARD_ADD("memcard_p4") + + MACHINE_CONFIG_END /* using macros for the video / sound roms because the locations never change between sets, and @@ -578,7 +584,9 @@ MACHINE_CONFIG_END #define ORLEG2_INTERNAL_CHINA \ ROM_REGION( 0x04000, "maincpu", 0 ) \ - ROM_LOAD( "xyj2_cn.igs036", 0x00000000, 0x0004000, CRC(bcce7641) SHA1(c3b5cf6e9f6eae09b6785314777a52b34c3c7657) ) + ROM_LOAD( "xyj2_cn.igs036", 0x00000000, 0x0004000, CRC(bcce7641) SHA1(c3b5cf6e9f6eae09b6785314777a52b34c3c7657) ) \ + ROM_REGION( 0x100, "default_card", 0 ) \ + ROM_LOAD( "blank_orleg2_china_card.pg2", 0x000, 0x100, CRC(099156f0) SHA1(a621c9772a98719c657bba3a1bf235487eb78615) ) #define ORLEG2_INTERNAL_OVERSEAS \ ROM_REGION( 0x04000, "maincpu", 0 ) \ @@ -658,7 +666,10 @@ ROM_END #define KOV2NL_INTERNAL_CHINA \ ROM_REGION( 0x04000, "maincpu", 0 ) \ - ROM_LOAD( "gsyx_igs036_china.rom", 0x00000000, 0x0004000, CRC(e09fe4ce) SHA1(c0cac64ef8727cbe79d503ec4df66ddb6f2c925e) ) + ROM_LOAD( "gsyx_igs036_china.rom", 0x00000000, 0x0004000, CRC(e09fe4ce) SHA1(c0cac64ef8727cbe79d503ec4df66ddb6f2c925e) ) \ + ROM_REGION( 0x100, "default_card", 0 ) \ + ROM_LOAD( "blank_kov2nl_china_card.pg2", 0x000, 0x100, CRC(91786244) SHA1(ac0ce11b46c19ffe21f6b94bc83ef061f547b591) ) + ROM_START( kov2nl ) KOV2NL_INTERNAL_CHINA @@ -1024,14 +1035,14 @@ GAME( 2007, orleg2, 0, pgm2, pgm2, pgm2_state, orleg2, GAME( 2007, orleg2_103, orleg2, pgm2, pgm2, pgm2_state, orleg2, ROT0, "IGS", "Oriental Legend 2 (V103, Oversea)", 0 ) GAME( 2007, orleg2_101, orleg2, pgm2, pgm2, pgm2_state, orleg2, ROT0, "IGS", "Oriental Legend 2 (V101, Oversea)", 0 ) -GAME( 2007, orleg2_104cn, orleg2, pgm2, pgm2, pgm2_state, orleg2, ROT0, "IGS", "Oriental Legend 2 (V104, China)", MACHINE_NOT_WORKING ) -GAME( 2007, orleg2_103cn, orleg2, pgm2, pgm2, pgm2_state, orleg2, ROT0, "IGS", "Oriental Legend 2 (V103, China)", MACHINE_NOT_WORKING ) -GAME( 2007, orleg2_101cn, orleg2, pgm2, pgm2, pgm2_state, orleg2, ROT0, "IGS", "Oriental Legend 2 (V101, China)", MACHINE_NOT_WORKING ) +GAME( 2007, orleg2_104cn, orleg2, pgm2, pgm2, pgm2_state, orleg2, ROT0, "IGS", "Oriental Legend 2 (V104, China)", 0 ) +GAME( 2007, orleg2_103cn, orleg2, pgm2, pgm2, pgm2_state, orleg2, ROT0, "IGS", "Oriental Legend 2 (V103, China)", 0 ) +GAME( 2007, orleg2_101cn, orleg2, pgm2, pgm2, pgm2_state, orleg2, ROT0, "IGS", "Oriental Legend 2 (V101, China)", 0 ) // Knights of Valour 2 New Legend -GAME( 2008, kov2nl, 0, pgm2, pgm2, pgm2_state, kov2nl, ROT0, "IGS", "Knights of Valour 2 New Legend (V302, China)", MACHINE_NOT_WORKING ) -GAME( 2008, kov2nl_301, kov2nl, pgm2, pgm2, pgm2_state, kov2nl, ROT0, "IGS", "Knights of Valour 2 New Legend (V301, China)", MACHINE_NOT_WORKING ) -GAME( 2008, kov2nl_300, kov2nl, pgm2, pgm2, pgm2_state, kov2nl, ROT0, "IGS", "Knights of Valour 2 New Legend (V300, China)", MACHINE_NOT_WORKING ) // was dumped from a Taiwan board tho +GAME( 2008, kov2nl, 0, pgm2, pgm2, pgm2_state, kov2nl, ROT0, "IGS", "Knights of Valour 2 New Legend (V302, China)", 0 ) +GAME( 2008, kov2nl_301, kov2nl, pgm2, pgm2, pgm2_state, kov2nl, ROT0, "IGS", "Knights of Valour 2 New Legend (V301, China)", 0 ) +GAME( 2008, kov2nl_300, kov2nl, pgm2, pgm2, pgm2_state, kov2nl, ROT0, "IGS", "Knights of Valour 2 New Legend (V300, China)", 0 ) // was dumped from a Taiwan board tho // Dodonpachi Daioujou Tamashii - should be a V200 too GAME( 2010, ddpdojh, 0, pgm2, pgm2, pgm2_state, ddpdojh, ROT270, "IGS", "Dodonpachi Daioujou Tamashii (V201, China)", MACHINE_NOT_WORKING ) diff --git a/src/mame/includes/pgm2.h b/src/mame/includes/pgm2.h index c25e0b91add..c31ee657c4a 100644 --- a/src/mame/includes/pgm2.h +++ b/src/mame/includes/pgm2.h @@ -16,6 +16,7 @@ #include "machine/nvram.h" #include "machine/timer.h" #include "machine/atmel_arm_aic.h" +#include "machine/pgm2_memcard.h" class pgm2_state : public driver_device { @@ -39,7 +40,11 @@ public: m_sp_palette(*this, "sp_palette"), m_bg_palette(*this, "bg_palette"), m_tx_palette(*this, "tx_palette"), - m_mcu_timer(*this, "mcu_timer") + m_mcu_timer(*this, "mcu_timer"), + m_memcard0(*this, "memcard_p1"), + m_memcard1(*this, "memcard_p2"), + m_memcard2(*this, "memcard_p3"), + m_memcard3(*this, "memcard_p4") { } DECLARE_READ32_MEMBER(unk_startup_r); @@ -116,9 +121,7 @@ private: uint32_t m_mcu_result0; uint32_t m_mcu_result1; uint8_t m_mcu_last_cmd; - void mcu_command(bool is_command); - uint8_t m_card_data[4][0x100]; - bool m_have_card[4]; + void mcu_command(address_space &space, bool is_command); // devices required_device m_maincpu; @@ -139,6 +142,13 @@ private: required_device m_bg_palette; required_device m_tx_palette; required_device m_mcu_timer; + + optional_device m_memcard0; + optional_device m_memcard1; + optional_device m_memcard2; + optional_device m_memcard3; + pgm2_memcard_device *m_memcard_device[4]; + }; #endif diff --git a/src/mame/machine/pgm2_memcard.cpp b/src/mame/machine/pgm2_memcard.cpp new file mode 100644 index 00000000000..73755409294 --- /dev/null +++ b/src/mame/machine/pgm2_memcard.cpp @@ -0,0 +1,91 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood, Miodrag Milanovic +/********************************************************************* + + pgm2_memcard.cpp + + PGM2 Memory card functions. + (based on ng_memcard.cpp) + +*********************************************************************/ + +#include "emu.h" +#include "emuopts.h" + +#include "pgm2_memcard.h" + + +// device type definition +DEFINE_DEVICE_TYPE(PGM2_MEMCARD, pgm2_memcard_device, "pgm2_memcard", "PGM2 Memory Card") + +//------------------------------------------------- +// pgm2_memcard_device - constructor +//------------------------------------------------- + +pgm2_memcard_device::pgm2_memcard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, PGM2_MEMCARD, tag, owner, clock) + , device_image_interface(mconfig, *this) +{ +} + + +//------------------------------------------------- +// device_start - device-specific startup +//------------------------------------------------- + +void pgm2_memcard_device::device_start() +{ + save_item(NAME(m_memcard_data)); +} + +/*------------------------------------------------- + memcard_insert - insert an existing memory card + with the given index +-------------------------------------------------*/ + +image_init_result pgm2_memcard_device::call_load() +{ + if(length() != 0x100) + return image_init_result::FAIL; + + fseek(0, SEEK_SET); + size_t ret = fread(m_memcard_data, 0x100); + if(ret != 0x100) + return image_init_result::FAIL; + + return image_init_result::PASS; +} + +void pgm2_memcard_device::call_unload() +{ + fseek(0, SEEK_SET); + fwrite(m_memcard_data, 0x100); +} + +image_init_result pgm2_memcard_device::call_create(int format_type, util::option_resolution *format_options) +{ + // cards must contain valid defaults for each game / region or they don't work? + memory_region *rgn = memregion("^default_card"); + + if (!rgn) + return image_init_result::FAIL; + + memcpy(m_memcard_data, rgn->base(), 0x100); + + size_t ret = fwrite(m_memcard_data, 0x100); + if(ret != 0x100) + return image_init_result::FAIL; + + return image_init_result::PASS; +} + + +READ8_MEMBER(pgm2_memcard_device::read) +{ + return m_memcard_data[offset]; +} + +WRITE8_MEMBER(pgm2_memcard_device::write) +{ + m_memcard_data[offset] = data; +} diff --git a/src/mame/machine/pgm2_memcard.h b/src/mame/machine/pgm2_memcard.h new file mode 100644 index 00000000000..0aa4d2adb04 --- /dev/null +++ b/src/mame/machine/pgm2_memcard.h @@ -0,0 +1,67 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood, Miodrag Milanovic +/********************************************************************* + + pgm2_memcard.h + + PGM2 Memory card functions. + (based on ng_memcard.h) + +*********************************************************************/ +#ifndef MAME_MACHINE_PGM2_MEMCARD_H +#define MAME_MACHINE_PGM2_MEMCARD_H + +#pragma once + + +//************************************************************************** +// INTERFACE CONFIGURATION MACROS +//************************************************************************** + +#define MCFG_PGM2_MEMCARD_ADD(_tag) \ + MCFG_DEVICE_ADD(_tag, PGM2_MEMCARD, 0) + +/*************************************************************************** + FUNCTION PROTOTYPES +***************************************************************************/ + +// ======================> pgm2_memcard_device + +class pgm2_memcard_device : public device_t, + public device_image_interface +{ +public: + // construction/destruction + pgm2_memcard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual iodevice_t image_type() const override { return IO_MEMCARD; } + + virtual bool is_readable() const override { return true; } + virtual bool is_writeable() const override { return true; } + virtual bool is_creatable() const override { return true; } + virtual bool must_be_loaded() const override { return false; } + virtual bool is_reset_on_load() const override { return false; } + virtual const char *file_extensions() const override { return "pg2,bin,mem"; } + + virtual image_init_result call_load() override; + virtual void call_unload() override; + virtual image_init_result call_create(int format_type, util::option_resolution *format_options) override; + + // device-level overrides + virtual void device_start() override; + + DECLARE_READ8_MEMBER(read); + DECLARE_WRITE8_MEMBER(write); + + /* returns the index of the current memory card, or -1 if none */ + int present() { return is_loaded() ? 0 : -1; } +private: + uint8_t m_memcard_data[0x100]; +}; + + +// device type definition +DECLARE_DEVICE_TYPE(PGM2_MEMCARD, pgm2_memcard_device) + + +#endif // MAME_MACHINE_PGM2_MEMCARD_H