Document mirage_tower.c. (Combine fldeff_groundshake.c and fossil_specials.c)

This commit is contained in:
Marcus Huderle
2018-12-25 11:02:41 -06:00
parent c7971ecb20
commit dcbc8db6a3
31 changed files with 1055 additions and 1301 deletions

View File

@@ -40,6 +40,7 @@
#include "fldeff.h"
#include "fldeff_misc.h"
#include "field_control_avatar.h"
#include "mirage_tower.h"
#include "constants/map_types.h"
#include "constants/battle_frontier.h"
@@ -341,7 +342,7 @@ static void Task_BattleStart(u8 taskId)
if (!FldEffPoison_IsActive()) // is poison not active?
{
BattleTransition_StartOnField(tTransition);
sub_81BE72C();
ClearMirageTowerPulseBlendEffect();
tState++; // go to case 1.
}
break;

View File

@@ -12,6 +12,7 @@
#include "fldeff.h"
#include "gpu_regs.h"
#include "main.h"
#include "mirage_tower.h"
#include "menu.h"
#include "metatile_behavior.h"
#include "overworld.h"
@@ -2325,7 +2326,7 @@ static void TeleportFieldEffectTask4(struct Task *task)
{
if (task->data[5] == FALSE)
{
sub_81BE72C();
ClearMirageTowerPulseBlendEffect();
task->data[5] = TRUE;
}

View File

@@ -17,6 +17,7 @@
#include "load_save.h"
#include "main.h"
#include "menu.h"
#include "mirage_tower.h"
#include "event_obj_lock.h"
#include "metatile_behavior.h"
#include "palette.h"
@@ -34,7 +35,6 @@
extern bool32 sub_81D6534(void);
extern bool8 walkrun_is_standing_still(void);
extern void ScriptUnfreezeEventObjects(void);
extern void sub_81BE72C(void);
extern void sub_80FB768(void);
extern void sub_808D194(void);
extern void sub_808D1C8(void);
@@ -673,7 +673,7 @@ static void sub_80AFA0C(u8 taskId)
{
if (task->data[1] == 0)
{
sub_81BE72C();
ClearMirageTowerPulseBlendEffect();
task->data[1] = 1;
}
if (BGMusicStopped())

View File

@@ -5,6 +5,7 @@
#include "fldeff_misc.h"
#include "frontier_util.h"
#include "menu.h"
#include "mirage_tower.h"
#include "overworld.h"
#include "palette.h"
#include "pokenav.h"
@@ -762,7 +763,7 @@ bool8 CameraMove(int x, int y)
else
{
save_serialize_map();
sub_81BE72C();
ClearMirageTowerPulseBlendEffect();
old_x = gSaveBlock1Ptr->pos.x;
old_y = gSaveBlock1Ptr->pos.y;
connection = sub_8088950(direction, gSaveBlock1Ptr->pos.x, gSaveBlock1Ptr->pos.y);

View File

@@ -1,322 +0,0 @@
#include "global.h"
#include "event_data.h"
#include "event_object_movement.h"
#include "field_camera.h"
#include "fldeff.h"
#include "alloc.h"
#include "random.h"
#include "roulette_util.h"
#include "script.h"
#include "sound.h"
#include "sprite.h"
#include "task.h"
#include "constants/flags.h"
#include "constants/maps.h"
#include "constants/songs.h"
// structures
struct Struct203CF18 {
u8 taskId;
struct InnerStruct203CF18 unk4;
}; //size = 0xC8
// extern data
extern const struct SpriteSheet gUnknown_08617D94[];
extern const s16 gUnknown_08617D64[][3];
// static functions
static void sub_81BE808(u8 taskId);
static void sub_81BE900(u8 taskId);
static void sub_81BE968(void);
static void sub_81BE9C0(u8 taskId);
static void sub_81BEA00(u8 taskId);
static void sub_81BEA20(void);
static void sub_81BEAD8(struct Sprite* sprite);
// rodata
const struct InnerStruct203CF18_3 gUnknown_08617E18 = {
.unk0 = 0x433b,
.unk2 = 0x61,
.unk4 = 0x0F,
.unk5 = 0x05,
.unk6 = 0xFF,
.unk7_0 = 0xB,
.unk7_4 = 0x1,
.unk7_6 = 0,
.unk7_7 = 1,
};
static const union AnimCmd gSpriteAnim_8617E20[] =
{
ANIMCMD_FRAME(0, 12),
ANIMCMD_JUMP(0),
};
static const union AnimCmd *const gSpriteAnimTable_8617E28[] =
{
gSpriteAnim_8617E20,
};
static const struct OamData gUnknown_08617E2C =
{
.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 struct SpriteTemplate gUnknown_08617E34 = {
.tileTag = 0x0FA0,
.paletteTag = 0xFFFF,
.oam = &gUnknown_08617E2C,
.anims = gSpriteAnimTable_8617E28,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = sub_81BEAD8
};
static const union AnimCmd gSpriteAnim_8617E4C[] =
{
ANIMCMD_FRAME(0, 12),
ANIMCMD_JUMP(0),
};
static const union AnimCmd *const gSpriteAnim_8617E54[] =
{
gSpriteAnim_8617E4C,
};
static const struct OamData gSpriteAnim_8617E58 =
{
.y = 0,
.affineMode = 0,
.objMode = 0,
.mosaic = 0,
.bpp = 0,
.shape = 0,
.x = 0,
.matrixNum = 0,
.size = 1,
.tileNum = 0,
.priority = 0,
.paletteNum = 0,
.affineParam = 0,
};
static const struct SpriteTemplate gUnknown_08617E60 = {
.tileTag = 0x0FA0,
.paletteTag = 0xFFFF,
.oam = &gSpriteAnim_8617E58,
.anims = gSpriteAnim_8617E54,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = sub_81BEAD8
};
// ewram
EWRAM_DATA struct Struct203CF18 *gUnknown_0203CF18 = NULL;
// text
bool8 sub_81BE66C(void)
{
if (!(gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(ROUTE111) && gSaveBlock1Ptr->location.mapNum == MAP_NUM(ROUTE111)))
return FALSE;
else
return FlagGet(FLAG_0x14E);
}
static void sub_81BE698(u8 taskId)
{
sub_8151E50(&(gUnknown_0203CF18->unk4));
}
void sub_81BE6AC(void)
{
gUnknown_0203CF18 = NULL;
}
void sub_81BE6B8(void)
{
if (gUnknown_0203CF18 != NULL)
{
gUnknown_0203CF18 = NULL;
return;
}
if (gSaveBlock1Ptr->location.mapGroup != MAP_GROUP(ROUTE111) || gSaveBlock1Ptr->location.mapNum != MAP_NUM(ROUTE111) || !FlagGet(FLAG_0x14E))
return;
gUnknown_0203CF18 = (struct Struct203CF18 *)AllocZeroed(sizeof(struct Struct203CF18));
sub_8151B3C(&(gUnknown_0203CF18->unk4));
sub_8151B68(&(gUnknown_0203CF18->unk4), &gUnknown_08617E18);
sub_8151CA8(&(gUnknown_0203CF18->unk4), 1, 1);
gUnknown_0203CF18->taskId = CreateTask(sub_81BE698, 0xFF);
}
void sub_81BE72C(void)
{
if (gSaveBlock1Ptr->location.mapGroup != MAP_GROUP(ROUTE111) || gSaveBlock1Ptr->location.mapNum != MAP_NUM(ROUTE111)
|| !FlagGet(FLAG_0x14E) || gUnknown_0203CF18 == NULL)
return;
if( FuncIsActiveTask(sub_81BE698))
DestroyTask(gUnknown_0203CF18->taskId);
sub_8151D28(&(gUnknown_0203CF18->unk4), 1, 1);
sub_8151C50(&(gUnknown_0203CF18->unk4), 1, 1);
Free(gUnknown_0203CF18);
gUnknown_0203CF18 = NULL;
}
void sub_81BE79C(void)
{
u16 rand;
bool8 chance;
if (VarGet(VAR_0x40CB) != 0)
{
FlagClear(FLAG_0x14E);
return;
}
rand = Random();
chance = rand & 1;
if (FlagGet(FLAG_0x09D) == TRUE)
chance = TRUE;
if (chance)
{
FlagSet(FLAG_0x14E);
sub_81BE6B8();
return;
}
FlagClear(FLAG_0x14E);
}
void sub_81BE7F4(void)
{
CreateTask(sub_81BE808, 0x8);
}
static void sub_81BE808(u8 taskId)
{
u8 eventObjectIdBuffer;
struct EventObject *fieldEventObject;
struct EventObject *playerAvatarEventObject;
TryGetEventObjectIdByLocalIdAndMap(0x2D, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &eventObjectIdBuffer);
fieldEventObject = &(gEventObjects[eventObjectIdBuffer]);
gSprites[fieldEventObject->spriteId].pos2.y += 4;
playerAvatarEventObject = &(gEventObjects[gPlayerAvatar.eventObjectId]);
if((gSprites[fieldEventObject->spriteId].pos1.y + gSprites[fieldEventObject->spriteId].pos2.y) >=
(gSprites[playerAvatarEventObject->spriteId].pos1.y + gSprites[playerAvatarEventObject->spriteId].pos2.y))
{
DestroyTask(taskId);
EnableBothScriptContexts();
}
}
static void sp136_strengh_sound(u8 a, u8 b, u8 c, u8 d)
{
u8 taskId;
taskId = CreateTask(sub_81BE900, 0x9);
gTasks[taskId].data[0] = b;
gTasks[taskId].data[1] = 0;
gTasks[taskId].data[2] = c;
gTasks[taskId].data[3] = d;
gTasks[taskId].data[4] = a;
SetCameraPanningCallback(NULL);
PlaySE(SE_W070);
}
static void sub_81BE900(u8 taskId)
{
s16 *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])
{
sub_81BE968();
DestroyTask(taskId);
InstallCameraPanAheadCallback();
}
}
}
static void sub_81BE968(void)
{
u8 taskId = FindTaskIdByFunc(sub_81BE9C0);
if (taskId != 0xFF)
gTasks[taskId].data[0]++;
}
void sub_81BE994(void)
{
LoadSpriteSheets(gUnknown_08617D94);
sub_81BEA20();
CreateTask(sub_81BE9C0, 0x8);
sp136_strengh_sound(2, 1, 16, 3);
}
static void sub_81BE9C0(u8 taskId)
{
u16 *data = gTasks[taskId].data;
if (++data[1] == 1000 || data[0] == 17)
gTasks[taskId].func = sub_81BEA00;
}
static void sub_81BEA00(u8 taskId)
{
FreeSpriteTilesByTag(4000);
DestroyTask(taskId);
EnableBothScriptContexts();
}
static void sub_81BEA20(void)
{
u8 i;
u8 spriteId;
for (i = 0; i < 8; i++)
{
spriteId = CreateSprite(&gUnknown_08617E60, gUnknown_08617D64[i][0] + 120, gUnknown_08617D64[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(&gUnknown_08617E34, gUnknown_08617D64[i][0] + 115, gUnknown_08617D64[i][1] - 3, 8);
gSprites[spriteId].oam.priority = 0;
gSprites[spriteId].oam.paletteNum = 0;
gSprites[spriteId].data[0] = i;
}
}
static void sub_81BEAD8(struct Sprite* sprite)
{
sprite->data[1] += 2;
sprite->pos2.y = (sprite->data[1] / 2);
if (((sprite->pos1.y) + (sprite->pos2.y)) > gUnknown_08617D64[sprite->data[0]][2])
{
DestroySprite(sprite);
sub_81BE968();
}
}

View File

@@ -6,6 +6,7 @@
#include "field_screen_effect.h"
#include "field_weather.h"
#include "fldeff.h"
#include "mirage_tower.h"
#include "palette.h"
#include "party_menu.h"
#include "script.h"
@@ -63,7 +64,7 @@ static void TrySweetScentEncounter(u8 taskId)
{
if (!gPaletteFade.active)
{
sub_81BE72C();
ClearMirageTowerPulseBlendEffect();
BlendPalettes(0x00000040, 8, RGB_RED);
if (gTasks[taskId].data[0] == 64)
{
@@ -76,7 +77,7 @@ static void TrySweetScentEncounter(u8 taskId)
{
gTasks[taskId].func = FailSweetScentEncounter;
BeginNormalPaletteFade(~(1 << (gSprites[GetPlayerAvatarObjectId()].oam.paletteNum + 16)), 4, 8, 0, RGB_RED);
sub_81BE6B8();
TryStartMirageTowerPulseBlendEffect();
}
}
else

View File

@@ -1,561 +0,0 @@
#include "global.h"
#include "constants/flags.h"
#include "constants/songs.h"
#include "bg.h"
#include "event_data.h"
#include "field_camera.h"
#include "event_object_movement.h"
#include "fieldmap.h"
#include "global.fieldmap.h"
#include "gpu_regs.h"
#include "alloc.h"
#include "menu.h"
#include "random.h"
#include "script.h"
#include "sound.h"
#include "sprite.h"
#include "task.h"
#include "window.h"
#define MIRAGE_TOWER_GFX_LENGTH (32 + sizeof(gMirageTower_Gfx))
#define MIRAGE_TOWER_PALETTE_LENGTH 0x800
#define ROOT_FOSSIL_GFX_LENGTH sizeof(gRootFossil_Gfx)
#define ROOT_FOSSIL_GFX_RANDOMIZER_LENGTH 0x100
struct Struct8617DA4
{
u8 x;
u8 y;
u16 tileId;
};
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;
};
// static functions
static void sub_81BED50(u8 taskId);
static void sub_81BEBF4(u8 taskId);
static void sub_81BF028(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 gUnknown_08617274[32] = {0};
static const u8 gMirageTower_Gfx[] = INCBIN_U8("graphics/misc/mirage_tower.4bpp");
static const u16 gUnknown_08617B94[] = INCBIN_U16("graphics/misc/mirage_tower.bin");
static const u16 gRootFossil_Pal[] = INCBIN_U16("graphics/misc/fossil.gbapal");
static const u8 gRootFossil_Gfx[] = INCBIN_U8("graphics/misc/fossil.4bpp");
static const u8 gMirageTowerCrumbles_Gfx[] = INCBIN_U8("graphics/misc/mirage_tower_crumbles.4bpp");
static const u16 gMirageTowerCrumbles_Palette[] = INCBIN_U16("graphics/misc/mirage_tower_crumbles.gbapal");
const s16 gUnknown_08617D64[][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 gUnknown_08617D94[] =
{
{gMirageTowerCrumbles_Gfx, 0x0080, 0x0fa0},
{NULL}
};
static const struct Struct8617DA4 gUnknown_08617DA4[] =
{
{0x12, 0x35, 0x251},
{0x13, 0x35, 0x251},
{0x14, 0x35, 0x251},
{0x12, 0x36, 0x251},
{0x13, 0x36, 0x251},
{0x14, 0x36, 0x251},
{0x12, 0x37, 0x251},
{0x13, 0x37, 0x251},
{0x14, 0x37, 0x251},
{0x12, 0x38, 0x251},
{0x13, 0x38, 0x251},
{0x14, 0x38, 0x251},
{0x12, 0x39, 0x259},
{0x13, 0x39, 0x259},
{0x14, 0x39, 0x259},
{0x12, 0x3A, 0x121},
{0x13, 0x3A, 0x121},
{0x14, 0x3A, 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
};
// EWRAM
EWRAM_DATA static u8* sUnknown_0203CF04 = NULL;
EWRAM_DATA static u8* sUnknown_0203CF08 = NULL;
EWRAM_DATA static struct Struct203CF0C *sUnknown_0203CF0C = NULL;
EWRAM_DATA static struct Struct203CF10 *sUnknown_0203CF10 = NULL;
EWRAM_DATA static u16 *sUnknown_0203CF14 = NULL;
// IWRAM bss
IWRAM_DATA static u16 gUnknown_030012A8[8];
// text
void sub_81BEB24(void)
{
u8 i;
for (i = 0; i < (sizeof(gUnknown_08617DA4)/sizeof(gUnknown_08617DA4[0])); i++)
MapGridSetMetatileIdAt(gUnknown_08617DA4[i].x + 7, gUnknown_08617DA4[i].y + 7, gUnknown_08617DA4[i].tileId);
DrawWholeMapView();
}
void sub_81BEB54(void)
{
CreateTask(sub_81BED50, 9);
}
void sub_81BEB68(void)
{
CreateTask(sub_81BEBF4, 9);
}
void sub_81BEB7C(void)
{
CreateTask(sub_81BF028, 9);
}
void sub_81BEB90(void)
{
SetGpuReg(REG_OFFSET_BG0HOFS, sUnknown_0203CF14[0]);
SetGpuReg(REG_OFFSET_BG0VOFS, sUnknown_0203CF14[1]);
}
void sub_81BEBB4(u8 taskId)
{
if (!(gTasks[taskId].data[0]))
{
sUnknown_0203CF14[0] = -sUnknown_0203CF14[0];
gTasks[taskId].data[0] = 2;
sub_81BEB90();
}
else
{
gTasks[taskId].data[0]--;
}
}
static void sub_81BEBF4(u8 taskId)
{
u8 zero;
switch (gTasks[taskId].data[0])
{
case 0:
FreeAllWindowBuffers();
SetBgAttribute(0, BG_CTRL_ATTR_MOSAIC, 2);
gTasks[taskId].data[0]++;
break;
case 1:
sUnknown_0203CF04 = (u8 *)AllocZeroed(MIRAGE_TOWER_GFX_LENGTH);
sUnknown_0203CF08 = (u8 *)AllocZeroed(MIRAGE_TOWER_PALETTE_LENGTH);
ChangeBgX(0, 0, 0);
ChangeBgY(0, 0, 0);
gTasks[taskId].data[0]++;
break;
case 2:
CpuSet(gUnknown_08617274, sUnknown_0203CF04, MIRAGE_TOWER_GFX_LENGTH / 2);
LoadBgTiles(0, sUnknown_0203CF04, MIRAGE_TOWER_GFX_LENGTH, 0);
gTasks[taskId].data[0]++;
break;
case 3:
SetBgTilemapBuffer(0, sUnknown_0203CF08);
CopyToBgTilemapBufferRect_ChangePalette(0, &gUnknown_08617B94, 12, 29, 6, 12, 17);
CopyBgTilemapBufferToVram(0);
gTasks[taskId].data[0]++;
break;
case 4:
ShowBg(0);
gTasks[taskId].data[0]++;
break;
case 5:
sub_81BEB24();
gTasks[taskId].data[0]++;
break;
case 6:
sUnknown_0203CF14 = Alloc(4);
zero = 0;
sUnknown_0203CF14[0] = 2;
sUnknown_0203CF14[1] = zero;
CreateTask(sub_81BEBB4, 0xA);
DestroyTask(taskId);
EnableBothScriptContexts();
break;
}
}
#define OUTER_BUFFER_LENGTH 0x60
#define INNER_BUFFER_LENGTH 0x30
static void sub_81BED50(u8 taskId)
{
u8 anotherTaskId, 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(sUnknown_0203CF04,
((((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)
sUnknown_0203CF14[1]--;
}
}
LoadBgTiles(0, sUnknown_0203CF04, MIRAGE_TOWER_GFX_LENGTH, 0);
if (sUnknown_0203CF10[OUTER_BUFFER_LENGTH - 1].currIndex > (INNER_BUFFER_LENGTH - 1))
break;
return;
case 4:
UnsetBgTilemapBuffer(0);
anotherTaskId = FindTaskIdByFunc(sub_81BEBB4);
if (anotherTaskId != 0xFF)
DestroyTask(anotherTaskId);
sUnknown_0203CF14[1] = sUnknown_0203CF14[0] = 0;
sub_81BEB90();
break;
case 5:
FREE_AND_SET_NULL(sUnknown_0203CF14);
FREE_AND_SET_NULL(sUnknown_0203CF10);
FREE_AND_SET_NULL(sUnknown_0203CF04);
FREE_AND_SET_NULL(sUnknown_0203CF08);
break;
case 6:
SetGpuRegBits(REG_OFFSET_BG2CNT, 0x2);
SetGpuRegBits(REG_OFFSET_BG0CNT, 0x0);
SetBgAttribute(0, BG_CTRL_ATTR_MOSAIC, 0);
sub_81971D0();
break;
case 7:
ShowBg(0);
break;
case 8:
DestroyTask(taskId);
EnableBothScriptContexts();
break;
}
gTasks[taskId].data[0]++;
}
static void sub_81BF028(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 = gRootFossil_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 >= 0x60)
{
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

868
src/mirage_tower.c Normal file
View File

@@ -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_CTRL_ATTR_MOSAIC, 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_CTRL_ATTR_MOSAIC, 0);
sub_81971D0();
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

View File

@@ -31,6 +31,7 @@
#include "map_name_popup.h"
#include "menu.h"
#include "metatile_behavior.h"
#include "mirage_tower.h"
#include "money.h"
#include "new_game.h"
#include "palette.h"
@@ -112,7 +113,6 @@ extern void sub_81AA1D8(void);
extern void c2_change_map(void);
extern void sub_81D5DF8(void);
extern void sub_80EB218(void);
extern void sub_81BE72C(void);
extern void sub_80AF3C8(void);
extern void sub_81971F4(void);
extern void sub_808B578(void);
@@ -134,7 +134,6 @@ extern void sub_81AA2F8(void);
extern void sub_8195E10(void);
extern void sub_80EDB44(void);
extern void sub_81D64C0(void);
extern void sub_81BE6AC(void);
extern void sub_8098128(void);
extern void copy_map_tileset1_to_vram(const struct MapLayout *);
extern void copy_map_tileset2_to_vram(const struct MapLayout *);
@@ -146,7 +145,6 @@ extern bool8 warp0_in_pokecenter(void);
extern void ResetAllPicSprites(void);
extern void FieldEffectActiveListClear(void);
extern void SetUpFieldTasks(void);
extern void sub_81BE6B8(void);
extern void ShowStartMenu(void);
extern void sub_80AEE84(void);
extern void mapldr_default(void);
@@ -1464,7 +1462,7 @@ static void overworld_bg_setup(void)
void overworld_free_bg_tilemaps(void)
{
sub_81BE72C();
ClearMirageTowerPulseBlendEffect();
sub_81971F4();
if (gBGTilemapBuffers3 != NULL)
FREE_AND_SET_NULL(gBGTilemapBuffers3);
@@ -2121,7 +2119,7 @@ static void do_load_map_stuff_loop(u8 *state)
static void sub_80867C8(void)
{
sub_81BE6AC();
ClearMirageTowerPulseBlend();
MoveSaveBlocks_ResetHeap();
}
@@ -2199,7 +2197,7 @@ static void sub_8086988(u32 a1)
if (!a1)
SetUpFieldTasks();
mapheader_run_script_with_tag_x5();
sub_81BE6B8();
TryStartMirageTowerPulseBlendEffect();
}
static void sub_80869DC(void)

View File

@@ -206,463 +206,227 @@ void sub_8151A9C(struct UnkStruct0 *r0, u16 r1)
}
}
void sub_8151B3C(struct InnerStruct203CF18 *arg0)
void InitPulseBlend(struct PulseBlend *pulseBlend)
{
u8 i = 0;
arg0->unk0 = 0;
memset(&arg0->unk4, 0, sizeof(arg0->unk4));
pulseBlend->usedPulseBlendPalettes = 0;
memset(&pulseBlend->pulseBlendPalettes, 0, sizeof(pulseBlend->pulseBlendPalettes));
for (; i < 16; i++)
{
arg0->unk4[i].unk0 = i;
}
pulseBlend->pulseBlendPalettes[i].paletteSelector = i;
}
int sub_8151B68(struct InnerStruct203CF18 *arg0, const struct InnerStruct203CF18_3 *arg1)
int InitPulseBlendPaletteSettings(struct PulseBlend *pulseBlend, const struct PulseBlendSettings *settings)
{
u8 i = 0;
struct InnerStruct203CF18_2 *r4 = NULL;
struct PulseBlendPalette *pulseBlendPalette = NULL;
if (!arg0->unk4[0].unk1_7)
if (!pulseBlend->pulseBlendPalettes[0].inUse)
{
r4 = &arg0->unk4[0];
pulseBlendPalette = &pulseBlend->pulseBlendPalettes[0];
}
else
{
while (++i < 16)
{
if (!arg0->unk4[i].unk1_7)
if (!pulseBlend->pulseBlendPalettes[i].inUse)
{
r4 = &arg0->unk4[i];
pulseBlendPalette = &pulseBlend->pulseBlendPalettes[i];
break;
}
}
}
if (r4 == 0)
if (pulseBlendPalette == NULL)
return 0xFF;
r4->unk1_0 = 0;
r4->unk1_4 = 0;
r4->unk1_6 = 1;
r4->unk1_7 = 1;
r4->unk2 = 0;
r4->unk3 = 0;
memcpy(&r4->unk4, arg1, sizeof(*arg1));
pulseBlendPalette->blendCoeff = 0;
pulseBlendPalette->fadeDirection = 0;
pulseBlendPalette->available = 1;
pulseBlendPalette->inUse = 1;
pulseBlendPalette->delayCounter = 0;
pulseBlendPalette->fadeCycleCounter = 0;
memcpy(&pulseBlendPalette->pulseBlendSettings, settings, sizeof(*settings));
return i;
}
void sub_8151BD4(struct InnerStruct203CF18_2 *arg0)
static void ClearPulseBlendPalettesSettings(struct PulseBlendPalette *pulseBlendPalette)
{
u16 i;
if (!arg0->unk1_6 && arg0->unk4.unk7_6)
if (!pulseBlendPalette->available && pulseBlendPalette->pulseBlendSettings.restorePaletteOnUnload)
{
for (i = arg0->unk4.unk2; i < arg0->unk4.unk2 + arg0->unk4.unk4; i++)
for (i = pulseBlendPalette->pulseBlendSettings.paletteOffset; i < pulseBlendPalette->pulseBlendSettings.paletteOffset + pulseBlendPalette->pulseBlendSettings.numColors; i++)
gPlttBufferFaded[i] = gPlttBufferUnfaded[i];
}
memset(&arg0->unk4, 0, sizeof(arg0->unk4));
arg0->unk1_0 = 0;
arg0->unk1_4 = 0;
arg0->unk1_5 = 0;
arg0->unk1_6 = 1;
arg0->unk1_7 = 0;
arg0->unk3 = 0;
arg0->unk2 = 0;
memset(&pulseBlendPalette->pulseBlendSettings, 0, sizeof(pulseBlendPalette->pulseBlendSettings));
pulseBlendPalette->blendCoeff = 0;
pulseBlendPalette->fadeDirection = 0;
pulseBlendPalette->unk1_5 = 0;
pulseBlendPalette->available = 1;
pulseBlendPalette->inUse = 0;
pulseBlendPalette->fadeCycleCounter = 0;
pulseBlendPalette->delayCounter = 0;
}
void sub_8151C50(struct InnerStruct203CF18 *arg0, u16 arg1, u8 arg2)
void UnloadUsedPulseBlendPalettes(struct PulseBlend *pulseBlend, u16 pulseBlendPaletteSelector, u8 multiSelection)
{
u16 i = 0;
if (!arg2)
if (!multiSelection)
{
sub_8151BD4(&arg0->unk4[arg1 & 0xF]);
ClearPulseBlendPalettesSettings(&pulseBlend->pulseBlendPalettes[pulseBlendPaletteSelector & 0xF]);
}
else
{
for (i = 0; i < 16; i++)
{
if ((arg1 & 1) && arg0->unk4[i].unk1_7)
sub_8151BD4(&arg0->unk4[i]);
if ((pulseBlendPaletteSelector & 1) && pulseBlend->pulseBlendPalettes[i].inUse)
ClearPulseBlendPalettesSettings(&pulseBlend->pulseBlendPalettes[i]);
arg1 >>= 1;
pulseBlendPaletteSelector >>= 1;
}
}
}
// there seems to be a temp var involved inside the first if block
void sub_8151CA8(struct InnerStruct203CF18 *arg0, u16 arg1, u8 arg2)
void MarkUsedPulseBlendPalettes(struct PulseBlend *pulseBlend, u16 pulseBlendPaletteSelector, u8 multiSelection)
{
u8 i = 0;
if (!arg2)
if (!multiSelection)
{
i = arg1 & 0xF;
arg0->unk4[i].unk1_6 = 0;
arg0->unk0 |= 1 << i;
i = pulseBlendPaletteSelector & 0xF;
pulseBlend->pulseBlendPalettes[i].available = 0;
pulseBlend->usedPulseBlendPalettes |= 1 << i;
}
else
{
for (i = 0; i < 16; i++)
{
if (!(arg1 & 1) || !arg0->unk4[i].unk1_7 || !arg0->unk4[i].unk1_6)
if (!(pulseBlendPaletteSelector & 1) || !pulseBlend->pulseBlendPalettes[i].inUse || !pulseBlend->pulseBlendPalettes[i].available)
{
arg1 <<= 1;
pulseBlendPaletteSelector <<= 1;
}
else
{
arg0->unk4[i].unk1_6 = 0;
arg0->unk0 |= 1 << i;
pulseBlend->pulseBlendPalettes[i].available = 0;
pulseBlend->usedPulseBlendPalettes |= 1 << i;
}
}
}
}
void sub_8151D28(struct InnerStruct203CF18 *arg0, u16 arg1, u8 arg2)
void UnmarkUsedPulseBlendPalettes(struct PulseBlend *pulseBlend, u16 pulseBlendPaletteSelector, u8 multiSelection)
{
u16 i;
struct InnerStruct203CF18_2 *var0;
struct PulseBlendPalette *pulseBlendPalette;
u8 j = 0;
if (!arg2)
if (!multiSelection)
{
var0 = &arg0->unk4[arg1 & 0xF];
if (!var0->unk1_6 && var0->unk1_7)
pulseBlendPalette = &pulseBlend->pulseBlendPalettes[pulseBlendPaletteSelector & 0xF];
if (!pulseBlendPalette->available && pulseBlendPalette->inUse)
{
if (var0->unk4.unk7_6)
if (pulseBlendPalette->pulseBlendSettings.restorePaletteOnUnload)
{
for (i = var0->unk4.unk2; i < var0->unk4.unk2 + var0->unk4.unk4; i++)
for (i = pulseBlendPalette->pulseBlendSettings.paletteOffset; i < pulseBlendPalette->pulseBlendSettings.paletteOffset + pulseBlendPalette->pulseBlendSettings.numColors; i++)
gPlttBufferFaded[i] = gPlttBufferUnfaded[i];
}
var0->unk1_6 = 1;
arg0->unk0 &= ~(1 << j);
pulseBlendPalette->available = 1;
pulseBlend->usedPulseBlendPalettes &= ~(1 << j);
}
}
else
{
for (j = 0; j < 16; j++)
{
var0 = &arg0->unk4[j];
if (!(arg1 & 1) || var0->unk1_6 || !var0->unk1_7)
pulseBlendPalette = &pulseBlend->pulseBlendPalettes[j];
if (!(pulseBlendPaletteSelector & 1) || pulseBlendPalette->available || !pulseBlendPalette->inUse)
{
arg1 <<= 1;
pulseBlendPaletteSelector <<= 1;
}
else
{
if (var0->unk4.unk7_6)
if (pulseBlendPalette->pulseBlendSettings.restorePaletteOnUnload)
{
for (i = var0->unk4.unk2; i < var0->unk4.unk2 + var0->unk4.unk4; i++)
for (i = pulseBlendPalette->pulseBlendSettings.paletteOffset; i < pulseBlendPalette->pulseBlendSettings.paletteOffset + pulseBlendPalette->pulseBlendSettings.numColors; i++)
gPlttBufferFaded[i] = gPlttBufferUnfaded[i];
}
var0->unk1_6 = 1;
arg0->unk0 &= ~(1 << j);
pulseBlendPalette->available = 1;
pulseBlend->usedPulseBlendPalettes &= ~(1 << j);
}
}
}
}
#ifdef NONMATCHING
void sub_8151E50(struct InnerStruct203CF18 *arg0)
void UpdatePulseBlend(struct PulseBlend *pulseBlend)
{
struct InnerStruct203CF18_2 *var0;
struct PulseBlendPalette *pulseBlendPalette;
u8 i = 0;
if (arg0->unk0)
if (pulseBlend->usedPulseBlendPalettes)
{
for (i = 0; i < 16; i++)
{
var0 = &arg0->unk4[i];
if ((!var0->unk1_6 && var0->unk1_7) && (!gPaletteFade.active || !var0->unk4.unk7_7))
pulseBlendPalette = &pulseBlend->pulseBlendPalettes[i];
if ((!pulseBlendPalette->available && pulseBlendPalette->inUse) && (!gPaletteFade.active || !pulseBlendPalette->pulseBlendSettings.unk7_7))
{
if (--var0->unk2 == 0xFF)
if (--pulseBlendPalette->delayCounter == 0xFF)
{
var0->unk2 = var0->unk4.unk5;
BlendPalette(var0->unk4.unk2, var0->unk4.unk4, var0->unk1_0, var0->unk4.unk0);
switch (var0->unk4.unk7_4)
pulseBlendPalette->delayCounter = pulseBlendPalette->pulseBlendSettings.delay;
BlendPalette(pulseBlendPalette->pulseBlendSettings.paletteOffset, pulseBlendPalette->pulseBlendSettings.numColors, pulseBlendPalette->blendCoeff, pulseBlendPalette->pulseBlendSettings.blendColor);
switch (pulseBlendPalette->pulseBlendSettings.fadeType)
{
case 0:
if (var0->unk1_0++ == var0->unk4.unk7_0)
case 0: // Fade all the way to the max blend amount, then wrap around
// BUG: This comparison will never be true for maxBlendCoeff values that are >= 8. This is because
// maxBlendCoeff is a signed 4-bit field, but blendCoeff is an unsigned 4-bit field. This code is never
// reached, anyway, so the bug is not observable in vanilla gameplay.
if (pulseBlendPalette->blendCoeff++ == pulseBlendPalette->pulseBlendSettings.maxBlendCoeff)
{
var0->unk3++;
var0->unk1_0 = 0;
pulseBlendPalette->fadeCycleCounter++;
pulseBlendPalette->blendCoeff = 0;
}
break;
case 1:
if (var0->unk1_4)
case 1: // Fade in and out
if (pulseBlendPalette->fadeDirection)
{
if (--var0->unk1_0 == 0)
if (--pulseBlendPalette->blendCoeff == 0)
{
var0->unk3++;
var0->unk1_4 ^= 1;
pulseBlendPalette->fadeCycleCounter++;
pulseBlendPalette->fadeDirection ^= 1;
}
}
else
{
if (var0->unk1_0++ == var0->unk4.unk7_0 - 1)
u8 max = (pulseBlendPalette->pulseBlendSettings.maxBlendCoeff - 1) & 0xF;
if (pulseBlendPalette->blendCoeff++ == max)
{
var0->unk3++;
var0->unk1_4 ^= 1;
pulseBlendPalette->fadeCycleCounter++;
pulseBlendPalette->fadeDirection ^= 1;
}
}
break;
case 2:
if (var0->unk1_4)
var0->unk1_0 = 0;
case 2: // Flip back and forth
if (pulseBlendPalette->fadeDirection)
pulseBlendPalette->blendCoeff = 0;
else
var0->unk1_0 = var0->unk4.unk7_0;
pulseBlendPalette->blendCoeff = pulseBlendPalette->pulseBlendSettings.maxBlendCoeff & 0xF;
var0->unk1_4 ^= 1;
var0->unk3++;
pulseBlendPalette->fadeDirection ^= 1;
pulseBlendPalette->fadeCycleCounter++;
break;
}
if (var0->unk4.unk6 != 0xFF && var0->unk3 == 0xFF)
sub_8151D28(arg0, var0->unk0, 0);
if (pulseBlendPalette->pulseBlendSettings.numFadeCycles != 0xFF
&& pulseBlendPalette->fadeCycleCounter == pulseBlendPalette->pulseBlendSettings.numFadeCycles)
UnmarkUsedPulseBlendPalettes(pulseBlend, pulseBlendPalette->paletteSelector, FALSE);
}
}
}
}
}
#else
NAKED
void sub_8151E50(struct InnerStruct203CF18 *arg0)
{
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, 0x4\n\
str r0, [sp]\n\
movs r0, 0\n\
mov r10, r0\n\
ldr r1, [sp]\n\
ldrh r0, [r1]\n\
cmp r0, 0\n\
bne _08151E6C\n\
b _08151FF6\n\
_08151E6C:\n\
movs r2, 0xF\n\
mov r9, r2\n\
movs r3, 0x10\n\
negs r3, r3\n\
mov r8, r3\n\
movs r7, 0x1\n\
_08151E78:\n\
mov r5, r10\n\
lsls r0, r5, 1\n\
add r0, r10\n\
lsls r0, 2\n\
adds r0, 0x4\n\
ldr r1, [sp]\n\
adds r4, r1, r0\n\
ldrb r2, [r4, 0x1]\n\
movs r3, 0xC0\n\
ands r3, r2\n\
cmp r3, 0x80\n\
beq _08151E92\n\
b _08151FE6\n\
_08151E92:\n\
ldr r0, =gPaletteFade\n\
ldrb r1, [r0, 0x7]\n\
adds r0, r3, 0\n\
ands r0, r1\n\
cmp r0, 0\n\
beq _08151EA8\n\
ldrb r0, [r4, 0xB]\n\
ands r3, r0\n\
cmp r3, 0\n\
beq _08151EA8\n\
b _08151FE6\n\
_08151EA8:\n\
ldrb r0, [r4, 0x2]\n\
subs r0, 0x1\n\
strb r0, [r4, 0x2]\n\
lsls r0, 24\n\
lsrs r0, 24\n\
cmp r0, 0xFF\n\
beq _08151EB8\n\
b _08151FE6\n\
_08151EB8:\n\
ldrb r0, [r4, 0x9]\n\
strb r0, [r4, 0x2]\n\
ldrh r0, [r4, 0x6]\n\
ldrb r1, [r4, 0x8]\n\
lsls r2, 28\n\
lsrs r2, 28\n\
ldrh r3, [r4, 0x4]\n\
bl BlendPalette\n\
ldrb r5, [r4, 0xB]\n\
lsls r0, r5, 26\n\
asrs r0, 30\n\
cmp r0, 0x1\n\
beq _08151F16\n\
cmp r0, 0x1\n\
bgt _08151EE4\n\
cmp r0, 0\n\
beq _08151EEA\n\
b _08151FD0\n\
.pool\n\
_08151EE4:\n\
cmp r0, 0x2\n\
beq _08151F92\n\
b _08151FD0\n\
_08151EEA:\n\
ldrb r2, [r4, 0x1]\n\
lsls r1, r2, 28\n\
lsrs r0, r1, 28\n\
adds r0, 0x1\n\
mov r3, r9\n\
ands r0, r3\n\
mov r6, r8\n\
adds r3, r6, 0\n\
ands r3, r2\n\
orrs r3, r0\n\
strb r3, [r4, 0x1]\n\
lsrs r1, 28\n\
lsls r0, r5, 28\n\
asrs r0, 28\n\
cmp r1, r0\n\
bne _08151FD0\n\
ldrb r0, [r4, 0x3]\n\
adds r0, 0x1\n\
strb r0, [r4, 0x3]\n\
ands r3, r6\n\
strb r3, [r4, 0x1]\n\
b _08151FD0\n\
_08151F16:\n\
ldrb r3, [r4, 0x1]\n\
movs r0, 0x10\n\
ands r0, r3\n\
cmp r0, 0\n\
beq _08151F54\n\
lsls r0, r3, 28\n\
lsrs r0, 28\n\
subs r0, 0x1\n\
mov r5, r9\n\
ands r0, r5\n\
mov r2, r8\n\
ands r2, r3\n\
orrs r2, r0\n\
strb r2, [r4, 0x1]\n\
cmp r0, 0\n\
bne _08151FD0\n\
ldrb r0, [r4, 0x3]\n\
adds r0, 0x1\n\
strb r0, [r4, 0x3]\n\
lsls r0, r2, 27\n\
lsrs r0, 31\n\
eors r0, r7\n\
ands r0, r7\n\
lsls r0, 4\n\
movs r3, 0x11\n\
negs r3, r3\n\
adds r1, r3, 0\n\
ands r2, r1\n\
orrs r2, r0\n\
strb r2, [r4, 0x1]\n\
b _08151FD0\n\
_08151F54:\n\
lsls r0, r5, 28\n\
asrs r0, 28\n\
subs r0, 0x1\n\
mov r5, r9\n\
ands r0, r5\n\
lsls r2, r3, 28\n\
lsrs r1, r2, 28\n\
adds r1, 0x1\n\
ands r1, r5\n\
mov r5, r8\n\
ands r3, r5\n\
orrs r3, r1\n\
strb r3, [r4, 0x1]\n\
lsrs r2, 28\n\
cmp r2, r0\n\
bne _08151FD0\n\
ldrb r0, [r4, 0x3]\n\
adds r0, 0x1\n\
strb r0, [r4, 0x3]\n\
lsls r0, r3, 27\n\
lsrs r0, 31\n\
eors r0, r7\n\
ands r0, r7\n\
lsls r0, 4\n\
movs r2, 0x11\n\
negs r2, r2\n\
adds r1, r2, 0\n\
ands r3, r1\n\
orrs r3, r0\n\
strb r3, [r4, 0x1]\n\
b _08151FD0\n\
_08151F92:\n\
ldrb r2, [r4, 0x1]\n\
movs r0, 0x10\n\
ands r0, r2\n\
cmp r0, 0\n\
beq _08151FA2\n\
mov r0, r8\n\
ands r0, r2\n\
b _08151FB0\n\
_08151FA2:\n\
lsls r1, r5, 28\n\
asrs r1, 28\n\
mov r3, r9\n\
ands r1, r3\n\
mov r0, r8\n\
ands r0, r2\n\
orrs r0, r1\n\
_08151FB0:\n\
strb r0, [r4, 0x1]\n\
ldrb r2, [r4, 0x1]\n\
lsls r0, r2, 27\n\
lsrs r0, 31\n\
eors r0, r7\n\
ands r0, r7\n\
lsls r0, 4\n\
movs r5, 0x11\n\
negs r5, r5\n\
adds r1, r5, 0\n\
ands r2, r1\n\
orrs r2, r0\n\
strb r2, [r4, 0x1]\n\
ldrb r0, [r4, 0x3]\n\
adds r0, 0x1\n\
strb r0, [r4, 0x3]\n\
_08151FD0:\n\
ldrb r1, [r4, 0xA]\n\
cmp r1, 0xFF\n\
beq _08151FE6\n\
ldrb r0, [r4, 0x3]\n\
cmp r0, r1\n\
bne _08151FE6\n\
ldrb r1, [r4]\n\
ldr r0, [sp]\n\
movs r2, 0\n\
bl sub_8151D28\n\
_08151FE6:\n\
mov r0, r10\n\
adds r0, 0x1\n\
lsls r0, 24\n\
lsrs r0, 24\n\
mov r10, r0\n\
cmp r0, 0xF\n\
bhi _08151FF6\n\
b _08151E78\n\
_08151FF6:\n\
add sp, 0x4\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");
}
#endif // NONMATCHING
void sub_8152008(u16 *dest, u16 src, u8 left, u8 top, u8 width, u8 height)
{