diff options
Diffstat (limited to 'attic/jrcrypt.cpp')
-rw-r--r-- | attic/jrcrypt.cpp | 530 |
1 files changed, 530 insertions, 0 deletions
diff --git a/attic/jrcrypt.cpp b/attic/jrcrypt.cpp new file mode 100644 index 00000000000..0ca833ea0a7 --- /dev/null +++ b/attic/jrcrypt.cpp @@ -0,0 +1,530 @@ +// license:GPL-2.0+ +// copyright-holders:David Caldwell +/*************************************************************************** + + jrcrypt.cpp + + This file is not part of MAME. It is here to provide detailed + documentation of the encryption used by Jr. Pac Man ROMs. + + David Caldwell 6-1-97 + bug reports and comments to: + david@indigita.com + + This code is published under the GNU Public License. (GPL) + +***************************************************************************/ + +#include "emu.h" +#include <cctype> + +static int irq_mask; + +typedef uint16_t word; +typedef uint8_t byte; + +#define PreDecryptedRoms + +#ifndef PreDecryptedRoms +static int s0,s1,s2,s3; /* 1 bit registers inside decoder PAL */ +static uint8_t shadowROM[0xffff]; +static uint8_t used[0xFFFF]; +uint32_t numberUsed = 0; +#else +struct { + int count; + int value; +} Jr_PacManTable[] = { + { 0x00C1, 0x00 }, + { 0x0002, 0x80 }, + { 0x0004, 0x00 }, + { 0x0006, 0x80 }, + { 0x0003, 0x00 }, + { 0x0002, 0x80 }, + { 0x0009, 0x00 }, + { 0x0004, 0x80 }, + { 0x9968, 0x00 }, + { 0x0001, 0x80 }, + { 0x0002, 0x00 }, + { 0x0001, 0x80 }, + { 0x0009, 0x00 }, + { 0x0002, 0x80 }, + { 0x0009, 0x00 }, + { 0x0001, 0x80 }, + { 0x00AF, 0x00 }, + { 0x000E, 0x04 }, + { 0x0002, 0x00 }, + { 0x0004, 0x04 }, + { 0x001E, 0x00 }, + { 0x0001, 0x80 }, + { 0x0002, 0x00 }, + { 0x0001, 0x80 }, + { 0x0002, 0x00 }, + { 0x0002, 0x80 }, + { 0x0009, 0x00 }, + { 0x0002, 0x80 }, + { 0x0009, 0x00 }, + { 0x0002, 0x80 }, + { 0x0083, 0x00 }, + { 0x0001, 0x04 }, + { 0x0001, 0x01 }, + { 0x0001, 0x00 }, + { 0x0002, 0x05 }, + { 0x0001, 0x00 }, + { 0x0003, 0x04 }, + { 0x0003, 0x01 }, + { 0x0002, 0x00 }, + { 0x0001, 0x04 }, + { 0x0003, 0x01 }, + { 0x0003, 0x00 }, + { 0x0003, 0x04 }, + { 0x0001, 0x01 }, + { 0x002E, 0x00 }, + { 0x0078, 0x01 }, + { 0x0001, 0x04 }, + { 0x0001, 0x05 }, + { 0x0001, 0x00 }, + { 0x0001, 0x01 }, + { 0x0001, 0x04 }, + { 0x0002, 0x00 }, + { 0x0001, 0x01 }, + { 0x0001, 0x04 }, + { 0x0002, 0x00 }, + { 0x0001, 0x01 }, + { 0x0001, 0x04 }, + { 0x0002, 0x00 }, + { 0x0001, 0x01 }, + { 0x0001, 0x04 }, + { 0x0001, 0x05 }, + { 0x0001, 0x00 }, + { 0x0001, 0x01 }, + { 0x0001, 0x04 }, + { 0x0002, 0x00 }, + { 0x0001, 0x01 }, + { 0x0001, 0x04 }, + { 0x0002, 0x00 }, + { 0x0001, 0x01 }, + { 0x0001, 0x04 }, + { 0x0001, 0x05 }, + { 0x0001, 0x00 }, + { 0x01B0, 0x01 }, + { 0x0001, 0x00 }, + { 0x0002, 0x01 }, + { 0x00AD, 0x00 }, + { 0x0031, 0x01 }, + { 0x005C, 0x00 }, + { 0x0005, 0x01 }, + { 0x604E, 0x00 }, + { 0,0 } +}; +#endif + +MACHINE_RESET( jrpacman ) +{ +#ifndef PreDecryptedRoms + s0 = 1; + s1 = 1; + s2 = 0; + s3 = 0; + + memset(shadowROM,0,sizeof(shadowROM)); + memset(used,0,sizeof(used)); +#endif +} + + +#ifdef PreDecryptedRoms +unsigned jrpacman_decode_roms(int address) +{ + int i; + int cumulative=0; + for (i=0;Jr_PacManTable[i].count;i++) + { + cumulative += Jr_PacManTable[i].count; + if (cumulative > address) + return RAM[address] ^ Jr_PacManTable[i].value; + } + return RAM[address]; // this should never happen! +} +#else +static inline WordBit(word theWord, int theBit) +{ + return (theWord >> theBit)&1; +} +static inline ByteBit(byte theByte, int theBit) +{ + return (theByte >> theBit)&1; +} + +int jrpacman_romdecode(int offset); +int jrpacman_romdecodeA(int offset) +{ + jrpacman_romdecode(offset); +} + +int jrpacman_romdecodeB(int offset) +{ + jrpacman_romdecode(offset + 0x8000); +} + + +/**************************************************************************** + + This function would look suprisingly similiar to the source code to +the encoder pals, I imagine. I wrote is based on the jedec file that I +got from VideoDoctor. It needs to be run during the game, since the +logic is kind of weird and state based. This is slow. So you'll see +that I made it store its "decrypted" opcodes in another array. When I +ran the program and was satisfied that it had decrypted enough code, I +dumped this new array out into some ROM files. These ROM files are +effectively decrypted. But nobody else has them, so I'd have to upload +them to some ROM archive somewhere and hope for the best. Besides, If +I ever found a bug in them its not easy to upgrade every ROM archive +site out there. So I created a table that has the decrypted ROMs and +the encrypted ROMs xor-ed with each other. So if something wrong is +ever discovered , all that is needed to update is the table. Jr. Pac +only messes with 3 bits (d0, d2 and d7) so the table doesn't look too +excited. Also I run length encoded it so its not unwieldly. + + A lot of the functions that are ifdef-ed out here were debugging +functions that I used to help me during the decoding process. + + -David Caldwell + david@indigita.com + +***************************************************************************/ + +int jrpacman_romdecode(int offset) +{ + int addressBus = offset; + Z80_Regs Regs; + Z80_GetRegs(&Regs); + + { + int m1 = !Regs.M1;//active low (supposedly means opcode read) + + /* Pal 8C (16L8) */ + int pcbe = !(addressBus >= 0x0000 && addressBus <= 0x3fff || + addressBus >= 0x8000 && addressBus <= +0xdfff); + + int sop0 = !(addressBus >= 0x0000 && addressBus <= 0x001f || + addressBus >= 0x00e0 && addressBus <= +0x00ff || + addressBus >= 0x9a60 && addressBus <= +0x9a7f || + addressBus >= 0x9ac0 && addressBus <= +0x9adf || + addressBus >= 0x9b60 && addressBus <= +0x9b7f || + addressBus >= 0x9be0 && addressBus <= +0x9bff && m1); + + int sop1 = !(addressBus >= 0x9be0 && addressBus <= 0x9bff && m1 || + addressBus >= 0x9ca0 && addressBus <= +0x9cbf); + + int sop2 = !(addressBus >= 0x00c0 && addressBus <= 0x00df || + addressBus >= 0x9a40 && addressBus <= +0x9a5f); + + + /* Pal 9c (16r4) */ + int md0 = ByteBit(RAM[addressBus],0); + int md2 = ByteBit(RAM[addressBus],2); + int md7 = ByteBit(RAM[addressBus],7); + + int d0 = !( s0 && s1 && !md0 || + !s0 && s1 && md0 || + s0 && !s1 && !md0 || + !s0 && !s1 && !md2); + + int d2 = !( s0 && s1 && !md2 || + !s0 && s1 && !md2 || + s0 && !s1 && md2 || + !s0 && !s1 && !md0); + + int d7 = !( s2 && s3 || + !s2 && !md7); + + int pb1 = !( sop0 && s0 || + !sop0 && !s0); + + int ns0 = ( sop1 && s0 || + !sop1 && !s0 || + !sop0 && sop1); + + int ns1 = ( sop1 && s1 && !pb1 || + !sop1 && s1 && !pb1 || + sop1 && s1 && pb1 || + !sop1 && !s1 && pb1 || + !sop0 && sop1); + + int ns2 = ( sop0 && sop1 && s2 || + sop0 && !sop1 && s2 || + !sop0 && !sop1 && s2 || + sop0 && !sop2); + + int ns3 = ( !md7 ); + +// DebugPrint("%04x: %02x & %02x | %02x = %02x",addressBus,RAM[addressBus],~(1<<0) & ~(1<<2) & ~(1<<7), (d0) | (d2<<2) | (d7<<7),(RAM[addressBus] & ~(1<<0) & ~(1<<2) & ~(1<<7)) | (d0) | (d2<<2) | (d7<<7)); +/* printf("%04x: %02x & %02x | %02x = %02x\n",addressBus,RAM[addressBus],~(1<<0) & ~(1<<2) & ~(1<<7), (d0) | (d2<<2) | (d7<<7),(RAM[addressBus] & ~(1<<0) & ~(1<<2) & ~(1<<7)) | (d0) | (d2<<2) | (d7<<7)); + {static int i=0; + if (i++>100) + { + while (getchar()!='\n') + {} + }}*/ + { + int temp= ((int)RAM[addressBus] & 0x7A) | ((d7<<7) | (d2<<2) | (d0)); + +// if (Z80_Trace==1) + if (!used[addressBus]) + { + used[addressBus]=1; + shadowROM[addressBus] = temp; + numberUsed++; + } + else + { + if (shadowROM[addressBus] != temp) + DebugPrint("Address: %04x translates to 2 different values!!!! (%02x and %02x)",addressBus,shadowROM[addressBus],temp); + } + + + if (Z80_Trace==1) + { + static last = 0; + if (last + 30 <= TickCount()) /* print bnanner if we havent been called in half a second */ + printf("m1 sop0 sop1 sop2 pcbe md7 md2 md0 d7 d2 d0 pb1 s0 s1 s2 s3 ns0 ns1 ns2 ns3\n"); + last = TickCount(); + printf("%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d ", + m1, sop0,sop1,sop2,pcbe, md7, md2, md0, +d7, d2, d0, pb1, s0, s1, s2, s3, ns0, ns1, ns2, ns3); + printf("%04x: %02x & %02x | %02x = %02x\n",addressBus,RAM[addressBus],~(1<<0) & ~(1<<2) & ~(1<<7), (d0) | (d2<<2) | (d7<<7),(RAM[addressBus] & ~(1<<0) & ~(1<<2) & ~(1<<7)) | (d0) | (d2<<2) | (d7<<7)); + Z80_Trace = 1; /* stop it if it was running for a count */ + } + + /* latch new flip flops on rising edge of pcbe */ + if (!pcbe) + { + s0 = ns0; + s1 = ns1; + s2 = ns2; + s3 = ns3; + } + return temp; + } + } +} + +int Z80_Trace=0; + +void jr_monitor() +{ + int i; + int encrypted=0; + //int last_used=-1; + int unmapped_encrypted=0; + int unmapped=0; + printf("statistics: \n"); + printf(" Successfully mapped: %d\n",numberUsed); + for (i=0;i<0xe000;i=(i==0x4000?0x8000:i+1)) /* skip hole where +hardware and RAM is */ + { + if (used[i]) + { + if (shadowROM[i] != RAM[i]) + encrypted = 1; + else + encrypted = 0; + //last_used = i; + } + else + { + if (encrypted) + unmapped_encrypted++; + else + unmapped++; + } + } + printf(" Non mapped, Probably not encrypted: %d\n",unmapped); + printf(" Non mapped, but Probably encrypted: %d\n",unmapped_encrypted); + + while (1) + { + void write_rom_section(char *prefix,char *suffix,int +start,int end); + char c; + printf(" Enter D to Merge mapped and unmapped and dump to rom file,\n"); + printf(" Enter Q to quit.\n"); + c=tolower(getchar()); + while (getchar()!='\n') {} + if (c=='q') + return; + if (c=='d') + { + char line[100],*l; + //int i; + printf("Enter file prefix (files will be named 'prefix'.8d 'prefix'.8e, etc.\n"); + gets(line); + // kill newline: + for (l=line;*l!='\n' && *l!='\0';l++) + {} + *l = '\0'; + + write_rom_section(line,".8d",0x0000,0x2000); + write_rom_section(line,".8e",0x2000,0x4000); + write_rom_section(line,".8h",0x8000,0xa000); + write_rom_section(line,".8j",0xa000,0xc000); + write_rom_section(line,".8k",0xc000,0xe000); + } + } +} + +void write_rom_section(char *prefix,char *suffix,int start,int end) +{ + FILE *out; + char file[100]; + int i; + + strcpy(file,prefix); + strcat(file,suffix); + out = fopen(file,"wb"); + for (i=start;i<end;i++) + if (used[i]) + putc(shadowROM[i],out); + else + putc(RAM[i],out); + fclose(out); +} +#endif + +void jrpacman_interrupt_mask_w(uint8_t data) +{ + irq_mask = data; +} + + + +/*************************************************************************** + + Interrupt handler. This function is called at regular intervals + (determined by IPeriod) by the CPU emulation. + +***************************************************************************/ + +static int IntVector = 0xff; /* Here we store the interrupt vector, if +the code performs */ + /* an OUT to port $0. Not +all games do it: many use */ + /* Interrupt Mode 1, which +doesn't use an interrupt vector */ + /* (see Z80.c for details). */ + +INTERRUPT_GEN( jrpacman_interrupt ) +{ + irq0_line_hold(device); +} + + + +/*************************************************************************** + + The Pac Man machine uses OUT to port $0 to set the interrupt vector, so + we have to remember the value passed. + +***************************************************************************/ +void jrpacman_out(byte Port,byte Value) +{ + /* OUT to port $0 is used to set the interrupt vector */ + if (Port == 0) IntVector = Value; +} + +#if 0 +/**************************************************************************** +What follows is the program I used to create the JrPacMan_Table[] array at +the top of this file. It is included here for completeness. +***************************************************************************/ + + +// CreateJrDecodeTable.c +// +// Copyright David Caldwell +// This program is published under the GNU Public License. +// +// Comments, questions to: david@indigita.com + +#include <cstdio> + +typedef uint8_t byte; + +void CreateJrDecodeTable(byte *x, int length); +void Load(char *name,byte *buffer,int from, int length); + +byte encrypted[0x10000],decrypted[0x10000]; +byte xored[0x10000]; +void main() +{ + int i; + + Load("jr8d",encrypted,0x0000,0x2000); + Load("jr8e",encrypted,0x2000,0x2000); + Load("jr8h",encrypted,0x8000,0x2000); + Load("jr8j",encrypted,0xA000,0x2000); + Load("jr8k",encrypted,0xC000,0x2000); + + Load("1.8d",decrypted,0x0000,0x2000); + Load("1.8e",decrypted,0x2000,0x2000); + Load("1.8h",decrypted,0x8000,0x2000); + Load("1.8j",decrypted,0xA000,0x2000); + Load("1.8k",decrypted,0xC000,0x2000); + + for (i=0;i<0x10000;i++) + xored[i] = encrypted[i] ^ decrypted[i]; + + CreateJrDecodeTable(xored,0x10000); +} + +void Load(char *name,byte *buffer,int from, int length) +{ +/* + emu_file file(options, nullptr, OPEN_FLAG_READ); + osd_file::error filerr = file.open(name); + if (filerr != osd_file::error::NONE) + return; + while (length--) + buffer[from++]=file->getc(); +*/ +} + +void CreateJrDecodeTable(byte *x, int length) +{ + int i=0; + byte last = 0; + int count = 0; + + printf( "struct {\n" + " int count;\n" + " int value;\n" + "} Jr_PacManTable[] = {\n"); + + goto first; + + for (i=0;i<length;i++) + { + if (x[i] != last) + { + printf(" { 0x%04X, 0x%02X },\n",count,last); + count = 0; + } +first: + last = x[i]; + count++; + } + + printf(" { 0x%04X, 0x%02X },\n",count,last); + printf( " { 0,0 }\n" + "};\n"); +} +#endif |