📄 slapstic.c
字号:
/*************************************************************************
Atari Slapstic decoding helper
*************************************************************************
Slapstic FAQ - ver 0.2
Frank Palazzolo
03/13/98
(Please send comments or corrections
to me at palazzol@home.com)
----------------------------------
0) Credits:
I would like to thank the Motorola 68HC11 Evaluation
Board. Anything is possible with one of these :)
Special Thanks to:
Aaron Giles, Mike Balfour, and Tim Lindquist, and the rest of
the MAME Team
1) What is a slapstic?
The slapstic was a chip made by Atari, which was used for
bank-switching and security in some coin-operated video games.
2) What games used one?
Empire Strikes Back
Tetris
Gauntlet
Gauntlet II
Marble Madness
Peter Packrat
Indiana Jones & the Temple of Doom
Road Runner
Road Blasters
Paperboy
APB
720 Degrees
Super Sprint
Championship Sprint
Rampart
Vindicators Part II
Xybots
3) What is the pinout?
(It is a small 20 pin DIP package)
Pin # Function
----------------------
1 A10 (I)
2 A11 (I)
3 A12 (I)
4 A13 (I)
5 A14 (I)
6 ~CS (I)
7 CLK (I)
8 +5V
9 BS1 (O)
10 BS0 (O)
11 Gnd
12 A1 (I)
13 A2 (I)
14 A3 (I)
15 A4 (I)
16 A5 (I)
17 A6 (I)
18 A7 (I)
19 A8 (I)
20 A9 (I)
4) What did it do / How did it work?
This chip would sit on the address bus of a game CPU, and control which one
of 4 possible banks of ROM would be selected into a given memory area based on
a combination of accesses to that memory region.
Note1: All addresses are relative to the Slapstic's memory space, not necessarily the game's
Note2: Reset Address = $0000 for all chips
Note3: Addresses with a * next to them have been deduced, but not verified on real hardware
Chip # Game Bank Select Addresses Disable Mask Ignore Mask Secondary Secondary Bank Select
(0) (1) (2) (3) (MS 10 bits) (LS 7 bits) Enable (0) (1) (2) (3)
----------------------------------------------------------------------------------------------------------------------------
137412-101 ESB/Tetris $0080, $0090, $00a0, $00b0 $1540 $00?? $???? $????, $????, $????, $????
137412-103 Marble Madness $0040, $0050, $0060, $0070 $34c0 $002d $3d14 $3d24, $3d25, $3d26, $3d27
137412-104 Gauntlet $0020, $0028, $0030, $0038 $3d90 $0069 $???? $????, $????, $????, $????
137412-105 Indiana Jones & $0010, $0014, $0018, $001c $35b0 $003d $0092, $00a4, $00a5, $00a6, $00a7
Paperboy
137412-106 Gauntlet II $0008, $000a, $000c, $000e $3da0 $002b *$0052 *$0064,*$0065,*$0066,*$0067
137412-107 Peter Packrat & $0018, $001a, $001c, $001e $00a0 $006b $3d52, $3d64, $3d65, $3d66, $3d67
Xybots &
2-player Gauntlet &
720 Degrees
137412-108 Road Runner & $0028, $002a, $002c, $002e $0060 $001f $???? $????, $????, $????, $????
Super Sprint
137412-109 Championship Sprint $0008, $000a, $000c, $000e $3da0 $002b $0052 $0064, $0065, $0066, $0067
137412-110 Road Blasters & $0040, $0050, $0060, $0070 $34c0 $002d $3d14 $3d24, $3d25, $3d26, $3d27
APB?
137412-118 Vindicators Part II $0014, $0034, $0054, $0074 $???0 $0002 $???? $????, $????, $????, $????
& Rampart
Surprisingly, the slapstic appears to have used DRAM cells to store
the current bank. After 5 or 6 seconds without a clock, the chip reverts
to bank 3, with the chip reset (bank select addresses are enabled)
Typically, the slapstic region is accessed often enough to cause a
problem.
"Normal" operating mode of this chip is something like this:
Access $0000 (bank switching is now enabled for one switch)
Access $xxxx ... (n times)
Access $0008 (switch to bank 0 command)
Access $1234 (During the access to location $1234,
the bank will be switched to 0, on the
rising edge of the clock pulse.
Note1: It appears that the access during the bank switch
comes from the new bank, but this may depend on
the processor inteface in question.
Note2: The "reset" state of the part is equivalent to the part having
been accessed at location $0
The details of the state machine representing the chip are
documented in the MAME code.
*/
#include <stdio.h>
#include "driver.h"
/*************************************
*
* Structure of slapstic params
*
*************************************/
struct slapstic_params
{
int reset;
int bank0, bank1, bank2, bank3;
int disable;
int ignore;
int senable;
int sbank0, sbank1, sbank2, sbank3;
};
/*************************************
*
* Constants
*
*************************************/
#define DISABLE_MASK 0x3ff0
#define IGNORE_MASK 0x007f
#define UNKNOWN 0xffff
enum state_type { ENABLED, DISABLED, IGNORE, SPECIAL };
/*************************************
*
* The master table
*
*************************************/
static struct slapstic_params slapstic_table[18] =
{
/* 137412-101 ESB/Tetris */
{ 0x0000, 0x0080, 0x0090, 0x00a0, 0x00b0, 0x1540,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN },
/* 137412-102 ???? */
{ 0x0000,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN },
/* 137412-103 Marble Madness */
{ 0x0000, 0x0040, 0x0050, 0x0060, 0x0070, 0x34c0, 0x002d, 0x3d14, 0x3d24, 0x3d25, 0x3d26, 0x3d27 },
/* 137412-104 Gauntlet */
{ 0x0000, 0x0020, 0x0028, 0x0030, 0x0038, 0x3d90, 0x0069,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN },
/* 137412-105 Indiana Jones/Paperboy */
{ 0x0000, 0x0010, 0x0014, 0x0018, 0x001c, 0x35b0, 0x003d, 0x0092, 0x00a4, 0x00a5, 0x00a6, 0x00a7 },
/* 137412-106 Gauntlet II */
{ 0x0000, 0x0008, 0x000a, 0x000c, 0x000e, 0x3da0, 0x002b, 0x0052, 0x0064, 0x0065, 0x0066, 0x0067 },
/* 137412-107 Peter Packrat/Xybots/2-player Gauntlet/720 Degrees */
{ 0x0000, 0x0018, 0x001a, 0x001c, 0x001e, 0x00a0, 0x006b, 0x3d52, 0x3d64, 0x3d65, 0x3d66, 0x3d67 },
/* 137412-108 Road Runner/Super Sprint */
{ 0x0000, 0x0028, 0x002a, 0x002c, 0x002e, 0x0060, 0x001f,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN },
/* 137412-109 Championship Sprint */
{ 0x0000, 0x0008, 0x000a, 0x000c, 0x000e, 0x3da0, 0x002b, 0x0052, 0x0064, 0x0065, 0x0066, 0x0067 },
/* 137412-110 Road Blasters/APB */
{ 0x0000, 0x0040, 0x0050, 0x0060, 0x0070, 0x34c0, 0x002d, 0x3d14, 0x3d24, 0x3d25, 0x3d26, 0x3d27 },
/* 137412-112 ???? */
{ 0x0000,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN },
/* 137412-113 ???? */
{ 0x0000,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN },
/* 137412-114 ???? */
{ 0x0000,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN },
/* 137412-115 ???? */
{ 0x0000,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN },
/* 137412-116 ???? */
{ 0x0000,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN },
/* 137412-117 ???? */
{ 0x0000,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN },
/* 137412-118 Vindicators II/Rampart */
{ 0x0000, 0x0014, 0x0034, 0x0054, 0x0074,UNKNOWN, 0x0002,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN,UNKNOWN },
};
/*************************************
*
* Statics
*
*************************************/
static struct slapstic_params *slapstic;
static enum state_type state;
static int next_bank;
static int extra_bank;
static int current_bank;
static int version;
#define slapstic_log(o)
extern unsigned char *atarigen_slapstic;
unsigned char *slapstic_area;
/*************************************
*
* Initialization
*
*************************************/
void slapstic_init (int chip)
{
/* only a small number of chips are known to exist */
if (chip < 101 || chip > 118)
return;
version = chip;
/* set up a pointer to the parameters */
slapstic = slapstic_table + (chip - 101);
/* reset the chip */
state = ENABLED;
next_bank = extra_bank = -1;
if (chip == 101)
current_bank = 3;
else
current_bank = 3;
if (version == 101)
{
/* Super ugly hack for ESB */
memcpy (slapstic_area, &atarigen_slapstic[current_bank * 0x2000], 0x2000);
}
}
/*************************************
*
* Returns active bank without tweaking
*
*************************************/
int slapstic_bank (void)
{
return current_bank;
}
/*************************************
*
* Call this before every access
*
*************************************/
int slapstic_tweak (int offset)
{
/* switch banks now if one is pending */
if (next_bank != -1)
{
current_bank = next_bank;
next_bank = -1;
extra_bank = -1;
if (version == 101)
{
/* Super ugly hack for ESB */
memcpy (slapstic_area, &atarigen_slapstic[current_bank * 0x2000], 0x2000);
}
}
/* state machine */
switch (state)
{
/* ENABLED state: the chip has been activated and is ready for a bankswitch */
case ENABLED:
if ((offset & DISABLE_MASK) == slapstic->disable)
{
state = DISABLED;
}
else if ((offset & IGNORE_MASK) == slapstic->ignore)
{
state = IGNORE;
}
else if (offset == slapstic->bank0)
{
state = DISABLED;
if (extra_bank == -1)
next_bank = 0;
else
next_bank = extra_bank;
}
else if (offset == slapstic->bank1)
{
state = DISABLED;
if (extra_bank == -1)
next_bank = 1;
else
next_bank = extra_bank;
}
else if (offset == slapstic->bank2)
{
state = DISABLED;
if (extra_bank == -1)
next_bank = 2;
else
next_bank = extra_bank;
}
else if (offset == slapstic->bank3)
{
state = DISABLED;
if (extra_bank == -1)
next_bank = 3;
else
next_bank = extra_bank;
}
else if (offset == slapstic->reset)
{
next_bank = -1;
extra_bank = -1;
}
/* This is the transition which has */
/* not been verified on the HW yet */
else if (offset == slapstic->senable)
{
state = SPECIAL;
}
break;
/* DISABLED state: everything is ignored except a reset */
case DISABLED:
if (offset == slapstic->reset)
{
state = ENABLED;
next_bank = -1;
extra_bank = -1;
}
break;
/* IGNORE state: next access is interpreted differently */
case IGNORE:
if (offset == slapstic->senable)
{
state = SPECIAL;
}
else
{
state = ENABLED;
}
break;
/* SPECIAL state: the special alternate bank switch override method is being used */
case SPECIAL:
if (offset == slapstic->sbank0)
{
state = ENABLED;
extra_bank = 0;
}
else if (offset == slapstic->sbank1)
{
state = ENABLED;
extra_bank = 1;
}
else if (offset == slapstic->sbank2)
{
state = ENABLED;
extra_bank = 2;
}
else if (offset == slapstic->sbank3)
{
state = ENABLED;
extra_bank = 3;
}
else if (offset == slapstic->reset)
{
state = ENABLED;
next_bank = -1;
extra_bank = -1;
}
else
{
state = ENABLED;
}
break;
}
/* log this access */
slapstic_log (offset);
/* return the active bank */
return current_bank;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -