Mercurial > touhou-doc
changeset 1:b1bec4b5ccf3
Add anm and pbg3 file formats, and improve the std one.
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> |
---|---|
date | Tue, 02 Aug 2011 14:18:01 +0200 |
parents | f82309a9465e |
children | 0a7e6e3d5327 |
files | 06/anm.xml 06/pbg3.xhtml 06/std.xhtml index.xhtml |
diffstat | 4 files changed, 415 insertions(+), 25 deletions(-) [+] |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/06/anm.xml @@ -0,0 +1,225 @@ +<?xml version="1.0" encoding="utf-8"?> +<?xml-stylesheet type="text/xsl" href="../html.xsl"?> +<?xml-stylesheet type="text/css" href="../style.css"?> +<!DOCTYPE html> +<opcodes xmlns="urn:opcodes:description"> + <title>ANM opcodes</title> + + <op> + <num>0</num> + </op> + + <op> + <num>1</num> + <name>set_sprite</name> + <params> + <param type="S">Sprite number.</param> + </params> + <desc>Displays a certain sprite, or change from the previous sprite.</desc> + </op> + + <op> + <num>2</num> + <name>set_scale</name> + <params> + <param type="f" default="in the sprite section">X factor.</param> + <param type="f" default="in the sprite section">Y factor.</param> + </params> + <desc>Resizes the current sprite.</desc> + </op> + + <op> + <num>3</num> + <params> + <param type="S"></param> + </params> + </op> + + <op> + <num>4</num> + <params> + <param type="S"></param> + </params> + </op> + + <op> + <num>5</num> + <params> + <param type="S"></param> + </params> + </op> + + <op> + <num>7</num> + <name>set_mirror</name> + <desc>Performs a scale of -1 on the x axis.</desc> + </op> + + <op> + <num>9</num> + <name>set_3d_rotation</name> + <params> + <param type="f">-x</param> + <param type="f">y</param> + <param type="f">-z</param> + </params> + <desc>Set a rotation for the current object.</desc> + </op> + + <op> + <num>10</num> + <params> + <param type="f"></param> + <param type="S"></param> + <param type="f"></param> + </params> + </op> + + <op> + <num>11</num> + <params> + <param type="f"></param> + <param type="f"></param> + </params> + </op> + + <op> + <num>12</num> + <params> + <param type="S"></param> + <param type="S"></param> + </params> + </op> + + <op> + <num>13</num> + </op> + + <op> + <num>14</num> + </op> + + <op> + <num>15</num> + <desc>A kind of return</desc> + </op> + + <op> + <num>16</num> + <params> + <param type="S"></param> + <param type="S"></param> + </params> + </op> + + <op> + <num>17</num> + <params> + <param type="f"></param> + <param type="f"></param> + <param type="f"></param> + </params> + </op> + + <op> + <num>18</num> + <params> + <param type="f"></param> + <param type="f"></param> + <param type="S"></param> + <param type="S"></param> + </params> + </op> + + <op> + <num>19</num> + <params> + <param type="f"></param> + <param type="f"></param> + <param type="S"></param> + <param type="S"></param> + </params> + </op> + + <op> + <num>20</num> + <params> + <param type="f"></param> + <param type="f"></param> + <param type="f"></param> + <param type="S"></param> + </params> + </op> + + <op> + <num>21</num> + </op> + + <op> + <num>22</num> + <params> + <param type="S"></param> + </params> + </op> + + <op> + <num>23</num> + <name>set_origin</name> + <desc>Apply transformations to the center of the quad, instead of its bottom-left corner.</desc> + </op> + + <op> + <num>24</num> + </op> + + <op> + <num>25</num> + <params> + <param type="S"></param> + </params> + </op> + + <op> + <num>26</num> + <params> + <param type="S"></param> + </params> + </op> + + <op> + <num>27</num> + <params> + <param type="f"></param> + </params> + </op> + + <op> + <num>28</num> + <params> + <param type="f"></param> + </params> + </op> + + <op> + <num>29</num> + <params> + <param type="S"></param> + </params> + </op> + + <op> + <num>30</num> + <params> + <param type="f"></param> + <param type="f"></param> + <param type="S"></param> + </params> + </op> + + <op> + <num>31</num> + <params> + <param type="S"></param> + </params> + </op> +</opcodes>
new file mode 100644 --- /dev/null +++ b/06/pbg3.xhtml @@ -0,0 +1,61 @@ +<?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>PBG3 format</title> + </head> + <body> + <h1>PBG3 format</h1> + <p>The PBG3 format is an archive format used by EoSD.</p> + + <p>It is a bitstream composed of a header, a file table, and LZSS-compressed files.</p> + + + <h2>Reading integers</h2> + <p>Integers in PBG3 files are never signed, they are not byte-aligned, and have a variable size.<br/> + Their size is given by two bits: 00 means the number is stored in one byte, 10 means it is stored in three bytes.</p> + + <p>Ex:</p> +<pre> + 0x0012 is stored as: 0000010010 + 0x0112 is stored as: 010000000100010010 +</pre> + + + <h2>Reading strings</h2> + <p>Strings are stored as standard NULL-terminated sequences of bytes.<br/> + The only catch is they are not byte-aligned.</p> + + + <h2>Header</h2> + <p>The header is composed of three fields:</p> + <ul> + <li>magic (string): "PBG3"</li> + <li>number of entries (integer)</li> + <li>offset of the file table (integer)</li> + </ul> + + <p>The size of the header is thus comprised between 52 bits and 100 bits.</p> + + + <h2>File table</h2> + <p>The file table starts at a byte boundary, but as the rest of the file, isn't byte-aligned.<br/> + It consists of a sequence of entries.<br/> + Each entry is composed of five fields:</p> + <ul> + <li>unknown1 (int) #TODO</li> + <li>unknown2 (int) #TODO</li> + <li>checksum (int): simple checksum of compressed data</li> + <li>size (int): size of uncompressed data</li> + <li>name (string): name of the file</li> + </ul> + + <p>The checksum is a mere sum of the compressed data.<br/> + Files are compressed using the LZSS algorithm, with a dictionary size of 8192 bytes and a minimum matching length of 4 bytes.<br/> + The size of the offset component of (offset, length) tuples is 13 bits, whereas the size of the length component is 4 bits.<br/> + A file ends with a (0, 0) tuple, that is, 18 zero bits.</p> + + <p>Uncompressing a LZSS-compressed file is quite easy, see lzss.py.</p> + </body> +</html>
--- a/06/std.xhtml +++ b/06/std.xhtml @@ -1,34 +1,135 @@ <?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="fr"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>STD format</title> </head> <body> <h1>STD format</h1> - <p>All integers are little endian, all number are hex.</p> <h2>Header</h2> - <pre> -0 - 2 - -2 - 2 - -4 - 4 - Size of something -8 - 2 - -a - 6 - Always zero -10 - 80 - Name of the stage -90 - 80 - Name of the first song -110 - 80 - Name of the second song -190 - 80 - A string of only a single whitespace -210 - 80 - A string of only a single whitespace -290 - 80 - path to the first song (as midi) -310 - 80 - path to the second song (as midi) -390 - 80 - A string of only a single whitespace -410 - 80 - A string of only a single whitespace -490 - ... - The real data</pre> +<pre> +typedef struct { + uint16_t nb_objects; //TODO + uint16_t nb_faces; //TODO + uint32_t faces_offset; //TODO + uint32_t messages_offset; //TODO + uint32_t unknown; //TODO: always 0 + char stage_name[128]; // Name of the stage in SHIFT_JIS + char song1_name[128]; // Name of the first song in SHIFT_JIS + char song2_name[128]; // Name of the second song in SHIFT_JIS + char song3_name[128]; // ? A single blank if unused + char song4_name[128]; // ? A single blank if unused + char song1_path[128]; + char song2_path[128]; + char song3_path[128]; // ? A single blank if unused + char song4_path[128]; // ? A single blank if unused +} thstd_header_t; +</pre> + + <h2>First section</h2> + <p>This section is responsible for creating objects from the stgxbg.anm file.</p> +<pre> +struct object_header { + uint16_t id; // Always equal to the object's number. Not used by the game. + uint16_t unknown1; //TODO + float unknown2; //TODO + uint32_t unknown3; //TODO + float unknown4; //TODO + float unknown5; //TODO + float unknown6; //TODO + float unknown7; //TODO +}; + +typedef struct { + uint16_t unknown; // 0 means a quad, 0xffff means the end. + uint16_t size; // 0x1c for a quad, 4 for the end marker. + uint16_t script_index; // Index of a script entry in the corresponding anm file + uint16_t _padding; // Unused, padding + float x; // x coordinate of the bottom-left corner of the quad + float y; // y coordinate of the bottom-left corner of the quad + float z; // z coordinate of the bottom-left corner of the quad + float width; // If 0, defaults to 32.0f + float height; // If 0, defaults to 32.0f +} thstd_object_t; + +struct object { + struct object_header header; + struct object_quad quads[]; // Stop when quads.unknown1 == 0x0004ff +}; +</pre> + + <p>The following description is symbolic.</p> +<pre> +struct section1 { + uint32_t offsets[]; // header.nb_objects offsets towards objects +};*/ +</pre> + - <h2>Data</h2> - <pre> -0 - ... - ... + <h2>Second section</h2> + <p>This section is responsible for placing objects from section 1 in the space.</p> +<pre> +typedef struct { + uint16_t object_id; // must not exceed header.nb_objects + uint16_t unknown1; // Always 256, doesn't seem to change anything + float x; + float y; + float z; +} thstd_face_t; +// ends with 16 \xFF +</pre> + + + + <h2>Third Section</h2> + <p>This section is responsible for camera movement, color effects, and such things.</p> +<pre> +typedef struct { + uint32_t frame_num; + uint16_t type; // 1=colormsg + uint16_t unknown; //TODO: Probably the size of the message, always 0x0c, ignored by the game + uint32_t arg1; + float arg2; + float arg3; +} thstd_message_t; + +typedef struct { + uint8_t b; + uint8_t g; + uint8_t r; + uint8_t unknown1; // Seems useless. padding? +} color_t; + +typedef struct { + color_t color; + float opacity_gradient_start; //TODO + float opacity_gradient_stop; //TODO +} thstd_colormsg_t; + +typedef struct { + float x; + float y; + float z; +} thstd_cameramsg_t; +// ends with 20 \xFF +</pre> + + + + + + + +<pre> +typedef struct { + thstd_header_t header; + uint32_t* offsets; + list_t objects; + list_t faces; + list_t messages; +} PACK_ATTRIBUTE thstd_t; </pre> </body> </html>
--- a/index.xhtml +++ b/index.xhtml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr"> +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head> <title>Touhou</title> </head> @@ -9,23 +9,26 @@ <h2>Embodiment of Scarlet Devil</h2> <h3>Formats</h3> <ul> + <li><a href="06/pbg3.xhtml">PBG3</a> (dat archives)</li> <li><a href="06/std.xhtml">STD</a> (stages)</li> </ul> <h3>Opcodes</h3> <ul> - <li><a href="06/std.xhtml">STD</a> (stages)</li> + <li><a href="06/anm.xml">STD</a> (stages)</li> <li><a href="06/ecl.xml">ECL</a> (enemy comportement)</li> <li><a href="06/msg.xml">MSG</a> (dialogs)</li> </ul> <h2>Mountain of Faith</h2> <ul> - <li><a href="10/ecl.xml">ECL</a> (<a href="http://code.google.com/p/thtk/wiki/Ecl10Reference">original</a>)</li> + <li><a href="10/ecl.xml">ECL</a> (<a href="//code.google.com/p/thtk/wiki/Ecl10Reference">original</a>)</li> </ul> <h2>Subterranean Animism</h2> <ul> - <li><a href="http://code.google.com/p/thtk/wiki/Ecl11Reference">ECL</a></li> + <li><a href="//code.google.com/p/thtk/wiki/Ecl11Reference">ECL</a></li> </ul> + + <p>The sources are <a href="//hg.linkmauve.fr/touhou-doc">here</a></p> </body> </html>