New WORKING game

--------------------
Lucky Boom [f205v, David Haywood]

Refactoring of the PGM protection [David Haywood, iq_132]
This commit is contained in:
Angelo Salese 2012-03-25 13:19:50 +00:00
parent 58eb388fd5
commit 83cde9101e
14 changed files with 3941 additions and 3604 deletions

6
.gitattributes vendored
View File

@ -4286,6 +4286,12 @@ src/mame/machine/pckeybrd.c svneol=native#text/plain
src/mame/machine/pcshare.c svneol=native#text/plain
src/mame/machine/pgmcrypt.c svneol=native#text/plain
src/mame/machine/pgmprot.c svneol=native#text/plain
src/mame/machine/pgmprot1.c svneol=native#text/plain
src/mame/machine/pgmprot2.c svneol=native#text/plain
src/mame/machine/pgmprot3.c svneol=native#text/plain
src/mame/machine/pgmprot4.c svneol=native#text/plain
src/mame/machine/pgmprot5.c svneol=native#text/plain
src/mame/machine/pgmprot6.c svneol=native#text/plain
src/mame/machine/pitnrun.c svneol=native#text/plain
src/mame/machine/playch10.c svneol=native#text/plain
src/mame/machine/psx.c svneol=native#text/plain

View File

@ -1,4 +1,4 @@
/* IGS ARM7 (IGS027A) based Mahjong / Gambling platform
/* IGS ARM7 (IGS027A) based Mahjong / Gambling platform(s)
Driver by Xing Xing
These games use the IGS027A processor.
@ -242,48 +242,6 @@ static const UINT8 sdwx_tab[] =
0x12,0x56,0x97,0x26,0x1D,0x5F,0xA7,0xF8,0x89,0x3F,0x14,0x36,0x72,0x3B,0x48,0x7B,
0xF1,0xED,0x72,0xB7,0x7A,0x56,0x05,0xDE,0x7B,0x27,0x6D,0xCF,0x33,0x4C,0x14,0x86,
};
static void sdwx_decrypt(running_machine &machine)
{
int i;
UINT16 *src = (UINT16 *) machine.region("user1")->base();
int rom_size = 0x80000;
for(i=0; i<rom_size/2; i++) {
UINT16 x = src[i];
if((i & 0x00480) != 0x00080)
x ^= 0x0001;
if((i & 0x004008) == 0x004008)
x ^= 0x0002;
// if((i & 0x000030) == 0x000010)
// x ^= 0x0004;
if((i & 0x000242) != 0x000042)
x ^= 0x0008;
if((i & 0x08100) == 0x08000)
x ^= 0x0010;
if((i & 0x022004) != 0x000004)
x ^= 0x0020;
if((i & 0x11800) != 0x10000)
x ^= 0x0040;
if((i & 0x004820) == 0x004820)
x ^= 0x0080;
x ^= sdwx_tab[(i >> 1) & 0xff] << 8;
src[i] = x;
}
}
@ -416,14 +374,6 @@ MACHINE_CONFIG_END
static DRIVER_INIT( sdwx )
{
sdwx_decrypt(machine);
sdwx_gfx_decrypt(machine);
logerror("init OK!\n");
}
/***************************************************************************
@ -690,7 +640,7 @@ ROM_START( gonefsh2 )
ROM_REGION( 0x400000, "gfx2", 0 )
ROM_LOAD( "gfii_cg.u17", 0x000000, 0x200000, CRC(2568359c) SHA1(f1f240246e53496bf624c84f7cae3edb9675579f) )
ROM_REGION( 0x200000, "unknown", 0 )
ROM_REGION( 0x200000, "oki", 0 )
ROM_LOAD( "gfii_sp.u13", 0x00000, 0x080000, CRC(61da1d58) SHA1(0a79578f0daf15f0efe2b0eeac59a60d8372a644) )
ROM_END
@ -760,7 +710,7 @@ IGS 0027 - Custom programmed ARM9
ROM_START( chessc2 )
ROM_REGION( 0x04000, "maincpu", 0 )
/* Internal rom of IGS027A ARM based MCU */
ROM_LOAD( "gonefsh2_igs027a", 0x00000, 0x4000, NO_DUMP )
ROM_LOAD( "chessc2_igs027a", 0x00000, 0x4000, NO_DUMP )
ROM_REGION( 0x80000, "user1", 0 ) // external ARM data / prg
ROM_LOAD( "ccii_v-707uso.u12", 0x000000, 0x80000, CRC(5937b67b) SHA1(967b3adf6f5bf92d63ec460d595e473898a78372) )
@ -771,12 +721,257 @@ ROM_START( chessc2 )
ROM_REGION( 0x400000, "gfx2", 0 )
ROM_LOAD( "ccii_cg.u17", 0x000000, 0x200000, CRC(47e45157) SHA1(4459799a4a6c30a2d0a3ad9ac54e92b62221e10b) )
ROM_REGION( 0x200000, "unknown", 0 )
ROM_REGION( 0x200000, "oki", 0 )
ROM_LOAD( "ccii_sp.u13", 0x00000, 0x080000, CRC(220a7b71) SHA1(7dab7baa97c20b83763cf46ef0a6e5e8c4d6a348) )
ROM_END
ROM_START( haunthig )
ROM_REGION( 0x04000, "maincpu", 0 )
/* Internal rom of IGS027A ARM based MCU */
ROM_LOAD( "haunthig_igs027a", 0x00000, 0x4000, NO_DUMP )
ROM_REGION( 0x80000, "user1", 0 ) // external ARM data / prg
ROM_LOAD( "hauntedhouse_ver-101us.u34", 0x000000, 0x80000, CRC(4bf045d4) SHA1(78c848fd69961df8d9b75f92ad57c3534fbf08db) )
ROM_REGION( 0x80000, "gfx1", 0 )
ROM_LOAD( "haunted-h_text.u15", 0x000000, 0x80000, CRC(c23f48c8) SHA1(0cb1b6c61611a081ae4a3c0be51812045ff632fe) )
// are these PGM-like sprites?
ROM_REGION( 0x400000, "gfx2", 0 )
ROM_LOAD( "haunted-h_cg.u32", 0x000000, 0x400000, CRC(e0ea10e6) SHA1(e81be78fea93e72d4b1f4c0b58560bda46cf7948) )
ROM_REGION( 0x400000, "gfx3", 0 )
ROM_LOAD( "haunted-h_ext.u12", 0x000000, 0x400000, CRC(662eb883) SHA1(831ebe29e1e7a8b2c2fff7fbc608975771c3486c) )
ROM_REGION( 0x200000, "oki", 0 )
ROM_LOAD( "haunted-h_sp.u3", 0x00000, 0x200000, CRC(fe3fcddf) SHA1(ac57ab6d4e4883747c093bd19d0025cf6588cb2c) )
ROM_END
static void pgm_create_dummy_internal_arm_region(running_machine &machine)
{
UINT16 *temp16 = (UINT16 *)machine.region("maincpu")->base();
// fill with RX 14
int i;
for (i=0;i<0x4000/2;i+=2)
{
temp16[i] = 0xff1e;
temp16[i+1] = 0xe12f;
}
// jump straight to external area
temp16[(0x0000)/2] = 0xd088;
temp16[(0x0002)/2] = 0xe59f;
temp16[(0x0004)/2] = 0x0680;
temp16[(0x0006)/2] = 0xe3a0;
temp16[(0x0008)/2] = 0xff10;
temp16[(0x000a)/2] = 0xe12f;
temp16[(0x0090)/2] = 0x0400;
temp16[(0x0092)/2] = 0x1000;
}
static void sdwx_decrypt(running_machine &machine)
{
int i;
UINT16 *src = (UINT16 *) machine.region("user1")->base();
int rom_size = 0x80000;
for(i=0; i<rom_size/2; i++)
{
UINT16 x = src[i];
if((i & 0x000480) != 0x000080) x ^= 0x0001;
if((i & 0x004008) == 0x004008) x ^= 0x0002;
if((i & 0x000030) == 0x000010) x ^= 0x0004;
if((i & 0x000242) != 0x000042) x ^= 0x0008;
if((i & 0x008100) == 0x008000) x ^= 0x0010;
if((i & 0x022004) != 0x000004) x ^= 0x0020;
if((i & 0x011800) != 0x010000) x ^= 0x0040;
if((i & 0x004820) == 0x004820) x ^= 0x0080;
x ^= sdwx_tab[(i >> 1) & 0xff] << 8;
src[i] = x;
}
}
static const UINT8 hauntedh_tab[0x100] = {
0x49, 0x47, 0x53, 0x30, 0x32, 0x35, 0x34, 0x52, 0x44, 0x34, 0x30, 0x36, 0x30, 0x35, 0x32, 0x36,
0x6C, 0x65, 0x33, 0xFD, 0x7A, 0x71, 0x3D, 0xB8, 0x07, 0xF1, 0x86, 0x96, 0x19, 0x5A, 0xA2, 0x05,
0x49, 0xB1, 0xED, 0x2E, 0x7C, 0x7A, 0x65, 0x8B, 0xE1, 0xE3, 0xC8, 0xAA, 0x2B, 0x32, 0xEE, 0x3F,
0x10, 0x6C, 0x69, 0x70, 0x02, 0x47, 0x5B, 0x5D, 0x2D, 0x52, 0x97, 0xEF, 0xB1, 0x63, 0xFB, 0xE3,
0x21, 0x41, 0x0C, 0x17, 0x3C, 0x93, 0xD4, 0x13, 0xEB, 0x08, 0xF9, 0xDB, 0x7A, 0xC8, 0x1E, 0xF4,
0x1B, 0x1B, 0x7F, 0xB4, 0x98, 0x59, 0xC8, 0xCF, 0x58, 0x12, 0x36, 0x1F, 0x96, 0x7D, 0xF0, 0xB3,
0xDC, 0x26, 0xA8, 0x1C, 0xC6, 0xD4, 0x6E, 0xF3, 0xF5, 0xB9, 0xD4, 0xAF, 0x52, 0xDD, 0x48, 0xA5,
0x85, 0xCC, 0xAD, 0x60, 0xB4, 0x7F, 0x3C, 0x24, 0x80, 0x88, 0x9B, 0xBD, 0x3E, 0x82, 0x3B, 0x8D,
0x73, 0xB8, 0xF7, 0xD5, 0x92, 0x15, 0xeb, 0x43, 0xF9, 0x4C, 0x91, 0xBD, 0x29, 0x48, 0x22, 0x6D,
0x45, 0xD6, 0x2C, 0x0D, 0xCE, 0x91, 0x70, 0x74, 0x9D, 0x0E, 0xFE, 0x62, 0x22, 0x49, 0x94, 0x88,
0xDB, 0x50, 0x33, 0xDB, 0x18, 0x2E, 0x03, 0x1B, 0xED, 0x1A, 0x69, 0x9E, 0x78, 0xE1, 0x66, 0x62,
0x54, 0x91, 0x33, 0x52, 0x5E, 0x67, 0x1B, 0xD9, 0xA7, 0xFB, 0x98, 0xA5, 0xBA, 0xAA, 0xB1, 0xBD,
0x0F, 0x44, 0x93, 0xC6, 0xCF, 0xF7, 0x6F, 0x91, 0xCA, 0x7B, 0x93, 0xEA, 0xB6, 0x7F, 0xCC, 0x9C,
0xAB, 0x54, 0xFB, 0xC8, 0xDB, 0xD9, 0xF5, 0x68, 0x96, 0xA7, 0xA1, 0x1F, 0x7D, 0x7D, 0x4C, 0x43,
0x06, 0xED, 0x50, 0x2D, 0x30, 0x48, 0xE6, 0xC0, 0x88, 0xC8, 0x48, 0x38, 0x5D, 0xFC, 0x0a, 0x35,
0x3F, 0x79, 0xBA, 0x07, 0xBE, 0xBF, 0xB7, 0x3B, 0x61, 0x69, 0x4F, 0x67, 0xE5, 0x9A, 0x1D, 0x33
};
static void hauntedh_decrypt(running_machine &machine)
{
int i;
UINT16 *src = (UINT16 *) machine.region("user1")->base();
int rom_size = 0x080000;
for(i=0; i<rom_size/2; i++) {
UINT16 x = src[i];
if ((i & 0x040480) != 0x000080) x ^= 0x0001;
// if ((i & 0x104008) == 0x104008) x ^= 0x0002;
// if ((i & 0x080030) == 0x080010) x ^= 0x0004;
if ((i & 0x000042) != 0x000042) x ^= 0x0008;
// if ((i & 0x048100) == 0x048000) x ^= 0x0010;
if ((i & 0x002004) != 0x000004) x ^= 0x0020;
if ((i & 0x001800) != 0x000000) x ^= 0x0040;
if ((i & 0x004820) == 0x004820) x ^= 0x0080;
x ^= hauntedh_tab[(i>> 1) & 0xff] << 8;
src[i] = x;
}
}
static const UINT8 chessc2_tab[0x100] = {
0x49, 0x47, 0x53, 0x30, 0x30, 0x38, 0x32, 0x52, 0x44, 0x34, 0x30, 0x32, 0x31, 0x32, 0x31, 0x31,
0x28, 0xCA, 0x9C, 0xAD, 0xBB, 0x2D, 0xF0, 0x41, 0x6E, 0xCE, 0xAD, 0x73, 0xAE, 0x1C, 0xD1, 0x14,
0x6F, 0x9A, 0x75, 0x18, 0xA8, 0x91, 0x68, 0xe4, 0x09, 0xF4, 0x0F, 0xD7, 0xFF, 0x93, 0x7D, 0x1B,
0xEB, 0x84, 0xce, 0xAD, 0x9E, 0xCF, 0xC9, 0xAB, 0x18, 0x59, 0xb6, 0xde, 0x82, 0x13, 0x7C, 0x88,
0x69, 0x63, 0xFF, 0x6F, 0x3C, 0xD2, 0xB9, 0x29, 0x09, 0xF8, 0x97, 0xAA, 0x74, 0xA5, 0x16, 0x0D,
0xF9, 0x51, 0x9E, 0x9f, 0x63, 0xC6, 0x1E, 0x32, 0x8C, 0x0C, 0xE9, 0xA0, 0x56, 0x95, 0xD1, 0x9D,
0xEA, 0xA9, 0x82, 0xC3, 0x30, 0x15, 0x21, 0xD8, 0x8F, 0x10, 0x25, 0x61, 0xE6, 0x6D, 0x75, 0x6D,
0xCB, 0x08, 0xC3, 0x9B, 0x03, 0x6A, 0x28, 0x6D, 0x42, 0xBF, 0x00, 0xd2, 0x24, 0xFA, 0x08, 0xEE,
0x6B, 0x46, 0xB7, 0x2C, 0x7B, 0xB0, 0xDA, 0x86, 0x13, 0x14, 0x73, 0x14, 0x4D, 0x45, 0xD3, 0xD4,
0xD9, 0x80, 0xF5, 0xB8, 0x76, 0x13, 0x1E, 0xF6, 0xB1, 0x4A, 0xB3, 0x8B, 0xE2, 0x9A, 0x5A, 0x11,
0x64, 0x11, 0x55, 0xC3, 0x14, 0xFD, 0x1B, 0xCe, 0x0C, 0xDC, 0x38, 0xDA, 0xA1, 0x84, 0x66, 0xD9,
0x9b, 0x93, 0xED, 0x0F, 0xB4, 0x19, 0x38, 0x62, 0x53, 0x85, 0xB9, 0xE5, 0x89, 0xCd, 0xFE, 0x9E,
0x4D, 0xE2, 0x14, 0x9F, 0xF4, 0x53, 0x1C, 0x46, 0xf4, 0x40, 0x2C, 0xCC, 0xDa, 0x82, 0x69, 0x15,
0x88, 0x18, 0x62, 0xB7, 0xB4, 0xD5, 0xAF, 0x4B, 0x9E, 0x48, 0xCA, 0xF4, 0x11, 0xEC, 0x2D, 0x2C,
0x9D, 0x91, 0xAD, 0xDA, 0x13, 0x0A, 0x16, 0x86, 0x41, 0x18, 0x08, 0x01, 0xef, 0x97, 0x11, 0x1f,
0x1A, 0xE7, 0x0C, 0xC9, 0x6D, 0x9D, 0xB9, 0x49, 0x0B, 0x6B, 0x9E, 0xD4, 0x72, 0x4D, 0x1D, 0x59
};
static void chessc2_decrypt(running_machine &machine)
{
int i;
UINT16 *src = (UINT16 *) machine.region("user1")->base();
int rom_size = 0x80000;
for(i=0; i<rom_size/2; i++) {
UINT16 x = src[i];
if ((i & 0x040480) != 0x000080) x ^= 0x0001;
if ((i & 0x004008) == 0x004008) x ^= 0x0002;
// if ((i & 0x080030) == 0x080010) x ^= 0x0004;
if ((i & 0x000242) != 0x000042) x ^= 0x0008;
if ((i & 0x008100) == 0x008000) x ^= 0x0010;
if ((i & 0x002004) != 0x000004) x ^= 0x0020; // correct??
if ((i & 0x011800) != 0x010000) x ^= 0x0040;
if ((i & 0x004820) == 0x004820) x ^= 0x0080;
x ^= chessc2_tab[(i>> 1) & 0xff] << 8;
src[i] = x;
}
}
static const UINT8 klxyj_tab[0x100] = {
0x49, 0x47, 0x53, 0x30, 0x30, 0x30, 0x38, 0x52, 0x44, 0x34, 0x30, 0x31, 0x30, 0x39, 0x32, 0x34,
0x3F, 0x0F, 0x66, 0x9A, 0xBF, 0x0D, 0x06, 0x55, 0x09, 0x01, 0xEB, 0x72, 0xEB, 0x9B, 0x89, 0xFA,
0x24, 0xD1, 0x5D, 0xCA, 0xE6, 0x8A, 0x8C, 0xE0, 0x92, 0x8D, 0xBF, 0xE4, 0xAF, 0xAA, 0x3E, 0xFA,
0x2B, 0x27, 0x4B, 0xC7, 0xD6, 0x6D, 0xC1, 0xC2, 0x1C, 0xF4, 0xED, 0xBD, 0x03, 0x6C, 0xAD, 0xB3,
0x65, 0x2D, 0xC7, 0xD3, 0x6E, 0xE0, 0x8C, 0xCE, 0x59, 0x6F, 0xAE, 0x5E, 0x66, 0x2B, 0x5E, 0x17,
0x20, 0x3D, 0xA9, 0x72, 0xCD, 0x4F, 0x14, 0x17, 0x35, 0x7B, 0x77, 0x6B, 0x98, 0x73, 0x17, 0x5A,
0xEA, 0xF2, 0x07, 0x66, 0x51, 0x64, 0xC1, 0xF0, 0xE2, 0xD1, 0x00, 0xC6, 0x97, 0x0F, 0xE0, 0xEE,
0x94, 0x28, 0x39, 0xB2, 0x9B, 0x0A, 0x38, 0xED, 0xCC, 0x6E, 0x40, 0x94, 0xA2, 0x0A, 0x00, 0x88,
0x2B, 0xFA, 0xD5, 0x9A, 0x87, 0x6C, 0x62, 0xDF, 0xA4, 0x8B, 0x6D, 0x37, 0x38, 0xAE, 0xFD, 0x18,
0xFF, 0xC2, 0xB2, 0xA0, 0x37, 0xF5, 0x64, 0xDB, 0x59, 0xA5, 0x00, 0x51, 0x19, 0x88, 0x9F, 0xD4,
0xA0, 0x1C, 0xE7, 0x88, 0x08, 0x51, 0xA7, 0x33, 0x19, 0x75, 0xAE, 0xC7, 0x42, 0x61, 0xEC, 0x2D,
0xDB, 0xE2, 0xCC, 0x54, 0x9A, 0x6A, 0xD1, 0x7A, 0x53, 0xF8, 0x6F, 0xBA, 0xF4, 0x45, 0x2C, 0xD7,
0xC0, 0x30, 0xF7, 0x47, 0xCC, 0x6B, 0xC8, 0x83, 0xB7, 0x67, 0x7A, 0x8E, 0xAD, 0x7E, 0xE5, 0xC4,
0x9F, 0x60, 0x40, 0xE5, 0xBC, 0xC0, 0xB5, 0x61, 0x33, 0x3F, 0x46, 0xE6, 0x2D, 0x98, 0xDF, 0x28,
0x05, 0x0E, 0xBC, 0xF0, 0xCA, 0x13, 0xFE, 0x68, 0xF7, 0x3A, 0x89, 0xA5, 0x71, 0x5F, 0x21, 0x76,
0xC2, 0x14, 0xC5, 0x6C, 0x95, 0x4f, 0x4f, 0x2A, 0x71, 0x52, 0x3C, 0xEE, 0xAA, 0xDB, 0xf1, 0x00
};
static void klxyj_decrypt(running_machine &machine)
{
int i;
UINT16 *src = (UINT16 *) machine.region("user1")->base();
int rom_size = 0x80000;
for(i=0; i<rom_size/2; i++) {
UINT16 x = src[i];
if ((i & 0x040480) != 0x000080) x ^= 0x0001;
if ((i & 0x004008) == 0x004008) x ^= 0x0002;
// if ((i & 0x080030) == 0x080010) x ^= 0x0004;
if ((i & 0x000242) != 0x000042) x ^= 0x0008;
if ((i & 0x008100) == 0x008000) x ^= 0x0010;
if ((i & 0x002004) != 0x000004) x ^= 0x0020;
if ((i & 0x011800) != 0x010000) x ^= 0x0040;
if ((i & 0x004820) == 0x004820) x ^= 0x0080;
x ^= klxyj_tab[(i>> 1) & 0xff] << 8;
src[i] = x;
}
}
static DRIVER_INIT( igs_m027 )
{
pgm_create_dummy_internal_arm_region(machine);
}
static DRIVER_INIT( sdwx )
{
sdwx_decrypt(machine);
sdwx_gfx_decrypt(machine);
pgm_create_dummy_internal_arm_region(machine);
}
static DRIVER_INIT( klxyj )
{
klxyj_decrypt(machine);
//sdwx_gfx_decrypt(machine);
pgm_create_dummy_internal_arm_region(machine);
}
static DRIVER_INIT( chessc2 )
{
chessc2_decrypt(machine);
//sdwx_gfx_decrypt(machine);
pgm_create_dummy_internal_arm_region(machine);
}
static DRIVER_INIT( hauntedh )
{
hauntedh_decrypt(machine);
//sdwx_gfx_decrypt(machine);
pgm_create_dummy_internal_arm_region(machine);
}
/***************************************************************************
Game Drivers
@ -784,11 +979,12 @@ ROM_END
***************************************************************************/
GAME( 2002, sdwx, 0, igs_majhong, sdwx, sdwx, ROT0, "IGS", "Sheng Dan Wu Xian", GAME_NO_SOUND | GAME_NOT_WORKING ) // aka Christmas 5 Line?
GAME( 200?, sddz, 0, igs_majhong, sdwx, 0, ROT0, "IGS", "Super Dou Di Zhu", GAME_NO_SOUND | GAME_NOT_WORKING )
GAME( 2000, bigd2, 0, igs_majhong, sdwx, 0, ROT0, "IGS", "Big D2", GAME_NO_SOUND | GAME_NOT_WORKING )
GAME( 200?, lhzb3, 0, igs_majhong, sdwx, 0, ROT0, "IGS", "Long Hu Zheng Ba 3", GAME_NO_SOUND | GAME_NOT_WORKING )
GAME( 200?, lhzb4, 0, igs_majhong, sdwx, 0, ROT0, "IGS", "Long Hu Zheng Ba 4", GAME_NO_SOUND | GAME_NOT_WORKING )
GAME( 200?, klxyj, 0, igs_majhong, sdwx, 0, ROT0, "IGS", "Kuai Le Xi You Ji", GAME_NO_SOUND | GAME_NOT_WORKING )
GAME( 2000, mgfx, 0, igs_majhong, sdwx, 0, ROT0, "IGS", "Man Guan Fu Xing", GAME_NO_SOUND | GAME_NOT_WORKING )
GAME( 200?, gonefsh2, 0, igs_majhong, sdwx, 0, ROT0, "IGS", "Gone Fishing 2", GAME_NO_SOUND | GAME_NOT_WORKING )
GAME( 200?, chessc2, 0, igs_majhong, sdwx, 0, ROT0, "IGS", "Chess Challenge 2", GAME_NO_SOUND | GAME_NOT_WORKING )
GAME( 200?, sddz, 0, igs_majhong, sdwx, igs_m027, ROT0, "IGS", "Super Dou Di Zhu", GAME_NO_SOUND | GAME_NOT_WORKING )
GAME( 2000, bigd2, 0, igs_majhong, sdwx, igs_m027, ROT0, "IGS", "Big D2", GAME_NO_SOUND | GAME_NOT_WORKING )
GAME( 200?, lhzb3, 0, igs_majhong, sdwx, igs_m027, ROT0, "IGS", "Long Hu Zheng Ba 3", GAME_NO_SOUND | GAME_NOT_WORKING )
GAME( 200?, lhzb4, 0, igs_majhong, sdwx, igs_m027, ROT0, "IGS", "Long Hu Zheng Ba 4", GAME_NO_SOUND | GAME_NOT_WORKING )
GAME( 200?, klxyj, 0, igs_majhong, sdwx, klxyj, ROT0, "IGS", "Kuai Le Xi You Ji", GAME_NO_SOUND | GAME_NOT_WORKING )
GAME( 2000, mgfx, 0, igs_majhong, sdwx, igs_m027, ROT0, "IGS", "Man Guan Fu Xing", GAME_NO_SOUND | GAME_NOT_WORKING )
GAME( 200?, gonefsh2, 0, igs_majhong, sdwx, igs_m027, ROT0, "IGS", "Gone Fishing 2", GAME_NO_SOUND | GAME_NOT_WORKING )
GAME( 200?, chessc2, 0, igs_majhong, sdwx, chessc2, ROT0, "IGS", "Chess Challenge 2", GAME_NO_SOUND | GAME_NOT_WORKING )
GAME( 200?, haunthig, 0, igs_majhong, sdwx, hauntedh, ROT0, "IGS", "Haunted House (IGS)", GAME_NO_SOUND | GAME_NOT_WORKING )

