About

MSX F1-Spirit password generator

F1-Spirit was one of my favorite MSX games. You could generate a password to save your result in the races. This page contains a generator and the corresponding javascript code to show how the password was constructed. It has a method of obfuscation which uses a block of bytes in the ROM. This block of data is different in the European and Japanese version (as far as I can tell). Therefor you can select the ROM version you are using.

Please contact me if you have any questions: rainier@meusesoft.com

Built-in cheat codes

MITAIYOENDDEMO: Show the end demo
MAXPOINT: Maximum points for all races
ESCON: Enable F5 to exit race
ESCOFF: Disable F5 to exit race
HYPEROFF: Pits early entry

Password generator

Javascript code

function Generate() {

	var password = GeneratePassword();

	document.getElementById("password").innerHTML = password;
}

function GeneratePassword() {

	var points = [];

	const European = [0xcd, 0x01, 0x51, 0xcd, 0xb3, 0x52, 0xc3, 0xd4, 0x52, 0xcd, 0xfc, 0x50, 0x20, 0x05, 0x3a, 0xc8, 0xe1, 0xe6, 0x02, 0xc4, 0x65, 0x50, 0xaf, 0x32, 0x50, 0xea, 0x3a, 0x51, 0xe2, 0x3d, 0x28, 0x4c, 0xf2, 0x7c, 0x50, 0xdd, 0x21, 0xb1, 0xe9, 0x06, 0x02];
	const Japanese = [0xcd, 0xf3, 0x50, 0x20, 0x05, 0x3a, 0xc8, 0xe1, 0xe6, 0x02, 0xc4, 0x5c, 0x50, 0xaf, 0x32, 0x50, 0xea, 0x3a, 0x51, 0xe2, 0x3d, 0x28, 0x4c, 0xf2, 0x73, 0x50, 0xdd, 0x21, 0xb1, 0xe9, 0x06, 0x02, 0x11, 0x08, 0x00, 0xdd, 0x7e, 0x05, 0xa7, 0x28, 0x05];

	//Initialise variables
	EuropeanRom = document.getElementById("version").value == "European";
	Random = parseInt(document.getElementById("random").value);
	points[0] = Random;

	//Populate array with the points per race
	for (i = 1; i < 22; i++)
	{
		var elementId = i.toString();
		var element = document.getElementById(elementId);
		points[i] = parseInt(element.value);
	}

	//Checksum
	var c1 = 0;
	var c2 = 0;

	for (i = 0; i < 22; i++) {

		var a = points[i];
		c1 = a ^ c1;
		c2 = a + c2;
		c2 = c2 & 0xff;
	}

	c1 = c1 & 0x0f;

	points[22] = c1;

	c1 = c1 & 0x0f;
	c2 = c1 + c2
	c2 = c2 & 0x0f;

	points[23] = c2;

	//Obfuscate
	for (i = 0; i < 23; i++)
	{
		byteValue = 0;

		if (EuropeanRom) {
			byteValue = European[i + Random]; 		
		}
		else {
			byteValue = Japanese[i + Random];
		}

		byteValue = byteValue & 0x0f;
		byteValue = byteValue ^ points[i+1];
		byteValue = byteValue & 0x1f;

		points[i+1] = byteValue;
	}

	//Add 65 to every value to get them in the ASCII range of capital characters A-Z
	for (i = 0; i < 24; i++)
	{
		points[i] = points[i] + 65;
	}

	//Construct the password by convert the integer values to chars
	password = "";
	for (i = 0; i < 24; i++) {

		password += String.fromCharCode(points[i]);
	}

	return password;
}
				

Addresses

These are addresses of interesting entry points for the European ROM version:
#72A9: start of encoding points per race into a password.
#7467: check if a built-in password is entered.
#EA52: location of generated / entered password.