diff options
author | SonikkuA-DatH <58025603+SonikkuA-DatH@users.noreply.github.com> | 2021-10-16 21:01:48 -0700 |
---|---|---|
committer | SonikkuA-DatH <58025603+SonikkuA-DatH@users.noreply.github.com> | 2021-10-16 21:01:48 -0700 |
commit | 6551e681db19b1130b3ce6b4150138455fc5c9a2 (patch) | |
tree | c27045619803d41cc4291b3df69e7fd2434c14c2 | |
parent | 5cc6b5af440838dfdec2e774055b31309347c375 (diff) |
Created Make space for EWRAM Data for Summary screen (markdown)
-rw-r--r-- | Make-space-for-EWRAM-Data-for-Summary-screen.md | 395 |
1 files changed, 395 insertions, 0 deletions
diff --git a/Make-space-for-EWRAM-Data-for-Summary-screen.md b/Make-space-for-EWRAM-Data-for-Summary-screen.md new file mode 100644 index 0000000..1b37d04 --- /dev/null +++ b/Make-space-for-EWRAM-Data-for-Summary-screen.md @@ -0,0 +1,395 @@ +The summary screen in RSE is surprisingly wasteful, which for Castform in particular has it so all forms are loaded in memory, despite only using 1. This tweak will fix it so it's more optimized + +Thanks to ShinyDragonHunter for this + +First, we'll set up **InitMonSpritesGfx_Battle** (or **static void sub_806F160** if your pret version is old) function in [src/pokemon.c](../blob/master/src/pokemon.c) to do the following + +Change this + +``` +void SetMultiuseSpriteTemplateToPokemon(u16 speciesTag, u8 battlerPosition) +{ + if (gMonSpritesGfxPtr != NULL) + gMultiuseSpriteTemplate = gMonSpritesGfxPtr->templates[battlerPosition]; + else if (sMonSpritesGfxManagers[MON_SPR_GFX_MANAGER_A]) + gMultiuseSpriteTemplate = sMonSpritesGfxManagers[MON_SPR_GFX_MANAGER_A]->templates[battlerPosition]; + else if (sMonSpritesGfxManagers[MON_SPR_GFX_MANAGER_B]) + gMultiuseSpriteTemplate = sMonSpritesGfxManagers[MON_SPR_GFX_MANAGER_B]->templates[battlerPosition]; + else + gMultiuseSpriteTemplate = gBattlerSpriteTemplates[battlerPosition]; +``` +To + +``` +void SetMultiuseSpriteTemplateToPokemon(u16 speciesTag, u8 battlerPosition) +{ + if (gMonSpritesGfxPtr != NULL) + gMultiuseSpriteTemplate = gMonSpritesGfxPtr->templates[battlerPosition]; + else if (sMonSpritesGfxManager) + gMultiuseSpriteTemplate = sMonSpritesGfxManager->templates[battlerPosition]; +``` + +Change the integer to a u32 (current version) + +```diff +static void InitMonSpritesGfx_Battle(struct MonSpritesGfxManager* gfx) +{ +- u16 i, j; ++ u32 i, j; + for (i = 0; i < gfx->numSprites; i++) + { + gfx->templates[i] = gBattlerSpriteTemplates[i]; + for (j = 0; j < gfx->numFrames; j++) + gfx->frameImages[i * gfx->numFrames + j].data = &gfx->spritePointers[i][j * MON_PIC_SIZE]; + + gfx->templates[i].images = &gfx->frameImages[i * gfx->numFrames]; + } +} +``` + +Next, in the struct below it (this is big) change + +``` +struct MonSpritesGfxManager *CreateMonSpritesGfxManager(u8 managerId, u8 mode) +{ + u8 i; + u8 failureFlags; + struct MonSpritesGfxManager *gfx; + + failureFlags = 0; + managerId %= MON_SPR_GFX_MANAGERS_COUNT; + gfx = AllocZeroed(sizeof(*gfx)); + if (gfx == NULL) + return NULL; + + switch (mode) + { + case MON_SPR_GFX_MODE_FULL_PARTY: + gfx->numSprites = PARTY_SIZE + 1; + gfx->numSprites2 = PARTY_SIZE + 1; + gfx->numFrames = GFX_MANAGER_NUM_FRAMES; + gfx->dataSize = 1; + gfx->mode = MON_SPR_GFX_MODE_FULL_PARTY; + break; + // case MON_SPR_GFX_MODE_BATTLE: + case MON_SPR_GFX_MODE_NORMAL: + default: + gfx->numSprites = MAX_BATTLERS_COUNT; + gfx->numSprites2 = MAX_BATTLERS_COUNT; + gfx->numFrames = GFX_MANAGER_NUM_FRAMES; + gfx->dataSize = 1; + gfx->mode = MON_SPR_GFX_MODE_NORMAL; + break; + } + + // Set up sprite / sprite pointer buffers + gfx->spriteBuffer = AllocZeroed(gfx->dataSize * GFX_MANAGER_SPR_SIZE * gfx->numSprites); + gfx->spritePointers = AllocZeroed(gfx->numSprites * 32); // ? Only * 4 is necessary, perhaps they were thinking bits. + if (gfx->spriteBuffer == NULL || gfx->spritePointers == NULL) + { + failureFlags |= ALLOC_FAIL_BUFFER; + } + else + { + for (i = 0; i < gfx->numSprites; i++) + gfx->spritePointers[i] = gfx->spriteBuffer + (gfx->dataSize * GFX_MANAGER_SPR_SIZE * i); + } + + // Set up sprite structs + gfx->templates = AllocZeroed(sizeof(struct SpriteTemplate) * gfx->numSprites); + gfx->frameImages = AllocZeroed(sizeof(struct SpriteFrameImage) * gfx->numSprites * gfx->numFrames); + if (gfx->templates == NULL || gfx->frameImages == NULL) + { + failureFlags |= ALLOC_FAIL_STRUCT; + } + else + { + for (i = 0; i < gfx->numFrames * gfx->numSprites; i++) + gfx->frameImages[i].size = MON_PIC_SIZE; + + switch (gfx->mode) + { + case MON_SPR_GFX_MODE_FULL_PARTY: + InitMonSpritesGfx_FullParty(gfx); + break; + case MON_SPR_GFX_MODE_NORMAL: + case MON_SPR_GFX_MODE_BATTLE: + default: + InitMonSpritesGfx_Battle(gfx); + break; + } + } + + // If either of the allocations failed free their respective members + if (failureFlags & ALLOC_FAIL_STRUCT) + { + TRY_FREE_AND_SET_NULL(gfx->frameImages); + TRY_FREE_AND_SET_NULL(gfx->templates); + } + if (failureFlags & ALLOC_FAIL_BUFFER) + { + TRY_FREE_AND_SET_NULL(gfx->spritePointers); + TRY_FREE_AND_SET_NULL(gfx->spriteBuffer); + } + + if (failureFlags) + { + // Clear, something failed to allocate + memset(gfx, 0, sizeof(*gfx)); + Free(gfx); + } + else + { + gfx->active = GFX_MANAGER_ACTIVE; + sMonSpritesGfxManagers[managerId] = gfx; + } + + return sMonSpritesGfxManagers[managerId]; +} +``` + +To + +``` +struct MonSpritesGfxManager *CreateMonSpritesGfxManager(void) +{ + u32 i; + u8 failureFlags; + struct MonSpritesGfxManager *gfx; + + failureFlags = 0; + gfx = AllocZeroed(sizeof(*gfx)); + if (gfx == NULL) + return NULL; + + gfx->numSprites = MAX_BATTLERS_COUNT; + gfx->numFrames = GFX_MANAGER_NUM_FRAMES; + gfx->spriteBuffer = AllocZeroed(GFX_MANAGER_SPR_SIZE * gfx->numSprites); + gfx->spritePointers = AllocZeroed(gfx->numSprites * 4); + if (gfx->spriteBuffer == NULL || gfx->spritePointers == NULL) + { + failureFlags |= ALLOC_FAIL_BUFFER; + } + else + { + for (i = 0; i < gfx->numSprites; i++) + gfx->spritePointers[i] = gfx->spriteBuffer + (GFX_MANAGER_SPR_SIZE * i); + } + + // Set up sprite structs + gfx->templates = AllocZeroed(sizeof(struct SpriteTemplate) * gfx->numSprites); + gfx->frameImages = AllocZeroed(sizeof(struct SpriteFrameImage) * gfx->numSprites * gfx->numFrames); + if (gfx->templates == NULL || gfx->frameImages == NULL) + { + failureFlags |= ALLOC_FAIL_STRUCT; + } + else + { + for (i = 0; i < gfx->numFrames * gfx->numSprites; i++) + gfx->frameImages[i].size = MON_PIC_SIZE; + InitMonSpritesGfx_Battle(gfx); + } + + // If either of the allocations failed free their respective members + if (failureFlags & ALLOC_FAIL_STRUCT) + { + TRY_FREE_AND_SET_NULL(gfx->frameImages); + TRY_FREE_AND_SET_NULL(gfx->templates); + } + if (failureFlags & ALLOC_FAIL_BUFFER) + { + TRY_FREE_AND_SET_NULL(gfx->spritePointers); + TRY_FREE_AND_SET_NULL(gfx->spriteBuffer); + } + + if (failureFlags) + { + // Clear, something failed to allocate + memset(gfx, 0, sizeof(*gfx)); + Free(gfx); + } + else + { + gfx->active = TRUE; + sMonSpritesGfxManager = gfx; + } + + return sMonSpritesGfxManager; +} +``` + +Then this + +``` +void DestroyMonSpritesGfxManager(u8 managerId) +{ + struct MonSpritesGfxManager *gfx; + + managerId %= MON_SPR_GFX_MANAGERS_COUNT; + gfx = sMonSpritesGfxManagers[managerId]; + if (gfx == NULL) + return; + + if (gfx->active != GFX_MANAGER_ACTIVE) + { + memset(gfx, 0, sizeof(*gfx)); + } + else + { + TRY_FREE_AND_SET_NULL(gfx->frameImages); + TRY_FREE_AND_SET_NULL(gfx->templates); + TRY_FREE_AND_SET_NULL(gfx->spritePointers); + TRY_FREE_AND_SET_NULL(gfx->spriteBuffer); + memset(gfx, 0, sizeof(*gfx)); + Free(gfx); + } +} +``` + +To + +``` +void DestroyMonSpritesGfxManager(void) +{ + struct MonSpritesGfxManager *gfx = sMonSpritesGfxManager; + + if (gfx == NULL) + return; + + if (gfx->active) + { + TRY_FREE_AND_SET_NULL(gfx->frameImages); + TRY_FREE_AND_SET_NULL(gfx->templates); + TRY_FREE_AND_SET_NULL(gfx->spritePointers); + TRY_FREE_AND_SET_NULL(gfx->spriteBuffer); + memset(gfx, 0, sizeof(*gfx)); + Free(gfx); + } + else + memset(gfx, 0, sizeof(*gfx)); +} +``` + +And finally, this +``` +u8 *MonSpritesGfxManager_GetSpritePtr(u8 managerId, u8 spriteNum) +{ + struct MonSpritesGfxManager *gfx = sMonSpritesGfxManagers[managerId % MON_SPR_GFX_MANAGERS_COUNT]; + if (gfx->active != GFX_MANAGER_ACTIVE) + { + return NULL; + } + else + { + if (spriteNum >= gfx->numSprites) + spriteNum = 0; + + return gfx->spritePointers[spriteNum]; + } +} +``` + +To this +``` +u8 *MonSpritesGfxManager_GetSpritePtr(u8 spriteNum) +{ + struct MonSpritesGfxManager *gfx = sMonSpritesGfxManager; + + if (gfx->active) + { + if (spriteNum >= gfx->numSprites) + spriteNum = 0; + + return gfx->spritePointers[spriteNum]; + } + return NULL; +} +``` + +After all that, head on to [include/pokemon.h](../blob/master/include/pokemon.h) to reduce this +``` +struct MonSpritesGfxManager +{ + u32 numSprites:4; + u32 numSprites2:4; // Never read + u32 numFrames:8; + u32 active:8; + u32 dataSize:4; + u32 mode:4; // MON_SPR_GFX_MODE_* + void *spriteBuffer; + u8 **spritePointers; + struct SpriteTemplate *templates; + struct SpriteFrameImage *frameImages; +}; +``` + +To this +``` +struct MonSpritesGfxManager +{ + u8 numSprites; + u8 numFrames; + bool16 active; + void *spriteBuffer; + u8 **spritePointers; + struct SpriteTemplate *templates; + struct SpriteFrameImage *frameImages; +}; +``` + +And then the void changes of these +```diff +- struct MonSpritesGfxManager *CreateMonSpritesGfxManager(u8 managerId, u8 mode); +- void DestroyMonSpritesGfxManager(u8 managerId); +- u8 *MonSpritesGfxManager_GetSpritePtr(u8 managerId, u8 spriteNum); ++ struct MonSpritesGfxManager *CreateMonSpritesGfxManager(void); ++ void DestroyMonSpritesGfxManager(void); ++ u8 *MonSpritesGfxManager_GetSpritePtr(u8 spriteNum); +``` + +Along with in [src/pokemon_summary_screen.c](../blob/master/src/pokemon_summary_screen.c) + +```diff + if (gMonSpritesGfxPtr == NULL) +- CreateMonSpritesGfxManager(MON_SPR_GFX_MANAGER_A, MON_SPR_GFX_MODE_NORMAL); ++ CreateMonSpritesGfxManager(); +``` + +and +```diff +static void CloseSummaryScreen(u8 taskId) +{ + if (MenuHelpers_CallLinkSomething() != TRUE && !gPaletteFade.active) + { + SetMainCallback2(sMonSummaryScreen->callback); + gLastViewedMonIndex = sMonSummaryScreen->curMonIndex; + SummaryScreen_DestroyAnimDelayTask(); + ResetSpriteData(); + FreeAllSpritePalettes(); + StopCryAndClearCrySongs(); + m4aMPlayVolumeControl(&gMPlayInfo_BGM, 0xFFFF, 0x100); + if (gMonSpritesGfxPtr == NULL) +- DestroyMonSpritesGfxManager(MON_SPR_GFX_MANAGER_A); ++ DestroyMonSpritesGfxManager(); + FreeSummaryScreen(); + DestroyTask(taskId); + } +} +``` + +And in **static u8 LoadMonGfxAndSprite** + +```diff + if (sMonSummaryScreen->monList.mons == gPlayerParty || sMonSummaryScreen->mode == SUMMARY_MODE_BOX || sMonSummaryScreen->unk40EF == TRUE) + HandleLoadSpecialPokePic_2(&gMonFrontPicTable[summary->species2], +- MonSpritesGfxManager_GetSpritePtr(MON_SPR_GFX_MANAGER_A, B_POSITION_OPPONENT_LEFT), ++ MonSpritesGfxManager_GetSpritePtr(B_POSITION_OPPONENT_LEFT), + summary->species2, + summary->pid); + else + HandleLoadSpecialPokePic_DontHandleDeoxys(&gMonFrontPicTable[summary->species2], +- MonSpritesGfxManager_GetSpritePtr(MON_SPR_GFX_MANAGER_A, B_POSITION_OPPONENT_LEFT), ++ MonSpritesGfxManager_GetSpritePtr(B_POSITION_OPPONENT_LEFT), + summary->species2, + summary->pid); +```
\ No newline at end of file |