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.
This commit is contained in:
Aaron Giles 2009-06-18 03:53:38 +00:00
parent d220998fed
commit 069747cca3
2 changed files with 474 additions and 153 deletions

View File

@ -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 )

View File

@ -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<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 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];
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:
// 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
}
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] = 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;