AMERICAN LASER GAMES RAM / ROM BOARD INFO - September 6, 2006
Developed & written by 'Any' (with a little help from Matteo Marioni)

The purpose of this document is to give a little technical insight of the RAM / ROM board used in the nine American Laser Games titles that were based on a plain Amiga 500 computer and a laserdisc player.  This document will describe how the board works and what the main differences are between the two revisions that were made:  Rev. A, (the first one) and Rev. B, (the last one to be developed).

Each RAM / ROM board is composed of five integrated circuits:

Pictures of the board can be found in the American Laser Games Virtual Library.
The RAM / ROM board is directly connected to the Amiga expansion port and it is used to store the code and data for game operation.  The two EPROMs contain the game code, while the RAM is used to keep game settings and other data.  The two PAL ICs are used to generate the Chip Select (CS) signals for EPROMs and RAM, and they are used to do some address swapping to prevent illegal board reproductions.  The PALs were factory programmed, and their surfaces were scraped off as a sort of copy protection.  Here's a basic schematic of a PAL16L8:

Quoting from Wikipedia:

"Programmable array logic (PAL) is a programmable logic device used to implement combinational logic circuits. The devices have fixed-or, programmable-and-plane arrays of transistor cells to implement 'sum-of-products' binary logic equations for each of the outputs in terms of the inputs and either synchronous or asynchronous feedback from the outputs"

 

PAL on location U5 generates the CS signals for all ROM and RAM ICs.  From Rev. A to Rev. B, the position of the RAM in the CPU memory map was changed, and the ROM size was doubled.

CS equations
PAL R2
(Rev.A boards)

PAL R5
(Rev.B boards)

Memory maps
RAM ROM RAM ROM
Start address End address Start address End address Start address End address Start address End address
0xF54000 0xF55FFF 0xF00000 0xF1FFFF 0xF7C000 0xF7DFFF 0xF00000 0xF3FFFF

where Axx stands for the corresponding bus address line.
Please note that these are NOT the exact formulas used in the PALs, but they work great for me. I've made a custom U5 PAL replacement with a bunch of TTL ICs that works nicely on both Rev. A and Rev. B boards.  The equations I used are more or less the following ones:

PAL on location U4 was more challenging to deal with... :P  There are 3 known versions that can be mounted in this location:

David Fickers, former ALG employee, once spoke about a possible R4 version used for Space Pirates, but no concrete evidence so far has come out about this version, so I'll pass on it.
My goal was to play all games on a Rev. B Board, so in order to do this I needed to understand how this address swap worked.  I used a socket to hold the PAL, some switches to drive the PAL inputs to high and low states, and some LEDs on the PAL outputs.  After a few hours, the puzzle was solved! :)
It came out that they used this PAL to swap data blocks of 0x7ff bytes in the ROM memory map.  So I obtained a 'truth table' for both R6 and R1, and I was able to re-scramble "Mad Dog McCree" V.1c from R1 version to R6.   I had Mad Dog McCree running on a Rev. B board using R6 and R2.  As previously said, the memory map was different in the 2 revisions, so I had to use R2 in place of R5 to get the correct CS signals for the RAM.  Unfortunately, I didn't have the R3 version, so I couldn't figure out its scramble and port also "Who Shot Johnny Rock ?" on Rev. B.
A friend later gave me a decrypted set of "Who Shot Johnny Rock ?" ROM images, so I scrambled them with the R1 algorithm, and now I have it up and running on a "Mad Dog McCree" Rev. A board, with PALs R1 and R2.  Take a look at the ALG tech center page to download a copy of these ROM images (file wsjr_1.6_RevA.zip) if you want to have "Who Shot Johnny Rock ?" running on your Mad Dog Rev. A board.  In addition, file wsjr_1.6_RevB.zip contains ROM images again for "Who Shot Johnny Rock ?", but running on a Rev. B this time, using PALs R6 and R2.  As a final step, I compared the decrypted "Who Shot Johnny Rock ?" set with a crypted one, to determine how PAL R3 works, and I wrote down the scramble (see program below).

