diff options
author | Diegoisawesome <Diegoisawesome@users.noreply.github.com> | 2018-04-18 14:12:51 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-18 14:12:51 -0500 |
commit | d10844f1feaf1e9add59685e037fab7ad0027dce (patch) | |
tree | 932a43254cff7cd4b3d480ab1a2c25cf9efa0b95 /src | |
parent | 4e63a52832f4a443e24df4f38503e3b449b54e45 (diff) | |
parent | dc759a501b7dfa183b64ea68fbd9437f04e39e74 (diff) |
Merge pull request #237 from KDSKardabox/master
Decompile mon markings, rotating_gate & field_camera
Diffstat (limited to 'src')
-rw-r--r-- | src/bike.c | 3 | ||||
-rw-r--r-- | src/decoration.c | 20 | ||||
-rw-r--r-- | src/field_camera.c | 491 | ||||
-rw-r--r-- | src/mon_markings.c | 611 | ||||
-rw-r--r-- | src/overworld.c | 27 | ||||
-rw-r--r-- | src/rotating_gate.c | 1188 | ||||
-rw-r--r-- | src/text_window.c | 40 |
7 files changed, 2321 insertions, 59 deletions
diff --git a/src/bike.c b/src/bike.c index 64af7c711..782eceb8e 100644 --- a/src/bike.c +++ b/src/bike.c @@ -12,7 +12,6 @@ extern bool8 gBikeCyclingChallenge; extern u8 gBikeCollisions; -extern bool8 gUnknown_02037348; extern u8 sub_8093514(u8 direction); extern u8 sub_808B980(u8 direction); @@ -989,7 +988,7 @@ bool8 player_should_look_direction_be_enforced_upon_movement(void) void GetOnOffBike(u8 transitionFlags) { - gUnknown_02037348 = FALSE; + gUnusedBikeCameraAheadPanback = FALSE; if (gPlayerAvatar.flags & (PLAYER_AVATAR_FLAG_MACH_BIKE | PLAYER_AVATAR_FLAG_ACRO_BIKE)) { diff --git a/src/decoration.c b/src/decoration.c index a0855db69..f376c2115 100644 --- a/src/decoration.c +++ b/src/decoration.c @@ -1305,12 +1305,12 @@ void sub_8128060(u8 taskId) void ConfigureCameraObjectForPlacingDecoration(struct PlaceDecorationGraphicsDataBuffer *data, u8 decor) { - sDecor_CameraSpriteObjectIdx1 = gSprites[gUnknown_03005DD0.unk4].data[0]; - gUnknown_03005DD0.unk4 = gpu_pal_decompress_alloc_tag_and_upload(data, decor); - gSprites[gUnknown_03005DD0.unk4].oam.priority = 1; - gSprites[gUnknown_03005DD0.unk4].callback = sub_81292D0; - gSprites[gUnknown_03005DD0.unk4].pos1.x = gUnknown_085A7250[data->decoration->shape].x; - gSprites[gUnknown_03005DD0.unk4].pos1.y = gUnknown_085A7250[data->decoration->shape].y; + sDecor_CameraSpriteObjectIdx1 = gSprites[gUnknown_03005DD0.spriteId].data[0]; + gUnknown_03005DD0.spriteId = gpu_pal_decompress_alloc_tag_and_upload(data, decor); + gSprites[gUnknown_03005DD0.spriteId].oam.priority = 1; + gSprites[gUnknown_03005DD0.spriteId].callback = sub_81292D0; + gSprites[gUnknown_03005DD0.spriteId].pos1.x = gUnknown_085A7250[data->decoration->shape].x; + gSprites[gUnknown_03005DD0.spriteId].pos1.y = gUnknown_085A7250[data->decoration->shape].y; } void SetUpPlacingDecorationPlayerAvatar(u8 taskId, struct PlaceDecorationGraphicsDataBuffer *data) @@ -1332,7 +1332,7 @@ void SetUpPlacingDecorationPlayerAvatar(u8 taskId, struct PlaceDecorationGraphic } gSprites[sDecor_CameraSpriteObjectIdx2].oam.priority = 1; DestroySprite(&gSprites[sDecor_CameraSpriteObjectIdx1]); - sDecor_CameraSpriteObjectIdx1 = gUnknown_03005DD0.unk4; + sDecor_CameraSpriteObjectIdx1 = gUnknown_03005DD0.spriteId; } void sub_812826C(u8 taskId) @@ -2251,9 +2251,9 @@ bool8 sub_81299AC(u8 taskId) void SetUpPuttingAwayDecorationPlayerAvatar(void) { player_get_direction_lower_nybble(); - sDecor_CameraSpriteObjectIdx1 = gSprites[gUnknown_03005DD0.unk4].data[0]; + sDecor_CameraSpriteObjectIdx1 = gSprites[gUnknown_03005DD0.spriteId].data[0]; sub_812A39C(); - gUnknown_03005DD0.unk4 = CreateSprite(&gUnknown_085A7404, 0x78, 0x50, 0); + gUnknown_03005DD0.spriteId = CreateSprite(&gUnknown_085A7404, 0x78, 0x50, 0); if (gSaveBlock2Ptr->playerGender == MALE) { sDecor_CameraSpriteObjectIdx2 = AddPseudoFieldObject(0xC1, SpriteCallbackDummy, 0x88, 0x48, 0); @@ -2264,7 +2264,7 @@ void SetUpPuttingAwayDecorationPlayerAvatar(void) } gSprites[sDecor_CameraSpriteObjectIdx2].oam.priority = 1; DestroySprite(&gSprites[sDecor_CameraSpriteObjectIdx1]); - sDecor_CameraSpriteObjectIdx1 = gUnknown_03005DD0.unk4; + sDecor_CameraSpriteObjectIdx1 = gUnknown_03005DD0.spriteId; gSprites[sDecor_CameraSpriteObjectIdx1].oam.priority = 1; } diff --git a/src/field_camera.c b/src/field_camera.c index 17ced6aa5..f653e0bf1 100644 --- a/src/field_camera.c +++ b/src/field_camera.c @@ -1,9 +1,18 @@ - -// Includes #include "global.h" +#include "berry.h" +#include "bike.h" +#include "field_camera.h" +#include "field_player_avatar.h" +#include "fieldmap.h" +#include "field_map_obj.h" +#include "gpu_regs.h" +#include "menu.h" +#include "overworld.h" +#include "rotating_gate.h" +#include "sprite.h" +#include "text.h" // Static type declarations - struct FieldCameraUnknownStruct { u8 unk0; @@ -13,16 +22,474 @@ struct FieldCameraUnknownStruct bool8 unk4; }; -// Static RAM declarations +// static functions +static void RedrawMapSliceNorth(struct FieldCameraUnknownStruct *a, const struct MapData *mapData); +static void RedrawMapSliceSouth(struct FieldCameraUnknownStruct *a, const struct MapData *mapData); +static void RedrawMapSliceEast(struct FieldCameraUnknownStruct *a, const struct MapData *mapData); +static void RedrawMapSliceWest(struct FieldCameraUnknownStruct *a, const struct MapData *mapData); +static s32 MapPosToBgTilemapOffset(struct FieldCameraUnknownStruct *a, s32 x, s32 y); +static void DrawWholeMapViewInternal(int x, int y, const struct MapData *mapData); +static void DrawMetatileAt(const struct MapData *mapData, u16, int, int); +static void DrawMetatile(s32 a, u16 *b, u16 c); +static void CameraPanningCB_PanAhead(void); + +// IWRAM bss vars +static IWRAM_DATA struct FieldCameraUnknownStruct gUnknown_03000E20; +static IWRAM_DATA s16 gUnknown_03000E28; +static IWRAM_DATA s16 gUnknown_03000E2A; +static IWRAM_DATA u8 gUnknown_03000E2C; +static IWRAM_DATA void (*gUnknown_03000E30)(void); + +// text +static void move_tilemap_camera_to_upper_left_corner_(struct FieldCameraUnknownStruct *a) +{ + a->unk2 = 0; + a->unk3 = 0; + a->unk0 = 0; + a->unk1 = 0; + a->unk4 = TRUE; +} + +static void tilemap_move_something(struct FieldCameraUnknownStruct *a, u32 b, u32 c) +{ + a->unk2 += b; + a->unk2 %= 32; + a->unk3 += c; + a->unk3 %= 32; +} + +static void coords8_add(struct FieldCameraUnknownStruct *a, u32 b, u32 c) +{ + a->unk0 += b; + a->unk1 += c; +} + +void move_tilemap_camera_to_upper_left_corner(void) +{ + move_tilemap_camera_to_upper_left_corner_(&gUnknown_03000E20); +} + +void FieldUpdateBgTilemapScroll(void) +{ + u32 r4, r5; + r5 = gUnknown_03000E20.unk0 + gUnknown_03000E28; + r4 = gUnknown_03000E2A + gUnknown_03000E20.unk1 + 8; + + SetGpuReg(REG_OFFSET_BG1HOFS, r5); + SetGpuReg(REG_OFFSET_BG1VOFS, r4); + SetGpuReg(REG_OFFSET_BG2HOFS, r5); + SetGpuReg(REG_OFFSET_BG2VOFS, r4); + SetGpuReg(REG_OFFSET_BG3HOFS, r5); + SetGpuReg(REG_OFFSET_BG3VOFS, r4); +} + +void sub_8089C08(s16 *a, s16 *b) +{ + *a = gUnknown_03000E20.unk0 + gUnknown_03000E28; + *b = gUnknown_03000E20.unk1 + gUnknown_03000E2A + 8; +} + +void DrawWholeMapView(void) +{ + DrawWholeMapViewInternal(gSaveBlock1Ptr->pos.x, gSaveBlock1Ptr->pos.y, gMapHeader.mapData); + gUnknown_03000E20.unk4 = TRUE; +} + +static void DrawWholeMapViewInternal(int x, int y, const struct MapData *mapData) +{ + u8 i; + u8 j; + u32 r6; + u8 temp; + + for (i = 0; i < 32; i += 2) + { + temp = gUnknown_03000E20.unk3 + i; + if (temp >= 32) + temp -= 32; + r6 = temp * 32; + for (j = 0; j < 32; j += 2) + { + temp = gUnknown_03000E20.unk2 + j; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapData, r6 + temp, x + j / 2, y + i / 2); + } + } +} + +static void RedrawMapSlicesForCameraUpdate(struct FieldCameraUnknownStruct *a, int x, int y) +{ + const struct MapData *mapData = gMapHeader.mapData; + + if (x > 0) + RedrawMapSliceWest(a, mapData); + if (x < 0) + RedrawMapSliceEast(a, mapData); + if (y > 0) + RedrawMapSliceNorth(a, mapData); + if (y < 0) + RedrawMapSliceSouth(a, mapData); + a->unk4 = TRUE; +} + +static void RedrawMapSliceNorth(struct FieldCameraUnknownStruct *a, const struct MapData *mapData) +{ + u8 i; + u8 temp; + u32 r7; + + temp = a->unk3 + 28; + if (temp >= 32) + temp -= 32; + r7 = temp * 32; + for (i = 0; i < 32; i += 2) + { + temp = a->unk2 + i; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapData, r7 + temp, gSaveBlock1Ptr->pos.x + i / 2, gSaveBlock1Ptr->pos.y + 14); + } +} + +static void RedrawMapSliceSouth(struct FieldCameraUnknownStruct *a, const struct MapData *mapData) +{ + u8 i; + u8 temp; + u32 r7 = a->unk3 * 32; + + for (i = 0; i < 32; i += 2) + { + temp = a->unk2 + i; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapData, r7 + temp, gSaveBlock1Ptr->pos.x + i / 2, gSaveBlock1Ptr->pos.y); + } +} + +static void RedrawMapSliceEast(struct FieldCameraUnknownStruct *a, const struct MapData *mapData) +{ + u8 i; + u8 temp; + u32 r6 = a->unk2; + + for (i = 0; i < 32; i += 2) + { + temp = a->unk3 + i; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapData, temp * 32 + r6, gSaveBlock1Ptr->pos.x, gSaveBlock1Ptr->pos.y + i / 2); + } +} + +static void RedrawMapSliceWest(struct FieldCameraUnknownStruct *a, const struct MapData *mapData) +{ + u8 i; + u8 temp; + u8 r5 = a->unk2 + 28; + + if (r5 >= 32) + r5 -= 32; + for (i = 0; i < 32; i += 2) + { + temp = a->unk3 + i; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapData, temp * 32 + r5, gSaveBlock1Ptr->pos.x + 14, gSaveBlock1Ptr->pos.y + i / 2); + } +} + +void CurrentMapDrawMetatileAt(int a, int b) +{ + int offset = MapPosToBgTilemapOffset(&gUnknown_03000E20, a, b); + + if (offset >= 0) + { + DrawMetatileAt(gMapHeader.mapData, offset, a, b); + gUnknown_03000E20.unk4 = TRUE; + } +} + +void DrawDoorMetatileAt(int x, int y, u16 *arr) +{ + int offset = MapPosToBgTilemapOffset(&gUnknown_03000E20, x, y); + + if (offset >= 0) + { + DrawMetatile(1, arr, offset); + gUnknown_03000E20.unk4 = TRUE; + } +} + +static void DrawMetatileAt(const struct MapData *mapData, u16 b, int c, int d) +{ + u16 metatileId = MapGridGetMetatileIdAt(c, d); + u16 *metatiles; + + if (metatileId > 1024) + metatileId = 0; + if (metatileId < 512) + metatiles = mapData->primaryTileset->metatiles; + else + { + metatiles = mapData->secondaryTileset->metatiles; + metatileId -= 512; + } + DrawMetatile(MapGridGetMetatileLayerTypeAt(c, d), metatiles + metatileId * 8, b); +} + +static void DrawMetatile(s32 a, u16 *b, u16 c) +{ + switch (a) + { + case 2: + gBGTilemapBuffers3[c] = b[0]; + gBGTilemapBuffers3[c + 1] = b[1]; + gBGTilemapBuffers3[c + 0x20] = b[2]; + gBGTilemapBuffers3[c + 0x21] = b[3]; + + gBGTilemapBuffers1[c] = 0; + gBGTilemapBuffers1[c + 1] = 0; + gBGTilemapBuffers1[c + 0x20] = 0; + gBGTilemapBuffers1[c + 0x21] = 0; + + gBGTilemapBuffers2[c] = b[4]; + gBGTilemapBuffers2[c + 1] = b[5]; + gBGTilemapBuffers2[c + 0x20] = b[6]; + gBGTilemapBuffers2[c + 0x21] = b[7]; + break; + case 1: + gBGTilemapBuffers3[c] = b[0]; + gBGTilemapBuffers3[c + 1] = b[1]; + gBGTilemapBuffers3[c + 0x20] = b[2]; + gBGTilemapBuffers3[c + 0x21] = b[3]; + + gBGTilemapBuffers1[c] = b[4]; + gBGTilemapBuffers1[c + 1] = b[5]; + gBGTilemapBuffers1[c + 0x20] = b[6]; + gBGTilemapBuffers1[c + 0x21] = b[7]; + + gBGTilemapBuffers2[c] = 0; + gBGTilemapBuffers2[c + 1] = 0; + gBGTilemapBuffers2[c + 0x20] = 0; + gBGTilemapBuffers2[c + 0x21] = 0; + break; + case 0: + gBGTilemapBuffers3[c] = 0x3014; + gBGTilemapBuffers3[c + 1] = 0x3014; + gBGTilemapBuffers3[c + 0x20] = 0x3014; + gBGTilemapBuffers3[c + 0x21] = 0x3014; + + gBGTilemapBuffers1[c] = b[0]; + gBGTilemapBuffers1[c + 1] = b[1]; + gBGTilemapBuffers1[c + 0x20] = b[2]; + gBGTilemapBuffers1[c + 0x21] = b[3]; -IWRAM_DATA struct FieldCameraUnknownStruct gUnknown_03000E20; -IWRAM_DATA s16 gUnknown_03000E28; -IWRAM_DATA s16 gUnknown_03000E2A; -IWRAM_DATA u8 gUnknown_03000E2C; -IWRAM_DATA void (*gUnknown_03000E30)(void); + gBGTilemapBuffers2[c] = b[4]; + gBGTilemapBuffers2[c + 1] = b[5]; + gBGTilemapBuffers2[c + 0x20] = b[6]; + gBGTilemapBuffers2[c + 0x21] = b[7]; + break; + } + schedule_bg_copy_tilemap_to_vram(1); + schedule_bg_copy_tilemap_to_vram(2); + schedule_bg_copy_tilemap_to_vram(3); +} + +static s32 MapPosToBgTilemapOffset(struct FieldCameraUnknownStruct *a, s32 x, s32 y) +{ + x -= gSaveBlock1Ptr->pos.x; + x *= 2; + if (x >= 32 || x < 0) + return -1; + x = x + a->unk2; + if (x >= 32) + x -= 32; + + y = (y - gSaveBlock1Ptr->pos.y) * 2; + if (y >= 32 || y < 0) + return -1; + y = y + a->unk3; + if (y >= 32) + y -= 32; + + return y * 32 + x; +} + +static void CameraUpdateCallback(struct CameraObject *a) +{ + if (a->spriteId != 0) + { + a->unk8 = gSprites[a->spriteId].data[2]; + a->unkC = gSprites[a->spriteId].data[3]; + } +} + +void ResetCameraUpdateInfo(void) +{ + gUnknown_03005DD0.unk8 = 0; + gUnknown_03005DD0.unkC = 0; + gUnknown_03005DD0.x = 0; + gUnknown_03005DD0.y = 0; + gUnknown_03005DD0.spriteId = 0; + gUnknown_03005DD0.callback = NULL; +} + +u32 InitCameraUpdateCallback(u8 a) +{ + if (gUnknown_03005DD0.spriteId != 0) + DestroySprite(&gSprites[gUnknown_03005DD0.spriteId]); + gUnknown_03005DD0.spriteId = AddCameraObject(a); + gUnknown_03005DD0.callback = CameraUpdateCallback; + return 0; +} + +void CameraUpdate(void) +{ + int deltaX; + int deltaY; + int r0; + int r1; + int r7; + int r8; + + if (gUnknown_03005DD0.callback != NULL) + gUnknown_03005DD0.callback(&gUnknown_03005DD0); + r7 = gUnknown_03005DD0.unk8; + r8 = gUnknown_03005DD0.unkC; + deltaX = 0; + deltaY = 0; + r1 = gUnknown_03005DD0.x; + r0 = gUnknown_03005DD0.y; + + + if (r1 == 0 && r7 != 0) + { + if (r7 > 0) + deltaX = 1; + else + deltaX = -1; + } + if (r0 == 0 && r8 != 0) + { + if (r8 > 0) + deltaY = 1; + else + deltaY = -1; + } + if (r1 != 0 && r1 == -r7) + { + if (r7 > 0) + deltaX = 1; + else + deltaX = -1; + } + if (r0 != 0 && r0 == -r8) + { + if (r8 > 0) + deltaX = 1; + else + deltaX = -1; + } + + gUnknown_03005DD0.x += r7; + gUnknown_03005DD0.x = gUnknown_03005DD0.x - 16 * (gUnknown_03005DD0.x / 16); + gUnknown_03005DD0.y += r8; + gUnknown_03005DD0.y = gUnknown_03005DD0.y - 16 * (gUnknown_03005DD0.y / 16); + + if (deltaX != 0 || deltaY != 0) + { + CameraMove(deltaX, deltaY); + UpdateFieldObjectsForCameraUpdate(deltaX, deltaY); + RotatingGatePuzzleCameraUpdate(deltaX, deltaY); + ResetBerryTreeSparkleFlags(); + tilemap_move_something(&gUnknown_03000E20, deltaX * 2, deltaY * 2); + RedrawMapSlicesForCameraUpdate(&gUnknown_03000E20, deltaX * 2, deltaY * 2); + } + + coords8_add(&gUnknown_03000E20, r7, r8); + gUnknown_03005DEC -= r7; + gUnknown_03005DE8 -= r8; +} + +void camera_move_and_redraw(int a, int b) //unused +{ + CameraMove(a, b); + UpdateFieldObjectsForCameraUpdate(a, b); + DrawWholeMapView(); + gUnknown_03005DEC -= a * 16; + gUnknown_03005DE8 -= b * 16; +} + +void SetCameraPanningCallback(void (*a)(void)) +{ + gUnknown_03000E30 = a; +} + +void SetCameraPanning(s16 a, s16 b) +{ + gUnknown_03000E28 = a; + gUnknown_03000E2A = b + 32; +} + +void InstallCameraPanAheadCallback(void) +{ + gUnknown_03000E30 = CameraPanningCB_PanAhead; + gUnknown_03000E2C = 0; + gUnknown_03000E28 = 0; + gUnknown_03000E2A = 32; +} + +void UpdateCameraPanning(void) +{ + if (gUnknown_03000E30 != NULL) + gUnknown_03000E30(); + //Update sprite offset of overworld objects + gSpriteCoordOffsetX = gUnknown_03005DEC - gUnknown_03000E28; + gSpriteCoordOffsetY = gUnknown_03005DE8 - gUnknown_03000E2A - 8; +} + +static void CameraPanningCB_PanAhead(void) +{ + u8 var; -// Static ROM declarations + if (gUnusedBikeCameraAheadPanback == FALSE) + { + InstallCameraPanAheadCallback(); + } + else + { + // this code is never reached. + if (gPlayerAvatar.tileTransitionState == T_TILE_TRANSITION) + { + gUnknown_03000E2C ^= 1; + if (gUnknown_03000E2C == 0) + return; + } + else + { + gUnknown_03000E2C = 0; + } -// .rodata + var = player_get_direction_upper_nybble(); + if (var == 2) + { + if (gUnknown_03000E2A > -8) + gUnknown_03000E2A -= 2; + } + else if (var == 1) + { + if (gUnknown_03000E2A < 72) + gUnknown_03000E2A += 2; + } + else if (gUnknown_03000E2A < 32) + { + gUnknown_03000E2A += 2; + } + else if (gUnknown_03000E2A > 32) + { + gUnknown_03000E2A -= 2; + } + } +} -// .text diff --git a/src/mon_markings.c b/src/mon_markings.c new file mode 100644 index 000000000..147872ab6 --- /dev/null +++ b/src/mon_markings.c @@ -0,0 +1,611 @@ +#include "global.h" +#include "dma3.h" +#include "graphics.h" +#include "main.h" +#include "menu_indicators.h" +#include "mon_markings.h" +#include "constants/songs.h" +#include "sound.h" +#include "sprite.h" +#include "text_window.h" + +#define MENU_TEXT_SPRITE_X_OFFSET 32 + +// static functions +static void sub_811FC80(s16, s16, u16, u16); +static void TaskDummy7(struct Sprite *); +static void sub_811FF40(struct Sprite *); +static void sub_811FF7C(struct Sprite *); +static struct Sprite *sub_811FFD4(u16, u16, const u16 *, u16); + +// .rodata +static const u16 gUnknown_0859E65C[] = INCBIN_U16("graphics/misc/mon_markings.gbapal"); +static const u8 gUnknown_0859E67C[] = INCBIN_U8("graphics/misc/mon_markings.4bpp"); + +static const struct OamData gUnknown_0859EE7C = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + +static const struct OamData gUnknown_0859EE84 = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 0, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + +static const union AnimCmd gUnknown_0859EE8C[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EE94[] = +{ + ANIMCMD_FRAME(1, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EE9C[] = +{ + ANIMCMD_FRAME(2, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EEA4[] = +{ + ANIMCMD_FRAME(3, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EEAC[] = +{ + ANIMCMD_FRAME(4, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EEB4[] = +{ + ANIMCMD_FRAME(5, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EEBC[] = +{ + ANIMCMD_FRAME(6, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EEC4[] = +{ + ANIMCMD_FRAME(7, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EECC[] = +{ + ANIMCMD_FRAME(8, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EED4[] = +{ + ANIMCMD_FRAME(9, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_0859EEDC[] = +{ + gUnknown_0859EE8C, + gUnknown_0859EE94, + gUnknown_0859EE9C, + gUnknown_0859EEA4, + gUnknown_0859EEAC, + gUnknown_0859EEB4, + gUnknown_0859EEBC, + gUnknown_0859EEC4, + gUnknown_0859EECC, + gUnknown_0859EED4, +}; + +static const union AnimCmd gUnknown_0859EF04[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF0C[] = +{ + ANIMCMD_FRAME(64, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_0859EF14[] = +{ + gUnknown_0859EF04, + gUnknown_0859EF0C, +}; + +static const struct OamData gUnknown_0859EF1C = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 1, + .x = 0, + .matrixNum = 0, + .size = 1, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + +static const union AnimCmd gUnknown_0859EF24[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF2C[] = +{ + ANIMCMD_FRAME(4, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF34[] = +{ + ANIMCMD_FRAME(8, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF3C[] = +{ + ANIMCMD_FRAME(12, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF44[] = +{ + ANIMCMD_FRAME(16, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF4C[] = +{ + ANIMCMD_FRAME(20, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF54[] = +{ + ANIMCMD_FRAME(24, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF5C[] = +{ + ANIMCMD_FRAME(28, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF64[] = +{ + ANIMCMD_FRAME(32, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF6C[] = +{ + ANIMCMD_FRAME(36, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF74[] = +{ + ANIMCMD_FRAME(40, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF7C[] = +{ + ANIMCMD_FRAME(44, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF84[] = +{ + ANIMCMD_FRAME(48, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF8C[] = +{ + ANIMCMD_FRAME(52, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF94[] = +{ + ANIMCMD_FRAME(56, 5), + ANIMCMD_END, +}; + +static const union AnimCmd gUnknown_0859EF9C[] = +{ + ANIMCMD_FRAME(60, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const gUnknown_0859EFA4[] = +{ + gUnknown_0859EF24, + gUnknown_0859EF2C, + gUnknown_0859EF34, + gUnknown_0859EF3C, + gUnknown_0859EF44, + gUnknown_0859EF4C, + gUnknown_0859EF54, + gUnknown_0859EF5C, + gUnknown_0859EF64, + gUnknown_0859EF6C, + gUnknown_0859EF74, + gUnknown_0859EF7C, + gUnknown_0859EF84, + gUnknown_0859EF8C, + gUnknown_0859EF94, + gUnknown_0859EF9C, +}; + +static EWRAM_DATA struct PokemonMarkMenu *sMenu = NULL; + +void sub_811F90C(struct PokemonMarkMenu *ptr) +{ + sMenu = ptr; +} + +void sub_811F918(void) +{ + const struct TilesPal *frame = GetWindowFrameTilesPal(gSaveBlock2Ptr->optionsWindowFrameType); + sMenu->frameTiles = frame->tiles; + sMenu->framePalette = frame->pal; + sMenu->tileLoadState = 0; + CpuFill16(0, sMenu->menuWindowSpriteTiles, sizeof(sMenu->menuWindowSpriteTiles)); +} + +bool8 sub_811F960(void) +{ + u16 i; + u8 *dest = sMenu->menuWindowSpriteTiles + sMenu->tileLoadState * 0x100; + + switch (sMenu->tileLoadState) + { + case 0: + CpuFastCopy(sMenu->frameTiles, dest, TILE_SIZE_4BPP); + for (i = 0; i < 6; i++) + { + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP, dest + TILE_SIZE_4BPP * (i + 1), TILE_SIZE_4BPP); + } + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 2, dest + TILE_SIZE_4BPP * 7, TILE_SIZE_4BPP); + sMenu->tileLoadState++; + break; + default: + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 3, dest, TILE_SIZE_4BPP); + for (i = 0; i < 6; i++) + { + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 4, dest + TILE_SIZE_4BPP * (i + 1), TILE_SIZE_4BPP); + } + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 5, dest + TILE_SIZE_4BPP * 7, TILE_SIZE_4BPP); + sMenu->tileLoadState++; + break; + case 13: + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 6, dest, TILE_SIZE_4BPP); + for (i = 0; i < 6; i++) + { + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 7, dest + TILE_SIZE_4BPP * (i + 1), TILE_SIZE_4BPP); + } + CpuFastCopy(sMenu->frameTiles + TILE_SIZE_4BPP * 8, dest + TILE_SIZE_4BPP * 7, TILE_SIZE_4BPP); + sMenu->tileLoadState++; + return FALSE; + case 14: + return FALSE; + } + + return TRUE; +} + +void sub_811FA90(void) +{ + sub_811F918(); + while (sub_811F960()); +} + +void sub_811FAA4(u8 markings, s16 x, s16 y) +{ + u16 i; + sMenu->cursorPos = 0; + sMenu->markings = markings; + for (i = 0; i < 4; i++) + sMenu->markingsArray[i] = (sMenu->markings >> i) & 1; + sub_811FC80(x, y, sMenu->baseTileTag, sMenu->basePaletteTag); +} + +void sub_811FAF8(void) +{ + u16 i; + + for (i = 0; i < 2; i++) + { + FreeSpriteTilesByTag(sMenu->baseTileTag + i); + FreeSpritePaletteByTag(sMenu->basePaletteTag + i); + } + for (i = 0; i < 2; i++) + { + if (!sMenu->menuWindowSprites[i]) + return; + DestroySprite(sMenu->menuWindowSprites[i]); + sMenu->menuWindowSprites[i] = NULL; + } + for (i = 0; i < 4; i++) + { + if (!sMenu->menuMarkingSprites[i]) + return; + DestroySprite(sMenu->menuMarkingSprites[i]); + sMenu->menuMarkingSprites[i] = NULL; + } + if (sMenu->unkSprite) + { + DestroySprite(sMenu->unkSprite); + sMenu->unkSprite = NULL; + } + if (sMenu->menuTextSprite) + { + DestroySprite(sMenu->menuTextSprite); + sMenu->menuTextSprite = NULL; + } +} + + +bool8 sub_811FBA4(void) +{ + u16 i; + + if (gMain.newKeys & DPAD_UP) + { + s8 pos; + PlaySE(SE_SELECT); + pos = --sMenu->cursorPos; + if (pos < 0) + sMenu->cursorPos = 5; + return TRUE; + } + + if (gMain.newKeys & DPAD_DOWN) + { + s8 pos; + PlaySE(SE_SELECT); + pos = ++sMenu->cursorPos; + if (pos > 5) + sMenu->cursorPos = 0; + return TRUE; + } + + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + + switch (sMenu->cursorPos) + { + case 4: + sMenu->markings = 0; + for (i = 0; i < 4; i++) + sMenu->markings |= sMenu->markingsArray[i] << i; + return FALSE; + case 5: + return FALSE; + } + + sMenu->markingsArray[sMenu->cursorPos] = !sMenu->markingsArray[sMenu->cursorPos]; + return TRUE; + } + + if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + return FALSE; + } + + return TRUE; +} + +static void sub_811FC80(s16 x, s16 y, u16 baseTileTag, u16 basePaletteTag) +{ + u16 i; + u8 spriteId; + + struct SpriteSheet sheets[] = + { + { sMenu->menuWindowSpriteTiles, 0x1000, baseTileTag }, + { gPokenavConditionMarker_Gfx, 0x320, baseTileTag + 1 }, + { NULL, 0 } + }; + + struct SpritePalette palettes[] = + { + { sMenu->framePalette, basePaletteTag }, + { gPokenavConditionMarker_Pal, basePaletteTag + 1}, + { NULL, 0 } + }; + + struct SpriteTemplate sprTemplate = + { + baseTileTag, + basePaletteTag, + &gUnknown_0859EE7C, + gUnknown_0859EF14, + NULL, + gDummySpriteAffineAnimTable, + TaskDummy7, + }; + + LoadSpriteSheets(sheets); + LoadSpritePalettes(palettes); + + for (i = 0; i < 2; i++) + { + spriteId = CreateSprite(&sprTemplate, x + 32, y + 32, 1); + if (spriteId != 64) + { + sMenu->menuWindowSprites[i] = &gSprites[spriteId]; + StartSpriteAnim(&gSprites[spriteId], i); + } + else + { + sMenu->menuWindowSprites[i] = NULL; + return; + } + } + + sMenu->menuWindowSprites[1]->pos1.y = y + 96; + + sprTemplate.tileTag++; + sprTemplate.paletteTag++; + sprTemplate.anims = gUnknown_0859EEDC; + sprTemplate.callback = sub_811FF40; + sprTemplate.oam = &gUnknown_0859EE84; + + for (i = 0; i < 4; i++) + { + spriteId = CreateSprite(&sprTemplate, x + 32, y + 16 + 16 * i, 0); + if (spriteId != 64) + { + sMenu->menuMarkingSprites[i] = &gSprites[spriteId]; + gSprites[spriteId].data[0] = i; + } + else + { + sMenu->menuMarkingSprites[i] = NULL; + return; + } + } + + sprTemplate.callback = SpriteCallbackDummy; + + spriteId = CreateSprite(&sprTemplate, 0, 0, 0); + + if (spriteId != 64) + { + sMenu->menuTextSprite = &gSprites[spriteId]; + sMenu->menuTextSprite->oam.shape = ST_OAM_SQUARE; + sMenu->menuTextSprite->oam.size = 2; + StartSpriteAnim(sMenu->menuTextSprite, 9); + sMenu->menuTextSprite->pos1.x = x + MENU_TEXT_SPRITE_X_OFFSET; + sMenu->menuTextSprite->pos1.y = y + 80; + CalcCenterToCornerVec(sMenu->menuTextSprite, 1, 2, 0); + } + else + { + sMenu->menuTextSprite = NULL; + } + + sprTemplate.callback = sub_811FF7C; + spriteId = CreateSprite(&sprTemplate, x + 12, 0, 0); + if(spriteId != 64) + { + sMenu->unkSprite = &gSprites[spriteId]; + sMenu->unkSprite->data[0] = y + 16; + StartSpriteAnim(sMenu->unkSprite, 8); + } + else + { + sMenu->unkSprite = NULL; + } + +} + +static void TaskDummy7(struct Sprite *sprite) +{ +} + +static void sub_811FF40(struct Sprite *sprite) +{ + if (sMenu->markingsArray[sprite->data[0]]) + StartSpriteAnim(sprite, 2 * sprite->data[0] + 1); + else + StartSpriteAnim(sprite, 2 * sprite->data[0]); +} + +static void sub_811FF7C(struct Sprite *sprite) +{ + sprite->pos1.y = (16 * sMenu->cursorPos) + sprite->data[0]; +} + +struct Sprite *sub_811FF94(u16 tileTag, u16 paletteTag, const u16 *palette) +{ + if (!palette) + palette = gUnknown_0859E65C; + return sub_811FFD4(tileTag, paletteTag, palette, 16); +} + +struct Sprite *sub_811FFB4(u16 tileTag, u16 paletteTag, const u16 *palette) +{ + if (!palette) + palette = gUnknown_0859E65C; + return sub_811FFD4(tileTag, paletteTag, palette, 1); +} + +static struct Sprite *sub_811FFD4(u16 tileTag, u16 paletteTag, const u16 *palette, u16 size) +{ + u8 spriteId; + struct SpriteTemplate sprTemplate; + struct SpriteSheet sheet = { gUnknown_0859E67C, 0x80, tileTag }; + struct SpritePalette sprPalette = { palette, paletteTag }; + + sprTemplate.tileTag = tileTag; + sprTemplate.paletteTag = paletteTag; + sprTemplate.oam = &gUnknown_0859EF1C; + sprTemplate.anims = gUnknown_0859EFA4; + sprTemplate.images = NULL; + sprTemplate.affineAnims = gDummySpriteAffineAnimTable; + sprTemplate.callback = TaskDummy7; + + sheet.size = size * 0x80; + + LoadSpriteSheet(&sheet); + LoadSpritePalette(&sprPalette); + + spriteId = CreateSprite(&sprTemplate, 0, 0, 0); + if (spriteId != 64) + return &gSprites[spriteId]; + else + return NULL; +} + +void sub_8120084(u8 markings, void *dest) +{ + RequestDma3Copy(gUnknown_0859E67C + markings * 0x80, dest, 0x80, 0x10); +} diff --git a/src/overworld.c b/src/overworld.c index 920f6f8f1..532615f27 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -89,9 +89,6 @@ extern const u16 gUnknown_82EC7C4[]; extern u16 gSaveFileStatus; extern u16 gUnknown_03005DA8; -extern u8 *gUnknown_03005DA0; -extern u8 *gUnknown_03005D9C; -extern u8 *gUnknown_03005DA4; extern bool8 (*gUnknown_03005DB0)(void); extern u8 gUnknown_03005DB4; extern u8 gFieldLinkPlayerCount; @@ -1422,12 +1419,12 @@ static void overworld_bg_setup(void) SetBgAttribute(1, BG_CTRL_ATTR_PALETTEMODE, 1); SetBgAttribute(2, BG_CTRL_ATTR_PALETTEMODE, 1); SetBgAttribute(3, BG_CTRL_ATTR_PALETTEMODE, 1); - gUnknown_03005DA0 = AllocZeroed(0x800); - gUnknown_03005D9C = AllocZeroed(0x800); - gUnknown_03005DA4 = AllocZeroed(0x800); - SetBgTilemapBuffer(1, gUnknown_03005DA0); - SetBgTilemapBuffer(2, gUnknown_03005D9C); - SetBgTilemapBuffer(3, gUnknown_03005DA4); + gBGTilemapBuffers2 = AllocZeroed(0x800); + gBGTilemapBuffers1 = AllocZeroed(0x800); + gBGTilemapBuffers3 = AllocZeroed(0x800); + SetBgTilemapBuffer(1, gBGTilemapBuffers2); + SetBgTilemapBuffer(2, gBGTilemapBuffers1); + SetBgTilemapBuffer(3, gBGTilemapBuffers3); sub_81971D0(); } @@ -1435,12 +1432,12 @@ void overworld_free_bg_tilemaps(void) { sub_81BE72C(); sub_81971F4(); - if (gUnknown_03005DA4 != NULL) - FREE_AND_SET_NULL(gUnknown_03005DA4); - if (gUnknown_03005D9C != NULL) - FREE_AND_SET_NULL(gUnknown_03005D9C); - if (gUnknown_03005DA0 != NULL) - FREE_AND_SET_NULL(gUnknown_03005DA0); + if (gBGTilemapBuffers3 != NULL) + FREE_AND_SET_NULL(gBGTilemapBuffers3); + if (gBGTilemapBuffers1 != NULL) + FREE_AND_SET_NULL(gBGTilemapBuffers1); + if (gBGTilemapBuffers2 != NULL) + FREE_AND_SET_NULL(gBGTilemapBuffers2); } static void ResetSafariZoneFlag_(void) diff --git a/src/rotating_gate.c b/src/rotating_gate.c new file mode 100644 index 000000000..db5935fc3 --- /dev/null +++ b/src/rotating_gate.c @@ -0,0 +1,1188 @@ +#include "global.h" +#include "bike.h" +#include "event_data.h" +#include "field_map_obj.h" +#include "constants/maps.h" +#include "constants/songs.h" +#include "sound.h" +#include "sprite.h" + +#define ROTATING_GATE_TILE_TAG 0x1300 +#define ROTATING_GATE_PUZZLE_MAX 12 +#define GATE_ARM_MAX_LENGTH 2 + +#define GATE_ROT(rotationDirection, arm, longArm) \ + ((rotationDirection & 15) << 4) | ((arm & 7) << 1) | (longArm & 1) +#define GATE_ROT_CW(arm, longArm) GATE_ROT(ROTATE_CLOCKWISE, arm, longArm) +#define GATE_ROT_ACW(arm, longArm) GATE_ROT(ROTATE_ANTICLOCKWISE, arm, longArm) +#define GATE_ROT_NONE 255 + +// static functions +static void SpriteCallback_RotatingGate(struct Sprite *sprite); +static u8 RotatingGate_CreateGate(u8 gateId, s16 deltaX, s16 deltaY); +static void RotatingGate_HideGatesOutsideViewport(struct Sprite *sprite); + +// enums +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, +}; + +// structure +struct RotatingGatePuzzle +{ + s16 x; + s16 y; + u8 shape; + u8 orientation; +}; + +struct Coords8 +{ + s8 deltaX; + s8 deltaY; +}; + +// .rodata +// Fortree +static const struct RotatingGatePuzzle sRotatingGate_FortreePuzzleConfig[] = +{ + { 6, 7, GATE_SHAPE_T2, GATE_ORIENTATION_90}, + { 9, 15, GATE_SHAPE_T2, GATE_ORIENTATION_180}, + { 3, 19, GATE_SHAPE_T2, GATE_ORIENTATION_90}, + { 2, 6, GATE_SHAPE_T1, GATE_ORIENTATION_90}, + { 9, 12, GATE_SHAPE_T1, GATE_ORIENTATION_0}, + { 6, 23, GATE_SHAPE_T1, GATE_ORIENTATION_0}, + {12, 22, GATE_SHAPE_T1, GATE_ORIENTATION_0}, + { 6, 3, GATE_SHAPE_L4, GATE_ORIENTATION_180}, +}; + +// Trickhouse +static const struct RotatingGatePuzzle sRotatingGate_TrickHousePuzzleConfig[] = +{ + {14, 5, GATE_SHAPE_T1, GATE_ORIENTATION_90}, + {10, 6, GATE_SHAPE_L2, GATE_ORIENTATION_180}, + { 6, 6, GATE_SHAPE_L4, GATE_ORIENTATION_90}, + {14, 8, GATE_SHAPE_T1, GATE_ORIENTATION_90}, + { 3, 10, GATE_SHAPE_L3, GATE_ORIENTATION_270}, + { 9, 14, GATE_SHAPE_L1, GATE_ORIENTATION_90}, + { 3, 15, GATE_SHAPE_T3, GATE_ORIENTATION_0}, + { 2, 17, GATE_SHAPE_L2, GATE_ORIENTATION_180}, + {12, 18, GATE_SHAPE_T3, GATE_ORIENTATION_270}, + { 5, 18, GATE_SHAPE_L4, GATE_ORIENTATION_90}, + {10, 19, GATE_SHAPE_L3, GATE_ORIENTATION_180}, +}; + +static const u8 sRotatingGateTiles_1[] = INCBIN_U8("graphics/misc/rotating_gate_1.4bpp"); +static const u8 sRotatingGateTiles_2[] = INCBIN_U8("graphics/misc/rotating_gate_2.4bpp"); +static const u8 sRotatingGateTiles_3[] = INCBIN_U8("graphics/misc/rotating_gate_3.4bpp"); +static const u8 sRotatingGateTiles_4[] = INCBIN_U8("graphics/misc/rotating_gate_4.4bpp"); +static const u8 sRotatingGateTiles_5[] = INCBIN_U8("graphics/misc/rotating_gate_5.4bpp"); +static const u8 sRotatingGateTiles_6[] = INCBIN_U8("graphics/misc/rotating_gate_6.4bpp"); +static const u8 sRotatingGateTiles_7[] = INCBIN_U8("graphics/misc/rotating_gate_7.4bpp"); +static const u8 sRotatingGateTiles_8[] = INCBIN_U8("graphics/misc/rotating_gate_8.4bpp"); + +static const struct OamData sOamData_RotatingGateLarge = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_NORMAL, + .objMode = 0, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = ST_OAM_SQUARE, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 2, + .paletteNum = 2, + .affineParam = 0, +}; + +static const struct OamData sOamData_RotatingGateRegular = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_NORMAL, + .objMode = 0, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = ST_OAM_SQUARE, + .x = 0, + .matrixNum = 0, + .size = 2, + .tileNum = 0, + .priority = 2, + .paletteNum = 2, + .affineParam = 0, +}; + +static const struct SpriteSheet sRotatingGatesGraphicsTable[] = +{ + {sRotatingGateTiles_1, 0x200, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L1}, + {sRotatingGateTiles_2, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L2}, + {sRotatingGateTiles_3, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L3}, + {sRotatingGateTiles_4, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L4}, + {sRotatingGateTiles_5, 0x200, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T1}, + {sRotatingGateTiles_6, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T2}, + {sRotatingGateTiles_7, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T3}, + {sRotatingGateTiles_8, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T4}, + {NULL}, +}; + +static const union AnimCmd sSpriteAnim_RotatingGateLarge[] = +{ + ANIMCMD_FRAME(0, 0), + ANIMCMD_END, +}; + +static const union AnimCmd sSpriteAnim_RotatingGateRegular[] = +{ + ANIMCMD_FRAME(0, 0), ANIMCMD_END, +}; + +static const union AnimCmd *const sSpriteAnimTable_RotatingGateLarge[] = +{ + sSpriteAnim_RotatingGateLarge, +}; + +static const union AnimCmd *const sSpriteAnimTable_RotatingGateRegular[] = +{ + sSpriteAnim_RotatingGateRegular, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated0[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated90[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated180[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated270[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise0to90[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise90to180[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise180to270[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise270to360[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise360to270[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise270to180[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise180to90[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise90to0[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise0to90Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise90to180Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise180to270Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise270to360Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise360to270Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise270to180Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise180to90Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +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 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, +}; + + +static const struct SpriteTemplate sSpriteTemplate_RotatingGateLarge = +{ + .tileTag = ROTATING_GATE_TILE_TAG, + .paletteTag = 0xFFFF, + .oam = &sOamData_RotatingGateLarge, + .anims = sSpriteAnimTable_RotatingGateLarge, + .images = NULL, + .affineAnims = sSpriteAffineAnimTable_RotatingGate, + .callback = SpriteCallback_RotatingGate, +}; + +static const struct SpriteTemplate sSpriteTemplate_RotatingGateRegular = +{ + .tileTag = ROTATING_GATE_TILE_TAG, + .paletteTag = 0xFFFF, + .oam = &sOamData_RotatingGateRegular, + .anims = sSpriteAnimTable_RotatingGateRegular, + .images = NULL, + .affineAnims = sSpriteAffineAnimTable_RotatingGate, + .callback = SpriteCallback_RotatingGate, +}; + +// 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_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_CW(GATE_ARM_WEST, 1), GATE_ROT_CW(GATE_ARM_WEST, 0), GATE_ROT_ACW(GATE_ARM_EAST, 0), GATE_ROT_ACW(GATE_ARM_EAST, 1), + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, +}; + +static const u8 sRotatingGate_RotationInfoSouth[4 * 4] = +{ + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_ACW(GATE_ARM_WEST, 1), GATE_ROT_ACW(GATE_ARM_WEST, 0), GATE_ROT_CW(GATE_ARM_EAST, 0), GATE_ROT_CW(GATE_ARM_EAST, 1), + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, +}; + +static const u8 sRotatingGate_RotationInfoWest[4 * 4] = +{ + GATE_ROT_NONE, GATE_ROT_ACW(GATE_ARM_NORTH, 1), GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_ACW(GATE_ARM_NORTH, 0), GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_CW(GATE_ARM_SOUTH, 0), GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_CW(GATE_ARM_SOUTH, 1), GATE_ROT_NONE, GATE_ROT_NONE, +}; + +static const u8 sRotatingGate_RotationInfoEast[4 * 4] = +{ + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_CW(GATE_ARM_NORTH, 1), GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_CW(GATE_ARM_NORTH, 0), GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_ACW(GATE_ARM_SOUTH, 0), GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_ACW(GATE_ARM_SOUTH, 1), GATE_ROT_NONE, +}; + +// 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 Coords8 sRotatingGate_ArmPositionsAntiClockwiseRotation[] = { + { -1, -1 }, { -1, -2 }, { 0, -1 }, { 1, -1 }, { 0, 0 }, { 0, 1 }, { -1, 0 }, { -2, 0 }, +}; + +// 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[][4 * 2] = +{ + // L-shape gates + { + 1, 0, + 1, 0, + 0, 0, + 0, 0, + }, + { + 1, 1, + 1, 0, + 0, 0, + 0, 0, + }, + { + 1, 0, + 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, 1, + 1, 0, + 1, 0, + 0, 0, + }, + { + 1, 0, + 1, 1, + 1, 0, + 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, 0, + 1, 1, + 0, 0, + }, + { + 1, 0, + 1, 1, + 1, 1, + 0, 0, + }, + { + 1, 1, + 1, 1, + 1, 1, + 0, 0, + }, +}; + +// ewram +static EWRAM_DATA u8 gRotatingGate_GateSpriteIds[ROTATING_GATE_PUZZLE_MAX] = {0}; +static EWRAM_DATA const struct RotatingGatePuzzle *gRotatingGate_PuzzleConfig = NULL; +static EWRAM_DATA u8 gRotatingGate_PuzzleCount = 0; + +// text +static s32 GetCurrentMapRotatingGatePuzzleType(void) +{ + if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(FORTREE_CITY_GYM) && + gSaveBlock1Ptr->location.mapNum == MAP_NUM(FORTREE_CITY_GYM)) + { + return PUZZLE_FORTREE_CITY_GYM; + } + + if (gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(ROUTE110_TRICK_HOUSE_PUZZLE6) && + gSaveBlock1Ptr->location.mapNum == MAP_NUM(ROUTE110_TRICK_HOUSE_PUZZLE6)) + { + return PUZZLE_ROUTE110_TRICK_HOUSE_PUZZLE6; + } + + return PUZZLE_NONE; +} + +static void RotatingGate_ResetAllGateOrientations(void) +{ + s32 i; + u8 *ptr; + + ptr = (u8 *)GetVarPointer(VAR_0x4000); + + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + ptr[i] = gRotatingGate_PuzzleConfig[i].orientation; + } +} + +static s32 RotatingGate_GetGateOrientation(u8 gateId) +{ + return ((u8 *)GetVarPointer(VAR_0x4000))[gateId]; +} + +static void RotatingGate_SetGateOrientation(u8 gateId, u8 orientation) +{ + ((u8 *)GetVarPointer(VAR_0x4000))[gateId] = orientation; +} + +static void RotatingGate_RotateInDirection(u8 gateId, u32 rotationDirection) +{ + u8 orientation = RotatingGate_GetGateOrientation(gateId); + + if (rotationDirection == ROTATE_ANTICLOCKWISE) + { + if (orientation) + orientation--; + else + orientation = GATE_ORIENTATION_270; + } + else + { + orientation = ++orientation % GATE_ORIENTATION_MAX; + } + RotatingGate_SetGateOrientation(gateId, orientation); +} + +static void RotatingGate_LoadPuzzleConfig(void) +{ + s32 puzzleType = GetCurrentMapRotatingGatePuzzleType(); + u32 i; + + switch (puzzleType) + { + case PUZZLE_FORTREE_CITY_GYM: + gRotatingGate_PuzzleConfig = sRotatingGate_FortreePuzzleConfig; + gRotatingGate_PuzzleCount = + sizeof(sRotatingGate_FortreePuzzleConfig) / sizeof(struct RotatingGatePuzzle); + break; + case PUZZLE_ROUTE110_TRICK_HOUSE_PUZZLE6: + gRotatingGate_PuzzleConfig = sRotatingGate_TrickHousePuzzleConfig; + gRotatingGate_PuzzleCount = + sizeof(sRotatingGate_TrickHousePuzzleConfig) / sizeof(struct RotatingGatePuzzle); + break; + case PUZZLE_NONE: + default: + return; + } + + for (i = 0; i < ROTATING_GATE_PUZZLE_MAX - 1; i++) + { + gRotatingGate_GateSpriteIds[i] = MAX_SPRITES; + } +} + +static void RotatingGate_CreateGatesWithinViewport(s16 deltaX, s16 deltaY) +{ + u8 i; + + // Calculate the bounding box of the camera + // Same as RotatingGate_DestroyGatesOutsideViewport + s16 x = gSaveBlock1Ptr->pos.x - 2; + s16 x2 = gSaveBlock1Ptr->pos.x + 0x11; + s16 y = gSaveBlock1Ptr->pos.y - 2; + s16 y2 = gSaveBlock1Ptr->pos.y + 0xe; + + s16 x3, y3; + + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + x3 = gRotatingGate_PuzzleConfig[i].x + 7; + y3 = gRotatingGate_PuzzleConfig[i].y + 7; + + if (y <= y3 && y2 >= y3 && x <= x3 && x2 >= x3 && + gRotatingGate_GateSpriteIds[i] == MAX_SPRITES) + { + gRotatingGate_GateSpriteIds[i] = RotatingGate_CreateGate(i, deltaX, deltaY); + } + } +} + +static u8 RotatingGate_CreateGate(u8 gateId, s16 deltaX, s16 deltaY) +{ + struct Sprite *sprite; + struct SpriteTemplate template; + const struct RotatingGatePuzzle *gate; + u8 spriteId; + s16 x, y; + + gate = &gRotatingGate_PuzzleConfig[gateId]; + + if (gate->shape == GATE_SHAPE_L1 || gate->shape == GATE_SHAPE_T1) + template = sSpriteTemplate_RotatingGateRegular; + else + template = sSpriteTemplate_RotatingGateLarge; + + template.tileTag = gate->shape + ROTATING_GATE_TILE_TAG; + + spriteId = CreateSprite(&template, 0, 0, 0x94); + if (spriteId == MAX_SPRITES) + return MAX_SPRITES; + + x = gate->x + 7; + y = gate->y + 7; + + sprite = &gSprites[spriteId]; + sprite->data[0] = gateId; + sprite->coordOffsetEnabled = 1; + + sub_8092FF0(x + deltaX, y + deltaY, &sprite->pos1.x, &sprite->pos1.y); + RotatingGate_HideGatesOutsideViewport(sprite); + StartSpriteAffineAnim(sprite, RotatingGate_GetGateOrientation(gateId)); + + return spriteId; +} + +static void SpriteCallback_RotatingGate(struct Sprite *sprite) +{ + u8 rotationDirection; + u8 orientation; + u8 affineAnimation; + + rotationDirection = sprite->data[1]; + orientation = sprite->data[2]; + + RotatingGate_HideGatesOutsideViewport(sprite); + + if (rotationDirection == ROTATE_ANTICLOCKWISE) + { + affineAnimation = orientation + 4; + + if (GetPlayerSpeed() != 1) + affineAnimation += 8; + + PlaySE(SE_HI_TURUN); + StartSpriteAffineAnim(sprite, affineAnimation); + } + else if (rotationDirection == ROTATE_CLOCKWISE) + { + affineAnimation = orientation + 8; + + if (GetPlayerSpeed() != 1) + affineAnimation += 8; + + PlaySE(SE_HI_TURUN); + StartSpriteAffineAnim(sprite, affineAnimation); + } + + sprite->data[1] = ROTATE_NONE; +} + +static void RotatingGate_HideGatesOutsideViewport(struct Sprite *sprite) +{ + u16 x; + s16 x2; + u16 y; + s16 y2; + + sprite->invisible = FALSE; + x = sprite->pos1.x + sprite->pos2.x + sprite->centerToCornerVecX + gSpriteCoordOffsetX; + y = sprite->pos1.y + sprite->pos2.y + sprite->centerToCornerVecY + gSpriteCoordOffsetY; + + x2 = x + 0x40; // Dimensions of the rotating gate + y2 = y + 0x40; + + if ((s16)x > DISPLAY_WIDTH + 0x10 - 1 || x2 < -0x10) + { + sprite->invisible = TRUE; + } + + if ((s16)y > DISPLAY_HEIGHT + 0x10 - 1 || y2 < -0x10) + { + sprite->invisible = TRUE; + } +} + +static void LoadRotatingGatePics(void) +{ + LoadSpriteSheets(sRotatingGatesGraphicsTable); +} + +/* +static*/ void RotatingGate_DestroyGatesOutsideViewport(void) +{ + s16 x; + s16 x2; + s16 y; + s16 y2; + s16 xGate; + s16 yGate; + s32 i; + struct Sprite *sprite; + + // Same as RotatingGate_CreateGatesWithinViewport + x = gSaveBlock1Ptr->pos.x - 2; + x2 = gSaveBlock1Ptr->pos.x + 0x11; + y = gSaveBlock1Ptr->pos.y - 2; + y2 = gSaveBlock1Ptr->pos.y + 0xe; + + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + xGate = gRotatingGate_PuzzleConfig[i].x + 7; + yGate = gRotatingGate_PuzzleConfig[i].y + 7; + + if (gRotatingGate_GateSpriteIds[i] == MAX_SPRITES) + continue; + + if (xGate < x || xGate > x2 || yGate < y || yGate > y2) + { + sprite = &gSprites[gRotatingGate_GateSpriteIds[i]]; + FreeSpriteOamMatrix(sprite); + DestroySprite(sprite); + gRotatingGate_GateSpriteIds[i] = MAX_SPRITES; + } + } +} + + +#ifdef NONMATCHING +bool8 MapGridIsImpassableAt(s32, s32); //fool the compiler + +static s32 RotatingGate_CanRotate(u8 gateId, s16 rotationDirection) +{ + const struct Coords8 *armPos; + u8 orientation; + s16 x; + s16 y; + u8 shape; + u32 shape8; + s32 i; + s32 j; + s32 armOrientation; + const u8 *gateArmCollisionData; + u8 armIndex; + + if (rotationDirection == ROTATE_ANTICLOCKWISE) + armPos = sRotatingGate_ArmPositionsAntiClockwiseRotation; + else if (rotationDirection == ROTATE_CLOCKWISE) + armPos = sRotatingGate_ArmPositionsClockwiseRotation; + else + return FALSE; + + orientation = RotatingGate_GetGateOrientation(gateId); + + shape = gRotatingGate_PuzzleConfig[gateId].shape; + x = gRotatingGate_PuzzleConfig[gateId].x + 7; + y = gRotatingGate_PuzzleConfig[gateId].y + 7; + + + // Loop through the gate's "arms" clockwise (north, south, east, west) + for (i = GATE_ARM_NORTH, shape8 = shape* 4*2 ; i <= GATE_ARM_WEST; i++) + { + // Ensure that no part of the arm collides with the map + for (j = 0, armOrientation = orientation + i, gateArmCollisionData = (u8 *)((u32)sRotatingGate_ArmLayout + shape8 + 2*i); j < GATE_ARM_MAX_LENGTH; j++) + { + armIndex = 2 * (armOrientation % 4) + j; + + if (*gateArmCollisionData) + { + if (MapGridIsImpassableAt(x + armPos[armIndex].deltaX, y + armPos[armIndex].deltaY) == TRUE) + return FALSE; + } + gateArmCollisionData++; + } + } + + return TRUE; +} + +#else +ASM_DIRECT +static s32 RotatingGate_CanRotate(u8 a, s16 rotationDirection) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0xC\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + cmp r1, 0x1\n\ + bne _080FBCFC\n\ + ldr r0, =sRotatingGate_ArmPositionsAntiClockwiseRotation\n\ + mov r10, r0\n\ + b _080FBD08\n\ + .pool\n\ +_080FBCFC:\n\ + cmp r1, 0x2\n\ + beq _080FBD04\n\ +_080FBD00:\n\ + movs r0, 0\n\ + b _080FBD98\n\ +_080FBD04:\n\ + ldr r1, =sRotatingGate_ArmPositionsClockwiseRotation\n\ + mov r10, r1\n\ +_080FBD08:\n\ + adds r0, r4, 0\n\ + bl RotatingGate_GetGateOrientation\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + str r0, [sp]\n\ + ldr r0, =gRotatingGate_PuzzleConfig\n\ + ldr r1, [r0]\n\ + lsls r0, r4, 3\n\ + adds r0, r1\n\ + ldrb r2, [r0, 0x4]\n\ + ldrh r1, [r0]\n\ + adds r1, 0x7\n\ + ldrh r0, [r0, 0x2]\n\ + adds r0, 0x7\n\ + movs r3, 0\n\ + lsls r2, 3\n\ + str r2, [sp, 0x4]\n\ + lsls r1, 16\n\ + asrs r1, 16\n\ + mov r9, r1\n\ + lsls r0, 16\n\ + asrs r0, 16\n\ + mov r8, r0\n\ +_080FBD38:\n\ + movs r6, 0\n\ + ldr r2, [sp]\n\ + adds r7, r2, r3\n\ + lsls r0, r3, 1\n\ + adds r5, r7, 0\n\ + ldr r1, [sp, 0x4]\n\ + adds r0, r1\n\ + ldr r2, =sRotatingGate_ArmLayout\n\ + adds r4, r0, r2\n\ +_080FBD4A:\n\ + adds r0, r5, 0\n\ + cmp r5, 0\n\ + bge _080FBD52\n\ + adds r0, r7, 0x3\n\ +_080FBD52:\n\ + asrs r0, 2\n\ + lsls r0, 2\n\ + subs r0, r5, r0\n\ + lsls r0, 1\n\ + adds r0, r6\n\ + lsls r0, 24\n\ + lsrs r1, r0, 24\n\ + ldrb r0, [r4]\n\ + cmp r0, 0\n\ + beq _080FBD88\n\ + lsls r1, 2\n\ + add r1, r10\n\ + movs r0, 0\n\ + ldrsb r0, [r1, r0]\n\ + add r0, r9\n\ + ldrb r1, [r1, 0x1]\n\ + lsls r1, 24\n\ + asrs r1, 24\n\ + add r1, r8\n\ + str r3, [sp, 0x8]\n\ + bl MapGridIsImpassableAt\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + ldr r3, [sp, 0x8]\n\ + cmp r0, 0x1\n\ + beq _080FBD00\n\ +_080FBD88:\n\ + adds r4, 0x1\n\ + adds r6, 0x1\n\ + cmp r6, 0x1\n\ + ble _080FBD4A\n\ + adds r3, 0x1\n\ + cmp r3, 0x3\n\ + ble _080FBD38\n\ + movs r0, 0x1\n\ +_080FBD98:\n\ + add sp, 0xC\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r1}\n\ + bx r1\n\ + .pool\n\ +.syntax divided\n"); +} +#endif + +static s32 RotatingGate_HasArm(u8 gateId, u8 armInfo) +{ + s32 isLongArm; + s8 armOrientation; + s32 arm; + s32 shape; + + arm = armInfo >> 1; + isLongArm = armInfo & 1; + + armOrientation = (arm - RotatingGate_GetGateOrientation(gateId) + 4) % 4; + shape = gRotatingGate_PuzzleConfig[gateId].shape; + return sRotatingGate_ArmLayout[shape][armOrientation * 2 + isLongArm]; +} + +static void RotatingGate_TriggerRotationAnimation(u8 gateId, s32 rotationDirection) +{ + struct Sprite *sprite; + + if (gRotatingGate_GateSpriteIds[gateId] != MAX_SPRITES) + { + sprite = &gSprites[gRotatingGate_GateSpriteIds[gateId]]; + sprite->data[1] = rotationDirection; + sprite->data[2] = RotatingGate_GetGateOrientation(gateId); + } +} + +static u8 RotatingGate_GetRotationInfo(u8 direction, s16 x, s16 y) +{ + register const u8 *ptr; + + 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 GATE_ROT_NONE; + + return ptr[y * 4 + x]; +} + +void RotatingGate_InitPuzzle(void) +{ + if (GetCurrentMapRotatingGatePuzzleType()) + { + RotatingGate_LoadPuzzleConfig(); + RotatingGate_ResetAllGateOrientations(); + } +} + +void RotatingGatePuzzleCameraUpdate(u16 deltaX, u16 deltaY) +{ + if (GetCurrentMapRotatingGatePuzzleType()) + { + RotatingGate_CreateGatesWithinViewport(deltaX, deltaY); + RotatingGate_DestroyGatesOutsideViewport(); + } +} + +void RotatingGate_InitPuzzleAndGraphics(void) +{ + if (GetCurrentMapRotatingGatePuzzleType()) + { + LoadRotatingGatePics(); + RotatingGate_LoadPuzzleConfig(); + RotatingGate_CreateGatesWithinViewport(0, 0); + } +} + +bool8 CheckForRotatingGatePuzzleCollision(u8 direction, s16 x, s16 y) +{ + s32 i; + + if (!GetCurrentMapRotatingGatePuzzleType()) + return FALSE; + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + s16 gateX = gRotatingGate_PuzzleConfig[i].x + 7; + s16 gateY = gRotatingGate_PuzzleConfig[i].y + 7; + + if (gateX - 2 <= x && x <= gateX + 1 && gateY - 2 <= y && y <= gateY + 1) + { + s16 centerX = x - gateX + 2; + s16 centerY = y - gateY + 2; + u8 rotationInfo = RotatingGate_GetRotationInfo(direction, centerX, centerY); + + if (rotationInfo != GATE_ROT_NONE) + { + u8 rotationDirection = ((rotationInfo & 0xF0) >> 4); + u8 armInfo = rotationInfo & 0xF; + + if (RotatingGate_HasArm(i, armInfo)) + { + if (RotatingGate_CanRotate(i, rotationDirection)) + { + RotatingGate_TriggerRotationAnimation(i, rotationDirection); + RotatingGate_RotateInDirection(i, rotationDirection); + return FALSE; + } + return TRUE; + } + } + } + } + return FALSE; +} + +bool8 CheckForRotatingGatePuzzleCollisionWithoutAnimation(u8 direction, s16 x, s16 y) +{ + s32 i; + + if (!GetCurrentMapRotatingGatePuzzleType()) + return FALSE; + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + s16 gateX = gRotatingGate_PuzzleConfig[i].x + 7; + s16 gateY = gRotatingGate_PuzzleConfig[i].y + 7; + + if (gateX - 2 <= x && x <= gateX + 1 && gateY - 2 <= y && y <= gateY + 1) + { + s16 centerX = x - gateX + 2; + s16 centerY = y - gateY + 2; + u8 rotationInfo = RotatingGate_GetRotationInfo(direction, centerX, centerY); + + if (rotationInfo != GATE_ROT_NONE) + { + u8 rotationDirection = ((rotationInfo & 0xF0) >> 4); + u8 armInfo = rotationInfo & 0xF; + + if (RotatingGate_HasArm(i, armInfo)) + { + if (!RotatingGate_CanRotate(i, rotationDirection)) + { + return TRUE; + } + } + } + } + } + return FALSE; +} diff --git a/src/text_window.c b/src/text_window.c index 33cd7cffe..c3b9f7197 100644 --- a/src/text_window.c +++ b/src/text_window.c @@ -7,26 +7,26 @@ #include "graphics.h" // const rom data -const u32 gTextWindowFrame1_Gfx[] = INCBIN_U32("graphics/text_window/1.4bpp"); -static const u32 sTextWindowFrame2_Gfx[] = INCBIN_U32("graphics/text_window/2.4bpp"); -static const u32 sTextWindowFrame3_Gfx[] = INCBIN_U32("graphics/text_window/3.4bpp"); -static const u32 sTextWindowFrame4_Gfx[] = INCBIN_U32("graphics/text_window/4.4bpp"); -static const u32 sTextWindowFrame5_Gfx[] = INCBIN_U32("graphics/text_window/5.4bpp"); -static const u32 sTextWindowFrame6_Gfx[] = INCBIN_U32("graphics/text_window/6.4bpp"); -static const u32 sTextWindowFrame7_Gfx[] = INCBIN_U32("graphics/text_window/7.4bpp"); -static const u32 sTextWindowFrame8_Gfx[] = INCBIN_U32("graphics/text_window/8.4bpp"); -static const u32 sTextWindowFrame9_Gfx[] = INCBIN_U32("graphics/text_window/9.4bpp"); -static const u32 sTextWindowFrame10_Gfx[] = INCBIN_U32("graphics/text_window/10.4bpp"); -static const u32 sTextWindowFrame11_Gfx[] = INCBIN_U32("graphics/text_window/11.4bpp"); -static const u32 sTextWindowFrame12_Gfx[] = INCBIN_U32("graphics/text_window/12.4bpp"); -static const u32 sTextWindowFrame13_Gfx[] = INCBIN_U32("graphics/text_window/13.4bpp"); -static const u32 sTextWindowFrame14_Gfx[] = INCBIN_U32("graphics/text_window/14.4bpp"); -static const u32 sTextWindowFrame15_Gfx[] = INCBIN_U32("graphics/text_window/15.4bpp"); -static const u32 sTextWindowFrame16_Gfx[] = INCBIN_U32("graphics/text_window/16.4bpp"); -static const u32 sTextWindowFrame17_Gfx[] = INCBIN_U32("graphics/text_window/17.4bpp"); -static const u32 sTextWindowFrame18_Gfx[] = INCBIN_U32("graphics/text_window/18.4bpp"); -static const u32 sTextWindowFrame19_Gfx[] = INCBIN_U32("graphics/text_window/19.4bpp"); -static const u32 sTextWindowFrame20_Gfx[] = INCBIN_U32("graphics/text_window/20.4bpp"); +const u8 gTextWindowFrame1_Gfx[] = INCBIN_U8("graphics/text_window/1.4bpp"); +static const u8 sTextWindowFrame2_Gfx[] = INCBIN_U8("graphics/text_window/2.4bpp"); +static const u8 sTextWindowFrame3_Gfx[] = INCBIN_U8("graphics/text_window/3.4bpp"); +static const u8 sTextWindowFrame4_Gfx[] = INCBIN_U8("graphics/text_window/4.4bpp"); +static const u8 sTextWindowFrame5_Gfx[] = INCBIN_U8("graphics/text_window/5.4bpp"); +static const u8 sTextWindowFrame6_Gfx[] = INCBIN_U8("graphics/text_window/6.4bpp"); +static const u8 sTextWindowFrame7_Gfx[] = INCBIN_U8("graphics/text_window/7.4bpp"); +static const u8 sTextWindowFrame8_Gfx[] = INCBIN_U8("graphics/text_window/8.4bpp"); +static const u8 sTextWindowFrame9_Gfx[] = INCBIN_U8("graphics/text_window/9.4bpp"); +static const u8 sTextWindowFrame10_Gfx[] = INCBIN_U8("graphics/text_window/10.4bpp"); +static const u8 sTextWindowFrame11_Gfx[] = INCBIN_U8("graphics/text_window/11.4bpp"); +static const u8 sTextWindowFrame12_Gfx[] = INCBIN_U8("graphics/text_window/12.4bpp"); +static const u8 sTextWindowFrame13_Gfx[] = INCBIN_U8("graphics/text_window/13.4bpp"); +static const u8 sTextWindowFrame14_Gfx[] = INCBIN_U8("graphics/text_window/14.4bpp"); +static const u8 sTextWindowFrame15_Gfx[] = INCBIN_U8("graphics/text_window/15.4bpp"); +static const u8 sTextWindowFrame16_Gfx[] = INCBIN_U8("graphics/text_window/16.4bpp"); +static const u8 sTextWindowFrame17_Gfx[] = INCBIN_U8("graphics/text_window/17.4bpp"); +static const u8 sTextWindowFrame18_Gfx[] = INCBIN_U8("graphics/text_window/18.4bpp"); +static const u8 sTextWindowFrame19_Gfx[] = INCBIN_U8("graphics/text_window/19.4bpp"); +static const u8 sTextWindowFrame20_Gfx[] = INCBIN_U8("graphics/text_window/20.4bpp"); const u16 gTextWindowFrame1_Pal[] = INCBIN_U16("graphics/text_window/1.gbapal"); static const u16 sTextWindowFrame2_Pal[] = INCBIN_U16("graphics/text_window/2.gbapal"); |