diff --git a/src/mame/drivers/kaneko16.c b/src/mame/drivers/kaneko16.c index 3e4878be536..26494164b94 100644 --- a/src/mame/drivers/kaneko16.c +++ b/src/mame/drivers/kaneko16.c @@ -1974,7 +1974,7 @@ static INTERRUPT_GEN( shogwarr_interrupt ) { case 2: cpu_set_input_line(device, 2, HOLD_LINE); break; case 1: cpu_set_input_line(device, 3, HOLD_LINE); break; -// case 0: cpu_set_input_line(device, 4, HOLD_LINE); break; + case 0: cpu_set_input_line(device, 4, HOLD_LINE); break; } } @@ -3255,23 +3255,6 @@ ROM_START( shogware ) ROM_LOAD( "fb003.u45", 0x080000, 0x080000, CRC(405722e9) SHA1(92e51093d50f74f650ba137f5fc2910e0f85337e) ) // 2 x $40000 ROM_END -static DRIVER_INIT( shogwarr ) -{ - DRIVER_INIT_CALL(kaneko16); - -/* - ROM test at 2237e: - - the chksum of 00000-03fffd = $657f is added to ($200042).w - [from shared ram]. The result must be $f463 [=($3fffe).w] - - Now, $f463-$657f = $8ee4 = byte sum of FB040A.U33 !! - - So, there's probably the MCU's code in there, though - I can't id what kind of CPU should run it :-( MCU is a 78K series III type CPU -*/ -} - /*************************************************************************** Fujiyama Buster @@ -3616,6 +3599,262 @@ static DRIVER_INIT( gtmr2 ) DRIVER_INIT_CALL(decrypt_toybox_rom_alt); } +// protection information for brapboys / shogwarr +// +// this is just an analysis of the MCU Data rom, in reality it probably processes this when requested, not pre-decrypts +// + +/* + +esentially the data rom is a linked list of encrypted blocks + +contains the following +ROM ADDRESS 0x0000 = the number of tables in this rom + +followed by several tables in the following format + +OFFSET 0 - the location of a word which specifies the size of the block + - this is usually '3', but if it's larger than 3 it enables an 'inline encryption' mode, whereby the decryption table is stored in the + - right before the length register + +OFFSET 1 - a 'mode' register of some sort, usually 0,1,2 or 3 for used data, shogun also called a 'blank' command (length 0) with mode 8 + +OFFSET 2 - unknown, might be some kind of 'step' register + +OFFSET 3 - decryption key - specifies which decryption table to use (ignored for inline tables, see offset 0) + +(inline decryption table goes here if specified) + +OFFSET 4-5 (or after the inline decryption table) - the length of the current block (so that the start of the next block can be found) + +OFFSET 6-size - data for thie block + +this continues for the number of blocks specified +after all the blocks there is a 0x1000 block of data which is the same between games + +where games specify the same decryption key the table used is the same, I don't know where these tables come from. + +*/ + +UINT16 calc3_mcu_crc; + +DRIVER_INIT( calc3 ) +{ + UINT8* rom = memory_region(machine,"cpu1"); + + int x; + int offset = 0; + UINT8 numregions; + + calc3_mcu_crc = 0; + for (x=0;x<0x20000;x++) + { + calc3_mcu_crc+=rom[x]; + } + printf("crc %04x\n",calc3_mcu_crc); + + numregions = rom[offset+0]; + rom++; + + + + + + for (x=0;x 3, it seems to specify the decryption table (or _a_ decryption table) inline of specified length, which loops over the data + if (blocksize_offset>3) + { + inline_table_base = offset+4; + inline_table_size = blocksize_offset-3; + for (xx=0;xx3)// inline decryption table case + { + int l; + for (l=0;lgamedrv->name, + x, + decryption_key_byte, + blocksize_offset, + length); + + + fp=fopen(filename, "w+b"); + if (fp) + { + fwrite(&rom[offset], length, 1, fp); + fclose(fp); + } + } + + } + } + + offset+=length; + } + + // dump out the 0x1000 sized block at the end + { + FILE *fp; + char filename[256]; + + sprintf(filename,"data_%s_finalblock", + machine->gamedrv->name); + + fp=fopen(filename, "w+b"); + if (fp) + { + fwrite(&rom[offset], 0x1000, 1, fp); + fclose(fp); + } + } + + DRIVER_INIT_CALL(kaneko16); + // MCU is a 78K series III type CPU +} + /*************************************************************************** @@ -3625,7 +3864,6 @@ static DRIVER_INIT( gtmr2 ) ***************************************************************************/ /* Working games */ - GAME( 1991, berlwall, 0, berlwall, berlwall, berlwall, ROT0, "Kaneko", "The Berlin Wall", 0 ) GAME( 1991, berlwalt, berlwall, berlwall, berlwalt, berlwall, ROT0, "Kaneko", "The Berlin Wall (bootleg ?)", 0 ) GAME( 1991, mgcrystl, 0, mgcrystl, mgcrystl, kaneko16, ROT0, "Kaneko", "Magical Crystals (World, 92/01/10)", 0 ) @@ -3646,8 +3884,8 @@ GAME( 1995, gtmr2u, gtmr2, gtmr2, gtmr2, gtmr2, ROT0, "Kaneko", "Gre /* Non-working games (mainly due to protection) */ -GAME( 1992, shogwarr, 0, shogwarr, shogwarr, shogwarr, ROT0, "Kaneko", "Shogun Warriors", GAME_NOT_WORKING ) -GAME( 1992, shogware, shogwarr, shogwarr, shogwarr, shogwarr, ROT0, "Kaneko", "Shogun Warriors (Euro)", GAME_NOT_WORKING ) -GAME( 1992, fjbuster, shogwarr, shogwarr, shogwarr, shogwarr, ROT0, "Kaneko", "Fujiyama Buster (Japan)", GAME_NOT_WORKING ) -GAME( 1992, brapboys, 0, shogwarr, shogwarr, 0, ROT0, "Kaneko", "B.Rap Boys (World)", GAME_NOT_WORKING ) -GAME( 1992, brapboyj, brapboys, shogwarr, shogwarr, 0, ROT0, "Kaneko", "B.Rap Boys (Japan)", GAME_NOT_WORKING ) +GAME( 1992, shogwarr, 0, shogwarr, shogwarr, calc3, ROT0, "Kaneko", "Shogun Warriors", GAME_NOT_WORKING ) +GAME( 1992, shogware, shogwarr, shogwarr, shogwarr, calc3, ROT0, "Kaneko", "Shogun Warriors (Euro)", GAME_NOT_WORKING ) +GAME( 1992, fjbuster, shogwarr, shogwarr, shogwarr, calc3, ROT0, "Kaneko", "Fujiyama Buster (Japan)", GAME_NOT_WORKING ) +GAME( 1992, brapboys, 0, shogwarr, shogwarr, calc3, ROT0, "Kaneko", "B.Rap Boys (World)", GAME_NOT_WORKING ) +GAME( 1992, brapboyj, brapboys, shogwarr, shogwarr, calc3, ROT0, "Kaneko", "B.Rap Boys (Japan)", GAME_NOT_WORKING ) diff --git a/src/mame/machine/kaneko16.c b/src/mame/machine/kaneko16.c index 89f62422d40..b3ca49ecc63 100644 --- a/src/mame/machine/kaneko16.c +++ b/src/mame/machine/kaneko16.c @@ -311,6 +311,83 @@ CALC3_MCU_COM_W(3) - Read the DSWs - Supply code snippets to the 68000 */ +UINT32 writeaddress; +extern UINT16 calc3_mcu_crc; + +// todo: change this to get it from the decrypted rom, it's block 0x19, and we have decrypted it (as specified in the parameters) +static const UINT16 shogwarr_snip_[] = { + 0x48E7,0xFFFE, // movem.l D0-D7/A0-A6, -(A7) + + 0x3039,0x00A8,0x0000, // move.w $a80000.l, D0 + 0x4279,0x0020,0xFFFE, // clr.w $20fffe.l + + 0x41F9,0x0020,0x0000, // lea $200000.l, A0 + 0x7000, // moveq #$0, D0 + + 0x43E8,0x01C6, // lea ($1c6,A0), A1 + 0x7E02, // moveq #$2, D7 + 0xD059, // add.w (A1)+, D0 + 0x51CF,0xFFFC, // dbra D7, 207ffe + + 0x43E9,0x0002, // lea ($2,A1), A1 + 0x7E04, // moveq #$4, D7 + 0xD059, // add.w (A1)+, D0 + 0x51CF,0xFFFC, // dbra D7, 20800a + + 0x4640, // not.w D0 + 0x5340, // subq.w #1, D0 + 0x0068,0x0030,0x0216, // ori.w #$30, ($216,A0) + + 0xB07A,0x009A, // cmp.w ($9a,PC), D0; ($2080b6) + 0x670A, // beq 20802a + + 0x0268,0x000F,0x0216, // andi.w #$f, ($216,A0) + 0x4268,0x0218, // clr.w ($218,A0) + + 0x5468,0x0216, // addq.w #2, ($216,A0) + 0x42A8,0x030C, // clr.l ($30c,A0) + 0x117C,0x0020,0x030C, // move.b #$20, ($30c,A0) + + 0x3E3C,0x0001, // move.w #$1, D7 + + 0x0C68,0x0008,0x0218, // cmpi.w #$8, ($218,A0) + 0x6C00,0x0068, // bge 2080ac + + 0x117C,0x0080,0x0310, // move.b #$80, ($310,A0) + 0x117C,0x0008,0x0311, // move.b #$8, ($311,A0) + 0x317C,0x7800,0x0312, // move.w #$7800, ($312,A0) + 0x5247, // addq.w #1, D7 + 0x0C68,0x0040,0x0216, // cmpi.w #$40, ($216,A0) + 0x6D08, // blt 20806a + + 0x5468,0x0218, // addq.w #2, ($218,A0) + 0x6000,0x0044, // bra 2080ac + + 0x117C,0x0041,0x0314, // move.b #$41, ($314,A0) + + 0x0C39,0x0001,0x0010,0x2E12,// cmpi.b #$1, $102e12.l + 0x6606, // bne 208080 + + 0x117C,0x0040,0x0314, // move.b #$40, ($314,A0) + + 0x117C,0x000C,0x0315, // move.b #$c, ($315,A0) + 0x317C,0x7000,0x0316, // move.w #$7000, ($316,A0) + 0x5247, // addq.w #1, D7 + + 0x0839,0x0001,0x0010,0x2E15,// btst #$1, $102e15.l ; service mode + 0x6714, // beq 2080ac + + 0x117C,0x0058,0x0318, // move.b #$58, ($318,A0) + 0x117C,0x0006,0x0319, // move.b #$6, ($319,A0) + 0x317C,0x6800,0x031A, // move.w #$6800, ($31a,A0) + 0x5247, // addq.w #1, D7 + + 0x3147,0x030A, // move.w D7, ($30a,A0) + 0x4CDF,0x7FFF, // movem.l (A7)+, D0-D7/A0-A6 + 0x4E73, // rte + 0xC747, +}; + static void calc3_mcu_run(running_machine *machine) { @@ -318,179 +395,185 @@ static void calc3_mcu_run(running_machine *machine) if ( calc3_mcu_status != (1|2|4|8) ) return; - mcu_command = kaneko16_mcu_ram[calc3_mcu_command_offset + 0]; + //calc3_mcu_status = 0; + + mcu_command = kaneko16_mcu_ram[calc3_mcu_command_offset/2 + 0]; if (mcu_command == 0) return; logerror("%s : MCU executed command at %04X: %04X\n", - cpuexec_describe_context(machine),calc3_mcu_command_offset*2,mcu_command); + cpuexec_describe_context(machine),calc3_mcu_command_offset,mcu_command); + switch (mcu_command) { case 0x00ff: { - static const UINT16 shogwarr_snip_[] = { - 0x48E7,0xFFFE, // movem.l D0-D7/A0-A6, -(A7) + - 0x3039,0x00A8,0x0000, // move.w $a80000.l, D0 - 0x4279,0x0020,0xFFFE, // clr.w $20fffe.l + int param1 = kaneko16_mcu_ram[(0>>1) + 1]; + int param2 = kaneko16_mcu_ram[(0>>1) + 2]; + int param3 = kaneko16_mcu_ram[(0>>1) + 3]; + int param4 = kaneko16_mcu_ram[(0>>1) + 4]; + int param5 = kaneko16_mcu_ram[(0>>1) + 5]; + int param6 = kaneko16_mcu_ram[(0>>1) + 6]; + int param7 = kaneko16_mcu_ram[(0>>1) + 7]; + int param8 = kaneko16_mcu_ram[(0>>1) + 8]; + int param9 = kaneko16_mcu_ram[(0>>1) + 9]; - 0x41F9,0x0020,0x0000, // lea $200000.l, A0 - 0x7000, // moveq #$0, D0 + logerror("params %04x %04x %04x %04x %04x %04x %04x %04x %04x\n", + param1,param2,param3,param4,param5,param6,param7,param8,param9); - 0x43E8,0x01C6, // lea ($1c6,A0), A1 - 0x7E02, // moveq #$2, D7 - 0xD059, // add.w (A1)+, D0 - 0x51CF,0xFFFC, // dbra D7, 207ffe - - 0x43E9,0x0002, // lea ($2,A1), A1 - 0x7E04, // moveq #$4, D7 - 0xD059, // add.w (A1)+, D0 - 0x51CF,0xFFFC, // dbra D7, 20800a - - 0x4640, // not.w D0 - 0x5340, // subq.w #1, D0 - 0x0068,0x0030,0x0216, // ori.w #$30, ($216,A0) - - 0xB07A,0x009A, // cmp.w ($9a,PC), D0; ($2080b6) - 0x670A, // beq 20802a - - 0x0268,0x000F,0x0216, // andi.w #$f, ($216,A0) - 0x4268,0x0218, // clr.w ($218,A0) - - 0x5468,0x0216, // addq.w #2, ($216,A0) - 0x42A8,0x030C, // clr.l ($30c,A0) - 0x117C,0x0020,0x030C, // move.b #$20, ($30c,A0) - - 0x3E3C,0x0001, // move.w #$1, D7 - - 0x0C68,0x0008,0x0218, // cmpi.w #$8, ($218,A0) - 0x6C00,0x0068, // bge 2080ac - - 0x117C,0x0080,0x0310, // move.b #$80, ($310,A0) - 0x117C,0x0008,0x0311, // move.b #$8, ($311,A0) - 0x317C,0x7800,0x0312, // move.w #$7800, ($312,A0) - 0x5247, // addq.w #1, D7 - 0x0C68,0x0040,0x0216, // cmpi.w #$40, ($216,A0) - 0x6D08, // blt 20806a - - 0x5468,0x0218, // addq.w #2, ($218,A0) - 0x6000,0x0044, // bra 2080ac - - 0x117C,0x0041,0x0314, // move.b #$41, ($314,A0) - - 0x0C39,0x0001,0x0010,0x2E12,// cmpi.b #$1, $102e12.l - 0x6606, // bne 208080 - - 0x117C,0x0040,0x0314, // move.b #$40, ($314,A0) - - 0x117C,0x000C,0x0315, // move.b #$c, ($315,A0) - 0x317C,0x7000,0x0316, // move.w #$7000, ($316,A0) - 0x5247, // addq.w #1, D7 - - 0x0839,0x0001,0x0010,0x2E15,// btst #$1, $102e15.l ; service mode - 0x6714, // beq 2080ac - - 0x117C,0x0058,0x0318, // move.b #$58, ($318,A0) - 0x117C,0x0006,0x0319, // move.b #$6, ($319,A0) - 0x317C,0x6800,0x031A, // move.w #$6800, ($31a,A0) - 0x5247, // addq.w #1, D7 - - 0x3147,0x030A, // move.w D7, ($30a,A0) - 0x4CDF,0x7FFF, // movem.l (A7)+, D0-D7/A0-A6 - 0x4E73, // rte - 0xC747, - }; + writeaddress = (param6 << 16) | param7; - int param1 = kaneko16_mcu_ram[calc3_mcu_command_offset + 1]; - int param2 = kaneko16_mcu_ram[calc3_mcu_command_offset + 2]; - int param3 = kaneko16_mcu_ram[calc3_mcu_command_offset + 3]; - int param4 = kaneko16_mcu_ram[calc3_mcu_command_offset + 4]; - int param5 = kaneko16_mcu_ram[calc3_mcu_command_offset + 5]; - int param6 = kaneko16_mcu_ram[calc3_mcu_command_offset + 6]; - int param7 = kaneko16_mcu_ram[calc3_mcu_command_offset + 7]; - UINT32 writeaddress = (param6 << 16) | param7; - int i; - logerror("params %04x %04x %04x %04x %04x %04x %04x\n", - param1,param2,param3,param4,param5,param6,param7); - - - - // clear old command (handshake to main cpu) - kaneko16_mcu_ram[calc3_mcu_command_offset] = 0x0000; // execute the command: kaneko16_mcu_ram[param1 / 2] = ~input_port_read(machine, "DSW1"); // DSW kaneko16_mcu_ram[param2 / 2] = 0xffff; // ? -1 / anything else - calc3_mcu_command_offset = param3 / 2; // where next command will be written? // param 4? - kaneko16_mcu_ram[param5 / 2] = 0x8ee4; // MCU Rom Checksum! + kaneko16_mcu_ram[param5 / 2] = calc3_mcu_crc; // MCU Rom Checksum! // param 6&7 = address.l + + + + // clear old command (handshake to main cpu) + kaneko16_mcu_ram[(calc3_mcu_command_offset>>1)+0] = 0x0000; + kaneko16_mcu_ram[(calc3_mcu_command_offset>>1)+1] = 0x0000; + kaneko16_mcu_ram[(calc3_mcu_command_offset>>1)+2] = 0x0000; + kaneko16_mcu_ram[(calc3_mcu_command_offset>>1)+3] = 0x0000; + kaneko16_mcu_ram[(calc3_mcu_command_offset>>1)+4] = 0x0000; + kaneko16_mcu_ram[(calc3_mcu_command_offset>>1)+5] = 0x0000; + kaneko16_mcu_ram[(calc3_mcu_command_offset>>1)+6] = 0x0000; + kaneko16_mcu_ram[(calc3_mcu_command_offset>>1)+7] = 0x0000; + + calc3_mcu_command_offset = param3; // where next command will be written? + + + } + break; + + // the 'case' seems to be the number of commands in the list + // there are parts of the code where i've seen up to '5' specified, and the game uploads 5 transfer commands + // + + case 0x0001: + { + int i; + int param1 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 1]; + int param2 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 2]; + int param3 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 3]; + int param4 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 4]; + int param5 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 5]; + int param6 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 6]; + int param7 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1)+ 7]; + + UINT32 writebackaddress = (param1&0x00ff) | (param2&0xff00); + UINT8 command1tabl = (param1&0xff00) >> 8; + UINT16 command1addr = (param1&0x00ff) | (param2&0xff00); + + + logerror("params %04x %04x %04x %04x %04x %04x %04x\n", + param1,param2,param3,param4,param5,param6,param7); + logerror("command 1 addr %04x command 1 table %02x\n", command1addr, command1tabl); + + // clear old command (handshake to main cpu) + kaneko16_mcu_ram[calc3_mcu_command_offset>>1] = 0x0000; + + + + // execute the command: + + // param1 ? + //kaneko16_mcu_ram[param2/2 + 0] = 0x0000; // ? + //kaneko16_mcu_ram[param2/2 + 1] = 0x0000; // ? + //kaneko16_mcu_ram[param2/2 + 2] = 0x0000; // ? + //kaneko16_mcu_ram[param2/2 + 3] = 0x0000; // ? addr.l + //kaneko16_mcu_ram[param2/2 + 4] = 0x00e0; // 0000e0: 4e73 rte + + //UINT32 writeaddress = (param2); + + + writeaddress&=0xffff; for(i=0;i>1) + 1]; + int param2 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 2]; + int param3 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 3]; + int param4 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 4]; + int param5 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 5]; + int param6 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 6]; + int param7 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1)+ 7]; + + + UINT8 command1tabl = (param1&0xff00) >> 8; + UINT16 command1addr = (param1&0x00ff) | (param2&0xff00); + UINT8 command2tabl = (param3&0xff00) >> 8; + UINT16 command2addr = (param3&0x00ff) | (param4&0xff00); logerror("params %04x %04x %04x %04x %04x %04x %04x\n", param1,param2,param3,param4,param5,param6,param7); - - + logerror("command 1 addr %04x command 1 table %02x | command 2 addr %04x command 2 table %02x\n", command1addr, command1tabl, command2addr, command2tabl); + // clear old command (handshake to main cpu) - kaneko16_mcu_ram[calc3_mcu_command_offset] = 0x0000; + kaneko16_mcu_ram[calc3_mcu_command_offset>>1] = 0x0000; // execute the command: +; + } + break; + + case 0x0003: + { + + int param1 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 1]; + int param2 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 2]; + int param3 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 3]; + int param4 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 4]; + int param5 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 5]; + int param6 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 6]; + int param7 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1)+ 7]; + + UINT8 command1tabl = (param1&0xff00) >> 8; + UINT16 command1addr = (param1&0x00ff) | (param2&0xff00); + UINT8 command2tabl = (param3&0xff00) >> 8; + UINT16 command2addr = (param3&0x00ff) | (param4&0xff00); + UINT8 command3tabl = (param5&0xff00) >> 8; + UINT16 command3addr = (param5&0x00ff) | (param6&0xff00); + + logerror("params %04x %04x %04x %04x %04x %04x %04x\n", + param1,param2,param3,param4,param5,param6,param7); + logerror("command 1 addr %04x command 1 table %02x | command 2 addr %04x command 2 table %02x | command 3 addr %04x command 3 table %02x\n", command1addr, command1tabl, command2addr, command2tabl, command3addr, command3tabl); + + // clear old command (handshake to main cpu) + kaneko16_mcu_ram[calc3_mcu_command_offset>>1] = 0x0000; + + // execute the command: } break;