Dragon World 2 : protection patch [iq_132]

This commit is contained in:
Robbbert 2013-01-09 13:13:39 +00:00
parent ab8d91b336
commit 63bd8690b4
3 changed files with 178 additions and 121 deletions

View file

@ -193,7 +193,6 @@ Notes:
READ16_MEMBER(pgm_state::pgm_videoram_r)
{
if (offset < 0x4000 / 2)
return m_bg_videoram[offset&0x7ff];
else if (offset < 0x7000 / 2)
@ -202,10 +201,8 @@ READ16_MEMBER(pgm_state::pgm_videoram_r)
return m_videoram[offset];
}
WRITE16_MEMBER(pgm_state::pgm_videoram_w)
{
if (offset < 0x4000 / 2)
pgm_bg_videoram_w(space, offset&0x7ff, data, mem_mask);
else if (offset < 0x7000 / 2)
@ -214,6 +211,14 @@ WRITE16_MEMBER(pgm_state::pgm_videoram_w)
COMBINE_DATA(&m_videoram[offset]);
}
WRITE16_MEMBER(pgm_state::pgm_coin_counter_w)
{
coin_counter_w(machine(), 0, data & 0x0001);
coin_counter_w(machine(), 1, data & 0x0002);
coin_counter_w(machine(), 2, data & 0x0004);
coin_counter_w(machine(), 3, data & 0x0008);
}
READ16_MEMBER(pgm_state::z80_ram_r)
{
return (m_z80_mainram[offset * 2] << 8) | m_z80_mainram[offset * 2 + 1];
@ -235,7 +240,6 @@ WRITE16_MEMBER(pgm_state::z80_ram_w)
WRITE16_MEMBER(pgm_state::z80_reset_w)
{
if (PGMLOGERROR)
logerror("Z80: reset %04x @ %04x (%06x)\n", data, mem_mask, space.device().safe_pc());
@ -244,18 +248,11 @@ WRITE16_MEMBER(pgm_state::z80_reset_w)
m_ics->reset();
m_soundcpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
m_soundcpu->set_input_line(INPUT_LINE_RESET, PULSE_LINE);
if(0)
{
FILE *out;
out = fopen("z80ram.bin", "wb");
fwrite(m_z80_mainram, 1, 65536, out);
fclose(out);
}
}
else
{
/* this might not be 100% correct, but several of the games (ddp2, puzzli2 etc. expect the z80 to be turned
off during data uploads, they write here before the upload */
off during data uploads, they write here before the upload */
m_soundcpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
}
}
@ -268,7 +265,6 @@ WRITE16_MEMBER(pgm_state::z80_ctrl_w)
WRITE16_MEMBER(pgm_state::m68k_l1_w)
{
if(ACCESSING_BITS_0_7)
{
if (PGMLOGERROR)
@ -333,7 +329,7 @@ ADDRESS_MAP_START( pgm_base_mem, AS_PROGRAM, 16, pgm_state )
AM_RANGE(0xc08000, 0xc08001) AM_READ_PORT("P1P2")
AM_RANGE(0xc08002, 0xc08003) AM_READ_PORT("P3P4")
AM_RANGE(0xc08004, 0xc08005) AM_READ_PORT("Service")
AM_RANGE(0xc08006, 0xc08007) AM_READ_PORT("DSW")
AM_RANGE(0xc08006, 0xc08007) AM_READ_PORT("DSW") AM_WRITE(pgm_coin_counter_w)
AM_RANGE(0xc10000, 0xc1ffff) AM_READWRITE(z80_ram_r, z80_ram_w) /* Z80 Program */
ADDRESS_MAP_END
@ -349,8 +345,6 @@ ADDRESS_MAP_START( pgm_basic_mem, AS_PROGRAM, 16, pgm_state )
ADDRESS_MAP_END
/*** Input Ports *************************************************************/
/* enough for 4 players, the basic dips mapped are listed in the test mode */
@ -397,10 +391,10 @@ INPUT_PORTS_START( pgm )
PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_COIN2 )
PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_COIN3 )
PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_COIN4 )
// PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON5 ) // test 1p+2p
// PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_BUTTON5 ) // test 1p+2p
PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_UNKNOWN ) // what should i use?
PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_SERVICE1 ) // service 1p+2p
// PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON6 ) // test 3p+4p
// PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_BUTTON6 ) // test 3p+4p
PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_UNKNOWN ) // what should i use?
PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_SERVICE2 ) // service 3p+4p
PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1)
@ -441,10 +435,6 @@ INPUT_PORTS_START( pgm )
INPUT_PORTS_END
/*** GFX Decodes *************************************************************/
/* we can't decode the sprite data like this because it isn't tile based. the
@ -501,8 +491,7 @@ TIMER_DEVICE_CALLBACK_MEMBER(pgm_state::pgm_interrupt)
MACHINE_START_MEMBER(pgm_state,pgm)
{
// machine().base_datetime(m_systime);
// machine().base_datetime(m_systime);
m_maincpu = machine().device<cpu_device>("maincpu");
m_soundcpu = machine().device<cpu_device>("soundcpu");
@ -514,7 +503,6 @@ MACHINE_RESET_MEMBER(pgm_state,pgm)
machine().device("soundcpu")->execute().set_input_line(INPUT_LINE_HALT, ASSERT_LINE);
}
MACHINE_CONFIG_FRAGMENT( pgmbase )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", M68000, 20000000) /* 20 mhz! verified on real board */
@ -548,7 +536,7 @@ MACHINE_CONFIG_FRAGMENT( pgmbase )
/*sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_ICS2115_ADD("ics", 0, pgm_sound_irq)
MCFG_ICS2115_ADD("ics", 0, pgm_sound_irq)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 5.0)
MACHINE_CONFIG_END
@ -557,15 +545,6 @@ MACHINE_CONFIG_START( pgm, pgm_state )
MACHINE_CONFIG_END
/*** Rom Loading *************************************************************/
/* take note of "gfx2" needed for expanding the 32x32x5bpp data and
@ -980,7 +959,6 @@ ROM_START( drgw2j )
ROM_END
/*
Dragon World 3 (KOREA 106 Ver.)
@ -1149,8 +1127,6 @@ ROM_START( dwex )
ROM_END
ROM_START( kov )
ROM_REGION( 0x600000, "maincpu", 0 ) /* 68000 Code */
PGM_68K_BIOS
@ -1357,7 +1333,6 @@ ROM_START( kovplusa )
ROM_LOAD( "m0600.rom", 0x400000, 0x400000, CRC(3ada4fd6) SHA1(4c87adb25d31cbd41f04fbffe31f7bc37173da76) )
ROM_END
ROM_START( kovsgqyz )
ROM_REGION( 0x600000, "maincpu", 0 ) /* 68000 Code */
PGM_68K_BIOS
@ -1440,8 +1415,6 @@ ROM_START( kovsgqyzb )
ROM_END
ROM_START( kovsh )
ROM_REGION( 0x600000, "maincpu", 0 ) /* 68000 Code */
PGM_68K_BIOS
@ -1592,7 +1565,6 @@ ROM_START( kovqhsgs )
ROM_END
/*
p0701_v105.u2
@ -1726,8 +1698,6 @@ ROM_START( photoy2k102 )
ROM_END
/*
Photo Y2K2 IGS PGM cart
@ -1775,8 +1745,6 @@ ROM_START( py2k2 )
ROM_END
ROM_START( pgm3in1 )
ROM_REGION( 0x600000, "maincpu", 0 ) /* 68000 Code */
PGM_68K_BIOS
@ -2615,8 +2583,6 @@ ROM_START( dw2001 )
ROM_END
ROM_START( dwpc )
ROM_REGION( 0x600000, "maincpu", 0 ) /* 68000 Code */
PGM_68K_BIOS
@ -2722,7 +2688,6 @@ ROM_START( puzzli2 )
ROM_END
ROM_START( puzzli2s )
ROM_REGION( 0x600000, "maincpu", 0 ) /* 68000 Code */
PGM_68K_BIOS
@ -2748,7 +2713,6 @@ ROM_START( puzzli2s )
ROM_END
/*
Martial Masters
@ -3460,7 +3424,6 @@ ROM_START( happy6 )
ROM_END
/* all known revisions of ketsui have roms marked v100, even when the actual game revision is upgraded */
ROM_START( ket )
@ -3679,11 +3642,6 @@ ROM_START( ddpdojblk )
ROM_END
/*** Init Stuff **************************************************************/
/* This function expands the 32x32 5-bit data into a format which is easier to
@ -3758,10 +3716,6 @@ static void expand_colourdata( running_machine &machine )
}
}
void pgm_basic_init( running_machine &machine, bool set_bank)
{
pgm_state *state = machine.driver_data<pgm_state>();
@ -3783,12 +3737,6 @@ DRIVER_INIT_MEMBER(pgm_state,pgm)
}
/*** GAME ********************************************************************/
GAME( 1997, pgm, 0, pgm, pgm, pgm_state, pgm, ROT0, "IGS", "PGM (Polygame Master) System BIOS", GAME_IS_BIOS_ROOT )
@ -3805,9 +3753,9 @@ GAME( 1997, orlegendca, orlegend, pgm_asic3, orlegend, pgm_asic3_state, o
GAME( 1997, orlegend111c, orlegend, pgm_asic3, orlegend, pgm_asic3_state, orlegend, ROT0, "IGS", "Oriental Legend / Xi You Shi E Zhuan (ver. 111, Chinese Board)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // V0001 no date! - runs as HongKong, China, China
GAME( 1997, orlegend105k, orlegend, pgm_asic3, orld105k, pgm_asic3_state, orlegend, ROT0, "IGS", "Oriental Legend / Xi You Shi E Zhuan (ver. 105, Korean Board)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // V0000 no date! - runs as Korea
GAME( 1997, drgw2, pgm, pgm, pgm, pgm_state, drgw2, ROT0, "IGS", "Dragon World II (ver. 110X, Export)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) // This set still has protection issues!
GAME( 1997, dw2v100x, drgw2, pgm, pgm, pgm_state, dw2v100x, ROT0, "IGS", "Dragon World II (ver. 100X, Export)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) // This set still has protection issues!
GAME( 1997, drgw2j, drgw2, pgm, pgm, pgm_state, drgw2j, ROT0, "IGS", "Chuugokuryuu II (ver. 100J, Japan)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE ) // This set still has protection issues!
GAME( 1997, drgw2, pgm, pgm, pgm, pgm_state, drgw2, ROT0, "IGS", "Dragon World II (ver. 110X, Export)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE )
GAME( 1997, dw2v100x, drgw2, pgm, pgm, pgm_state, dw2v100x, ROT0, "IGS", "Dragon World II (ver. 100X, Export)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE )
GAME( 1997, drgw2j, drgw2, pgm, pgm, pgm_state, drgw2j, ROT0, "IGS", "Chuugokuryuu II (ver. 100J, Japan)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE )
GAME( 1997, drgw2c, drgw2, pgm, pgm, pgm_state, drgw2c, ROT0, "IGS", "Zhong Guo Long II (ver. 100C, China)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE )
// region provided by internal ARM rom
@ -3851,16 +3799,12 @@ GAME( 2001, dw2001, pgm, pgm_arm_type2, dw2001, pgm_arm_type2_st
// japan region only?
GAME( 2001, dwpc, pgm, pgm_arm_type2, dw2001, pgm_arm_type2_state, dwpc, ROT0, "IGS", "Dragon World Pretty Chance (V101, Japan)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // 09/26/01 10:23:26
// 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, pgm_arm_type3, pgm, pgm_arm_type3_state, 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, pgm_arm_type3, pgm, pgm_arm_type3_state, 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, pgm_arm_type3, pgm, pgm_arm_type3_state, dmnfrnt, ROT0, "IGS", "Demon Front (68k label V107KR, ROM M107KR 11/03/03) (ARM label V106KR, 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?)
/* these don't use an External ARM rom, and don't have any weak internal functions which would allow the internal ROM to be read out */
GAME( 2002, ddpdoj, 0, pgm_arm_type1_cave, pgm, pgm_arm_type1_state, ddp3, ROT270, "Cave", "DoDonPachi Dai-Ou-Jou V101 (2002.04.05.Master Ver)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE ) // is there a v101 without the . after 05?
@ -3876,8 +3820,6 @@ GAME( 2002, ketb, ket, pgm_arm_type1_cave, pgm, pgm_arm_type1_s
GAME( 2003, espgal, 0, pgm_arm_type1_cave, pgm, pgm_arm_type1_state, espgal, ROT270, "Cave", "Espgaluda (2003/10/15 Master Ver)", GAME_IMPERFECT_SOUND | GAME_SUPPORTS_SAVE )
/* -----------------------------------------------------------------------------------------------------------------------
Partially Working, playable, but some imperfections
-----------------------------------------------------------------------------------------------------------------------*/
@ -3903,8 +3845,6 @@ GAME( 1999, kovsgqyza, kovplus, pgm_arm_type1_sim, sango_ch, pgm_arm_ty
GAME( 1999, kovsgqyzb, kovplus, pgm_arm_type1_sim, sango_ch, pgm_arm_type1_state, kovboot, ROT0, "bootleg", "Knights of Valour: SanGuo QunYingZhuan / Sangoku Senki: SanGuo QunYingZhuan (bootleg, set 3)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_SUPPORTS_SAVE ) /* need internal rom of IGS027A */
/* -----------------------------------------------------------------------------------------------------------------------
NOT Working (mostly due to needing internal protection roms dumped)
-----------------------------------------------------------------------------------------------------------------------*/
@ -3926,16 +3866,13 @@ GAME( 1999, puzzli2, pgm, pgm_arm_type1_sim, puzzli2, pgm_arm_type1_
GAME( 2001, puzzli2s, puzzli2, pgm_arm_type1_sim, puzzli2, pgm_arm_type1_state, puzzli2, ROT0, "IGS", "Puzzli 2 Super (ver. 200)", GAME_IMPERFECT_SOUND | GAME_UNEMULATED_PROTECTION | GAME_NOT_WORKING | GAME_SUPPORTS_SAVE )
/* Games below this point are known to have an 'execute only' internal ROM area covering an area at the start of the internal ROM. This can't be read when running code from either internal or external ROM space. */
// 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, pgm_arm_type3, pgm, pgm_arm_type3_state, 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, pgm_arm_type3, pgm, pgm_arm_type3_state, 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, pgm_arm_type3, pgm, pgm_arm_type3_state, 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
// simulation doesn't seem 100%
GAME( 2004, oldsplus, pgm, pgm_arm_type1_sim, oldsplus, pgm_arm_type1_state, 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 */
@ -3958,6 +3895,3 @@ GAME( 2004, happy6, pgm, pgm_arm_type3, pgm, pgm_arm_type3_state
GAME( 2005, svg, pgm, pgm_arm_type3, pgm, pgm_arm_type3_state, 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, pgm_arm_type3, pgm, pgm_arm_type3_state, 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

View file

@ -66,6 +66,7 @@ public:
DECLARE_READ16_MEMBER(pgm_videoram_r);
DECLARE_WRITE16_MEMBER(pgm_videoram_w);
DECLARE_WRITE16_MEMBER(pgm_coin_counter_w);
DECLARE_READ16_MEMBER(z80_ram_r);
DECLARE_WRITE16_MEMBER(z80_ram_w);
DECLARE_WRITE16_MEMBER(z80_reset_w);

View file

@ -13,60 +13,167 @@
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
To do:
How is the additional xor data is calculated?
Should the "hold" value be reset if the power is turned off? How?
Patches are actually overlays or just hacks?
***********************************************************************/
#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
static int protection_address;
static UINT16 dw2_asic_reg[2];
static UINT8 dw2_asic_z;
static UINT8 dw2_asic_y;
static UINT16 dw2_asic_hold;
READ16_HANDLER( dw2_d80000_r )
{
// addr&=0xff;
// if(dw2reg<0x20) //NOT SURE!!
// pgm_state *state = space.machine().driver_data<pgm_state>();
UINT16 ret;
/* UINT16 test;
switch (dw2_asic_reg[0])
{
//The value at 0x80EECE is computed in the routine at 0x107c18
pgm_state *state = space.machine().driver_data<pgm_state>();
UINT16 d = state->m_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;
case 0x05: // Read to $80eec0
case 0x13: // Read to $80eeb8
case 0x1f: // Read to $80eeb8
case 0x40: // Read to $80eeb8, increase counters
case 0xf4: // Read to $80eeb8
case 0xf6: // Read to $80eeb8
case 0xf8: // Read to $80eeb8
break;
default:
logerror("%06x: warning, reading with igs003_reg = %02x\n", space.device().safe_pc(), dw2_asic_reg[0]);
}
test = BITSWAP16(state->m_mainram[protection_address], 14,11,8,6,4,3,1,0, 5,2,9,7,10,13,12,15) & 0xff; // original hack
*/
// This bitswap seems to also be common to a few IGS protection devices (igs011.c, Oriental Legend)
ret = BITSWAP16(dw2_asic_hold, 14,11,8,6,4,3,1,0, 5,2,9,7,10,13,12,15) & 0xff;
/*
if ((ret != test) || (dw2_asic_hold != state->m_mainram[protection_address])) {
logerror ("Protection calculation error: SIMRET: %2.2x, HACKRET: %2.2x, SIMHOLD: %4.4x, REALHOLD: %4.4x\n", ret, test, dw2_asic_hold, state->m_mainram[protection_address]);
}
*/
return ret;
}
WRITE16_HANDLER( dw2_d80000_w )
{
pgm_state *state = space.machine().driver_data<pgm_state>();
COMBINE_DATA(&dw2_asic_reg[offset]);
if (offset == 0)
return;
switch (dw2_asic_reg[0])
{
case 0x08:
// This reg doesn't seem to be used for anything useful but is
// initialized. Ok to use as reset??
// The last "hold" value used is stored in NVRAM. Otherwise we either
// need to set the "hold" value as non-volatile or wipe NVRAM.
dw2_asic_hold = state->m_mainram[protection_address]; // hack
break;
case 0x09: // Used only on init...
case 0x0a:
case 0x0b:
case 0x0c:
break;
case 0x15: // ????
case 0x17:
break;
case 0x20:
case 0x21:
case 0x22:
case 0x23:
case 0x24:
case 0x25:
case 0x26:
case 0x27:
{
// computed ~$107000
UINT16 old;
dw2_asic_y = dw2_asic_reg[0] & 0x07;
dw2_asic_z = data;
// drgw2c = $80eecc, drgw2/dw2v100x = $80cb7c, drgw2j = $8091ca
old = dw2_asic_hold;
// drgw2c = $80eece, drgw2/dw2v100x = $80cb7e, drgw2j = $8091cc
// roation, fixed xor, and z/y xor all also common to asic-type protection devices
dw2_asic_hold = old << 1;
dw2_asic_hold |= BIT(old, 15); // rotate
dw2_asic_hold ^= 0x2bad;
dw2_asic_hold ^= BIT(dw2_asic_z, dw2_asic_y);
dw2_asic_hold ^= BIT( old, 7);
dw2_asic_hold ^= BIT( old, 3) << 11;
dw2_asic_hold ^= BIT(~old, 13) << 4; // inverted!
/*
// additional...
// how is this calculated? is it ever used??
// drgw2c = $80eeca, drgw2/dw2v100x = $80cb7a, drgw2j = $809168
dw2_asic_hold ^= BIT(space.read_byte(0x80eecb), 0) << 1;
dw2_asic_hold ^= BIT(space.read_byte(0x80eecb), 1) << 2;
dw2_asic_hold ^= BIT(space.read_byte(0x80eecb), 2) << 3;
dw2_asic_hold ^= BIT(space.read_byte(0x80eecb), 4) << 5;
dw2_asic_hold ^= BIT(space.read_byte(0x80eecb), 5) << 6;
dw2_asic_hold ^= BIT(space.read_byte(0x80eecb), 6) << 7;
dw2_asic_hold ^= BIT(space.read_byte(0x80eecb), 7) << 8;
dw2_asic_hold ^= BIT(space.read_byte(0x80eeca), 0) << 9;
dw2_asic_hold ^= BIT(space.read_byte(0x80eeca), 1) << 10;
dw2_asic_hold ^= BIT(space.read_byte(0x80eeca), 3) << 12;
dw2_asic_hold ^= BIT(space.read_byte(0x80eeca), 4) << 13;
dw2_asic_hold ^= BIT(space.read_byte(0x80eeca), 5) << 14;
dw2_asic_hold ^= BIT(space.read_byte(0x80eeca), 6) << 15;
*/
}
break;
case 0xf2: // ????
break;
default:
logerror("%06x: warning, writing to igs003_reg %02x = %02x\n", space.device().safe_pc(), dw2_asic_reg[0], data);
}
}
// What purpose to writes to this region serve? Written, but never read back? Must be related to the protection device?
WRITE16_HANDLER(dw2_unk_w)
{
// logerror("%06x: warning, writing to address %6.6x = %4.4x\n", space.device().safe_pc(), 0xd00000+(offset*2), data);
}
static void pgm_dw2_decrypt(running_machine &machine)
{
int i;
UINT16 *src = (UINT16 *) (machine.root_device().memregion("maincpu")->base()+0x100000);
int rom_size = 0x80000;
for(i=0; i<rom_size/2; i++) {
for (i=0; i<rom_size/2; i++) {
UINT16 x = src[i];
if(((i & 0x020890) == 0x000000)
|| ((i & 0x020000) == 0x020000 && (i & 0x001500) != 0x001400))
if (((i & 0x20890) == 0) || ((i & 0x20000) == 0x20000 && (i & 0x01500) != 0x01400))
x ^= 0x0002;
if(((i & 0x020400) == 0x000000 && (i & 0x002010) != 0x002010)
|| ((i & 0x020000) == 0x020000 && (i & 0x000148) != 0x000140))
if (((i & 0x20400) == 0 && (i & 0x02010) != 0x02010) || ((i & 0x20000) == 0x20000 && (i & 0x00148) != 0x00140))
x ^= 0x0400;
src[i] = x;
@ -77,19 +184,21 @@ 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));
machine.device("maincpu")->memory().space(AS_PROGRAM).install_legacy_write_handler(0xd80000, 0xd80003, FUNC(dw2_d80000_w));
machine.device("maincpu")->memory().space(AS_PROGRAM).install_legacy_write_handler(0xd00000, 0xd00fff, FUNC(dw2_unk_w));
}
DRIVER_INIT_MEMBER(pgm_state,drgw2)
{ /* incomplete? */
{
/* incomplete? */
UINT16 *mem16 = (UINT16 *)machine().root_device().memregion("maincpu")->base();
drgwld2_common_init(machine());
protection_address = 0xcb7e/2; // $80cb7e;
/* 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 */
@ -101,17 +210,27 @@ DRIVER_INIT_MEMBER(pgm_state,drgw2)
DRIVER_INIT_MEMBER(pgm_state,dw2v100x)
{
UINT16 *mem16 = (UINT16 *)machine().root_device().memregion("maincpu")->base();
drgwld2_common_init(machine());
protection_address = 0xcb7e/2; // $80cb7e;
/* 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[0x131084 / 2] = 0x4e93;
mem16[(0x131084+0xa6) / 2] = 0x4e93;
mem16[(0x131084+0x136) / 2] = 0x4e93;
mem16[0x13112a / 2] = 0x4e93;
mem16[0x1311ba / 2] = 0x4e93;
}
DRIVER_INIT_MEMBER(pgm_state,drgw2c)
{
UINT16 *mem16 = (UINT16 *)machine().root_device().memregion("maincpu")->base();
drgwld2_common_init(machine());
protection_address = 0xeece/2; // $80eece;
/* 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 */
@ -123,7 +242,11 @@ DRIVER_INIT_MEMBER(pgm_state,drgw2c)
DRIVER_INIT_MEMBER(pgm_state,drgw2j)
{
UINT16 *mem16 = (UINT16 *)machine().root_device().memregion("maincpu")->base();
drgwld2_common_init(machine());
protection_address = 0x91cc/2; // $8091cc;
/* 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 */
@ -131,4 +254,3 @@ DRIVER_INIT_MEMBER(pgm_state,drgw2j)
mem16[0x130366 / 2] = 0x4e93;
mem16[0x1303f6 / 2] = 0x4e93;
}