a bit more readable (nw)

This commit is contained in:
Vas Crabb 2017-02-10 18:02:51 +11:00
parent dddf09d26c
commit 17a597434a
3 changed files with 141 additions and 129 deletions

View File

@ -248,15 +248,22 @@ template <typename T, typename U, typename... V> constexpr T bitswap(T val, U b,
return (BIT(val, b) << sizeof...(c)) | bitswap(val, c...);
}
template <unsigned B, typename T, typename... U> T bitswap(T val, U... b)
{
static_assert(sizeof...(b) == B, "wrong number of bits");
static_assert((sizeof(std::remove_reference_t<T>) * 8) >= B, "return type too small for result");
return bitswap(val, b...);
}
// explicit versions that check number of bit position arguments
template <typename T, typename... U> constexpr T BITSWAP8(T val, U... b) { static_assert(sizeof...(b) == 8U, "wrong number of bits"); return bitswap(val, b...); }
template <typename T, typename... U> constexpr T BITSWAP16(T val, U... b) { static_assert(sizeof...(b) == 16U, "wrong number of bits"); return bitswap(val, b...); }
template <typename T, typename... U> constexpr T BITSWAP24(T val, U... b) { static_assert(sizeof...(b) == 24U, "wrong number of bits"); return bitswap(val, b...); }
template <typename T, typename... U> constexpr T BITSWAP32(T val, U... b) { static_assert(sizeof...(b) == 32U, "wrong number of bits"); return bitswap(val, b...); }
template <typename T, typename... U> constexpr T BITSWAP40(T val, U... b) { static_assert(sizeof...(b) == 40U, "wrong number of bits"); return bitswap(val, b...); }
template <typename T, typename... U> constexpr T BITSWAP48(T val, U... b) { static_assert(sizeof...(b) == 48U, "wrong number of bits"); return bitswap(val, b...); }
template <typename T, typename... U> constexpr T BITSWAP56(T val, U... b) { static_assert(sizeof...(b) == 56U, "wrong number of bits"); return bitswap(val, b...); }
template <typename T, typename... U> constexpr T BITSWAP64(T val, U... b) { static_assert(sizeof...(b) == 64U, "wrong number of bits"); return bitswap(val, b...); }
template <typename T, typename... U> constexpr T BITSWAP8(T val, U... b) { return bitswap<8U>(val, b...); }
template <typename T, typename... U> constexpr T BITSWAP16(T val, U... b) { return bitswap<16U>(val, b...); }
template <typename T, typename... U> constexpr T BITSWAP24(T val, U... b) { return bitswap<24U>(val, b...); }
template <typename T, typename... U> constexpr T BITSWAP32(T val, U... b) { return bitswap<32U>(val, b...); }
template <typename T, typename... U> constexpr T BITSWAP40(T val, U... b) { return bitswap<40U>(val, b...); }
template <typename T, typename... U> constexpr T BITSWAP48(T val, U... b) { return bitswap<48U>(val, b...); }
template <typename T, typename... U> constexpr T BITSWAP56(T val, U... b) { return bitswap<56U>(val, b...); }
template <typename T, typename... U> constexpr T BITSWAP64(T val, U... b) { return bitswap<64U>(val, b...); }

View File

