summaryrefslogtreecommitdiffstatshomepage
path: root/src/mame
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2009-06-18 03:53:38 +0000
committer Aaron Giles <aaron@aarongiles.com>2009-06-18 03:53:38 +0000
commit069747cca37247954eb2f22fe6fb7ffeef8afa00 (patch)
tree904d83ed7529ba109f8fdb9671949c862d74451e /src/mame
parentd220998fed9d4e6fca754ac033a507f8e83812a2 (diff)
From: David Haywood
Subject: Shogun Warriors / BRAP Boys Aaron / Kale, I got a private request to take a look at these, and made a few discoveries about the external protection data rom. Basically it's a 'linked list' of encrypted tables and command types / modes. The encryption is pretty straightforward, although working out the tables could be tricky. It also has an 'inline table' mode, but it's only used for a few tables. There is a large 0x1000 block at the end of all the data which could be related to the normal tables. I've added some rather verbose code to process the rom, and dump out some data, so that if somebody wants to look at it further they can. Understanding how it works properly before decapping it would help to verify and implement the proper emulation of the device later. (the actual protection device is a completely unemulated cpu type, so could prove tricky even with results) I don't fully understand all the parameters at the moment, although I suspect that with this newfound knowledge getting the game(s) up and running would only take a few trojans to figure out the behaviors that aren't understood, and get the decryption tables (which could be time consuming otherwise) The previous implementation of the protection simulation was also wrong, it copies the first 'block' of data (worked out at the time with a trojan) upon the first mcu command (0xff) but infact, it shouldn't be transfered at that point, as the command containing the number of the table to transfer (0x19 in the list) comes later. The game seems to provide lists of transfer operations to perform, I suspect some are direct, and some are indirect. I've also added code to calculate the CRC of the protection rom, rather than hard coding it. I haven't yet moved the decrypted startup code out of the driver, which should be possible as we can correctly copy that from the external rom using the command system at this point. I know Andreas was looking at this in the past, so this new information might be of interest to him, as it provides clearer blocks of encrypted data, and the 0x1000 block at the end might be of interest to him if it relates in some way to the smaller 0x40 byte tables used for decrypting the data.
Diffstat (limited to 'src/mame')
-rw-r--r--src/mame/drivers/kaneko16.c286
-rw-r--r--src/mame/machine/kaneko16.c305
2 files changed, 456 insertions, 135 deletions
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<numregions;x++)
+ {
+ int length;
+ int startoffset = offset;
+ int xx;
+ int blocksize_offset = rom[offset+0]; // location of the 'block length'
+ int decryption_key_byte = rom[offset+3];
+ int inline_table_base = 0;
+ int inline_table_size = 0;
+ UINT8 mode = rom[offset+1];
+ UINT8 unknown = rom[offset+2];
+
+
+ printf("%04x keydat %02x - bsofs:%02x m:%02x u:%02x k:%02x | ", startoffset, x, blocksize_offset,mode,unknown,decryption_key_byte);
+
+ // if blocksize_offset > 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;xx<blocksize_offset-3;xx++)
+ {
+ printf("%02x ", rom[inline_table_base+xx]);
+ }
+ }
+
+
+ offset+= blocksize_offset+1;
+ length = rom[offset+0] | (rom[offset+1]<<8);
+
+ printf("(length %04x)", length);
+
+ printf("\n");
+
+ offset+=2;
+
+ //if (x==0x2d)
+ {
+ if (length != 0)
+ {
+
+ if (blocksize_offset==3)
+ {
+
+ // these tables are guessed, where do they come from? internal mcu rom? 0x1000 block at the end? are they related?
+ UINT8* table = 0;
+
+ /* ok */
+ UINT8 table01[64] = {
+ 0xce,0xab,0xa1,0xaa,0x20,0x20,0xcb,0x57,0x5b,0x65,0xd6,0x65,0x5e,0x92,0x6c,0x0a,
+ 0xf8,0xea,0xb6,0xfd,0x76,0x35,0x47,0xaf,0xed,0xe0,0xcc,0x4d,0x4c,0xd6,0x74,0x78,
+ 0x20,0x1c,0x1f,0xc1,0x25,0x2e,0x49,0xe7,0x90,0x1b,0xb4,0xcf,0x1e,0x61,0xd7,0x46,
+ 0xda,0x89,0x08,0x77,0xb1,0x81,0x6b,0x2d,0xb6,0xbc,0x99,0xc9,0x35,0x0a,0x0f,0x01
+ };
+
+
+
+ /* ok */
+ UINT8 table15[64] = {
+ 0x0C,0xEB,0x30,0x25,0xA8,0xED,0xE3,0x23,0xAC,0x2B,0x8D,0x34,0x88,0x9F,0x55,0xB5,
+ 0xBF,0x15,0xE3,0x7C,0x54,0xD4,0x72,0xA9,0x7E,0x80,0x27,0x9F,0xA3,0x3F,0xA1,0x4D,
+ 0x84,0x1B,0xD1,0xB2,0xB5,0xA7,0x0C,0xA0,0x51,0xE6,0x5E,0xC0,0xEB,0x68,0x22,0xD6,
+ 0xC8,0xB6,0xCF,0x46,0x4B,0xF0,0x15,0xD7,0xB0,0xB5,0x29,0xB8,0xFD,0x43,0x5C,0xC0
+ };
+
+
+ /* used by shogun & brapboys */
+ unsigned char table31[64] = {
+ // x x x ok x x x ok x x x ok x x x ok
+ 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0xaf, 0x00, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x3b,
+ 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xb1, 0x00, 0x00, 0x00, 0xdc,
+ 0x00, 0x00, 0x00, 0xb5, 0x00, 0x00, 0x00, 0x3d, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0xde,
+ 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x26, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0xb1
+ };
+
+ /* not ok */
+ unsigned char table3f[64] = {
+ 0x29,0x34,0xD9,0x20,0x61,0x54,0x5F,0x6C,0x21,0x7E,0x5A,0x0F,0xD0,0x35,0x3B,0x2E,
+ 0x44,0x4C,0x71,0xE5,0x53,0x93,0x59,0x1A,0x1A,0xB5,0xE7,0x7A,0x0F,0x61,0x13,0xBD,
+ 0xC7,0xA8,0x05,0x2A,0x86,0xA7,0x00,0x5A,0x8B,0x65,0x10,0xBE,0x18,0xFE,0x71,0xE3,
+ 0x43,0x02,0xC3,0xF5,0x7E,0x18,0xF1,0x82,0xE7,0xE7,0xDC,0x01,0x4F,0x36,0xCA,0x13
+ };
+
+
+
+ unsigned char tableb0[64] = {
+ // x x x ok x x x ok x x x ok x x x ok
+ 0x00, 0x00, 0x00, 0x5e, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x81,
+ 0x00, 0x00, 0x00, 0x85, 0x00, 0x00, 0x00, 0x6d, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x32,
+ 0x00, 0x00, 0x00, 0x76, 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xb2, 0x00, 0x00, 0x00, 0xe4, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x5b
+ };
+
+ unsigned char tableb7[64] = {
+ // x x x ok x x x ok x x x ok x x x ok
+ 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xd7,
+ 0x00, 0x00, 0x00, 0xe7, 0x00, 0x00, 0x00, 0x54, 0x00, 0x00, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x82,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa2, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, 0x26,
+ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x9d, 0x00, 0x00, 0x00, 0x33
+ };
+
+ unsigned char tablebb[64] = {
+ // x x x ok x x x ok x x x ok x x x ok
+ 0x00, 0x00, 0x00, 0x62, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x3d,
+ 0x00, 0x00, 0x00, 0xec, 0x00, 0x00, 0x00, 0x99, 0x00, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0x69,
+ 0x00, 0x00, 0x00, 0xeb, 0x00, 0x00, 0x00, 0x6f, 0x00, 0x00, 0x00, 0x97, 0x00, 0x00, 0x00, 0x9e,
+ 0x00, 0x00, 0x00, 0xe1, 0x00, 0x00, 0x00, 0x9f, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x00, 0x00, 0x4d
+ };
+ /* not ok */
+ unsigned char tablebf[64] = {
+ 0x9B, 0x8F, 0xDC, 0xBE, 0xE1, 0xD9, 0xE1, 0x86, 0x10, 0x4E, 0xBA, 0xC4, 0x8D, 0x6E, 0xD8, 0x9B,
+ 0x2F, 0x0F, 0xAC, 0x2C, 0xCB, 0x00, 0x92, 0x5D, 0x80, 0xED, 0x7E, 0xD9, 0xC3, 0x82, 0x69, 0x58,
+ 0x29, 0xD3, 0x78, 0x21, 0xF7, 0xFC, 0xF1, 0xCD, 0x69, 0x04, 0xDD, 0x4D, 0xC4, 0x08, 0x7C, 0x2F,
+ 0x1D, 0x95, 0x6C, 0x1C, 0xE7, 0x55, 0x98, 0xA6, 0x3D, 0xEE, 0xE1, 0x40, 0xF4, 0x27, 0x8E, 0x8E
+ };
+
+ if (decryption_key_byte == 0x01) table = table01;
+ if (decryption_key_byte == 0x15) table = table15;
+ if (decryption_key_byte == 0x31) table = table31;
+ if (decryption_key_byte == 0x3f) table = table3f;
+ if (decryption_key_byte == 0xb0) table = tableb0;
+ if (decryption_key_byte == 0xb7) table = tableb7;
+ if (decryption_key_byte == 0xbb) table = tablebb;
+ if (decryption_key_byte == 0xbf) table = tablebf;
+
+ if (table)
+ {
+ int l;
+ for (l=0;l<length;l++)
+ {
+ rom[offset+l] -= table[l&0x3f];
+ }
+ }
+ }
+ else if (blocksize_offset>3)// inline decryption table case
+ {
+ int l;
+ for (l=0;l<length;l++)
+ {
+ rom[offset+l] -= rom[inline_table_base + (l%inline_table_size)];
+ }
+ }
+ else
+ {
+ printf("blocksize offset < 3??\n");
+
+ }
+
+ // dump out file
+ {
+ FILE *fp;
+ char filename[256];
+
+ sprintf(filename,"data_%s_tableno%02x_key%02x_inlineoffset%02x_length%04x",
+ machine->gamedrv->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,186 +311,269 @@ CALC3_MCU_COM_W(3)
- Read the DSWs
- Supply code snippets to the 68000
*/
+UINT32 writeaddress;
+extern UINT16 calc3_mcu_crc;
-static void calc3_mcu_run(running_machine *machine)
-{
- UINT16 mcu_command;
+// 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)
- if ( calc3_mcu_status != (1|2|4|8) ) return;
+ 0x3039,0x00A8,0x0000, // move.w $a80000.l, D0
+ 0x4279,0x0020,0xFFFE, // clr.w $20fffe.l
- mcu_command = kaneko16_mcu_ram[calc3_mcu_command_offset + 0];
+ 0x41F9,0x0020,0x0000, // lea $200000.l, A0
+ 0x7000, // moveq #$0, D0
- if (mcu_command == 0) return;
+ 0x43E8,0x01C6, // lea ($1c6,A0), A1
+ 0x7E02, // moveq #$2, D7
+ 0xD059, // add.w (A1)+, D0
+ 0x51CF,0xFFFC, // dbra D7, 207ffe
- logerror("%s : MCU executed command at %04X: %04X\n",
- cpuexec_describe_context(machine),calc3_mcu_command_offset*2,mcu_command);
+ 0x43E9,0x0002, // lea ($2,A1), A1
+ 0x7E04, // moveq #$4, D7
+ 0xD059, // add.w (A1)+, D0
+ 0x51CF,0xFFFC, // dbra D7, 20800a
- switch (mcu_command)
- {
+ 0x4640, // not.w D0
+ 0x5340, // subq.w #1, D0
+ 0x0068,0x0030,0x0216, // ori.w #$30, ($216,A0)
- case 0x00ff:
- {
- static const UINT16 shogwarr_snip_[] = {
- 0x48E7,0xFFFE, // movem.l D0-D7/A0-A6, -(A7)
+ 0xB07A,0x009A, // cmp.w ($9a,PC), D0; ($2080b6)
+ 0x670A, // beq 20802a
- 0x3039,0x00A8,0x0000, // move.w $a80000.l, D0
- 0x4279,0x0020,0xFFFE, // clr.w $20fffe.l
+ 0x0268,0x000F,0x0216, // andi.w #$f, ($216,A0)
+ 0x4268,0x0218, // clr.w ($218,A0)
- 0x41F9,0x0020,0x0000, // lea $200000.l, A0
- 0x7000, // moveq #$0, D0
+ 0x5468,0x0216, // addq.w #2, ($216,A0)
+ 0x42A8,0x030C, // clr.l ($30c,A0)
+ 0x117C,0x0020,0x030C, // move.b #$20, ($30c,A0)
- 0x43E8,0x01C6, // lea ($1c6,A0), A1
- 0x7E02, // moveq #$2, D7
- 0xD059, // add.w (A1)+, D0
- 0x51CF,0xFFFC, // dbra D7, 207ffe
+ 0x3E3C,0x0001, // move.w #$1, D7
- 0x43E9,0x0002, // lea ($2,A1), A1
- 0x7E04, // moveq #$4, D7
- 0xD059, // add.w (A1)+, D0
- 0x51CF,0xFFFC, // dbra D7, 20800a
+ 0x0C68,0x0008,0x0218, // cmpi.w #$8, ($218,A0)
+ 0x6C00,0x0068, // bge 2080ac
- 0x4640, // not.w D0
- 0x5340, // subq.w #1, D0
- 0x0068,0x0030,0x0216, // ori.w #$30, ($216,A0)
+ 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
- 0xB07A,0x009A, // cmp.w ($9a,PC), D0; ($2080b6)
- 0x670A, // beq 20802a
+ 0x5468,0x0218, // addq.w #2, ($218,A0)
+ 0x6000,0x0044, // bra 2080ac
- 0x0268,0x000F,0x0216, // andi.w #$f, ($216,A0)
- 0x4268,0x0218, // clr.w ($218,A0)
+ 0x117C,0x0041,0x0314, // move.b #$41, ($314,A0)
- 0x5468,0x0216, // addq.w #2, ($216,A0)
- 0x42A8,0x030C, // clr.l ($30c,A0)
- 0x117C,0x0020,0x030C, // move.b #$20, ($30c,A0)
+ 0x0C39,0x0001,0x0010,0x2E12,// cmpi.b #$1, $102e12.l
+ 0x6606, // bne 208080
- 0x3E3C,0x0001, // move.w #$1, D7
+ 0x117C,0x0040,0x0314, // move.b #$40, ($314,A0)
- 0x0C68,0x0008,0x0218, // cmpi.w #$8, ($218,A0)
- 0x6C00,0x0068, // bge 2080ac
+ 0x117C,0x000C,0x0315, // move.b #$c, ($315,A0)
+ 0x317C,0x7000,0x0316, // move.w #$7000, ($316,A0)
+ 0x5247, // addq.w #1, D7
- 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
+ 0x0839,0x0001,0x0010,0x2E15,// btst #$1, $102e15.l ; service mode
+ 0x6714, // beq 2080ac
- 0x5468,0x0218, // addq.w #2, ($218,A0)
- 0x6000,0x0044, // bra 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
- 0x117C,0x0041,0x0314, // move.b #$41, ($314,A0)
+ 0x3147,0x030A, // move.w D7, ($30a,A0)
+ 0x4CDF,0x7FFF, // movem.l (A7)+, D0-D7/A0-A6
+ 0x4E73, // rte
+ 0xC747,
+};
- 0x0C39,0x0001,0x0010,0x2E12,// cmpi.b #$1, $102e12.l
- 0x6606, // bne 208080
- 0x117C,0x0040,0x0314, // move.b #$40, ($314,A0)
+static void calc3_mcu_run(running_machine *machine)
+{
+ UINT16 mcu_command;
- 0x117C,0x000C,0x0315, // move.b #$c, ($315,A0)
- 0x317C,0x7000,0x0316, // move.w #$7000, ($316,A0)
- 0x5247, // addq.w #1, D7
+ if ( calc3_mcu_status != (1|2|4|8) ) return;
- 0x0839,0x0001,0x0010,0x2E15,// btst #$1, $102e15.l ; service mode
- 0x6714, // beq 2080ac
+ //calc3_mcu_status = 0;
+
+ mcu_command = kaneko16_mcu_ram[calc3_mcu_command_offset/2 + 0];
- 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
+ if (mcu_command == 0) return;
- 0x3147,0x030A, // move.w D7, ($30a,A0)
- 0x4CDF,0x7FFF, // movem.l (A7)+, D0-D7/A0-A6
- 0x4E73, // rte
- 0xC747,
- };
+ logerror("%s : MCU executed command at %04X: %04X\n",
+ cpuexec_describe_context(machine),calc3_mcu_command_offset,mcu_command);
+
+ switch (mcu_command)
+ {
- 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);
+ case 0x00ff:
+ {
+
+ 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];
+
+ logerror("params %04x %04x %04x %04x %04x %04x %04x %04x %04x\n",
+ param1,param2,param3,param4,param5,param6,param7,param8,param9);
+
+ writeaddress = (param6 << 16) | 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
- writeaddress&=0xffff;
- for(i=0;i<sizeof(shogwarr_snip_) / 2;i++)
- {
- kaneko16_mcu_ram[(writeaddress/2)+i] = shogwarr_snip_[i];
- }
+ // 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 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];
-
+ {
+ 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] = 0x0000;
+ 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
+ //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<sizeof(shogwarr_snip_) / 2;i++)
+ {
+ // printf("writes\n %08x", (writeaddress+i)*2);
+ kaneko16_mcu_ram[(writeaddress/2)+i] = shogwarr_snip_[i];
+ }
+
+ kaneko16_mcu_ram[(writebackaddress/2)+0] = 0x0020;
+ kaneko16_mcu_ram[(writebackaddress/2)+1] = writeaddress;
+
+ // calc3_mcu_command_offset = param3; // where next command will be written?
+ // calc3_mcu_status =0;
+
}
break;
-
case 0x0002:
{
- 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];
+
+
+ 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);
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>>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] = 0x0000;
+ kaneko16_mcu_ram[calc3_mcu_command_offset>>1] = 0x0000;
// execute the command:
-
}
break;