# HG changeset patch # User Emmanuel Gil Peyrot # Date 1329479648 -3600 # Node ID 2925b0e246c6ec7376369e51130e2c05badcb69b # Parent 79dfd9765a67911fdafc6e94f60ebadc786e76c6 Fix a lot of things, and add a TODO. diff --git a/06/anm.xml b/06/anm.xml --- a/06/anm.xml +++ b/06/anm.xml @@ -1,12 +1,12 @@ - ANM opcodes 0 + delete @@ -96,17 +96,19 @@ 12 fade - + 13 + set_blendfunc_alphablend 14 + set_blendfunc_add @@ -127,6 +129,7 @@ 17 + set_3d_translation @@ -136,43 +139,53 @@ 18 + move_to_linear - - - - + + + + + Move the sprite in the indicated coordinates in `duration` seconds. 19 + move_to_decel - - - - + + + + + Move the sprite in the indicated coordinates in `duration` seconds. 20 + move_to_accel - - - - + + + + + Move the sprite in the indicated coordinates in `duration` seconds. 21 + wait_event + Wait for an event. 22 + set_event + Set the event number to wait for. @@ -184,13 +197,17 @@ 24 + ?_event + Has something to do with events. 25 + set_allow_dest_offset + @@ -222,9 +239,11 @@ 29 + + @@ -240,8 +259,10 @@ 31 + + diff --git a/06/cfg.txt b/06/cfg.txt new file mode 100644 --- /dev/null +++ b/06/cfg.txt @@ -0,0 +1,54 @@ +0: 00 +1: 00 +2: 01 +3: 00 +4: 00 +5: 00 +6: ff +7: ff +8: ff +9: ff +a: ff +b: ff +c: ff +d: ff +e: ff +f: ff +10: ff +11: ff +12: 00 +13: 00 +14: 02 +15: 01 +16: 00 +17: 00 +18: 02 +19: 03 +1a: 00 = 32 bits, 01 = 16 bits +1b: 02 +1c: 01 +1d: 01 +1e: 00 = fullscreen, 01 = windowed +1f: 00 = 1/1, 01 = 1/2, 02 = 1/3 +20-21: uint16_t, Pad X Axis +22-23: uint16_t, Pad Y Axis +24: 00 +25: 00 +26: 00 +27: 00 +28: 00 +29: 00 +2a: 00 +2b: 00 +2c: 00 +2d: 00 +2e: 00 +2f: 00 +30: 00 +31: 00 +32: 00 +33: 00 +34: 01 = nothing, 02 = No Vertex buffer, 04 = 16 Bits textures, 08 = Clear back buffer on refresh, 10 = Display minimum graphics needed, 20 = Controlled use of gouraud shading, 40 = No Depth Test, 80 = Force 60 fps +35: 00 = nothing, 01 = Color composition is not applied to textures, 02 = Start in reference rasterized mode, 04 = No fog, 08 = No DirectInput Pad +36: 00 +37: 00 diff --git a/06/ecl.xhtml b/06/ecl.xhtml --- a/06/ecl.xhtml +++ b/06/ecl.xhtml @@ -59,13 +59,12 @@ typedef struct { float x; float y; float z; // Unused, always 0. - int16_t resistance; // From 0 to 0x7fff; greater is equal to 0. + int16_t life; // From 0 to 0x7fff; lower than 0 is equal to 1. int16_t object_dropped; // Between -2 and 2. - // 0000 to 00ff: power - // ff00 to ffff: random + // 0 to 6: corresponding bonus + // -1: random // other: nothing - uint16_t unknown1; - uint16_t unknown2; // 0 for normal enemies; 1 for mid-boss; 3 or 4 for boss. + uint32_t die_score; } thecl_enemy_t; @@ -103,9 +102,9 @@ typedef struct {
  • normal enemy
  • mirrored enemy
  • mirrored enemy
  • -
  • normal enemy
  • +
  • normal enemy (random placement)
  • normal enemy (random placement)
  • -
  • mirrored enemy
  • +
  • mirrored enemy (random placement)
  • mirrored enemy (random placement)
  • starts the msg (which?)
  • nothing?
  • diff --git a/06/ecl.xml b/06/ecl.xml --- a/06/ecl.xml +++ b/06/ecl.xml @@ -1,7 +1,6 @@ - ECL Sub format @@ -50,13 +49,13 @@ else -10014int difficulty ro Unused. -10015float x rw -10016float y rw - -10017float z rw + -10017float z rw Actually used by Flandre. Warning! -10018float player_x ro -10019float player_y ro -10020float ro Unused. - -10021float enemy_player_angle ro + -10021float player_angle ro -10022int last_frame rw - -10023float enemy_player_distanceroUnused. + -10023float player_distancero Unused. -10024int life rw -10025int player ro 0 = ReimuA, 1 = ReimuB, 2 = MarisaA, 3 = MarisaB @@ -337,7 +336,7 @@ else - Like 2 but only when the comparison register equals to 1. Used only one time in 4. + Like 2 but only when the comparison register equals to 1. @@ -445,7 +444,7 @@ else - Set the enemy angle in the [min, max-min) range. Used only five times, in 2. + Set the enemy angle in the [min, max-min) range. @@ -465,7 +464,7 @@ else Ignored - Sets the speed of the enemy, and change its direction to where the player is at that frame. Used only one time in 2. + Sets the speed of the enemy, and change its direction to where the player is at that frame. @@ -488,7 +487,7 @@ else Ignored - Move the enemy to the new position in `duration` amount of frames, using the x↦x function. Used only two times in 7. + Move the enemy to the new position in `duration` amount of frames, using the x↦x function. @@ -571,102 +570,42 @@ else 68 set_bullet_attributes_to_the_right - - - - - - - - - - - + The same as 67, except the 0.0f launch angle is to the right of the enemy, instead of towards the player. 69 set_bullet_attributes_towards_player_equally_distributed - - - - - - - - - - - + Like 67, except bullets of a shot are distributed equally all around the enemy, computing the angle by itself. 70 set_bullet_attributes_to_the_right_equally_distributed - - - - - - - - - - - + Like 68, except bullets of a shot are distributed equally all around the enemy, computing the angle by itself. 71 set_bullet_attributes_towards_player_equally_distributed_and_rotated - - - - - - - - - - - + Like 69, but with a rotation of pi/bullets_per_shot. 74 set_bullet_attributes_towards_player_randomly_distributed - - - - - - - - - - - - Used only one time, in 3. Like 70 but with some alea (?) in the angle. + + Like 70 but with some alea (?) in the angle. 75 set_bullet_attributes_to_the_right_with_some_random_angle - - - - - - - - - - - + Like 68, but with some random angle. @@ -752,7 +691,7 @@ else
    1024: 82(int nb_bounces,,,, float speed,,,)
    Bullets “bounce”, reentering the screen as soon as they leave it, with a new speed set.
    2048:
    -
    Like 1024, except it only bounces when colliding with the left and right edges.
    +
    Like 1024, except it only bounces when colliding with the left, upper and right edges.
    @@ -774,13 +713,13 @@ else 85 laser - - - clockwise, from the +x axis + + + clockwise speed of the laser along its axis offset along the laser axis, relative to the enemy. If negative, it is considered as 0. offset along the laser axis, relative to the enemy. Can be negative. In case end_offset < start_offset, the laser will be in the oposite direction. - TODO: Not really a length, something really odd. The laser starts at max(start_offset, end_offset - length) and ends at end_offset. + TODO: Not really a length, something really odd. The laser starts at max(start_offset, end_offset - length) and ends at end_offset. @@ -795,22 +734,7 @@ else 86 laser_towards_player - - - - clockwise, from the enemy->player axis - speed of the laser along its axis - offset along the laser axis, relative to the enemy. If negative, it is considered as 0. - offset along the laser axis, relative to the enemy. Can be negative. In case end_offset < start_offset, the laser will be in the oposite direction. - TODO: Not really a length, something really odd. The laser starts at max(start_offset, end_offset - length) and ends at end_offset. - - - - - how long to wait before allowing grazing - how long to allow grazing after the laser started to disappear - - + Like 85, with the default direction towards the player. @@ -835,40 +759,56 @@ else 90 - + translate_laser - - Perhaps a float? - Perhaps a float? - Perhaps a float? + + + + Ignored - Used only in 7. + Translate a laser with the current position of the launching enemy as origin, but don’t follow her after that. 92 - + cancel_laser - + - Used only in 7. + Cancel a laser before its normal duration. 93 set_spellcard - + If greater than 3, it’s the character faces that are used. As in the captured spellcards screen, minus 1. In SHIFT_JIS - + +

    Start a spellcard and

    +
      +
    • Display the name of the spellcard in the screen.
    • +
    • Change the background to the eff one.
    • +
    • Make the enemies more resistant or the attacks weaker. The damage caused by a bullet is reduced to 6 instead of 48.
    • +
    • Clear all the bullets and transform them in star bonus.
    • +
    +
    94 end_spellcard - Finish the current spellcard. + +

    Finish the current spellcard and

    +
      +
    • Remove its name.
    • +
    • Put back the normal background.
    • +
    • Return the damages to the normal.
    • +
    • Clear all the bullets and transform them in star bonus.
    • +
    +
    @@ -881,8 +821,7 @@ else - - +
    Spawns an enemy, see the main creation of an enemy.
    @@ -890,7 +829,7 @@ else 96 kill_all_enemies - Instantly kill all enemies presents in the screen, dropping their bonus as if they were killed by the player. Seems to not kill if the enemy is not touchable (see 117). + Instantly kill all enemies presents in the screen, dropping their bonus as if they were killed by the player. Seems to not kill if the enemy is not touchable (see 117) or a boss (see 101). @@ -918,12 +857,12 @@ else 99 - + set_aux_anim - - + + - + Add an auxiliary animation (up to 8) with always the same coordinates as the enemy. @@ -939,9 +878,9 @@ else 101 set_boss_mode - Unknown meaning, seems to be 0 for mid-boss and -1 for real boss. + 0 is activate, -1 is deactivate. - Activates the boss mode, with her life bar and lives number displayed on the top. Doesn't do anything before calling 126. + Activates the boss mode, with her life bar and lives number displayed on the top. Doesn't do anything before calling 126 (TODO: really?). If there are multiple boss, spawned by a 95, only the last one has her life displayed, but standard enemies are blocked only until any of them is killed. @@ -1005,7 +944,14 @@ else - Control what to do when life falls to zero. 0 = normal, 1 = don't clean the sprite, 2 = don't die, 4 (unused) = don't die and don't drop bonus. These are flags that can be combined. + +

    Control what to do when life falls to zero, only in the [0, 7] interval:

    +

    0 = normal;
    + 1 = die once and unset touchable/collidable;
    + 2 = die in loop (drop an item each time, start a new die animation), but keep being here, touchable/collidable;
    + 3 = die once and keep being touchable/collidable if killed by the normal attack, else die as in normal (with a bomb, a collision, a 96…), even after dying once from a normal attack;
    + 4-7 (unused) = die in loop, with lot of sparks, but don't drop bonus.

    +
    @@ -1014,7 +960,7 @@ else - Specify the subroutine to call when the enemy is killed. + Specify the subroutine to call when the enemy is killed. Only if the death flag is not null. @@ -1140,16 +1086,19 @@ memory[offset] = value; FunctionDescription 0Freeze all the bullets in the screen if the parameter is 0, else unfreeze them. Do an explosion animation too. 1Launch a bullet immediately, with a launch_offset of [-param, param] for each coordinate. - 3Do nothing? + 3Change the -10002, -10003 and -10004 variables according to the character. [0, 3, 1] for ReimuA, [2, 3, 4] for ReimuB, [1, 4, 0] for MarisaA and [4, 2, 3] for MarisaB. Used to choose the dual-sign spellcards of Patchouli. The parameter is unused. 4If 0, unfreeze time and do an explosion animation. If 1, freeze time for the player, the bullets, the texts, but let the ECL run normally, also do an explosion animation. Else do nothing. 7If 0, make a lasers web, and remove any previous. Else, a crapload of bullets directed towards the player (TODO: find their origin). 8Do nothing? 9Do an explosion animation. 11Do an explosion animation. 12Do nothing? - 13Launch `param` bullets in circle towards the player with the launch point being the center of the screen. + 13Fire `param` times the configured attack in circle, as if the enemy was at the center of the screen with:
      +
    • -10006 that overrides the launch_angle set in 67-75;
    • +
    • -10007 the rotation of the launch points with the center of the screen as origin;
    • +
    • -10008 the distance between the center of the screen and the launch points.
    Seems to be launched only each 6 frames, even if the call is each frame. 14Do nothing? - 16Do nothing? + 16Used in QED: Ripples of 495 Years and probably do a temporization and modify launch_offset.
    @@ -1167,9 +1116,9 @@ memory[offset] = value; -1Stop 2Do nothing? 5Sakuya’s knives, each 12 frames. - 6Some graphic animation. + 6Add a wings flapping animation. Used by the Scarlet sisters. 10Some graphic animation. - 15Some graphic animation. + 15The bullets 6, 7, 8 and 9 push the 1, 2, 3, 4 and 5 bullets. Also do some graphic animation.
    @@ -1187,7 +1136,7 @@ memory[offset] = value; 124 drop_specific_bonus - 0 = power, 1 = point, 2 = big power, 3 = bomb, 4 = full power, 5 = 1up, 6 = star bonus, greater drop nothing. + 0 = power, 1 = point, 2 = big power, 3 = bomb, 4 = full power, 5 = 1up, 6 = star bonus, greater drop nothing. Drop a bonus vertically. Can be called multiple times to drop more items, but they'll be superposed. @@ -1218,11 +1167,11 @@ memory[offset] = value; 128 - set_smooth_disappear + interrupt_anm - Bitfield + - If x & 1, make the enemy sprite diseappear in a fade out now, not abruptly at 1. TODO: check the duration. + Send this interruption to the anm. @@ -1246,25 +1195,27 @@ memory[offset] = value; 131 - + set_difficulty_influence - - - - - - + + + + + + - + Change the influence of the difficulty on the attacks. The defaults are (-0.5f, 0.5f, 0, 0, 0, 0). 132 - set_visible + set_invisible Bitfield - If x & 1, disable drawing of the sprite and destroy it. While it isn’t set to 0, loading a new sprite won’t make it reappear. +
    + If x & 1, disable drawing of the sprite and destroy it. While it isn’t set to 0, loading a new sprite won’t make it reappear. +
    @@ -1281,10 +1232,10 @@ memory[offset] = value; 135 - + enable_spellcard_bonus Bitfield - + If x & 1, FIXME. Enabled is the default.
    diff --git a/06/msg.xml b/06/msg.xml --- a/06/msg.xml +++ b/06/msg.xml @@ -1,7 +1,6 @@ - MSG opcodes @@ -13,10 +12,10 @@ 1 - + enter - - + 0 is left, 1 is right. + @@ -25,8 +24,8 @@ 2 change_face - Affected girl (0 is left, 1 is right) - Sprite to use. + + @@ -35,9 +34,9 @@ 3 display - Girl speaking (0 is left, 1 is right) - Line to which display. - The text to display. + + 0 is top, 1 is bottom. + Only one line. Displays a line of text. @@ -46,7 +45,7 @@ 4 pause - Number of frames to wait. + Wait for the user to provide an input, or timeout. @@ -55,8 +54,8 @@ 5 switch - Affected girl (0 is left, 1 is right) - Animation to use (0=?; 1=appear; 2=unused (leave too?); 3=front; 4=back; 5=leave) + + Animation to use (0=?; 1=appear; 2=unused (leave too?); 3=front; 4=back; 5=leave) Makes one of the two girls come to or leave the screen. @@ -71,7 +70,7 @@ 7 music - Music number. + Plays the selected music. @@ -80,26 +79,26 @@ 8 display2 - Girl speaking (0 is left, 1 is right) - Line to which display. - The text to display. + + 0 is top, 1 is bottom. + Only one line. Displays a line of text on a character. Always used to introduce her. 9 - + show_scores - + Unused? - + Display the score panel. 10 - - + freeze + Disable the input and fige the pause. @@ -116,11 +115,11 @@ 13 - + allow_skip - + boolean - + If 0 disallow, if 1 allow. diff --git a/06/pbg3.xhtml b/06/pbg3.xhtml --- a/06/pbg3.xhtml +++ b/06/pbg3.xhtml @@ -44,7 +44,7 @@ It consists of a sequence of entries.
    Each entry is composed of five fields:

      -
    • unknown1 (int) #TODO
    • +
    • unknown1 (int): the same for every entry of an archive, and without much change between two archives #TODO
    • unknown2 (int) #TODO
    • checksum (int): simple checksum of compressed data
    • size (int): size of uncompressed data
    • diff --git a/06/std.xhtml b/06/std.xhtml --- a/06/std.xhtml +++ b/06/std.xhtml @@ -32,16 +32,18 @@ typedef struct {

      First section

      This section is responsible for creating objects from the stgxbg.anm file.

      -struct object_header {
      +typedef struct {
           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
      -};
      +    uint16_t unknown; //TODO
      +
      +    // The bounding box.
      +    float x;
      +    float y;
      +    float z;
      +    float width;
      +    float height;
      +    float depth;
      +} object_header_t;
       
       typedef struct {
           uint16_t unknown; // 0 means a quad, 0xffff means the end.
      @@ -55,10 +57,10 @@ typedef struct {
           float height; // If not 0, override the sprite's height (else, use anm info)
       } thstd_object_t;
       
      -struct object {
      +typedef struct {
           struct object_header header;
           struct object_quad quads[]; // Stop when quads.unknown == 0x0004ff
      -};
      +} object_t;
       
      @@ -146,7 +148,7 @@ typedef struct { list_t objects; list_t faces; list_t messages; -} PACK_ATTRIBUTE thstd_t; +} thstd_t; diff --git a/06/t6rp.xhtml b/06/t6rp.xhtml --- a/06/t6rp.xhtml +++ b/06/t6rp.xhtml @@ -9,15 +9,14 @@

      T6RP format

      The T6RP format is the replay format used by EoSD.

      -

      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.

      +

      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.

      Header

       typedef struct {
           char magic[4]; // T6RP
      -    uint16_t unknown; //TODO: always 0x0102
      -                      // Seems to be a switch, if 0x0102 do something, else (whatever the value is), do something else
      +    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)
      @@ -69,9 +68,9 @@ typedef struct {
           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)
      +    // 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
      -    uint8_t unknown3[3]; //TODO: seems to be ignored by the game. Padding?
      +    uint32_t unknown3; //TODO: seems to be ignored by the game. Padding?
           thrpy6_keystate_t keystates[];
       } thrpy6_stage_t;
       
      diff --git a/07/sht.xhtml b/07/sht.xhtml new file mode 100644 --- /dev/null +++ b/07/sht.xhtml @@ -0,0 +1,73 @@ + + + + + + SHT format + + +

      SHT format

      +

      The SHT format defines a character and its shots in PCB.

      + + +

      Header

      +
      +typedef struct {
      +    uint16_t unknown1; // Seems ignored
      +    uint16_t level_count;
      +
      +    // All hitboxes have only one value, the same for the width and the height.
      +    float bombs; // Why is it a float?
      +    float unknown2; //TODO
      +    float hitbox;
      +    float graze_hitbox;
      +    float autocollected_item_speed; // Applies to all items going towards us
      +    float item_hitbox;
      +    float percentage_of_cherry_loss_on_die; //TODO: verify the formula
      +    float point_of_collection;
      +    float horizontal_vertical_speed;
      +    float horizontal_vertical_focused_speed;
      +    float diagonal_speed;
      +    float diagonal_focused_speed;
      +
      +    thsht_offset_t offsets[level_count];
      +
      +    thsht_shot_type_t shots[];
      +} thsht_header_t;
      +
      + +
      +typedef struct {
      +    uint32_t offset;
      +    uint32_t power;
      +} thsht_offset_t;
      +
      + +

      Shot type

      +
      +typedef struct {
      +    // If these 2 are 0xffff, then end the parsing.
      +    uint16_t interval;
      +    uint16_t unknown1;
      +
      +    float x;
      +    float y;
      +    float hitbox_x;
      +    float hitbox_y;
      +    float angle;
      +    float speed;
      +    uint16_t damage;
      +    uint8_t orb; // 0 = character, 1 = left orb, 2 = right orb
      +    uint8_t unknown2;
      +    uint16_t sprite;
      +    uint16_t unknown3;
      +
      +    // These 4 are actually booleans.
      +    uint32_t unknown4;
      +    uint32_t homing; // accelerates too
      +    uint32_t unknown5;
      +    uint32_t unknown6;
      +} thsht_shot_type_t;
      +
      + + diff --git a/10/ecl.xml b/10/ecl.xml --- a/10/ecl.xml +++ b/10/ecl.xml @@ -1,7 +1,6 @@ - ECL opcodes diff --git a/TODO.txt b/TODO.txt new file mode 100644 --- /dev/null +++ b/TODO.txt @@ -0,0 +1,19 @@ +Documentation +- 10 instructions ECL restantes +- des fonctions hardcodées +- 3 instructions ANM restantes +- 4 instructions MSG restantes +- instructions END + +Moteur +- vm END +- homing de ReimuA, lasers de MarisaB +- les textes, OSD +- les effets genre explosions, carrés +- les bombes +- changement de niveau +- interface +- MUSIC! + +Plus tard +- Perfect Cherry Blossom diff --git a/html.xsl b/html.xsl --- a/html.xsl +++ b/html.xsl @@ -33,7 +33,13 @@ + + + + + + @@ -45,17 +51,18 @@ - + + - - - - - + + + + + - +
      TypeNameUnitVariableNotesValuesNameUnitVariableNotesValues
      @@ -97,14 +104,18 @@
      +

      - - + + + + -

      +
      +

      diff --git a/index.xhtml b/index.xhtml --- a/index.xhtml +++ b/index.xhtml @@ -13,6 +13,7 @@
    • STD (stages)
    • ECL (enemies and patterns)
    • T6RP (replays)
    • +
    • CFG (configuration)

    Opcodes

      @@ -21,16 +22,25 @@
    • MSG (dialogs)
    + +

    Perfect Cherry Blossom

    +

    Formats

    +
      +
    • SHT (characters)
    • +
    + +

    Mountain of Faith

    +

    Subterranean Animism

    -

    The sources are here

    +

    The sources are here, and a reimplementation in python is here.