The following is a simple C code I used to scramble/descramble the binary files of the ROM images.  It's quite simple if you are familiar with programming, so it doesn't need too much comment.  If you're not, then just stay away from it. ;)

// Use this main program to :
//  - input a crypted ROM with known algorithm (file rom1.bin) and return it decrypted (file out1.bin);
//  - input a decrypted ROM (file rom1.bin) and return it crypted with a known algorithm (file out1.bin)
//  - to "port" game from Rev. A to Rev. B first you have to de-scramble the ROM, then copy the plain ROM twice in a new file
//  (copy /b out1.bin + out1.bin rom1.bin) and finally scramble the result with R6 algorithm.


#include <stdio.h>

static const int r1[] = { 0,1,3,2,4,5,7,6,12,13,15,14,8,9,11,10,16,17,19,18,20,21,23,22,28,29,31,30,24,25,27,26};
static const int r3[] = { 0,1,3,2,4,5,7,6,8,9,11,10,12,13,15,14,16,17,19,18,20,21,23,22,24,25,27,26,28,29,31,30};
static const int r6[] = { 33,32,34,35,37,36,38,39,45,44,46,47,41,40,42,43,49,48,50,51,53,52,54,55,61,60,62,63,57,56,58,59,
1,0,2,3,5,4,6,7,13,12,14,15,9,8,10,11,17,16,18,19,21,20,22,23,29,28,30,31,25,24,26,27};


int main (void){

    int R1 = 1;
    int R3 = 0;
    int R6 = 0;
    int rev_a = 1;
    int rev_b = 0;

    int i=0;
    char rom_src_rev_a[65535];
    char rom_src_rev_b[65535*2];

    char rom_dest_rev_a[65535];
    char rom_dest_rev_b[65535*2];

    static FILE *src_file = NULL;
    static FILE *dst_file = NULL;

    src_file = fopen( "rom1.bin", "rb" );
    dst_file = fopen( "out1.bin", "wb" );

    if (rev_a){
        for (i=0;i<65535;i++){
            rom_src_rev_a[i]=fgetc(src_file);
        }
    }
    if (rev_a){
        for (i=0;i<65535*2;i++){
            rom_src_rev_b[i]=fgetc(src_file);
        }
    }
    fclose(src_file);

    if (rev_a){
        if (R1){
            for (i = 0; i < 32; i++)
                memcpy ( rom_dest_rev_a + r1[i] * 0x800, rom_src_rev_a + i * 0x800, 0x800);
        }
        if (R3){
            for (i = 0; i < 32; i++)
                memcpy ( rom_dest_rev_a + r3[i] * 0x800, rom_src_rev_a + i * 0x800, 0x800);
        }
    }

    if (rev_b){
        for (i = 0; i < 64; i++)
            memcpy (rom_dest_rev_b + r6[i] * 0x800, rom_src_rev_b + i * 0x800, 0x800);
    }

    if (rev_a){
        for (i=0;i<65536;i++){
            fputc(rom_dest_rev_a[i],dst_file);
        }
    }

    if (rev_b){
        for (i=0;i<65536*2;i++){
            fputc(rom_dest_rev_b[i],dst_file);
        }
    }

    fclose(dst_file);
}

DISCLAIMER

English isn't my mother tongue, so don't expect this document to be perfect.  I'm not a professional electronic engineer or programmer either, so 100% accuracy is not guaranteed.
I'm not responsible for any damage to yourself, your computer, or your American Laser Games machine.  The above worked fine for me; I hope it does the same for you.  Feel free to submit corrections, comments and suggestions by e-mailing the DLP staff.


QUESTIONS? COMMENTS? PROBLEMS?
Contact Us

HOME | LASER GAMES | LASER COMMUNITY | TECH CENTER

This website was created by Jeff Kinder & Dave Hallock, 1997 - 2017.
All trademarks and copyrighted materials are property of their respective owners.