mirror of
https://github.com/holub/mame
synced 2025-04-21 16:01:56 +03:00
pgm2: memcard reader now uses image_device stuff, cards can be inserted / removed and get saved [Metallic, David Haywood]
promoted China set of Oriental Legend 2 to working promoted Knights of Valour 2 New Legend to working as each game/region requires a valid default card in order to save said cards are part of romset. (there's probably a cleaner way to do the device finder stuff but I forgot and can't find reference)
This commit is contained in:
parent
afcba799fc
commit
caed83833c
@ -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",
|
||||
|
@ -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 )
|
||||
|
@ -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<cpu_device> m_maincpu;
|
||||
@ -139,6 +142,13 @@ private:
|
||||
required_device<palette_device> m_bg_palette;
|
||||
required_device<palette_device> m_tx_palette;
|
||||
required_device<timer_device> m_mcu_timer;
|
||||
|
||||
optional_device<pgm2_memcard_device> m_memcard0;
|
||||
optional_device<pgm2_memcard_device> m_memcard1;
|
||||
optional_device<pgm2_memcard_device> m_memcard2;
|
||||
optional_device<pgm2_memcard_device> m_memcard3;
|
||||
pgm2_memcard_device *m_memcard_device[4];
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
91
src/mame/machine/pgm2_memcard.cpp
Normal file
91
src/mame/machine/pgm2_memcard.cpp
Normal file
@ -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;
|
||||
}
|
67
src/mame/machine/pgm2_memcard.h
Normal file
67
src/mame/machine/pgm2_memcard.h
Normal file
@ -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
|
Loading…
Reference in New Issue
Block a user