File diff suppressed because it is too large Load Diff

View File

@ -292,6 +292,25 @@ static ADDRESS_MAP_START( sderby_map, AS_PROGRAM, 16 )
AM_RANGE(0xffc000, 0xffffff) AM_RAM
ADDRESS_MAP_END
static ADDRESS_MAP_START( luckboom_map, AS_PROGRAM, 16 )
AM_RANGE(0x000000, 0x07ffff) AM_ROM
AM_RANGE(0x100000, 0x100fff) AM_RAM_WRITE(sderby_videoram_w) AM_BASE_MEMBER(sderby_state,m_videoram) /* bg */
AM_RANGE(0x101000, 0x101fff) AM_RAM_WRITE(sderby_md_videoram_w) AM_BASE_MEMBER(sderby_state,m_md_videoram) /* mid */
AM_RANGE(0x102000, 0x103fff) AM_RAM_WRITE(sderby_fg_videoram_w) AM_BASE_MEMBER(sderby_state,m_fg_videoram) /* fg */
AM_RANGE(0x104000, 0x10400b) AM_WRITE(sderby_scroll_w)
AM_RANGE(0x10400c, 0x10400d) AM_WRITENOP /* ??? - check code at 0x000456 (executed once at startup) */
AM_RANGE(0x10400e, 0x10400f) AM_WRITENOP /* ??? - check code at 0x000524 (executed once at startup) */
AM_RANGE(0x200000, 0x200fff) AM_RAM AM_BASE_MEMBER(sderby_state,m_spriteram) AM_SIZE_MEMBER(sderby_state,m_spriteram_size)
AM_RANGE(0x308000, 0x30800d) AM_READ(sderby_input_r)
AM_RANGE(0x308008, 0x308009) AM_WRITE(sderby_out_w) /* output port */
AM_RANGE(0x30800e, 0x30800f) AM_DEVREADWRITE8_MODERN("oki", okim6295_device, read, write, 0x00ff)
AM_RANGE(0x380000, 0x380fff) AM_WRITE(paletteram16_RRRRRGGGGGBBBBBx_word_w) AM_BASE_GENERIC(paletteram)
AM_RANGE(0x500000, 0x500001) AM_WRITENOP /* unknown... write 0x01 in game, and 0x00 on reset */
AM_RANGE(0xe00000, 0xe007ff) AM_RAM AM_SHARE("nvram")
AM_RANGE(0xff0000, 0xffffff) AM_RAM
ADDRESS_MAP_END
static ADDRESS_MAP_START( spacewin_map, AS_PROGRAM, 16 )
AM_RANGE(0x000000, 0x03ffff) AM_ROM
AM_RANGE(0x100000, 0x100fff) AM_RAM_WRITE(sderby_videoram_w) AM_BASE_MEMBER(sderby_state,m_videoram) /* bg */
@ -359,6 +378,26 @@ static INPUT_PORTS_START( sderby )
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN )
INPUT_PORTS_END
static INPUT_PORTS_START( luckboom )
PORT_START("IN0") /* 0x308000.w */
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT )
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT )
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_JOYSTICK_UP )
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN )
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_START1 )
PORT_SERVICE_NO_TOGGLE(0x1000, IP_ACTIVE_LOW)
PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN )
INPUT_PORTS_END
static INPUT_PORTS_START( spacewin )
PORT_START("IN0") /* 0x308000.w */
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_POKER_HOLD1 )
@ -478,6 +517,30 @@ static MACHINE_CONFIG_START( sderby, sderby_state )
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
MACHINE_CONFIG_END
static MACHINE_CONFIG_START( luckboom, sderby_state )
MCFG_CPU_ADD("maincpu", M68000, 12000000)
MCFG_CPU_PROGRAM_MAP(luckboom_map)
MCFG_CPU_VBLANK_INT("screen", irq4_line_hold)
MCFG_NVRAM_ADD_0FILL("nvram")
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_REFRESH_RATE(60)
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
MCFG_SCREEN_SIZE(64*8, 64*8)
MCFG_SCREEN_VISIBLE_AREA(4*8, 44*8-1, 3*8, 33*8-1)
MCFG_SCREEN_UPDATE_STATIC(sderby)
MCFG_GFXDECODE(sderby)
MCFG_PALETTE_LENGTH(0x1000)
MCFG_VIDEO_START(sderby)
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_OKIM6295_ADD("oki", 1056000, OKIM6295_PIN7_HIGH) /* clock frequency & pin 7 not verified */
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.0)
MACHINE_CONFIG_END
static MACHINE_CONFIG_START( spacewin, sderby_state )
MCFG_CPU_ADD("maincpu", M68000, 12000000)
@ -718,6 +781,53 @@ ROM_START( croupiera )
ROM_LOAD( "8.bin", 0x200000, 0x80000, CRC(d4c2b7da) SHA1(515be861443acc5b911241dbaafa42e02f79985a))
ROM_END
/*
Lucky Boom (c)1996 Playmark
QTY Type clock position function
1x MC68000P12 u24 16/32-bit Microprocessor - main
1x M6295 u146 4-Channel Mixing ADCPM Voice Synthesis LSI - sound
1x KA358 u155 Dual Operational Amplifier - sound
1x TDA2003 TD1 Audio Amplifier - sound
1x oscillator 24.000000MHz XL1
1x oscillator 28.000000MHz XL2
1x blu resonator 1000J Y1
ROMs
QTY Type position status
1x TMS27C020 1 dumped
2x AM27C010 2,3 dumped
5x TMS27C010 4-8 dumped
RAMs
QTY Type position
8x HM3-65728BK-5 u42,u73,u74,u75,u80,u81,u124,u125
2x HY62256ALP-10 u2,u6
2x KM6264BL-7L u36,u37
PLDs
QTY Type position status
2x A1020B-PL84C u110,u137 read protected
4x TIBPAL22V10ACNT u1,u77,u111,u112 read protected
*/
ROM_START( luckboom )
ROM_REGION( 0x80000, "maincpu", 0 ) /* 68000 Code */
ROM_LOAD16_BYTE( "2.u16", 0x00000, 0x20000, CRC(0a20eaca) SHA1(edd325b60b3a3ce84e89f8be91b9e19f82d15317) )
ROM_LOAD16_BYTE( "3.u15", 0x00001, 0x20000, CRC(0d3bb24c) SHA1(31826ec29650aa8b70e1b713678401113e008832) )
ROM_REGION( 0x080000, "oki", 0 ) /* Samples */
ROM_LOAD( "1.u147", 0x00000, 0x40000, CRC(0d42c0a3) SHA1(1b1d4c7dcbb063e8bf133063770b753947d1a017) )
ROM_REGION( 0xa0000, "gfx1", 0 ) /* Sprites */
ROM_LOAD( "4.u141", 0x000000, 0x20000, CRC(3aeccad7) SHA1(4104dd3ae928c1a876ac9b460fe18b58ce1206f7) )
ROM_LOAD( "5.u142", 0x020000, 0x20000, CRC(4e4f9ac6) SHA1(e9b0c48195d8b21cdab16d66423ff43e6292ef2c) )
ROM_LOAD( "6.u143", 0x040000, 0x20000, CRC(d1b4910e) SHA1(cfcb14bcd992bceaa634b20eb2d446caa62b6d82) )
ROM_LOAD( "7.u144", 0x060000, 0x20000, CRC(00334bad) SHA1(2d8af2a4b517ceb1ae5504b15086c8faaf934b53) )
ROM_LOAD( "8.u145", 0x080000, 0x20000, CRC(dc12df50) SHA1(0796d6428dc3a032ea55e06e8e07245a256ed036) )
ROM_END
/******************************
* Game Drivers *
@ -728,3 +838,4 @@ GAMEL( 1996, sderby, 0, sderby, sderby, 0, ROT0, "Playmark", "
GAMEL( 1996, spacewin, 0, spacewin, spacewin, 0, ROT0, "Playmark", "Scacco Matto / Space Win", 0, layout_spacewin )
GAMEL( 1997, croupier, 0, pmroulet, pmroulet, 0, ROT0, "Playmark", "Croupier (Playmark Roulette v.20.05)", GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING, layout_pmroulet )
GAMEL( 1997, croupiera, croupier, pmroulet, pmroulet, 0, ROT0, "Playmark", "Croupier (Playmark Roulette v.09.04)", GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING, layout_pmroulet )
GAME ( 1996, luckboom, 0, luckboom, luckboom, 0, ROT0, "Playmark", "Lucky Boom", 0 )

View File

@ -1,4 +1,14 @@
#include "machine/v3021.h"
#include "cpu/z80/z80.h"
#include "cpu/m68000/m68000.h"
#include "cpu/arm7/arm7.h"
#include "sound/ics2115.h"
#include "cpu/arm7/arm7core.h"
#include "machine/nvram.h"
#define PGMARM7LOGERROR 0
class pgm_state : public driver_device
{
public:
@ -72,15 +82,6 @@ public:
UINT32 m_kb_regs[0x10];
UINT16 m_olds_bs;
UINT16 m_olds_cmd3;
// pstars
UINT16 m_pstars_key;
UINT16 m_pstars_int[2];
UINT32 m_pstars_regs[16];
UINT32 m_pstars_val;
UINT16 m_pstar_e7;
UINT16 m_pstar_b1;
UINT16 m_pstar_ce;
UINT16 m_pstar_ram[3];
// ASIC 3 (oriental legends protection)
UINT8 m_asic3_reg;
UINT8 m_asic3_latch[3];
@ -90,29 +91,68 @@ public:
UINT8 m_asic3_h1;
UINT8 m_asic3_h2;
UINT16 m_asic3_hold;
// ASIC28
UINT16 m_asic28_key;
UINT16 m_asic28_regs[10];
UINT16 m_asic_params[256];
UINT16 m_asic28_rcnt;
UINT32 m_eoregs[16];
// Oldsplus simulation
UINT16 m_oldsplus_key;
UINT16 m_oldsplus_int[2];
UINT32 m_oldsplus_val;
UINT16 m_oldsplus_ram[0x100];
UINT32 m_oldsplus_regs[0x100];
UINT32* m_arm_ram;
};
/* for machine/pgmprot1.c type games */
class pgm_kovarmsim_state : public pgm_state
{
public:
pgm_kovarmsim_state(const machine_config &mconfig, device_type type, const char *tag)
: pgm_state(mconfig, type, tag) {
m_ddp3internal_slot = 0;
}
UINT16 m_value0;
UINT16 m_value1;
UINT16 m_valuekey;
UINT16 m_ddp3lastcommand;
UINT32 m_valueresponse;
int m_ddp3internal_slot;
UINT32 m_ddp3slots[0x100];
// pstars / oldsplus
UINT16 m_pstar_e7;
UINT16 m_pstar_b1;
UINT16 m_pstar_ce;
UINT16 m_extra_ram[0x100];
typedef void (*pgm_arm_sim_command_handler)(pgm_kovarmsim_state *state, int pc);
pgm_arm_sim_command_handler arm_sim_handler;
};
extern UINT16 *pgm_mainram; // used by nvram handler, we cannot move it to driver data struct
/*----------- defined in drivers/pgm.c -----------*/
void pgm_basic_init( running_machine &machine, bool set_bank = true );
INPUT_PORTS_EXTERN( pgm );
/* we only need half of these because CavePGM has it's own MACHINE DRIVER in pgmprot1.c - refactor */
TIMER_DEVICE_CALLBACK( pgm_interrupt );
GFXDECODE_EXTERN( pgm );
MACHINE_CONFIG_EXTERN( pgm );
ADDRESS_MAP_EXTERN( pgm_z80_mem, 8 );
ADDRESS_MAP_EXTERN( pgm_z80_io, 8 );
void pgm_sound_irq( device_t *device, int level );
ADDRESS_MAP_EXTERN( pgm_mem, 16 );
ADDRESS_MAP_EXTERN( pgm_basic_mem, 16 );
ADDRESS_MAP_EXTERN( pgm_base_mem, 16 );
MACHINE_START( pgm );
MACHINE_RESET( pgm );
/*----------- defined in machine/pgmcrypt.c -----------*/
void pgm_kov_decrypt(running_machine &machine);
@ -141,27 +181,101 @@ void pgm_happy6_decrypt(running_machine &machine);
/*----------- defined in machine/pgmprot.c -----------*/
READ16_HANDLER( pstars_protram_r );
READ16_HANDLER( pstars_r );
WRITE16_HANDLER( pstars_w );
DRIVER_INIT( orlegend );
READ16_HANDLER( pgm_asic3_r );
WRITE16_HANDLER( pgm_asic3_w );
WRITE16_HANDLER( pgm_asic3_reg_w );
INPUT_PORTS_EXTERN( orlegend );
INPUT_PORTS_EXTERN( orld105k );
READ16_HANDLER( sango_protram_r );
READ16_HANDLER( asic28_r );
WRITE16_HANDLER( asic28_w );
/*----------- defined in machine/pgmprot1.c -----------*/
READ16_HANDLER( dw2_d80000_r );
/* emulations */
DRIVER_INIT( photoy2k );
DRIVER_INIT( kovsh );
DRIVER_INIT( kovshp );
DRIVER_INIT( kovlsqh2 );
DRIVER_INIT( kovqhsgs );
MACHINE_CONFIG_EXTERN( kov );
READ16_HANDLER( oldsplus_protram_r );
READ16_HANDLER( oldsplus_r );
WRITE16_HANDLER( oldsplus_w );
/* simulations */
DRIVER_INIT( ddp3 );
DRIVER_INIT( ket );
DRIVER_INIT( espgal );
DRIVER_INIT( puzzli2 );
DRIVER_INIT( py2k2 );
DRIVER_INIT( pstar );
DRIVER_INIT( kov );
DRIVER_INIT( kovboot );
DRIVER_INIT( oldsplus );
MACHINE_CONFIG_EXTERN( kov_simulated_arm );
MACHINE_CONFIG_EXTERN( cavepgm );
INPUT_PORTS_EXTERN( sango );
INPUT_PORTS_EXTERN( sango_ch );
INPUT_PORTS_EXTERN( photoy2k );
INPUT_PORTS_EXTERN( oldsplus );
INPUT_PORTS_EXTERN( pstar );
INPUT_PORTS_EXTERN( py2k2 );
INPUT_PORTS_EXTERN( puzzli2 );
INPUT_PORTS_EXTERN( kovsh );
/*----------- defined in machine/pgmprot2.c -----------*/
/* emulations */
MACHINE_CONFIG_EXTERN( kov2 );
DRIVER_INIT( kov2 );
DRIVER_INIT( kov2p );
DRIVER_INIT( martmast );
DRIVER_INIT( ddp2 );
/* simulations (or missing) */
DRIVER_INIT( dw2001 );
INPUT_PORTS_EXTERN( ddp2 );
INPUT_PORTS_EXTERN( kov2 );
INPUT_PORTS_EXTERN( martmast );
INPUT_PORTS_EXTERN( dw2001 );
/*----------- defined in machine/pgmprot3.c -----------*/
MACHINE_CONFIG_EXTERN( svg );
DRIVER_INIT( theglad );
DRIVER_INIT( svg );
DRIVER_INIT( svgpcb );
DRIVER_INIT( killbldp );
DRIVER_INIT( dmnfrnt );
DRIVER_INIT( happy6 );
/*----------- defined in machine/pgmprot4.c -----------*/
MACHINE_CONFIG_EXTERN( killbld );
MACHINE_CONFIG_EXTERN( dw3 );
DRIVER_INIT( killbld );
DRIVER_INIT( drgw3 );
INPUT_PORTS_EXTERN( killbld );
INPUT_PORTS_EXTERN( dw3 );
/*----------- defined in machine/pgmprot5.c -----------*/
DRIVER_INIT( drgw2 );
DRIVER_INIT( dw2v100x );
DRIVER_INIT( drgw2c );
DRIVER_INIT( drgw2j );
/*----------- defined in machine/pgmprot6.c -----------*/
MACHINE_CONFIG_EXTERN( olds );
DRIVER_INIT( olds );
INPUT_PORTS_EXTERN( olds );
MACHINE_RESET( kov );
void install_protection_asic_sim_kov(running_machine &machine);
/*----------- defined in video/pgm.c -----------*/

