sedan 2001

Security chip MM


  • Sr. Member
  • ****
    • Antal inlägg: 394
    • Visa profil
  • Stad: Kungsbacka
Är det någon som kan förklara hur security chippet i MM fungerar, är det fler spel som har detta eller är det ett annat namn på något man kanske vet vad det är??


  • Sr. Member
  • ****
    • Antal inlägg: 499
    • Visa profil
  • Stad: Göteborg


  • Full Member
  • ***
    • Antal inlägg: 100
    • Visa profil
  • Stad: Huddinge
Security chippet innehåller ett serinummer och var till för att se till att distributörer höll sig inom sitt distrikt. (Tveksam till om det fungerade men det var iallafall tanken)

Jag skrev ett långt dokument en gång i tiden som beskrev exakt hur det fungerade. Ska se om jag kan gräva fram det.

- Chippet är unikt för varje spel.
- Serienumret i chippet är krypterat och krypteringsnyckeln beror på i vilken ordning man läser numret.
- Chippet måste sitta där rent fysiskt eftersom det har hand om switch-skanningen.
- En firma i USA tog mitt dokument och skapade egna chip.
- Jag har ett program som modifierar ROM-koden så den fungerar med vilket PIC-chip som helst.

Finns en lite rolig grej med chippet som du kan prova själv.
- Spela klart ett spel med 3 spelare.
- Stäng av spelet
- Sätt på spelet igen.
- Nu visas poängen för 4 spelare.
- Spelare 4 poängen är serinumret + ett slags slumpmässigt värde som jag inte kommer ihåg.


  • Full Member
  • ***
    • Antal inlägg: 100
    • Visa profil
  • Stad: Huddinge
PIC Documentation (last updated Oct 26, 2000)

1. What is the PIC chip?
The PIC security chip for pinball machines was introduced by Bally/Williams
in 1994 in the "World Cup Soccer" game.
The following is quoted from "Repairing Williams/Bally WPC Pinball Games"
by []

"This was done by Williams, because of problems in Europe, with distributors
selling games out of their sales territory. Anyone could turn a game on, write
down the displayed serial number, and determine if the game was 'bootlegged'
from another distributor. Unfortunately, this was easily defeated by adding
a dot matrix power delay board. This small board didn't power the dot matrix
display until the game was powered on for 10 seconds, making the serial
number impossible to see at power up, on location. This was embarrassing
to Williams, as they spent a large amount of time and money to develop this
security chip system as a distributor territory protection device, yet the
whole system was disabled by this simple modification"

A similar chip was used in the Williams video games.

I have collected the information below from several sources and I can not
guarantee its correctness. I don't own a PIC game myself.

