diff options
Diffstat (limited to 'src/mirage_tower.c')
-rw-r--r-- | src/mirage_tower.c | 868 |
1 files changed, 868 insertions, 0 deletions
diff --git a/src/mirage_tower.c b/src/mirage_tower.c new file mode 100644 index 000000000..a8dd5d9de --- /dev/null +++ b/src/mirage_tower.c @@ -0,0 +1,868 @@ +#include "global.h" +#include "alloc.h" +#include "bg.h" +#include "event_data.h" +#include "event_object_movement.h" +#include "field_camera.h" +#include "fieldmap.h" +#include "gpu_regs.h" +#include "menu.h" +#include "random.h" +#include "roulette_util.h" +#include "script.h" +#include "sound.h" +#include "sprite.h" +#include "task.h" +#include "window.h" +#include "constants/flags.h" +#include "constants/maps.h" +#include "constants/rgb.h" +#include "constants/songs.h" + +struct MirageTowerPulseBlend { + u8 taskId; + struct PulseBlend pulseBlend; +}; + +struct MetatileCoords +{ + u8 x; + u8 y; + u16 metatileId; +}; + +struct BgRegOffsets +{ + u16 bgHOFS; + u16 bgVOFS; +}; + +struct Struct203CF10 +{ + u8 *buffer; + u8 currIndex; +}; + +struct DynamicSpriteFrameImage +{ + u8 *data; + u16 size; +}; + +struct Struct203CF0C +{ + u8 *frameImageTiles; + struct DynamicSpriteFrameImage *frameImage; + u8 spriteId; + u16 *unkC; + u16 unk10; +}; + +#define MIRAGE_TOWER_GFX_LENGTH (sizeof(sBlankTile_Gfx) + sizeof(sMirageTower_Gfx)) +#define ROOT_FOSSIL_GFX_LENGTH sizeof(sRootFossil_Gfx) +#define ROOT_FOSSIL_GFX_RANDOMIZER_LENGTH 0x100 + +// extern data +extern const struct SpriteSheet gMirageTowerCeilingCrumbleSpriteSheets[]; +extern const s16 sCeilingCrumblePositions[][3]; + +// static functions +static void PlayerDescendMirageTower(u8 taskId); +static void DoScreenShake(u8 taskId); +static void IncrementCeilingCrumbleFinishedCount(void); +static void WaitCeilingCrumble(u8 taskId); +static void FinishCeilingCrumbleTask(u8 taskId); +static void CreateCeilingCrumbleSprites(void); +static void MoveCeilingCrumbleSprite(struct Sprite* sprite); +static void DoMirageTowerDisintegration(u8 taskId); +static void InitMirageTowerShake(u8 taskId); +static void DoFossilFallAndSink(u8 taskId); +static void sub_81BF248(struct Sprite *); +static void sub_81BF2B8(u8* a, u16 b, u8 c, u8 d, u8 e); + +// rodata +static const u8 sBlankTile_Gfx[32] = {0}; +static const u8 sMirageTower_Gfx[] = INCBIN_U8("graphics/misc/mirage_tower.4bpp"); +static const u16 sMirageTowerTilemap[] = INCBIN_U16("graphics/misc/mirage_tower.bin"); +static const u16 sRootFossil_Pal[] = INCBIN_U16("graphics/misc/fossil.gbapal"); +static const u8 sRootFossil_Gfx[] = INCBIN_U8("graphics/misc/fossil.4bpp"); +static const u8 sMirageTowerCrumbles_Gfx[] = INCBIN_U8("graphics/misc/mirage_tower_crumbles.4bpp"); +static const u16 sMirageTowerCrumbles_Palette[] = INCBIN_U16("graphics/misc/mirage_tower_crumbles.gbapal"); + +const s16 sCeilingCrumblePositions[][3] = +{ + { 0, 10, 65}, + { 17, 3, 50}, + {-12, 0, 75}, + { 10, 15, 90}, + { 7, 8, 65}, + {-18, 5, 75}, + { 22, -10, 55}, + {-24, -4, 65}, +}; + +const struct SpriteSheet gMirageTowerCeilingCrumbleSpriteSheets[] = +{ + {sMirageTowerCrumbles_Gfx, 0x0080, 4000}, + {NULL} +}; + +static const struct MetatileCoords sInvisibleMirageTowerMetatiles[] = +{ + {18, 53, 0x251}, + {19, 53, 0x251}, + {20, 53, 0x251}, + {18, 54, 0x251}, + {19, 54, 0x251}, + {20, 54, 0x251}, + {18, 55, 0x251}, + {19, 55, 0x251}, + {20, 55, 0x251}, + {18, 56, 0x251}, + {19, 56, 0x251}, + {20, 56, 0x251}, + {18, 57, 0x259}, + {19, 57, 0x259}, + {20, 57, 0x259}, + {18, 58, 0x121}, + {19, 58, 0x121}, + {20, 58, 0x121}, +}; + +static const union AnimCmd gSpriteAnim_8617DEC[] = +{ + ANIMCMD_FRAME(0, 1), + ANIMCMD_END, +}; + +static const struct OamData gOamData_8617DF4 = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 1, + .tileNum = 0, + .priority = 0, + .paletteNum = 3, + .affineParam = 0, +}; + +static const union AnimCmd *const gSpriteAnimTable_8617DFC[] = +{ + gSpriteAnim_8617DEC, +}; + +static const struct SpriteTemplate gUnknown_08617E00 = +{ + 0xFFFF, 0xFFFF, &gOamData_8617DF4, gSpriteAnimTable_8617DFC, NULL, gDummySpriteAffineAnimTable, SpriteCallbackDummy +}; + +const struct PulseBlendSettings gMirageTowerPulseBlendSettings = { + .blendColor = RGB(27, 25, 16), + .paletteOffset = 0x61, + .numColors = 15, + .delay = 5, + .numFadeCycles = -1, + .maxBlendCoeff = 11, + .fadeType = 1, + .restorePaletteOnUnload = FALSE, + .unk7_7 = 1, +}; + +static const union AnimCmd sCeilingCrumble2AnimCmd[] = +{ + ANIMCMD_FRAME(0, 12), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const sCeilingCrumble2AnimCmds[] = +{ + sCeilingCrumble2AnimCmd, +}; + +static const struct OamData sCeilingCrumble2OamData = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_OFF, + .objMode = ST_OAM_OBJ_NORMAL, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = ST_OAM_SQUARE, + .x = 0, + .matrixNum = 0, + .size = 0, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + +static const struct SpriteTemplate sCeilingCrumbleSpriteTemplate2 = { + .tileTag = 4000, + .paletteTag = 0xFFFF, + .oam = &sCeilingCrumble2OamData, + .anims = sCeilingCrumble2AnimCmds, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = MoveCeilingCrumbleSprite +}; + +static const union AnimCmd sCeilingCrumble1AnimCmd[] = +{ + ANIMCMD_FRAME(0, 12), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const sCeilingCrumble1AnimCmds[] = +{ + sCeilingCrumble1AnimCmd, +}; + +static const struct OamData sCeilingCrumble1OamData = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_OFF, + .objMode = ST_OAM_OBJ_NORMAL, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = ST_OAM_SQUARE, + .x = 0, + .matrixNum = 0, + .size = 1, + .tileNum = 0, + .priority = 0, + .paletteNum = 0, + .affineParam = 0, +}; + +static const struct SpriteTemplate sCeilingCrumbleSpriteTemplate1 = { + .tileTag = 4000, + .paletteTag = 0xFFFF, + .oam = &sCeilingCrumble1OamData, + .anims = sCeilingCrumble1AnimCmds, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = MoveCeilingCrumbleSprite +}; + +EWRAM_DATA static u8* sMirageTowerGfxBuffer = NULL; +EWRAM_DATA static u8* sMirageTowerTilemapBuffer = NULL; +EWRAM_DATA static struct Struct203CF0C *sUnknown_0203CF0C = NULL; +EWRAM_DATA static struct Struct203CF10 *sUnknown_0203CF10 = NULL; +EWRAM_DATA static struct BgRegOffsets *sBgShakeOffsets = NULL; +EWRAM_DATA struct MirageTowerPulseBlend *sMirageTowerPulseBlend = NULL; + +IWRAM_DATA static u16 gUnknown_030012A8[8]; + +bool8 IsMirageTowerVisible(void) +{ + if (!(gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(ROUTE111) && gSaveBlock1Ptr->location.mapNum == MAP_NUM(ROUTE111))) + return FALSE; + return FlagGet(FLAG_MIRAGE_TOWER_VISIBLE); +} + +static void UpdateMirageTowerPulseBlend(u8 taskId) +{ + UpdatePulseBlend(&sMirageTowerPulseBlend->pulseBlend); +} + +void ClearMirageTowerPulseBlend(void) +{ + sMirageTowerPulseBlend = NULL; +} + +void TryStartMirageTowerPulseBlendEffect(void) +{ + if (sMirageTowerPulseBlend) + { + sMirageTowerPulseBlend = NULL; + return; + } + + if (gSaveBlock1Ptr->location.mapGroup != MAP_GROUP(ROUTE111) + || gSaveBlock1Ptr->location.mapNum != MAP_NUM(ROUTE111) + || !FlagGet(FLAG_MIRAGE_TOWER_VISIBLE)) + return; + + sMirageTowerPulseBlend = AllocZeroed(sizeof(*sMirageTowerPulseBlend)); + InitPulseBlend(&sMirageTowerPulseBlend->pulseBlend); + InitPulseBlendPaletteSettings(&sMirageTowerPulseBlend->pulseBlend, &gMirageTowerPulseBlendSettings); + MarkUsedPulseBlendPalettes(&sMirageTowerPulseBlend->pulseBlend, 0x1, TRUE); + sMirageTowerPulseBlend->taskId = CreateTask(UpdateMirageTowerPulseBlend, 0xFF); +} + +void ClearMirageTowerPulseBlendEffect(void) +{ + if (gSaveBlock1Ptr->location.mapGroup != MAP_GROUP(ROUTE111) + || gSaveBlock1Ptr->location.mapNum != MAP_NUM(ROUTE111) + || !FlagGet(FLAG_MIRAGE_TOWER_VISIBLE) + || sMirageTowerPulseBlend == NULL) + return; + + if (FuncIsActiveTask(UpdateMirageTowerPulseBlend)) + DestroyTask(sMirageTowerPulseBlend->taskId); + + UnmarkUsedPulseBlendPalettes(&sMirageTowerPulseBlend->pulseBlend, 0x1, TRUE); + UnloadUsedPulseBlendPalettes(&sMirageTowerPulseBlend->pulseBlend, 0x1, TRUE); + FREE_AND_SET_NULL(sMirageTowerPulseBlend); +} + +void SetMirageTowerVisibility(void) +{ + u16 rand; + bool8 visible; + + if (VarGet(VAR_0x40CB)) + { + FlagClear(FLAG_MIRAGE_TOWER_VISIBLE); + return; + } + + rand = Random(); + visible = rand & 1; + if (FlagGet(FLAG_FORCE_MIRAGE_TOWER_VISIBLE) == TRUE) + visible = TRUE; + + if (visible) + { + FlagSet(FLAG_MIRAGE_TOWER_VISIBLE); + TryStartMirageTowerPulseBlendEffect(); + return; + } + + FlagClear(FLAG_MIRAGE_TOWER_VISIBLE); +} + +void StartPlayerDescendMirageTower(void) +{ + CreateTask(PlayerDescendMirageTower, 8); +} + +static void PlayerDescendMirageTower(u8 taskId) +{ + u8 eventObjectId; + struct EventObject *fakePlayerEventObject; + struct EventObject *playerEventObject; + + TryGetEventObjectIdByLocalIdAndMap(45, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &eventObjectId); + fakePlayerEventObject = &gEventObjects[eventObjectId]; + gSprites[fakePlayerEventObject->spriteId].pos2.y += 4; + playerEventObject = &gEventObjects[gPlayerAvatar.eventObjectId]; + if ((gSprites[fakePlayerEventObject->spriteId].pos1.y + gSprites[fakePlayerEventObject->spriteId].pos2.y) >= + (gSprites[playerEventObject->spriteId].pos1.y + gSprites[playerEventObject->spriteId].pos2.y)) + { + DestroyTask(taskId); + EnableBothScriptContexts(); + } +} + +static void StartScreenShake(u8 yShakeOffset, u8 xShakeOffset, u8 numShakes, u8 shakeDelay) +{ + u8 taskId = CreateTask(DoScreenShake, 9); + gTasks[taskId].data[0] = xShakeOffset; + gTasks[taskId].data[1] = 0; + gTasks[taskId].data[2] = numShakes; + gTasks[taskId].data[3] = shakeDelay; + gTasks[taskId].data[4] = yShakeOffset; + SetCameraPanningCallback(NULL); + PlaySE(SE_W070); +} + +static void DoScreenShake(u8 taskId) +{ + s16 *data; + + data = gTasks[taskId].data; + data[1]++; + if (data[1] % data[3] == 0) + { + data[1] = 0; + data[2]--; + data[0] = -data[0]; + data[4] = -data[4]; + SetCameraPanning(data[0], data[4]); + if (data[2] == 0) + { + IncrementCeilingCrumbleFinishedCount(); + DestroyTask(taskId); + InstallCameraPanAheadCallback(); + } + } +} + +static void IncrementCeilingCrumbleFinishedCount(void) +{ + u8 taskId = FindTaskIdByFunc(WaitCeilingCrumble); + if (taskId != 0xFF) + gTasks[taskId].data[0]++; +} + +void DoMirageTowerCeilingCrumble(void) +{ + LoadSpriteSheets(gMirageTowerCeilingCrumbleSpriteSheets); + CreateCeilingCrumbleSprites(); + CreateTask(WaitCeilingCrumble, 8); + StartScreenShake(2, 1, 16, 3); +} + +static void WaitCeilingCrumble(u8 taskId) +{ + u16 *data = gTasks[taskId].data; + data[1]++; + // Either wait 1000 frames, or until all 16 crumble sprites and the one screen-shake task are completed. + if (data[1] == 1000 || data[0] == 17) + gTasks[taskId].func = FinishCeilingCrumbleTask; +} + +static void FinishCeilingCrumbleTask(u8 taskId) +{ + FreeSpriteTilesByTag(4000); + DestroyTask(taskId); + EnableBothScriptContexts(); +} + +static void CreateCeilingCrumbleSprites(void) +{ + u8 i; + u8 spriteId; + + for (i = 0; i < 8; i++) + { + spriteId = CreateSprite(&sCeilingCrumbleSpriteTemplate1, sCeilingCrumblePositions[i][0] + 120, sCeilingCrumblePositions[i][1], 8); + gSprites[spriteId].oam.priority = 0; + gSprites[spriteId].oam.paletteNum = 0; + gSprites[spriteId].data[0] = i; + } + for (i = 0; i < 8; i++) + { + spriteId = CreateSprite(&sCeilingCrumbleSpriteTemplate2, sCeilingCrumblePositions[i][0] + 115, sCeilingCrumblePositions[i][1] - 3, 8); + gSprites[spriteId].oam.priority = 0; + gSprites[spriteId].oam.paletteNum = 0; + gSprites[spriteId].data[0] = i; + } +} + +static void MoveCeilingCrumbleSprite(struct Sprite* sprite) +{ + sprite->data[1] += 2; + sprite->pos2.y = sprite->data[1] / 2; + if(((sprite->pos1.y) + (sprite->pos2.y)) > sCeilingCrumblePositions[sprite->data[0]][2]) + { + DestroySprite(sprite); + IncrementCeilingCrumbleFinishedCount(); + } +} + +static void SetInvisibleMirageTowerMetatiles(void) +{ + u8 i; + for (i = 0; i < ARRAY_COUNT(sInvisibleMirageTowerMetatiles); i++) + MapGridSetMetatileIdAt(sInvisibleMirageTowerMetatiles[i].x + 7, sInvisibleMirageTowerMetatiles[i].y + 7, sInvisibleMirageTowerMetatiles[i].metatileId); + DrawWholeMapView(); +} + +void StartMirageTowerDisintegration(void) +{ + CreateTask(DoMirageTowerDisintegration, 9); +} + +void StartMirageTowerShake(void) +{ + CreateTask(InitMirageTowerShake, 9); +} + +void StartMirageTowerFossilFallAndSink(void) +{ + CreateTask(DoFossilFallAndSink, 9); +} + +static void SetBgShakeOffsets(void) +{ + SetGpuReg(REG_OFFSET_BG0HOFS, sBgShakeOffsets->bgHOFS); + SetGpuReg(REG_OFFSET_BG0VOFS, sBgShakeOffsets->bgVOFS); +} + +static void UpdateBgShake(u8 taskId) +{ + if (!gTasks[taskId].data[0]) + { + sBgShakeOffsets->bgHOFS = -sBgShakeOffsets->bgHOFS; + gTasks[taskId].data[0] = 2; + SetBgShakeOffsets(); + } + else + { + gTasks[taskId].data[0]--; + } +} + +static void InitMirageTowerShake(u8 taskId) +{ + u8 zero; + + switch (gTasks[taskId].data[0]) + { + case 0: + FreeAllWindowBuffers(); + SetBgAttribute(0, BG_ATTR_PRIORITY, 2); + gTasks[taskId].data[0]++; + break; + case 1: + sMirageTowerGfxBuffer = (u8 *)AllocZeroed(MIRAGE_TOWER_GFX_LENGTH); + sMirageTowerTilemapBuffer = (u8 *)AllocZeroed(BG_SCREEN_SIZE); + ChangeBgX(0, 0, 0); + ChangeBgY(0, 0, 0); + gTasks[taskId].data[0]++; + break; + case 2: + CpuSet(sBlankTile_Gfx, sMirageTowerGfxBuffer, MIRAGE_TOWER_GFX_LENGTH / 2); + LoadBgTiles(0, sMirageTowerGfxBuffer, MIRAGE_TOWER_GFX_LENGTH, 0); + gTasks[taskId].data[0]++; + break; + case 3: + SetBgTilemapBuffer(0, sMirageTowerTilemapBuffer); + CopyToBgTilemapBufferRect_ChangePalette(0, &sMirageTowerTilemap, 12, 29, 6, 12, 17); + CopyBgTilemapBufferToVram(0); + gTasks[taskId].data[0]++; + break; + case 4: + ShowBg(0); + gTasks[taskId].data[0]++; + break; + case 5: + SetInvisibleMirageTowerMetatiles(); + gTasks[taskId].data[0]++; + break; + case 6: + sBgShakeOffsets = Alloc(sizeof(*sBgShakeOffsets)); + zero = 0; + sBgShakeOffsets->bgHOFS = 2; + sBgShakeOffsets->bgVOFS = zero; + CreateTask(UpdateBgShake, 10); + DestroyTask(taskId); + EnableBothScriptContexts(); + break; + } +} + +#define OUTER_BUFFER_LENGTH 0x60 +#define INNER_BUFFER_LENGTH 0x30 +static void DoMirageTowerDisintegration(u8 taskId) +{ + u8 bgShakeTaskId, j; + u16 i; + u8 index; + + switch (gTasks[taskId].data[0]) + { + case 1: + sUnknown_0203CF10 = AllocZeroed(OUTER_BUFFER_LENGTH * sizeof(struct Struct203CF10)); + break; + case 3: + if (gTasks[taskId].data[3] <= (OUTER_BUFFER_LENGTH - 1)) + { + if (gTasks[taskId].data[1] > 1) + { + index = gTasks[taskId].data[3]; + sUnknown_0203CF10[index].buffer = Alloc(INNER_BUFFER_LENGTH); + for (i = 0; i <= (INNER_BUFFER_LENGTH - 1); i++) + sUnknown_0203CF10[index].buffer[i] = i; + for (i = 0; i <= (INNER_BUFFER_LENGTH - 1); i++) + { + u16 rand1, rand2, temp; + + rand1 = Random() % 0x30; + rand2 = Random() % 0x30; + SWAP(sUnknown_0203CF10[index].buffer[rand2], sUnknown_0203CF10[index].buffer[rand1], temp); + } + if (gTasks[taskId].data[3] <= (OUTER_BUFFER_LENGTH - 1)) + gTasks[taskId].data[3]++; + gTasks[taskId].data[1] = 0; + } + gTasks[taskId].data[1]++; + } + index = gTasks[taskId].data[3]; + for (i = (u8)(gTasks[taskId].data[2]); i < index; i++) + { + for (j = 0; j < 1; j++) + { + sub_81BF2B8(sMirageTowerGfxBuffer, + ((((OUTER_BUFFER_LENGTH - 1) - i) * INNER_BUFFER_LENGTH) + sUnknown_0203CF10[i].buffer[(sUnknown_0203CF10[i].currIndex)++]), + 0, INNER_BUFFER_LENGTH, 1); + } + if (sUnknown_0203CF10[i].currIndex > (INNER_BUFFER_LENGTH - 1)) + { + FREE_AND_SET_NULL(sUnknown_0203CF10[i].buffer); + gTasks[taskId].data[2]++; + if ((i % 2) == 1) + sBgShakeOffsets->bgVOFS--; + } + } + LoadBgTiles(0, sMirageTowerGfxBuffer, MIRAGE_TOWER_GFX_LENGTH, 0); + if (sUnknown_0203CF10[OUTER_BUFFER_LENGTH - 1].currIndex > (INNER_BUFFER_LENGTH - 1)) + break; + return; + case 4: + UnsetBgTilemapBuffer(0); + bgShakeTaskId = FindTaskIdByFunc(UpdateBgShake); + if (bgShakeTaskId != 0xFF) + DestroyTask(bgShakeTaskId); + sBgShakeOffsets->bgVOFS = sBgShakeOffsets->bgHOFS = 0; + SetBgShakeOffsets(); + break; + case 5: + FREE_AND_SET_NULL(sBgShakeOffsets); + FREE_AND_SET_NULL(sUnknown_0203CF10); + FREE_AND_SET_NULL(sMirageTowerGfxBuffer); + FREE_AND_SET_NULL(sMirageTowerTilemapBuffer); + break; + case 6: + SetGpuRegBits(REG_OFFSET_BG2CNT, BGCNT_PRIORITY(2)); + SetGpuRegBits(REG_OFFSET_BG0CNT, BGCNT_PRIORITY(0)); + SetBgAttribute(0, BG_ATTR_PRIORITY, 0); + InitStandardTextBoxWindows(); + break; + case 7: + ShowBg(0); + break; + case 8: + DestroyTask(taskId); + EnableBothScriptContexts(); + break; + } + gTasks[taskId].data[0]++; +} + +static void DoFossilFallAndSink(u8 taskId) +{ + u16 i; + u8 *buffer; + + switch (gTasks[taskId].data[0]) + { + case 1: + sUnknown_0203CF0C = AllocZeroed(sizeof(*sUnknown_0203CF0C)); + sUnknown_0203CF0C->frameImageTiles = AllocZeroed(ROOT_FOSSIL_GFX_LENGTH); + sUnknown_0203CF0C->frameImage = AllocZeroed(sizeof(*sUnknown_0203CF0C->frameImage)); + sUnknown_0203CF0C->unkC = AllocZeroed(ROOT_FOSSIL_GFX_RANDOMIZER_LENGTH * sizeof(u16)); + sUnknown_0203CF0C->unk10 = 0; + break; + case 2: + buffer = sUnknown_0203CF0C->frameImageTiles; + for (i = 0; i < ROOT_FOSSIL_GFX_LENGTH; i++, buffer++) + *buffer = sRootFossil_Gfx[i]; + break; + case 3: + sUnknown_0203CF0C->frameImage->data = sUnknown_0203CF0C->frameImageTiles; + sUnknown_0203CF0C->frameImage->size = ROOT_FOSSIL_GFX_LENGTH; + break; + case 4: + { + struct SpriteTemplate fossilTemplate; + + fossilTemplate = gUnknown_08617E00; + fossilTemplate.images = (struct SpriteFrameImage *)(sUnknown_0203CF0C->frameImage); + sUnknown_0203CF0C->spriteId = CreateSprite(&fossilTemplate, 128, -16, 1); + gSprites[sUnknown_0203CF0C->spriteId].centerToCornerVecX = 0; + gSprites[sUnknown_0203CF0C->spriteId].data[0] = gSprites[sUnknown_0203CF0C->spriteId].pos1.x; + gSprites[sUnknown_0203CF0C->spriteId].data[1] = 1; + } + case 5: + for (i = 0; i < ROOT_FOSSIL_GFX_RANDOMIZER_LENGTH; i++) + sUnknown_0203CF0C->unkC[i] = i; + break; + case 6: + for (i = 0; i < (ROOT_FOSSIL_GFX_RANDOMIZER_LENGTH * sizeof(u16)); i++) + { + u16 rand1, rand2, temp; + + rand1 = Random() % 0x100; + rand2 = Random() % 0x100; + SWAP(sUnknown_0203CF0C->unkC[rand2], sUnknown_0203CF0C->unkC[rand1], temp); + } + gSprites[sUnknown_0203CF0C->spriteId].callback = sub_81BF248; + break; + case 7: + if (gSprites[sUnknown_0203CF0C->spriteId].callback != SpriteCallbackDummy) + return; + DestroySprite(&gSprites[sUnknown_0203CF0C->spriteId]); + FREE_AND_SET_NULL(sUnknown_0203CF0C->unkC);; + FREE_AND_SET_NULL(sUnknown_0203CF0C->frameImage); + FREE_AND_SET_NULL(sUnknown_0203CF0C->frameImageTiles); + FREE_AND_SET_NULL(sUnknown_0203CF0C); + break; + case 8: + EnableBothScriptContexts(); + break; + } + + gTasks[taskId].data[0]++; +} + +static void sub_81BF248(struct Sprite *sprite) +{ + if (sUnknown_0203CF0C->unk10 >= (ROOT_FOSSIL_GFX_RANDOMIZER_LENGTH)) + { + sprite->callback = SpriteCallbackDummy; + } + else if (sprite->pos1.y >= 96) + { + u8 i; + for (i = 0; i < 2; i++) + sub_81BF2B8(sUnknown_0203CF0C->frameImageTiles, sUnknown_0203CF0C->unkC[sUnknown_0203CF0C->unk10++], 0, 16, 0); + + StartSpriteAnim(sprite, 0); + } + else + { + sprite->pos1.y++; + } +} + +#ifdef NONMATCHING +static void sub_81BF2B8(u8* a, u16 b, u8 c, u8 d, u8 e) +{ + u8 r5, r4, r0, r2; + u16 var; + + r4 = r5 = b / d; + gUnknown_030012A8[0] = r4; + + r0 = r2 = b % d; + gUnknown_030012A8[1] = r2; + + r4 &= 7; + r2 &= 7; + gUnknown_030012A8[2] = r4; + gUnknown_030012A8[3] = r2; + + r0 /= 8; + r5 /= 8; + gUnknown_030012A8[4] = r0; + gUnknown_030012A8[5] = r5; + + var = ((d / 8) * (r5 * 64)) + (r0 * 64); + gUnknown_030012A8[6] = var; + + var += (r4 * 8) + r2; + gUnknown_030012A8[7] = var; + + // This part is non-matching. 99% sure it IS functionally equivalent, though. + b = (b & 1) ^ 1; + c = (c << ((b) << 2)) | (15 << ((b ^ 1) << 2)); + + a[(var / 2) + (e * 32)] &= c; +} + +#else +NAKED +static void sub_81BF2B8(u8* a, u16 b, u8 c, u8 d, u8 e) +{ + asm_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, 0x8\n\ + str r0, [sp]\n\ + mov r10, r1\n\ + adds r6, r2, 0\n\ + mov r8, r3\n\ + ldr r0, [sp, 0x28]\n\ + mov r9, r0\n\ + lsls r1, 16\n\ + lsrs r1, 16\n\ + mov r10, r1\n\ + lsls r6, 24\n\ + lsrs r6, 24\n\ + mov r0, r8\n\ + lsls r0, 24\n\ + mov r8, r0\n\ + lsrs r7, r0, 24\n\ + mov r1, r9\n\ + lsls r1, 24\n\ + lsrs r1, 24\n\ + mov r9, r1\n\ + mov r0, r10\n\ + adds r1, r7, 0\n\ + bl __divsi3\n\ + adds r5, r0, 0\n\ + lsls r5, 24\n\ + lsrs r4, r5, 24\n\ + ldr r3, =gUnknown_030012A8\n\ + strh r4, [r3]\n\ + mov r0, r10\n\ + adds r1, r7, 0\n\ + str r3, [sp, 0x4]\n\ + bl __modsi3\n\ + lsls r0, 24\n\ + lsrs r2, r0, 24\n\ + ldr r3, [sp, 0x4]\n\ + strh r2, [r3, 0x2]\n\ + movs r1, 0x7\n\ + ands r4, r1\n\ + ands r2, r1\n\ + strh r4, [r3, 0x4]\n\ + strh r2, [r3, 0x6]\n\ + lsrs r0, 27\n\ + lsrs r5, 27\n\ + strh r0, [r3, 0x8]\n\ + strh r5, [r3, 0xA]\n\ + mov r1, r8\n\ + lsrs r1, 27\n\ + lsls r1, 6\n\ + mov r8, r1\n\ + mov r1, r8\n\ + muls r1, r5\n\ + lsls r0, 6\n\ + adds r1, r0\n\ + lsls r1, 16\n\ + lsrs r1, 16\n\ + strh r1, [r3, 0xC]\n\ + lsls r4, 3\n\ + adds r4, r2\n\ + adds r1, r4\n\ + lsls r4, r1, 16\n\ + lsrs r4, 17\n\ + strh r1, [r3, 0xE]\n\ + movs r1, 0x1\n\ + mov r0, r10\n\ + ands r1, r0\n\ + movs r2, 0x1\n\ + eors r1, r2\n\ + lsls r0, r1, 2\n\ + lsls r6, r0\n\ + eors r1, r2\n\ + lsls r1, 2\n\ + movs r0, 0xF\n\ + lsls r0, r1\n\ + orrs r6, r0\n\ + lsls r6, 24\n\ + lsrs r6, 24\n\ + mov r1, r9\n\ + lsls r1, 5\n\ + mov r9, r1\n\ + add r9, r4\n\ + ldr r1, [sp]\n\ + add r1, r9\n\ + ldrb r0, [r1]\n\ + ands r6, r0\n\ + strb r6, [r1]\n\ + add sp, 0x8\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .pool\n\ + "); +} +#endif // NONMATCHING |