diff options
Diffstat (limited to 'src/mame/machine/segas32.c')
-rw-r--r-- | src/mame/machine/segas32.c | 400 |
1 files changed, 400 insertions, 0 deletions
diff --git a/src/mame/machine/segas32.c b/src/mame/machine/segas32.c new file mode 100644 index 00000000000..0026d3beaac --- /dev/null +++ b/src/mame/machine/segas32.c @@ -0,0 +1,400 @@ +/* Sega System 32 Protection related functions */ + +#include "driver.h" +#include "segas32.h" + + +/****************************************************************************** + ****************************************************************************** + Golden Axe 2 (Revenge of Death Adder) + ****************************************************************************** + ******************************************************************************/ + +#define xxxx 0x00 + +static const UINT8 ga2_v25_opcode_table[256] = { + xxxx,xxxx,0xEA,xxxx,xxxx,0x8B,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xFA, + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x49,xxxx,xxxx,xxxx, + xxxx,xxxx,xxxx,xxxx,xxxx,0xE8,xxxx,xxxx,0x75,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, + xxxx,xxxx,xxxx,xxxx,0x8D,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xBF,xxxx,0x88,xxxx, + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xBC, + xxxx,xxxx,xxxx,0x8A,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0x83,xxxx,xxxx,xxxx,xxxx,xxxx, + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xB8,0x26,xxxx, + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xEB, + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xB2,xxxx,xxxx,xxxx,xxxx, + xxxx,xxxx,xxxx,0xC3,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xB9,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, + xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx, + xxxx,xxxx,0x8E,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,xxxx,0xBE,xxxx,xxxx,xxxx,xxxx +}; + +#undef xxxx + +static void nec_v25_cpu_decrypt(void) +{ + int i; + UINT8 *rom = memory_region(REGION_CPU3); + UINT8* decrypted = auto_malloc(0x100000); + UINT8* temp = malloc_or_die(0x100000); + + // set CPU3 opcode base + memory_set_decrypted_region(2, 0x00000, 0xfffff, decrypted); + + // make copy of ROM so original can be overwritten + memcpy(temp, rom, 0x10000); + + for(i = 0; i < 0x10000; i++) + { + int j = BITSWAP16(i, 14, 11, 15, 12, 13, 4, 3, 7, 5, 10, 2, 8, 9, 6, 1, 0); + + // normal ROM data with address swap undone + rom[i] = temp[j]; + + // decryped opcodes with address swap undone + decrypted[i] = ga2_v25_opcode_table[ temp[j] ]; + } + + memcpy(rom+0xf0000, rom, 0x10000); + memcpy(decrypted+0xf0000, decrypted, 0x10000); + + free(temp); +} + +void decrypt_ga2_protrom(void) +{ + nec_v25_cpu_decrypt(); +} + + +WRITE16_HANDLER( ga2_dpram_w ) +{ + /* does it ever actually write.. */ +} + +READ16_HANDLER( ga2_dpram_r ) +{ + return (ga2_dpram[offset])|(ga2_dpram[offset+1]<<8); +} + + +#if 0 // simulation +READ16_HANDLER(ga2_sprite_protection_r) +{ + static UINT32 prot[16] = + { + 0x0a, 0, + 0xc5, 0, + 0x11, 0, + 0x11, 0, + 0x18, 0, + 0x18, 0, + 0x1f, 0, + 0xc6, 0, + }; + + return prot[offset]; +} + +READ16_HANDLER(ga2_wakeup_protection_r) +{ + static const char *prot = + "wake up! GOLDEN AXE The Revenge of Death-Adder! "; + return prot[offset]; +} +#endif + +/****************************************************************************** + ****************************************************************************** + Sonic Arcade protection + ****************************************************************************** + ******************************************************************************/ + + +// This code duplicates the actions of the protection device used in SegaSonic +// arcade revision C, allowing the game to run correctly. +#define CLEARED_LEVELS 0xE5C4 +#define CURRENT_LEVEL 0xF06E +#define CURRENT_LEVEL_STATUS 0xF0BC +#define LEVEL_ORDER_ARRAY 0x263A + +WRITE16_HANDLER(sonic_level_load_protection) +{ + UINT16 level; +//Perform write + system32_workram[CLEARED_LEVELS / 2] = (data & ~mem_mask) | (system32_workram[CLEARED_LEVELS / 2] & mem_mask); + +//Refresh current level + if (system32_workram[CLEARED_LEVELS / 2] == 0) + { + level = 0x0007; + } + else + { + level = *((memory_region(REGION_CPU1) + LEVEL_ORDER_ARRAY) + (system32_workram[CLEARED_LEVELS / 2] * 2) - 1); + level |= *((memory_region(REGION_CPU1) + LEVEL_ORDER_ARRAY) + (system32_workram[CLEARED_LEVELS / 2] * 2) - 2) << 8; + } + system32_workram[CURRENT_LEVEL / 2] = level; + +//Reset level status + system32_workram[CURRENT_LEVEL_STATUS / 2] = 0x0000; + system32_workram[(CURRENT_LEVEL_STATUS + 2) / 2] = 0x0000; +} + + +/****************************************************************************** + ****************************************************************************** + Burning Rival + ****************************************************************************** + ******************************************************************************/ + + +// the protection board on many system32 games has full dma/bus access +// and can write things into work RAM. we simulate that here for burning rival. +READ16_HANDLER(brival_protection_r) +{ + if (!mem_mask) // only trap on word-wide reads + { + switch (offset) + { + case 0: + case 2: + case 3: + return 0; + break; + } + } + + return system32_workram[0xba00/2 + offset]; +} + +WRITE16_HANDLER(brival_protection_w) +{ + static const int protAddress[6][2] = + { + { 0x109517, 0x00/2 }, + { 0x109597, 0x10/2 }, + { 0x109597, 0x20/2 }, + { 0x109597, 0x30/2 }, + { 0x109597, 0x40/2 }, + { 0x109617, 0x50/2 }, + }; + char ret[32]; + int curProtType; + UINT8 *ROM = memory_region(REGION_CPU1); + + switch (offset) + { + case 0x800/2: + curProtType = 0; + break; + case 0x802/2: + curProtType = 1; + break; + case 0x804/2: + curProtType = 2; + break; + case 0x806/2: + curProtType = 3; + break; + case 0x808/2: + curProtType = 4; + break; + case 0x80a/2: + curProtType = 5; + break; + default: + if (offset >= 0xa00/2 && offset < 0xc00/2) + return; + logerror("brival_protection_w: UNKNOWN WRITE: offset %x value %x\n", offset, data); + return; + break; + } + + memcpy(ret, &ROM[protAddress[curProtType][0]], 16); + ret[16] = '\0'; + + memcpy(&system32_protram[protAddress[curProtType][1]], ret, 16); +} + + +/****************************************************************************** + ****************************************************************************** + Dark Edge + ****************************************************************************** + ******************************************************************************/ + +void darkedge_fd1149_vblank(void) +{ + program_write_word(0x20f072, 0); + program_write_word(0x20f082, 0); + + if( program_read_byte(0x20a12c) != 0 ) + { + program_write_byte(0x20a12c, program_read_byte(0x20a12c)-1 ); + + if( program_read_byte(0x20a12c) == 0 ) + program_write_byte(0x20a12e, 1); + } +} + + +WRITE16_HANDLER( darkedge_protection_w ) +{ + logerror("%06x:darkedge_prot_w(%06X) = %04X & %04X\n", + activecpu_get_pc(), 0xa00000 + 2*offset, data, mem_mask ^ 0xffff); +} + + +READ16_HANDLER( darkedge_protection_r ) +{ + logerror("%06x:darkedge_prot_r(%06X) & %04X\n", + activecpu_get_pc(), 0xa00000 + 2*offset, mem_mask ^ 0xffff); + return 0xffff; +} + + + +/****************************************************************************** + ****************************************************************************** + DBZ VRVS + ****************************************************************************** + ******************************************************************************/ + +WRITE16_HANDLER( dbzvrvs_protection_w ) +{ + program_write_word( 0x2080c8, program_read_word( 0x200044 ) ); +} + + +READ16_HANDLER( dbzvrvs_protection_r ) +{ + return 0xffff; +} + + + +/****************************************************************************** + ****************************************************************************** + Arabian Fight + ****************************************************************************** + ******************************************************************************/ + + +// protection ram is 8-bits wide and only occupies every other address +READ16_HANDLER(arabfgt_protection_r) +{ + int PC = activecpu_get_pc(); + int cmpVal; + + if (PC == 0xfe0325 || PC == 0xfe01e5 || PC == 0xfe035e || PC == 0xfe03cc) + { + cmpVal = activecpu_get_reg(1); + + // R0 always contains the value the protection is supposed to return (!) + return cmpVal; + } + else + { + popmessage("UNKONWN ARF PROTECTION READ PC=%x\n", PC); + } + + return 0; +} + +WRITE16_HANDLER(arabfgt_protection_w) +{ +} + +READ16_HANDLER(arf_wakeup_protection_r) +{ + static const char *prot = + "wake up! ARF! "; + return prot[offset]; +} + +/****************************************************************************** + ****************************************************************************** + The J.League 1994 (Japan) + ****************************************************************************** + ******************************************************************************/ +WRITE16_HANDLER( jleague_protection_w ) + { + COMBINE_DATA( &system32_workram[0xf700/2 + offset ] ); + + switch( offset ) + { + // Map team browser selection to opponent browser selection + // using same lookup table that V60 uses for sound sample mapping. + case 0: + program_write_byte( 0x20f708, program_read_word( 0x7bbc0 + data*2 ) ); + break; + + // move on to team browser + case 4/2: + program_write_byte( 0x200016, data & 0xff ); + break; + + default: + break; + } +} + +/****************************************************************************** + ****************************************************************************** + Air Rescue + ****************************************************************************** + ******************************************************************************/ +/* + protection + a00000 - a00002 dsp i/o + a00004 - dsp int/ack + + dsp uses its p0/p1 for address select + dsp.sr = ???0 read a00000 into dsp.a + dsp.sr = ???1 read a00002 into dsp.b + dsp.sr = ???2 write dsp.b in a00000 + dsp.sr = ???3 write dsp.a in a00002 + + Use of p0/p1 means there's no other way for dsp to communicate with V60, unless it shares RAM. + 99.99% of the dsp code is unused because the V60 ROM is hardcoded as part of a twin set, + maybe the standalone board was for dev only? nop the 3 bytes at 0x06023A for standalone. (centred intro text) +*/ +static UINT16 arescue_dsp_io[6] = {0,0,0,0,0,0}; + +READ16_HANDLER( arescue_dsp_r ) +{ + if( offset == 4/2 ) + { + switch( arescue_dsp_io[0] ) + { + case 0: + case 1: + case 2: + break; + + case 3: + arescue_dsp_io[0] = 0x8000; + arescue_dsp_io[2/2] = 0x0001; + break; + + case 6: + arescue_dsp_io[0] = 4 * arescue_dsp_io[2/2]; + break; + + default: + logerror("Unhandled DSP cmd %04x (%04x).\n", arescue_dsp_io[0], arescue_dsp_io[1] ); + break; + } + } + + return arescue_dsp_io[offset]; +} + +WRITE16_HANDLER( arescue_dsp_w ) +{ + COMBINE_DATA(&arescue_dsp_io[offset]); +} + |