summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author David Haywood <mamehaze@users.noreply.github.com>2015-01-20 16:53:09 +0000
committer David Haywood <mamehaze@users.noreply.github.com>2015-01-20 16:53:09 +0000
commitcd61a2736d8149f6640a5756b83caae55b7b07ae (patch)
tree75c05d2d3710486c4f0a4ee10410cb09a947601e
parentf8096960a9c74bb78c093421ff61096d34705c1c (diff)
some changes to the 315-5881 to allow basic multiple stream support, astrass needs this - we were ignoring a size value in the header, when the 'size' is reached the stream ends, and a new header needs to be read.
I need to review the changes w/regards the naomi code later (don't have the material to test here) also this will need looking at w/regards compressed streams, as they can be mixed. the data decrypted from astrass is now a 100% match for the data that was extracted from the saturn version.
-rw-r--r--src/mame/machine/315-5881_crypt.c113
-rw-r--r--src/mame/machine/315-5881_crypt.h4
2 files changed, 71 insertions, 46 deletions
diff --git a/src/mame/machine/315-5881_crypt.c b/src/mame/machine/315-5881_crypt.c
index bedbb2b6f09..0d9ee7cfc60 100644
--- a/src/mame/machine/315-5881_crypt.c
+++ b/src/mame/machine/315-5881_crypt.c
@@ -529,109 +529,110 @@ of the function. Even so, it would still be pretty slow, so caching techniques c
UINT16 sega_315_5881_crypt_device::block_decrypt(UINT32 game_key, UINT16 sequence_key, UINT16 counter, UINT16 data)
{
int j;
- int aux,aux2;
- int A,B;
+ int aux, aux2;
+ int A, B;
int middle_result;
UINT32 fn1_subkeys[4];
UINT32 fn2_subkeys[4];
/* Game-key scheduling; this could be done just once per game at initialization time */
- memset(fn1_subkeys,0,sizeof(UINT32)*4);
- memset(fn2_subkeys,0,sizeof(UINT32)*4);
-
- for (j=0; j<38; ++j) {
- if (BIT(game_key, fn1_game_key_scheduling[j][0])!=0) {
- aux = fn1_game_key_scheduling[j][1]%24;
- aux2 = fn1_game_key_scheduling[j][1]/24;
- fn1_subkeys[aux2] ^= (1<<aux);
+ memset(fn1_subkeys, 0, sizeof(UINT32) * 4);
+ memset(fn2_subkeys, 0, sizeof(UINT32) * 4);
+
+ for (j = 0; j < 38; ++j) {
+ if (BIT(game_key, fn1_game_key_scheduling[j][0]) != 0) {
+ aux = fn1_game_key_scheduling[j][1] % 24;
+ aux2 = fn1_game_key_scheduling[j][1] / 24;
+ fn1_subkeys[aux2] ^= (1 << aux);
}
}
- for (j=0; j<34; ++j) {
- if (BIT(game_key, fn2_game_key_scheduling[j][0])!=0) {
- aux = fn2_game_key_scheduling[j][1]%24;
- aux2 = fn2_game_key_scheduling[j][1]/24;
- fn2_subkeys[aux2] ^= (1<<aux);
+ for (j = 0; j < 34; ++j) {
+ if (BIT(game_key, fn2_game_key_scheduling[j][0]) != 0) {
+ aux = fn2_game_key_scheduling[j][1] % 24;
+ aux2 = fn2_game_key_scheduling[j][1] / 24;
+ fn2_subkeys[aux2] ^= (1 << aux);
}
}
/********************************************************/
/* Sequence-key scheduling; this could be done just once per decryption run */
- for (j=0; j<20; ++j) {
- if (BIT(sequence_key,fn1_sequence_key_scheduling[j][0])!=0) {
- aux = fn1_sequence_key_scheduling[j][1]%24;
- aux2 = fn1_sequence_key_scheduling[j][1]/24;
- fn1_subkeys[aux2] ^= (1<<aux);
+ for (j = 0; j < 20; ++j) {
+ if (BIT(sequence_key, fn1_sequence_key_scheduling[j][0]) != 0) {
+ aux = fn1_sequence_key_scheduling[j][1] % 24;
+ aux2 = fn1_sequence_key_scheduling[j][1] / 24;
+ fn1_subkeys[aux2] ^= (1 << aux);
}
}
- for (j=0; j<16; ++j) {
- if (BIT(sequence_key,j)!=0) {
- aux = fn2_sequence_key_scheduling[j]%24;
- aux2 = fn2_sequence_key_scheduling[j]/24;
- fn2_subkeys[aux2] ^= (1<<aux);
+ for (j = 0; j < 16; ++j) {
+ if (BIT(sequence_key, j) != 0) {
+ aux = fn2_sequence_key_scheduling[j] % 24;
+ aux2 = fn2_sequence_key_scheduling[j] / 24;
+ fn2_subkeys[aux2] ^= (1 << aux);
}
}
// subkeys bits 10 & 41
- fn2_subkeys[0] ^= (BIT(sequence_key,2)<<10);
- fn2_subkeys[1] ^= (BIT(sequence_key,4)<<17);
+ fn2_subkeys[0] ^= (BIT(sequence_key, 2) << 10);
+ fn2_subkeys[1] ^= (BIT(sequence_key, 4) << 17);
/**************************************************************/
// First Feistel Network
- aux = BITSWAP16(counter,5,12,14,13,9,3,6,4, 8,1,15,11,0,7,10,2);
+ aux = BITSWAP16(counter, 5, 12, 14, 13, 9, 3, 6, 4, 8, 1, 15, 11, 0, 7, 10, 2);
// 1st round
B = aux >> 8;
- A = (aux & 0xff) ^ feistel_function(B,fn1_sboxes[0],fn1_subkeys[0]);
+ A = (aux & 0xff) ^ feistel_function(B, fn1_sboxes[0], fn1_subkeys[0]);
// 2nd round
- B = B ^ feistel_function(A,fn1_sboxes[1],fn1_subkeys[1]);
+ B = B ^ feistel_function(A, fn1_sboxes[1], fn1_subkeys[1]);
// 3rd round
- A = A ^ feistel_function(B,fn1_sboxes[2],fn1_subkeys[2]);
+ A = A ^ feistel_function(B, fn1_sboxes[2], fn1_subkeys[2]);
// 4th round
- B = B ^ feistel_function(A,fn1_sboxes[3],fn1_subkeys[3]);
+ B = B ^ feistel_function(A, fn1_sboxes[3], fn1_subkeys[3]);
- middle_result = (B<<8)|A;
+ middle_result = (B << 8) | A;
/* Middle-result-key sheduling */
- for (j=0; j<16; ++j) {
- if (BIT(middle_result,j)!=0) {
- aux = fn2_middle_result_scheduling[j]%24;
- aux2 = fn2_middle_result_scheduling[j]/24;
- fn2_subkeys[aux2] ^= (1<<aux);
+ for (j = 0; j < 16; ++j) {
+ if (BIT(middle_result, j) != 0) {
+ aux = fn2_middle_result_scheduling[j] % 24;
+ aux2 = fn2_middle_result_scheduling[j] / 24;
+ fn2_subkeys[aux2] ^= (1 << aux);
}
}
/*********************/
// Second Feistel Network
- aux = BITSWAP16(data,14,3,8,12,13,7,15,4, 6,2,9,5,11,0,1,10);
+ aux = BITSWAP16(data, 14, 3, 8, 12, 13, 7, 15, 4, 6, 2, 9, 5, 11, 0, 1, 10);
// 1st round
B = aux >> 8;
- A = (aux & 0xff) ^ feistel_function(B,fn2_sboxes[0],fn2_subkeys[0]);
+ A = (aux & 0xff) ^ feistel_function(B, fn2_sboxes[0], fn2_subkeys[0]);
// 2nd round
- B = B ^ feistel_function(A,fn2_sboxes[1],fn2_subkeys[1]);
+ B = B ^ feistel_function(A, fn2_sboxes[1], fn2_subkeys[1]);
// 3rd round
- A = A ^ feistel_function(B,fn2_sboxes[2],fn2_subkeys[2]);
+ A = A ^ feistel_function(B, fn2_sboxes[2], fn2_subkeys[2]);
// 4th round
- B = B ^ feistel_function(A,fn2_sboxes[3],fn2_subkeys[3]);
+ B = B ^ feistel_function(A, fn2_sboxes[3], fn2_subkeys[3]);
- aux = (B<<8)|A;
+ aux = (B << 8) | A;
- aux = BITSWAP16(aux,15,7,6,14,13,12,5,4, 3,2,11,10,9,1,0,8);
+ aux = BITSWAP16(aux, 15, 7, 6, 14, 13, 12, 5, 4, 3, 2, 11, 10, 9, 1, 0, 8);
return aux;
}
+
UINT16 sega_315_5881_crypt_device::get_decrypted_16()
{
UINT16 enc;
@@ -643,20 +644,34 @@ UINT16 sega_315_5881_crypt_device::get_decrypted_16()
dec_hist = dec;
prot_cur_address ++;
+
return res;
}
+
void sega_315_5881_crypt_device::enc_start()
{
+ dec_hist = 0; // seems to be needed by astrass at least otherwise any call after the first one will be influenced by the one before it.
+ block_pos = 0;
buffer_pos = BUFFER_SIZE;
dec_header = get_decrypted_16() << 16;
dec_header |= get_decrypted_16();
+ // the lower header bits are 2 values that multiply together to get the current stream length
+ // in astrass the first block is 0xffff (for a 0x10000 block) followed by 0x3f3f (for a 0x1000 block)
+ // etc. after each block a new header must be read, it looks like compressed and uncompressed blocks
+ // can be mixed like this, I don't know if the length is src length of decompressed length.
+ int blockx = ((dec_header & 0x00ff) >> 0) + 1;
+ int blocky = ((dec_header & 0xff00) >> 8) + 1;
+ block_size = blockx * blocky;
+
if(dec_header & FLAG_COMPRESSED) {
line_buffer_size = dec_header & FLAG_LINE_SIZE_512 ? 512 : 256;
line_buffer_pos = line_buffer_size;
buffer_bit = 7;
}
+
+// printf("header %08x\n", dec_header);
enc_ready = true;
}
@@ -667,6 +682,14 @@ void sega_315_5881_crypt_device::enc_fill()
UINT16 val = get_decrypted_16();
buffer[i] = val;
buffer[i+1] = val >> 8;
+ block_pos+=2;
+ if (block_pos == block_size)
+ {
+ // if we reach the size specified we need to read a new header
+ // todo: how should this work with compressed blocks??
+
+ enc_start();
+ }
}
buffer_pos = 0;
}
diff --git a/src/mame/machine/315-5881_crypt.h b/src/mame/machine/315-5881_crypt.h
index 6b73ffd0700..46862165342 100644
--- a/src/mame/machine/315-5881_crypt.h
+++ b/src/mame/machine/315-5881_crypt.h
@@ -40,7 +40,7 @@ protected:
private:
enum {
- BUFFER_SIZE = 32768, LINE_SIZE = 512,
+ BUFFER_SIZE = 32768*8, LINE_SIZE = 512*8,
FLAG_COMPRESSED = 0x10000, FLAG_LINE_SIZE_512 = 0x20000
};
@@ -54,6 +54,8 @@ private:
bool enc_ready;
int buffer_pos, line_buffer_pos, line_buffer_size, buffer_bit;
+ int block_size;
+ int block_pos;
struct sbox {
UINT8 table[64];