• Our software update is now concluded. You will need to reset your password to log in. In order to do this, you will have to click "Log in" in the top right corner and then "Forgot your password?".
  • Welcome to PokéCommunity! Register now and join one of the best fan communities on the 'net to talk Pokémon and more! We are not affiliated with The Pokémon Company or Nintendo.

[Graphic✓] Is it *possible* to show an animation during the "Saving... Don't turn off the power" screen?

POKéMIKE1

AKA meejle
85
Posts
14
Years
  • So I was poking around in save_failed_screen.c and thought how cool it'd be if I could get the clock animation working on the normal save screen. Something akin to what the DS games have.

    It went... badly. 😅

    I weirdly had more luck trying to "port over" the shaking Poké Ball effect from starter_choose.c, but the Poké Ball would only animate until the "Saving... Don't turn off the power" text printer finished, and then it would freeze until the "Player saved the game" message.

    What is it that stops animations from running while the save message is being shown? Is there any way around it?
    If so, would it likely cause any problems with saving the game?

    EDIT: We got it working, find a tutorial here - https://github.com/pret/pokeemerald/wiki/Show-a-throbber-animation-while-the-game-is-saving
     
    Last edited:

    POKéMIKE1

    AKA meejle
    85
    Posts
    14
    Years

  • ETA: My video is pretty compressed, so you might need to full-screen it to even notice the animation, haah.
    --

    OK, so it's definitely possible... But probably wasn't worth two days of effort unless I can squeeze a few more frames of animation out of it. 😆

    This is still based on the Poké Ball animation from starter_choose.c.

    So far what I've got is:

    Below the includes in start_menu.c:

    Spoiler:
    Right at the start of the SaveSavingMessageCallback function:
    Code:
        ShowThrobber();
    Added AnimateSprites and BuildOamBuffer to the WriteSaveSectorOrSlot function in save.c:
    Code:
            for (i = 0; i < NUM_SECTORS_PER_SLOT; i++)
            {
                AnimateSprites();
                BuildOamBuffer();
                HandleWriteSector(i, locations);
            }

    Through a lot of trial and error I figured out that "for" statement is the point where everything freezes, so that's the part I messed with.

    I don't understand much about save.c, but am I right in thinking this is only updating the animation once per save sector? Or... something along those lines? 🤔

    Can someone smarter than me find way to run it more often, please? (Also I haven't figured out how to get DestroySprite to work, yet.)
     
    Last edited:
    449
    Posts
    6
    Years
    • Seen today
    Can someone smarter than me find way to run it more often, please?

    So the issue you're having is that normally the sprite animation code is executed once per frame in the main loop via callbacks, but during saving the game is not returning to the main loop so sprites aren't getting updated. You added code for animating the sprites in the saving loop but obviously it's only running once per sector.

    To make the code run once every frame, you could put it in a VBlank callback, which is a kind of function that the hardware runs once every frame. For Example:

    Code:
    [COLOR="Red"]--- a/src/save.c[/COLOR]
    [COLOR="Lime"]+++ b/src/save.c[/COLOR]
    @@ -136,8 +136,16 @@ static bool32 SetDamagedSectorBits(u8 op, u8 sectorId)
         return retVal;
     }
     
    [COLOR="Lime"]+static void VBlankCB_Saving(void)
    +{
    +    AnimateSprites();
    +    BuildOamBuffer();
    +    LoadOam();
    +    ProcessSpriteCopyRequests();
    +}
    +[/COLOR]
     static u8 WriteSaveSectorOrSlot(u16 sectorId, const struct SaveSectorLocation *locations)
     {
    [COLOR="Lime"]+    IntrCallback prevVblankCB;[/COLOR]
         u32 status;
         u16 i;
     
    @@ -157,13 +165,13 @@ static u8 WriteSaveSectorOrSlot(u16 sectorId, const struct SaveSectorLocation *l
             gLastWrittenSector = gLastWrittenSector % NUM_SECTORS_PER_SLOT;
             gSaveCounter++;
             status = SAVE_STATUS_OK;
    [COLOR="Red"]-[/COLOR]
    [COLOR="Lime"]+       prevVblankCB = gMain.vblankCallback;
    +       SetVBlankCallback(VBlankCB_Saving);[/COLOR]
             for (i = 0; i < NUM_SECTORS_PER_SLOT; i++)
             {
    [COLOR="Red"]-            AnimateSprites();
    -            BuildOamBuffer();[/COLOR]
                 HandleWriteSector(i, locations);
             }
    [COLOR="Lime"]+       SetVBlankCallback(prevVblankCB);[/COLOR]
     
             if (gDamagedSaveSectors)
             {

    kkB8px1.gif
     
    Last edited:

    POKéMIKE1

    AKA meejle
    85
    Posts
    14
    Years
  • You're amazing! 🙏 Thank you so much!

    I was starting to suspect it'd be something to do with VBlank callbacks but I didn't know enough to actually get it working. 😅

    I don't suppose you could point me in the right direction for destroying the sprite afterwards? I experimented for another couple of hours yesterday but all I succeeded in doing was destroying the player object haha.
     
    449
    Posts
    6
    Years
    • Seen today
    I don't suppose you could point me in the right direction for destroying the sprite afterwards? I experimented for another couple of hours yesterday but all I succeeded in doing was destroying the player object haha.

    You should locate a place in the code that runs when you want the sprite to disappear. There you should call the DestroySprite function with a pointer to your sprite, which you can obtain from the sprite's id like this:
    Code:
    DestroySprite(&gSprites[spriteId]);

    You should store the spriteId that you get when you call CreateSprite somewhere. If the sprite is both created and destroyed in a task, you could use the task's data array, otherwise you might use a global variable.
     
    Back
    Top