File diff suppressed because it is too large Load Diff

1624
src/mame/machine/pgmprot1.c Normal file

File diff suppressed because it is too large Load Diff

387
src/mame/machine/pgmprot2.c Normal file
View File

@ -0,0 +1,387 @@
/***********************************************************************
PGM IGA027A (55857F type) ARM protection emulation
these are emulation of the 'kov2' type ARM device
used by
Knights of Valor 2 (kov2)
Knights of Valor 2 Nine Dragons (kov2p) *
DoDonPachi 2 - Bee Storm (ddp2)
Martial Masters (martmast)
* using a hacked kov2 internal ROM
the following also use this device, but the internal
ROMs are not yet dumped
Dragon World 2001 (dw2001)
----
These games use a larger region of shared RAM than the 55857E
type and have a communication based on interrupts
----
All of these games have an external ARM rom.
The external ARM roms are encrypted, the internal ARM rom uploads
the decryption tables.
Game Region is supplied by internal ARM rom.
***********************************************************************/
#include "emu.h"
#include "includes/pgm.h"
static READ32_HANDLER( arm7_latch_arm_r )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
device_set_input_line(state->m_prot, ARM7_FIRQ_LINE, CLEAR_LINE ); // guess
if (PGMARM7LOGERROR)
logerror("ARM7: Latch read: %08x (%08x) (%06x)\n", state->m_kov2_latchdata_68k_w, mem_mask, cpu_get_pc(&space->device()));
return state->m_kov2_latchdata_68k_w;
}
static WRITE32_HANDLER( arm7_latch_arm_w )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
if (PGMARM7LOGERROR)
logerror("ARM7: Latch write: %08x (%08x) (%06x)\n", data, mem_mask, cpu_get_pc(&space->device()));
COMBINE_DATA(&state->m_kov2_latchdata_arm_w);
}
static READ32_HANDLER( arm7_shareram_r )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
if (PGMARM7LOGERROR)
logerror("ARM7: ARM7 Shared RAM Read: %04x = %08x (%08x) (%06x)\n", offset << 2, state->m_arm7_shareram[offset], mem_mask, cpu_get_pc(&space->device()));
return state->m_arm7_shareram[offset];
}
static WRITE32_HANDLER( arm7_shareram_w )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
if (PGMARM7LOGERROR)
logerror("ARM7: ARM7 Shared RAM Write: %04x = %08x (%08x) (%06x)\n", offset << 2, data, mem_mask, cpu_get_pc(&space->device()));
COMBINE_DATA(&state->m_arm7_shareram[offset]);
}
static READ16_HANDLER( arm7_latch_68k_r )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
if (PGMARM7LOGERROR)
logerror("M68K: Latch read: %04x (%04x) (%06x)\n", state->m_kov2_latchdata_arm_w & 0x0000ffff, mem_mask, cpu_get_pc(&space->device()));
return state->m_kov2_latchdata_arm_w;
}
static WRITE16_HANDLER( arm7_latch_68k_w )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
if (PGMARM7LOGERROR)
logerror("M68K: Latch write: %04x (%04x) (%06x)\n", data & 0x0000ffff, mem_mask, cpu_get_pc(&space->device()));
COMBINE_DATA(&state->m_kov2_latchdata_68k_w);
device_set_input_line(state->m_prot, ARM7_FIRQ_LINE, ASSERT_LINE ); // guess
}
static READ16_HANDLER( arm7_ram_r )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
UINT16 *share16 = (UINT16 *)state->m_arm7_shareram;
if (PGMARM7LOGERROR)
logerror("M68K: ARM7 Shared RAM Read: %04x = %04x (%08x) (%06x)\n", BYTE_XOR_LE(offset), share16[BYTE_XOR_LE(offset)], mem_mask, cpu_get_pc(&space->device()));
return share16[BYTE_XOR_LE(offset)];
}
static WRITE16_HANDLER( arm7_ram_w )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
UINT16 *share16 = (UINT16 *)state->m_arm7_shareram;
if (PGMARM7LOGERROR)
logerror("M68K: ARM7 Shared RAM Write: %04x = %04x (%04x) (%06x)\n", BYTE_XOR_LE(offset), data, mem_mask, cpu_get_pc(&space->device()));
COMBINE_DATA(&share16[BYTE_XOR_LE(offset)]);
}
/* 55857F? */
/* Knights of Valor 2, Martial Masters, DoDonpachi 2 */
/* no execute only space? */
static ADDRESS_MAP_START( kov2_mem, AS_PROGRAM, 16)
AM_IMPORT_FROM(pgm_mem)
AM_RANGE(0x100000, 0x5fffff) AM_ROMBANK("bank1") /* Game ROM */
AM_RANGE(0xd00000, 0xd0ffff) AM_READWRITE(arm7_ram_r, arm7_ram_w) /* ARM7 Shared RAM */
AM_RANGE(0xd10000, 0xd10001) AM_READWRITE(arm7_latch_68k_r, arm7_latch_68k_w) /* ARM7 Latch */
ADDRESS_MAP_END
static ADDRESS_MAP_START( 55857F_arm7_map, AS_PROGRAM, 32 )
AM_RANGE(0x00000000, 0x00003fff) AM_ROM
AM_RANGE(0x08000000, 0x083fffff) AM_ROM AM_REGION("user1", 0)
AM_RANGE(0x10000000, 0x100003ff) AM_RAM
AM_RANGE(0x18000000, 0x1800ffff) AM_RAM AM_BASE_MEMBER(pgm_state, m_arm_ram)
AM_RANGE(0x38000000, 0x38000003) AM_READWRITE(arm7_latch_arm_r, arm7_latch_arm_w) /* 68k Latch */
AM_RANGE(0x48000000, 0x4800ffff) AM_READWRITE(arm7_shareram_r, arm7_shareram_w) AM_BASE_MEMBER(pgm_state, m_arm7_shareram)
AM_RANGE(0x50000000, 0x500003ff) AM_RAM
ADDRESS_MAP_END
/******* ARM 55857F *******/
MACHINE_CONFIG_DERIVED( kov2, pgm )
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_PROGRAM_MAP(kov2_mem)
/* protection CPU */
MCFG_CPU_ADD("prot", ARM7, 20000000) // 55857F
MCFG_CPU_PROGRAM_MAP(55857F_arm7_map)
MACHINE_CONFIG_END
static void kov2_latch_init( running_machine &machine )
{
pgm_state *state = machine.driver_data<pgm_state>();
state->m_kov2_latchdata_68k_w = 0;
state->m_kov2_latchdata_arm_w = 0;
state->save_item(NAME(state->m_kov2_latchdata_68k_w));
state->save_item(NAME(state->m_kov2_latchdata_arm_w));
}
static WRITE32_HANDLER( kov2_arm_region_w )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
int pc = cpu_get_pc(&space->device());
int regionhack = input_port_read(space->machine(), "RegionHack");
if (pc==0x190 && regionhack != 0xff) data = (data & 0xffff0000) | (regionhack << 0);
COMBINE_DATA(&state->m_arm7_shareram[0x138/4]);
}
DRIVER_INIT( kov2 )
{
pgm_basic_init(machine);
pgm_kov2_decrypt(machine);
kov2_latch_init(machine);
// we only have a HK internal ROM dumped for now, allow us to override that for debugging purposes.
machine.device("prot")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x48000138, 0x4800013b, FUNC(kov2_arm_region_w));
}
DRIVER_INIT( kov2p )
{
// this hacks the identification of the kov2 rom to return the string required for kov2p
// this isn't guaranteed to work properly (and definitely wouldn't on real hardware due to the internal
// ROM uploading the encryption table) The internal ROM should be dumped properly.
pgm_basic_init(machine);
pgm_kov2p_decrypt(machine);
kov2_latch_init(machine);
UINT8 *mem8 = (UINT8 *)machine.region("user1")->base();
mem8[0xDE] = 0xC0;
mem8[0xDF] = 0x46;
mem8[0x4ED8] = 0xA8;// B0
mem8[0x4EDC] = 0x9C;// A4
mem8[0x4EE0] = 0x5C;// 64
mem8[0x4EE4] = 0x94;// 9C
mem8[0x4EE8] = 0xE8;// F0
mem8[0x4EEC] = 0x6C;// 74
mem8[0x4EF0] = 0xD4;// DC
mem8[0x4EF4] = 0x50;// 58
mem8[0x4EF8] = 0x80;// 88
mem8[0x4EFC] = 0x9C;// A4
mem8[0x4F00] = 0x28;// 30
mem8[0x4F04] = 0x30;// 38
mem8[0x4F08] = 0x34;// 3C
mem8[0x4F0C] = 0x1C;// 24
mem8[0x1FFFFC] = 0x33;
mem8[0x1FFFFD] = 0x99;
// we only have a HK internal ROM dumped for now, allow us to override that for debugging purposes.
machine.device("prot")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x48000138, 0x4800013b, FUNC(kov2_arm_region_w));
}
static WRITE32_HANDLER( martmast_arm_region_w )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
int pc = cpu_get_pc(&space->device());
int regionhack = input_port_read(space->machine(), "RegionHack");
if (pc==0x170 && regionhack != 0xff) data = (data & 0xffff0000) | (regionhack << 0);
COMBINE_DATA(&state->m_arm7_shareram[0x138/4]);
}
DRIVER_INIT( martmast )
{
pgm_basic_init(machine);
pgm_mm_decrypt(machine);
kov2_latch_init(machine);
// we only have a USA / CHINA internal ROMs dumped for now, allow us to override that for debugging purposes.
machine.device("prot")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x48000138, 0x4800013b, FUNC(martmast_arm_region_w));
}
static WRITE32_HANDLER( ddp2_arm_region_w )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
int pc = cpu_get_pc(&space->device());
int regionhack = input_port_read(space->machine(), "RegionHack");
if (pc==0x0174 && regionhack != 0xff) data = (data & 0x0000ffff) | (regionhack << 16);
COMBINE_DATA(&state->m_arm7_shareram[0x0]);
}
static READ32_HANDLER( ddp2_speedup_r )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
int pc = cpu_get_pc(&space->device());
UINT32 data = state->m_arm_ram[0x300c/4];
if (pc==0x080109b4)
{
/* if we've hit the loop where this is read and both values are 0 then the only way out is an interrupt */
int r4 = (cpu_get_reg(&space->device(), ARM7_R4));
r4 += 0xe;
if (r4==0x18002f9e)
{
UINT32 data2 = state->m_arm_ram[0x2F9C/4]&0xffff0000;
if ((data==0x00000000) && (data2==0x00000000)) device_spin_until_interrupt(&space->device());
}
}
return data;
}
static READ16_HANDLER( ddp2_main_speedup_r )
{
UINT16 data = pgm_mainram[0x0ee54/2];
int pc = cpu_get_pc(&space->device());
if (pc == 0x149dce) device_spin_until_interrupt(&space->device());
if (pc == 0x149cfe) device_spin_until_interrupt(&space->device());
return data;
}
DRIVER_INIT( ddp2 )
{
pgm_basic_init(machine);
pgm_ddp2_decrypt(machine);
kov2_latch_init(machine);
// we only have a Japan internal ROM dumped for now, allow us to override that for debugging purposes.
machine.device("prot")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0x48000000, 0x48000003, FUNC(ddp2_arm_region_w));
machine.device("prot")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x1800300c, 0x1800300f, FUNC(ddp2_speedup_r));
machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x80ee54, 0x80ee55, FUNC(ddp2_main_speedup_r));
}
DRIVER_INIT( dw2001 )
{
//pgm_state *state = machine.driver_data<pgm_state>();
UINT16 *mem16 = (UINT16 *)machine.region("maincpu")->base();
pgm_basic_init(machine);
kov2_latch_init(machine);
pgm_mm_decrypt(machine); // encryption is the same as martial masters
mem16[0x11e90c / 2] = 0x4e71;
mem16[0x11e90e / 2] = 0x4e71;
mem16[0x11e91a / 2] = 0x4e71;
mem16[0x11eaf6 / 2] = 0x4e71;
mem16[0x11eaf8 / 2] = 0x4e71;
mem16[0x11eb04 / 2] = 0x4e71;
/* patch ARM area with fake code */
UINT16 *temp16 = (UINT16 *)machine.region("prot")->base();
temp16[(0x0000)/2] = 0xd088;
temp16[(0x0002)/2] = 0xe59f;
temp16[(0x0004)/2] = 0x0680;
temp16[(0x0006)/2] = 0xe3a0;
temp16[(0x0008)/2] = 0x0001;
temp16[(0x000a)/2] = 0xe280;
temp16[(0x000c)/2] = 0xff10;
temp16[(0x000e)/2] = 0xe12f;
temp16[(0x0090)/2] = 0x0400;
temp16[(0x0092)/2] = 0x1000;
}
INPUT_PORTS_START( ddp2 )
PORT_INCLUDE ( pgm )
PORT_START("RegionHack") /* Region - actually supplied by protection device */
PORT_CONFNAME( 0x00ff, 0x00ff, DEF_STR( Region ) )
PORT_CONFSETTING( 0x0000, DEF_STR( China ) )
PORT_CONFSETTING( 0x0001, DEF_STR( Taiwan ) )
PORT_CONFSETTING( 0x0002, "Japan (Cave license)" )
PORT_CONFSETTING( 0x0003, DEF_STR( Korea ) )
PORT_CONFSETTING( 0x0004, DEF_STR( Hong_Kong ) )
PORT_CONFSETTING( 0x0005, DEF_STR( World ) )
PORT_CONFSETTING( 0x00ff, "Untouched" ) // don't hack the region
INPUT_PORTS_END
INPUT_PORTS_START( kov2 )
PORT_INCLUDE ( pgm )
PORT_START("RegionHack") /* Region - actually supplied by protection device */
PORT_CONFNAME( 0x00ff, 0x00ff, DEF_STR( Region ) )
PORT_CONFSETTING( 0x0000, DEF_STR( China ) )
PORT_CONFSETTING( 0x0001, DEF_STR( Taiwan ) )
PORT_CONFSETTING( 0x0002, "Japan (Cave license)" )
PORT_CONFSETTING( 0x0003, DEF_STR( Korea ) )
PORT_CONFSETTING( 0x0004, DEF_STR( Hong_Kong ) )
PORT_CONFSETTING( 0x0005, DEF_STR( World ) )
PORT_CONFSETTING( 0x00ff, "Untouched" ) // don't hack the region
INPUT_PORTS_END
INPUT_PORTS_START( martmast )
PORT_INCLUDE ( pgm )
PORT_START("RegionHack") /* Region - actually supplied by protection device */
PORT_CONFNAME( 0x00ff, 0x00ff, DEF_STR( Region ) )
PORT_CONFSETTING( 0x0000, DEF_STR( China ) )
PORT_CONFSETTING( 0x0001, DEF_STR( Taiwan ) )
PORT_CONFSETTING( 0x0002, DEF_STR( Japan ) )
PORT_CONFSETTING( 0x0003, DEF_STR( Korea ) )
PORT_CONFSETTING( 0x0004, DEF_STR( Hong_Kong ) )
PORT_CONFSETTING( 0x0005, DEF_STR( World ) )
PORT_CONFSETTING( 0x0006, DEF_STR( USA ) )
PORT_CONFSETTING( 0x00ff, "Untouched" ) // don't hack the region
INPUT_PORTS_END
INPUT_PORTS_START( dw2001 )
PORT_INCLUDE ( pgm )
PORT_MODIFY("Region") /* Region - supplied by protection device */
PORT_CONFNAME( 0x000f, 0x0005, DEF_STR( Region ) )
PORT_CONFSETTING( 0x0000, DEF_STR( China ) )
PORT_CONFSETTING( 0x0001, DEF_STR( Taiwan ) )
PORT_CONFSETTING( 0x0002, "Japan (Alta license)" )
PORT_CONFSETTING( 0x0003, DEF_STR( Korea ) )
PORT_CONFSETTING( 0x0004, DEF_STR( Hong_Kong ) )
PORT_CONFSETTING( 0x0005, DEF_STR( World ) )
INPUT_PORTS_END