2. Where is it?
The PIC chip sits on th CPU board between the CPU and the switch matrix logic.
This means that the game will not be able to access the switch matrix
without a PIC chip (or some other logic that performes the switch column

3. CPU  <->  PIC Communication
The CPU communicates with the PIC by writing a command to address 0x3fe9.
The PIC then makes the result of the operation available for read at 0x3fea.

Command     Result          Description
0x00     (never read)       Reset
0x0d     Counter value      Update the internal counter.
0x20     (never read)       Switch matrix unlock code (3 bytes) coming.
0x1x     Row value          Enable a switch column [0x16=Column 1, 0x17=Column 2...]
0x7x     Serial Number      Read serial number byte x [0x00-0x0f]

4. Serial Number
The main purpose of the PIC is to store a serial number. All other functions
are just there to prevent someone from using a game without a real PIC.

The serial number stored in the PIC contains 17 digits (0-9) in 4 groups


Group A,B and C are displayed when the game is powered up. Some code hacking
is required to display the group D digits. Search for the code sequence
'8620a723a72a6fa810' and replace the last '0' to a '4'. The checksum must
also be updated. (see 9.) The displaymight be a bit messed up but the group
D digits should be visible.

4.1 Group A
This is the game number without the coin door number (digit 2 & 3, usually '00'
or '33') removed, e.g. game 50066 becomes 566. This is checked by the software
on startup. If the value does not match the game number in the ROM the message
"Incorrect G10 for this game" is displayed. (If the serial number is wrong
in any other way the message is only "G10 Error").

Note that the check is performed towards a value stored at a different place
in the ROM than the game number displayed at startup (the 50066). This means
that it iseasy to change the ROM to use a PIC chip from another game (see 7.2).

4.2 Group B

These 6 digits are stored (BCD coded and inverted) in the game RAM. The only
use of them I have found is rather strange: If the last game played before
power off (or enter pressed) had 3 players, the group B digits are used to
form a fake player 4 score which is displayed during attract mode. A pseudo
random digit (2-9) is added to every other digit.

Example: 123456 - Group B digits
         909090 - pseudo random number 9
        1032546 - Fake player 4 score

I don't know the purpose of this. Maybe to be sure that the game actually
contains a PIC chip and that the serial number display on startup is real
(by subtracting the 4 player score from the Group B digits)

4.3 Group C
These digits are not checked by the game in anyway. I assume it is just a plain
serial number. I don't know if it relates to the game production serial number
or not.

4.4 Group D
These digits are the switch matrix unlock code encrypted with the game number
as key. This unlock code is sent to the PIC (via the 0x20 command) every time
the PIC internal counter becomes 0. I assume the purpose is to prvent someone
from just disabling the PIC code in the game ROM.

The encryption algorithm is described in 8.3

4.5 Serial Number encryption
The 17 digit serial number is encrypted into 12 bytes and a 2 byte checksum.
The encryption algorithm is described in 8.14.

6 Reading the serial number
When the CPU reads the serial number it reads 16 bytes in a random order.
The two extra bytes read (excluding the 12 byte serial number and the 2 byte
checksum) are two internal PIC registers. The value of these internal
registers depend on the order the 16 bytes are read. This is to prevent
someone from copying the PIC chip by just looking at the output from it.

The internal registers are described in 8.2

5. Internal timer
I don't know much about this. It might be free-running but it could also be
updated everytime it is read. My guess is that it updated on every read to
avoid timing problems.

Everytime the timer returns 0 (I don't know where it starts or if it wraps) the
CPU sends a three byte unlock code to the PIC (see 4.4). On power-up the game
waits for the timer to become 0 at least once. (If the checksum is turned off
the display will read "WAITING FOR SWITCH SCANNING" until the timer becomes 0).

The game only checks fora timer value of 0

6. Switch Matrix
This is simple. Command 0x16 will enable column 1, 0x17 column 2 and so on.
Reading will return the switch states in the selected row. Note that there
are 10 possible switch columns (0x16-0x1f).

I don't know if the PIC actually performs the switch scanning independently of
the CPU and only returns a stored value. The "WAITING FOR SWITCH SCANNING"
(see 5.) message indicates that this might be the case.

However, the CPU performs almost the same operations in PIC games as in
non-PIC games when accessing the switch matrix. The only difference is the
value used to activate the different columns and that the last columns is
never turned off.
My guess is that the PIC does scan the switch matrix independently. But if
someone creates a PIC replacement ship it is not necessary to implement
switch scanning.

7. Defeating the PIC
The knowledge about the PIC chip can be used in many different ways. I
have not tested any of these so be careful.

7.1 Create a fake PIC chip
With access to the correct hardware and knowledge about programmable PICs it
should be possible to create a PIC chip from the information in this file.
Some simplifications can also be done:
  - The internal timer can always return 0.
  - The 0x20 command bytes can be ignored.
  - No switch scanning is neccessary (the 0x1x command just enables a column)

7.2 Use a PIC chip from another game
It is easy to update the game code to use a PIC chip from another game. Only
one byte need to be changed in the game code (plus the checksum). Two manual
ways of doing itis presented here.

A. The easy (might not always work)
     - Add 0x1234 to the game number. e.g. 541 (decimal)+0x1234 = 0x1451 for
     - Search the game ROM for this number. You should find it in the last
       10000  bytes of the ROM file. If not or if you find several places
       use the safe version below
     - Replace the number with the game number of the new PIC chip + 0x1234.
     - Update the checksum. (see 9.)

B. The difficult (but safe)
     - Locate the byte sequence EC9F????831234. You will find it in at least
       three places.
     - The ???? is the address to a pointer to the game number. (If you find
       several use the most frequent address). I'll use 0x81ED as
       an example but the real position will differ with game and ROM version.
     - The last address in the ROM file is always 0xFFFF so the 0x81ED is
       located 0xFFFF-0x81ED bytes from the end of the file.
     - Use the 2 bytes found at 0x81ED (and 0x81EE) to locate the game number.
       I'll use 0xE998 as an example.
     - The bytes found at 0xe998-0xe999 (using the same method as above) should
       be the current game number + 0x1234
     - replace the game number with the game number + 0x1234 of the new PIC
     - Update the checksum. (see 9.)

It is also possible to change the code to allow any PIC chip. I have created
a program called anypic that will patch any WPC PIC rom to use any PIC chip.

7.3 Remove the PIC chip
I don't have access to the shematics but it should be possible to replace the
PIC chip with some simple logic that performes the switch matrix column
selection. The ROM must then be altered to either disable the PIC code or
some new code that emulates the PIC chip must be added (change writes to
3fea and reads from 3fe9 into subroutine calls).

8. Algorithms

8.1 Serial number encoder
This c-program ecrypts the serial number stored in ser[] into the 16 PIC
registers pic[].

Note that pic[5] and pic[13] are the PIC internal registers described in 8.2.

/* "ser" contains the serial numbers 0-9 without blanks */
/* e.g. unsigned char ser[17] = {1,2,3,1,2,3,4,5,6,1,2,3,4,5,1,2,3}; */
/*                               A A A B B B B B B C C C C C D D D */
void ser2pic(unsigned char ser[17], unsigned char pic[16], int key) {
  int tmp;

  pic[10] = key>> 8;
  pic[2]  = key;
  tmp = (100*ser[1] + 10*ser[7] + ser[4] + 5*pic[10]) * 0x001bcd + 0x01f3f0;
  pic[1] = tmp>> 16;
  pic[11] = tmp>> 8;
  pic[9]  = tmp;

  tmp = (10000*ser[2] + 1000*ser[15] + 100*ser[0] + 10*ser[8] + ser[6] +
         2*pic[10] + pic[2]) * 0x0000107f + 0x0071e259;
  pic[7] = tmp>> 24;
  pic[12] = tmp>> 16;
  pic[0] = tmp>> 8;
  pic[8] = tmp;

  tmp = (1000*ser[16] + 100*ser[3] + 10*ser[5] + ser[14] +
         pic[2]) * 0x000245 + 0x003d74;
  pic[3] = tmp>> 16;
  pic[14] = tmp>> 8;
  pic[6] = tmp;

  tmp = 99999 - (10000*ser[13] + 1000*ser[12] + 100*ser[11] +
                 10*ser[10] + ser[9]);
  pic[15] = tmp>> 8;
  pic[4] = tmp;

8.2 Serial number registers
The internal registers used when reading the serial number are calculated as:
init:  x = 0xa5;
       pic[5]  = pic[0] ^ pic[15];
       pic[13] = pic[2] ^ pic[12];

for each read (no = byte to read 0..15):
       x = ((x> > 4) | (no < <4)) & 0xff;
       pic[5]  = (pic[5]  ^ x) + pic[13];
       pic[13] = (pic[13] + x) ^ pic[5];

8.2 Switch matrix unlock code
The three byte unlock code sent to the PIC are calculated as:

/* "ser" contains the serial numbers 0-9 without blanks (only the A digits */
/* are used) */
/* e.g. unsigned char ser[17] = {1,2,3,1,2,3,4,5,6,1,2,3,4,5,1,2,3}; */
/*                               A A A B B B B B B C C C C C D D D */
void ser2code(unsigned char ser[17], unsigned char code[3]) {
  int tmp;

  tmp = 100*ser[0] + 10*ser[1] + ser[2];
  tmp = (tmp >>   8) * (0x100*ser[14] + ser[16] + 0x3030) +
        (tmp & 0xff) * (0x100*ser[15] + ser[14] + 0x3030);
  code[0] = tmp>> 16; code[1] = tmp>> 8; code[2] = tmp;