From: David Haywood

Kaneko16 improvements.

This is the one that eliminates the hardcoded table with the initial 
program snippet in, gets it from the rom instead, and generally cleans 
things up.
This commit is contained in:
Aaron Giles 2009-06-25 07:37:44 +00:00
parent 1360627416
commit be41beaf71
2 changed files with 287 additions and 373 deletions

View File

@ -80,6 +80,9 @@ Dip locations verified from manual for:
#include "sound/2151intf.h"
#include "sound/okim6295.h"
UINT16* kaneko16_calc3_fakeram;
static UINT16* kaneko16_mainram;
/***************************************************************************
@ -789,7 +792,7 @@ static WRITE16_HANDLER( shogwarr_oki_bank_w )
static ADDRESS_MAP_START( shogwarr, ADDRESS_SPACE_PROGRAM, 16 )
AM_RANGE(0x000000, 0x03ffff) AM_ROM // ROM
AM_RANGE(0x100000, 0x10ffff) AM_RAM // Work RAM
AM_RANGE(0x100000, 0x10ffff) AM_RAM AM_BASE(&kaneko16_mainram) // Work RAM
AM_RANGE(0x200000, 0x20ffff) AM_READWRITE(SMH_RAM,calc3_mcu_ram_w) AM_BASE(&kaneko16_mcu_ram) // Shared With MCU
AM_RANGE(0x280000, 0x280001) AM_WRITE(calc3_mcu_com0_w)
AM_RANGE(0x290000, 0x290001) AM_WRITE(calc3_mcu_com1_w)
@ -813,6 +816,8 @@ static ADDRESS_MAP_START( shogwarr, ADDRESS_SPACE_PROGRAM, 16 )
AM_RANGE(0xb80006, 0xb80007) AM_READ_PORT("UNK")
AM_RANGE(0xd00000, 0xd00001) AM_NOP // ? (bit 0)
AM_RANGE(0xe00000, 0xe00001) AM_WRITE(shogwarr_oki_bank_w) // Samples Bankswitching
AM_RANGE(0xf00000, 0xffffff) AM_RAM AM_BASE(&kaneko16_calc3_fakeram) // I copy protection data tables here because I don't know where they really go. NOT ON PCB
ADDRESS_MAP_END
@ -1974,7 +1979,18 @@ 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;
// the code for this interupt is provided by the MCU..
//case 0: cpu_set_input_line(device, 4, HOLD_LINE); break;
case 0:
{
// hack, clear this ram address to get into test mode (interrupt would clear it)
if (kaneko16_mainram[0x2dfe/2]==0xff00)
{
kaneko16_mainram[0x2dfe/2]=0x0000;
}
}
}
}
@ -3615,8 +3631,8 @@ 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
- 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
@ -3629,7 +3645,7 @@ OFFSET 4-5 (or after the inline decryption table) - the length of the current bl
OFFSET 6-size - data for thie block
this continues for the number of blocks specified
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.
@ -3638,13 +3654,195 @@ where games specify the same decryption key the table used is the same, I don't
UINT16 calc3_mcu_crc;
/* decryption tables */
/* table 0x00 = not encrypted? */
static UINT8 calc3_table00[64] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
};
/* ok */
static UINT8 calc3_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 */
static UINT8 calc3_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
};
/* partial guessed tables
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
};
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
};
*/
// global so we can use them in the filename when we save out the data (debug..)
static UINT8 calc3_decryption_key_byte;
static UINT8 calc3_unknown;
static UINT8 calc3_mode;
static UINT8 calc3_blocksize_offset;
static UINT16 calc3_dataend;
static UINT16 calc3_database;
// endian safe? you're having a laugh
int calc3_decompress_table(running_machine* machine, int tabnum, UINT8* dstram, int dstoffset)
{
UINT8* rom = memory_region(machine,"cpu1");
UINT8 numregions;
UINT16 length;
int x;
int offset = 0;
numregions = rom[offset+0];
if (tabnum > numregions)
{
printf("CALC3 error, requested table > num tables!\n");
return 0;
}
rom++;
// scan through the linked list to find the start of the requested table info
for (x=0;x<tabnum;x++)
{
UINT8 blocksize_offset = rom[offset+0]; // location of the 'block length'
offset+= blocksize_offset+1;
length = rom[offset+0] | (rom[offset+1]<<8);
offset+=length+2;
}
// we're at the start of the block, get the info about it
{
UINT16 inline_table_base = 0;
UINT16 inline_table_size = 0;
calc3_database = offset;
calc3_blocksize_offset = rom[offset+0]; // location of the 'block length'
calc3_mode = rom[offset+1];
calc3_unknown = rom[offset+2];
calc3_decryption_key_byte = rom[offset+3];
// if blocksize_offset > 3, it appears to specify the encryption table as 'inline' which can be of any size (odd or even) and loops over the bytes to decrypt
// the decryption key specified seems to be ignored?
if (calc3_blocksize_offset>3)
{
inline_table_base = offset+4;
inline_table_size = calc3_blocksize_offset-3;
}
offset+= calc3_blocksize_offset+1;
length = rom[offset+0] | (rom[offset+1]<<8);
offset+=2;
if (inline_table_size)
{
printf("Block %02x Found Base %04x - Inline Encryption (size %02x) - Mode? %02x Unknown %02x Key (unused?) %02x Length %04x\n", tabnum, calc3_database, inline_table_size, calc3_mode, calc3_unknown, calc3_decryption_key_byte, length);
}
else
{
printf("Block %02x Found Base %04x - Mode? %02x Unknown %02x Key (unused?) %02x Length %04x\n", tabnum, calc3_database, calc3_mode, calc3_unknown, calc3_decryption_key_byte, length);
}
// copy + decrypt the table to the specified memory area
if (dstram)
{
int i;
if (length==0x00)
{
// shogwarr does this with 'mode' as 0x08, which probably has some special meaning
//printf("CALC3: requested 0 length table!\n");
}
if (inline_table_size)
{
for (i=0;i<length;i++)
{
UINT8 dat = rom[offset+i];
dat -= rom[inline_table_base + (i%inline_table_size)];
dstram[(dstoffset+i)^1] = dat;
}
}
else
{
UINT8* table = calc3_table00;
// 0x00 seems to have no 'encryption'
if (calc3_decryption_key_byte == 0x00) table = calc3_table00;
// currently only handle 2 of the formats :-(
if (calc3_decryption_key_byte == 0x01) table = calc3_table01;
if (calc3_decryption_key_byte == 0x15) table = calc3_table15;
for (i=0;i<length;i++)
{
UINT8 dat = rom[offset+i];
dat -= table[i&0x3f];
dstram[(dstoffset+i)^1] = dat;
}
}
}
calc3_dataend = offset+length+1;
}
//printf("data base %04x data end %04x\n", calc3_database, calc3_dataend);
return length;
}
static UINT8 calc3_decryption_key_byte;
static UINT8 calc3_unknown;
static UINT8 calc3_mode;
static UINT8 calc3_blocksize_offset;
DRIVER_INIT( calc3 )
{
UINT8* rom = memory_region(machine,"cpu1");
UINT8 numregions;
int x;
int offset = 0;
UINT8 numregions;
calc3_mcu_crc = 0;
for (x=0;x<0x20000;x++)
@ -3652,189 +3850,49 @@ DRIVER_INIT( calc3 )
calc3_mcu_crc+=rom[x];
}
printf("crc %04x\n",calc3_mcu_crc);
numregions = rom[offset+0];
rom++;
numregions = rom[0];
for (x=0;x<numregions;x++)
{
UINT8* tmpdstram = malloc(0x2000);
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)
memset(tmpdstram, 0x00,0x2000);
length = calc3_decompress_table(machine, x, tmpdstram, 0);
// dump to file
if (length)
{
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]);
FILE *fp;
char filename[256];
if (calc3_blocksize_offset==3)
{
sprintf(filename,"data_%s_table_%04x k%02x m%02x u%02x length %04x",
machine->gamedrv->name,
x, calc3_decryption_key_byte, calc3_mode, calc3_unknown, length);
}
}
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)
else
{
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",
sprintf(filename,"data_%s_table_%04x k%02x (use indirect size %02x) m%02x u%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);
}
}
x, calc3_decryption_key_byte, calc3_blocksize_offset-3, calc3_mode, calc3_unknown, length);
}
}
fp=fopen(filename, "w+b");
if (fp)
{
fwrite(tmpdstram, length, 1, fp);
fclose(fp);
}
}
offset+=length;
free(tmpdstram);
}
// there is also a 0x1000 block of data at the end.. same on both games, maybe it's related to the decryption tables??
// the calc3_dataend points to the data after the last block processed, as we process all the blocks in the above loop, we assume this points
// to that extra block of data
// dump out the 0x1000 sized block at the end
{
FILE *fp;
@ -3846,7 +3904,7 @@ DRIVER_INIT( calc3 )
fp=fopen(filename, "w+b");
if (fp)
{
fwrite(&rom[offset], 0x1000, 1, fp);
fwrite(&rom[calc3_dataend], 0x1000, 1, fp);
fclose(fp);
}
}