298
src/mame/machine/pgmprot3.c Normal file
View File

@ -0,0 +1,298 @@
/***********************************************************************
PGM IGA027A (55857G type) ARM protection emulation
these are emulation of the 'dmnfrnt' type ARM device
used by
Demon Front (dmnfrnt) *1
The Gladiator (theglad)
Spectral vs. Generation (svg)
Happy 6-in-1 (happy6)
The Killing Blade Plus (killbldp) *2
None of these work at all, with the following exception.
*1 - We bypass the internal ROM entirely! Game doesn't jump back
*2 - Partial dump of the internal ROM is used, but 'Execute Only' region is missing
----
These games use a large amount of shared RAM which is banked between CPUs
----
All of these games have an external ARM rom.
The internal ROMs contain an 'execute only' region at the start of the
ROM which prevents reading out.
IGS027A type 55857G has also been seen on various IGS gambling boards
as the main CPU (eg. Haunted House, see igs_m027a)
***********************************************************************/
#include "emu.h"
#include "includes/pgm.h"
static WRITE32_HANDLER( svg_arm7_ram_sel_w )
{
// printf("svg_arm7_ram_sel_w %08x\n", data);
space->machine().scheduler().synchronize(); // force resync
pgm_state *state = space->machine().driver_data<pgm_state>();
state->m_svg_ram_sel = data & 1;
}
static READ32_HANDLER( svg_arm7_shareram_r )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
return state->m_svg_shareram[state->m_svg_ram_sel & 1][offset];
}
static WRITE32_HANDLER( svg_arm7_shareram_w )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
COMBINE_DATA(&state->m_svg_shareram[state->m_svg_ram_sel & 1][offset]);
}
static READ16_HANDLER( svg_m68k_ram_r )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
int ram_sel = (state->m_svg_ram_sel & 1) ^ 1;
UINT16 *share16 = (UINT16 *)(state->m_svg_shareram[ram_sel & 1]);
return share16[BYTE_XOR_LE(offset)];
}
static WRITE16_HANDLER( svg_m68k_ram_w )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
int ram_sel = (state->m_svg_ram_sel & 1) ^ 1;
UINT16 *share16 = (UINT16 *)(state->m_svg_shareram[ram_sel & 1]);
COMBINE_DATA(&share16[BYTE_XOR_LE(offset)]);
}
static READ16_HANDLER( svg_68k_nmi_r )
{
return 0;
}
static WRITE16_HANDLER( svg_68k_nmi_w )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
generic_pulse_irq_line(state->m_prot, ARM7_FIRQ_LINE, 1);
}
static WRITE16_HANDLER( svg_latch_68k_w )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
if (PGMARM7LOGERROR)
logerror("M68K: Latch write: %04x (%04x) (%06x)\n", data & 0x0000ffff, mem_mask, cpu_get_pc(&space->device()));
COMBINE_DATA(&state->m_kov2_latchdata_68k_w);
}
static READ16_HANDLER( svg_latch_68k_r )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
if (PGMARM7LOGERROR)
logerror("M68K: Latch read: %04x (%04x) (%06x)\n", state->m_kov2_latchdata_arm_w & 0x0000ffff, mem_mask, cpu_get_pc(&space->device()));
return state->m_kov2_latchdata_arm_w;
}
static READ32_HANDLER( svg_latch_arm_r )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
if (PGMARM7LOGERROR)
logerror("ARM7: Latch read: %08x (%08x) (%06x)\n", state->m_kov2_latchdata_68k_w, mem_mask, cpu_get_pc(&space->device()));
return state->m_kov2_latchdata_68k_w;
}
static WRITE32_HANDLER( svg_latch_arm_w )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
if (PGMARM7LOGERROR)
logerror("ARM7: Latch write: %08x (%08x) (%06x)\n", data, mem_mask, cpu_get_pc(&space->device()));
COMBINE_DATA(&state->m_kov2_latchdata_arm_w);
}
/* 55857G? */
/* Demon Front, The Gladiator, Happy 6-in-1, Spectral Vs. Generation, Killing Blade EX */
/* the ones with an EXECUTE ONLY region of ARM space? */
static ADDRESS_MAP_START( svg_68k_mem, AS_PROGRAM, 16)
AM_IMPORT_FROM(pgm_mem)
AM_RANGE(0x100000, 0x1fffff) AM_ROMBANK("bank1") /* Game ROM */
AM_RANGE(0x500000, 0x51ffff) AM_READWRITE(svg_m68k_ram_r, svg_m68k_ram_w) /* ARM7 Shared RAM */
AM_RANGE(0x5c0000, 0x5c0001) AM_READWRITE(svg_68k_nmi_r, svg_68k_nmi_w) /* ARM7 FIQ */
AM_RANGE(0x5c0300, 0x5c0301) AM_READWRITE(svg_latch_68k_r, svg_latch_68k_w) /* ARM7 Latch */
ADDRESS_MAP_END
static ADDRESS_MAP_START( 55857G_arm7_map, AS_PROGRAM, 32 )
AM_RANGE(0x00000000, 0x00003fff) AM_ROM
AM_RANGE(0x08000000, 0x087fffff) AM_ROM AM_REGION("user1", 0)
AM_RANGE(0x10000000, 0x100003ff) AM_RAM
AM_RANGE(0x18000000, 0x1803ffff) AM_RAM AM_BASE_MEMBER(pgm_state, m_arm_ram)
AM_RANGE(0x38000000, 0x3801ffff) AM_READWRITE(svg_arm7_shareram_r, svg_arm7_shareram_w)
AM_RANGE(0x48000000, 0x48000003) AM_READWRITE(svg_latch_arm_r, svg_latch_arm_w) /* 68k Latch */
AM_RANGE(0x40000018, 0x4000001b) AM_WRITE(svg_arm7_ram_sel_w) /* RAM SEL */
AM_RANGE(0x50000000, 0x500003ff) AM_RAM
ADDRESS_MAP_END
/******* ARM 55857G *******/
MACHINE_CONFIG_DERIVED( svg, pgm )
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_PROGRAM_MAP(svg_68k_mem)
/* protection CPU */
MCFG_CPU_ADD("prot", ARM7, 33333333) // 55857G
MCFG_CPU_PROGRAM_MAP(55857G_arm7_map)
MACHINE_CONFIG_END
static void svg_basic_init(running_machine &machine)
{
pgm_state *state = machine.driver_data<pgm_state>();
pgm_basic_init(machine);
state->m_svg_shareram[0] = auto_alloc_array(machine, UINT32, 0x10000 / 4);
state->m_svg_shareram[1] = auto_alloc_array(machine, UINT32, 0x10000 / 4);
state->m_svg_ram_sel = 0;
state->save_pointer(NAME(state->m_svg_shareram[0]), 0x10000 / 4);
state->save_pointer(NAME(state->m_svg_shareram[1]), 0x10000 / 4);
state->save_item(NAME(state->m_svg_ram_sel));
}
static void pgm_create_dummy_internal_arm_region(running_machine &machine)
{
UINT16 *temp16 = (UINT16 *)machine.region("prot")->base();
// fill with RX 14
int i;
for (i=0;i<0x4000/2;i+=2)
{
temp16[i] = 0xff1e;
temp16[i+1] = 0xe12f;
}
// jump straight to external area
temp16[(0x0000)/2] = 0xd088;
temp16[(0x0002)/2] = 0xe59f;
temp16[(0x0004)/2] = 0x0680;
temp16[(0x0006)/2] = 0xe3a0;
temp16[(0x0008)/2] = 0xff10;
temp16[(0x000a)/2] = 0xe12f;
temp16[(0x0090)/2] = 0x0400;
temp16[(0x0092)/2] = 0x1000;
}
static void kov2_latch_init( running_machine &machine )
{
pgm_state *state = machine.driver_data<pgm_state>();
state->m_kov2_latchdata_68k_w = 0;
state->m_kov2_latchdata_arm_w = 0;
state->save_item(NAME(state->m_kov2_latchdata_68k_w));
state->save_item(NAME(state->m_kov2_latchdata_arm_w));
}
DRIVER_INIT( theglad )
{
svg_basic_init(machine);
pgm_theglad_decrypt(machine);
kov2_latch_init(machine);
pgm_create_dummy_internal_arm_region(machine);
}
DRIVER_INIT( svg )
{
svg_basic_init(machine);
pgm_svg_decrypt(machine);
kov2_latch_init(machine);
pgm_create_dummy_internal_arm_region(machine);
}
DRIVER_INIT( svgpcb )
{
svg_basic_init(machine);
pgm_svgpcb_decrypt(machine);
kov2_latch_init(machine);
pgm_create_dummy_internal_arm_region(machine);
}
DRIVER_INIT( killbldp )
{
svg_basic_init(machine);
pgm_killbldp_decrypt(machine);
kov2_latch_init(machine);
}
static READ32_HANDLER( dmnfrnt_speedup_r )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
int pc = cpu_get_pc(&space->device());
if (pc == 0x8000fea) device_eat_cycles(&space->device(), 500);
// else printf("dmn_speedup_r %08x\n", pc);
return state->m_arm_ram[0x000444/4];
}
static READ16_HANDLER( dmnfrnt_main_speedup_r )
{
UINT16 data = pgm_mainram[0xa03c/2];
int pc = cpu_get_pc(&space->device());
if (pc == 0x10193a) device_spin_until_interrupt(&space->device());
else if (pc == 0x1019a4) device_spin_until_interrupt(&space->device());
return data;
}
DRIVER_INIT( dmnfrnt )
{
pgm_state *state = machine.driver_data<pgm_state>();
svg_basic_init(machine);
pgm_dfront_decrypt(machine);
kov2_latch_init(machine);
/* put some fake code for the ARM here ... */
pgm_create_dummy_internal_arm_region(machine);
machine.device("prot")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x18000444, 0x18000447, FUNC(dmnfrnt_speedup_r));
machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x80a03c, 0x80a03d, FUNC(dmnfrnt_main_speedup_r));
state->m_svg_ram_sel = 1;
// the internal rom probably also supplies the region here
// we have to copy it to both shared ram regions because it reads from a different one before the attract story?
// could be a timing error? or shared ram behavior isn't how we think it is?
UINT16 *share16;
share16 = (UINT16 *)(state->m_svg_shareram[1]);
share16[0x158/2] = 0x0005;
share16 = (UINT16 *)(state->m_svg_shareram[0]);
share16[0x158/2] = 0x0005;
}
DRIVER_INIT( happy6 )
{
svg_basic_init(machine);
pgm_happy6_decrypt(machine);
kov2_latch_init(machine);
pgm_create_dummy_internal_arm_region(machine);
}

