ST-0010 Gamepaks

F1 Race of Champions 2 Exhaust Heat F1 Driver Locus

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