@ -30,9 +30,9 @@ The LCG is the same that was used to generate the FD1094 keys.
Note that the algorithm skips the special value that would instruct the CPU to
not decrypt at that address.
void generate_key(uint8_t *key, int seed, int upper_bound)
void generate_key(uint8_t (&key)[0x2000], uint32_t seed, unsigned upper_bound)
{
int i;
unsigned i;
for (i = 0; i < upper_bound; ++i)
{
@ -40,16 +40,17 @@ void generate_key(uint8_t *key, int seed, int upper_bound)
do
{
seed = seed * 0x29;
seed *= 0x29;
seed += seed << 16;
byteval = (~seed >> 16) & 0xff;
} while (byteval == 0xff);
}
while (byteval == 0xff);
key[i] = byteval;
}
for (; i < 0x2000; ++i)
for ( ; i < 0x2000; ++i)
key[i] = 0xff;
}
@ -78,8 +79,12 @@ CPU # Game Notes Seed Upper Limit
#include "mc8123.h"
namespace {
static int decrypt_type0(int val,int param,int swap)
template <typename T> constexpr u8 BITS(T b) { return u8(1) << b; }
template <typename T, typename... U> constexpr u8 BITS(T b, U... c) { return (u8(1) << b) | BITS(c...); }
u8 decrypt_type0(u8 val, u8 param, unsigned swap)
{
if (swap == 0) val = BITSWAP8(val,7,5,3,1,2,0,6,4);
if (swap == 1) val = BITSWAP8(val,5,3,7,2,1,0,4,6);
@ -87,23 +92,23 @@ static int decrypt_type0(int val,int param,int swap)
if (swap == 3) val = BITSWAP8(val,0,7,3,2,6,4,1,5);
if (BIT(param,3) && BIT(val,7))
val ^= (1<<5)|(1<<3)|(1<<0);
val ^= BITS(5,3,0);
if (BIT(param,2) && BIT(val,6))
val ^= (1<<7)|(1<<2)|(1<<1);
val ^= BITS(7,2,1);
if (BIT(val,6)) val ^= (1<<7);
if (BIT(val,6)) val ^= BITS(7);
if (BIT(param,1) && BIT(val,7))
val ^= (1<<6);
val ^= BITS(6);
if (BIT(val,2)) val ^= (1<<5)|(1<<0);
if (BIT(val,2)) val ^= BITS(5,0);
val ^= (1<<4)|(1<<3)|(1<<1);
val ^= BITS(4,3,1);
if (BIT(param,2)) val ^= (1<<5)|(1<<2)|(1<<0);
if (BIT(param,1)) val ^= (1<<7)|(1<<6);
if (BIT(param,0)) val ^= (1<<5)|(1<<0);
if (BIT(param,2)) val ^= BITS(5,2,0);
if (BIT(param,1)) val ^= BITS(7,6);
if (BIT(param,0)) val ^= BITS(5,0);
if (BIT(param,0)) val = BITSWAP8(val,7,6,5,1,4,3,2,0);
@ -111,7 +116,7 @@ static int decrypt_type0(int val,int param,int swap)
}
static int decrypt_type1a(int val,int param,int swap)
u8 decrypt_type1a(u8 val, u8 param, unsigned swap)
{
if (swap == 0) val = BITSWAP8(val,4,2,6,5,3,7,1,0);
if (swap == 1) val = BITSWAP8(val,6,0,5,4,3,2,1,7);
@ -120,26 +125,26 @@ static int decrypt_type1a(int val,int param,int swap)
if (BIT(param,2)) val = BITSWAP8(val,7,6,1,5,3,2,4,0);
if (BIT(val,1)) val ^= (1<<0);
if (BIT(val,6)) val ^= (1<<3);
if (BIT(val,7)) val ^= (1<<6)|(1<<3);
if (BIT(val,2)) val ^= (1<<6)|(1<<3)|(1<<1);
if (BIT(val,4)) val ^= (1<<7)|(1<<6)|(1<<2);
if (BIT(val,1)) val ^= BITS(0);
if (BIT(val,6)) val ^= BITS(3);
if (BIT(val,7)) val ^= BITS(6,3);
if (BIT(val,2)) val ^= BITS(6,3,1);
if (BIT(val,4)) val ^= BITS(7,6,2);
if (BIT(val,7) ^ BIT(val,2))
val ^= (1<<4);
val ^= BITS(4);
val ^= (1<<6)|(1<<3)|(1<<1)|(1<<0);
val ^= BITS(6,3,1,0);
if (BIT(param,3)) val ^= (1<<7)|(1<<2);
if (BIT(param,1)) val ^= (1<<6)|(1<<3);
if (BIT(param,3)) val ^= BITS(7,2);
if (BIT(param,1)) val ^= BITS(6,3);
if (BIT(param,0)) val = BITSWAP8(val,7,6,1,4,3,2,5,0);
return val;
}
static int decrypt_type1b(int val,int param,int swap)
u8 decrypt_type1b(u8 val, u8 param, unsigned swap)
{
if (swap == 0) val = BITSWAP8(val,1,0,3,2,5,6,4,7);
if (swap == 1) val = BITSWAP8(val,2,0,5,1,7,4,6,3);
@ -147,27 +152,27 @@ static int decrypt_type1b(int val,int param,int swap)
if (swap == 3) val = BITSWAP8(val,7,1,3,6,0,2,5,4);
if (BIT(val,2) && BIT(val,0))
val ^= (1<<7)|(1<<4);
val ^= BITS(7,4);
if (BIT(val,7)) val ^= (1<<2);
if (BIT(val,5)) val ^= (1<<7)|(1<<2);
if (BIT(val,1)) val ^= (1<<5);
if (BIT(val,6)) val ^= (1<<1);
if (BIT(val,4)) val ^= (1<<6)|(1<<5);
if (BIT(val,0)) val ^= (1<<6)|(1<<2)|(1<<1);
if (BIT(val,3)) val ^= (1<<7)|(1<<6)|(1<<2)|(1<<1)|(1<<0);
if (BIT(val,7)) val ^= BITS(2);
if (BIT(val,5)) val ^= BITS(7,2);
if (BIT(val,1)) val ^= BITS(5);
if (BIT(val,6)) val ^= BITS(1);
if (BIT(val,4)) val ^= BITS(6,5);
if (BIT(val,0)) val ^= BITS(6,2,1);
if (BIT(val,3)) val ^= BITS(7,6,2,1,0);
val ^= (1<<6)|(1<<4)|(1<<0);
val ^= BITS(6,4,0);
if (BIT(param,3)) val ^= (1<<4)|(1<<1);
if (BIT(param,2)) val ^= (1<<7)|(1<<6)|(1<<3)|(1<<0);
if (BIT(param,1)) val ^= (1<<4)|(1<<3);
if (BIT(param,0)) val ^= (1<<6)|(1<<2)|(1<<1)|(1<<0);
if (BIT(param,3)) val ^= BITS(4,1);
if (BIT(param,2)) val ^= BITS(7,6,3,0);
if (BIT(param,1)) val ^= BITS(4,3);
if (BIT(param,0)) val ^= BITS(6,2,1,0);
return val;
}
static int decrypt_type2a(int val,int param,int swap)
u8 decrypt_type2a(u8 val, u8 param, unsigned swap)
{
if (swap == 0) val = BITSWAP8(val,0,1,4,3,5,6,2,7);
if (swap == 1) val = BITSWAP8(val,6,3,0,5,7,4,1,2);
@ -177,15 +182,15 @@ static int decrypt_type2a(int val,int param,int swap)
if (BIT(val,3) || (BIT(param,1) && BIT(val,2)))
val = BITSWAP8(val,6,0,7,4,3,2,1,5);
if (BIT(val,5)) val ^= (1<<7);
if (BIT(val,6)) val ^= (1<<5);
if (BIT(val,0)) val ^= (1<<6);
if (BIT(val,4)) val ^= (1<<3)|(1<<0);
if (BIT(val,1)) val ^= (1<<2);
if (BIT(val,5)) val ^= BITS(7);
if (BIT(val,6)) val ^= BITS(5);
if (BIT(val,0)) val ^= BITS(6);
if (BIT(val,4)) val ^= BITS(3,0);
if (BIT(val,1)) val ^= BITS(2);
val ^= (1<<7)|(1<<6)|(1<<5)|(1<<4)|(1<<1);
val ^= BITS(7,6,5,4,1);
if (BIT(param,2)) val ^= (1<<4)|(1<<3)|(1<<2)|(1<<1)|(1<<0);
if (BIT(param,2)) val ^= BITS(4,3,2,1,0);
if (BIT(param,3))
{
@ -194,16 +199,15 @@ static int decrypt_type2a(int val,int param,int swap)
else
val = BITSWAP8(val,7,6,5,1,2,4,3,0);
}
else
else if (BIT(param,0))
{
if (BIT(param,0))
val = BITSWAP8(val,7,6,5,2,1,3,4,0);
val = BITSWAP8(val,7,6,5,2,1,3,4,0);
}
return val;
}
static int decrypt_type2b(int val,int param,int swap)
u8 decrypt_type2b(u8 val, u8 param, unsigned swap)
{
// only 0x20 possible encryptions for this method - all others have 0x40
// this happens because BIT(param,2) cancels the other three
@ -214,106 +218,106 @@ static int decrypt_type2b(int val,int param,int swap)
if (swap == 3) val = BITSWAP8(val,5,2,3,0,4,7,6,1);
if (BIT(val,7) && BIT(val,3))
val ^= (1<<6)|(1<<4)|(1<<0);
val ^= BITS(6,4,0);
if (BIT(val,7)) val ^= (1<<2);
if (BIT(val,5)) val ^= (1<<7)|(1<<3);
if (BIT(val,1)) val ^= (1<<5);
if (BIT(val,4)) val ^= (1<<7)|(1<<5)|(1<<3)|(1<<1);
if (BIT(val,7)) val ^= BITS(2);
if (BIT(val,5)) val ^= BITS(7,3);
if (BIT(val,1)) val ^= BITS(5);
if (BIT(val,4)) val ^= BITS(7,5,3,1);
if (BIT(val,7) && BIT(val,5))
val ^= (1<<4)|(1<<0);
val ^= BITS(4,0);
if (BIT(val,5) && BIT(val,1))
val ^= (1<<4)|(1<<0);
val ^= BITS(4,0);
if (BIT(val,6)) val ^= (1<<7)|(1<<5);
if (BIT(val,3)) val ^= (1<<7)|(1<<6)|(1<<5)|(1<<1);
if (BIT(val,2)) val ^= (1<<3)|(1<<1);
if (BIT(val,6)) val ^= BITS(7,5);
if (BIT(val,3)) val ^= BITS(7,6,5,1);
if (BIT(val,2)) val ^= BITS(3,1);
val ^= (1<<7)|(1<<3)|(1<<2)|(1<<1);
val ^= BITS(7,3,2,1);
if (BIT(param,3)) val ^= (1<<6)|(1<<3)|(1<<1);
if (BIT(param,2)) val ^= (1<<7)|(1<<6)|(1<<5)|(1<<3)|(1<<2)|(1<<1); // same as the other three combined
if (BIT(param,1)) val ^= (1<<7);
if (BIT(param,0)) val ^= (1<<5)|(1<<2);
if (BIT(param,3)) val ^= BITS(6,3,1);
if (BIT(param,2)) val ^= BITS(7,6,5,3,2,1); // same as the other three combined
if (BIT(param,1)) val ^= BITS(7);
if (BIT(param,0)) val ^= BITS(5,2);
return val;
}
static int decrypt_type3a(int val,int param,int swap)
u8 decrypt_type3a(u8 val, u8 param, unsigned swap)
{
if (swap == 0) val = BITSWAP8(val,5,3,1,7,0,2,6,4);
if (swap == 1) val = BITSWAP8(val,3,1,2,5,4,7,0,6);
if (swap == 2) val = BITSWAP8(val,5,6,1,2,7,0,4,3);
if (swap == 3) val = BITSWAP8(val,5,6,7,0,4,2,1,3);
if (BIT(val,2)) val ^= (1<<7)|(1<<5)|(1<<4);
if (BIT(val,3)) val ^= (1<<0);
if (BIT(val,2)) val ^= BITS(7,5,4);
if (BIT(val,3)) val ^= BITS(0);
if (BIT(param,0)) val = BITSWAP8(val,7,2,5,4,3,1,0,6);
if (BIT(val,1)) val ^= (1<<6)|(1<<0);
if (BIT(val,3)) val ^= (1<<4)|(1<<2)|(1<<1);
if (BIT(val,1)) val ^= BITS(6,0);
if (BIT(val,3)) val ^= BITS(4,2,1);
if (BIT(param,3)) val ^= (1<<4)|(1<<3);
if (BIT(param,3)) val ^= BITS(4,3);
if (BIT(val,3)) val = BITSWAP8(val,5,6,7,4,3,2,1,0);
if (BIT(val,5)) val ^= (1<<2)|(1<<1);
if (BIT(val,5)) val ^= BITS(2,1);
val ^= (1<<6)|(1<<5)|(1<<4)|(1<<3);
val ^= BITS(6,5,4,3);
if (BIT(param,2)) val ^= (1<<7);
if (BIT(param,1)) val ^= (1<<4);
if (BIT(param,0)) val ^= (1<<0);
if (BIT(param,2)) val ^= BITS(7);
if (BIT(param,1)) val ^= BITS(4);
if (BIT(param,0)) val ^= BITS(0);
return val;
}
static int decrypt_type3b(int val,int param,int swap)
u8 decrypt_type3b(u8 val, u8 param, unsigned swap)
{
if (swap == 0) val = BITSWAP8(val,3,7,5,4,0,6,2,1);
if (swap == 1) val = BITSWAP8(val,7,5,4,6,1,2,0,3);
if (swap == 2) val = BITSWAP8(val,7,4,3,0,5,1,6,2);
if (swap == 3) val = BITSWAP8(val,2,6,4,1,3,7,0,5);
if (BIT(val,2)) val ^= (1<<7);
if (BIT(val,2)) val ^= BITS(7);
if (BIT(val,7)) val = BITSWAP8(val,7,6,3,4,5,2,1,0);
if (BIT(param,3)) val ^= (1<<7);
if (BIT(param,3)) val ^= BITS(7);
if (BIT(val,4)) val ^= (1<<6);
if (BIT(val,1)) val ^= (1<<6)|(1<<4)|(1<<2);
if (BIT(val,4)) val ^= BITS(6);
if (BIT(val,1)) val ^= BITS(6,4,2);
if (BIT(val,7) && BIT(val,6))
val ^= (1<<1);
val ^= BITS(1);
if (BIT(val,7)) val ^= (1<<1);
if (BIT(val,7)) val ^= BITS(1);
if (BIT(param,3)) val ^= (1<<7);
if (BIT(param,2)) val ^= (1<<0);
if (BIT(param,3)) val ^= BITS(7);
if (BIT(param,2)) val ^= BITS(0);
if (BIT(param,3)) val = BITSWAP8(val,4,6,3,2,5,0,1,7);
if (BIT(val,4)) val ^= (1<<1);
if (BIT(val,5)) val ^= (1<<4);
if (BIT(val,7)) val ^= (1<<2);
if (BIT(val,4)) val ^= BITS(1);
if (BIT(val,5)) val ^= BITS(4);
if (BIT(val,7)) val ^= BITS(2);
val ^= (1<<5)|(1<<3)|(1<<2);
val ^= BITS(5,3,2);
if (BIT(param,1)) val ^= (1<<7);
if (BIT(param,0)) val ^= (1<<3);
if (BIT(param,1)) val ^= BITS(7);
if (BIT(param,0)) val ^= BITS(3);
return val;
}
static int decrypt(int val, int key, int opcode)
u8 decrypt(u8 val, u8 key, bool opcode)
{
int type = 0;
int swap = 0;
int param = 0;
unsigned type = 0;
unsigned swap = 0;
u8 param = 0;
key ^= 0xff;
@ -348,46 +352,47 @@ static int decrypt(int val, int key, int opcode)
if (!opcode)
{
param ^= 1 << 0;
type ^= 1 << 0;
param ^= BITS(0);
type ^= BITS(0);
}
switch (type)
{
default:
case 0: return decrypt_type0(val,param,swap);
case 1: return decrypt_type0(val,param,swap);
case 2: return decrypt_type1a(val,param,swap);
case 3: return decrypt_type1b(val,param,swap);
case 4: return decrypt_type2a(val,param,swap);
case 5: return decrypt_type2b(val,param,swap);
case 6: return decrypt_type3a(val,param,swap);
case 7: return decrypt_type3b(val,param,swap);
case 0: return decrypt_type0(val, param, swap);
case 1: return decrypt_type0(val, param, swap);
case 2: return decrypt_type1a(val, param, swap);
case 3: return decrypt_type1b(val, param, swap);
case 4: return decrypt_type2a(val, param, swap);
case 5: return decrypt_type2b(val, param, swap);
case 6: return decrypt_type3a(val, param, swap);
case 7: return decrypt_type3b(val, param, swap);
}
}
static uint8_t mc8123_decrypt(offs_t addr,uint8_t val,const uint8_t *key,int opcode)
u8 mc8123_decrypt(offs_t addr, u8 val, u8 const *key, bool opcode)
{
int tbl_num;
// pick the translation table from bits fd57 of the address
offs_t const tbl_num = bitswap(addr,15,14,13,12,11,10,8,6,4,2,1,0);
/* pick the translation table from bits fd57 of the address */
tbl_num = (addr & 7) + ((addr & 0x10)>>1) + ((addr & 0x40)>>2) + ((addr & 0x100)>>3) + ((addr & 0xc00)>>4) + ((addr & 0xf000)>>4) ;
return decrypt(val,key[tbl_num + (opcode ? 0 : 0x1000)],opcode);
return decrypt(val, key[tbl_num | (opcode ? 0x0000 : 0x1000)], opcode);
}
void mc8123_decode(uint8_t *rom, uint8_t *opcodes, const uint8_t *key, int length)
} // anonymous namespace
void mc8123_decode(u8 *rom, u8 *opcodes, u8 const *key, unsigned length)
{
for (int A = 0x0000;A < length;A++)
for (unsigned i = 0; i < length; i++)
{
int adr = A >= 0xc000 ? (A & 0x3fff) | 0x8000 : A;
uint8_t src = rom[A];
unsigned const adr = (i >= 0xc000) ? ((i & 0x3fff) | 0x8000) : i;
u8 const src = rom[i];
/* decode the opcodes */
opcodes[A] = mc8123_decrypt(adr,src,key,1);
// decode the opcodes
opcodes[i] = mc8123_decrypt(adr, src, key, true);
/* decode the data */
rom[A] = mc8123_decrypt(adr,src,key,0);
// decode the data
rom[i] = mc8123_decrypt(adr, src, key, false);
}
}

View File

@ -9,4 +9,4 @@
// this function assumes a fixed portion of ROM at 0000-7FFF, and
// an arbitrary amount of banks at 8000-BFFF.
void mc8123_decode(uint8_t *rom, uint8_t *opcodes, const uint8_t *key, int length);
void mc8123_decode(u8 *rom, u8 *opcodes, u8 const *key, unsigned length);