608
src/mame/machine/pgmprot4.c Normal file
View File

@ -0,0 +1,608 @@
/***********************************************************************
PGM 022 + 025 PGM protection emulation
these are simulations of the IGS 022 and 025 protection combination
used on the following PGM games
The Killing Blade
Dragon World 3*
Dragon World 3 EX*
* preliminary, not working
----
IGS022 is an encrypted DMA device, most likely an MCU of some sort
IGS025 is some kind of state machine / logic device which the game
uses for various securit checks, and to determine the region of the
game based on string sequences.
***********************************************************************/
#include "emu.h"
#include "includes/pgm.h"
/* The IGS022 is an MCU which performs encrypted DMA used by
- The Killing Blade
- Dragon World 3
There is also an automatic transfer which happens on startup using params stored in the data ROM.
This has been verified on real hardware running without any 68k game program.
*/
static void IGS022_do_dma(running_machine& machine, UINT16 src, UINT16 dst, UINT16 size, UINT16 mode)
{
pgm_state *state = machine.driver_data<pgm_state>();
UINT16 param;
/*
P_SRC =0x300290 (offset from prot rom base)
P_DST =0x300292 (words from 0x300000)
P_SIZE=0x300294 (words)
P_MODE=0x300296
Mode 5 direct
Mode 6 swap nibbles and bytes
1,2,3 table based ops
*/
//mame_printf_debug("src %04x dst %04x size %04x mode %04x\n", src, dst, size, mode);
//if (src&1) mame_printf_debug("odd offset\n");
param = mode >> 8;
mode &=0xf; // what are the other bits?
if ((mode == 0) || (mode == 1) || (mode == 2) || (mode == 3))
{
/* mode3 applies a xor from a 0x100 byte table to the data being
transferred
the table is stored at the start of the protection rom.
the param used with the mode gives a start offset into the table
odd offsets seem to change the table slightly (see rawDataOdd)
*/
/*
unsigned char rawDataOdd[256] = {
0xB6, 0xA8, 0xB1, 0x5D, 0x2C, 0x5D, 0x4F, 0xC1,
0xCF, 0x39, 0x3A, 0xB7, 0x65, 0x85, 0xD9, 0xEE,
0xDB, 0x7B, 0x5F, 0x81, 0x03, 0x6D, 0xEB, 0x07,
0x0F, 0xB5, 0x61, 0x59, 0xCD, 0x60, 0x06, 0x21,
0xA0, 0x99, 0xDD, 0x27, 0x42, 0xD7, 0xC5, 0x5B,
0x3B, 0xC6, 0x4F, 0xA2, 0x20, 0xF6, 0x61, 0x61,
0x8C, 0x46, 0x8C, 0xCA, 0xE0, 0x0E, 0x2C, 0xE9,
0xBA, 0x0F, 0x45, 0x6D, 0x36, 0x1C, 0x18, 0x37,
0xE7, 0x85, 0x89, 0xA4, 0x94, 0x46, 0x30, 0x9B,
0xB2, 0xF4, 0x41, 0x55, 0xA5, 0x63, 0x1C, 0xEF,
0xB7, 0x18, 0xB3, 0xB1, 0xD4, 0x72, 0xA0, 0x1C,
0x0B, 0x97, 0x02, 0xB6, 0xC5, 0x1F, 0x1B, 0x94,
0xC3, 0x83, 0xAA, 0xAC, 0xD9, 0x44, 0x09, 0xD7,
0x6C, 0xDB, 0x07, 0xA9, 0xAD, 0x64, 0x83, 0xF1,
0x92, 0x09, 0xCD, 0x0E, 0x99, 0x2F, 0xBC, 0xF8,
0x3C, 0x63, 0x8F, 0x0A, 0x33, 0x03, 0x84, 0x91,
0x6C, 0xAC, 0x3A, 0x15, 0xCB, 0x67, 0xC7, 0x69,
0xA1, 0x92, 0x99, 0x74, 0xEE, 0x90, 0x0D, 0xBE,
0x57, 0x30, 0xD1, 0xBA, 0xE5, 0xDE, 0xFA, 0xD6,
0x83, 0x8C, 0xE4, 0x43, 0x36, 0x5E, 0xCD, 0x84,
0x1A, 0x18, 0x31, 0xB9, 0x20, 0x48, 0xE3, 0xA8,
0x89, 0x32, 0xF0, 0x90, 0x21, 0x80, 0x33, 0xAE,
0x3C, 0xA6, 0xB8, 0x8C, 0x72, 0x17, 0xD1, 0x0C,
0x1A, 0x29, 0xFA, 0x38, 0x87, 0xC9, 0x6E, 0xC7,
0x05, 0xDE, 0x85, 0x6E, 0x92, 0x7E, 0xD4, 0xED,
0x5C, 0xD3, 0x03, 0xD4, 0xFE, 0xCB, 0x6C, 0x19,
0x7A, 0x83, 0x79, 0x5B, 0xF6, 0x71, 0xBA, 0xF4,
0x37, 0x53, 0xC9, 0xC1, 0xDE, 0xDB, 0xDE, 0xB1,
0x64, 0x17, 0x31, 0x0E, 0xD7, 0xA2, 0x13, 0x8E,
0x52, 0x8D, 0xCB, 0x19, 0x3D, 0x0B, 0x31, 0x58,
0x4A, 0xDE, 0x0C, 0x01, 0x2B, 0x85, 0x2D, 0xE5,
0x13, 0x22, 0x48, 0xB6, 0xF3, 0x2D, 0x00, 0x9A
};
*/
int x;
UINT16 *PROTROM = (UINT16*)machine.region("igs022data")->base();
for (x = 0; x < size; x++)
{
//UINT16 *RAMDUMP = (UINT16*)space->machine().region("user2")->base();
//UINT16 dat = RAMDUMP[dst + x];
UINT16 dat2 = PROTROM[src + x];
UINT8 extraoffset = param&0xfe; // the lowest bit changed the table addressing in tests, see 'rawDataOdd' table instead.. it's still related to the main one, not identical
UINT8* dectable = (UINT8*)machine.region("igs022data")->base();//rawDataEven; // the basic decryption table is at the start of the mcu data rom! at least in killbld
UINT16 extraxor = ((dectable[((x*2)+0+extraoffset)&0xff]) << 8) | (dectable[((x*2)+1+extraoffset)&0xff] << 0);
dat2 = ((dat2 & 0x00ff)<<8) | ((dat2 & 0xff00)>>8);
// mode==0 plain
if (mode==3) dat2 ^= extraxor;
if (mode==2) dat2 += extraxor;
if (mode==1) dat2 -= extraxor;
//if (dat!=dat2)
// printf("Mode %04x Param %04x Mismatch %04x %04x\n", mode, param, dat, dat2);
state->m_sharedprotram[dst + x] = dat2;
}
/* Killing Blade: hack, patches out some additional security checks... we need to emulate them instead! */
// different region IGS025 devices supply different sequences - we currently only have the china sequence for Killing Blade
//if ((mode==3) && (param==0x54) && (src*2==0x2120) && (dst*2==0x2600)) state->m_sharedprotram[0x2600 / 2] = 0x4e75;
}
if (mode == 4)
{
mame_printf_debug("unhandled copy mode %04x!\n", mode);
// not used by killing blade
/* looks almost like a fixed value xor, but isn't */
}
else if (mode == 5)
{
/* mode 5 seems to be a straight copy */
int x;
UINT16 *PROTROM = (UINT16*)machine.region("igs022data")->base();
for (x = 0; x < size; x++)
{
UINT16 dat = PROTROM[src + x];
state->m_sharedprotram[dst + x] = dat;
}
}
else if (mode == 6)
{
/* mode 6 seems to swap bytes and nibbles */
int x;
UINT16 *PROTROM = (UINT16*)machine.region("igs022data")->base();
for (x = 0; x < size; x++)
{
UINT16 dat = PROTROM[src + x];
dat = ((dat & 0xf000) >> 12)|
((dat & 0x0f00) >> 4)|
((dat & 0x00f0) << 4)|
((dat & 0x000f) << 12);
state->m_sharedprotram[dst + x] = dat;
}
}
else if (mode == 7)
{
mame_printf_debug("unhandled copy mode %04x!\n", mode);
// not used by killing blade
/* weird mode, the params get left in memory? - maybe it's a NOP? */
}
else
{
mame_printf_debug("unhandled copy mode %04x!\n", mode);
// not used by killing blade
/* invalid? */
}
}
// the internal MCU boot code automatically does this DMA
// and puts the version # of the data rom in ram
static void IGS022_reset(running_machine& machine)
{
int i;
UINT16 *PROTROM = (UINT16*)machine.region("igs022data")->base();
pgm_state *state = machine.driver_data<pgm_state>();
UINT16 tmp;
// fill ram with A5 patern
for (i = 0; i < 0x4000/2; i++)
state->m_sharedprotram[i] = 0xa55a;
// the auto-dma
UINT16 src = PROTROM[0x100 / 2];
UINT32 dst = PROTROM[0x102 / 2];
UINT16 size = PROTROM[0x104/ 2];
UINT16 mode = PROTROM[0x106 / 2];
src = ((src & 0xff00) >> 8) | ((src & 0x00ff) << 8);
dst = ((dst & 0xff00) >> 8) | ((dst & 0x00ff) << 8);
size = ((size & 0xff00) >> 8) | ((size & 0x00ff) << 8);
mode &= 0xff;
src >>= 1;
printf("Auto-DMA %04x %04x %04x %04x\n",src,dst,size,mode);
IGS022_do_dma(machine,src,dst,size,mode);
// there is also a version ID? (or is it some kind of checksum) that is stored in the data rom, and gets copied..
// Dragon World 3 checks it
tmp = PROTROM[0x114/2];
tmp = ((tmp & 0xff00) >> 8) | ((tmp & 0x00ff) << 8);
state->m_sharedprotram[0x2a2/2] = tmp;
}
static void IGS022_handle_command(running_machine& machine)
{
pgm_state *state = machine.driver_data<pgm_state>();
UINT16 cmd = state->m_sharedprotram[0x200/2];
//mame_printf_debug("command %04x\n", cmd);
if (cmd == 0x6d) //Store values to asic ram
{
UINT32 p1 = (state->m_sharedprotram[0x298/2] << 16) | state->m_sharedprotram[0x29a/2];
UINT32 p2 = (state->m_sharedprotram[0x29c/2] << 16) | state->m_sharedprotram[0x29e/2];
if ((p2 & 0xffff) == 0x9) //Set value
{
int reg = (p2 >> 16) & 0xffff;
if (reg & 0x200)
state->m_kb_regs[reg & 0xff] = p1;
}
if ((p2 & 0xffff) == 0x6) //Add value
{
int src1 = (p1 >> 16) & 0xff;
int src2 = (p1 >> 0) & 0xff;
int dst = (p2 >> 16) & 0xff;
state->m_kb_regs[dst] = state->m_kb_regs[src2] - state->m_kb_regs[src1];
}
if ((p2 & 0xffff) == 0x1) //Add Imm?
{
int reg = (p2 >> 16) & 0xff;
int imm = (p1 >> 0) & 0xffff;
state->m_kb_regs[reg] += imm;
}
if ((p2 & 0xffff) == 0xa) //Get value
{
int reg = (p1 >> 16) & 0xFF;
state->m_sharedprotram[0x29c/2] = (state->m_kb_regs[reg] >> 16) & 0xffff;
state->m_sharedprotram[0x29e/2] = state->m_kb_regs[reg] & 0xffff;
}
}
if(cmd == 0x4f) //memcpy with encryption / scrambling
{
UINT16 src = state->m_sharedprotram[0x290 / 2] >> 1; // ?
UINT32 dst = state->m_sharedprotram[0x292 / 2];
UINT16 size = state->m_sharedprotram[0x294 / 2];
UINT16 mode = state->m_sharedprotram[0x296 / 2];
IGS022_do_dma(machine, src,dst,size,mode);
}
}
static WRITE16_HANDLER( killbld_igs025_prot_w )
{
// mame_printf_debug("killbrd prot r\n");
// return 0;
pgm_state *state = space->machine().driver_data<pgm_state>();
offset &= 0xf;
if (offset == 0)
state->m_kb_cmd = data;
else //offset==2
{
logerror("%06X: ASIC25 W CMD %X VAL %X\n", cpu_get_pc(&space->device()), state->m_kb_cmd, data);
if (state->m_kb_cmd == 0)
state->m_kb_reg = data;
else if (state->m_kb_cmd == 2)
{
if (data == 1) //Execute cmd
{
IGS022_handle_command(space->machine());
state->m_kb_reg++;
}
}
else if (state->m_kb_cmd == 4)
state->m_kb_ptr = data;
else if (state->m_kb_cmd == 0x20)
state->m_kb_ptr++;
}
}
static READ16_HANDLER( killbld_igs025_prot_r )
{
// mame_printf_debug("killbld prot w\n");
pgm_state *state = space->machine().driver_data<pgm_state>();
UINT16 res ;
offset &= 0xf;
res = 0;
if (offset == 1)
{
if (state->m_kb_cmd == 1)
{
res = state->m_kb_reg & 0x7f;
}
else if (state->m_kb_cmd == 5)
{
UINT8 kb_region_sequence[11] = {0x17, 0x14, 0x91, 0x89, 0x21, 0xD5, 0x7C, 0x65, 0x8F, 0x8E, 0xE1};
UINT8 ret;
// this isn't properly understood.. should be some kind of bitswap / xor / shift..based on values written to 0x22/0x23 etc.?
// return hardcoded china sequence results for now, avoids rom patch
if (state->m_kb_region_sequence_position < 11)
{
ret = kb_region_sequence[state->m_kb_region_sequence_position];
state->m_kb_region_sequence_position++;
}
else
{
UINT32 protvalue = 0x89911400 | input_port_read(space->machine(), "Region");
ret = (protvalue >> (8 * (state->m_kb_ptr - 1))) & 0xff;
}
res = 0x3f00 | ret; // always 0x3fxx in logged behavior...
}
}
logerror("%06X: ASIC25 R CMD %X VAL %X\n", cpu_get_pc(&space->device()), state->m_kb_cmd, res);
return res;
}
static MACHINE_RESET( killbld )
{
pgm_state *state = machine.driver_data<pgm_state>();
MACHINE_RESET_CALL(pgm);
/* fill the protection ram with a5 + auto dma */
IGS022_reset(machine);
// Reset IGS025 stuff
state->m_kb_cmd = 0;
state->m_kb_reg = 0;
state->m_kb_ptr = 0;
state->m_kb_region_sequence_position = 0;
memset(state->m_kb_regs, 0, 0x10);
}
DRIVER_INIT( killbld )
{
pgm_state *state = machine.driver_data<pgm_state>();
pgm_basic_init(machine);
pgm_killbld_decrypt(machine);
machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0xd40000, 0xd40003, FUNC(killbld_igs025_prot_r), FUNC(killbld_igs025_prot_w));
state->m_kb_cmd = 0;
state->m_kb_reg = 0;
state->m_kb_ptr = 0;
state->m_kb_region_sequence_position = 0;
memset(state->m_kb_regs, 0, 0x10);
state->save_item(NAME(state->m_kb_region_sequence_position));
state->save_item(NAME(state->m_kb_cmd));
state->save_item(NAME(state->m_kb_reg));
state->save_item(NAME(state->m_kb_ptr));
state->save_item(NAME(state->m_kb_regs));
}
static MACHINE_RESET( dw3 )
{
pgm_state *state = machine.driver_data<pgm_state>();
MACHINE_RESET_CALL(pgm);
/* fill the protection ram with a5 + auto dma */
IGS022_reset(machine);
/* game won't boot unless various values are in protection RAM
- these should almost certainly end up there as the result of executing the protection
commands are startup, but which, and how? */
// state->m_sharedprotram[0x200/2] = 0x006d;
state->m_sharedprotram[0x202/2] = 0x007c; // it cares about this, operation status flag?
// state->m_sharedprotram[0x20c/2] = 0x0000;
// state->m_sharedprotram[0x20e/2] = 0x0007;
// state->m_sharedprotram[0x210/2] = 0x0000;
// state->m_sharedprotram[0x212/2] = 0x0004;
// state->m_sharedprotram[0x214/2] = 0x0000;
// state->m_sharedprotram[0x216/2] = 0x0007;
// state->m_sharedprotram[0x218/2] = 0x0000;
// state->m_sharedprotram[0x21a/2] = 0x0004;
// state->m_sharedprotram[0x288/2] = 0x0000;
// state->m_sharedprotram[0x28a/2] = 0x00c2;
// state->m_sharedprotram[0x28c/2] = 0x0000;
// state->m_sharedprotram[0x28e/2] = 0x00c2;
// state->m_sharedprotram[0x290/2] = 0x0500;
// state->m_sharedprotram[0x292/2] = 0x1000;
// state->m_sharedprotram[0x294/2] = 0x00c3;
// state->m_sharedprotram[0x296/2] = 0x7104;
// state->m_sharedprotram[0x298/2] = 0x0000;
// state->m_sharedprotram[0x29a/2] = 0x0003;
// state->m_sharedprotram[0x29c/2] = 0x0108;
// state->m_sharedprotram[0x29e/2] = 0x0009;
// state->m_sharedprotram[0x2a2/2] = 0x84f6; // it cares about this, it's the version number of the data rom, copied automatically!
// state->m_sharedprotram[0x2ac/2] = 0x006d;
// state->m_sharedprotram[0x2ae/2] = 0x0000;
// state->m_sharedprotram[0x2b0/2] = 0xaf56;
// Reset IGS025 stuff
state->m_kb_cmd = 0;
state->m_kb_reg = 0;
state->m_kb_ptr = 0;
state->m_kb_region_sequence_position = 0;
memset(state->m_kb_regs, 0, 0x10);
}
static int reg;
static int ptr=0;
#define DW3BITSWAP(s,d,bs,bd) d=((d&(~(1<<bd)))|(((s>>bs)&1)<<bd))
static UINT8 dw3_swap;
static WRITE16_HANDLER( drgw3_igs025_prot_w )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
offset&=0xf;
if(offset==0)
state->m_kb_cmd=data;
else //offset==2
{
printf("%06X: ASIC25 W CMD %X VAL %X\n",cpu_get_pc(&space->device()),state->m_kb_cmd,data);
if(state->m_kb_cmd==0)
reg=data;
else if(state->m_kb_cmd==3) //??????????
{
dw3_swap = data;
printf("SWAP %02x\n",dw3_swap);
}
//else if(kb_cmd==4)
// ptr=data;
else if(state->m_kb_cmd==0x20)
ptr++;
}
}
static READ16_HANDLER( drgw3_igs025_prot_r )
{
// mame_printf_debug("killbld prot w\n");
pgm_state *state = space->machine().driver_data<pgm_state>();
UINT16 res ;
offset&=0xf;
res=0;
if(offset==1)
{
if(state->m_kb_cmd==0) //swap
{
UINT8 v1=(dw3_swap+1)&0x7F;
UINT8 v2=0;
DW3BITSWAP(v1,v2,7,0);
DW3BITSWAP(v1,v2,6,1);
DW3BITSWAP(v1,v2,5,2);
DW3BITSWAP(v1,v2,4,3);
DW3BITSWAP(v1,v2,3,4);
DW3BITSWAP(v1,v2,2,5);
DW3BITSWAP(v1,v2,1,6);
DW3BITSWAP(v1,v2,0,7);
res=v2;
}
else if(state->m_kb_cmd==1)
{
res=reg&0x7f;
}
else if(state->m_kb_cmd==5)
{
UINT32 protvalue;
protvalue = 0x60000|input_port_read(space->machine(), "Region");
res=(protvalue>>(8*(ptr-1)))&0xff;
}
}
logerror("%06X: ASIC25 R CMD %X VAL %X\n",cpu_get_pc(&space->device()),state->m_kb_cmd,res);
return res;
}
DRIVER_INIT( drgw3 )
{
pgm_basic_init(machine);
/*
pgm_state *state = machine.driver_data<pgm_state>();
{
int x;
UINT16 *RAMDUMP = (UINT16*)machine.region("user2")->base();
for (x=0;x<(0x4000/2);x++)
{
state->m_sharedprotram[x] = RAMDUMP[x];
if((x>=0x100)&&(x<0x110)) printf("data 0x%4x, offset:%x\n",state->m_sharedprotram[x],x);
}
}
*/
machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0xDA5610, 0xDA5613, FUNC(drgw3_igs025_prot_r), FUNC(drgw3_igs025_prot_w));
pgm_dw3_decrypt(machine);
}
static ADDRESS_MAP_START( killbld_mem, AS_PROGRAM, 16)
AM_IMPORT_FROM(pgm_mem)
AM_RANGE(0x100000, 0x2fffff) AM_ROMBANK("bank1") /* Game ROM */
AM_RANGE(0x300000, 0x303fff) AM_RAM AM_BASE_MEMBER(pgm_state, m_sharedprotram) // Shared with protection device
ADDRESS_MAP_END
MACHINE_CONFIG_DERIVED( killbld, pgm )
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_PROGRAM_MAP(killbld_mem)
MCFG_MACHINE_RESET(killbld)
MACHINE_CONFIG_END
MACHINE_CONFIG_DERIVED( dw3, pgm )
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_PROGRAM_MAP(killbld_mem)
MCFG_MACHINE_RESET(dw3)
MACHINE_CONFIG_END
INPUT_PORTS_START( killbld )
PORT_INCLUDE ( pgm )
PORT_MODIFY("Region") /* Region - supplied by protection device */
PORT_DIPNAME( 0x00ff, 0x0021, "Region (not currently working)" ) // different regions supply different protection code sequences, we only have the China one ATM
PORT_DIPSETTING( 0x0016, DEF_STR( Taiwan ) )
PORT_DIPSETTING( 0x0017, DEF_STR( China ) )
PORT_DIPSETTING( 0x0018, DEF_STR( Hong_Kong ) )
PORT_DIPSETTING( 0x0019, DEF_STR( Japan ) )
// PORT_DIPSETTING( 0x001a, "1a" ) // invalid
// PORT_DIPSETTING( 0x001b, "1b" ) // invalid
// PORT_DIPSETTING( 0x001c, "1c" ) // invalid
// PORT_DIPSETTING( 0x001d, "1d" ) // invalid
// PORT_DIPSETTING( 0x001e, "1e" ) // invalid
// PORT_DIPSETTING( 0x001f, "1f" ) // invalid
PORT_DIPSETTING( 0x0020, DEF_STR( Korea ) )
PORT_DIPSETTING( 0x0021, DEF_STR( World ) )
INPUT_PORTS_END
INPUT_PORTS_START( dw3 )
PORT_INCLUDE ( pgm )
PORT_MODIFY("Region") /* Region - supplied by protection device */
PORT_CONFNAME( 0x000f, 0x0006, DEF_STR( Region ) )
PORT_CONFSETTING( 0x0000, "0" )
PORT_CONFSETTING( 0x0001, "1" )
PORT_CONFSETTING( 0x0002, "2" )
PORT_CONFSETTING( 0x0003, "3" )
PORT_CONFSETTING( 0x0004, "4" )
PORT_CONFSETTING( 0x0005, "5" )
PORT_CONFSETTING( 0x0006, DEF_STR( World ) )
PORT_CONFSETTING( 0x0007, "7" )
INPUT_PORTS_END