View File

@ -313,80 +313,9 @@ CALC3_MCU_COM_W(3)
*/
UINT32 writeaddress;
extern UINT16 calc3_mcu_crc;
extern UINT16* kaneko16_calc3_fakeram;
// 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,
};
extern int calc3_decompress_table(running_machine* machine, int tabnum, UINT8* dstram, int dstoffset);
static void calc3_mcu_run(running_machine *machine)
@ -396,7 +325,7 @@ static void calc3_mcu_run(running_machine *machine)
if ( calc3_mcu_status != (1|2|4|8) ) return;
//calc3_mcu_status = 0;
mcu_command = kaneko16_mcu_ram[calc3_mcu_command_offset/2 + 0];
if (mcu_command == 0) return;
@ -404,13 +333,13 @@ static void calc3_mcu_run(running_machine *machine)
logerror("%s : MCU executed command at %04X: %04X\n",
cpuexec_describe_context(machine),calc3_mcu_command_offset,mcu_command);
switch (mcu_command)
{
case 0x00ff:
{
int param1 = kaneko16_mcu_ram[(0>>1) + 1];
int param2 = kaneko16_mcu_ram[(0>>1) + 2];
@ -443,6 +372,7 @@ static void calc3_mcu_run(running_machine *machine)
// 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;
@ -450,133 +380,59 @@ static void calc3_mcu_run(running_machine *machine)
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 0x0002:
{
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:
case 0x0004:
case 0x0005:
case 0x0006:
case 0x0007:
// 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
//
{
int num_transfers = mcu_command;
int i;
logerror("Calc3 transfer request, %d transfers\n", num_transfers);
for (i=0;i<num_transfers;i++)
{
int param1 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 1 + (2*i)];
int param2 = kaneko16_mcu_ram[(calc3_mcu_command_offset>>1) + 2 + (2*i)];
UINT8 commandtabl = (param1&0xff00) >> 8;
UINT16 commandaddr = (param1&0x00ff) | (param2&0xff00);
UINT32 fakeoffs;
logerror("transfer %d table %02x writeback address %04x\n", i, commandtabl, commandaddr);
// the data SHOULD be written somewhere to main ram, probably related to the writeaddress set in command 0xff
// but I'm not sure how, for now write it back to a FAKE region instead
fakeoffs = 0x1e00*commandtabl;
calc3_decompress_table(machine, commandtabl, (UINT8*)kaneko16_calc3_fakeram, fakeoffs);
// write back WHERE we wrote the data to the address specified so that the code can jump to it etc.
fakeoffs+=0xf00000;
fakeoffs+=2;// the first 2 bytes don't seem to be the offset it expects to jump to..
printf("writing back fake address %08x to %08x\n", fakeoffs, commandaddr);
kaneko16_mcu_ram[(commandaddr>>1)+0] = (fakeoffs>>16)&0xffff;
kaneko16_mcu_ram[(commandaddr>>1)+1] = (fakeoffs&0xffff);
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:
}
// reset 'number of commands' to 0 to indicate processing complete to the main cpu.
kaneko16_mcu_ram[calc3_mcu_command_offset>>1] = 0x0000;;
}
break;
}
}