diff options
| author | Touched <jtouched@gmail.com> | 2017-06-26 15:08:59 +0200 | 
|---|---|---|
| committer | Touched <jtouched@gmail.com> | 2017-06-30 21:25:45 +0200 | 
| commit | a27a90423d9e46461e803f9049fb4b90600c5003 (patch) | |
| tree | a0dccaeda7e1c7200b87d7b6042ecc180b742c7d | |
| parent | 4ccd42ebf610fb1c4e423dbad8674a35ffccc9d2 (diff) | |
Label rotating_gate.c
| -rw-r--r-- | src/rotating_gate.c | 902 | 
1 files changed, 549 insertions, 353 deletions
| diff --git a/src/rotating_gate.c b/src/rotating_gate.c index e22be3221..665a16ae4 100644 --- a/src/rotating_gate.c +++ b/src/rotating_gate.c @@ -1,64 +1,236 @@  #include "global.h"  #include "bike.h"  #include "event_data.h" +#include "field_map_obj.h"  #include "fieldmap.h" +#include "map_constants.h" +#include "songs.h"  #include "sound.h"  #include "sprite.h" -struct UnknownStruct +#define ROTATING_GATE_TILE_TAG 0x1300 +#define ROTATING_GATE_PUZZLE_MAX 14 +#define GATE_ARM_MAX_LENGTH 2 + +#define GATE_ROTATION(rotationDirection, arm, longArm)                                             \ +    ((rotationDirection & 15) << 4) | ((arm & 7) << 1) | (longArm & 1) +#define GATE_ROTATION_CLOCKWISE(arm, longArm) GATE_ROTATION(ROTATE_CLOCKWISE, arm, longArm) +#define GATE_ROTATION_ANTICLOCKWISE(arm, longArm) GATE_ROTATION(ROTATE_ANTICLOCKWISE, arm, longArm) +#define GATE_ROTATION_NONE 255 + +static void SpriteCallback_RotatingGate(struct Sprite *sprite); +static u8 RotatingGate_CreateGate(u8 gateId, s16 deltaX, s16 deltaY); +static void RotatingGate_HideGatesOutsideViewport(struct Sprite *sprite); + +enum +{ +    /* +     * | +     * +-- +     */ +    GATE_SHAPE_L1, + +    /* +     * | +     * | +     * +-- +     */ +    GATE_SHAPE_L2, + +    /* +     * | +     * +---- +     */ +    GATE_SHAPE_L3, + +    /* +     * | +     * | +     * +---- +     */ +    GATE_SHAPE_L4, + +    /* +     * | +     * +-- +     * | +     */ +    GATE_SHAPE_T1, + +    /* +     * | +     * | +     * +-- +     * | +     */ +    GATE_SHAPE_T2, + +    /* +     * | +     * +---- +     * | +     */ +    GATE_SHAPE_T3, + +    /* +     * An unused T-shape gate +     * | +     * +-- +     * | +     * | +     */ +    GATE_SHAPE_T4, + +    /* +     * An unused T-shape gate +     * | +     * | +     * +---- +     * | +     */ +    GATE_SHAPE_UNUSED_T1, + +    /* +     * An unused T-shape gate +     * | +     * | +     * +-- +     * | +     * | +     */ +    GATE_SHAPE_UNUSED_T2, + +    /* +     * An unused T-shape gate +     * | +     * +---- +     * | +     * | +     */ +    GATE_SHAPE_UNUSED_T3, + +    /* +     * An unused T-shape gate +     * | +     * | +     * +---- +     * | +     * | +     */ +    GATE_SHAPE_UNUSED_T4, +}; + +enum +{ +    /* +     * 0 degrees (clockwise) +     * | +     * +-- +     * | +     */ +    GATE_ORIENTATION_0, + +    /* +     * 90 degress (clockwise) +     * --+-- +     *   | +     */ +    GATE_ORIENTATION_90, + +    /* +     * 180 degrees (clockwise) +     *   | +     * --+ +     *   | +     */ +    GATE_ORIENTATION_180, + +    /* +     * 270 degrees (clockwise) +     *   | +     * --+-- +     */ +    GATE_ORIENTATION_270, + +    GATE_ORIENTATION_MAX, +}; + +// Describes the location of the gates "arms" when the gate has not +// been rotated (i.e. rotated 0 degrees) +enum +{ +    GATE_ARM_NORTH, +    GATE_ARM_EAST, +    GATE_ARM_SOUTH, +    GATE_ARM_WEST, +}; + +enum +{ +    ROTATE_NONE, +    ROTATE_ANTICLOCKWISE, +    ROTATE_CLOCKWISE, +}; + +enum +{ +    PUZZLE_NONE, +    PUZZLE_FORTREE_CITY_GYM, +    PUZZLE_ROUTE110_TRICK_HOUSE_PUZZLE6, +}; + +struct RotatingGatePuzzle  { -    /* 0x0 */ struct Coords16 pos; -    /* 0x4 */ u8 e; -    /* 0x5 */ u8 f; -    /* 0x6 */ u8 g; -    /* 0x7 */ u8 h; +    struct Coords16 pos; +    u8 shape; +    u8 orientation;  }; -struct UnknownStruct2 +struct Coords8  { -    s8 a; -    s8 b; -    u8 c; -    u8 d; +    s8 deltaX; +    s8 deltaY;  }; -static const struct UnknownStruct sUnknown_083D2964[] = { -    { { 12, 5 }, 3, 0, 0, 0 }, -    { { 14, 7 }, 3, 3, 0, 0 }, -    { { 16, 4 }, 5, 1, 0, 0 }, -    { { 15, 14 }, 1, 0, 0, 0 }, -    { { 18, 13 }, 4, 2, 0, 0 }, -    { { 8, 20 }, 4, 2, 0, 0 }, -    { { 16, 20 }, 7, 1, 0, 0 }, +// Fortree +static const struct RotatingGatePuzzle sRotatingGate_FortreePuzzleConfig[] = { +    { { 12, 5 }, GATE_SHAPE_L4, GATE_ORIENTATION_0 }, +    { { 14, 7 }, GATE_SHAPE_L4, GATE_ORIENTATION_270 }, +    { { 16, 4 }, GATE_SHAPE_T2, GATE_ORIENTATION_90 }, +    { { 15, 14 }, GATE_SHAPE_L2, GATE_ORIENTATION_0 }, +    { { 18, 13 }, GATE_SHAPE_T1, GATE_ORIENTATION_180 }, +    { { 8, 20 }, GATE_SHAPE_T1, GATE_ORIENTATION_180 }, +    { { 16, 20 }, GATE_SHAPE_T4, GATE_ORIENTATION_90 },  }; -static const struct UnknownStruct sUnknown_083D299C[] = { -    { { 13, 3 }, 4, 3, 0, 0 }, -    { { 12, 6 }, 4, 2, 0, 0 }, -    { { 3, 6 }, 4, 2, 0, 0 }, -    { { 3, 9 }, 5, 3, 0, 0 }, -    { { 8, 8 }, 0, 1, 0, 0 }, -    { { 2, 12 }, 6, 2, 0, 0 }, -    { { 9, 13 }, 1, 0, 0, 0 }, -    { { 3, 14 }, 2, 1, 0, 0 }, -    { { 9, 15 }, 3, 2, 0, 0 }, -    { { 3, 18 }, 5, 2, 0, 0 }, -    { { 2, 19 }, 4, 0, 0, 0 }, -    { { 5, 21 }, 0, 0, 0, 0 }, -    { { 9, 19 }, 3, 3, 0, 0 }, -    { { 12, 20 }, 4, 1, 0, 0 }, +// Trickhouse +static const struct RotatingGatePuzzle sRotatingGate_TrickHousePuzzleConfig[] = { +    { { 13, 3 }, GATE_SHAPE_T1, GATE_ORIENTATION_270 }, +    { { 12, 6 }, GATE_SHAPE_T1, GATE_ORIENTATION_180 }, +    { { 3, 6 }, GATE_SHAPE_T1, GATE_ORIENTATION_180 }, +    { { 3, 9 }, GATE_SHAPE_T2, GATE_ORIENTATION_270 }, +    { { 8, 8 }, GATE_SHAPE_L1, GATE_ORIENTATION_90 }, +    { { 2, 12 }, GATE_SHAPE_T3, GATE_ORIENTATION_180 }, +    { { 9, 13 }, GATE_SHAPE_L2, GATE_ORIENTATION_0 }, +    { { 3, 14 }, GATE_SHAPE_L3, GATE_ORIENTATION_90 }, +    { { 9, 15 }, GATE_SHAPE_L4, GATE_ORIENTATION_180 }, +    { { 3, 18 }, GATE_SHAPE_T2, GATE_ORIENTATION_180 }, +    { { 2, 19 }, GATE_SHAPE_T1, GATE_ORIENTATION_0 }, +    { { 5, 21 }, GATE_SHAPE_L1, GATE_ORIENTATION_0 }, +    { { 9, 19 }, GATE_SHAPE_L4, GATE_ORIENTATION_270 }, +    { { 12, 20 }, GATE_SHAPE_T1, GATE_ORIENTATION_90 },  }; -static const u8 RotatingGateTiles_1[] = INCBIN_U8("graphics/rotating_gates/1.4bpp"); -static const u8 RotatingGateTiles_2[] = INCBIN_U8("graphics/rotating_gates/2.4bpp"); -static const u8 RotatingGateTiles_3[] = INCBIN_U8("graphics/rotating_gates/3.4bpp"); -static const u8 RotatingGateTiles_5[] = INCBIN_U8("graphics/rotating_gates/5.4bpp"); -static const u8 RotatingGateTiles_6[] = INCBIN_U8("graphics/rotating_gates/6.4bpp"); -static const u8 RotatingGateTiles_7[] = INCBIN_U8("graphics/rotating_gates/7.4bpp"); -static const u8 RotatingGateTiles_0[] = INCBIN_U8("graphics/rotating_gates/0.4bpp"); -static const u8 RotatingGateTiles_4[] = INCBIN_U8("graphics/rotating_gates/4.4bpp"); +static const u8 sRotatingGateTiles_1[] = INCBIN_U8("graphics/rotating_gates/1.4bpp"); +static const u8 sRotatingGateTiles_2[] = INCBIN_U8("graphics/rotating_gates/2.4bpp"); +static const u8 sRotatingGateTiles_3[] = INCBIN_U8("graphics/rotating_gates/3.4bpp"); +static const u8 sRotatingGateTiles_5[] = INCBIN_U8("graphics/rotating_gates/5.4bpp"); +static const u8 sRotatingGateTiles_6[] = INCBIN_U8("graphics/rotating_gates/6.4bpp"); +static const u8 sRotatingGateTiles_7[] = INCBIN_U8("graphics/rotating_gates/7.4bpp"); +static const u8 sRotatingGateTiles_0[] = INCBIN_U8("graphics/rotating_gates/0.4bpp"); +static const u8 sRotatingGateTiles_4[] = INCBIN_U8("graphics/rotating_gates/4.4bpp"); -static const struct OamData gOamData_83D5E0C = { +static const struct OamData sOamData_RotatingGateLarge = {      .y = 0,      .affineMode = ST_OAM_AFFINE_NORMAL,      .objMode = 0, @@ -74,8 +246,7 @@ static const struct OamData gOamData_83D5E0C = {      .affineParam = 0,  }; -// Smaller -static const struct OamData gOamData_83D5E14 = { +static const struct OamData sOamData_RotatingGateRegular = {      .y = 0,      .affineMode = ST_OAM_AFFINE_NORMAL,      .objMode = 0, @@ -91,291 +262,331 @@ static const struct OamData gOamData_83D5E14 = {      .affineParam = 0,  }; -static const struct SpriteSheet gRotatingGatesGraphicsTable[] = { -    { RotatingGateTiles_0, 0x200, 0x1300 }, -    { RotatingGateTiles_1, 0x800, 0x1301 }, -    { RotatingGateTiles_2, 0x800, 0x1302 }, -    { RotatingGateTiles_3, 0x800, 0x1303 }, -    { RotatingGateTiles_4, 0x200, 0x1304 }, -    { RotatingGateTiles_5, 0x800, 0x1305 }, -    { RotatingGateTiles_6, 0x800, 0x1306 }, -    { RotatingGateTiles_7, 0x800, 0x1307 }, +static const struct SpriteSheet sRotatingGatesGraphicsTable[] = { +    { sRotatingGateTiles_0, 0x200, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L1 }, +    { sRotatingGateTiles_1, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L2 }, +    { sRotatingGateTiles_2, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L3 }, +    { sRotatingGateTiles_3, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L4 }, +    { sRotatingGateTiles_4, 0x200, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T1 }, +    { sRotatingGateTiles_5, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T2 }, +    { sRotatingGateTiles_6, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T3 }, +    { sRotatingGateTiles_7, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T4 },      { NULL },  }; -static const union AnimCmd gSpriteAnim_83D5E64[] = { +static const union AnimCmd sSpriteAnim_RotatingGateLarge[] = {      ANIMCMD_FRAME(0, 0), ANIMCMD_END,  }; -static const union AnimCmd gSpriteAnim_83D5E6C[] = { +static const union AnimCmd sSpriteAnim_RotatingGateRegular[] = {      ANIMCMD_FRAME(0, 0), ANIMCMD_END,  }; -static const union AnimCmd *const gSpriteAnimTable_83D5E74[] = { -    gSpriteAnim_83D5E64, +static const union AnimCmd *const sSpriteAnimTable_RotatingGateLarge[] = { +    sSpriteAnim_RotatingGateLarge,  }; -static const union AnimCmd *const gSpriteAnimTable_83D5E78[] = { -    gSpriteAnim_83D5E6C, +static const union AnimCmd *const sSpriteAnimTable_RotatingGateRegular[] = { +    sSpriteAnim_RotatingGateRegular,  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D5E7C[] = { +static const union AffineAnimCmd sSpriteAffineAnim_Rotated0[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), AFFINEANIMCMD_JUMP(0),  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D5E8C[] = { +static const union AffineAnimCmd sSpriteAffineAnim_Rotated90[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), AFFINEANIMCMD_JUMP(0),  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D5E9C[] = { +static const union AffineAnimCmd sSpriteAffineAnim_Rotated180[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), AFFINEANIMCMD_JUMP(0),  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D5EAC[] = { +static const union AffineAnimCmd sSpriteAffineAnim_Rotated270[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), AFFINEANIMCMD_JUMP(0),  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D5EBC[] = { +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise0to90[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0),      AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16),      AFFINEANIMCMD_END,  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D5ED4[] = { +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise90to180[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0),      AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16),      AFFINEANIMCMD_END,  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D5EEC[] = { +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise180to270[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0),      AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16),      AFFINEANIMCMD_END,  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D5F04[] = { +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise270to360[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0),      AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16),      AFFINEANIMCMD_END,  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D5F1C[] = { +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise360to270[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0),      AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16),      AFFINEANIMCMD_END,  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D5F34[] = { +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise270to180[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0),      AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16),      AFFINEANIMCMD_END,  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D5F4C[] = { +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise180to90[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0),      AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16),      AFFINEANIMCMD_END,  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D5F64[] = { +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise90to0[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0),      AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16),      AFFINEANIMCMD_END,  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D5F7C[] = { +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise0to90Faster[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0),      AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8),      AFFINEANIMCMD_END,  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D5F94[] = { +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise90to180Faster[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0),      AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8),      AFFINEANIMCMD_END,  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D5FAC[] = { +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise180to270Faster[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0),      AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8),      AFFINEANIMCMD_END,  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D5FC4[] = { +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise270to360Faster[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0),      AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8),      AFFINEANIMCMD_END,  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D5FDC[] = { +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise360to270Faster[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), AFFINEANIMCMD_END,  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D5FF4[] = { +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise270to180Faster[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0),      AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8),      AFFINEANIMCMD_END,  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D600C[] = { +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise180to90Faster[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0),      AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8),      AFFINEANIMCMD_END,  }; -static const union AffineAnimCmd gSpriteAffineAnim_83D6024[] = { +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise90to0Faster[] = {      AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0),      AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8),      AFFINEANIMCMD_END,  }; -static const union AffineAnimCmd *const gSpriteAffineAnimTable_83D603C[] = { -    gSpriteAffineAnim_83D5E7C, -    gSpriteAffineAnim_83D5E8C, -    gSpriteAffineAnim_83D5E9C, -    gSpriteAffineAnim_83D5EAC, -    gSpriteAffineAnim_83D5F1C, -    gSpriteAffineAnim_83D5F64, -    gSpriteAffineAnim_83D5F4C, -    gSpriteAffineAnim_83D5F34, -    gSpriteAffineAnim_83D5EBC, -    gSpriteAffineAnim_83D5ED4, -    gSpriteAffineAnim_83D5EEC, -    gSpriteAffineAnim_83D5F04, -    gSpriteAffineAnim_83D5FDC, -    gSpriteAffineAnim_83D6024, -    gSpriteAffineAnim_83D600C, -    gSpriteAffineAnim_83D5FF4, -    gSpriteAffineAnim_83D5F7C, -    gSpriteAffineAnim_83D5F94, -    gSpriteAffineAnim_83D5FAC, -    gSpriteAffineAnim_83D5FC4, +static const union AffineAnimCmd *const sSpriteAffineAnimTable_RotatingGate[] = { +    sSpriteAffineAnim_Rotated0, +    sSpriteAffineAnim_Rotated90, +    sSpriteAffineAnim_Rotated180, +    sSpriteAffineAnim_Rotated270, +    sSpriteAffineAnim_RotatingAnticlockwise360to270, +    sSpriteAffineAnim_RotatingAnticlockwise90to0, +    sSpriteAffineAnim_RotatingAnticlockwise180to90, +    sSpriteAffineAnim_RotatingAnticlockwise270to180, +    sSpriteAffineAnim_RotatingClockwise0to90, +    sSpriteAffineAnim_RotatingClockwise90to180, +    sSpriteAffineAnim_RotatingClockwise180to270, +    sSpriteAffineAnim_RotatingClockwise270to360, +    sSpriteAffineAnim_RotatingAnticlockwise360to270Faster, +    sSpriteAffineAnim_RotatingAnticlockwise90to0Faster, +    sSpriteAffineAnim_RotatingAnticlockwise180to90Faster, +    sSpriteAffineAnim_RotatingAnticlockwise270to180Faster, +    sSpriteAffineAnim_RotatingClockwise0to90Faster, +    sSpriteAffineAnim_RotatingClockwise90to180Faster, +    sSpriteAffineAnim_RotatingClockwise180to270Faster, +    sSpriteAffineAnim_RotatingClockwise270to360Faster,  }; -void sub_80C7C94(struct Sprite *sprite); - -static const struct SpriteTemplate gSpriteTemplate_83D608C = { -    .tileTag = 4864, +static const struct SpriteTemplate sSpriteTemplate_RotatingGateLarge = { +    .tileTag = ROTATING_GATE_TILE_TAG,      .paletteTag = 0xFFFF, -    .oam = &gOamData_83D5E0C, -    .anims = gSpriteAnimTable_83D5E74, +    .oam = &sOamData_RotatingGateLarge, +    .anims = sSpriteAnimTable_RotatingGateLarge,      .images = NULL, -    .affineAnims = gSpriteAffineAnimTable_83D603C, -    .callback = sub_80C7C94, +    .affineAnims = sSpriteAffineAnimTable_RotatingGate, +    .callback = SpriteCallback_RotatingGate,  }; -static const struct SpriteTemplate gSpriteTemplate_83D60A4 = { -    .tileTag = 4864, +static const struct SpriteTemplate sSpriteTemplate_RotatingGateRegular = { +    .tileTag = ROTATING_GATE_TILE_TAG,      .paletteTag = 0xFFFF, -    .oam = &gOamData_83D5E14, -    .anims = gSpriteAnimTable_83D5E78, +    .oam = &sOamData_RotatingGateRegular, +    .anims = sSpriteAnimTable_RotatingGateRegular,      .images = NULL, -    .affineAnims = gSpriteAffineAnimTable_83D603C, -    .callback = sub_80C7C94, +    .affineAnims = sSpriteAffineAnimTable_RotatingGate, +    .callback = SpriteCallback_RotatingGate,  }; -static const u8 sUnknown_083D60BC[4][4] = { -    { 255, 255, 255, 255 }, { 39, 38, 18, 19 }, { 255, 255, 255, 255 }, { 255, 255, 255, 255 }, +// These structures describe what happens to the gate if you hit it at +// a given coordinate in a 4x4 grid when walking in the specified +// direction. Either the gate does not rotate, or it rotates in the +// given direction. This information is compared against the gate +// "arm" layout to see if there is an arm at the position in order to +// produce the final rotation. +static const u8 sRotatingGate_RotationInfoNorth[4][4] = { +    { GATE_ROTATION_NONE, GATE_ROTATION_NONE, GATE_ROTATION_NONE, GATE_ROTATION_NONE }, +    { GATE_ROTATION_CLOCKWISE(GATE_ARM_WEST, 1), +        GATE_ROTATION_CLOCKWISE(GATE_ARM_WEST, 0), +        GATE_ROTATION_ANTICLOCKWISE(GATE_ARM_EAST, 0), +        GATE_ROTATION_ANTICLOCKWISE(GATE_ARM_EAST, 1) }, +    { GATE_ROTATION_NONE, GATE_ROTATION_NONE, GATE_ROTATION_NONE, GATE_ROTATION_NONE }, +    { GATE_ROTATION_NONE, GATE_ROTATION_NONE, GATE_ROTATION_NONE, GATE_ROTATION_NONE },  }; -static const u8 sUnknown_083D60CC[4][4] = { -    { 255, 255, 255, 255 }, { 255, 255, 255, 255 }, { 23, 22, 34, 35 }, { 255, 255, 255, 255 }, +static const u8 sRotatingGate_RotationInfoSouth[4][4] = { +    { GATE_ROTATION_NONE, GATE_ROTATION_NONE, GATE_ROTATION_NONE, GATE_ROTATION_NONE }, +    { GATE_ROTATION_NONE, GATE_ROTATION_NONE, GATE_ROTATION_NONE, GATE_ROTATION_NONE }, +    { GATE_ROTATION_ANTICLOCKWISE(GATE_ARM_WEST, 1), +        GATE_ROTATION_ANTICLOCKWISE(GATE_ARM_WEST, 0), +        GATE_ROTATION_CLOCKWISE(GATE_ARM_EAST, 0), +        GATE_ROTATION_CLOCKWISE(GATE_ARM_EAST, 1) }, +    { GATE_ROTATION_NONE, GATE_ROTATION_NONE, GATE_ROTATION_NONE, GATE_ROTATION_NONE },  }; -static const u8 sUnknown_083D60DC[4][4] = { -    { 255, 17, 255, 255 }, { 255, 16, 255, 255 }, { 255, 36, 255, 255 }, { 255, 37, 255, 255 }, +static const u8 sRotatingGate_RotationInfoWest[4][4] = { +    { GATE_ROTATION_NONE, +        GATE_ROTATION_ANTICLOCKWISE(GATE_ARM_NORTH, 1), +        GATE_ROTATION_NONE, +        GATE_ROTATION_NONE }, +    { GATE_ROTATION_NONE, +        GATE_ROTATION_ANTICLOCKWISE(GATE_ARM_NORTH, 0), +        GATE_ROTATION_NONE, +        GATE_ROTATION_NONE }, +    { GATE_ROTATION_NONE, +        GATE_ROTATION_CLOCKWISE(GATE_ARM_SOUTH, 0), +        GATE_ROTATION_NONE, +        GATE_ROTATION_NONE }, +    { GATE_ROTATION_NONE, +        GATE_ROTATION_CLOCKWISE(GATE_ARM_SOUTH, 1), +        GATE_ROTATION_NONE, +        GATE_ROTATION_NONE },  }; -static const u8 sUnknown_083D60EC[4][4] = { -    { 255, 255, 33, 255 }, { 255, 255, 32, 255 }, { 255, 255, 20, 255 }, { 255, 255, 21, 255 }, +static const u8 sRotatingGate_RotationInfoEast[4][4] = { +    { GATE_ROTATION_NONE, +        GATE_ROTATION_NONE, +        GATE_ROTATION_CLOCKWISE(GATE_ARM_NORTH, 1), +        GATE_ROTATION_NONE }, +    { GATE_ROTATION_NONE, +        GATE_ROTATION_NONE, +        GATE_ROTATION_CLOCKWISE(GATE_ARM_NORTH, 0), +        GATE_ROTATION_NONE }, +    { GATE_ROTATION_NONE, +        GATE_ROTATION_NONE, +        GATE_ROTATION_ANTICLOCKWISE(GATE_ARM_SOUTH, 0), +        GATE_ROTATION_NONE }, +    { GATE_ROTATION_NONE, +        GATE_ROTATION_NONE, +        GATE_ROTATION_ANTICLOCKWISE(GATE_ARM_SOUTH, 1), +        GATE_ROTATION_NONE },  }; -static const struct UnknownStruct2 sUnknown_083D60FC[] = { -    { 0, -1, 0, 0 }, -    { 1, -2, 0, 0 }, -    { 0, 0, 0, 0 }, -    { 1, 0, 0, 0 }, -    { -1, 0, 0, 0 }, -    { -1, 1, 0, 0 }, -    { -1, -1, 0, 0 }, -    { -2, -1, 0, 0 }, +// These tables describe the relative coordinate positions the arms +// must move through in order to be rotated. +static const struct Coords8 sRotatingGate_ArmPositionsClockwiseRotation[] = { +    { 0, -1 }, { 1, -2 }, { 0, 0 }, { 1, 0 }, { -1, 0 }, { -1, 1 }, { -1, -1 }, { -2, -1 },  }; -static const struct UnknownStruct2 sUnknown_083D611C[] = { -    { -1, -1, 0, 0 }, -    { -1, -2, 0, 0 }, -    { 0, -1, 0, 0 }, -    { 1, -1, 0, 0 }, -    { 0, 0, 0, 0 }, -    { 0, 1, 0, 0 }, -    { -1, 0, 0, 0 }, -    { -2, 0, 0, 0 }, +static const struct Coords8 sRotatingGate_ArmPositionsAntiClockwiseRotation[] = { +    { -1, -1 }, { -1, -2 }, { 0, -1 }, { 1, -1 }, { 0, 0 }, { 0, 1 }, { -1, 0 }, { -2, 0 },  }; -static const u8 sUnknown_083D613C[12][8] = { +// Describes where the gates "arms" are in the order north, east, south, west. +// These are adjusted using the current orientation to perform collision checking +static const u8 sRotatingGate_ArmLayout[][GATE_ARM_WEST + 1][GATE_ARM_MAX_LENGTH] = { +    // L-shape gates      { -        1, 0, 1, 0, 0, 0, 0, 0, +        { 1, 0 }, { 1, 0 }, { 0, 0 }, { 0, 0 },      },      { -        1, 1, 1, 0, 0, 0, 0, 0, +        { 1, 1 }, { 1, 0 }, { 0, 0 }, { 0, 0 },      },      { -        1, 0, 1, 1, 0, 0, 0, 0, +        { 1, 0 }, { 1, 1 }, { 0, 0 }, { 0, 0 },      },      { -        1, 1, 1, 1, 0, 0, 0, 0, +        { 1, 1 }, { 1, 1 }, { 0, 0 }, { 0, 0 },      }, + +    // T-shape gates      { -        1, 0, 1, 0, 1, 0, 0, 0, +        { 1, 0 }, { 1, 0 }, { 1, 0 }, { 0, 0 },      },      { -        1, 1, 1, 0, 1, 0, 0, 0, +        { 1, 1 }, { 1, 0 }, { 1, 0 }, { 0, 0 },      },      { -        1, 0, 1, 1, 1, 0, 0, 0, +        { 1, 0 }, { 1, 1 }, { 1, 0 }, { 0, 0 },      },      { -        1, 0, 1, 0, 1, 1, 0, 0, +        { 1, 0 }, { 1, 0 }, { 1, 1 }, { 0, 0 },      }, + +    // Unused T-shape gates +    // These have 2-3 long arms and cannot actually be used anywhere +    // since configuration for them is missing from the other tables.      { -        1, 1, 1, 1, 1, 0, 0, 0, +        { 1, 1 }, { 1, 1 }, { 1, 0 }, { 0, 0 },      },      { -        1, 1, 1, 0, 1, 1, 0, 0, +        { 1, 1 }, { 1, 0 }, { 1, 1 }, { 0, 0 },      },      { -        1, 0, 1, 1, 1, 1, 0, 0, +        { 1, 0 }, { 1, 1 }, { 1, 1 }, { 0, 0 },      },      { -        1, 1, 1, 1, 1, 1, 0, 0, +        { 1, 1 }, { 1, 1 }, { 1, 1 }, { 0, 0 },      },  }; -extern u8 gUnknown_020387F0[10]; // puzzle oam ID list -extern const struct UnknownStruct *gUnknown_02038800; +extern u8 gUnknown_020387F0[ROTATING_GATE_PUZZLE_MAX]; // puzzle oam ID list +extern const struct RotatingGatePuzzle *gUnknown_02038800; // sRotatingGatePuzzleConfiguration  extern u8 gUnknown_02038804; // puzzle count -u8 sub_80C7BAC(u8 i, s16 a, s16 b); -void sub_8060388(s16 x, s16 y, s16 *outX, s16 *outY); -void sub_80C7D14(struct Sprite *sprite); - -int GetCurrentMapRotatingGatePuzzleType(void) +static int GetCurrentMapRotatingGatePuzzleType(void)  { -    if (gSaveBlock1.location.mapGroup == 0xC && gSaveBlock1.location.mapNum == 0x1) +    if (gSaveBlock1.location.mapGroup == MAP_GROUP_FORTREE_CITY_GYM && +        gSaveBlock1.location.mapNum == MAP_ID_FORTREE_CITY_GYM)      { -        return 1; +        return PUZZLE_FORTREE_CITY_GYM;      } -    if (gSaveBlock1.location.mapGroup == 0x1d && gSaveBlock1.location.mapNum == 0x8) +    if (gSaveBlock1.location.mapGroup == MAP_GROUP_ROUTE110_TRICK_HOUSE_PUZZLE6 && +        gSaveBlock1.location.mapNum == MAP_ID_ROUTE110_TRICK_HOUSE_PUZZLE6)      { -        return 2; +        return PUZZLE_ROUTE110_TRICK_HOUSE_PUZZLE6;      } -    return 0; +    return PUZZLE_NONE;  } -// ResetSomething -void sub_80C79CC(void) +static void RotatingGate_ResetAllGateOrientations(void)  {      int i;      u8 *ptr; @@ -384,81 +595,77 @@ void sub_80C79CC(void)      for (i = 0; i < gUnknown_02038804; i++)      { -        ptr[i] = gUnknown_02038800[i].f; +        ptr[i] = gUnknown_02038800[i].orientation;      }  } -// GetSomething -/* u8 */ int sub_80C7A08(u8 a) +static int RotatingGate_GetGateOrientation(u8 gateId)  { -    u8 *ptr; -    ptr = (u8 *)GetVarPointer(0x4000); -    return ptr[a]; +    return ((u8 *)GetVarPointer(0x4000))[gateId];  } -// SetSomething -void sub_80C7A24(u8 a, u8 b) +static void RotatingGate_SetGateOrientation(u8 gateId, u8 orientation)  { -    u8 *ptr; -    ptr = (u8 *)GetVarPointer(0x4000); -    ptr[a] = b; +    ((u8 *)GetVarPointer(0x4000))[gateId] = orientation;  } -// RotateInDirectionProbably -void sub_80C7A44(u8 a, u32 b) +static void RotatingGate_RotateInDirection(u8 gateId, u32 rotationDirection)  { -    u8 r1; -    r1 = sub_80C7A08(a); +    u8 orientation = RotatingGate_GetGateOrientation(gateId); -    if (b == 1) +    if (rotationDirection == ROTATE_ANTICLOCKWISE)      { -        if (r1) +        if (orientation)          { -            r1--; +            orientation--;          }          else          { -            r1 = 3; +            orientation = GATE_ORIENTATION_270;          }      }      else      { -        r1 = ++r1 % 4; +        orientation = ++orientation % GATE_ORIENTATION_MAX;      } -    sub_80C7A24(a, r1); +    RotatingGate_SetGateOrientation(gateId, orientation);  } -// Configure -void sub_80C7A80(void) +static void RotatingGate_LoadPuzzleConfig(void)  { -    int a = GetCurrentMapRotatingGatePuzzleType(); +    int puzzleType = GetCurrentMapRotatingGatePuzzleType();      u32 i; -    switch (a) +    switch (puzzleType)      { -    case 1: -        gUnknown_02038800 = sUnknown_083D2964; -        gUnknown_02038804 = 7; +    case PUZZLE_FORTREE_CITY_GYM: +        gUnknown_02038800 = sRotatingGate_FortreePuzzleConfig; +        gUnknown_02038804 = +            sizeof(sRotatingGate_FortreePuzzleConfig) / sizeof(struct RotatingGatePuzzle);          break; -    case 2: -        gUnknown_02038800 = sUnknown_083D299C; -        gUnknown_02038804 = 0xE; +    case PUZZLE_ROUTE110_TRICK_HOUSE_PUZZLE6: +        gUnknown_02038800 = sRotatingGate_TrickHousePuzzleConfig; +        gUnknown_02038804 = +            sizeof(sRotatingGate_TrickHousePuzzleConfig) / sizeof(struct RotatingGatePuzzle);          break; -    case 0: +    case PUZZLE_NONE:      default:          return;      } -    for (i = 0; i < 14; i++) +    for (i = 0; i < ROTATING_GATE_PUZZLE_MAX; i++)      {          gUnknown_020387F0[i] = MAX_SPRITES;      }  } -void sub_80C7ADC(s16 a, s16 b) +static void RotatingGate_CreateGatesWithinViewport(s16 deltaX, s16 deltaY)  {      u8 i; + +    // Calculate the bounding box of the camera +    // Same as RotatingGate_DestroyGatesOutsideViewport      s16 x = gSaveBlock1.pos.x - 2;      s16 x2 = gSaveBlock1.pos.x + 0x11;      s16 y = gSaveBlock1.pos.y - 2; @@ -473,91 +680,88 @@ void sub_80C7ADC(s16 a, s16 b)          if (y <= y3 && y2 >= y3 && x <= x3 && x2 >= x3 && gUnknown_020387F0[i] == MAX_SPRITES)          { -            gUnknown_020387F0[i] = sub_80C7BAC(i, a, b); +            gUnknown_020387F0[i] = RotatingGate_CreateGate(i, deltaX, deltaY);          }      }  } -// CreateSprite -u8 sub_80C7BAC(u8 i, s16 a, s16 b) +static u8 RotatingGate_CreateGate(u8 gateId, s16 deltaX, s16 deltaY)  { -    struct Sprite *sprite; // r4 +    struct Sprite *sprite;      struct SpriteTemplate template; -    const struct UnknownStruct *unk; -    u8 id; //  r5 +    const struct RotatingGatePuzzle *gate; +    u8 spriteId;      s16 x, y; -    unk = &gUnknown_02038800[i]; +    gate = &gUnknown_02038800[gateId]; -    if (unk->e == 0 || unk->e == 4) +    if (gate->shape == GATE_SHAPE_L1 || gate->shape == GATE_SHAPE_T1)      { -        template = gSpriteTemplate_83D60A4; +        template = sSpriteTemplate_RotatingGateRegular;      }      else      { -        template = gSpriteTemplate_83D608C; +        template = sSpriteTemplate_RotatingGateLarge;      } -    template.tileTag = unk->e + 0x1300; +    template.tileTag = gate->shape + ROTATING_GATE_TILE_TAG; -    id = CreateSprite(&template, 0, 0, 0x94); -    if (id == MAX_SPRITES) +    spriteId = CreateSprite(&template, 0, 0, 0x94); +    if (spriteId == MAX_SPRITES)      {          return MAX_SPRITES;      } -    x = unk->pos.x + 7; -    y = unk->pos.y + 7; +    x = gate->pos.x + 7; +    y = gate->pos.y + 7; -    sprite = &gSprites[id]; -    sprite->data0 = i; +    sprite = &gSprites[spriteId]; +    sprite->data0 = gateId;      sprite->coordOffsetEnabled = 1; -    sub_8060388(x + a, y + b, &sprite->pos1.x, &sprite->pos1.y); -    sub_80C7D14(sprite); -    StartSpriteAffineAnim(sprite, sub_80C7A08(i)); +    sub_8060388(x + deltaX, y + deltaY, &sprite->pos1.x, &sprite->pos1.y); +    RotatingGate_HideGatesOutsideViewport(sprite); +    StartSpriteAffineAnim(sprite, RotatingGate_GetGateOrientation(gateId)); -    return id; +    return spriteId;  } -// RotateGateWithSE -void sub_80C7C94(struct Sprite *sprite) +static void SpriteCallback_RotatingGate(struct Sprite *sprite)  { -    u8 a; // r5 -    u8 b; +    u8 rotationDirection; +    u8 orientation;      u8 affineAnimation; -    a = sprite->data1; -    b = sprite->data2; +    rotationDirection = sprite->data1; +    orientation = sprite->data2; -    sub_80C7D14(sprite); +    RotatingGate_HideGatesOutsideViewport(sprite); -    if (a == 1) +    if (rotationDirection == ROTATE_ANTICLOCKWISE)      { -        affineAnimation = b + 4; +        affineAnimation = orientation + 4;          if (GetPlayerSpeed() != 1)              affineAnimation += 8; -        PlaySE(48); +        PlaySE(SE_HI_TURUN);          StartSpriteAffineAnim(sprite, affineAnimation);      } -    else if (a == 2) +    else if (rotationDirection == ROTATE_CLOCKWISE)      { -        affineAnimation = b + 8; +        affineAnimation = orientation + 8;          if (GetPlayerSpeed() != 1)              affineAnimation += 8; -        PlaySE(48); +        PlaySE(SE_HI_TURUN);          StartSpriteAffineAnim(sprite, affineAnimation);      } -    sprite->data1 = 0; +    sprite->data1 = ROTATE_NONE;  } -// See sub_806487C (field_map_obj_helpers.c) -void sub_80C7D14(struct Sprite *sprite) +static void RotatingGate_HideGatesOutsideViewport(struct Sprite *sprite)  {      u16 x;      s16 x2; @@ -571,7 +775,6 @@ void sub_80C7D14(struct Sprite *sprite)      x2 = x + 0x40; // Dimensions of the rotating gate      y2 = y + 0x40; -    // TODO: Make this 0x10 a constant      if ((s16)x > DISPLAY_WIDTH + 0x10 - 1 || x2 < -0x10)      {          sprite->invisible = 1; @@ -583,12 +786,12 @@ void sub_80C7D14(struct Sprite *sprite)      }  } -void LoadRotatingGatePics(void) +static void LoadRotatingGatePics(void)  { -    LoadSpriteSheets(gRotatingGatesGraphicsTable); +    LoadSpriteSheets(sRotatingGatesGraphicsTable);  } -void sub_80C7DC0(void) +static void RotatingGate_DestroyGatesOutsideViewport(void)  {      s16 x;      s16 x2; @@ -599,10 +802,11 @@ void sub_80C7DC0(void)      int i;      struct Sprite *sprite; +    // Same as RotatingGate_CreateGatesWithinViewport      x = gSaveBlock1.pos.x - 2; -    x2 = gSaveBlock1.pos.x + 17; +    x2 = gSaveBlock1.pos.x + 0x11;      y = gSaveBlock1.pos.y - 2; -    y2 = gSaveBlock1.pos.y + 14; +    y2 = gSaveBlock1.pos.y + 0xe;      for (i = 0; i < gUnknown_02038804; i++)      { @@ -623,62 +827,57 @@ void sub_80C7DC0(void)  }  #ifdef NONMATCHING -int sub_80C7E8C(u8 a, int puzzleType) +static int RotatingGate_CanRotate(u8 gateId, int rotationDirection)  { -    const struct UnknownStruct2 *unk1; -    u8 unk2; +    const struct Coords8 *armPos; +    u8 orientation;      s16 x;      s16 y; -    int unk3; +    int shape;      int i;      int j; -    int unk4; -    const u8 *unk5; -    int unk6; -    u8 unk7; -    int wat; - -    if (puzzleType == 1) -        unk1 = sUnknown_083D611C; -    else if (puzzleType == 2) -        unk1 = sUnknown_083D60FC; +    int armOrientation; +    const u8 *gateArmCollisionData; +    u8 armIndex; + +    if (rotationDirection == ROTATE_ANTICLOCKWISE) +        armPos = sRotatingGate_ArmPositionsAntiClockwiseRotation; +    else if (rotationDirection == ROTATE_CLOCKWISE) +        armPos = sRotatingGate_ArmPositionsClockwiseRotation;      else          return 0; -    unk2 = sub_80C7A08(a); +    orientation = RotatingGate_GetGateOrientation(gateId); -    unk3 = gUnknown_02038800[a].e; -    x = gUnknown_02038800[a].pos.x + 7; -    y = gUnknown_02038800[a].pos.y + 7; +    shape = gUnknown_02038800[gateId].shape; +    x = gUnknown_02038800[gateId].pos.x + 7; +    y = gUnknown_02038800[gateId].pos.y + 7; -    for (i = 0; i <= 3; i++) +    // Loop through the gate's "arms" clockwise (north, south, east, west) +    for (i = GATE_ARM_NORTH; i <= GATE_ARM_WEST; i++)      { -        j = 0; -        unk4 = unk2 + i; -        wat = unk2 + i; -        unk5 = &sUnknown_083D613C[unk3][i * 2]; +        armOrientation = orientation + i; +        gateArmCollisionData = sRotatingGate_ArmLayout[shape][i]; -        for (; j <= 1; j++) +        // Ensure that no part of the arm collides with the map +        for (j = 0; j < GATE_ARM_MAX_LENGTH; j++)          { -            unk6 = wat; -            if (wat < 0) -                unk6 = unk4 + 3; - -            unk7 = (2 * (wat - ((unk6 >> 2) << 2)) + j); +            armIndex = 2 * (armOrientation % 4) + j; -            if (*unk5) +            if (*gateArmCollisionData)              { -                if (MapGridIsImpassableAt(unk1[unk7].a + x, unk1[unk7].b + y) == 1) +                if (MapGridIsImpassableAt( +                        armPos[armIndex].deltaX + x, armPos[armIndex].deltaY + y) == 1)                      return 0;              } -            unk5++; +            gateArmCollisionData++;          }      }      return 1;  }  #else -__attribute__((naked)) int sub_80C7E8C(u8 a, int puzzleType) +__attribute__((naked)) static int RotatingGate_CanRotate(u8 a, int puzzleType)  {      asm(".syntax unified\n\  	push {r4-r7,lr}\n\ @@ -691,11 +890,11 @@ __attribute__((naked)) int sub_80C7E8C(u8 a, int puzzleType)  	lsrs r4, r0, 24\n\  	cmp r1, 0x1\n\  	bne _080C7EAC\n\ -	ldr r0, _080C7EA8 @ =sUnknown_083D611C\n\ +	ldr r0, _080C7EA8 @ =sRotatingGate_ArmPositionsAntiClockwiseRotation\n\  	mov r10, r0\n\  	b _080C7EB8\n\  	.align 2, 0\n\ -_080C7EA8: .4byte sUnknown_083D611C\n\ +_080C7EA8: .4byte sRotatingGate_ArmPositionsAntiClockwiseRotation\n\  _080C7EAC:\n\  	cmp r1, 0x2\n\  	beq _080C7EB4\n\ @@ -703,11 +902,11 @@ _080C7EB0:\n\  	movs r0, 0\n\  	b _080C7F48\n\  _080C7EB4:\n\ -	ldr r1, _080C7F58 @ =sUnknown_083D60FC\n\ +	ldr r1, _080C7F58 @ =sRotatingGate_ArmPositionsClockwiseRotation\n\  	mov r10, r1\n\  _080C7EB8:\n\  	adds r0, r4, 0\n\ -	bl sub_80C7A08\n\ +	bl RotatingGate_GetGateOrientation\n\  	lsls r0, 24\n\  	lsrs r0, 24\n\  	str r0, [sp]\n\ @@ -737,7 +936,7 @@ _080C7EE8:\n\  	adds r5, r7, 0\n\  	ldr r1, [sp, 0x4]\n\  	adds r0, r1\n\ -	ldr r2, _080C7F60 @ =sUnknown_083D613C\n\ +	ldr r2, _080C7F60 @ =sRotatingGate_ArmLayout\n\  	adds r4, r0, r2\n\  _080C7EFA:\n\  	adds r0, r5, 0\n\ @@ -790,33 +989,30 @@ _080C7F48:\n\  	pop {r1}\n\  	bx r1\n\  	.align 2, 0\n\ -_080C7F58: .4byte sUnknown_083D60FC\n\ +_080C7F58: .4byte sRotatingGate_ArmPositionsClockwiseRotation\n\  _080C7F5C: .4byte gUnknown_02038800\n\ -_080C7F60: .4byte sUnknown_083D613C\n\ +_080C7F60: .4byte sRotatingGate_ArmLayout\n\  .syntax divided\n");  }  #endif  #ifdef NONMATCHING -int sub_80C7F64(u8 a, u8 b) +static int RotatingGate_HasArm(u8 gateId, u8 armInfo)  { -    int unk1; -    int unk2; -    int unk4; -    int unk5; -    int unk6; -    int unk7; - -    unk5 = a >> 1; -    unk1 = b & 1; -    unk2 = unk5 - sub_80C7A08(a) + 4; -    unk7 = unk2 < 0 ? unk2 + 3 : unk2; -    unk4 = (unk7 - ((unk7 >> 2) << 2)); -    unk6 = gUnknown_02038800[a].e; -    return sUnknown_083D613C[unk6][(s8)unk4 * 2 + unk1]; +    int isLongArm; +    s8 armOrientation; +    int arm; +    int shape; + +    arm = armInfo >> 1; +    isLongArm = armInfo & 1; + +    armOrientation = (arm - RotatingGate_GetGateOrientation(gateId) + 4) % 4; +    shape = gUnknown_02038800[gateId].shape; +    return sRotatingGate_ArmLayout[shape][armOrientation][isLongArm];  }  #else -__attribute__((naked)) int sub_80C7F64(u8 a, u8 b) +__attribute__((naked)) static int RotatingGate_HasArm(u8 a, u8 b)  {      asm(".syntax unified\n\  	push {r4-r6,lr}\n\ @@ -830,7 +1026,7 @@ __attribute__((naked)) int sub_80C7F64(u8 a, u8 b)  	movs r0, 0x1\n\  	ands r5, r0\n\  	adds r0, r6, 0\n\ -	bl sub_80C7A08\n\ +	bl RotatingGate_GetGateOrientation\n\  	subs r4, r0\n\  	adds r1, r4, 0x4\n\  	adds r0, r1, 0\n\ @@ -846,7 +1042,7 @@ _080C7F8A:\n\  	lsls r1, r6, 3\n\  	adds r1, r2\n\  	ldrb r1, [r1, 0x4]\n\ -	ldr r2, _080C7FB4 @ =sUnknown_083D613C\n\ +	ldr r2, _080C7FB4 @ =sRotatingGate_ArmLayout\n\  	lsls r0, 24\n\  	asrs r0, 23\n\  	adds r0, r5\n\ @@ -859,43 +1055,43 @@ _080C7F8A:\n\  	bx r1\n\  	.align 2, 0\n\  _080C7FB0: .4byte gUnknown_02038800\n\ -_080C7FB4: .4byte sUnknown_083D613C\n\ +_080C7FB4: .4byte sRotatingGate_ArmLayout\n\  .syntax divided\n");  }  #endif -void sub_80C7FB8(u8 a, int b) +static void RotatingGate_TriggerRotationAnimation(u8 gateId, int rotationDirection)  {      struct Sprite *sprite; -    if (gUnknown_020387F0[a] != MAX_SPRITES) +    if (gUnknown_020387F0[gateId] != MAX_SPRITES)      { -        sprite = &gSprites[gUnknown_020387F0[a]]; -        sprite->data1 = b; -        sprite->data2 = sub_80C7A08(a); +        sprite = &gSprites[gUnknown_020387F0[gateId]]; +        sprite->data1 = rotationDirection; +        sprite->data2 = RotatingGate_GetGateOrientation(gateId);      }  }  #ifdef NONMATCHING -u8 sub_80C7FEC(u8 a, s16 b, s16 c) +static u8 RotatingGate_GetRotationInfo(u8 direction, s16 x, s16 y)  {      register const u8(*ptr)[][4] asm("r3"); -    if (a == 2) -        ptr = &sUnknown_083D60BC; -    else if (a == 1) -        ptr = &sUnknown_083D60CC; -    else if (a == 3) -        ptr = &sUnknown_083D60DC; -    else if (a == 4) -        ptr = &sUnknown_083D60EC; +    if (direction == DIR_NORTH) +        ptr = &sRotatingGate_RotationInfoNorth; +    else if (direction == DIR_SOUTH) +        ptr = &sRotatingGate_RotationInfoSouth; +    else if (direction == DIR_WEST) +        ptr = &sRotatingGate_RotationInfoWest; +    else if (direction == DIR_EAST) +        ptr = &sRotatingGate_RotationInfoEast;      else -        return 0xFF; +        return GATE_ROTATION_NONE; -    return (*ptr)[c][b]; +    return (*ptr)[y][x];  }  #else -__attribute__((naked)) u8 sub_80C7FEC(u8 a, s16 b, s16 c) +__attribute__((naked)) static u8 RotatingGate_GetRotationInfo(u8 a, s16 b, s16 c)  {      asm(".syntax unified\n\      	push {lr}\n\ @@ -908,31 +1104,31 @@ __attribute__((naked)) u8 sub_80C7FEC(u8 a, s16 b, s16 c)  	lsrs r2, 16\n\  	cmp r0, 0x2\n\  	bne _080C8008\n\ -	ldr r3, _080C8004 @ =sUnknown_083D60BC\n\ +	ldr r3, _080C8004 @ =sRotatingGate_RotationInfoNorth\n\  	b _080C802A\n\  	.align 2, 0\n\ -_080C8004: .4byte sUnknown_083D60BC\n\ +_080C8004: .4byte sRotatingGate_RotationInfoNorth\n\  _080C8008:\n\  	cmp r0, 0x1\n\  	bne _080C8014\n\ -	ldr r3, _080C8010 @ =sUnknown_083D60CC\n\ +	ldr r3, _080C8010 @ =sRotatingGate_RotationInfoSouth\n\  	b _080C802A\n\  	.align 2, 0\n\ -_080C8010: .4byte sUnknown_083D60CC\n\ +_080C8010: .4byte sRotatingGate_RotationInfoSouth\n\  _080C8014:\n\  	cmp r0, 0x3\n\  	bne _080C8020\n\ -	ldr r3, _080C801C @ =sUnknown_083D60DC\n\ +	ldr r3, _080C801C @ =sRotatingGate_RotationInfoWest\n\  	b _080C802A\n\  	.align 2, 0\n\ -_080C801C: .4byte sUnknown_083D60DC\n\ +_080C801C: .4byte sRotatingGate_RotationInfoWest\n\  _080C8020:\n\  	cmp r3, 0x4\n\  	beq _080C8028\n\  	movs r0, 0xFF\n\  	b _080C8038\n\  _080C8028:\n\ -	ldr r3, _080C803C @ =sUnknown_083D60EC\n\ +	ldr r3, _080C803C @ =sRotatingGate_RotationInfoEast\n\  _080C802A:\n\  	lsls r0, r2, 16\n\  	lsls r1, 16\n\ @@ -945,7 +1141,7 @@ _080C8038:\n\  	pop {r1}\n\  	bx r1\n\  	.align 2, 0\n\ -_080C803C: .4byte sUnknown_083D60EC\n\ +_080C803C: .4byte sRotatingGate_RotationInfoEast\n\  .syntax divided\n");  }  #endif @@ -954,17 +1150,17 @@ void sub_80C8040(void)  {      if (GetCurrentMapRotatingGatePuzzleType())      { -        sub_80C7A80(); -        sub_80C79CC(); +        RotatingGate_LoadPuzzleConfig(); +        RotatingGate_ResetAllGateOrientations();      }  } -void RotatingGatePuzzleCameraUpdate(u16 a, u16 b) +void RotatingGatePuzzleCameraUpdate(u16 deltaX, u16 deltaY)  {      if (GetCurrentMapRotatingGatePuzzleType())      { -        sub_80C7ADC(a, b); -        sub_80C7DC0(); +        RotatingGate_CreateGatesWithinViewport(deltaX, deltaY); +        RotatingGate_DestroyGatesOutsideViewport();      }  } @@ -973,21 +1169,21 @@ void sub_80C8080(void)      if (GetCurrentMapRotatingGatePuzzleType())      {          LoadRotatingGatePics(); -        sub_80C7A80(); -        sub_80C7ADC(0, 0); +        RotatingGate_LoadPuzzleConfig(); +        RotatingGate_CreateGatesWithinViewport(0, 0);      }  } -bool8 CheckForRotatingGatePuzzleCollision(u8 a, s16 x, s16 y) +bool8 CheckForRotatingGatePuzzleCollision(u8 direction, s16 x, s16 y)  {      int i;      s16 gateX;      s16 gateY; -    register u32 check asm("r0"); -    int upperNibble; -    int lowerNibble; -    s16 finalX; -    s16 finalY; +    register u32 rotationInfo asm("r0"); +    int rotationDirection; +    int armInfo; +    s16 centerX; +    s16 centerY;      if (!GetCurrentMapRotatingGatePuzzleType())      { @@ -1001,23 +1197,23 @@ bool8 CheckForRotatingGatePuzzleCollision(u8 a, s16 x, s16 y)          if (gateX - 2 <= x && x <= gateX + 1 && gateY - 2 <= y && y <= gateY + 1)          { -            finalX = x - gateX + 2; -            finalY = y - gateY + 2; -            check = sub_80C7FEC(a, finalX, finalY); +            centerX = x - gateX + 2; +            centerY = y - gateY + 2; +            rotationInfo = RotatingGate_GetRotationInfo(direction, centerX, centerY); -            if (check != 255) +            if (rotationInfo != GATE_ROTATION_NONE)              { -                upperNibble = check >> 4; -                lowerNibble = check & 0xF; +                rotationDirection = rotationInfo >> 4; +                armInfo = rotationInfo & 0xF; -                asm("" ::"r"(lowerNibble)); +                asm("" ::"r"(armInfo)); -                if (sub_80C7F64(i, lowerNibble)) +                if (RotatingGate_HasArm(i, armInfo))                  { -                    if (sub_80C7E8C(i, upperNibble)) +                    if (RotatingGate_CanRotate(i, rotationDirection))                      { -                        sub_80C7FB8(i, upperNibble); -                        sub_80C7A44(i, upperNibble); +                        RotatingGate_TriggerRotationAnimation(i, rotationDirection); +                        RotatingGate_RotateInDirection(i, rotationDirection);                          return 0;                      } | 