112
src/mame/machine/pgmprot5.c Normal file
View File

@ -0,0 +1,112 @@
/***********************************************************************
PGM 012 + 025 PGM protection emulation
these are simulations of the IGS 012 and 025 protection combination
used on the following PGM games
Dragon World 2
----
IGS012 provides ROM overlay???
IGS025 is some kind of state machine / logic device which the game
uses for various security checks bitswap checks.
Simulation is incomplete for some regions
***********************************************************************/
#include "emu.h"
#include "includes/pgm.h"
/* Dragon World 2 */
#define DW2BITSWAP(s,d,bs,bd) d=((d&(~(1<<bd)))|(((s>>bs)&1)<<bd))
//Use this handler for reading from 0xd80000-0xd80002
READ16_HANDLER( dw2_d80000_r )
{
// addr&=0xff;
// if(dw2reg<0x20) //NOT SURE!!
{
//The value at 0x80EECE is computed in the routine at 0x107c18
UINT16 d = pgm_mainram[0xEECE/2];
UINT16 d2 = 0;
d = (d >> 8) | (d << 8);
DW2BITSWAP(d, d2, 7, 0);
DW2BITSWAP(d, d2, 4, 1);
DW2BITSWAP(d, d2, 5, 2);
DW2BITSWAP(d, d2, 2, 3);
DW2BITSWAP(d, d2, 15, 4);
DW2BITSWAP(d, d2, 1, 5);
DW2BITSWAP(d, d2, 10, 6);
DW2BITSWAP(d, d2, 13, 7);
// ... missing bitswaps here (8-15) there is not enough data to know them
// the code only checks the lowest 8 bytes
return d2;
}
}
static void drgwld2_common_init(running_machine &machine)
{
pgm_basic_init(machine);
pgm_dw2_decrypt(machine);
/*
Info from Elsemi
Here is how to "bypass" the dw2 hang protection, it fixes the mode
select and after failing in the 2nd stage (probably there are other checks
out there).
*/
machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0xd80000, 0xd80003, FUNC(dw2_d80000_r));
}
DRIVER_INIT( drgw2 )
{ /* incomplete? */
UINT16 *mem16 = (UINT16 *)machine.region("maincpu")->base();
drgwld2_common_init(machine);
/* These ROM patches are not hacks, the protection device
overlays the normal ROM code, this has been confirmed on a real PCB
although some addresses may be missing */
mem16[0x131098 / 2] = 0x4e93;
mem16[0x13113e / 2] = 0x4e93;
mem16[0x1311ce / 2] = 0x4e93;
}
DRIVER_INIT( dw2v100x )
{
UINT16 *mem16 = (UINT16 *)machine.region("maincpu")->base();
drgwld2_common_init(machine);
mem16[0x131084 / 2] = 0x4e93;
mem16[(0x131084+0xa6) / 2] = 0x4e93;
mem16[(0x131084+0x136) / 2] = 0x4e93;
}
DRIVER_INIT( drgw2c )
{
UINT16 *mem16 = (UINT16 *)machine.region("maincpu")->base();
drgwld2_common_init(machine);
/* These ROM patches are not hacks, the protection device
overlays the normal ROM code, this has been confirmed on a real PCB
although some addresses may be missing */
mem16[0x1303bc / 2] = 0x4e93;
mem16[0x130462 / 2] = 0x4e93;
mem16[0x1304f2 / 2] = 0x4e93;
}
DRIVER_INIT( drgw2j )
{
UINT16 *mem16 = (UINT16 *)machine.region("maincpu")->base();
drgwld2_common_init(machine);
/* These ROM patches are not hacks, the protection device
overlays the normal ROM code, this has been confirmed on a real PCB
although some addresses may be missing */
mem16[0x1302c0 / 2] = 0x4e93;
mem16[0x130366 / 2] = 0x4e93;
mem16[0x1303f6 / 2] = 0x4e93;
}

