ST-0010 Gamepaks
F1 Race of Champions 2 (a.k.a. Exhaust Heat F1 Driver
Locus)
ST-0010 Memory Mapping
|
Mode
|
Size
|
Bank
|
Data Register
|
Status Register
|
|
20H
|
8Mbit
|
68H ~ 6FH
|
0000H ~ 0FFFH
|
0021H
|
ST-0010 Command Summary
|
Commands are executed on the ST-0010 by writing the
command to 0x0020 and setting bit 7 of 0x0021. Bit 7 of 0x0021 will stay set
until the Command has completed, at which time output data will be available.
See individual commands for input and output parameter addresses.
|
|
01H
|
Unknown Command
|
|
02H
|
Sort Driver Placements
|
|
03H
|
2D Coordinate Scale (Bit Perfect)
|
|
04H
|
Unknown Command
|
|
05H
|
Simulated Driver Coordinate Calculation
|
|
06H
|
Multiply (Bit Perfect)
|
|
07H
|
Raster Data Calculation (Bit Perfect)
|
|
08H
|
2D Coordinate Rotation (Bit Perfect)
|
ST-0010 Source Code Contributors
The Dumper, Matthew Kendora, Overload, Feather
// st010.cpp
const short ST010_SinTable[256] = {
0x0000, 0x0324, 0x0648, 0x096a, 0x0c8c, 0x0fab, 0x12c8, 0x15e2,
0x18f9, 0x1c0b, 0x1f1a, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11,
0x30fb, 0x33df, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a,
0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842,
0x5a82, 0x5cb3, 0x5ed7, 0x60eb, 0x62f1, 0x64e8, 0x66cf, 0x68a6,
0x6a6d, 0x6c23, 0x6dc9, 0x6f5e, 0x70e2, 0x7254, 0x73b5, 0x7504,
0x7641, 0x776b, 0x7884, 0x7989, 0x7a7c, 0x7b5c, 0x7c29, 0x7ce3,
0x7d89, 0x7e1d, 0x7e9c, 0x7f09, 0x7f61, 0x7fa6, 0x7fd8, 0x7ff5,
0x7fff, 0x7ff5, 0x7fd8, 0x7fa6, 0x7f61, 0x7f09, 0x7e9c, 0x7e1d,
0x7d89, 0x7ce3, 0x7c29, 0x7b5c, 0x7a7c, 0x7989, 0x7884, 0x776b,
0x7641, 0x7504, 0x73b5, 0x7254, 0x70e2, 0x6f5e, 0x6dc9, 0x6c23,
0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f1, 0x60eb, 0x5ed7, 0x5cb3,
0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4,
0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33df,
0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f1a, 0x1c0b,
0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8c, 0x096a, 0x0648, 0x0324,
0x0000, -0x0324, -0x0648, -0x096b, -0x0c8c, -0x0fab, -0x12c8, -0x15e2,
-0x18f9, -0x1c0b, -0x1f1a, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11,
-0x30fb, -0x33df, -0x36ba, -0x398d, -0x3c56, -0x3f17, -0x41ce, -0x447a,
-0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842,
-0x5a82, -0x5cb3, -0x5ed7, -0x60ec, -0x62f1, -0x64e8, -0x66cf, -0x68a6,
-0x6a6d, -0x6c23, -0x6dc9, -0x6f5e, -0x70e2, -0x7254, -0x73b5, -0x7504,
-0x7641, -0x776b, -0x7884, -0x7989, -0x7a7c, -0x7b5c, -0x7c29, -0x7ce3,
-0x7d89, -0x7e1d, -0x7e9c, -0x7f09, -0x7f61, -0x7fa6, -0x7fd8, -0x7ff5,
-0x7fff, -0x7ff5, -0x7fd8, -0x7fa6, -0x7f61, -0x7f09, -0x7e9c, -0x7e1d,
-0x7d89, -0x7ce3, -0x7c29, -0x7b5c, -0x7a7c, -0x7989, -0x7883, -0x776b,
-0x7641, -0x7504, -0x73b5, -0x7254, -0x70e2, -0x6f5e, -0x6dc9, -0x6c23,
-0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f1, -0x60eb, -0x5ed7, -0x5cb3,
-0x5a82, -0x5842, -0x55f5, -0x539a, -0x5133, -0x4ebf, -0x4c3f, -0x49b3,
-0x471c, -0x447a, -0x41cd, -0x3f17, -0x3c56, -0x398c, -0x36b9, -0x33de,
-0x30fb, -0x2e10, -0x2b1f, -0x2826, -0x2527, -0x2223, -0x1f19, -0x1c0b,
-0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324
};
short ST010_Sin(short Theta)
{
return ST010_SinTable[(Theta >> 8) & 0xff];
}
short ST010_Cos(short Theta)
{
return ST010_SinTable[((Theta + 0x4000) >> 8) & 0xff];
}
01H - Unknown Command
|
Input
|
$0000
|
integer(X0)
|
|
|
$0002
|
integer(Y0)
|
|
Output
|
$0000
|
integer(X1)
|
|
|
$0002
|
integer(Y1)
|
|
|
$0004
|
integer(Quadrant)
|
|
|
$0006
|
integer(Y0)
|
|
|
$0010
|
integer(Theta)
|
void ST010_OP01(short X0, short Y0, short &X1, short &Y1, short &Quadrant, short &Theta)
{
if ((X0 < 0) && (Y0 < 0))
{
X1 = -X0;
Y1 = -Y0;
Quadrant = -0x8000;
}
else if (X0 < 0)
{
X1 = Y0;
Y1 = -X0;
Quadrant = -0x4000;
}
else if (Y0 < 0)
{
X1 = -Y0;
Y1 = X0;
Quadrant = 0x4000;
}
else
{
X1 = X0;
Y1 = Y0;
Quadrant = 0x0000;
}
while ((X1 > 0x1f) || (Y1 > 0x1f))
{
if (X1 > 1) X1 >>= 1;
if (Y1 > 1) Y1 >>= 1;
}
if (Y1 == 0) Quadrant += 0x4000;
Theta = (ST010_ArcTan[Y1][X1] << 8) ^ Quadrant;
}
02H - Sort Driver Placements
|
Input
|
$0024
|
integer(Positions)
|
|
|
$0040
|
integer[32] Places
|
|
|
$0080
|
integer[32] Drivers
|
|
Output
|
$0040
|
integer[32] Places
|
|
|
$0080
|
integer[32] Drivers
|
void ST010_SortDrivers(short Positions, short Places[32], short Drivers[32])
{
bool Sorted;
short Temp;
if (Positions > 1)
do {
Sorted = true;
for (int i = 0; i < Positions - 1; i++)
if (Places[i] < Places[i + 1])
{
Temp = Places[i + 1];
Places[i + 1] = Places[i];
Places[i] = Temp;
Temp = Drivers[i + 1];
Drivers[i + 1] = Drivers[i];
Drivers[i] = Temp;
Sorted = false;
}
Positions--;
} while (!Sorted);
}
03H - 2D Coordinate Scale (Bit Perfect)
|
Input
|
$0000
|
integer(X0)
|
|
|
$0002
|
integer(Y0)
|
|
|
$0004
|
integer(Multiplier)
|
|
Output
|
$0010
|
double(X1)
|
|
|
$0014
|
double(Y1)
|
void ST010_Scale(short Multiplier, short X0, short Y0, int &X1, int &Y1)
{
X1 = X0 * Multiplier << 1;
Y1 = Y0 * Multiplier << 1;
}
04H - Unknown Command
|
Input
|
$0000
|
integer(X)
|
|
|
$0002
|
integer(Y)
|
|
Output
|
$0010
|
integer(Distance)
|
void ST010_Distance(short X0, short Y0, short &Distance)
{
if (X0 < 0) X0 = -X0;
Distance = ((X0 * 0x7af0) + 0x4000) >> 15;
}
05H - Simulated Driver Coordinate Calculation
|
Input
|
$00C0
|
integer(MaxX)
|
|
|
$00C2
|
integer(MaxY)
|
|
|
$00C4
|
double(X0)
|
|
|
$00C8
|
double(Y0)
|
|
|
$00CC
|
integer(Theta)
|
|
|
$00D4
|
integer(Radius)
|
|
|
$00D6
|
integer(Increment)
|
|
|
$00D8
|
integer(MaxRadius)
|
|
|
$00DA
|
integer(?)
|
|
|
$00DC
|
integer(Flags)
|
|
|
$00DE
|
integer(X1)
|
|
|
$00E0
|
integer(Y1)
|
06H - Multiply (Bit Perfect)
|
Input
|
$0000
|
integer(Multiplicand)
|
|
|
$0002
|
integer(Multiplier)
|
|
Output
|
$0010
|
double(Product)
|
void ST010_Multiply(short Multiplicand, short Multiplier, int &Product)
{
Product = Multiplicand * Multiplier << 1;
}
07H - Raster Data Calculation (Bit Perfect)
|
Input
|
$0000
|
integer(Theta)
|
|
Output
|
$00F0
|
integer[176]
|
|
|
$0250
|
integer[176]
|
|
|
$03B0
|
integer[176]
|
|
|
$0510
|
integer[176]
|
const short ST010_M7Scale[176] = {
0x0380, 0x0325, 0x02da, 0x029c, 0x0268, 0x023b, 0x0215, 0x01f3,
0x01d5, 0x01bb, 0x01a3, 0x018e, 0x017b, 0x016a, 0x015a, 0x014b,
0x013e, 0x0132, 0x0126, 0x011c, 0x0112, 0x0109, 0x0100, 0x00f8,
0x00f0, 0x00e9, 0x00e3, 0x00dc, 0x00d6, 0x00d1, 0x00cb, 0x00c6,
0x00c1, 0x00bd, 0x00b8, 0x00b4, 0x00b0, 0x00ac, 0x00a8, 0x00a5,
0x00a2, 0x009e, 0x009b, 0x0098, 0x0095, 0x0093, 0x0090, 0x008d,
0x008b, 0x0088, 0x0086, 0x0084, 0x0082, 0x0080, 0x007e, 0x007c,
0x007a, 0x0078, 0x0076, 0x0074, 0x0073, 0x0071, 0x006f, 0x006e,
0x006c, 0x006b, 0x0069, 0x0068, 0x0067, 0x0065, 0x0064, 0x0063,
0x0062, 0x0060, 0x005f, 0x005e, 0x005d, 0x005c, 0x005b, 0x005a,
0x0059, 0x0058, 0x0057, 0x0056, 0x0055, 0x0054, 0x0053, 0x0052,
0x0051, 0x0051, 0x0050, 0x004f, 0x004e, 0x004d, 0x004d, 0x004c,
0x004b, 0x004b, 0x004a, 0x0049, 0x0048, 0x0048, 0x0047, 0x0047,
0x0046, 0x0045, 0x0045, 0x0044, 0x0044, 0x0043, 0x0042, 0x0042,
0x0041, 0x0041, 0x0040, 0x0040, 0x003f, 0x003f, 0x003e, 0x003e,
0x003d, 0x003d, 0x003c, 0x003c, 0x003b, 0x003b, 0x003a, 0x003a,
0x003a, 0x0039, 0x0039, 0x0038, 0x0038, 0x0038, 0x0037, 0x0037,
0x0036, 0x0036, 0x0036, 0x0035, 0x0035, 0x0035, 0x0034, 0x0034,
0x0034, 0x0033, 0x0033, 0x0033, 0x0032, 0x0032, 0x0032, 0x0031,
0x0031, 0x0031, 0x0030, 0x0030, 0x0030, 0x0030, 0x002f, 0x002f,
0x002f, 0x002e, 0x002e, 0x002e, 0x002e, 0x002d, 0x002d, 0x002d,
0x002d, 0x002c, 0x002c, 0x002c, 0x002c, 0x002b, 0x002b, 0x002b};
void ST010_Raster(short Theta)
{
short data;
int offset = 0;
for (int i = 0; i < 176; i++)
{
data = ST010_M7Scale[i] * ST010_Cos(Theta) >> 15;
Memory.SRAM[0x00f0 + offset] = data;
Memory.SRAM[0x00f1 + offset] = data >> 8;
Memory.SRAM[0x0510 + offset] = data;
Memory.SRAM[0x0511 + offset] = data >> 8;
data = ST010_M7Scale[i] * ST010_Sin(Theta) >> 15;
Memory.SRAM[0x0250 + offset] = data;
Memory.SRAM[0x0251 + offset] = data >> 8;
if (data) data = ~data;
Memory.SRAM[0x03b0 + offset] = data;
Memory.SRAM[0x03b1 + offset] = data >> 8;
offset += 2;
}
}
08H - 2D Coordinate Rotation (Bit Perfect)
|
Input
|
$0000
|
integer(X0)
|
|
|
$0002
|
integer(Y0)
|
|
|
$0004
|
integer(Theta)
|
|
Output
|
$0010
|
integer(X1)
|
|
|
$0012
|
integer(Y1)
|
void ST010_Rotate(short Theta, short X0, short Y0, short &X1, short &Y1)
{
X1 = (Y0 * ST010_Sin(Theta) >> 15) + (X0 * ST010_Cos(Theta) >> 15);
Y1 = (Y0 * ST010_Cos(Theta) >> 15) - (X0 * ST010_Sin(Theta) >> 15);
}
Copyright 2003-2004 Snes9x DSP Team. Maintained by
Overload