diff options
author | Rangi <remy.oukaour+rangi42@gmail.com> | 2018-10-28 20:11:17 -0400 |
---|---|---|
committer | Rangi <remy.oukaour+rangi42@gmail.com> | 2018-10-28 20:11:17 -0400 |
commit | 968e297e6056eaeff6cdf27c74ad02d803d0e634 (patch) | |
tree | b4a84e3f6af32b17d8d671b67b677039c88bd380 | |
parent | f678cc8c765a918971ed2d1b965e2ff30fdfe931 (diff) |
- Link to the save delay tutorial from the main page
- Link .asm filenames in the save delay tutorial
-rw-r--r-- | Remove-the-artificial-save-delay.md | 71 | ||||
-rw-r--r-- | Tutorials.md | 2 |
2 files changed, 41 insertions, 32 deletions
diff --git a/Remove-the-artificial-save-delay.md b/Remove-the-artificial-save-delay.md index bbc784f..7195e4d 100644 --- a/Remove-the-artificial-save-delay.md +++ b/Remove-the-artificial-save-delay.md @@ -2,7 +2,8 @@ This tutorial describes how to remove the artificial delays introduced when savi Saving the game is a reasonably quick process. A full write to SRAM takes less than a quarter of a second. However, for reasons unknown, the game makes it seem like a five-second process, displaying at least two confirmation windows, and forcing the player to wait while saving. Regardless of whether this annoyance was an intentional design choice or an artifact of its time, there is no actual need for the delays, and thus they can easily be removed for a much smoother saving process. -Note that most of this tutorial takes place in a single file, `engine/menus/save.asm`. If nothing else is indicated, assume that the listed functions are found in that file. +Note that most of this tutorial takes place in a single file, [engine/menus/save.asm](../blob/master/engine/menus/save.asm). If nothing else is indicated, assume that the listed functions are found in that file. + ## Contents @@ -15,9 +16,10 @@ Note that most of this tutorial takes place in a single file, `engine/menus/save 7. [Removing the remaining delays][sec-7] 8. [Adding a message without delays][sec-8] + ## 1. Understanding the saving process -Before making any changes to the saving process, it is instructive to look at how it works. The game mainly gets saved in five occasions: +Before making any changes to the saving process, it is instructive to look at how it works. The game gets saved on five occasions: * When the player manually initiates a save, via the Start menu; * When the player uses the "move Pokémon without mail" feature; @@ -30,7 +32,7 @@ Each of these five situations calls slightly different code, but the underlying 1. Display a prompt asking if they want to save. 2. If a previous savefile exists, display another confirmation prompt (with separate prompts for updating the current game's savefile vs. overwriting a previous game's savefile with a completely new one). 3. Block all player inputs after confirming. -4. Override the text speed, setting it to "Medium", and display `SAVING... DON'T TURN OFF THE POWER`. +4. Override the text speed, setting it to "Medium", and display `SAVING… DON'T TURN OFF THE POWER`. 5. Wait 16 frames. 6. Actually save the game. This is the important step. 7. Wait 32 frames. @@ -39,13 +41,14 @@ Each of these five situations calls slightly different code, but the underlying 10. Wait 30 frames. 11. Close the menus and let the player continue playing. -The key takeaway from this list is that saving _only occurs during step 6_. That means that while the game is waiting and displaying the "saving..." message, _no actual saving is happening_. Therefore, all of these delays can be removed without interfering at all with the saving feature. The following steps show how to achieve this goal. +The key takeaway from this list is that saving _only occurs during step 6_. That means that while the game is waiting and displaying the `SAVING…` message, _no actual saving is happening_. Therefore, all of these delays can be removed without interfering at all with the saving feature. The following steps show how to achieve this goal. Note that, with the exception of the immediately following section, all sections are optional. If you want to keep some of the delays, skip the corresponding sections. + ## 2. Removing the slow text printing function -Much of the slowness in the process comes from the function that prints the `SAVING... DON'T TURN OFF THE POWER` text. This function is adequately called `SavingDontTurnOffThePower`, and handles steps 3 through 5 in [the section above][sec-1]. Since this function serves no useful purpose, it can safely be deleted, along with the two calls to it. Delete the entire function, and remove the two calls as follows: +Much of the slowness in the process comes from the function that prints the `SAVING… DON'T TURN OFF THE POWER` text. This function is adequately called `SavingDontTurnOffThePower`, and handles steps 3 through 5 in [the section above][sec-1]. Since this function serves no useful purpose, it can safely be deleted, along with the two calls to it. Delete the entire function, and remove the two calls as follows: ```diff ChangeBoxSaveGame: @@ -63,7 +66,7 @@ Much of the slowness in the process comes from the function that prints the `SAV ; ... ``` -The deleted function also references a text element, which in turn makes a far jump to the actual text in `data/text/common_3.asm`. Both of these elements may be deleted: +The deleted function also references a text element, which in turn makes a far jump to the actual text in [data/text/common_3.asm](../blob/master/data/text/common_3.asm). Both of these elements may be deleted: ```diff -Text_SavingDontTurnOffThePower: @@ -72,7 +75,7 @@ The deleted function also references a text element, which in turn makes a far j - db "@" ``` -And in `data/text/common_3.asm`: +And in [data/text/common_3.asm](../blob/master/data/text/common_3.asm): ```diff -UnknownText_0x1c456d:: @@ -83,6 +86,7 @@ And in `data/text/common_3.asm`: While most of the delay will be gone with this single step, the rest of the steps in this tutorial will fully remove the delays and polish the experience for the user. + ## 3. Renaming functions After the deletion from [the previous section][sec-2], `_SavingDontTurnOffThePower` becomes a simple dummy function that falls through into `SavedTheGame`; the former can thus be removed, and all calls replaced with calls to the latter. Similarly, `SaveGameData` is nothing but a wrapper for `_SaveGameData`; the wrapper can be deleted and the underscore removed. @@ -97,9 +101,9 @@ Note that, while this step isn't necessary, it will greatly improve the readabil + call SavedTheGame call ResumeGameLogic ; ... - + ; ... - + Link_SaveGame: ; ... call PauseGameLogic @@ -107,9 +111,9 @@ Note that, while this step isn't necessary, it will greatly improve the readabil + call SavedTheGame call ResumeGameLogic ; ... - + ; ... - + StartMoveMonWOMail_SaveGame: ; ... call PauseGameLogic @@ -118,28 +122,28 @@ Note that, while this step isn't necessary, it will greatly improve the readabil call ResumeGameLogic and a ret - + ; ... - + -SaveGameData: - call _SaveGameData - ret - + ; ... - + -_SavingDontTurnOffThePower: SavedTheGame: - call _SaveGameData + call SaveGameData ; ... - + -_SaveGameData: +SaveGameData: ld a, TRUE ; ... ``` -This renaming also requires editing a single line in `mobile/mobile_5f.asm`: +This renaming also requires editing a single line in [mobile/mobile_5f.asm](../blob/master/mobile/mobile_5f.asm): ```diff IncCrashCheckPointer_SaveGameData: @@ -147,9 +151,10 @@ This renaming also requires editing a single line in `mobile/mobile_5f.asm`: + inc_crash_check_pointer_farcall SaveGameData ``` + ## 4. Removing delays in save function -With the text delays removed, every piece of code that used to print the slow `SAVING... DON'T TURN OFF THE POWER` message now calls `SavedTheGame` instead; other parts of the code call it directly. This function is responsible for calling `SaveGameData` (which is where the actual saving happens) and then informing the player that saving succeeded. +With the text delays removed, every piece of code that used to print the slow `SAVING… DON'T TURN OFF THE POWER` message now calls `SavedTheGame` instead; other parts of the code call it directly. This function is responsible for calling `SaveGameData` (which is where the actual saving happens) and then informing the player that saving succeeded. Of course, the informing part is done with plenty of delays (namely, steps 7, 8 and 10 in [the first section][sec-1]), which we can remove: @@ -201,7 +206,7 @@ Fortunately, since the game already contains separate texts for each situation, call SaveTheGame_yesorno jr nz, .refused - jr .erase - + -.yoursavefile - ld hl, Text_AlreadyASaveFile - call SaveTheGame_yesorno @@ -214,20 +219,20 @@ Fortunately, since the game already contains separate texts for each situation, -.ok and a ret - + .refused scf ret - + ; ... - + -Text_AlreadyASaveFile: - ; There is already a save file. Is it OK to overwrite? - text_jump UnknownText_0x1c45a3 - db "@" ``` -The corresponding text from `data/text/common_3.asm` can be removed as well: +The corresponding text from [data/text/common_3.asm](../blob/master/data/text/common_3.asm) can be removed as well: ```diff -UnknownText_0x1c45a3:: @@ -237,11 +242,12 @@ The corresponding text from `data/text/common_3.asm` can be removed as well: - done ``` + ## 6. Removing the delays on Bill's PC -Bill's PC requires a save when changing boxes, and also when using the "move Pokémon without mail" feature (which saves once initially and once per swap). Changing boxes just uses the regular save code (the same we just edited), so that's taken care of. However, swapping Pokémon through the "move Pokémon without mail" feature uses separate code, with smaller delays, simply because the longer delays from the regular function would be intolerable here. Despite these delays are smaller, they have no reason to exist, and thus can safely be removed. +Bill's PC requires a save when changing boxes, and also when using the "move Pokémon without mail" feature (which saves once initially and once per swap). Changing boxes just uses the regular save code (the same we just edited), so that's taken care of. However, swapping Pokémon through the "move Pokémon without mail" feature uses separate code, with smaller delays, simply because the longer delays from the regular function would be intolerable here. Despite these delays being smaller, they have no reason to exist, and thus can safely be removed. -First of all, the function in `engine/menus/save.asm`, the file we've been editing so far: +First of all, the function in [engine/menus/save.asm](../blob/master/engine/menus/save.asm), the file we've been editing so far: ```diff MoveMonWOMail_InsertMon_SaveGame: @@ -256,7 +262,7 @@ First of all, the function in `engine/menus/save.asm`, the file we've been editi - ret ``` -And secondly, the actual function in Bill's PC's code, in `engine/pokemon/bills_pc.asm`: +And secondly, the actual function in Bill's PC's code, in [engine/pokemon/bills_pc.asm](../blob/master/engine/pokemon/bills_pc.asm): ```diff MovePKMNWitoutMail_InsertMon: @@ -272,11 +278,12 @@ And secondly, the actual function in Bill's PC's code, in `engine/pokemon/bills_ ; ... ``` + ## 7. Removing the remaining delays At this point, only two sources of delay remain, corresponding to the two most uncommon cases out of the five listed in the [first section][sec-1]. The first one of them is the "quick save" function, used by the link features and the Battle Tower when they require the player to save in the middle of their text prompts. The delay here is very small, hence the "quick" moniker, but it can still be removed. -In `engine/link/link.asm`: +In [engine/link/link.asm](../blob/master/engine/link/link.asm): ```diff TryQuickSave: @@ -291,7 +298,7 @@ In `engine/link/link.asm`: Finally, the one delay that remains is the one that appears when the player becomes Champion, before the credits roll. This delay is very large, as it replaces all the smaller delays in other functions; it's nearly two seconds long. Fortunately, it can also be removed. -In `engine/events/halloffame.asm`: +In [engine/events/halloffame.asm](../blob/master/engine/events/halloffame.asm): ```diff HallOfFame_FadeOutMusic: @@ -302,11 +309,12 @@ In `engine/events/halloffame.asm`: + ret ``` + ## 8. Adding a message without delays At this point, with all sources of delay removed, saving only takes the amount of time that is actually necessary to write data to SRAM. Sadly, since the code isn't as optimized as it could be and the GB is just slow, this takes a visible amount of time; typically around a quarter of a second, but enough to make it seem like the game temporarily froze. -A simple solution to this problem is to add again a message like the one we removed. Despite the game wasn't saving while `SAVING... DON'T TURN OFF THE POWER` was being printed, the game _did_ save at some point in time after that (in the middle of the delays) while the message was still visible, so the player knew that the game was doing something. +A simple solution to this problem is to add again a message like the one we removed. Despite the game wasn't saving while `SAVING… DON'T TURN OFF THE POWER` was being printed, the game _did_ save at some point in time after that (in the middle of the delays) while the message was still visible, so the player knew that the game was doing something. If we are to reinstate this message, we should be careful not to introduce back the delays we spent the whole tutorial removing. Therefore, any message that we introduce must meet the following conditions: @@ -335,12 +343,13 @@ Making a final edit to `SavedTheGame` achieves this goal: ld de, SFX_SAVE call WaitPlaySFX jp WaitSFX - + +.saving_text + text "Saving…" + done ``` + [sec-1]: #1-understanding-the-saving-process [sec-2]: #2-removing-the-slow-text-printing-function [sec-3]: #3-renaming-functions @@ -348,4 +357,4 @@ Making a final edit to `SavedTheGame` achieves this goal: [sec-5]: #5-removing-the-extra-prompt [sec-6]: #6-removing-the-delays-on-bills-pc [sec-7]: #7-removing-the-remaining-delays -[sec-8]: #8-adding-a-message-without-delays
\ No newline at end of file +[sec-8]: #8-adding-a-message-without-delays diff --git a/Tutorials.md b/Tutorials.md index 21673d7..2314b01 100644 --- a/Tutorials.md +++ b/Tutorials.md @@ -52,6 +52,7 @@ Tutorials may use diff syntax to show edits: - [Print text when you lose a trainer battle](Print-text-when-you-lose-a-trainer-battle) - [Correct grammar for plural trainers like Twins](Correct-grammar-for-plural-trainers-like-Twins) - [Custom order for the Old Pokédex mode](Custom-order-for-the-Old-Pokédex-mode) +- [Remove the artificial save delay](Remove-the-artificial-save-delay) **Removing features:** @@ -104,7 +105,6 @@ Tutorials may use diff syntax to show edits: - Trainer dialog and music change for their last Pokémon - TM/HM item balls say the move name - Items that act like overworld moves -- Remove the artificial save delay - Safari Game - Ghost and Silph Scope - Nuzlocke mode (an in-game enforced [Nuzlocke Challenge](https://bulbapedia.bulbagarden.net/wiki/Nuzlocke_Challenge)) |