summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Angelo Salese <angelosa@users.noreply.github.com>2012-03-25 13:19:50 +0000
committer Angelo Salese <angelosa@users.noreply.github.com>2012-03-25 13:19:50 +0000
commit83cde9101ebb98dfeab971a94aef88ce026e8439 (patch)
treea9c41dce726009c4914f1afcd112dfcd86039d9a
parent58eb388fd50a5267b57b9150bc1e3d35dfa7b47e (diff)
New WORKING game
-------------------- Lucky Boom [f205v, David Haywood] Refactoring of the PGM protection [David Haywood, iq_132]
-rw-r--r--.gitattributes6
-rw-r--r--src/mame/drivers/igs_m027.c322
-rw-r--r--src/mame/drivers/pgm.c2398
-rw-r--r--src/mame/drivers/sderby.c111
-rw-r--r--src/mame/includes/pgm.h186
-rw-r--r--src/mame/machine/pgmprot.c1246
-rw-r--r--src/mame/machine/pgmprot1.c1624
-rw-r--r--src/mame/machine/pgmprot2.c387
-rw-r--r--src/mame/machine/pgmprot3.c298
-rw-r--r--src/mame/machine/pgmprot4.c608
-rw-r--r--src/mame/machine/pgmprot5.c112
-rw-r--r--src/mame/machine/pgmprot6.c245
-rw-r--r--src/mame/mame.lst2
-rw-r--r--src/mame/mame.mak6
14 files changed, 3944 insertions, 3607 deletions
diff --git a/.gitattributes b/.gitattributes
index 80051564396..32c22387c68 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -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
diff --git a/src/mame/drivers/igs_m027.c b/src/mame/drivers/igs_m027.c
index ca7a53e6737..d685ed42037 100644
--- a/src/mame/drivers/igs_m027.c
+++ b/src/mame/drivers/igs_m027.c
@@ -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,24 +721,270 @@ 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
***************************************************************************/
-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( 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, 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 )
diff --git a/src/mame/drivers/pgm.c b/src/mame/drivers/pgm.c
index 421a3605802..d1a8d5bc918 100644
--- a/src/mame/drivers/pgm.c
+++ b/src/mame/drivers/pgm.c
@@ -63,59 +63,32 @@ Most of these are not emulated correctly. In most cases the protection device su
game region code..
ASIC 3:
- used by:
- different per region, supplies region code
- used by:
- Oriental Legend
- function:
+ state based device?
+ see
+ machine/pgmprot.c
ASIC 25 + ASIC 12
- ASIC25 is a logic device (not MCU) which performs bitswap operations
- ASIC12 is ... ? (rom overlays?)
-
- used by:
- Dragon World 2
+ state based device + rom overlays
+ see
+ machine/pgmprot5.c
ASIC 25 + ASIC 22
- ASIC25 is a logic device (not MCU) which performs bitswap operations, and connects to the ASIC22. It differs per region.
- ASIC22 is an MCU and acts as an encrypted DMA device
+ state based device + encrypted DMA device
+ see
+ machine/pgmprot4.c
- (ASIC22 can be swapped between games with no side-effects, ASIC25 can't)
+ASIC 25 + ASIC 28
+ state based device + encrypted DMA device?
+ see
+ machine/pgmprot6.c
- used by:
- Dragon World 3
- The Killing Blade
+ASIC 027A(55857F/55857G):
+ ARM based CPUs with internal ROM
+ see
+ machine/pgmprot1.c
+ machine/pgmprot2.c
+ machine/pgmprot3.c
-ASIC 25 + ASIC 28
- ASIC25 (see above)
- ASIC28 acts as an encrypted DMA device (updated version of ASIC22 with different encryption etc.)
-
- used by:
- Oriental Legend Super
-
-ASIC 27 (55857E):
- performs a variety of calculations, quite complex, different per region, supplies region code
-
- used by:
- Knights of Valour 1 / (Plus?)
- Photo Y2k / Real and Fake
-
-ASIC 27A(55857F/55857G):
- arm7 cpu with 16kb internal rom (different per game / region) + optional external data rom
- probably used to give extra power to the system, lots of calculations are offloaded to it
- used by:
- Knights of Valour Super Heroes / Plus
- Puzzli II
- Oriental Legend Special Plus
- Knights of Valor 2 / 2 Plus
- DoDonPachi II
- Martial Masters
- The Gladiator
- Demon Front
- The Killing Blade Plus
- Spectral VS Generation
-
- The 55857G variant appears to be protected against reading even from native code.
there are probably more...
@@ -213,20 +186,13 @@ Notes:
*/
#define PGMLOGERROR 0
-#define PGMARM7LOGERROR 0
#include "emu.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"
#include "includes/pgm.h"
-#include "machine/v3021.h"
+
UINT16 *pgm_mainram;
-static void IGS022_reset(running_machine& machine);
+
static READ16_HANDLER( pgm_videoram_r )
{
@@ -259,85 +225,6 @@ static READ16_HANDLER ( z80_ram_r )
return (state->m_z80_mainram[offset * 2] << 8) | state->m_z80_mainram[offset * 2 + 1];
}
-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)]);
-}
-
static WRITE16_HANDLER ( z80_ram_w )
{
pgm_state *state = space->machine().driver_data<pgm_state>();
@@ -407,7 +294,7 @@ static WRITE8_HANDLER( z80_l3_w )
soundlatch3_w(space, 0, data);
}
-static void sound_irq( device_t *device, int level )
+void pgm_sound_irq( device_t *device, int level )
{
pgm_state *state = device->machine().driver_data<pgm_state>();
device_set_input_line(state->m_soundcpu, 0, level);
@@ -418,170 +305,16 @@ static void sound_irq( device_t *device, int level )
sound_irq
};*/
-/*** Misc Protection Handlers *************************************************************/
-
-/* Kov Superheroes */
-
-static READ32_HANDLER( kovsh_arm7_protlatch_r )
-{
- pgm_state *state = space->machine().driver_data<pgm_state>();
-
- space->machine().scheduler().synchronize(); // force resync
-
- return (state->m_kovsh_highlatch_68k_w << 16) | (state->m_kovsh_lowlatch_68k_w);
-}
-
-static WRITE32_HANDLER( kovsh_arm7_protlatch_w )
-{
- pgm_state *state = space->machine().driver_data<pgm_state>();
-
- space->machine().scheduler().synchronize(); // force resync
-
- if (ACCESSING_BITS_16_31)
- {
- state->m_kovsh_highlatch_arm_w = data >> 16;
- state->m_kovsh_highlatch_68k_w = 0;
- }
- if (ACCESSING_BITS_0_15)
- {
- state->m_kovsh_lowlatch_arm_w = data;
- state->m_kovsh_lowlatch_68k_w = 0;
- }
-}
-
-static READ16_HANDLER( kovsh_68k_protlatch_r )
-{
- pgm_state *state = space->machine().driver_data<pgm_state>();
-
- space->machine().scheduler().synchronize(); // force resync
-
- switch (offset)
- {
- case 1: return state->m_kovsh_highlatch_arm_w;
- case 0: return state->m_kovsh_lowlatch_arm_w;
- }
- return -1;
-}
-
-static WRITE16_HANDLER( kovsh_68k_protlatch_w )
-{
- pgm_state *state = space->machine().driver_data<pgm_state>();
-
- space->machine().scheduler().synchronize(); // force resync
-
- switch (offset)
- {
- case 1:
- state->m_kovsh_highlatch_68k_w = data;
- break;
-
- case 0:
- state->m_kovsh_lowlatch_68k_w = data;
- break;
- }
-}
-
-static READ16_HANDLER( kovsh_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 << 1)];
-}
-
-static WRITE16_HANDLER( kovsh_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 << 1)]);
-}
-
-
-
-
-static READ32_HANDLER( kovsh_arm7_unk_r )
-{
- pgm_state *state = space->machine().driver_data<pgm_state>();
- return state->m_kovsh_counter++;
-}
-
-static READ32_HANDLER( kovsh_exrom_r )
-{
- return 0x00000000;
-}
-
-
-//55857G
-
-static WRITE32_HANDLER( svg_arm7_ram_sel_w )
-{
- 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);
-}
/*** Memory Maps *************************************************************/
/*** Z80 (sound CPU)**********************************************************/
-static ADDRESS_MAP_START( z80_mem, AS_PROGRAM, 8 )
+ADDRESS_MAP_START( pgm_z80_mem, AS_PROGRAM, 8 )
AM_RANGE(0x0000, 0xffff) AM_RAM AM_BASE_MEMBER(pgm_state, m_z80_mainram)
ADDRESS_MAP_END
-static ADDRESS_MAP_START( z80_io, AS_IO, 8 )
+ADDRESS_MAP_START( pgm_z80_io, AS_IO, 8 )
AM_RANGE(0x8000, 0x8003) AM_DEVREADWRITE("ics", ics2115_device::read, ics2115_device::write)
AM_RANGE(0x8100, 0x81ff) AM_READWRITE(soundlatch3_r, z80_l3_w)
AM_RANGE(0x8200, 0x82ff) AM_READWRITE(soundlatch_r, soundlatch_w)
@@ -590,7 +323,7 @@ ADDRESS_MAP_END
/*** 68000 (main CPU) + variants for protection devices **********************/
-static ADDRESS_MAP_START( pgm_base_mem, AS_PROGRAM, 16)
+ADDRESS_MAP_START( pgm_base_mem, AS_PROGRAM, 16)
AM_RANGE(0x700006, 0x700007) AM_WRITENOP // Watchdog?
AM_RANGE(0x800000, 0x81ffff) AM_RAM AM_MIRROR(0x0e0000) AM_BASE(&pgm_mainram) AM_SHARE("sram") /* Main Ram */
@@ -614,108 +347,24 @@ static ADDRESS_MAP_START( pgm_base_mem, AS_PROGRAM, 16)
AM_RANGE(0xc10000, 0xc1ffff) AM_READWRITE(z80_ram_r, z80_ram_w) /* Z80 Program */
ADDRESS_MAP_END
-static ADDRESS_MAP_START( pgm_mem, AS_PROGRAM, 16)
+ADDRESS_MAP_START( pgm_mem, AS_PROGRAM, 16)
AM_IMPORT_FROM(pgm_base_mem)
AM_RANGE(0x000000, 0x01ffff) AM_ROM /* BIOS ROM */
ADDRESS_MAP_END
-static ADDRESS_MAP_START( pgm_basic_mem, AS_PROGRAM, 16)
+ADDRESS_MAP_START( pgm_basic_mem, AS_PROGRAM, 16)
AM_IMPORT_FROM(pgm_mem)
AM_RANGE(0x100000, 0x3fffff) AM_ROMBANK("bank1") /* Game ROM */
ADDRESS_MAP_END
-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
-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
-
-/* 55857E? */
-/* Knights of Valor, Photo Y2k */
-/* no execute only space? */
-static ADDRESS_MAP_START( kov_map, AS_PROGRAM, 16)
- AM_IMPORT_FROM(pgm_mem)
- AM_RANGE(0x100000, 0x4effff) AM_ROMBANK("bank1") /* Game ROM */
- AM_RANGE(0x4f0000, 0x4f003f) AM_READWRITE(kovsh_arm7_ram_r, kovsh_arm7_ram_w) /* ARM7 Shared RAM */
- AM_RANGE(0x500000, 0x500005) AM_READWRITE(kovsh_68k_protlatch_r, kovsh_68k_protlatch_w) /* ARM7 Latch */
-ADDRESS_MAP_END
-
-/* 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
-
-/* 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(arm7_latch_68k_r, svg_latch_68k_w) /* ARM7 Latch */
-ADDRESS_MAP_END
-
-
-static ADDRESS_MAP_START( cavepgm_mem, AS_PROGRAM, 16)
- AM_IMPORT_FROM(pgm_base_mem)
- AM_RANGE(0x000000, 0x3fffff) AM_ROM
- /* protection devices installed (simulated) later */
-ADDRESS_MAP_END
-
-/*** ARM7 (protection CPUs) **************************************************/
-
-static ADDRESS_MAP_START( 55857E_arm7_map, AS_PROGRAM, 32 )
- AM_RANGE(0x00000000, 0x00003fff) AM_ROM
- AM_RANGE(0x08100000, 0x083fffff) AM_READ(kovsh_exrom_r) // unpopulated, returns 0 to keep checksum happy
- AM_RANGE(0x10000000, 0x100003ff) AM_RAM // internal ram for asic
- AM_RANGE(0x40000000, 0x40000003) AM_READWRITE(kovsh_arm7_protlatch_r, kovsh_arm7_protlatch_w)
- AM_RANGE(0x40000008, 0x4000000b) AM_WRITENOP // ?
- AM_RANGE(0x4000000c, 0x4000000f) AM_READ(kovsh_arm7_unk_r)
- AM_RANGE(0x50800000, 0x5080003f) AM_READWRITE(arm7_shareram_r, arm7_shareram_w) AM_BASE_MEMBER(pgm_state, m_arm7_shareram)
- AM_RANGE(0x50000000, 0x500003ff) AM_RAM // uploads xor table to decrypt 68k rom here
-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
-
-
-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(arm7_latch_arm_r, arm7_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
/*** Input Ports *************************************************************/
/* enough for 4 players, the basic dips mapped are listed in the test mode */
-static INPUT_PORTS_START( pgm )
+INPUT_PORTS_START( pgm )
PORT_START("P1P2")
PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_START1 )
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1)
@@ -800,143 +449,9 @@ static INPUT_PORTS_START( pgm )
PORT_BIT( 0xffff, IP_ACTIVE_LOW, IPT_UNUSED )
INPUT_PORTS_END
-static INPUT_PORTS_START( orlegend )
- PORT_INCLUDE ( pgm )
-
- PORT_MODIFY("Region")
- PORT_DIPNAME( 0x0003, 0x0000, DEF_STR( Region ) )
- PORT_CONFSETTING( 0x0000, DEF_STR( World ) )
- PORT_CONFSETTING( 0x0001, "World (duplicate)" ) // again?
- PORT_CONFSETTING( 0x0002, DEF_STR( Korea ) )
- PORT_CONFSETTING( 0x0003, DEF_STR( China ) )
-INPUT_PORTS_END
-
-static INPUT_PORTS_START( orld105k )
- PORT_INCLUDE ( pgm )
-
- PORT_MODIFY("Region")
- PORT_DIPNAME( 0x0003, 0x0002, DEF_STR( Unused ) ) // region switch
- PORT_DIPSETTING( 0x0002, DEF_STR( Off ) ) // if enabled, game gives
- PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) // "incorrect version" error
-INPUT_PORTS_END
-
-static INPUT_PORTS_START( sango )
- 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
-
-static INPUT_PORTS_START( sango_ch )
- PORT_INCLUDE ( pgm )
-
- PORT_MODIFY("Region") /* Region - supplied by protection device */
- PORT_CONFNAME( 0x000f, 0x0000, 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
-
-static 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
-
-
-static 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
-
-static 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
-static INPUT_PORTS_START( photoy2k )
- PORT_INCLUDE ( pgm )
-
- PORT_MODIFY("Region") /* Region - supplied by protection device */
- PORT_CONFNAME( 0x000f, 0x0003, DEF_STR( Region ) )
- PORT_CONFSETTING( 0x0000, DEF_STR( Taiwan ) )
- PORT_CONFSETTING( 0x0001, DEF_STR( China ) )
- PORT_CONFSETTING( 0x0002, "Japan (Alta license)" )
- PORT_CONFSETTING( 0x0003, DEF_STR( World ) )
- PORT_CONFSETTING( 0x0004, DEF_STR( Korea ) )
- PORT_CONFSETTING( 0x0005, DEF_STR( Hong_Kong ) )
-INPUT_PORTS_END
-static 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
-static INPUT_PORTS_START( oldsplus )
- PORT_INCLUDE ( pgm )
-
- PORT_MODIFY("Region") /* Region - supplied by protection device */
- PORT_CONFNAME( 0x000f, 0x0001, DEF_STR( Region ) )
- PORT_CONFSETTING( 0x0001, DEF_STR( China ) )
- 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( Taiwan ) )
-INPUT_PORTS_END
/*** GFX Decodes *************************************************************/
@@ -972,7 +487,7 @@ static const gfx_layout pgm32_charlayout =
32*256
};
-static GFXDECODE_START( pgm )
+GFXDECODE_START( pgm )
GFXDECODE_ENTRY( "tiles", 0, pgm8_charlayout, 0x800, 32 ) /* 8x8x4 Tiles */
// we have to unpack the data before we can decode it as 32x32, hence we don't know how many tiles etc. in advance, see INIT
//GFXDECODE_ENTRY( "gfx2", 0, pgm32_charlayout, 0x400, 32 ) /* 32x32x5 Tiles */
@@ -980,9 +495,9 @@ GFXDECODE_END
/*** Machine Driver **********************************************************/
-/* only dragon world 2 NEEDs irq4, Puzzli 2 explicitly doesn't want it, what
- is the source? maybe the protection device? */
-static TIMER_DEVICE_CALLBACK( drgw_interrupt )
+/* most games require IRQ4 for inputs to work, Puzzli 2 is explicit about not wanting it tho
+ what is the source? */
+TIMER_DEVICE_CALLBACK( pgm_interrupt )
{
pgm_state *state = timer.machine().driver_data<pgm_state>();
int scanline = param;
@@ -994,7 +509,7 @@ static TIMER_DEVICE_CALLBACK( drgw_interrupt )
if (!state->m_irq4_disabled) device_set_input_line(state->m_maincpu, 4, HOLD_LINE);
}
-static MACHINE_START( pgm )
+MACHINE_START( pgm )
{
pgm_state *state = machine.driver_data<pgm_state>();
@@ -1004,40 +519,24 @@ static MACHINE_START( pgm )
state->m_soundcpu = machine.device<cpu_device>("soundcpu");
state->m_prot = machine.device<cpu_device>("prot");
state->m_ics = machine.device("ics");
-
-// state->save_item(NAME(state->m_cal_val));
-// state->save_item(NAME(state->m_cal_mask));
-// state->save_item(NAME(state->m_cal_com));
-// state->save_item(NAME(state->m_cal_cnt));
}
-static MACHINE_RESET( pgm )
+MACHINE_RESET( pgm )
{
-// pgm_state *state = machine.driver_data<pgm_state>();
-
cputag_set_input_line(machine, "soundcpu", INPUT_LINE_HALT, ASSERT_LINE);
-
-// state->m_cal_val = 0;
-// state->m_cal_mask = 0;
-// state->m_cal_com = 0;
-// state->m_cal_cnt = 0;
}
-static MACHINE_RESET( killbld );
-static MACHINE_RESET( dw3 );
-static MACHINE_RESET( olds );
-extern MACHINE_RESET( kov );
MACHINE_CONFIG_FRAGMENT( pgmbase )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", M68000, 20000000) /* 20 mhz! verified on real board */
MCFG_CPU_PROGRAM_MAP(pgm_basic_mem)
MCFG_CPU_VBLANK_INT("screen", irq6_line_hold)
- MCFG_TIMER_ADD_SCANLINE("scantimer", drgw_interrupt, "screen", 0, 1)
+ MCFG_TIMER_ADD_SCANLINE("scantimer", pgm_interrupt, "screen", 0, 1)
MCFG_CPU_ADD("soundcpu", Z80, 33868800/4)
- MCFG_CPU_PROGRAM_MAP(z80_mem)
- MCFG_CPU_IO_MAP(z80_io)
+ MCFG_CPU_PROGRAM_MAP(pgm_z80_mem)
+ MCFG_CPU_IO_MAP(pgm_z80_io)
MCFG_MACHINE_START( pgm )
MCFG_MACHINE_RESET( pgm )
@@ -1061,192 +560,22 @@ MACHINE_CONFIG_FRAGMENT( pgmbase )
/*sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
- MCFG_ICS2115_ADD("ics", 0, sound_irq)
+ MCFG_ICS2115_ADD("ics", 0, pgm_sound_irq)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 5.0)
MACHINE_CONFIG_END
-static MACHINE_CONFIG_START( pgm, pgm_state )
+MACHINE_CONFIG_START( pgm, pgm_state )
MCFG_FRAGMENT_ADD(pgmbase)
MACHINE_CONFIG_END
-static MACHINE_CONFIG_DERIVED( killbld, pgm )
- MCFG_CPU_MODIFY("maincpu")
- MCFG_CPU_PROGRAM_MAP(killbld_mem)
-
- MCFG_MACHINE_RESET(killbld)
-MACHINE_CONFIG_END
-
-
-static MACHINE_CONFIG_DERIVED( dw3, pgm )
- MCFG_CPU_MODIFY("maincpu")
- MCFG_CPU_PROGRAM_MAP(killbld_mem)
-
- MCFG_MACHINE_RESET(dw3)
-MACHINE_CONFIG_END
-
-
-static MACHINE_CONFIG_DERIVED( olds, pgm )
- MCFG_CPU_MODIFY("maincpu")
- MCFG_CPU_PROGRAM_MAP(olds_mem)
-
- MCFG_MACHINE_RESET(olds)
-MACHINE_CONFIG_END
-
-/******* ARM 55857E *******/
-
-static MACHINE_CONFIG_DERIVED( kov, pgm )
- MCFG_CPU_MODIFY("maincpu")
- MCFG_CPU_PROGRAM_MAP(kov_map)
-
- /* protection CPU */
- MCFG_CPU_ADD("prot", ARM7, 20000000) // 55857E?
- MCFG_CPU_PROGRAM_MAP(55857E_arm7_map)
-MACHINE_CONFIG_END
-
-static MACHINE_CONFIG_DERIVED( kov_disabled_arm, pgm ) // for simulated cases
- MCFG_CPU_MODIFY("maincpu")
- MCFG_CPU_PROGRAM_MAP(pgm_basic_mem)
-
- /* protection CPU */
- MCFG_CPU_ADD("prot", ARM7, 20000000) // 55857E?
- MCFG_CPU_PROGRAM_MAP(55857E_arm7_map)
- MCFG_DEVICE_DISABLE()
-MACHINE_CONFIG_END
-
-static MACHINE_CONFIG_DERIVED( kov_simulated_arm, kov_disabled_arm ) // for simulated cases
- MCFG_CPU_MODIFY("maincpu")
- MCFG_CPU_PROGRAM_MAP(kov_map)
-
- MCFG_MACHINE_RESET(kov)
-MACHINE_CONFIG_END
-
-/******* ARM 55857F *******/
-
-static 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 MACHINE_CONFIG_DERIVED( kov2_disabled_arm, pgm ) // for simulated cases
- MCFG_CPU_MODIFY("maincpu")
- MCFG_CPU_PROGRAM_MAP(pgm_basic_mem)
-
- /* protection CPU */
- MCFG_CPU_ADD("prot", ARM7, 20000000) // 55857F
- MCFG_CPU_PROGRAM_MAP(55857F_arm7_map)
- MCFG_DEVICE_DISABLE()
-MACHINE_CONFIG_END
-
-/******* ARM 55857G *******/
-
-static 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 MACHINE_CONFIG_DERIVED( svg_disabled_arm, pgm ) // for simulated cases
- MCFG_CPU_MODIFY("maincpu")
- MCFG_CPU_PROGRAM_MAP(pgm_basic_mem)
-
- /* protection CPU */
- MCFG_CPU_ADD("prot", ARM7, 33333333) // 55857G
- MCFG_CPU_PROGRAM_MAP(55857G_arm7_map)
- MCFG_DEVICE_DISABLE()
-MACHINE_CONFIG_END
-
-class cavepgm_state : public pgm_state
-{
-public:
- cavepgm_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];
- INT16 m_ddp3thrust;
-};
-
-static MACHINE_START( cavepgm )
-{
- MACHINE_START_CALL(pgm);
-
- cavepgm_state *state = machine.driver_data<cavepgm_state>();
-
- state->save_item(NAME(state->m_value0));
- state->save_item(NAME(state->m_value1));
- state->save_item(NAME(state->m_valuekey));
- state->save_item(NAME(state->m_valueresponse));
- state->save_item(NAME(state->m_ddp3internal_slot));
- state->save_item(NAME(state->m_ddp3slots));
-}
-
-static MACHINE_CONFIG_START( cavepgm, cavepgm_state )
-
- /* basic machine hardware */
- MCFG_CPU_ADD("maincpu", M68000, 20000000)
- MCFG_CPU_PROGRAM_MAP(cavepgm_mem)
- MCFG_TIMER_ADD_SCANLINE("scantimer", drgw_interrupt, "screen", 0, 1)
-
- MCFG_CPU_ADD("soundcpu", Z80, 33868800/4)
- MCFG_CPU_PROGRAM_MAP(z80_mem)
- MCFG_CPU_IO_MAP(z80_io)
-
- MCFG_MACHINE_START( cavepgm )
- MCFG_MACHINE_RESET( pgm )
- MCFG_NVRAM_ADD_0FILL("sram")
-
- MCFG_V3021_ADD("rtc")
-
- /* video hardware */
- MCFG_SCREEN_ADD("screen", RASTER)
- MCFG_SCREEN_REFRESH_RATE(59.17) // verified on pcb
- MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
- MCFG_SCREEN_SIZE(64*8, 64*8)
- MCFG_SCREEN_VISIBLE_AREA(0*8, 56*8-1, 0*8, 28*8-1)
- MCFG_SCREEN_UPDATE_STATIC(pgm)
- MCFG_SCREEN_VBLANK_STATIC(pgm)
- MCFG_GFXDECODE(pgm)
- MCFG_PALETTE_LENGTH(0x1200/2)
- MCFG_VIDEO_START(pgm)
- /*sound hardware */
- MCFG_SPEAKER_STANDARD_MONO("mono")
- MCFG_ICS2115_ADD("ics", 0, sound_irq)
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 5.0)
-MACHINE_CONFIG_END
-// for now we're using a protection sim close ot the CavePgm one, so use that state.
-static MACHINE_CONFIG_DERIVED( puzzli2_disabled_arm, cavepgm )
- MCFG_CPU_MODIFY("maincpu")
- MCFG_CPU_PROGRAM_MAP(pgm_basic_mem)
- /* protection CPU */
- MCFG_CPU_ADD("prot", ARM7, 20000000) // 55857F?
- MCFG_CPU_PROGRAM_MAP(55857F_arm7_map)
- MCFG_DEVICE_DISABLE()
-MACHINE_CONFIG_END
/*** Rom Loading *************************************************************/
@@ -3197,7 +2526,7 @@ ROM_START( ddp2 )
ROM_REGION( 0x4000, "prot", 0 ) /* ARM protection ASIC - internal rom */
ROM_LOAD( "ddp2_igs027a_japan.bin", 0x000000, 0x04000, CRC(742d34d2) SHA1(4491c08f3cefef2933ad5a741f4bb05cc2f3e1a0) )
- ROM_REGION32_LE( 0x400000, "user1", 0 ) /* Protection Data (encrypted external ARM data, internal missing) */
+ ROM_REGION32_LE( 0x400000, "user1", 0 ) /* Protection Data (encrypted external ARM data) */
ROM_LOAD( "v100.u23", 0x000000, 0x20000, CRC(06c3dd29) SHA1(20c9479f158467fc2037dcf162b6c6be18c91d46) )
ROM_REGION( 0xc00000, "tiles", 0 ) /* 8x8 Text Tiles + 32x32 BG Tiles */
@@ -3224,7 +2553,7 @@ ROM_START( ddp2101 )
ROM_REGION( 0x4000, "prot", 0 ) /* ARM protection ASIC - internal rom */
ROM_LOAD( "ddp2_igs027a_japan.bin", 0x000000, 0x04000, CRC(742d34d2) SHA1(4491c08f3cefef2933ad5a741f4bb05cc2f3e1a0) )
- ROM_REGION32_LE( 0x400000, "user1", 0 ) /* Protection Data (encrypted external ARM data, internal missing) */
+ ROM_REGION32_LE( 0x400000, "user1", 0 ) /* Protection Data (encrypted external ARM data) */
ROM_LOAD( "v100.u23", 0x000000, 0x20000, CRC(06c3dd29) SHA1(20c9479f158467fc2037dcf162b6c6be18c91d46) )
ROM_REGION( 0xc00000, "tiles", 0 ) /* 8x8 Text Tiles + 32x32 BG Tiles */
@@ -3251,7 +2580,7 @@ ROM_START( ddp2100 )
ROM_REGION( 0x4000, "prot", 0 ) /* ARM protection ASIC - internal rom */
ROM_LOAD( "ddp2_igs027a_japan.bin", 0x000000, 0x04000, CRC(742d34d2) SHA1(4491c08f3cefef2933ad5a741f4bb05cc2f3e1a0) )
- ROM_REGION32_LE( 0x400000, "user1", 0 ) /* Protection Data (encrypted external ARM data, internal missing) */
+ ROM_REGION32_LE( 0x400000, "user1", 0 ) /* Protection Data (encrypted external ARM data) */
ROM_LOAD( "v100.u23", 0x000000, 0x20000, CRC(06c3dd29) SHA1(20c9479f158467fc2037dcf162b6c6be18c91d46) )
ROM_REGION( 0xc00000, "tiles", 0 ) /* 8x8 Text Tiles + 32x32 BG Tiles */
@@ -3381,9 +2710,6 @@ ROM_START( puzzli2 )
ROM_REGION( 0x4000, "prot", ROMREGION_ERASEFF ) /* ARM protection ASIC - internal rom */
ROM_LOAD( "puzzli2_igs027a.bin", 0x000000, 0x04000, NO_DUMP )
- ROM_REGION32_LE( 0x4000000, "user1", ROMREGION_ERASEFF )
- /* not on this PCB */
-
ROM_REGION( 0x600000, "tiles", 0 ) /* 8x8 Text Tiles + 32x32 BG Tiles */
PGM_VIDEO_BIOS
ROM_LOAD( "t0900.u9", 0x180000, 0x200000, CRC(70615611) SHA1(a46d4aa71396947b427f9ba4ba0e636876c09d6b) )
@@ -3620,7 +2946,7 @@ ROM_START( dmnfrnt )
/* one of these is probably a bad dump, it should be obvious once progress is made because the external rom is checksummed by the internal one */
ROM_LOAD( "v105_32m.u26", 0x000000, 0x400000, CRC(d200ee63) SHA1(3128c27c5f5a4361d31e7b4bb006de631b3a228c) )
ROM_LOAD( "chinese-v105.u62", 0x000000, 0x400000, CRC(c798c2ef) SHA1(91e364c33b935293fa765ca521cdb67ac45ec70f) )
-
+
ROM_REGION( 0xc00000, "tiles", 0 ) /* 8x8 Text Tiles + 32x32 BG Tiles */
PGM_VIDEO_BIOS
ROM_LOAD( "t04501.u29", 0x180000, 0x800000, CRC(900eaaac) SHA1(4033cb7b28fcadb92d5af3ea7fdd1c22747618fd) )
@@ -3670,7 +2996,7 @@ ROM_END
ROM_START( dmnfrntpcb )
ROM_REGION( 0x600000, "maincpu", 0 ) /* 68000 Code */
- ROM_LOAD16_WORD_SWAP( "demonfrontpcb_bios.42", 0x000000, 0x020000, NO_DUMP ) // missing
+ ROM_LOAD16_WORD_SWAP( "pgm_p02s.u42", 0x00000, 0x020000, CRC(78c15fa2) SHA1(885a6558e022602cc6f482ac9667ba9f61e75092) ) /* IGS PGM P02S 1A3708A1A0 S002838 (uses standard PGM v2 bios) */
ROM_LOAD16_WORD_SWAP( "demonfront_v107-u43.bin", 0x100000, 0x200000, CRC(671d8a31) SHA1(a0c2af67d7c56b4b355883892a47640fc72408a1) )
ROM_REGION( 0x4000, "prot", 0 ) /* ARM protection ASIC - internal rom */
@@ -3976,9 +3302,6 @@ ROM_START( ket )
ROM_REGION( 0x4000, "prot", 0 ) /* ARM protection ASIC - internal rom */
ROM_LOAD( "ket_igs027a.bin", 0x000000, 0x04000, NO_DUMP )
- ROM_REGION32_LE( 0x400000, "user1", ROMREGION_ERASE00 )
- /* no external protection rom */
-
ROM_REGION( 0xc00000, "tiles", 0 ) /* 8x8 Text Tiles + 32x32 BG Tiles */
ROM_LOAD( "pgm_t01s.rom", 0x000000, 0x200000, CRC(1a7123a0) SHA1(cc567f577bfbf45427b54d6695b11b74f2578af3) ) // same as standard PGM text bios - surface scratched to remove details
ROM_LOAD( "t04701w064.u19", 0x180000, 0x800000, CRC(2665b041) SHA1(fb1107778b66f2af0de77ac82e1ee2902f53a959) ) //text-1
@@ -4006,9 +3329,6 @@ ROM_START( keta )
ROM_REGION( 0x4000, "prot", 0 ) /* ARM protection ASIC - internal rom */
ROM_LOAD( "ket_igs027a.bin", 0x000000, 0x04000, NO_DUMP )
- ROM_REGION32_LE( 0x400000, "user1", ROMREGION_ERASE00 )
- /* no external protection rom */
-
ROM_REGION( 0xc00000, "tiles", 0 ) /* 8x8 Text Tiles + 32x32 BG Tiles */
ROM_LOAD( "pgm_t01s.rom", 0x000000, 0x200000, CRC(1a7123a0) SHA1(cc567f577bfbf45427b54d6695b11b74f2578af3) ) // same as standard PGM text bios - surface scratched to remove details
ROM_LOAD( "t04701w064.u19", 0x180000, 0x800000, CRC(2665b041) SHA1(fb1107778b66f2af0de77ac82e1ee2902f53a959) ) //text-1
@@ -4036,9 +3356,6 @@ ROM_START( ketb )
ROM_REGION( 0x4000, "prot", 0 ) /* ARM protection ASIC - internal rom */
ROM_LOAD( "ket_igs027a.bin", 0x000000, 0x04000, NO_DUMP )
- ROM_REGION32_LE( 0x400000, "user1", ROMREGION_ERASE00 )
- /* no external protection rom */
-
ROM_REGION( 0xc00000, "tiles", 0 ) /* 8x8 Text Tiles + 32x32 BG Tiles */
ROM_LOAD( "pgm_t01s.rom", 0x000000, 0x200000, CRC(1a7123a0) SHA1(cc567f577bfbf45427b54d6695b11b74f2578af3) ) // same as standard PGM text bios - surface scratched to remove details
ROM_LOAD( "t04701w064.u19", 0x180000, 0x800000, CRC(2665b041) SHA1(fb1107778b66f2af0de77ac82e1ee2902f53a959) ) //text-1
@@ -4066,9 +3383,6 @@ ROM_START( espgal )
ROM_REGION( 0x4000, "prot", 0 ) /* ARM protection ASIC - internal rom */
ROM_LOAD( "espgal_igs027a.bin", 0x000000, 0x04000, NO_DUMP )
- ROM_REGION32_LE( 0x400000, "user1", ROMREGION_ERASE00 )
- /* no external protection rom */
-
ROM_REGION( 0xc00000, "tiles", 0 ) /* 8x8 Text Tiles + 32x32 BG Tiles */
ROM_LOAD( "t01s.u18", 0x000000, 0x200000, CRC(1a7123a0) SHA1(cc567f577bfbf45427b54d6695b11b74f2578af3) ) // same as standard PGM text bios - surface scratched to remove details
ROM_LOAD( "t04801w064.u19", 0x180000, 0x800000, CRC(6021c79e) SHA1(fbc340dafb18aa3094de29b881318a5a9794e4bc) ) //text-1
@@ -4093,9 +3407,6 @@ ROM_START( ddpdoj )
ROM_REGION( 0x4000, "prot", 0 ) /* ARM protection ASIC - internal rom */
ROM_LOAD( "ddp3_igs027a.bin", 0x000000, 0x04000, NO_DUMP )
- ROM_REGION32_LE( 0x400000, "user1", ROMREGION_ERASE00 )
- /* no external protection rom */
-
ROM_REGION( 0xc00000, "tiles", 0 ) /* 8x8 Text Tiles + 32x32 BG Tiles */
ROM_LOAD( "pgm_t01s.rom", 0x000000, 0x200000, CRC(1a7123a0) SHA1(cc567f577bfbf45427b54d6695b11b74f2578af3) ) // same as standard PGM bios
ROM_LOAD( "t04401w064.u19",0x180000, 0x800000, CRC(3a95f19c) SHA1(fd3c47cf0b8b1e20c6bec4be68a089fc8bbf4dbe) ) //text-1
@@ -4124,9 +3435,6 @@ ROM_START( ddpdoja )
ROM_REGION( 0x4000, "prot", 0 ) /* ARM protection ASIC - internal rom */
ROM_LOAD( "ddp3_igs027a.bin", 0x000000, 0x04000, NO_DUMP )
- ROM_REGION32_LE( 0x400000, "user1", ROMREGION_ERASE00 )
- /* no external protection rom */
-
ROM_REGION( 0xc00000, "tiles", 0 ) /* 8x8 Text Tiles + 32x32 BG Tiles */
ROM_LOAD( "pgm_t01s.rom", 0x000000, 0x200000, CRC(1a7123a0) SHA1(cc567f577bfbf45427b54d6695b11b74f2578af3) ) // same as standard PGM bios
ROM_LOAD( "t04401w064.u19",0x180000, 0x800000, CRC(3a95f19c) SHA1(fd3c47cf0b8b1e20c6bec4be68a089fc8bbf4dbe) ) //text-1
@@ -4154,9 +3462,6 @@ ROM_START( ddpdojb )
ROM_REGION( 0x4000, "prot", 0 ) /* ARM protection ASIC - internal rom */
ROM_LOAD( "ddp3_igs027a.bin", 0x000000, 0x04000, NO_DUMP )
- ROM_REGION32_LE( 0x400000, "user1", ROMREGION_ERASE00 )
- /* no external protection rom */
-
ROM_REGION( 0xc00000, "tiles", 0 ) /* 8x8 Text Tiles + 32x32 BG Tiles */
ROM_LOAD( "pgm_t01s.rom", 0x000000, 0x200000, CRC(1a7123a0) SHA1(cc567f577bfbf45427b54d6695b11b74f2578af3) ) // same as standard PGM bios
ROM_LOAD( "t04401w064.u19",0x180000, 0x800000, CRC(3a95f19c) SHA1(fd3c47cf0b8b1e20c6bec4be68a089fc8bbf4dbe) ) //text-1
@@ -4185,9 +3490,6 @@ ROM_START( ddpdojblk )
ROM_REGION( 0x4000, "prot", 0 ) /* ARM protection ASIC - internal rom */
ROM_LOAD( "ddp3_igs027a.bin", 0x000000, 0x04000, NO_DUMP )
- ROM_REGION32_LE( 0x400000, "user1", ROMREGION_ERASE00 )
- /* no external protection rom */
-
ROM_REGION( 0xc00000, "tiles", 0 ) /* 8x8 Text Tiles + 32x32 BG Tiles */
ROM_LOAD( "pgm_t01s.rom", 0x000000, 0x200000, CRC(1a7123a0) SHA1(cc567f577bfbf45427b54d6695b11b74f2578af3) ) // same as standard PGM bios
ROM_LOAD( "t04401w064.u19",0x180000, 0x800000, CRC(3a95f19c) SHA1(fd3c47cf0b8b1e20c6bec4be68a089fc8bbf4dbe) ) //text-1
@@ -4286,7 +3588,7 @@ static void expand_colourdata( running_machine &machine )
-static void pgm_basic_init( running_machine &machine, bool set_bank = true )
+void pgm_basic_init( running_machine &machine, bool set_bank)
{
pgm_state *state = machine.driver_data<pgm_state>();
@@ -4306,1553 +3608,11 @@ static DRIVER_INIT( pgm )
pgm_basic_init(machine);
}
-/* Oriental Legend INIT */
-static DRIVER_INIT( orlegend )
-{
- pgm_state *state = machine.driver_data<pgm_state>();
- pgm_basic_init(machine);
-
- machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0xC0400e, 0xC0400f, FUNC(pgm_asic3_r), FUNC(pgm_asic3_w));
- machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0xC04000, 0xC04001, FUNC(pgm_asic3_reg_w));
-
- state->m_asic3_reg = 0;
- state->m_asic3_latch[0] = 0;
- state->m_asic3_latch[1] = 0;
- state->m_asic3_latch[2] = 0;
- state->m_asic3_x = 0;
- state->m_asic3_y = 0;
- state->m_asic3_z = 0;
- state->m_asic3_h1 = 0;
- state->m_asic3_h2 = 0;
- state->m_asic3_hold = 0;
-
- state->save_item(NAME(state->m_asic3_reg));
- state->save_item(NAME(state->m_asic3_latch));
- state->save_item(NAME(state->m_asic3_x));
- state->save_item(NAME(state->m_asic3_y));
- state->save_item(NAME(state->m_asic3_z));
- state->save_item(NAME(state->m_asic3_h1));
- state->save_item(NAME(state->m_asic3_h2));
- state->save_item(NAME(state->m_asic3_hold));
-}
-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));
-}
-
-static 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;
-}
-
-static 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;
-}
-static 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;
-}
-
-static 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;
-}
-
-static void kovsh_latch_init( running_machine &machine )
-{
- pgm_state *state = machine.driver_data<pgm_state>();
-
- state->m_kovsh_highlatch_arm_w = 0;
- state->m_kovsh_lowlatch_arm_w = 0;
- state->m_kovsh_highlatch_68k_w = 0;
- state->m_kovsh_lowlatch_68k_w = 0;
- state->m_kovsh_counter = 1;
-
- state->save_item(NAME(state->m_kovsh_highlatch_arm_w));
- state->save_item(NAME(state->m_kovsh_lowlatch_arm_w));
- state->save_item(NAME(state->m_kovsh_highlatch_68k_w));
- state->save_item(NAME(state->m_kovsh_lowlatch_68k_w));
- state->save_item(NAME(state->m_kovsh_counter));
-}
-
-static DRIVER_INIT( kov )
-{
- pgm_basic_init(machine);
- pgm_kov_decrypt(machine);
- kovsh_latch_init(machine);
- install_protection_asic_sim_kov(machine);
-}
-
-static DRIVER_INIT( kovboot )
-{
- pgm_basic_init(machine);
-// pgm_kov_decrypt(machine);
- kovsh_latch_init(machine);
- install_protection_asic_sim_kov(machine);
-}
-
-static DRIVER_INIT( pstar )
-{
- pgm_state *state = machine.driver_data<pgm_state>();
-
- pgm_basic_init(machine);
- pgm_pstar_decrypt(machine);
- kovsh_latch_init(machine);
-
- state->m_pstars_key = 0;
- state->m_pstars_int[0] = 0;
- state->m_pstars_int[1] = 0;
- state->m_pstars_val = 0;
- state->m_pstar_e7 = 0;
- state->m_pstar_b1 = 0;
- state->m_pstar_ce = 0;
- state->m_pstar_ram[0] = 0;
- state->m_pstar_ram[1] = 0;
- state->m_pstar_ram[2] = 0;
- memset(state->m_pstars_regs, 0, 16);
-
- state->save_item(NAME(state->m_pstars_key));
- state->save_item(NAME(state->m_pstars_int));
- state->save_item(NAME(state->m_pstars_regs));
- state->save_item(NAME(state->m_pstars_val));
- state->save_item(NAME(state->m_pstar_e7));
- state->save_item(NAME(state->m_pstar_b1));
- state->save_item(NAME(state->m_pstar_ce));
- state->save_item(NAME(state->m_pstar_ram));
-
-}
-
-static DRIVER_INIT( photoy2k )
-{
- pgm_basic_init(machine);
- pgm_photoy2k_decrypt(machine);
- kovsh_latch_init(machine);
-}
-
-static DRIVER_INIT( py2k2 )
-{
- pgm_basic_init(machine);
- pgm_py2k2_decrypt(machine);
- kovsh_latch_init(machine);
-}
-
-
-static DRIVER_INIT( kovsh )
-{
- pgm_basic_init(machine);
- pgm_kovsh_decrypt(machine);
- kovsh_latch_init(machine);
-}
-
-static DRIVER_INIT( kovshp )
-{
- pgm_basic_init(machine);
- pgm_kovshp_decrypt(machine);
- kovsh_latch_init(machine);
-}
-
-
-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 DRIVER_INIT( kov2 )
-{
- pgm_basic_init(machine);
- pgm_kov2_decrypt(machine);
- kov2_latch_init(machine);
-}
-
-
-static DRIVER_INIT( martmast )
-{
- pgm_basic_init(machine);
- pgm_mm_decrypt(machine);
- kov2_latch_init(machine);
-}
-
-
-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 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));
-
-
-}
-
-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 DRIVER_INIT( theglad )
-{
- svg_basic_init(machine);
- pgm_theglad_decrypt(machine);
- kov2_latch_init(machine);
-}
-
-static DRIVER_INIT( svg )
-{
- svg_basic_init(machine);
- pgm_svg_decrypt(machine);
- kov2_latch_init(machine);
-}
-
-static DRIVER_INIT( svgpcb )
-{
- svg_basic_init(machine);
- pgm_svgpcb_decrypt(machine);
- kov2_latch_init(machine);
-}
-
-static 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 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 ... */
- 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] = 0xff10;
- temp16[(0x000a)/2] = 0xe12f;
- temp16[(0x0090)/2] = 0x0400;
- temp16[(0x0092)/2] = 0x1000;
-
- machine.device("prot")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x18000444, 0x18000447, FUNC(dmnfrnt_speedup_r));
-
- // the internal rom probably also supplies the region here
- UINT16 *share16 = (UINT16 *)(state->m_svg_shareram[0]);
- share16[0x158/2] = 0x0005;
-
-
-}
-
-
-/* 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);
-
-}
-
-
-
-
-/* ASIC025/ASIC022 don't provide rom patches like the DW2 protection does, the previous dump was bad :-) */
-static 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;
-}
-
-
-static 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 INT32 puzzli_54_trigger = 0;
-
-// Preliminary
-static WRITE16_HANDLER( puzzli2_asic_w )
-{
- cavepgm_state *state = space->machine().driver_data<cavepgm_state>();
-
- switch (offset & 0x03)
- {
- case 0: state->m_value0 = data; return;
-
- case 1:
- {
- if ((data >> 8) == 0xff) state->m_valuekey = 0xffff;
-
- state->m_value0 ^= state->m_valuekey;
-
- switch ((data ^ state->m_valuekey) & 0xff)
- {
- case 0x13: // ASIC status?
- state->m_valueresponse = 0x74<<16; // 2d or 74! (based on?)
- break;
-
- case 0x31:
- {
- // how is this selected? command 54?
-
- // just a wild guess
- if (puzzli_54_trigger) {
- // pc == 1387de
- state->m_valueresponse = 0x63<<16; // ?
- } else {
- // pc == 14cf58
- state->m_valueresponse = 0xd2<<16;
- }
-
- puzzli_54_trigger = 0;
- }
- break;
-
- case 0x38: // Reset
- state->m_valueresponse = 0x78<<16;
- state->m_valuekey = 0;
- puzzli_54_trigger = 0;
- break;
-
- case 0x41: // ASIC status?
- state->m_valueresponse = 0x74<<16;
- break;
-
- case 0x47: // ASIC status?
- state->m_valueresponse = 0x74<<16;
- break;
-
- case 0x52: // ASIC status?
- {
- // how is this selected?
-
- //if (state->m_value0 == 6) {
- state->m_valueresponse = (0x74<<16)|1; // |1?
- //} else {
- // state->m_valueresponse = 0x74<<16;
- //}
- }
- break;
-
- case 0x54: // ??
- puzzli_54_trigger = 1;
- state->m_valueresponse = 0x36<<16;
- break;
-
- case 0x61: // ??
- state->m_valueresponse = 0x36<<16;
- break;
-
- case 0x63: // probably read from a data table?
- state->m_valueresponse = 0; // wrong...
- break;
-
- case 0x67: // probably read from a data table?
- state->m_valueresponse = 0; // wrong...
- break;
-
- default:
- state->m_valueresponse = 0x74<<16;
- break;
- }
-
- state->m_valuekey = (state->m_valuekey + 0x0100) & 0xff00;
- if (state->m_valuekey == 0xff00) state->m_valuekey = 0x0100;
- state->m_valuekey |= state->m_valuekey >> 8;
- }
- return;
-
- case 2: return;
- }
-}
-
-
-static DRIVER_INIT( dw2001 )
-{
- //pgm_state *state = machine.driver_data<pgm_state>();
- UINT16 *mem16 = (UINT16 *)machine.region("maincpu")->base();
-
- pgm_basic_init(machine);
- kovsh_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;
-
-}
-
-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];
-
-}
-
-static 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 void pgm_decode_kovlsqh2_tiles( running_machine &machine )
-{
- int i, j;
- UINT16 *src = (UINT16 *)(machine.region("tiles")->base() + 0x180000);
- UINT16 *dst = auto_alloc_array(machine, UINT16, 0x800000);
-
- for (i = 0; i < 0x800000 / 2; i++)
- {
- j = BITSWAP24(i, 23, 22, 9, 8, 21, 18, 0, 1, 2, 3, 16, 15, 14, 13, 12, 11, 10, 19, 20, 17, 7, 6, 5, 4);
-
- dst[j] = BITSWAP16(src[i], 1, 14, 8, 7, 0, 15, 6, 9, 13, 2, 5, 10, 12, 3, 4, 11);
- }
-
- memcpy( src, dst, 0x800000 );
-
- auto_free( machine, dst );
-}
-
-static void pgm_decode_kovlsqh2_sprites( running_machine &machine, UINT8 *src )
-{
- int i, j;
- UINT8 *dst = auto_alloc_array(machine, UINT8, 0x800000);
-
- for (i = 0; i < 0x800000; i++)
- {
- j = BITSWAP24(i, 23, 10, 9, 22, 19, 18, 20, 21, 17, 16, 15, 14, 13, 12, 11, 8, 7, 6, 5, 4, 3, 2, 1, 0);
-
- dst[j] = src[i];
- }
-
- memcpy( src, dst, 0x800000 );
-
- auto_free( machine, dst );
-}
-
-static void pgm_decode_kovlsqh2_samples( running_machine &machine )
-{
- int i;
- UINT8 *src = (UINT8 *)(machine.region("ics")->base() + 0x400000);
-
- for (i = 0; i < 0x400000; i+=2) {
- src[i + 0x000001] = src[i + 0x400001];
- }
-
- memcpy( src + 0x400000, src, 0x400000 );
-}
-
-static void pgm_decode_kovqhsgs_program( running_machine &machine )
-{
- int i;
- UINT16 *src = (UINT16 *)(machine.region("maincpu")->base() + 0x100000);
- UINT16 *dst = auto_alloc_array(machine, UINT16, 0x400000);
-
- for (i = 0; i < 0x400000 / 2; i++)
- {
- int j = BITSWAP24(i, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 5, 4, 3, 2, 1, 0);
-
- dst[j] = BITSWAP16(src[i], 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 4, 5, 3, 2, 1, 0);
- }
-
- memcpy( src, dst, 0x400000 );
-
- auto_free( machine, dst );
-}
-
-static void pgm_decode_kovqhsgs2_program( running_machine &machine )
-{
- int i;
- UINT16 *src = (UINT16 *)(machine.region("maincpu")->base() + 0x100000);
- UINT16 *dst = auto_alloc_array(machine, UINT16, 0x400000);
-
- for (i = 0; i < 0x400000 / 2; i++)
- {
- int j = BITSWAP24(i, 23, 22, 21, 20, 19, 16, 15, 14, 13, 12, 11, 10, 9, 8, 0, 1, 2, 3, 4, 5, 6, 18, 17, 7);
-
- dst[j] = src[i];
- }
-
- memcpy( src, dst, 0x400000 );
-
- auto_free( machine, dst );
-}
-
-
-static DRIVER_INIT( kovlsqh2 )
-{
- pgm_decode_kovqhsgs2_program(machine);
- pgm_decode_kovlsqh2_tiles(machine);
-
- pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x0000000);
- pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x0800000);
- pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x1000000);
- pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x1800000);
- pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x2000000);
- pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x2800000);
- pgm_decode_kovlsqh2_sprites(machine, machine.region("sprmask")->base() + 0x0000000);
- pgm_decode_kovlsqh2_sprites(machine, machine.region("sprmask")->base() + 0x0800000);
-
- pgm_decode_kovlsqh2_samples(machine);
- pgm_basic_init(machine);
- kovsh_latch_init(machine);
-}
-
-static DRIVER_INIT( kovqhsgs )
-{
- pgm_decode_kovqhsgs_program(machine);
- pgm_decode_kovlsqh2_tiles(machine);
-
- pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x0000000);
- pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x0800000);
- pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x1000000);
- pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x1800000);
- pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x2000000);
- pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x2800000);
- pgm_decode_kovlsqh2_sprites(machine, machine.region("sprmask")->base() + 0x0000000);
- pgm_decode_kovlsqh2_sprites(machine, machine.region("sprmask")->base() + 0x0800000);
-
- pgm_decode_kovlsqh2_samples(machine);
-
- pgm_basic_init(machine);
- kovsh_latch_init(machine);
-}
-
-/*
- in Ketsui (ket) @ 000A719C (move.w)
-
- if you change D0 to 0x12
- the game will runs to "Asic27 Test" mode
-
- bp A71A0,1,{d0=0x12;g}
-*/
-
-static WRITE16_HANDLER( ddp3_asic_w )
-{
- cavepgm_state *state = space->machine().driver_data<cavepgm_state>();
-
- if (offset == 0)
- {
- state->m_value0 = data;
- return;
- }
- else if (offset == 1)
- {
- UINT16 realkey;
- if ((data >> 8) == 0xff)
- state->m_valuekey = 0xff00;
- realkey = state->m_valuekey >> 8;
- realkey |= state->m_valuekey;
- {
- state->m_valuekey += 0x0100;
- state->m_valuekey &= 0xff00;
- if (state->m_valuekey == 0xff00)
- state->m_valuekey = 0x0100;
- }
- data ^= realkey;
- state->m_value1 = data;
- state->m_value0 ^= realkey;
-
- state->m_ddp3lastcommand = state->m_value1 & 0xff;
-
- /* typical frame (ddp3) (all 3 games use only these commands? for the most part of levels espgal just issues 8e)
- vbl
- 145f28 command 67
- 145f70 command e5
- 145f28 command 67
- 145f70 command e5
- 1460c6 command 40
- 145ec0 command 8e
- */
-
- switch (state->m_ddp3lastcommand)
- {
- default:
- printf("%06x command %02x | %04x\n", cpu_get_pc(&space->device()), state->m_ddp3lastcommand, state->m_value0);
- state->m_valueresponse = 0x880000;
- break;
-
- case 0x40:
- state->m_valueresponse = 0x880000;
- state->m_ddp3slots[(state->m_value0>>10)&0x1F]=
- (state->m_ddp3slots[(state->m_value0>>5)&0x1F]+
- state->m_ddp3slots[(state->m_value0>>0)&0x1F])&0xffffff;
- break;
-
- case 0x67: // set high bits
- // printf("%06x command %02x | %04x\n", cpu_get_pc(&space->device()), state->m_ddp3lastcommand, state->m_value0);
- state->m_valueresponse = 0x880000;
- state->m_ddp3internal_slot = (state->m_value0 & 0xff00)>>8;
- state->m_ddp3slots[state->m_ddp3internal_slot] = (state->m_value0 & 0x00ff) << 16;
- break;
-
- case 0xe5: // set low bits for operation?
- // printf("%06x command %02x | %04x\n", cpu_get_pc(&space->device()), state->m_ddp3lastcommand, state->m_value0);
- state->m_valueresponse = 0x880000;
- state->m_ddp3slots[state->m_ddp3internal_slot] |= (state->m_value0 & 0xffff);
- break;
-
-
- case 0x8e: // read back result of operations
- // printf("%06x command %02x | %04x\n", cpu_get_pc(&space->device()), state->m_ddp3lastcommand, state->m_value0);
- state->m_valueresponse = state->m_ddp3slots[state->m_value0&0xff];
- break;
-
-
- case 0x99: // reset?
- state->m_valuekey = 0x100;
- state->m_valueresponse = 0x00880000;
- break;
-
- }
- }
- else if (offset==2)
- {
-
- }
-
-}
-
-static READ16_HANDLER( ddp3_asic_r )
-{
- cavepgm_state *state = space->machine().driver_data<cavepgm_state>();
-
- if (offset == 0)
- {
- UINT16 d = state->m_valueresponse & 0xffff;
- UINT16 realkey = state->m_valuekey >> 8;
- realkey |= state->m_valuekey;
- d ^= realkey;
-
- return d;
-
- }
- else if (offset == 1)
- {
- UINT16 d = state->m_valueresponse >> 16;
- UINT16 realkey = state->m_valuekey >> 8;
- realkey |= state->m_valuekey;
- d ^= realkey;
- return d;
-
- }
- return 0xffff;
-}
-
-
-void install_asic27a_ddp3(running_machine& machine)
-{
- machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x500000, 0x500005, FUNC(ddp3_asic_r), FUNC(ddp3_asic_w));
-}
-
-void install_asic27a_ket(running_machine& machine)
-{
- machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x400000, 0x400005, FUNC(ddp3_asic_r), FUNC(ddp3_asic_w));
-}
-
-void install_asic27a_espgal(running_machine& machine)
-{
- machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x400000, 0x400005, FUNC(ddp3_asic_r), FUNC(ddp3_asic_w));
-}
-
-static DRIVER_INIT( ddp3 )
-{
- pgm_basic_init(machine, false);
- pgm_py2k2_decrypt(machine); // yes, it's the same as photo y2k2
- install_asic27a_ddp3(machine);
-}
-
-static DRIVER_INIT( ket )
-{
- pgm_basic_init(machine, false);
- pgm_ket_decrypt(machine);
- install_asic27a_ket(machine);
-}
-
-static DRIVER_INIT( espgal )
-{
- pgm_basic_init(machine, false);
- pgm_espgal_decrypt(machine);
- install_asic27a_espgal(machine);
-}
-
-static DRIVER_INIT( puzzli2 )
-{
- cavepgm_state *state = machine.driver_data<cavepgm_state>();
-
- pgm_basic_init(machine);
-
- pgm_puzzli2_decrypt(machine);
-
- machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x500000, 0x500005, FUNC(ddp3_asic_r), FUNC(puzzli2_asic_w));
- machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x4f0000, 0x4fffff, FUNC(sango_protram_r));
-
- // doesn't like this irq??
- state->m_irq4_disabled = 1;
-}
-
-static void oldsplus_latch_init( running_machine &machine )
-{
- pgm_state *state = machine.driver_data<pgm_state>();
-
- state->m_oldsplus_key = 0;
- state->m_oldsplus_int[0] = 0;
- state->m_oldsplus_int[1] = 0;
- state->m_oldsplus_val = 0;
- memset(state->m_oldsplus_ram, 0, 0x100);
- memset(state->m_oldsplus_regs, 0, 0x100);
-
- state_save_register_global(machine, state->m_oldsplus_key);
- state_save_register_global(machine, state->m_oldsplus_val);
- state_save_register_global_array(machine, state->m_oldsplus_int);
- state_save_register_global_array(machine, state->m_oldsplus_ram);
- state_save_register_global_array(machine, state->m_oldsplus_regs);
-}
-
-#if 0
-static DRIVER_INIT( oldsplus )
-{
- pgm_basic_init(machine);
- pgm_oldsplus_decrypt(machine);
- kovsh_latch_init(machine);
-}
-#endif
-
-static DRIVER_INIT( oldsplus )
-{
- pgm_basic_init(machine);
- pgm_oldsplus_decrypt(machine);
- oldsplus_latch_init(machine);
-
- machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x500000, 0x500003, FUNC(oldsplus_r), FUNC(oldsplus_w));
- machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x4f0000, 0x4fffff, FUNC(oldsplus_protram_r));
-}
-
-static 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.
- UINT8 *mem8 = (UINT8 *)machine.region("user1")->base();
- pgm_basic_init(machine);
- pgm_kov2p_decrypt(machine);
- kov2_latch_init(machine);
- 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;
-}
-
-static DRIVER_INIT( happy6 )
-{
- svg_basic_init(machine);
- pgm_happy6_decrypt(machine);
- kov2_latch_init(machine);
-}
/*** GAME ********************************************************************/
@@ -5882,27 +3642,27 @@ GAME( 1999, photoy2k104, photoy2k, kov, photoy2k, photoy2k, ROT0, "IGS
GAME( 1999, photoy2k102, photoy2k, kov, photoy2k, photoy2k, ROT0, "IGS", "Photo Y2K (ver. 102, Japanese Board)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) /* region provided by protection device */
// region provided by internal ARM rom
-GAME( 1999, kovsh, pgm, kov, sango, kovsh, ROT0, "IGS", "Knights of Valour Super Heroes / Sangoku Senki Super Heroes (ver. 104, CN)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 68k V104, China internal ROM
-GAME( 1999, kovsh103, kovsh, kov, sango, kovsh, ROT0, "IGS", "Knights of Valour Super Heroes / Sangoku Senki Super Heroes (ver. 103, CN)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 68k V103, China internal ROM
+GAME( 1999, kovsh, pgm, kov, kovsh, kovsh, ROT0, "IGS", "Knights of Valour Super Heroes / Sangoku Senki Super Heroes (ver. 104, CN)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 68k V104, China internal ROM
+GAME( 1999, kovsh103, kovsh, kov, kovsh, kovsh, ROT0, "IGS", "Knights of Valour Super Heroes / Sangoku Senki Super Heroes (ver. 103, CN)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 68k V103, China internal ROM
// nasty modern asian bootleg of Knights of Valour Super Heroes with characters ripped from SNK's The King of Fighters series!
-GAME( 1999, kovqhsgs, kovsh, kov, sango, kovqhsgs, ROT0, "bootleg", "Knights of Valour: Quan Huang San Guo Special / Sangoku Senki: Quan Huang San Guo Special (ver. 303CN)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE )
+GAME( 1999, kovqhsgs, kovsh, kov, kovsh, kovqhsgs, ROT0, "bootleg", "Knights of Valour: Quan Huang San Guo Special / Sangoku Senki: Quan Huang San Guo Special (ver. 303CN)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE )
// region provided by internal ARM rom
-GAME( 2000, kov2, pgm, kov2, sango, kov2, ROT0, "IGS", "Knights of Valour 2 / Sangoku Senki 2 (ver. 107, 102, 100HK)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 05/10/01 14:24:08 V107 (Ext. Arm V102, Int. Arm V100HK)
-GAME( 2000, kov2106, kov2, kov2, sango, kov2, ROT0, "IGS", "Knights of Valour 2 / Sangoku Senki 2 (ver. 106, 102, 100KH)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 02/27/01 13:26:46 V106 (Ext. Arm V102, Int. Arm V100HK)
-GAME( 2000, kov2103, kov2, kov2, sango, kov2, ROT0, "IGS", "Knights of Valour 2 / Sangoku Senki 2 (ver. 103, 101, 100HK)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 12/28/00 15:09:31 V103 (Ext. Arm V101, Int. Arm V100HK)
-GAME( 2000, kov2102, kov2, kov2, sango, kov2, ROT0, "IGS", "Knights of Valour 2 / Sangoku Senki 2 (ver. 102, 101, 100HK)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 12/14/00 10:33:36 V102 (Ext. Arm V101, Int. Arm V100HK)
-GAME( 2000, kov2101, kov2, kov2, sango, kov2, ROT0, "IGS", "Knights of Valour 2 / Sangoku Senki 2 (ver. 101, 101, 100HK)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 11/29/00 11:03:08 V100 (Ext. Arm V100, Int. Arm V100HK)
-GAME( 2000, kov2100, kov2, kov2, sango, kov2, ROT0, "IGS", "Knights of Valour 2 / Sangoku Senki 2 (ver. 100, 100, 100HK)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 11/29/00 11:03:08 V100 (Ext. Arm V100, Int. Arm V100HK)
+GAME( 2000, kov2, pgm, kov2, kov2, kov2, ROT0, "IGS", "Knights of Valour 2 / Sangoku Senki 2 (ver. 107, 102, 100HK)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 05/10/01 14:24:08 V107 (Ext. Arm V102, Int. Arm V100HK)
+GAME( 2000, kov2106, kov2, kov2, kov2, kov2, ROT0, "IGS", "Knights of Valour 2 / Sangoku Senki 2 (ver. 106, 102, 100KH)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 02/27/01 13:26:46 V106 (Ext. Arm V102, Int. Arm V100HK)
+GAME( 2000, kov2103, kov2, kov2, kov2, kov2, ROT0, "IGS", "Knights of Valour 2 / Sangoku Senki 2 (ver. 103, 101, 100HK)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 12/28/00 15:09:31 V103 (Ext. Arm V101, Int. Arm V100HK)
+GAME( 2000, kov2102, kov2, kov2, kov2, kov2, ROT0, "IGS", "Knights of Valour 2 / Sangoku Senki 2 (ver. 102, 101, 100HK)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 12/14/00 10:33:36 V102 (Ext. Arm V101, Int. Arm V100HK)
+GAME( 2000, kov2101, kov2, kov2, kov2, kov2, ROT0, "IGS", "Knights of Valour 2 / Sangoku Senki 2 (ver. 101, 101, 100HK)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 11/29/00 11:03:08 V100 (Ext. Arm V100, Int. Arm V100HK)
+GAME( 2000, kov2100, kov2, kov2, kov2, kov2, ROT0, "IGS", "Knights of Valour 2 / Sangoku Senki 2 (ver. 100, 100, 100HK)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 11/29/00 11:03:08 V100 (Ext. Arm V100, Int. Arm V100HK)
// region provided by internal ARM rom
-GAME( 2001, kov2p, pgm, kov2, sango, kov2p, ROT0, "IGS", "Knights of Valour 2 Plus - Nine Dragons / Sangoku Senki 2 Plus - Nine Dragons (ver. M204XX)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
-GAME( 2001, kov2p205, kov2p, kov2, sango, kov2p, ROT0, "IGS", "Knights of Valour 2 Plus - Nine Dragons / Sangoku Senki 2 Plus - Nine Dragons (ver. M205XX)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
+GAME( 2001, kov2p, pgm, kov2, kov2, kov2p, ROT0, "IGS", "Knights of Valour 2 Plus - Nine Dragons / Sangoku Senki 2 Plus - Nine Dragons (ver. M204XX)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
+GAME( 2001, kov2p205, kov2p, kov2, kov2, kov2p, ROT0, "IGS", "Knights of Valour 2 Plus - Nine Dragons / Sangoku Senki 2 Plus - Nine Dragons (ver. M205XX)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
// region provided by internal ARM rom
-GAME( 2001, martmast, pgm, kov2, sango, martmast, ROT0, "IGS", "Martial Masters (ver. 104, 102, 102US)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 68k V104, Ext Arm 102, Int Arm 102US
-GAME( 2001, martmastc, martmast, kov2, sango, martmast, ROT0, "IGS", "Martial Masters (ver. 104, 102, 101CN)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 68k V104, Ext Arm 102, Int Arm 101CN
-GAME( 2001, martmastc102, martmast, kov2, sango, martmast, ROT0, "IGS", "Martial Masters (ver. 102, 101, 101CN)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 68k V102, Ext Arm 101, Int Arm 101CN
+GAME( 2001, martmast, pgm, kov2, martmast, martmast, ROT0, "IGS", "Martial Masters (ver. 104, 102, 102US)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 68k V104, Ext Arm 102, Int Arm 102US
+GAME( 2001, martmastc, martmast, kov2, martmast, martmast, ROT0, "IGS", "Martial Masters (ver. 104, 102, 101CN)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 68k V104, Ext Arm 102, Int Arm 101CN
+GAME( 2001, martmastc102, martmast, kov2, martmast, martmast, ROT0, "IGS", "Martial Masters (ver. 102, 101, 101CN)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 68k V102, Ext Arm 101, Int Arm 101CN
// region provided by internal ARM rom
GAME( 2001, ddp2, pgm, kov2, ddp2, ddp2, ROT270, "IGS", "DoDonPachi II - Bee Storm (Japan, ver. 102)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE )
@@ -5911,9 +3671,9 @@ GAME( 2001, ddp2100, ddp2, kov2, ddp2, ddp2, ROT270, "IGS
// we bypass the internal ARM rom on these, ideally it should still be dumped tho!
// ARM version strings don't match 100% with labels... for 68k ROMs I'm using the build time / date stamp from near the start of the rom, there are some slightly different time stamps later
-GAME( 2002, dmnfrnt, pgm, svg, sango, dmnfrnt, ROT0, "IGS", "Demon Front (68k label V105, ROM M105XX 08/05/02) (ARM label V105, ROM 08/05/02 S105XX)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 68k time: 10:24:11 ARM time: 10:33:23
-GAME( 2002, dmnfrnta, dmnfrnt, svg, sango, dmnfrnt, ROT0, "IGS", "Demon Front (68k label V102, ROM M102XX 06/19/02) (ARM label V102, ROM 05/24/02 S101XX)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 68k time: 13:44:08 ARM time: 13:04:31
-GAME( 2002, dmnfrntpcb, dmnfrnt, svg, sango, dmnfrnt, ROT0, "IGS", "Demon Front (68k label V107KR, ROM M107KR 11/03/03) (ARM label V107KR, ROM 10/16/03 S106KR) (JAMMA PCB)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) // works but reports version mismatch (wants internal rom version and region to match external?)
+GAME( 2002, dmnfrnt, pgm, svg, pgm, dmnfrnt, ROT0, "IGS", "Demon Front (68k label V105, ROM M105XX 08/05/02) (ARM label V105, ROM 08/05/02 S105XX)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 68k time: 10:24:11 ARM time: 10:33:23
+GAME( 2002, dmnfrnta, dmnfrnt, svg, pgm, dmnfrnt, ROT0, "IGS", "Demon Front (68k label V102, ROM M102XX 06/19/02) (ARM label V102, ROM 05/24/02 S101XX)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 68k time: 13:44:08 ARM time: 13:04:31
+GAME( 2002, dmnfrntpcb, dmnfrnt, svg, pgm, dmnfrnt, ROT0, "IGS", "Demon Front (68k label V107KR, ROM M107KR 11/03/03) (ARM label V107KR, ROM 10/16/03 S106KR) (JAMMA PCB)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) // works but reports version mismatch (wants internal rom version and region to match external?)
@@ -5972,13 +3732,13 @@ GAME( 1998, drgw3100, drgw3, dw3, dw3, drgw3, ROT0, "IGS
GAME( 1998, dwex, pgm, dw3, dw3, drgw3, ROT0, "IGS", "Dragon World 3 EX (ver. 100)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE )
-GAME( 1999, puzlstar, pgm, kov_disabled_arm, sango, pstar, ROT0, "IGS", "Puzzle Star (ver. 100MG)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
+GAME( 2001, dw2001, pgm, kov2, dw2001, dw2001, ROT0, "IGS", "Dragon World 2001", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) // V0000 02/21/01 16:05:16
-GAME( 2001, py2k2, pgm, kov_disabled_arm, photoy2k, py2k2, ROT0, "IGS", "Photo Y2K 2", GAME_NOT_WORKING ) /* need internal rom of IGS027A */
+GAME( 1999, puzlstar, pgm, kov_simulated_arm, pstar, pstar, ROT0, "IGS", "Puzzle Star (ver. 100MG)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
-GAME( 2001, dw2001, pgm, kov2_disabled_arm, sango, dw2001, ROT0, "IGS", "Dragon World 2001", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) // V0000 02/21/01 16:05:16
+GAME( 2001, py2k2, pgm, kov_simulated_arm, py2k2, py2k2, ROT0, "IGS", "Photo Y2K 2", GAME_NOT_WORKING ) /* need internal rom of IGS027A */
-GAME( 2001, puzzli2, pgm, puzzli2_disabled_arm, sango, puzzli2, ROT0, "IGS", "Puzzli 2 Super (ver. 200)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE )
+GAME( 2001, puzzli2, pgm, kov_simulated_arm, puzzli2, puzzli2, ROT0, "IGS", "Puzzli 2 Super (ver. 200)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE )
@@ -5986,27 +3746,27 @@ GAME( 2001, puzzli2, pgm, puzzli2_disabled_arm, sango, puzzli2,
// all 3 68k roms still have V100 strings, but are clearly different builds, there don't appear to be build string dates in them. Two of the external ARM roms are marked V100 but are different builds, it's possible the single PCB version 100 is based on a later main revision
-GAME( 2003, theglad, pgm, svg, sango, theglad, ROT0, "IGS", "The Gladiator - Road of the Sword / Shen Jian (M68k label V100) (ARM label V100, ROM 01/16/03 SHEN JIAN)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */ // ARM time: 10:39:25
-GAME( 2003, theglada, theglad, svg, sango, theglad, ROT0, "IGS", "The Gladiator - Road of the Sword / Shen Jian (M68k label V101) (ARM label V107, ROM 06/06/03 SHEN JIAN V107)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */ // ARM time: 16:17:27
-GAME( 2003, thegladpcb, theglad, svg, sango, theglad, ROT0, "IGS", "The Gladiator - Road of the Sword / Shen Jian (M68k label V100) (ARM label V100, ROM 02/25/03 SHEN JIAN) (JAMMA PCB)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */ // ARM time: 16:32:21
+GAME( 2003, theglad, pgm, svg, pgm, theglad, ROT0, "IGS", "The Gladiator - Road of the Sword / Shen Jian (M68k label V100) (ARM label V100, ROM 01/16/03 SHEN JIAN)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */ // ARM time: 10:39:25
+GAME( 2003, theglada, theglad, svg, pgm, theglad, ROT0, "IGS", "The Gladiator - Road of the Sword / Shen Jian (M68k label V101) (ARM label V107, ROM 06/06/03 SHEN JIAN V107)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */ // ARM time: 16:17:27
+GAME( 2003, thegladpcb, theglad, svg, pgm, theglad, ROT0, "IGS", "The Gladiator - Road of the Sword / Shen Jian (M68k label V100) (ARM label V100, ROM 02/25/03 SHEN JIAN) (JAMMA PCB)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */ // ARM time: 16:32:21
-GAME( 2004, oldsplus, pgm, svg_disabled_arm, oldsplus, oldsplus, ROT0, "IGS", "Oriental Legend Special Plus / Xi You Shi E Zhuan Super Plus", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
+GAME( 2004, oldsplus, pgm, kov_simulated_arm, oldsplus, oldsplus, ROT0, "IGS", "Oriental Legend Special Plus / Xi You Shi E Zhuan Super Plus", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
-GAME( 2004, kovshp, pgm, kov, sango, kovshp, ROT0, "IGS", "Knights of Valour Super Heroes Plus / Sangoku Senki Super Heroes Plus (ver. 100)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
+GAME( 2004, kovshp, pgm, kov, kovsh, kovshp, ROT0, "IGS", "Knights of Valour Super Heroes Plus / Sangoku Senki Super Heroes Plus (ver. 100)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
// these bootlegs are clones of this instead
-GAME( 2004, kovlsqh, kovshp, kov, sango, kovlsqh2, ROT0, "bootleg", "Knights of Valour: Luan Shi Quan Huang / Sangoku Senki: Luan Shi Quan Huang (ver. 200CN)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
-GAME( 2004, kovlsqh2, kovshp, kov, sango, kovlsqh2, ROT0, "bootleg", "Knights of Valour: Luan Shi Quan Huang 2 / Sangoku Senki: Luan Shi Quan Huang 2 (ver. 200CN)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
-GAME( 2004, kovlsjb, kovshp, kov, sango, kovlsqh2, ROT0, "bootleg", "Knights of Valour: Luan Shi Jie Ba / Sangoku Senki: Luan Shi Jie Ba (ver. 200CN, set 1)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
-GAME( 2004, kovlsjba, kovshp, kov, sango, kovlsqh2, ROT0, "bootleg", "Knights of Valour: Luan Shi Jie Ba / Sangoku Senki: Luan Shi Jie Ba (ver. 200CN, set 2)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
+GAME( 2004, kovlsqh, kovshp, kov, kovsh, kovlsqh2, ROT0, "bootleg", "Knights of Valour: Luan Shi Quan Huang / Sangoku Senki: Luan Shi Quan Huang (ver. 200CN)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
+GAME( 2004, kovlsqh2, kovshp, kov, kovsh, kovlsqh2, ROT0, "bootleg", "Knights of Valour: Luan Shi Quan Huang 2 / Sangoku Senki: Luan Shi Quan Huang 2 (ver. 200CN)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
+GAME( 2004, kovlsjb, kovshp, kov, kovsh, kovlsqh2, ROT0, "bootleg", "Knights of Valour: Luan Shi Jie Ba / Sangoku Senki: Luan Shi Jie Ba (ver. 200CN, set 1)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
+GAME( 2004, kovlsjba, kovshp, kov, kovsh, kovlsqh2, ROT0, "bootleg", "Knights of Valour: Luan Shi Jie Ba / Sangoku Senki: Luan Shi Jie Ba (ver. 200CN, set 2)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
-GAME( 2005, killbldp, pgm, svg, sango, killbldp, ROT0, "IGS", "The Killing Blade Plus (ver. 300)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
+GAME( 2005, killbldp, pgm, svg, pgm, killbldp, ROT0, "IGS", "The Killing Blade Plus (ver. 300)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
-GAME( 2004, happy6, pgm, svg, sango, happy6, ROT0, "IGS", "Happy 6-in-1 (ver. 101CN)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
+GAME( 2004, happy6, pgm, svg, pgm, happy6, ROT0, "IGS", "Happy 6-in-1 (ver. 101CN)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
-GAME( 2005, svg, pgm, svg, sango, svg, ROT0, "IGS / Idea Factory", "S.V.G. - Spectral vs Generation (M68k label V200) (ARM label V200, ROM 10/11/05 S.V.G V201)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */ // label was 200, but it's code rev 201? // ARM time: 10:07:20
-GAME( 2005, svgpcb, svg, svg, sango, svgpcb, ROT0, "IGS / Idea Factory", "S.V.G. - Spectral vs Generation (M68k label V100JP) (ARM label V100JP ROM 05/12/05 S.V.G V100) (JAMMA PCB)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */ // ARM time: 15:31:35
+GAME( 2005, svg, pgm, svg, pgm, svg, ROT0, "IGS / Idea Factory", "S.V.G. - Spectral vs Generation (M68k label V200) (ARM label V200, ROM 10/11/05 S.V.G V201)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */ // label was 200, but it's code rev 201? // ARM time: 10:07:20
+GAME( 2005, svgpcb, svg, svg, pgm, svgpcb, ROT0, "IGS / Idea Factory", "S.V.G. - Spectral vs Generation (M68k label V100JP) (ARM label V100JP ROM 05/12/05 S.V.G V100) (JAMMA PCB)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */ // ARM time: 15:31:35
diff --git a/src/mame/drivers/sderby.c b/src/mame/drivers/sderby.c
index 809db05dbf5..26cb6612c6b 100644
--- a/src/mame/drivers/sderby.c
+++ b/src/mame/drivers/sderby.c
@@ -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 )
diff --git a/src/mame/includes/pgm.h b/src/mame/includes/pgm.h
index 9f8bdf6532c..121082ac3af 100644
--- a/src/mame/includes/pgm.h
+++ b/src/mame/includes/pgm.h
@@ -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 );
+
+INPUT_PORTS_EXTERN( orlegend );
+INPUT_PORTS_EXTERN( orld105k );
+
+/*----------- defined in machine/pgmprot1.c -----------*/
+
+/* emulations */
+DRIVER_INIT( photoy2k );
+DRIVER_INIT( kovsh );
+DRIVER_INIT( kovshp );
+DRIVER_INIT( kovlsqh2 );
+DRIVER_INIT( kovqhsgs );
+
+MACHINE_CONFIG_EXTERN( kov );
+
+/* 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 -----------*/
-READ16_HANDLER( pgm_asic3_r );
-WRITE16_HANDLER( pgm_asic3_w );
-WRITE16_HANDLER( pgm_asic3_reg_w );
+DRIVER_INIT( drgw2 );
+DRIVER_INIT( dw2v100x );
+DRIVER_INIT( drgw2c );
+DRIVER_INIT( drgw2j );
-READ16_HANDLER( sango_protram_r );
-READ16_HANDLER( asic28_r );
-WRITE16_HANDLER( asic28_w );
+/*----------- defined in machine/pgmprot6.c -----------*/
-READ16_HANDLER( dw2_d80000_r );
+MACHINE_CONFIG_EXTERN( olds );
+DRIVER_INIT( olds );
-READ16_HANDLER( oldsplus_protram_r );
-READ16_HANDLER( oldsplus_r );
-WRITE16_HANDLER( oldsplus_w );
+INPUT_PORTS_EXTERN( olds );
-MACHINE_RESET( kov );
-void install_protection_asic_sim_kov(running_machine &machine);
/*----------- defined in video/pgm.c -----------*/
diff --git a/src/mame/machine/pgmprot.c b/src/mame/machine/pgmprot.c
index cb9ed714062..1cfb3b83ea3 100644
--- a/src/mame/machine/pgmprot.c
+++ b/src/mame/machine/pgmprot.c
@@ -1,276 +1,15 @@
-#include "emu.h"
-#include "includes/pgm.h"
-
-
-
-/*** ASIC27a (Puzzle Star) -- ARM but with no external rom? behaves a bit like KOV ***/
-
-
-/*** (pstarS) ***/
-
-static const int pstar_ba[0x1E]={
- 0x02,0x00,0x00,0x01,0x00,0x03,0x00,0x00, //0
- 0x02,0x00,0x06,0x00,0x22,0x04,0x00,0x03, //8
- 0x00,0x00,0x06,0x00,0x20,0x07,0x00,0x03, //10
- 0x00,0x21,0x01,0x00,0x00,0x63
-};
-
-static const int pstar_b0[0x10]={
- 0x09,0x0A,0x0B,0x00,0x01,0x02,0x03,0x04,
- 0x05,0x06,0x07,0x08,0x00,0x00,0x00,0x00
-};
-
-static const int pstar_ae[0x10]={
- 0x5D,0x86,0x8C ,0x8B,0xE0,0x8B,0x62,0xAF,
- 0xB6,0xAF,0x10A,0xAF,0x00,0x00,0x00,0x00
-};
+/***********************************************************************
+ PGM ASIC3 PGM protection emulation
-static const int pstar_a0[0x10]={
- 0x02,0x03,0x04,0x05,0x06,0x01,0x0A,0x0B,
- 0x0C,0x0D,0x0E,0x09,0x00,0x00,0x00,0x00,
-};
+ these are simulations of the IGS 012 and 025 protection combination
+ used on the following PGM games
-static const int pstar_9d[0x10]={
- 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-};
+ Oriental Legend
-static const int pstar_90[0x10]={
- 0x0C,0x10,0x0E,0x0C,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
-};
-static const int pstar_8c[0x23]={
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,
- 0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,
- 0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x04,
- 0x03,0x03,0x03
-};
+ ***********************************************************************/
-static const int pstar_80[0x1a3]={
- 0x03,0x03,0x04,0x04,0x04,0x04,0x05,0x05,
- 0x05,0x05,0x06,0x06,0x03,0x03,0x04,0x04,
- 0x05,0x05,0x05,0x05,0x06,0x06,0x07,0x07,
- 0x03,0x03,0x04,0x04,0x05,0x05,0x05,0x05,
- 0x06,0x06,0x07,0x07,0x06,0x06,0x06,0x06,
- 0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x07,
- 0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x07,
- 0x07,0x07,0x08,0x08,0x05,0x05,0x05,0x05,
- 0x05,0x05,0x05,0x06,0x06,0x06,0x07,0x07,
- 0x06,0x06,0x06,0x07,0x07,0x07,0x08,0x08,
- 0x09,0x09,0x09,0x09,0x07,0x07,0x07,0x07,
- 0x07,0x08,0x08,0x08,0x08,0x09,0x09,0x09,
- 0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,
- 0x08,0x08,0x09,0x09,0x05,0x05,0x06,0x06,
- 0x06,0x07,0x07,0x08,0x08,0x08,0x08,0x09,
- 0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x08,
- 0x08,0x09,0x09,0x09,0x06,0x06,0x07,0x03,
- 0x07,0x06,0x07,0x07,0x08,0x07,0x05,0x04,
- 0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,
- 0x06,0x06,0x06,0x06,0x03,0x04,0x04,0x04,
- 0x04,0x05,0x05,0x06,0x06,0x06,0x06,0x07,
- 0x04,0x04,0x05,0x05,0x06,0x06,0x06,0x06,
- 0x06,0x07,0x07,0x08,0x05,0x05,0x06,0x07,
- 0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
- 0x05,0x05,0x05,0x07,0x07,0x07,0x07,0x07,
- 0x07,0x08,0x08,0x08,0x08,0x08,0x09,0x09,
- 0x09,0x09,0x03,0x04,0x04,0x05,0x05,0x05,
- 0x06,0x06,0x07,0x07,0x07,0x07,0x08,0x08,
- 0x08,0x09,0x09,0x09,0x03,0x04,0x05,0x05,
- 0x04,0x03,0x04,0x04,0x04,0x05,0x05,0x04,
- 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
- 0x03,0x03,0x03,0x04,0x04,0x04,0x04,0x04,
- 0x04,0x04,0x04,0x04,0x04,0x03,0x03,0x03,
- 0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,
- 0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00
-};
-
-
-
-
-READ16_HANDLER( pstars_protram_r )
-{
- pgm_state *state = space->machine().driver_data<pgm_state>();
-
- if (offset == 4) //region
- return input_port_read(space->machine(), "Region");
- else if (offset >= 0x10) //timer
- {
- logerror("PSTARS ACCESS COUNTER %6X\n", state->m_pstar_ram[offset - 0x10]);
- return state->m_pstar_ram[offset - 0x10]--;
- }
- return 0x0000;
-}
-
-READ16_HANDLER( pstars_r )
-{
- pgm_state *state = space->machine().driver_data<pgm_state>();
-
- if (offset == 0)
- {
- UINT16 d = state->m_pstars_val & 0xffff;
- UINT16 realkey = state->m_pstars_key >> 8;
- realkey |= state->m_pstars_key;
- d ^= realkey;
-// logerror("PSTARS A27 R %6X\n", state->m_pstars_val);
- return d;
- }
- else if (offset == 1)
- {
- UINT16 d = state->m_pstars_val >> 16;
- UINT16 realkey = state->m_pstars_key >> 8;
- realkey |= state->m_pstars_key;
- d ^= realkey;
- return d;
-
- }
- return 0xff;
-}
-
-WRITE16_HANDLER( pstars_w )
-{
- pgm_state *state = space->machine().driver_data<pgm_state>();
-
- if (offset == 0)
- {
- state->m_pstars_int[0] = data;
- return;
- }
-
- if (offset == 1)
- {
- UINT16 realkey;
- if ((data >> 8) == 0xff)
- state->m_pstars_key = 0xff00;
- realkey = state->m_pstars_key >> 8;
- realkey |= state->m_pstars_key;
- {
- state->m_pstars_key += 0x100;
- state->m_pstars_key &= 0xff00;
- if (state->m_pstars_key == 0xff00)
- state->m_pstars_key = 0x100;
- }
- data ^= realkey;
- state->m_pstars_int[1] = data;
- state->m_pstars_int[0] ^= realkey;
-
- switch (state->m_pstars_int[1] & 0xff)
- {
- case 0x99:
- state->m_pstars_key = 0x100;
- state->m_pstars_val = 0x880000;
- break;
-
- case 0xe0:
- state->m_pstars_val = 0xa00000 + (state->m_pstars_int[0] << 6);
- break;
-
- case 0xdc:
- state->m_pstars_val = 0xa00800 + (state->m_pstars_int[0] << 6);
- break;
-
- case 0xd0:
- state->m_pstars_val = 0xa01000 + (state->m_pstars_int[0] << 5);
- break;
-
- case 0xb1:
- state->m_pstar_b1 = state->m_pstars_int[0];
- state->m_pstars_val = 0x890000;
- break;
-
- case 0xbf:
- state->m_pstars_val = state->m_pstar_b1 * state->m_pstars_int[0];
- break;
-
- case 0xc1: //TODO:TIMER 0,1,2,FIX TO 0 should be OK?
- state->m_pstars_val = 0;
- break;
-
- case 0xce: //TODO:TIMER 0,1,2
- state->m_pstar_ce = state->m_pstars_int[0];
- state->m_pstars_val=0x890000;
- break;
-
- case 0xcf: //TODO:TIMER 0,1,2
- state->m_pstar_ram[state->m_pstar_ce] = state->m_pstars_int[0];
- state->m_pstars_val = 0x890000;
- break;
-
- case 0xe7:
- state->m_pstar_e7 = (state->m_pstars_int[0] >> 12) & 0xf;
- state->m_pstars_regs[state->m_pstar_e7] &= 0xffff;
- state->m_pstars_regs[state->m_pstar_e7] |= (state->m_pstars_int[0] & 0xff) << 16;
- state->m_pstars_val = 0x890000;
- break;
-
- case 0xe5:
- state->m_pstars_regs[state->m_pstar_e7] &= 0xff0000;
- state->m_pstars_regs[state->m_pstar_e7] |= state->m_pstars_int[0];
- state->m_pstars_val = 0x890000;
- break;
-
- case 0xf8: //@73C
- state->m_pstars_val = state->m_pstars_regs[state->m_pstars_int[0] & 0xf] & 0xffffff;
- break;
-
- case 0xba:
- state->m_pstars_val = pstar_ba[state->m_pstars_int[0]];
- break;
-
- case 0xb0:
- state->m_pstars_val = pstar_b0[state->m_pstars_int[0]];
- break;
-
- case 0xae:
- state->m_pstars_val = pstar_ae[state->m_pstars_int[0]];
- break;
-
- case 0xa0:
- state->m_pstars_val = pstar_a0[state->m_pstars_int[0]];
- break;
-
- case 0x9d:
- state->m_pstars_val = pstar_9d[state->m_pstars_int[0]];
- break;
-
- case 0x90:
- state->m_pstars_val = pstar_90[state->m_pstars_int[0]];
- break;
-
- case 0x8c:
- state->m_pstars_val = pstar_8c[state->m_pstars_int[0]];
- break;
-
- case 0x80:
- state->m_pstars_val = pstar_80[state->m_pstars_int[0]];
- break;
-
- default:
- state->m_pstars_val = 0x890000;
- logerror("PSTARS PC(%06x) UNKNOWN %4X %4X\n", cpu_get_pc(&space->device()), state->m_pstars_int[1], state->m_pstars_int[0]);
-
- }
-
- }
-}
+#include "emu.h"
+#include "includes/pgm.h"
/*** ASIC 3 (oriental legends protection) ****************************************/
@@ -399,930 +138,59 @@ WRITE16_HANDLER( pgm_asic3_reg_w )
state->m_asic3_reg = data & 0xff;
}
-/*** Knights of Valour / Sango / PhotoY2k Protection (from ElSemi) (ASIC28) ***/
-
-static const UINT32 B0TABLE[16] = {2, 0, 1, 4, 3}; //maps char portraits to tables
-
-// photo2yk bonus stage
-static const UINT32 AETABLE[16]={0x00,0x0a,0x14,
- 0x01,0x0b,0x15,
- 0x02,0x0c,0x16
-};
-
-//Not sure if BATABLE is complete
-static const UINT32 BATABLE[0x40]= {
- 0x00,0x29,0x2c,0x35,0x3a,0x41,0x4a,0x4e, //0x00
- 0x57,0x5e,0x77,0x79,0x7a,0x7b,0x7c,0x7d, //0x08
- 0x7e,0x7f,0x80,0x81,0x82,0x85,0x86,0x87, //0x10
- 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x90, //0x18
- 0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,
- 0x9e,0xa3,0xd4,0xa9,0xaf,0xb5,0xbb,0xc1
-};
-
-
-
-READ16_HANDLER( sango_protram_r )
-{
- // at offset == 4 is region (supplied by device)
- // 0 = china
- // 1 = taiwan
- // 2 = japan
- // 3 = korea
- // 4 = hong kong
- // 5 = world
-
- if (offset == 4)
- return input_port_read(space->machine(), "Region");
-
- // otherwise it doesn't seem to use the ram for anything important, we return 0 to avoid test mode corruption
- // kovplus reads from offset 000e a lot ... why?
-#ifdef MAME_DEBUG
- popmessage ("protection ram r %04x",offset);
-#endif
- return 0x0000;
-}
-
-#define BITSWAP10(val,B9,B8,B7,B6,B5,B4,B3,B2,B1,B0) \
- ((BIT(val, B9) << 9) | \
- (BIT(val, B8) << 8) | \
- (BIT(val, B7) << 7) | \
- (BIT(val, B6) << 6) | \
- (BIT(val, B5) << 5) | \
- (BIT(val, B4) << 4) | \
- (BIT(val, B3) << 3) | \
- (BIT(val, B2) << 2) | \
- (BIT(val, B1) << 1) | \
- (BIT(val, B0) << 0))
-
-
-READ16_HANDLER( asic28_r )
-{
- pgm_state *state = space->machine().driver_data<pgm_state>();
- UINT32 val = (state->m_asic28_regs[1] << 16) | (state->m_asic28_regs[0]);
-
- //logerror("Asic28 Read PC = %06x Command = %02x ??\n", cpu_get_pc(&space->device()), state->m_asic28_regs[1]);
-
- switch (state->m_asic28_regs[1] & 0xff)
- {
- case 0x99:
- val = 0x880000;
- break;
-
- case 0x9d: // spr palette
- val = 0xa00000 + ((state->m_asic28_regs[0] & 0x1f) << 6);
- break;
-
- case 0xb0:
- val = B0TABLE[state->m_asic28_regs[0] & 0xf];
- break;
-
- case 0xb4:
- {
- //UINT16 tmp = state->m_eoregs[v2];
- int v2 = state->m_asic28_regs[0] & 0x0f;
- int v1 = (state->m_asic28_regs[0] & 0x0f00) >> 8;
- //state->m_eoregs[v2] = state->m_eoregs[v1];
- //state->m_eoregs[v1] = tmp;
- if (state->m_asic28_regs[0] == 0x102)
- state->m_eoregs[1] = state->m_eoregs[0];
- else
- state->m_eoregs[v1] = state->m_eoregs[v2];
-
- val = 0x880000;
- }
- break;
-
- case 0xba:
- val = BATABLE[state->m_asic28_regs[0] & 0x3f];
- if (state->m_asic28_regs[0] > 0x2f)
- popmessage("Unmapped BA com %02x, contact ElSemi / MameDev", state->m_asic28_regs[0]);
- break;
-
- case 0xc0:
- val = 0x880000;
- break;
-
- case 0xc3: //TXT tile position Uses C0 to select column
- val = 0x904000 + (state->m_asic_params[0xc0] + state->m_asic_params[0xc3] * 64) * 4;
- break;
-
- case 0xcb:
- val = 0x880000;
- break;
-
- case 0xcc: //BG
- {
- int y = state->m_asic_params[0xcc];
- if (y & 0x400) //y is signed (probably x too and it also applies to TXT, but I've never seen it used)
- y -= (0x400 - (y & 0x3ff));
- val = 0x900000 + (((state->m_asic_params[0xcb] + (y) * 64) * 4) /*&0x1fff*/);
- }
- break;
-
- case 0xd0: //txt palette
- val = 0xa01000 + (state->m_asic28_regs[0] << 5);
- break;
- case 0xd6: //???? check it
- {
- int v2 = state->m_asic28_regs[0] & 0xf;
- //int v1 = (state->m_asic28_regs[0] & 0xf0) >> 4;
- state->m_eoregs[0] = state->m_eoregs[v2];
- //state->m_eoregs[v2] = 0;
- val = 0x880000;
- }
- break;
- case 0xdc: //bg palette
- val = 0xa00800 + (state->m_asic28_regs[0] << 6);
- break;
- case 0xe0: //spr palette
- val = 0xa00000 + ((state->m_asic28_regs[0] & 0x1f) << 6);
- break;
- case 0xe5:
- val = 0x880000;
- break;
+/* Oriental Legend INIT */
- case 0xe7:
- val = 0x880000;
- break;
-
- case 0xf0:
- val = 0x00C000;
- break;
-
- case 0xf8:
- val = state->m_eoregs[state->m_asic28_regs[0] & 0xf] & 0xffffff;
- break;
-
- case 0xfc: //Adjust damage level to char experience level
- {
- val = (state->m_asic_params[0xfc] * state->m_asic_params[0xfe]) >> 6;
- break;
- }
-
- case 0xfe: //todo
- val = 0x880000;
- break;
-
-
- default:
- val = 0x880000;
- }
-
- if(offset == 0)
- {
- UINT16 d = val & 0xffff;
- UINT16 realkey = state->m_asic28_key >> 8;
- realkey |= state->m_asic28_key;
- d ^= realkey;
- return d;
- }
- else if (offset == 1)
- {
- UINT16 d = val >> 16;
- UINT16 realkey = state->m_asic28_key >> 8;
- realkey |= state->m_asic28_key;
- d ^= realkey;
- state->m_asic28_rcnt++;
- if (!(state->m_asic28_rcnt & 0xf))
- {
- state->m_asic28_key += 0x100;
- state->m_asic28_key &= 0xff00;
- }
- return d;
- }
- return 0xff;
-}
-
-WRITE16_HANDLER( asic28_w )
+DRIVER_INIT( orlegend )
{
- pgm_state *state = space->machine().driver_data<pgm_state>();
-
- if (offset == 0)
- {
- UINT16 realkey =state->m_asic28_key >> 8;
- realkey |= state->m_asic28_key;
- data ^= realkey;
- state->m_asic28_regs[0] = data;
- return;
- }
- if (offset == 1)
- {
- UINT16 realkey;
-
- state->m_asic28_key = data & 0xff00;
-
- realkey = state->m_asic28_key >> 8;
- realkey |= state->m_asic28_key;
- data ^= realkey;
- state->m_asic28_regs[1] = data;
- logerror("ASIC28 CMD %04x PARAM %04x\n", state->m_asic28_regs[1], state->m_asic28_regs[0]);
-
- state->m_asic_params[state->m_asic28_regs[1] & 0xff] = state->m_asic28_regs[0];
- if (state->m_asic28_regs[1] == 0xE7)
- {
- UINT32 E0R = (state->m_asic_params[0xe7] >> 12) & 0xf;
- state->m_eoregs[E0R] &= 0xffff;
- state->m_eoregs[E0R] |= state->m_asic28_regs[0] << 16;
- }
- if (state->m_asic28_regs[1]==0xE5)
- {
- UINT32 E0R = (state->m_asic_params[0xe7] >> 12) & 0xf;
- state->m_eoregs[E0R] &= 0xff0000;
- state->m_eoregs[E0R] |= state->m_asic28_regs[0];
- }
- state->m_asic28_rcnt = 0;
- }
-}
-
-/* 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;
- }
-}
-
-/* Dragon World 3
-
-Dragon World 3 has 2 protection chips
-ASIC022 and ASIC025
-one of them also has an external data rom (encrypted?)
-
-code below is ElSemi's preliminary code, it doesn't work properly and isn't used, much of the protection isn't understood */
-
-#if 0
-AddWriteArea(0xda0000,0xdaffff,0,dw3_w8,dw3_w16,dw3_w32);
-AddReadArea (0xda0000,0xdaffff,0,dw3_r8,dw3_r16,dw3_r32);
-
-#define DW3BITSWAP(s,d,bs,bd) d=((d&(~(1<<bd)))|(((s>>bs)&1)<<bd))
-
-UINT16 dw3_Rw[8];
-UINT8 *dw3_R=(UINT8 *) dw3_Rw;
-
-UINT8 dw3_r8(UINT32 addr)
-{
- if(addr>=0xDA5610 && addr<=0xDA5613)
- return *((UINT8 *) (dw3_R+((addr-0xDA5610)^1)));
- return 0;
-}
-
-UINT16 dw3_r16(UINT32 addr)
-{
- if(addr>=0xDA5610 && addr<=0xDA5613)
- return *((UINT16 *) (dw3_R+(addr-0xDA5610)));
- return 0;
-}
-
-UINT32 dw3_r32(UINT32 addr)
-{
- return 0;
-}
-
-void dw3_w8(UINT32 addr,UINT8 val)
-{
- if(addr==0xDA5610)
- dw3_R[1]=val;
- if(addr==0xDA5611)
- dw3_R[0]=val;
- if(addr==0xDA5612)
- dw3_R[3]=val;
- if(addr==0xDA5613)
- dw3_R[2]=val;
-}
-
-void dw3_w16(UINT32 addr,UINT16 val)
-{
- if(addr>=0xDA5610 && addr<=0xDA5613)
- {
- UINT16 *s=((UINT16 *) (dw3_R+(addr-0xDA5610)));
- *s=val;
- if(addr==0xDA5610)
- {
- if(val==1)
- {
- UINT16 v1=dw3_Rw[1];
- UINT16 v2=0;
- DW3BITSWAP(v1,v2,0,0);
- DW3BITSWAP(v1,v2,1,1);
- DW3BITSWAP(v1,v2,7,2);
- DW3BITSWAP(v1,v2,6,3);
- DW3BITSWAP(v1,v2,5,4);
- DW3BITSWAP(v1,v2,4,5);
- DW3BITSWAP(v1,v2,3,6);
- DW3BITSWAP(v1,v2,2,7);
-
- dw3_Rw[1]=v2;
- }
- }
- }
-
-}
-
-
-void dw3_w32(UINT32 addr,UINT32 val)
-{
-
-}
-#endif
-
-/* Oriental Legend Super Plus ARM simulation */
-
-static const int oldsplus_80[0x5]={
- 0xbb8,0x1770,0x2328,0x2ee0,0xf4240
-};
-
-static const int oldsplus_fc[0x20]={
- 0x00,0x00,0x0a,0x3a,0x4e,0x2e,0x03,0x40,
- 0x33,0x43,0x26,0x2c,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x44,0x4d,0xb,0x27,0x3d,0x0f,
- 0x37,0x2b,0x02,0x2f,0x15,0x45,0x0e,0x30
-};
-
-static const int oldsplus_a0[0x20]={
- 0x000,0x023,0x046,0x069,0x08c,0x0af,0x0d2,0x0f5,
- 0x118,0x13b,0x15e,0x181,0x1a4,0x1c7,0x1ea,0x20d,
- 0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,
- 0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,
-};
-
-static const int oldsplus_90[0x7]={
- 0x50,0xa0,0xc8,0xf0,0x190,0x1f4,0x258
-};
-
-static const int oldsplus_5e[0x20]={
- 0x04,0x04,0x04,0x04,0x04,0x03,0x03,0x03,
- 0x02,0x02,0x02,0x01,0x01,0x01,0x01,0x01,
- 0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
-};
-
-static const int oldsplus_b0[0xe0]={
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
-
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,
- 0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,
- 0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,
-
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
- 0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,
- 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,
-
- 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,
- 0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,
- 0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,
- 0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,
-
- 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
- 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
- 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
- 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
-
- 0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,
- 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,
- 0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,
- 0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f
-};
-
-static const int oldsplus_ae[0xe0]={
- 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
- 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
- 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
- 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
-
- 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
- 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
- 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
- 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
-
- 0x1E,0x1F,0x20,0x21,0x22,0x23,0x23,0x23,
- 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
- 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
- 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
-
- 0x1F,0x20,0x21,0x22,0x23,0x23,0x23,0x23,
- 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
- 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
- 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
-
- 0x20,0x21,0x22,0x23,0x23,0x23,0x23,0x23,
- 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
- 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
- 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
-
- 0x21,0x22,0x23,0x23,0x23,0x23,0x23,0x23,
- 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
- 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
- 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
-
- 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
- 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
- 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
- 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23
-};
-
-static const int oldsplus_ba[0x4]={
- 0x3138,0x2328,0x1C20,0x1518
-};
-
-static const int oldsplus_9d[0x111]={
- 0x0000,0x0064,0x00c8,0x012c,0x0190,0x01f4,0x0258,0x02bc,
- 0x02f8,0x0334,0x0370,0x03ac,0x03e8,0x0424,0x0460,0x049c,
- 0x04d8,0x0514,0x0550,0x058c,0x05c8,0x0604,0x0640,0x06bc,
- 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
- 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x0000,
- 0x0064,0x00c8,0x012c,0x0190,0x01f4,0x0258,0x02bc,0x0302,
- 0x0348,0x038e,0x03d4,0x041a,0x0460,0x04a6,0x04ec,0x0532,
- 0x0578,0x05be,0x0604,0x064a,0x0690,0x06d6,0x06bc,0x06bc,
- 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
- 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x0000,0x0064,
- 0x00c8,0x012c,0x0190,0x01f4,0x0258,0x02bc,0x0316,0x0370,
- 0x03ca,0x0424,0x047e,0x04d8,0x0532,0x058c,0x05e6,0x0640,
- 0x069a,0x06f4,0x074e,0x07a8,0x0802,0x06bc,0x06bc,0x06bc,
- 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
- 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x0000,0x0064,0x00c8,
- 0x012c,0x0190,0x01f4,0x0258,0x02bc,0x032a,0x0398,0x0406,
- 0x0474,0x04e2,0x0550,0x05be,0x062c,0x069a,0x0708,0x0776,
- 0x07e4,0x0852,0x08c0,0x092e,0x06bc,0x06bc,0x06bc,0x06bc,
- 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
- 0x06bc,0x06bc,0x06bc,0x06bc,0x0000,0x0064,0x00c8,0x012c,
- 0x0190,0x01f4,0x0258,0x02bc,0x0348,0x03d4,0x0460,0x04ec,
- 0x0578,0x0604,0x0690,0x071c,0x07a8,0x0834,0x08c0,0x094c,
- 0x09d8,0x0a64,0x0af0,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
- 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
- 0x06bc,0x06bc,0x06bc,0x0000,0x0064,0x00c8,0x012c,0x0190,
- 0x01f4,0x0258,0x02bc,0x0384,0x044c,0x0514,0x05dc,0x06a4,
- 0x076c,0x0834,0x08fc,0x09c4,0x0a8c,0x0b54,0x0c1c,0x0ce4,
- 0x0dac,0x0e74,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
- 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
- 0x06bc,0x06bc,0x0000,0x0064,0x00c8,0x012c,0x0190,0x01f4,
- 0x0258,0x02bc,0x030c,0x035c,0x03ac,0x03fc,0x044c,0x049c,
- 0x04ec,0x053c,0x058c,0x05dc,0x062c,0x067c,0x06cc,0x071c,
- 0x076c,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
- 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
- 0x06bc
-};
-
-static const int oldsplus_8c[0x20]={
- 0x0032,0x0032,0x0064,0x0096,0x0096,0x00fa,0x012c,0x015e,
- 0x0032,0x0064,0x0096,0x00c8,0x00c8,0x012c,0x015e,0x0190,
- 0x0064,0x0096,0x00c8,0x00fa,0x00fa,0x015e,0x0190,0x01c2,
- 0x0096,0x00c8,0x00fa,0x012c,0x012c,0x0190,0x01c2,0x01f4
-};
-
-READ16_HANDLER( oldsplus_protram_r )
-{
- if (offset == 4)
- return input_port_read(space->machine(), "Region");
-
- return 0x0000;
-}
-
-READ16_HANDLER( oldsplus_r )
-{
- pgm_state *state = space->machine().driver_data<pgm_state>();
-
- if (offset == 0)
- {
- UINT16 d = state->m_oldsplus_val & 0xffff;
- UINT16 realkey = state->m_oldsplus_key >> 8;
- realkey |= state->m_oldsplus_key;
- d ^= realkey;
- return d;
- }
- else if (offset == 1)
- {
- UINT16 d = state->m_oldsplus_val >> 16;
- UINT16 realkey = state->m_oldsplus_key >> 8;
- realkey |= state->m_oldsplus_key;
- d ^= realkey;
- return d;
-
- }
- return 0xff;
-}
-
-WRITE16_HANDLER( oldsplus_w )
-{
- pgm_state *state = space->machine().driver_data<pgm_state>();
-
- if (offset == 0)
- {
- state->m_oldsplus_int[0] = data;
- return;
- }
-
- if (offset == 1)
- {
- UINT16 realkey;
- if ((data >> 8) == 0xff)
- state->m_oldsplus_key = 0xff00;
- realkey = state->m_oldsplus_key >> 8;
- realkey |= state->m_oldsplus_key;
- {
- state->m_oldsplus_key += 0x100;
- state->m_oldsplus_key &= 0xff00;
- if (state->m_oldsplus_key == 0xff00)
- state->m_oldsplus_key = 0x100;
- }
- data ^= realkey;
- state->m_oldsplus_int[1] = data;
- state->m_oldsplus_int[0] ^= realkey;
-
- switch (state->m_oldsplus_int[1] & 0xff)
- {
- case 0x88:
- state->m_oldsplus_key = 0x100;
- state->m_oldsplus_val = 0x990000;
- break;
-
- case 0xd0:
- state->m_oldsplus_val = 0xa01000 + (state->m_oldsplus_int[0] << 5);
- break;
-
- case 0xc0:
- state->m_oldsplus_val = 0xa00000 + (state->m_oldsplus_int[0] << 6);
- break;
-
- case 0xc3:
- state->m_oldsplus_val = 0xa00800 + (state->m_oldsplus_int[0] << 6);
- break;
-
- case 0x36:
- state->m_oldsplus_ram[0x36] = state->m_oldsplus_int[0];
- state->m_oldsplus_val = 0x990000;
- break;
-
- case 0x33:
- state->m_oldsplus_ram[0x33] = state->m_oldsplus_int[0];
- state->m_oldsplus_val = 0x990000;
- break;
-
- case 0x35:
- state->m_oldsplus_ram[0x36] += state->m_oldsplus_int[0];
- state->m_oldsplus_val = 0x990000;
- break;
-
- case 0x37:
- state->m_oldsplus_ram[0x33] += state->m_oldsplus_int[0];
- state->m_oldsplus_val = 0x990000;
- break;
-
- case 0x34:
- state->m_oldsplus_val = state->m_oldsplus_ram[0x36];
- break;
-
- case 0x38:
- state->m_oldsplus_val = state->m_oldsplus_ram[0x33];
- break;
-
- case 0x80:
- state->m_oldsplus_val = oldsplus_80[state->m_oldsplus_int[0]];
- break;
-
- case 0xe7:
- state->m_oldsplus_ram[0xe7] = state->m_oldsplus_int[0];
- state->m_oldsplus_val = 0x990000;
- break;
-
- case 0xe5:
- switch (state->m_oldsplus_ram[0xe7])
- {
- case 0xb000:
- state->m_oldsplus_regs[0xb] = state->m_oldsplus_int[0];
- state->m_oldsplus_regs[0xc] = 0;
- break;
-
- case 0xc000:
- state->m_oldsplus_regs[0xc] = state->m_oldsplus_int[0];
- break;
-
- case 0xd000:
- state->m_oldsplus_regs[0xd] = state->m_oldsplus_int[0];
- break;
-
- case 0xf000:
- state->m_oldsplus_regs[0xf] = state->m_oldsplus_int[0];
- break;
- }
- state->m_oldsplus_val = 0x990000;
- break;
-
- case 0xf8:
- state->m_oldsplus_val = state->m_oldsplus_regs[state->m_oldsplus_int[0]];
- break;
-
- case 0xfc:
- state->m_oldsplus_val = oldsplus_fc[state->m_oldsplus_int[0]];
- break;
-
- case 0xc5:
- state->m_oldsplus_regs[0xd] --;
- state->m_oldsplus_val = 0x990000;
- break;
-
- case 0xd6:
- state->m_oldsplus_regs[0xb] ++;
- state->m_oldsplus_val = 0x990000;
- break;
-
- case 0x3a:
- state->m_oldsplus_regs[0xf] = 0;
- state->m_oldsplus_val = 0x990000;
- break;
-
- case 0xf0:
- state->m_oldsplus_ram[0xf0] = state->m_oldsplus_int[0];
- state->m_oldsplus_val = 0x990000;
- break;
-
- case 0xed:
- state->m_oldsplus_val = state->m_oldsplus_int[0] << 0x6;
- state->m_oldsplus_val += state->m_oldsplus_ram[0xf0];
- state->m_oldsplus_val = state->m_oldsplus_val << 0x2;
- state->m_oldsplus_val += 0x900000;
- break;
-
- case 0xe0:
- state->m_oldsplus_ram[0xe0] = state->m_oldsplus_int[0];
- state->m_oldsplus_val = 0x990000;
- break;
-
- case 0xdc:
- state->m_oldsplus_val = state->m_oldsplus_int[0] << 0x6;
- state->m_oldsplus_val += state->m_oldsplus_ram[0xe0];
- state->m_oldsplus_val = state->m_oldsplus_val << 0x2;
- state->m_oldsplus_val += 0x904000;
- break;
-
- case 0xcb:
- state->m_oldsplus_val = 0xc000;
- break;
-
- case 0xa0:
- state->m_oldsplus_val = oldsplus_a0[state->m_oldsplus_int[0]];
- break;
-
- case 0xba:
- state->m_oldsplus_val = oldsplus_ba[state->m_oldsplus_int[0]];
- break;
-
- case 0x5e:
- state->m_oldsplus_val = oldsplus_5e[state->m_oldsplus_int[0]];
- break;
-
- case 0xb0:
- state->m_oldsplus_val = oldsplus_b0[state->m_oldsplus_int[0]];
- break;
-
- case 0xae:
- state->m_oldsplus_val = oldsplus_ae[state->m_oldsplus_int[0]];
- break;
-
- case 0x9d:
- state->m_oldsplus_val = oldsplus_9d[state->m_oldsplus_int[0]];
- break;
-
- case 0x90:
- state->m_oldsplus_val = oldsplus_90[state->m_oldsplus_int[0]];
- break;
-
- case 0x8c:
- state->m_oldsplus_val = oldsplus_8c[state->m_oldsplus_int[0]];
- break;
-
- default:
- state->m_oldsplus_val = 0x990000;
- printf("%06X: oldsplus_UNKNOWN W CMD %X VAL %X\n",cpu_get_pc(&space->device()),state->m_oldsplus_int[1],state->m_oldsplus_int[0]);
- break;
- }
- }
-}
-
-/* Old KOV and bootlegs sim ... really these should be read out... */
-
-static const UINT8 kov_BATABLE[0x40] = {
- 0x00,0x29,0x2c,0x35,0x3a,0x41,0x4a,0x4e,0x57,0x5e,0x77,0x79,0x7a,0x7b,0x7c,0x7d,
- 0x7e,0x7f,0x80,0x81,0x82,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x90,
- 0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9e,0xa3,0xd4,0xa9,0xaf,0xb5,0xbb,0xc1
-};
-
-static const UINT8 kov_B0TABLE[16] = { 2, 0, 1, 4, 3 }; // Maps char portraits to tables
-
-static UINT32 kov_slots[16];
-static UINT16 kov_internal_slot;
-static UINT16 kov_key;
-static UINT32 kov_response;
-static UINT16 kov_value;
-
-static UINT16 kov_c0_value;
-static UINT16 kov_cb_value;
-static UINT16 kov_fe_value;
-
-WRITE16_HANDLER( kov_asic_sim_w )
-{
- switch ((offset*2) & 0x06)
- {
- case 0: kov_value = data; return;
-
- case 2:
- {
- if ((data >> 8) == 0xff) kov_key = 0xffff;
-
- kov_value ^= kov_key;
-
- // bprintf (PRINT_NORMAL, _T("ASIC27 command: %2.2x data: %4.4x\n"), (data ^ kov_key) & 0xff, kov_value);
-
- switch ((data ^ kov_key) & 0xff)
- {
- case 0x67: // unknown or status check?
- case 0x8e:
- case 0xa3:
- case 0x33: // kovsgqyz (a3)
- case 0x3a: // kovplus
- case 0xc5: // kovplus
- kov_response = 0x880000;
- break;
-
- case 0x99: // Reset
- kov_response = 0x880000;
- kov_key = 0;
- break;
-
- case 0x9d: // Sprite palette offset
- kov_response = 0xa00000 + ((kov_value & 0x1f) * 0x40);
- break;
-
- case 0xb0: // Read from data table
- kov_response = kov_B0TABLE[kov_value & 0x0f];
- break;
-
- case 0xb4: // Copy slot 'a' to slot 'b'
- case 0xb7: // kovsgqyz (b4)
- {
- kov_response = 0x880000;
-
- if (kov_value == 0x0102) kov_value = 0x0100; // why?
-
- kov_slots[(kov_value >> 8) & 0x0f] = kov_slots[(kov_value >> 0) & 0x0f];
- }
- break;
-
- case 0xba: // Read from data table
- kov_response = kov_BATABLE[kov_value & 0x3f];
- break;
-
- case 0xc0: // Text layer 'x' select
- kov_response = 0x880000;
- kov_c0_value = kov_value;
- break;
-
- case 0xc3: // Text layer offset
- kov_response = 0x904000 + ((kov_c0_value + (kov_value * 0x40)) * 4);
- break;
-
- case 0xcb: // Background layer 'x' select
- kov_response = 0x880000;
- kov_cb_value = kov_value;
- break;
-
- case 0xcc: // Background layer offset
- if (kov_value & 0x400) kov_value = -(0x400 - (kov_value & 0x3ff));
- kov_response = 0x900000 + ((kov_cb_value + (kov_value * 0x40)) * 4);
- break;
-
- case 0xd0: // Text palette offset
- case 0xcd: // kovsgqyz (d0)
- kov_response = 0xa01000 + (kov_value * 0x20);
- break;
-
- case 0xd6: // Copy slot to slot 0
- kov_response = 0x880000;
- kov_slots[0] = kov_slots[kov_value & 0x0f];
- break;
-
- case 0xdc: // Background palette offset
- case 0x11: // kovsgqyz (dc)
- kov_response = 0xa00800 + (kov_value * 0x40);
- break;
-
- case 0xe0: // Sprite palette offset
- case 0x9e: // kovsgqyz (e0)
- kov_response = 0xa00000 + ((kov_value & 0x1f) * 0x40);
- break;
-
- case 0xe5: // Write slot (low)
- {
- kov_response = 0x880000;
-
- INT32 sel = (kov_internal_slot >> 12) & 0x0f;
- kov_slots[sel] = (kov_slots[sel] & 0x00ff0000) | ((kov_value & 0xffff) << 0);
- }
- break;
-
- case 0xe7: // Write slot (and slot select) (high)
- {
- kov_response = 0x880000;
- kov_internal_slot = kov_value;
-
- INT32 sel = (kov_internal_slot >> 12) & 0x0f;
- kov_slots[sel] = (kov_slots[sel] & 0x0000ffff) | ((kov_value & 0x00ff) << 16);
- }
- break;
-
- case 0xf0: // Some sort of status read?
- kov_response = 0x00c000;
- break;
-
- case 0xf8: // Read slot
- case 0xab: // kovsgqyz (f8)
- kov_response = kov_slots[kov_value & 0x0f] & 0x00ffffff;
- break;
-
- case 0xfc: // Adjust damage level to char experience level
- kov_response = (kov_value * kov_fe_value) >> 6;
- break;
-
- case 0xfe: // Damage level adjust
- kov_response = 0x880000;
- kov_fe_value = kov_value;
- break;
-
- default:
- kov_response = 0x880000;
- // bprintf (PRINT_NORMAL, _T("Unknown ASIC27 command: %2.2x data: %4.4x\n"), (data ^ kov_key) & 0xff, kov_value);
- break;
- }
-
- kov_key = (kov_key + 0x0100) & 0xff00;
- if (kov_key == 0xff00) kov_key = 0x0100;
- kov_key |= kov_key >> 8;
- }
- return;
-
- case 4: return;
- }
-}
-
-READ16_HANDLER( kov_asic_sim_r )
-{
- switch ((offset*2) & 0x02)
- {
- case 0: return (kov_response >> 0) ^ kov_key;
- case 2: return (kov_response >> 16) ^ kov_key;
- }
-
- return 0;
-}
-
-MACHINE_RESET( kov )
-{
- kov_internal_slot = 0;
- kov_key = 0;
- kov_response = 0;
- kov_value = 0;
-
- kov_c0_value = 0;
- kov_cb_value = 0;
- kov_fe_value = 0;
-
- cputag_set_input_line(machine, "soundcpu", INPUT_LINE_HALT, ASSERT_LINE);
-}
+ pgm_state *state = machine.driver_data<pgm_state>();
+ pgm_basic_init(machine);
+
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0xC0400e, 0xC0400f, FUNC(pgm_asic3_r), FUNC(pgm_asic3_w));
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_write_handler(0xC04000, 0xC04001, FUNC(pgm_asic3_reg_w));
+
+ state->m_asic3_reg = 0;
+ state->m_asic3_latch[0] = 0;
+ state->m_asic3_latch[1] = 0;
+ state->m_asic3_latch[2] = 0;
+ state->m_asic3_x = 0;
+ state->m_asic3_y = 0;
+ state->m_asic3_z = 0;
+ state->m_asic3_h1 = 0;
+ state->m_asic3_h2 = 0;
+ state->m_asic3_hold = 0;
+
+ state->save_item(NAME(state->m_asic3_reg));
+ state->save_item(NAME(state->m_asic3_latch));
+ state->save_item(NAME(state->m_asic3_x));
+ state->save_item(NAME(state->m_asic3_y));
+ state->save_item(NAME(state->m_asic3_z));
+ state->save_item(NAME(state->m_asic3_h1));
+ state->save_item(NAME(state->m_asic3_h2));
+ state->save_item(NAME(state->m_asic3_hold));
+}
+
+
+INPUT_PORTS_START( orlegend )
+ PORT_INCLUDE ( pgm )
+
+ PORT_MODIFY("Region")
+ PORT_DIPNAME( 0x0003, 0x0000, DEF_STR( Region ) )
+ PORT_CONFSETTING( 0x0000, DEF_STR( World ) )
+ PORT_CONFSETTING( 0x0001, "World (duplicate)" ) // again?
+ PORT_CONFSETTING( 0x0002, DEF_STR( Korea ) )
+ PORT_CONFSETTING( 0x0003, DEF_STR( China ) )
+INPUT_PORTS_END
+
+INPUT_PORTS_START( orld105k )
+ PORT_INCLUDE ( pgm )
+
+ PORT_MODIFY("Region")
+ PORT_DIPNAME( 0x0003, 0x0002, DEF_STR( Unused ) ) // region switch
+ PORT_DIPSETTING( 0x0002, DEF_STR( Off ) ) // if enabled, game gives
+ PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) // "incorrect version" error
+INPUT_PORTS_END
-void install_protection_asic_sim_kov(running_machine &machine)
-{
- machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x500000, 0x500003, FUNC(kov_asic_sim_r), FUNC(kov_asic_sim_w));
- machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x4f0000, 0x4fffff, FUNC(sango_protram_r));
-}
diff --git a/src/mame/machine/pgmprot1.c b/src/mame/machine/pgmprot1.c
new file mode 100644
index 00000000000..ca19cc480db
--- /dev/null
+++ b/src/mame/machine/pgmprot1.c
@@ -0,0 +1,1624 @@
+/***********************************************************************
+ PGM IGA027A (55857E type) ARM protection simulations & emulation
+
+ these are simulations of the 'kov' type ARM device
+ used by
+
+ Knights of Valor (kov) + bootlegs
+ Knights of Valor Plus (kovplus)
+ Puzzli 2 Super (puzzli2)
+ Photo Y2k2 (py2k2)
+ Puzzle Star (puzlstar)
+
+ the following appear to use this scheme but are post 2001 so
+ might use a newer revision of the chip with EO area
+
+ DoDonPachi Dai-ou-jou (ddpdoj)
+ Espgaluda (espgal)
+ Ketsui (ket)
+ Oriental Legend Super Plus (oldsplus)
+ Knights of Valor Super Plus (kovshp) + bootlegs
+
+ the following also use the 55857E type and we emulate the
+ internal ROM
+
+ Photo Y2k (photoy2k)
+ Knights of Valor Superheros (kovsh) + bootlegs
+
+ ----
+
+ Many of the simulations are preliminary. If functions to access
+ internal tables exist it is sometimes possible to extract the ROM
+ via these functions if the buffers are unchecked, however many
+ games have no table accesses.
+
+ ----
+
+ The basic protection communication is the same between all games
+ however the commands differ
+
+ None of these games have an external ARM rom, although it appears
+ the program code does check for the possibility of one existing.
+
+ 68k code is encrypted on these, decryption table is uploaded to
+ ARM space.
+
+ Game Region is supplied by internal ARM rom.
+
+
+ ***********************************************************************/
+
+#include "emu.h"
+#include "includes/pgm.h"
+
+/**************************** EMULATION *******************************/
+/* used by photoy2k, kovsh */
+
+static READ32_HANDLER( kovsh_arm7_protlatch_r )
+{
+ pgm_state *state = space->machine().driver_data<pgm_state>();
+
+ space->machine().scheduler().synchronize(); // force resync
+
+ return (state->m_kovsh_highlatch_68k_w << 16) | (state->m_kovsh_lowlatch_68k_w);
+}
+
+static WRITE32_HANDLER( kovsh_arm7_protlatch_w )
+{
+ pgm_state *state = space->machine().driver_data<pgm_state>();
+
+ space->machine().scheduler().synchronize(); // force resync
+
+ if (ACCESSING_BITS_16_31)
+ {
+ state->m_kovsh_highlatch_arm_w = data >> 16;
+ state->m_kovsh_highlatch_68k_w = 0;
+ }
+ if (ACCESSING_BITS_0_15)
+ {
+ state->m_kovsh_lowlatch_arm_w = data;
+ state->m_kovsh_lowlatch_68k_w = 0;
+ }
+}
+
+static READ16_HANDLER( kovsh_68k_protlatch_r )
+{
+ pgm_state *state = space->machine().driver_data<pgm_state>();
+
+ space->machine().scheduler().synchronize(); // force resync
+
+ switch (offset)
+ {
+ case 1: return state->m_kovsh_highlatch_arm_w;
+ case 0: return state->m_kovsh_lowlatch_arm_w;
+ }
+ return -1;
+}
+
+static WRITE16_HANDLER( kovsh_68k_protlatch_w )
+{
+ pgm_state *state = space->machine().driver_data<pgm_state>();
+
+ space->machine().scheduler().synchronize(); // force resync
+
+ switch (offset)
+ {
+ case 1:
+ state->m_kovsh_highlatch_68k_w = data;
+ break;
+
+ case 0:
+ state->m_kovsh_lowlatch_68k_w = data;
+ break;
+ }
+}
+
+static READ16_HANDLER( kovsh_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 << 1)];
+}
+
+static WRITE16_HANDLER( kovsh_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 << 1)]);
+}
+
+
+
+
+static READ32_HANDLER( kovsh_arm7_unk_r )
+{
+ pgm_state *state = space->machine().driver_data<pgm_state>();
+ return state->m_kovsh_counter++;
+}
+
+static READ32_HANDLER( kovsh_exrom_r )
+{
+ return 0x00000000;
+}
+
+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]);
+}
+
+/* 55857E? */
+/* Knights of Valor, Photo Y2k */
+/* no execute only space? */
+static ADDRESS_MAP_START( kov_map, AS_PROGRAM, 16)
+ AM_IMPORT_FROM(pgm_mem)
+ AM_RANGE(0x100000, 0x4effff) AM_ROMBANK("bank1") /* Game ROM */
+ AM_RANGE(0x4f0000, 0x4f003f) AM_READWRITE(kovsh_arm7_ram_r, kovsh_arm7_ram_w) /* ARM7 Shared RAM */
+ AM_RANGE(0x500000, 0x500005) AM_READWRITE(kovsh_68k_protlatch_r, kovsh_68k_protlatch_w) /* ARM7 Latch */
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( 55857E_arm7_map, AS_PROGRAM, 32 )
+ AM_RANGE(0x00000000, 0x00003fff) AM_ROM
+ AM_RANGE(0x08100000, 0x083fffff) AM_READ(kovsh_exrom_r) // unpopulated, returns 0 to keep checksum happy
+ AM_RANGE(0x10000000, 0x100003ff) AM_RAM // internal ram for asic
+ AM_RANGE(0x40000000, 0x40000003) AM_READWRITE(kovsh_arm7_protlatch_r, kovsh_arm7_protlatch_w)
+ AM_RANGE(0x40000008, 0x4000000b) AM_WRITENOP // ?
+ AM_RANGE(0x4000000c, 0x4000000f) AM_READ(kovsh_arm7_unk_r)
+ AM_RANGE(0x50800000, 0x5080003f) AM_READWRITE(arm7_shareram_r, arm7_shareram_w) AM_BASE_MEMBER(pgm_state, m_arm7_shareram)
+ AM_RANGE(0x50000000, 0x500003ff) AM_RAM // uploads xor table to decrypt 68k rom here
+ADDRESS_MAP_END
+
+
+MACHINE_CONFIG_DERIVED( kov, pgm )
+ MCFG_CPU_MODIFY("maincpu")
+ MCFG_CPU_PROGRAM_MAP(kov_map)
+
+ /* protection CPU */
+ MCFG_CPU_ADD("prot", ARM7, 20000000) // 55857E?
+ MCFG_CPU_PROGRAM_MAP(55857E_arm7_map)
+MACHINE_CONFIG_END
+
+/**************************** SIMULATIONS *****************************/
+
+static ADDRESS_MAP_START( kov_sim_map, AS_PROGRAM, 16)
+ AM_IMPORT_FROM(pgm_mem)
+ AM_RANGE(0x100000, 0x4effff) AM_ROMBANK("bank1") /* Game ROM */
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START( cavepgm_mem, AS_PROGRAM, 16)
+ AM_IMPORT_FROM(pgm_base_mem)
+ AM_RANGE(0x000000, 0x3fffff) AM_ROM
+ /* protection devices installed (simulated) later */
+ADDRESS_MAP_END
+
+
+static MACHINE_START( cavepgm )
+{
+ MACHINE_START_CALL(pgm);
+
+ pgm_kovarmsim_state *state = machine.driver_data<pgm_kovarmsim_state>();
+
+ state->save_item(NAME(state->m_value0));
+ state->save_item(NAME(state->m_value1));
+ state->save_item(NAME(state->m_valuekey));
+ state->save_item(NAME(state->m_valueresponse));
+ state->save_item(NAME(state->m_ddp3internal_slot));
+ state->save_item(NAME(state->m_ddp3slots));
+}
+
+MACHINE_CONFIG_START( cavepgm, pgm_kovarmsim_state )
+
+ /* basic machine hardware */
+ MCFG_CPU_ADD("maincpu", M68000, 20000000)
+ MCFG_CPU_PROGRAM_MAP(cavepgm_mem)
+ MCFG_TIMER_ADD_SCANLINE("scantimer", pgm_interrupt, "screen", 0, 1)
+
+ MCFG_CPU_ADD("soundcpu", Z80, 33868800/4)
+ MCFG_CPU_PROGRAM_MAP(pgm_z80_mem)
+ MCFG_CPU_IO_MAP(pgm_z80_io)
+
+ MCFG_MACHINE_START( cavepgm )
+ MCFG_MACHINE_RESET( pgm )
+ MCFG_NVRAM_ADD_0FILL("sram")
+
+ MCFG_V3021_ADD("rtc")
+
+ /* video hardware */
+ MCFG_SCREEN_ADD("screen", RASTER)
+ MCFG_SCREEN_REFRESH_RATE(59.17) // verified on pcb
+ MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
+ MCFG_SCREEN_SIZE(64*8, 64*8)
+ MCFG_SCREEN_VISIBLE_AREA(0*8, 56*8-1, 0*8, 28*8-1)
+ MCFG_SCREEN_UPDATE_STATIC(pgm)
+ MCFG_SCREEN_VBLANK_STATIC(pgm)
+
+ MCFG_GFXDECODE(pgm)
+ MCFG_PALETTE_LENGTH(0x1200/2)
+
+ MCFG_VIDEO_START(pgm)
+
+ /*sound hardware */
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+ MCFG_ICS2115_ADD("ics", 0, pgm_sound_irq)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 5.0)
+MACHINE_CONFIG_END
+
+MACHINE_CONFIG_DERIVED( kov_simulated_arm, cavepgm )
+ MCFG_CPU_MODIFY("maincpu")
+ MCFG_CPU_PROGRAM_MAP(kov_sim_map)
+
+ /* protection CPU */
+ MCFG_CPU_ADD("prot", ARM7, 20000000) // 55857E?
+ MCFG_CPU_PROGRAM_MAP(55857E_arm7_map)
+ MCFG_DEVICE_DISABLE()
+MACHINE_CONFIG_END
+
+void kovsh_latch_init( running_machine &machine )
+{
+ pgm_state *state = machine.driver_data<pgm_state>();
+
+ state->m_kovsh_highlatch_arm_w = 0;
+ state->m_kovsh_lowlatch_arm_w = 0;
+ state->m_kovsh_highlatch_68k_w = 0;
+ state->m_kovsh_lowlatch_68k_w = 0;
+ state->m_kovsh_counter = 1;
+
+ state->save_item(NAME(state->m_kovsh_highlatch_arm_w));
+ state->save_item(NAME(state->m_kovsh_lowlatch_arm_w));
+ state->save_item(NAME(state->m_kovsh_highlatch_68k_w));
+ state->save_item(NAME(state->m_kovsh_lowlatch_68k_w));
+ state->save_item(NAME(state->m_kovsh_counter));
+}
+
+static READ16_HANDLER( kovsh_fake_region_r )
+{
+ pgm_state *state = space->machine().driver_data<pgm_state>();
+ int regionhack = input_port_read(space->machine(), "RegionHack");
+ if (regionhack != 0xff) return regionhack;
+
+ offset = 0x4;
+ UINT16 *share16 = (UINT16 *)state->m_arm7_shareram;
+ return share16[BYTE_XOR_LE(offset << 1)];
+}
+
+DRIVER_INIT( photoy2k )
+{
+ pgm_basic_init(machine);
+ pgm_photoy2k_decrypt(machine);
+ kovsh_latch_init(machine);
+ /* we only have a china internal ROM dumped for now.. allow region to be changed for debugging (to ensure all alt titles / regions can be seen) */
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x4f0008, 0x4f0009, FUNC(kovsh_fake_region_r));
+}
+
+DRIVER_INIT( kovsh )
+{
+ pgm_basic_init(machine);
+ pgm_kovsh_decrypt(machine);
+ kovsh_latch_init(machine);
+ /* we only have a china internal ROM dumped for now.. allow region to be changed for debugging (to ensure all alt titles / regions can be seen) */
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x4f0008, 0x4f0009, FUNC(kovsh_fake_region_r));
+}
+
+DRIVER_INIT( kovshp )
+{
+ pgm_basic_init(machine);
+ pgm_kovshp_decrypt(machine);
+ kovsh_latch_init(machine);
+ /* we only have a china internal ROM dumped for now.. allow region to be changed for debugging (to ensure all alt titles / regions can be seen) */
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x4f0008, 0x4f0009, FUNC(kovsh_fake_region_r));
+}
+
+/* bootleg inits */
+
+static void pgm_decode_kovlsqh2_tiles( running_machine &machine )
+{
+ int i, j;
+ UINT16 *src = (UINT16 *)(machine.region("tiles")->base() + 0x180000);
+ UINT16 *dst = auto_alloc_array(machine, UINT16, 0x800000);
+
+ for (i = 0; i < 0x800000 / 2; i++)
+ {
+ j = BITSWAP24(i, 23, 22, 9, 8, 21, 18, 0, 1, 2, 3, 16, 15, 14, 13, 12, 11, 10, 19, 20, 17, 7, 6, 5, 4);
+
+ dst[j] = BITSWAP16(src[i], 1, 14, 8, 7, 0, 15, 6, 9, 13, 2, 5, 10, 12, 3, 4, 11);
+ }
+
+ memcpy( src, dst, 0x800000 );
+
+ auto_free( machine, dst );
+}
+
+static void pgm_decode_kovlsqh2_sprites( running_machine &machine, UINT8 *src )
+{
+ int i, j;
+ UINT8 *dst = auto_alloc_array(machine, UINT8, 0x800000);
+
+ for (i = 0; i < 0x800000; i++)
+ {
+ j = BITSWAP24(i, 23, 10, 9, 22, 19, 18, 20, 21, 17, 16, 15, 14, 13, 12, 11, 8, 7, 6, 5, 4, 3, 2, 1, 0);
+
+ dst[j] = src[i];
+ }
+
+ memcpy( src, dst, 0x800000 );
+
+ auto_free( machine, dst );
+}
+
+static void pgm_decode_kovlsqh2_samples( running_machine &machine )
+{
+ int i;
+ UINT8 *src = (UINT8 *)(machine.region("ics")->base() + 0x400000);
+
+ for (i = 0; i < 0x400000; i+=2) {
+ src[i + 0x000001] = src[i + 0x400001];
+ }
+
+ memcpy( src + 0x400000, src, 0x400000 );
+}
+
+static void pgm_decode_kovqhsgs_program( running_machine &machine )
+{
+ int i;
+ UINT16 *src = (UINT16 *)(machine.region("maincpu")->base() + 0x100000);
+ UINT16 *dst = auto_alloc_array(machine, UINT16, 0x400000);
+
+ for (i = 0; i < 0x400000 / 2; i++)
+ {
+ int j = BITSWAP24(i, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 6, 7, 5, 4, 3, 2, 1, 0);
+
+ dst[j] = BITSWAP16(src[i], 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 4, 5, 3, 2, 1, 0);
+ }
+
+ memcpy( src, dst, 0x400000 );
+
+ auto_free( machine, dst );
+}
+
+static void pgm_decode_kovqhsgs2_program( running_machine &machine )
+{
+ int i;
+ UINT16 *src = (UINT16 *)(machine.region("maincpu")->base() + 0x100000);
+ UINT16 *dst = auto_alloc_array(machine, UINT16, 0x400000);
+
+ for (i = 0; i < 0x400000 / 2; i++)
+ {
+ int j = BITSWAP24(i, 23, 22, 21, 20, 19, 16, 15, 14, 13, 12, 11, 10, 9, 8, 0, 1, 2, 3, 4, 5, 6, 18, 17, 7);
+
+ dst[j] = src[i];
+ }
+
+ memcpy( src, dst, 0x400000 );
+
+ auto_free( machine, dst );
+}
+
+
+DRIVER_INIT( kovlsqh2 )
+{
+ pgm_decode_kovqhsgs2_program(machine);
+ pgm_decode_kovlsqh2_tiles(machine);
+
+ pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x0000000);
+ pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x0800000);
+ pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x1000000);
+ pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x1800000);
+ pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x2000000);
+ pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x2800000);
+ pgm_decode_kovlsqh2_sprites(machine, machine.region("sprmask")->base() + 0x0000000);
+ pgm_decode_kovlsqh2_sprites(machine, machine.region("sprmask")->base() + 0x0800000);
+
+ pgm_decode_kovlsqh2_samples(machine);
+ pgm_basic_init(machine);
+ kovsh_latch_init(machine);
+ /* we only have a china internal ROM dumped for now.. allow region to be changed for debugging (to ensure all alt titles / regions can be seen) */
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x4f0008, 0x4f0009, FUNC(kovsh_fake_region_r));
+}
+
+DRIVER_INIT( kovqhsgs )
+{
+ pgm_decode_kovqhsgs_program(machine);
+ pgm_decode_kovlsqh2_tiles(machine);
+
+ pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x0000000);
+ pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x0800000);
+ pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x1000000);
+ pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x1800000);
+ pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x2000000);
+ pgm_decode_kovlsqh2_sprites(machine, machine.region("sprcol")->base() + 0x2800000);
+ pgm_decode_kovlsqh2_sprites(machine, machine.region("sprmask")->base() + 0x0000000);
+ pgm_decode_kovlsqh2_sprites(machine, machine.region("sprmask")->base() + 0x0800000);
+
+ pgm_decode_kovlsqh2_samples(machine);
+ pgm_basic_init(machine);
+ kovsh_latch_init(machine);
+ /* we only have a china internal ROM dumped for now.. allow region to be changed for debugging (to ensure all alt titles / regions can be seen) */
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x4f0008, 0x4f0009, FUNC(kovsh_fake_region_r));
+}
+
+/*
+ in Ketsui (ket) @ 000A719C (move.w)
+
+ if you change D0 to 0x12
+ the game will runs to "Asic27 Test" mode
+
+ bp A71A0,1,{d0=0x12;g}
+*/
+
+static READ16_HANDLER( ddp3_asic_r )
+{
+ pgm_kovarmsim_state *state = space->machine().driver_data<pgm_kovarmsim_state>();
+
+ if (offset == 0)
+ {
+ UINT16 d = state->m_valueresponse & 0xffff;
+ UINT16 realkey = state->m_valuekey >> 8;
+ realkey |= state->m_valuekey;
+ d ^= realkey;
+
+ return d;
+
+ }
+ else if (offset == 1)
+ {
+ UINT16 d = state->m_valueresponse >> 16;
+ UINT16 realkey = state->m_valuekey >> 8;
+ realkey |= state->m_valuekey;
+ d ^= realkey;
+ return d;
+
+ }
+ return 0xffff;
+}
+
+/* working */
+void command_handler_ddp3(pgm_kovarmsim_state *state, int pc)
+{
+ switch (state->m_ddp3lastcommand)
+ {
+ default:
+ printf("%06x command %02x | %04x\n", pc, state->m_ddp3lastcommand, state->m_value0);
+ state->m_valueresponse = 0x880000;
+ break;
+
+ case 0x40:
+ state->m_valueresponse = 0x880000;
+ state->m_ddp3slots[(state->m_value0>>10)&0x1F]=
+ (state->m_ddp3slots[(state->m_value0>>5)&0x1F]+
+ state->m_ddp3slots[(state->m_value0>>0)&0x1F])&0xffffff;
+ break;
+
+ case 0x67: // set high bits
+ // printf("%06x command %02x | %04x\n", cpu_get_pc(&space->device()), state->m_ddp3lastcommand, state->m_value0);
+ state->m_valueresponse = 0x880000;
+ state->m_ddp3internal_slot = (state->m_value0 & 0xff00)>>8;
+ state->m_ddp3slots[state->m_ddp3internal_slot] = (state->m_value0 & 0x00ff) << 16;
+ break;
+
+ case 0xe5: // set low bits for operation?
+ // printf("%06x command %02x | %04x\n", cpu_get_pc(&space->device()), state->m_ddp3lastcommand, state->m_value0);
+ state->m_valueresponse = 0x880000;
+ state->m_ddp3slots[state->m_ddp3internal_slot] |= (state->m_value0 & 0xffff);
+ break;
+
+
+ case 0x8e: // read back result of operations
+ // printf("%06x command %02x | %04x\n", cpu_get_pc(&space->device()), state->m_ddp3lastcommand, state->m_value0);
+ state->m_valueresponse = state->m_ddp3slots[state->m_value0&0xff];
+ break;
+
+
+ case 0x99: // reset?
+ state->m_valuekey = 0x100;
+ state->m_valueresponse = 0x00880000;
+ break;
+
+ }
+}
+
+/* preliminary */
+static INT32 puzzli_54_trigger = 0;
+void command_handler_puzzli2(pgm_kovarmsim_state *state, int pc)
+{
+ printf("%08x: %02x %04x\n",pc, state->m_ddp3lastcommand, state->m_value0);
+
+ switch (state->m_ddp3lastcommand)
+ {
+ case 0x13: // ASIC status?
+ state->m_valueresponse = 0x74<<16; // 2d or 74! (based on?)
+ break;
+
+ case 0x31:
+ {
+ // how is this selected? command 54?
+
+ // just a wild guess
+ if (puzzli_54_trigger) {
+ // pc == 1387de
+ state->m_valueresponse = 0x63<<16; // ?
+ } else {
+ // pc == 14cf58
+ state->m_valueresponse = 0xd2<<16;
+ }
+
+ puzzli_54_trigger = 0;
+ }
+ break;
+
+ case 0x38: // Reset
+ state->m_valueresponse = 0x78<<16;
+ state->m_valuekey = 0x100;
+ puzzli_54_trigger = 0;
+ break;
+
+ case 0x41: // ASIC status?
+ state->m_valueresponse = 0x74<<16;
+ break;
+
+ case 0x47: // ASIC status?
+ state->m_valueresponse = 0x74<<16;
+ break;
+
+ case 0x52: // ASIC status?
+ {
+ // how is this selected?
+
+ //if (state->m_value0 == 6) {
+ state->m_valueresponse = (0x74<<16)|1; // |1?
+ //} else {
+ // state->m_valueresponse = 0x74<<16;
+ //}
+ }
+ break;
+
+ case 0x54: // ??
+ puzzli_54_trigger = 1;
+ state->m_valueresponse = 0x36<<16;
+ break;
+
+ case 0x61: // ??
+ state->m_valueresponse = 0x36<<16;
+ break;
+
+ case 0x63: // used as a read address by the 68k code (related to previous uploaded values like cave?) should point at a table of ~0x80 in size? seems to use values as further pointers?
+ state->m_valueresponse = 0x00600000;
+ break;
+
+ case 0x67: // used as a read address by the 68k code (related to previous uploaded values like cave?) directly reads ~0xDBE from the address..
+ state->m_valueresponse = 0x00400000;
+ break;
+
+ default:
+ state->m_valueresponse = 0x74<<16;
+ break;
+ }
+}
+
+/* preliminary */
+void command_handler_py2k2(pgm_kovarmsim_state *state, int pc)
+{
+ switch (state->m_ddp3lastcommand)
+ {
+ default:
+ printf("%06x command %02x | %04x\n", pc, state->m_ddp3lastcommand, state->m_value0);
+ state->m_valueresponse = 0x880000;
+ break;
+
+ case 0xc0:
+ printf("%06x command %02x | %04x\n", pc, state->m_ddp3lastcommand, state->m_value0);
+ state->m_valueresponse = 0x880000;
+ break;
+
+ case 0x99: // reset?
+ state->m_valuekey = 0x100;
+ state->m_valueresponse = 0x00880000;
+ break;
+ }
+}
+
+/* preliminary */
+
+
+static const int pstar_ba[0x1E]={
+ 0x02,0x00,0x00,0x01,0x00,0x03,0x00,0x00, //0
+ 0x02,0x00,0x06,0x00,0x22,0x04,0x00,0x03, //8
+ 0x00,0x00,0x06,0x00,0x20,0x07,0x00,0x03, //10
+ 0x00,0x21,0x01,0x00,0x00,0x63
+};
+
+static const int pstar_b0[0x10]={
+ 0x09,0x0A,0x0B,0x00,0x01,0x02,0x03,0x04,
+ 0x05,0x06,0x07,0x08,0x00,0x00,0x00,0x00
+};
+
+static const int pstar_ae[0x10]={
+ 0x5D,0x86,0x8C ,0x8B,0xE0,0x8B,0x62,0xAF,
+ 0xB6,0xAF,0x10A,0xAF,0x00,0x00,0x00,0x00
+};
+
+static const int pstar_a0[0x10]={
+ 0x02,0x03,0x04,0x05,0x06,0x01,0x0A,0x0B,
+ 0x0C,0x0D,0x0E,0x09,0x00,0x00,0x00,0x00,
+};
+
+static const int pstar_9d[0x10]={
+ 0x05,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+static const int pstar_90[0x10]={
+ 0x0C,0x10,0x0E,0x0C,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
+static const int pstar_8c[0x23]={
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,
+ 0x01,0x01,0x01,0x01,0x02,0x02,0x02,0x02,
+ 0x02,0x02,0x03,0x03,0x03,0x04,0x04,0x04,
+ 0x03,0x03,0x03
+};
+
+static const int pstar_80[0x1a3]={
+ 0x03,0x03,0x04,0x04,0x04,0x04,0x05,0x05,
+ 0x05,0x05,0x06,0x06,0x03,0x03,0x04,0x04,
+ 0x05,0x05,0x05,0x05,0x06,0x06,0x07,0x07,
+ 0x03,0x03,0x04,0x04,0x05,0x05,0x05,0x05,
+ 0x06,0x06,0x07,0x07,0x06,0x06,0x06,0x06,
+ 0x06,0x06,0x06,0x07,0x07,0x07,0x07,0x07,
+ 0x06,0x06,0x06,0x06,0x06,0x06,0x07,0x07,
+ 0x07,0x07,0x08,0x08,0x05,0x05,0x05,0x05,
+ 0x05,0x05,0x05,0x06,0x06,0x06,0x07,0x07,
+ 0x06,0x06,0x06,0x07,0x07,0x07,0x08,0x08,
+ 0x09,0x09,0x09,0x09,0x07,0x07,0x07,0x07,
+ 0x07,0x08,0x08,0x08,0x08,0x09,0x09,0x09,
+ 0x06,0x06,0x07,0x07,0x07,0x08,0x08,0x08,
+ 0x08,0x08,0x09,0x09,0x05,0x05,0x06,0x06,
+ 0x06,0x07,0x07,0x08,0x08,0x08,0x08,0x09,
+ 0x07,0x07,0x07,0x07,0x07,0x08,0x08,0x08,
+ 0x08,0x09,0x09,0x09,0x06,0x06,0x07,0x03,
+ 0x07,0x06,0x07,0x07,0x08,0x07,0x05,0x04,
+ 0x03,0x03,0x04,0x04,0x05,0x05,0x06,0x06,
+ 0x06,0x06,0x06,0x06,0x03,0x04,0x04,0x04,
+ 0x04,0x05,0x05,0x06,0x06,0x06,0x06,0x07,
+ 0x04,0x04,0x05,0x05,0x06,0x06,0x06,0x06,
+ 0x06,0x07,0x07,0x08,0x05,0x05,0x06,0x07,
+ 0x07,0x08,0x08,0x08,0x08,0x08,0x08,0x08,
+ 0x05,0x05,0x05,0x07,0x07,0x07,0x07,0x07,
+ 0x07,0x08,0x08,0x08,0x08,0x08,0x09,0x09,
+ 0x09,0x09,0x03,0x04,0x04,0x05,0x05,0x05,
+ 0x06,0x06,0x07,0x07,0x07,0x07,0x08,0x08,
+ 0x08,0x09,0x09,0x09,0x03,0x04,0x05,0x05,
+ 0x04,0x03,0x04,0x04,0x04,0x05,0x05,0x04,
+ 0x03,0x03,0x03,0x03,0x03,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x04,0x04,0x04,0x04,0x04,
+ 0x04,0x04,0x04,0x04,0x04,0x03,0x03,0x03,
+ 0x03,0x03,0x03,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,
+ 0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00
+};
+
+void command_handler_pstars(pgm_kovarmsim_state *state, int pc)
+{
+ switch (state->m_ddp3lastcommand)
+ {
+ case 0x99:
+ state->m_valuekey = 0x100;
+ state->m_valueresponse = 0x880000;
+ break;
+
+ case 0xe0:
+ state->m_valueresponse = 0xa00000 + (state->m_value0 << 6);
+ break;
+
+ case 0xdc:
+ state->m_valueresponse = 0xa00800 + (state->m_value0 << 6);
+ break;
+
+ case 0xd0:
+ state->m_valueresponse = 0xa01000 + (state->m_value0 << 5);
+ break;
+
+ case 0xb1:
+ state->m_pstar_b1 = state->m_value0;
+ state->m_valueresponse = 0x890000;
+ break;
+
+ case 0xbf:
+ state->m_valueresponse = state->m_pstar_b1 * state->m_value0;
+ break;
+
+ case 0xc1: //TODO:TIMER 0,1,2,FIX TO 0 should be OK?
+ state->m_valueresponse = 0;
+ break;
+
+ case 0xce: //TODO:TIMER 0,1,2
+ state->m_pstar_ce = state->m_value0;
+ state->m_valueresponse=0x890000;
+ break;
+
+ case 0xcf: //TODO:TIMER 0,1,2
+ state->m_extra_ram[state->m_pstar_ce] = state->m_value0;
+ state->m_valueresponse = 0x890000;
+ break;
+
+ case 0xe7:
+ state->m_pstar_e7 = (state->m_value0 >> 12) & 0xf;
+ state->m_ddp3slots[state->m_pstar_e7] &= 0xffff;
+ state->m_ddp3slots[state->m_pstar_e7] |= (state->m_value0 & 0xff) << 16;
+ state->m_valueresponse = 0x890000;
+ break;
+
+ case 0xe5:
+ state->m_ddp3slots[state->m_pstar_e7] &= 0xff0000;
+ state->m_ddp3slots[state->m_pstar_e7] |= state->m_value0;
+ state->m_valueresponse = 0x890000;
+ break;
+
+ case 0xf8: //@73C
+ state->m_valueresponse = state->m_ddp3slots[state->m_value0 & 0xf] & 0xffffff;
+ break;
+
+ case 0xba:
+ state->m_valueresponse = pstar_ba[state->m_value0];
+ break;
+
+ case 0xb0:
+ state->m_valueresponse = pstar_b0[state->m_value0];
+ break;
+
+ case 0xae:
+ state->m_valueresponse = pstar_ae[state->m_value0];
+ break;
+
+ case 0xa0:
+ state->m_valueresponse = pstar_a0[state->m_value0];
+ break;
+
+ case 0x9d:
+ state->m_valueresponse = pstar_9d[state->m_value0];
+ break;
+
+ case 0x90:
+ state->m_valueresponse = pstar_90[state->m_value0];
+ break;
+
+ case 0x8c:
+ state->m_valueresponse = pstar_8c[state->m_value0];
+ break;
+
+ case 0x80:
+ state->m_valueresponse = pstar_80[state->m_value0];
+ break;
+
+ default:
+ state->m_valueresponse = 0x890000;
+ logerror("PSTARS PC(%06x) UNKNOWN %4X %4X\n", pc, state->m_value1, state->m_value0);
+ }
+}
+
+/* Old KOV and bootlegs sim ... really these should be read out... */
+
+static const UINT8 kov_BATABLE[0x40] = {
+ 0x00,0x29,0x2c,0x35,0x3a,0x41,0x4a,0x4e,0x57,0x5e,0x77,0x79,0x7a,0x7b,0x7c,0x7d,
+ 0x7e,0x7f,0x80,0x81,0x82,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x90,
+ 0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9e,0xa3,0xd4,0xa9,0xaf,0xb5,0xbb,0xc1
+};
+
+static const UINT8 kov_B0TABLE[16] = { 2, 0, 1, 4, 3 }; // Maps char portraits to tables
+
+static UINT32 kov_slots[16];
+static UINT16 kov_internal_slot;
+static UINT16 kov_c0_value;
+static UINT16 kov_cb_value;
+static UINT16 kov_fe_value;
+
+void command_handler_kov(pgm_kovarmsim_state *state, int pc)
+{
+ switch (state->m_ddp3lastcommand)
+ {
+ case 0x67: // unknown or status check?
+ case 0x8e:
+ case 0xa3:
+ case 0x33: // kovsgqyz (a3)
+ case 0x3a: // kovplus
+ case 0xc5: // kovplus
+ state->m_valueresponse = 0x880000;
+ break;
+
+ case 0x99: // Reset
+ state->m_valueresponse = 0x880000;
+ state->m_valuekey = 0x100;
+ break;
+
+ case 0x9d: // Sprite palette offset
+ state->m_valueresponse = 0xa00000 + ((state->m_value0 & 0x1f) * 0x40);
+ break;
+
+ case 0xb0: // Read from data table
+ state->m_valueresponse = kov_B0TABLE[state->m_value0 & 0x0f];
+ break;
+
+ case 0xb4: // Copy slot 'a' to slot 'b'
+ case 0xb7: // kovsgqyz (b4)
+ {
+ state->m_valueresponse = 0x880000;
+
+ if (state->m_value0 == 0x0102) state->m_value0 = 0x0100; // why?
+
+ kov_slots[(state->m_value0 >> 8) & 0x0f] = kov_slots[(state->m_value0 >> 0) & 0x0f];
+ }
+ break;
+
+ case 0xba: // Read from data table
+ state->m_valueresponse = kov_BATABLE[state->m_value0 & 0x3f];
+ break;
+
+ case 0xc0: // Text layer 'x' select
+ state->m_valueresponse = 0x880000;
+ kov_c0_value = state->m_value0;
+ break;
+
+ case 0xc3: // Text layer offset
+ state->m_valueresponse = 0x904000 + ((kov_c0_value + (state->m_value0 * 0x40)) * 4);
+ break;
+
+ case 0xcb: // Background layer 'x' select
+ state->m_valueresponse = 0x880000;
+ kov_cb_value = state->m_value0;
+ break;
+
+ case 0xcc: // Background layer offset
+ if (state->m_value0 & 0x400) state->m_value0 = -(0x400 - (state->m_value0 & 0x3ff));
+ state->m_valueresponse = 0x900000 + ((kov_cb_value + (state->m_value0 * 0x40)) * 4);
+ break;
+
+ case 0xd0: // Text palette offset
+ case 0xcd: // kovsgqyz (d0)
+ state->m_valueresponse = 0xa01000 + (state->m_value0 * 0x20);
+ break;
+
+ case 0xd6: // Copy slot to slot 0
+ state->m_valueresponse = 0x880000;
+ kov_slots[0] = kov_slots[state->m_value0 & 0x0f];
+ break;
+
+ case 0xdc: // Background palette offset
+ case 0x11: // kovsgqyz (dc)
+ state->m_valueresponse = 0xa00800 + (state->m_value0 * 0x40);
+ break;
+
+ case 0xe0: // Sprite palette offset
+ case 0x9e: // kovsgqyz (e0)
+ state->m_valueresponse = 0xa00000 + ((state->m_value0 & 0x1f) * 0x40);
+ break;
+
+ case 0xe5: // Write slot (low)
+ {
+ state->m_valueresponse = 0x880000;
+
+ INT32 sel = (kov_internal_slot >> 12) & 0x0f;
+ kov_slots[sel] = (kov_slots[sel] & 0x00ff0000) | ((state->m_value0 & 0xffff) << 0);
+ }
+ break;
+
+ case 0xe7: // Write slot (and slot select) (high)
+ {
+ state->m_valueresponse = 0x880000;
+ kov_internal_slot = state->m_value0;
+
+ INT32 sel = (kov_internal_slot >> 12) & 0x0f;
+ kov_slots[sel] = (kov_slots[sel] & 0x0000ffff) | ((state->m_value0 & 0x00ff) << 16);
+ }
+ break;
+
+ case 0xf0: // Some sort of status read?
+ state->m_valueresponse = 0x00c000;
+ break;
+
+ case 0xf8: // Read slot
+ case 0xab: // kovsgqyz (f8)
+ state->m_valueresponse = kov_slots[state->m_value0 & 0x0f] & 0x00ffffff;
+ break;
+
+ case 0xfc: // Adjust damage level to char experience level
+ state->m_valueresponse = (state->m_value0 * kov_fe_value) >> 6;
+ break;
+
+ case 0xfe: // Damage level adjust
+ state->m_valueresponse = 0x880000;
+ kov_fe_value = state->m_value0;
+ break;
+
+ default:
+ state->m_valueresponse = 0x880000;
+// bprintf (PRINT_NORMAL, _T("Unknown ASIC27 command: %2.2x data: %4.4x\n"), (data ^ state->m_valuekey) & 0xff, state->m_value0);
+ break;
+ }
+}
+
+
+/* Oriental Legend Super Plus ARM simulation */
+
+static const int oldsplus_80[0x5]={
+ 0xbb8,0x1770,0x2328,0x2ee0,0xf4240
+};
+
+static const int oldsplus_fc[0x20]={
+ 0x00,0x00,0x0a,0x3a,0x4e,0x2e,0x03,0x40,
+ 0x33,0x43,0x26,0x2c,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x44,0x4d,0xb,0x27,0x3d,0x0f,
+ 0x37,0x2b,0x02,0x2f,0x15,0x45,0x0e,0x30
+};
+
+static const int oldsplus_a0[0x20]={
+ 0x000,0x023,0x046,0x069,0x08c,0x0af,0x0d2,0x0f5,
+ 0x118,0x13b,0x15e,0x181,0x1a4,0x1c7,0x1ea,0x20d,
+ 0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,
+ 0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,0x20d,
+};
+
+static const int oldsplus_90[0x7]={
+ 0x50,0xa0,0xc8,0xf0,0x190,0x1f4,0x258
+};
+
+static const int oldsplus_5e[0x20]={
+ 0x04,0x04,0x04,0x04,0x04,0x03,0x03,0x03,
+ 0x02,0x02,0x02,0x01,0x01,0x01,0x01,0x01,
+ 0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
+
+static const int oldsplus_b0[0xe0]={
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,
+ 0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,
+ 0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,
+
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
+ 0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,
+ 0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,
+
+ 0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,
+ 0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,
+ 0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,
+ 0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,
+
+ 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
+ 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,
+
+ 0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,
+ 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,
+ 0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,
+ 0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f
+};
+
+static const int oldsplus_ae[0xe0]={
+ 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
+ 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
+ 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
+ 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
+
+ 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
+ 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
+ 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
+ 0x50,0x50,0x50,0x50,0x50,0x50,0x50,0x50,
+
+ 0x1E,0x1F,0x20,0x21,0x22,0x23,0x23,0x23,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
+
+ 0x1F,0x20,0x21,0x22,0x23,0x23,0x23,0x23,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
+
+ 0x20,0x21,0x22,0x23,0x23,0x23,0x23,0x23,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
+
+ 0x21,0x22,0x23,0x23,0x23,0x23,0x23,0x23,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
+
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23,
+ 0x23,0x23,0x23,0x23,0x23,0x23,0x23,0x23
+};
+
+static const int oldsplus_ba[0x4]={
+ 0x3138,0x2328,0x1C20,0x1518
+};
+
+static const int oldsplus_9d[0x111]={
+ 0x0000,0x0064,0x00c8,0x012c,0x0190,0x01f4,0x0258,0x02bc,
+ 0x02f8,0x0334,0x0370,0x03ac,0x03e8,0x0424,0x0460,0x049c,
+ 0x04d8,0x0514,0x0550,0x058c,0x05c8,0x0604,0x0640,0x06bc,
+ 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
+ 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x0000,
+ 0x0064,0x00c8,0x012c,0x0190,0x01f4,0x0258,0x02bc,0x0302,
+ 0x0348,0x038e,0x03d4,0x041a,0x0460,0x04a6,0x04ec,0x0532,
+ 0x0578,0x05be,0x0604,0x064a,0x0690,0x06d6,0x06bc,0x06bc,
+ 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
+ 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x0000,0x0064,
+ 0x00c8,0x012c,0x0190,0x01f4,0x0258,0x02bc,0x0316,0x0370,
+ 0x03ca,0x0424,0x047e,0x04d8,0x0532,0x058c,0x05e6,0x0640,
+ 0x069a,0x06f4,0x074e,0x07a8,0x0802,0x06bc,0x06bc,0x06bc,
+ 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
+ 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x0000,0x0064,0x00c8,
+ 0x012c,0x0190,0x01f4,0x0258,0x02bc,0x032a,0x0398,0x0406,
+ 0x0474,0x04e2,0x0550,0x05be,0x062c,0x069a,0x0708,0x0776,
+ 0x07e4,0x0852,0x08c0,0x092e,0x06bc,0x06bc,0x06bc,0x06bc,
+ 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
+ 0x06bc,0x06bc,0x06bc,0x06bc,0x0000,0x0064,0x00c8,0x012c,
+ 0x0190,0x01f4,0x0258,0x02bc,0x0348,0x03d4,0x0460,0x04ec,
+ 0x0578,0x0604,0x0690,0x071c,0x07a8,0x0834,0x08c0,0x094c,
+ 0x09d8,0x0a64,0x0af0,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
+ 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
+ 0x06bc,0x06bc,0x06bc,0x0000,0x0064,0x00c8,0x012c,0x0190,
+ 0x01f4,0x0258,0x02bc,0x0384,0x044c,0x0514,0x05dc,0x06a4,
+ 0x076c,0x0834,0x08fc,0x09c4,0x0a8c,0x0b54,0x0c1c,0x0ce4,
+ 0x0dac,0x0e74,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
+ 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
+ 0x06bc,0x06bc,0x0000,0x0064,0x00c8,0x012c,0x0190,0x01f4,
+ 0x0258,0x02bc,0x030c,0x035c,0x03ac,0x03fc,0x044c,0x049c,
+ 0x04ec,0x053c,0x058c,0x05dc,0x062c,0x067c,0x06cc,0x071c,
+ 0x076c,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
+ 0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,0x06bc,
+ 0x06bc
+};
+
+static const int oldsplus_8c[0x20]={
+ 0x0032,0x0032,0x0064,0x0096,0x0096,0x00fa,0x012c,0x015e,
+ 0x0032,0x0064,0x0096,0x00c8,0x00c8,0x012c,0x015e,0x0190,
+ 0x0064,0x0096,0x00c8,0x00fa,0x00fa,0x015e,0x0190,0x01c2,
+ 0x0096,0x00c8,0x00fa,0x012c,0x012c,0x0190,0x01c2,0x01f4
+};
+
+
+void command_handler_oldsplus(pgm_kovarmsim_state *state, int pc)
+{
+ switch (state->m_ddp3lastcommand)
+ {
+ case 0x88:
+ state->m_valuekey = 0x100;
+ state->m_valueresponse = 0x990000;
+ break;
+
+ case 0xd0:
+ state->m_valueresponse = 0xa01000 + (state->m_value0 << 5);
+ break;
+
+ case 0xc0:
+ state->m_valueresponse = 0xa00000 + (state->m_value0 << 6);
+ break;
+
+ case 0xc3:
+ state->m_valueresponse = 0xa00800 + (state->m_value0 << 6);
+ break;
+
+ case 0x36:
+ state->m_extra_ram[0x36] = state->m_value0;
+ state->m_valueresponse = 0x990000;
+ break;
+
+ case 0x33:
+ state->m_extra_ram[0x33] = state->m_value0;
+ state->m_valueresponse = 0x990000;
+ break;
+
+ case 0x35:
+ state->m_extra_ram[0x36] += state->m_value0;
+ state->m_valueresponse = 0x990000;
+ break;
+
+ case 0x37:
+ state->m_extra_ram[0x33] += state->m_value0;
+ state->m_valueresponse = 0x990000;
+ break;
+
+ case 0x34:
+ state->m_valueresponse = state->m_extra_ram[0x36];
+ break;
+
+ case 0x38:
+ state->m_valueresponse = state->m_extra_ram[0x33];
+ break;
+
+ case 0x80:
+ state->m_valueresponse = oldsplus_80[state->m_value0];
+ break;
+
+ case 0xe7:
+ state->m_extra_ram[0xe7] = state->m_value0;
+ state->m_valueresponse = 0x990000;
+ break;
+
+ case 0xe5:
+ switch (state->m_extra_ram[0xe7])
+ {
+ case 0xb000:
+ state->m_ddp3slots[0xb] = state->m_value0;
+ state->m_ddp3slots[0xc] = 0;
+ break;
+
+ case 0xc000:
+ state->m_ddp3slots[0xc] = state->m_value0;
+ break;
+
+ case 0xd000:
+ state->m_ddp3slots[0xd] = state->m_value0;
+ break;
+
+ case 0xf000:
+ state->m_ddp3slots[0xf] = state->m_value0;
+ break;
+ }
+ state->m_valueresponse = 0x990000;
+ break;
+
+ case 0xf8:
+ state->m_valueresponse = state->m_ddp3slots[state->m_value0];
+ break;
+
+ case 0xfc:
+ state->m_valueresponse = oldsplus_fc[state->m_value0];
+ break;
+
+ case 0xc5:
+ state->m_ddp3slots[0xd] --;
+ state->m_valueresponse = 0x990000;
+ break;
+
+ case 0xd6:
+ state->m_ddp3slots[0xb] ++;
+ state->m_valueresponse = 0x990000;
+ break;
+
+ case 0x3a:
+ state->m_ddp3slots[0xf] = 0;
+ state->m_valueresponse = 0x990000;
+ break;
+
+ case 0xf0:
+ state->m_extra_ram[0xf0] = state->m_value0;
+ state->m_valueresponse = 0x990000;
+ break;
+
+ case 0xed:
+ state->m_valueresponse = state->m_value0 << 0x6;
+ state->m_valueresponse += state->m_extra_ram[0xf0];
+ state->m_valueresponse = state->m_valueresponse << 0x2;
+ state->m_valueresponse += 0x900000;
+ break;
+
+ case 0xe0:
+ state->m_extra_ram[0xe0] = state->m_value0;
+ state->m_valueresponse = 0x990000;
+ break;
+
+ case 0xdc:
+ state->m_valueresponse = state->m_value0 << 0x6;
+ state->m_valueresponse += state->m_extra_ram[0xe0];
+ state->m_valueresponse = state->m_valueresponse << 0x2;
+ state->m_valueresponse += 0x904000;
+ break;
+
+ case 0xcb:
+ state->m_valueresponse = 0xc000;
+ break;
+
+ case 0xa0:
+ state->m_valueresponse = oldsplus_a0[state->m_value0];
+ break;
+
+ case 0xba:
+ state->m_valueresponse = oldsplus_ba[state->m_value0];
+ break;
+
+ case 0x5e:
+ state->m_valueresponse = oldsplus_5e[state->m_value0];
+ break;
+
+ case 0xb0:
+ state->m_valueresponse = oldsplus_b0[state->m_value0];
+ break;
+
+ case 0xae:
+ state->m_valueresponse = oldsplus_ae[state->m_value0];
+ break;
+
+ case 0x9d:
+ state->m_valueresponse = oldsplus_9d[state->m_value0];
+ break;
+
+ case 0x90:
+ state->m_valueresponse = oldsplus_90[state->m_value0];
+ break;
+
+ case 0x8c:
+ state->m_valueresponse = oldsplus_8c[state->m_value0];
+ break;
+
+ default:
+ state->m_valueresponse = 0x990000;
+ printf("%06X: oldsplus_UNKNOWN W CMD %X VAL %X\n", pc,state->m_value1,state->m_value0);
+ break;
+ }
+}
+
+static WRITE16_HANDLER( ddp3_asic_w )
+{
+ pgm_kovarmsim_state *state = space->machine().driver_data<pgm_kovarmsim_state>();
+ int pc = cpu_get_pc(&space->device());
+
+ if (offset == 0)
+ {
+ state->m_value0 = data;
+ return;
+ }
+ else if (offset == 1)
+ {
+ UINT16 realkey;
+ if ((data >> 8) == 0xff)
+ state->m_valuekey = 0xff00;
+ realkey = state->m_valuekey >> 8;
+ realkey |= state->m_valuekey;
+ {
+ state->m_valuekey += 0x0100;
+ state->m_valuekey &= 0xff00;
+ if (state->m_valuekey == 0xff00)
+ state->m_valuekey = 0x0100;
+ }
+ data ^= realkey;
+ state->m_value1 = data;
+ state->m_value0 ^= realkey;
+
+ state->m_ddp3lastcommand = state->m_value1 & 0xff;
+
+ state->arm_sim_handler(state, pc);
+ }
+ else if (offset==2)
+ {
+
+ }
+}
+
+
+static READ16_HANDLER( sango_protram_r )
+{
+ // at offset == 4 is region (supplied by device)
+ // 0 = china
+ // 1 = taiwan
+ // 2 = japan
+ // 3 = korea
+ // 4 = hong kong
+ // 5 = world
+
+ if (offset == 4)
+ return input_port_read(space->machine(), "Region");
+
+ // otherwise it doesn't seem to use the ram for anything important, we return 0 to avoid test mode corruption
+ // kovplus reads from offset 000e a lot ... why?
+#ifdef MAME_DEBUG
+ popmessage ("protection ram r %04x",offset);
+#endif
+ return 0x0000;
+}
+
+static READ16_HANDLER( pstars_protram_r )
+{
+ pgm_kovarmsim_state *state = space->machine().driver_data<pgm_kovarmsim_state>();
+
+ if (offset == 4) //region
+ return input_port_read(space->machine(), "Region");
+ else if (offset >= 0x10) //timer
+ {
+ logerror("PSTARS ACCESS COUNTER %6X\n", state->m_extra_ram[offset - 0x10]);
+ return state->m_extra_ram[offset - 0x10]--;
+ }
+ return 0x0000;
+}
+
+
+static READ16_HANDLER( puzzli2_protram_r )
+{
+ if (offset == 4)
+ return input_port_read(space->machine(), "Region");
+
+ printf("%06x puzzli2_protram_r %02x\n", cpu_get_pc(&space->device()), offset);
+
+ return 0x0000;
+}
+
+static READ16_HANDLER( oldsplus_protram_r )
+{
+ if (offset == 4)
+ return input_port_read(space->machine(), "Region");
+
+ return 0x0000;
+}
+
+DRIVER_INIT( ddp3 )
+{
+ pgm_kovarmsim_state *state = machine.driver_data<pgm_kovarmsim_state>();
+ pgm_basic_init(machine, false);
+ pgm_py2k2_decrypt(machine); // yes, it's the same as photo y2k2
+ state->arm_sim_handler = command_handler_ddp3;
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x500000, 0x500005, FUNC(ddp3_asic_r), FUNC(ddp3_asic_w));
+}
+
+DRIVER_INIT( ket )
+{
+ pgm_kovarmsim_state *state = machine.driver_data<pgm_kovarmsim_state>();
+ pgm_basic_init(machine, false);
+ pgm_ket_decrypt(machine);
+ state->arm_sim_handler = command_handler_ddp3;
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x400000, 0x400005, FUNC(ddp3_asic_r), FUNC(ddp3_asic_w));
+}
+
+DRIVER_INIT( espgal )
+{
+ pgm_basic_init(machine, false);
+ pgm_espgal_decrypt(machine);
+ pgm_kovarmsim_state *state = machine.driver_data<pgm_kovarmsim_state>();
+ state->arm_sim_handler = command_handler_ddp3;
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x400000, 0x400005, FUNC(ddp3_asic_r), FUNC(ddp3_asic_w));
+}
+
+DRIVER_INIT( puzzli2 )
+{
+ pgm_kovarmsim_state *state = machine.driver_data<pgm_kovarmsim_state>();
+ pgm_basic_init(machine);
+ pgm_puzzli2_decrypt(machine);
+ state->arm_sim_handler = command_handler_puzzli2;
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x500000, 0x500005, FUNC(ddp3_asic_r), FUNC(ddp3_asic_w));
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x4f0000, 0x4f003f, FUNC(puzzli2_protram_r));
+ state->m_irq4_disabled = 1; // // doesn't like this irq??
+}
+
+DRIVER_INIT( py2k2 )
+{
+ pgm_kovarmsim_state *state = machine.driver_data<pgm_kovarmsim_state>();
+ pgm_basic_init(machine);
+ pgm_py2k2_decrypt(machine);
+ state->arm_sim_handler = command_handler_py2k2;
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x500000, 0x500005, FUNC(ddp3_asic_r), FUNC(ddp3_asic_w));
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x4f0000, 0x4f003f, FUNC(puzzli2_protram_r));
+}
+
+DRIVER_INIT( pstar )
+{
+ pgm_kovarmsim_state *state = machine.driver_data<pgm_kovarmsim_state>();
+
+ pgm_basic_init(machine);
+ pgm_pstar_decrypt(machine);
+ kovsh_latch_init(machine);
+
+ state->m_pstar_e7 = 0;
+ state->m_pstar_b1 = 0;
+ state->m_pstar_ce = 0;
+ state->m_extra_ram[0] = 0;
+ state->m_extra_ram[1] = 0;
+ state->m_extra_ram[2] = 0;
+ memset(state->m_ddp3slots, 0, 16);
+
+ state->arm_sim_handler = command_handler_pstars;
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x500000, 0x500005, FUNC(ddp3_asic_r), FUNC(ddp3_asic_w));
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x4f0000, 0x4f003f, FUNC(pstars_protram_r));
+
+ state->save_item(NAME(state->m_pstar_e7));
+ state->save_item(NAME(state->m_pstar_b1));
+ state->save_item(NAME(state->m_pstar_ce));
+ state->save_item(NAME(state->m_extra_ram));
+}
+
+DRIVER_INIT( kov )
+{
+ pgm_kovarmsim_state *state = machine.driver_data<pgm_kovarmsim_state>();
+ pgm_basic_init(machine);
+ pgm_kov_decrypt(machine);
+ kovsh_latch_init(machine);
+ kov_internal_slot = 0;
+ kov_c0_value = 0;
+ kov_cb_value = 0;
+ kov_fe_value = 0;
+ state->arm_sim_handler = command_handler_kov;
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x500000, 0x500005, FUNC(ddp3_asic_r), FUNC(ddp3_asic_w));
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x4f0000, 0x4f003f, FUNC(sango_protram_r));
+}
+
+DRIVER_INIT( kovboot )
+{
+ pgm_kovarmsim_state *state = machine.driver_data<pgm_kovarmsim_state>();
+ pgm_basic_init(machine);
+// pgm_kov_decrypt(machine);
+ kovsh_latch_init(machine);
+ kov_internal_slot = 0;
+ kov_c0_value = 0;
+ kov_cb_value = 0;
+ kov_fe_value = 0;
+ state->arm_sim_handler = command_handler_kov;
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x500000, 0x500005, FUNC(ddp3_asic_r), FUNC(ddp3_asic_w));
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x4f0000, 0x4f003f, FUNC(sango_protram_r));
+
+}
+
+DRIVER_INIT( oldsplus )
+{
+ pgm_kovarmsim_state *state = machine.driver_data<pgm_kovarmsim_state>();
+ pgm_basic_init(machine);
+ pgm_oldsplus_decrypt(machine);
+ kovsh_latch_init(machine);
+ memset(state->m_extra_ram, 0, 0x100);
+ memset(state->m_ddp3slots, 0, 0x100);
+ state->arm_sim_handler = command_handler_oldsplus;
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_readwrite_handler(0x500000, 0x500005, FUNC(ddp3_asic_r), FUNC(ddp3_asic_w));
+ machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0x4f0000, 0x4f003f, FUNC(oldsplus_protram_r));
+ state_save_register_global_array(machine, state->m_extra_ram);
+ state_save_register_global_array(machine, state->m_ddp3slots);
+}
+
+INPUT_PORTS_START( photoy2k )
+ PORT_INCLUDE ( pgm )
+
+ PORT_START("RegionHack") /* Region - supplied by protection device */
+ PORT_CONFNAME( 0x00ff, 0x00ff, DEF_STR( Region ) )
+ PORT_CONFSETTING( 0x0000, DEF_STR( Taiwan ) )
+ PORT_CONFSETTING( 0x0001, DEF_STR( China ) )
+ PORT_CONFSETTING( 0x0002, "Japan (Alta license)" )
+ PORT_CONFSETTING( 0x0003, DEF_STR( World ) )
+ PORT_CONFSETTING( 0x0004, DEF_STR( Korea ) )
+ PORT_CONFSETTING( 0x0005, DEF_STR( Hong_Kong ) )
+ PORT_CONFSETTING( 0x00ff, "Untouched" ) // don't hack the region
+INPUT_PORTS_END
+
+
+
+INPUT_PORTS_START( kovsh )
+ PORT_INCLUDE ( pgm )
+
+ PORT_START("RegionHack") /* Region - 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 (Alta 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( sango )
+ 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
+
+INPUT_PORTS_START( sango_ch )
+ PORT_INCLUDE ( pgm )
+
+ PORT_MODIFY("Region") /* Region - supplied by protection device */
+ PORT_CONFNAME( 0x000f, 0x0000, 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
+
+
+INPUT_PORTS_START( oldsplus )
+ PORT_INCLUDE ( pgm )
+
+ PORT_MODIFY("Region") /* Region - supplied by protection device */
+ PORT_CONFNAME( 0x000f, 0x0001, DEF_STR( Region ) )
+ PORT_CONFSETTING( 0x0001, DEF_STR( China ) )
+ 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( Taiwan ) )
+INPUT_PORTS_END
+
+INPUT_PORTS_START( pstar )
+ 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
+
+INPUT_PORTS_START( py2k2 )
+ PORT_INCLUDE ( pgm )
+
+ PORT_MODIFY("Region") /* Region - supplied by protection device */
+ PORT_CONFNAME( 0x000f, 0x0003, DEF_STR( Region ) )
+ PORT_CONFSETTING( 0x0000, DEF_STR( Taiwan ) )
+ PORT_CONFSETTING( 0x0001, DEF_STR( China ) )
+ PORT_CONFSETTING( 0x0002, "Japan (Alta license)" )
+ PORT_CONFSETTING( 0x0003, DEF_STR( World ) )
+ PORT_CONFSETTING( 0x0004, DEF_STR( Korea ) )
+ PORT_CONFSETTING( 0x0005, DEF_STR( Hong_Kong ) )
+ PORT_CONFSETTING( 0x0006, "Singapore, Malaysia" )
+INPUT_PORTS_END
+
+
+INPUT_PORTS_START( puzzli2 )
+ PORT_INCLUDE ( pgm )
+
+ PORT_MODIFY("Region") /* Region - supplied by protection device */
+ PORT_CONFNAME( 0x000f, 0x0005, DEF_STR( Region ) )
+ PORT_CONFSETTING( 0x0000, DEF_STR( Taiwan ) )
+ PORT_CONFSETTING( 0x0001, DEF_STR( China ) )
+ 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 \ No newline at end of file
diff --git a/src/mame/machine/pgmprot2.c b/src/mame/machine/pgmprot2.c
new file mode 100644
index 00000000000..429acbdbbef
--- /dev/null
+++ b/src/mame/machine/pgmprot2.c
@@ -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
diff --git a/src/mame/machine/pgmprot3.c b/src/mame/machine/pgmprot3.c
new file mode 100644
index 00000000000..f763e068f50
--- /dev/null
+++ b/src/mame/machine/pgmprot3.c
@@ -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);
+}
diff --git a/src/mame/machine/pgmprot4.c b/src/mame/machine/pgmprot4.c
new file mode 100644
index 00000000000..57f2f252101
--- /dev/null
+++ b/src/mame/machine/pgmprot4.c
@@ -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
diff --git a/src/mame/machine/pgmprot5.c b/src/mame/machine/pgmprot5.c
new file mode 100644
index 00000000000..488c4bb4858
--- /dev/null
+++ b/src/mame/machine/pgmprot5.c
@@ -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;
+}
+
diff --git a/src/mame/machine/pgmprot6.c b/src/mame/machine/pgmprot6.c
new file mode 100644
index 00000000000..53fffdf01ea
--- /dev/null
+++ b/src/mame/machine/pgmprot6.c
@@ -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
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index 07eabc1e8e9..7895ef241b7 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -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
diff --git a/src/mame/mame.mak b/src/mame/mame.mak
index 9276f47a868..ff1565b132f 100644
--- a/src/mame/mame.mak
+++ b/src/mame/mame.mak
@@ -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 \