summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame/machine/segas32.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mame/machine/segas32.c')
-rw-r--r--src/mame/machine/segas32.c400
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]);
+}
+