view 06/t6rp.xhtml @ 13:2925b0e246c6 default tip

Fix a lot of things, and add a TODO.
author Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
date Fri, 17 Feb 2012 12:54:08 +0100
parents 9f0e37b7eeab
children
line wrap: on
line source

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/css" href="../style.css"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
	<head>
		<title>T6RP format</title>
	</head>
	<body>
		<h1>T6RP format</h1>
		<p>The T6RP format is the replay format used by EoSD.</p>

		<p>It is composed of a header and an “encrypted” data section, which is itself composed of a header, per-stage structures and lists of keystates.</p>


		<h2>Header</h2>
<pre>
typedef struct {
    char magic[4]; // T6RP
    uint16_t version; // 0x0102 for 1.02h
    uint8_t player; // 0 = ReimuA, 1 = ReimuB, 2 = MarisaA, 3 = MarisaB
    uint8_t rank; // 0 = Easy, 3 = Lunatic, 4 = Extra
    uint32_t checksum; // (0x3f000318 + key + sum(c for c in decrypted_data)) % (2 ** 32)
    uint16_t unknown2; //TODO: seems to be ignored by the game.
    uint8_t key;
    char crypted_data[]; // crypted(a, i) = (a + key + 7*i) % 256
                         // decrypted(c, i) = (c - key - 7*i) % 256
} thrpy6_header_t;
</pre>

		<h2>Decrypting the data section</h2>
		<p>As stated earlier, the data section is encrypted. Luckily, this encryption is quite simplistic, and encrypting/decrypting it is easy (see this snippet of python3 code):</p>
<pre>
def decrypt(key, data):
    return bytes((c - key - 7 * i) % 256 for i, c in enumerate(data))

def encrypt(key, data):
    return bytes((c + key + 7 * i) % 256 for i, c in enumerate(data))
</pre>

		<h2>Encrypted header</h2>
<pre>
typedef struct {
    uint8_t unknown; //TODO: seems to be ignored by the game. Padding?
    char date[9]; // null-terminated string
    char name[9]; // null-terminated string
    uint16_t unknown2; //TODO: seems to be ignored by the game. Padding?
    uint32_t score; //TODO: Total score. seems to be ignored by the game.
    uint32_t unknown3; //TODO: seems to be ignored by the game.
    float slowdown_rate; // As a percentage, not a proper rate
    uint32_t unknown4; //TODO: seems to be ignored by the game.
    uint32_t stage1_offset; // Offset of a thrpy6_stage_t from the start of the file (including the unencrypted header)
    uint32_t stage2_offset;
    uint32_t stage3_offset;
    uint32_t stage4_offset;
    uint32_t stage5_offset;
    uint32_t stage6_offset;
    uint32_t stage7_offset;
} thrpy6_encrypted_header;
</pre>

		<h2>Stage entry</h2>
<pre>
typedef struct {
    uint32_t score;
    uint16_t random_seed;
    uint16_t unknown1; //TODO: seems to be ignored by the game.
    uint8_t power;
    int8_t lives;
    int8_t bombs;
    uint8_t difficulty; //TODO: WARNING: This has a huge effect on the game!
    // It is also called rank (but we use the term “difficulty” because “rank” is the official name for Easy/Normal/Hard/Lunatic/Extra)
    // See: http://en.touhouwiki.net/wiki/Embodiment_of_Scarlet_Devil/Gameplay#Rank
    uint32_t unknown3; //TODO: seems to be ignored by the game. Padding?
    thrpy6_keystate_t keystates[];
} thrpy6_stage_t;
</pre>

		<h2>Keystates</h2>
<pre>
struct {
    uint32_t time; // Time of the event, most probably exprimed in frames.
    uint16_t keys; // 1 = shoot, 2 = bomb, 4 = focus, 8 = ?, 16 = up, 32 = down, 64 = left, 128 = right, 256 = skip dialogs
    uint16_t unknown; //TODO: seems to be ignored by the game.
} thrpy6_keystate_t;
</pre>
	</body>
</html>