245
src/mame/machine/pgmprot6.c Normal file
View File

@ -0,0 +1,245 @@
/***********************************************************************
PGM 012 + 28 PGM protection emulation
these are simulations of the IGS 012 and 025 protection combination
used on the following PGM games
Oriental Legend Super
----
IGS28 is some kind of encrypted DMA device, works with data in an
external ROM, more advaned version of IGS022?
IGS025 is some kind of state machine, bitswaps etc.
Simulation is incomplete
***********************************************************************/
#include "emu.h"
#include "includes/pgm.h"
static UINT32 olds_prot_addr( UINT16 addr )
{
UINT32 mode = addr & 0xff;
UINT32 offset = addr >> 8;
UINT32 realaddr;
switch(mode)
{
case 0x0:
case 0x5:
case 0xa:
realaddr = 0x402a00 + (offset << 2);
break;
case 0x2:
case 0x8:
realaddr = 0x402e00 + (offset << 2);
break;
case 0x1:
realaddr = 0x40307e;
break;
case 0x3:
realaddr = 0x403090;
break;
case 0x4:
realaddr = 0x40309a;
break;
case 0x6:
realaddr = 0x4030a4;
break;
case 0x7:
realaddr = 0x403000;
break;
case 0x9:
realaddr = 0x40306e;
break;
default:
realaddr = 0;
}
return realaddr;
}
static UINT32 olds_read_reg( running_machine &machine, UINT16 addr )
{
pgm_state *state = machine.driver_data<pgm_state>();
UINT32 protaddr = (olds_prot_addr(addr) - 0x400000) / 2;
return state->m_sharedprotram[protaddr] << 16 | state->m_sharedprotram[protaddr + 1];
}
static void olds_write_reg( running_machine &machine, UINT16 addr, UINT32 val )
{
pgm_state *state = machine.driver_data<pgm_state>();
state->m_sharedprotram[(olds_prot_addr(addr) - 0x400000) / 2] = val >> 16;
state->m_sharedprotram[(olds_prot_addr(addr) - 0x400000) / 2 + 1] = val & 0xffff;
}
static MACHINE_RESET( olds )
{
pgm_state *state = machine.driver_data<pgm_state>();
UINT16 *mem16 = (UINT16 *)machine.region("user2")->base();
int i;
MACHINE_RESET_CALL(pgm);
/* populate shared protection ram with data read from pcb .. */
for (i = 0; i < 0x4000 / 2; i++)
{
state->m_sharedprotram[i] = mem16[i];
}
//ROM:004008B4 .word 0xFBA5
for(i = 0; i < 0x4000 / 2; i++)
{
if (state->m_sharedprotram[i] == (0xffff - i))
state->m_sharedprotram[i] = 0x4e75;
}
}
static READ16_HANDLER( olds_r )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
UINT16 res = 0;
if (offset == 1)
{
if (state->m_kb_cmd == 1)
res = state->m_kb_reg & 0x7f;
if (state->m_kb_cmd == 2)
res = state->m_olds_bs | 0x80;
if (state->m_kb_cmd == 3)
res = state->m_olds_cmd3;
else if (state->m_kb_cmd == 5)
{
UINT32 protvalue = 0x900000 | input_port_read(space->machine(), "Region"); // region from protection device.
res = (protvalue >> (8 * (state->m_kb_ptr - 1))) & 0xff; // includes region 1 = taiwan , 2 = china, 3 = japan (title = orlegend special), 4 = korea, 5 = hongkong, 6 = world
}
}
logerror("%06X: ASIC25 R CMD %X VAL %X\n", cpu_get_pc(&space->device()), state->m_kb_cmd, res);
return res;
}
static WRITE16_HANDLER( olds_w )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
if (offset == 0)
state->m_kb_cmd = data;
else //offset==2
{
logerror("%06X: ASIC25 W CMD %X VAL %X\n",cpu_get_pc(&space->device()), state->m_kb_cmd, data);
if (state->m_kb_cmd == 0)
state->m_kb_reg = data;
else if(state->m_kb_cmd == 2) //a bitswap=
{
int reg = 0;
if (data & 0x01)
reg |= 0x40;
if (data & 0x02)
reg |= 0x80;
if (data & 0x04)
reg |= 0x20;
if (data & 0x08)
reg |= 0x10;
state->m_olds_bs = reg;
}
else if (state->m_kb_cmd == 3)
{
UINT16 cmd = state->m_sharedprotram[0x3026 / 2];
switch (cmd)
{
case 0x11:
case 0x12:
break;
case 0x64:
{
UINT16 cmd0 = state->m_sharedprotram[0x3082 / 2];
UINT16 val0 = state->m_sharedprotram[0x3050 / 2]; //CMD_FORMAT
{
if ((cmd0 & 0xff) == 0x2)
olds_write_reg(space->machine(), val0, olds_read_reg(space->machine(), val0) + 0x10000);
}
break;
}
default:
break;
}
state->m_olds_cmd3 = ((data >> 4) + 1) & 0x3;
}
else if (state->m_kb_cmd == 4)
state->m_kb_ptr = data;
else if(state->m_kb_cmd == 0x20)
state->m_kb_ptr++;
}
}
static READ16_HANDLER( olds_prot_swap_r )
{
if (cpu_get_pc(&space->device()) < 0x100000) //bios
return pgm_mainram[0x178f4 / 2];
else //game
return pgm_mainram[0x178d8 / 2];
}
DRIVER_INIT( olds )
{
pgm_state *state = machine.driver_data<pgm_state>();
pgm_basic_init(machine);
machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0xdcb400, 0xdcb403, FUNC(olds_r), FUNC(olds_w));
machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x8178f4, 0x8178f5, FUNC(olds_prot_swap_r));
state->m_kb_cmd = 0;
state->m_kb_reg = 0;
state->m_kb_ptr = 0;
state->m_olds_bs = 0;
state->m_olds_cmd3 = 0;
state->save_item(NAME(state->m_kb_cmd));
state->save_item(NAME(state->m_kb_reg));
state->save_item(NAME(state->m_kb_ptr));
state->save_item(NAME(state->m_olds_bs));
state->save_item(NAME(state->m_olds_cmd3));
}
static ADDRESS_MAP_START( olds_mem, AS_PROGRAM, 16)
AM_IMPORT_FROM(pgm_mem)
AM_RANGE(0x100000, 0x3fffff) AM_ROMBANK("bank1") /* Game ROM */
AM_RANGE(0x400000, 0x403fff) AM_RAM AM_BASE_MEMBER(pgm_state, m_sharedprotram) // Shared with protection device
ADDRESS_MAP_END
MACHINE_CONFIG_DERIVED( olds, pgm )
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_PROGRAM_MAP(olds_mem)
MCFG_MACHINE_RESET(olds)
MACHINE_CONFIG_END
INPUT_PORTS_START( olds )
PORT_INCLUDE ( pgm )
PORT_MODIFY("Region") /* Region - supplied by protection device */
PORT_CONFNAME( 0x000f, 0x0006, DEF_STR( Region ) )
/* includes the following regions:
1 = taiwan, 2 = china, 3 = japan (title = orlegend special),
4 = korea, 5 = hong kong, 6 = world */
PORT_CONFSETTING( 0x0001, DEF_STR( Taiwan ) )
PORT_CONFSETTING( 0x0002, DEF_STR( China ) )
PORT_CONFSETTING( 0x0003, DEF_STR( Japan ) )
PORT_CONFSETTING( 0x0004, DEF_STR( Korea ) )
PORT_CONFSETTING( 0x0005, DEF_STR( Hong_Kong ) )
PORT_CONFSETTING( 0x0006, DEF_STR( World ) )
INPUT_PORTS_END

View File

@ -8537,6 +8537,7 @@ sderby // (c) 1996
croupier // (c) 1997 Playmark
croupiera // (c) 1997 Playmark
spacewin
luckboom
// Pacific Novelty games
sharkatt // (c) 1980
@ -8927,6 +8928,7 @@ klxyj // (c) 200?
mgfx // (c) 200?
gonefsh2 // (c) 200?
chessc2 // (c) 200?
haunthig // (c) 200?
// IGS PGM System Games
pgm

View File

@ -757,6 +757,12 @@ $(MAMEOBJ)/igs.a: \
$(DRIVERS)/spoker.o \
$(MACHINE)/pgmcrypt.o \
$(MACHINE)/pgmprot.o \
$(MACHINE)/pgmprot1.o \
$(MACHINE)/pgmprot2.o \
$(MACHINE)/pgmprot3.o \
$(MACHINE)/pgmprot4.o \
$(MACHINE)/pgmprot5.o \
$(MACHINE)/pgmprot6.o \
$(MAMEOBJ)/irem.a: \
$(DRIVERS)/m10.o $(VIDEO)/m10.o \