├── .github └── workflows │ └── release-zip.yml ├── .gitignore ├── README.md ├── Readme.html ├── amk_resources ├── music │ └── 01 Miss (no intro).txt └── sfx │ └── Death Prelude.txt ├── changelog.txt ├── credits.txt ├── docs ├── _template.html ├── api.html ├── extra.html ├── faq.html ├── files.html ├── getting_started.html ├── hijack_map.html ├── img │ ├── icon.png │ ├── insert_object.png │ ├── midway_object.png │ ├── multiple_midway_$00.png │ ├── multiple_midway_$01.png │ ├── multiple_midway_$02.png │ └── multiple_midway_$03.png ├── index.html ├── midway_instruction.html ├── objectool_info.html ├── ram_map.html ├── settings_global.html ├── settings_local.html ├── sram_bwram_info.html ├── sram_tables.html ├── style.css ├── troubleshooting.html └── uninstall.html ├── retry_install.bat └── src ├── gamemode ├── retry_gm00.asm ├── retry_gm06.asm ├── retry_gm07.asm ├── retry_gm0C.asm ├── retry_gm0D.asm ├── retry_gm0F.asm ├── retry_gm10.asm ├── retry_gm11.asm ├── retry_gm12.asm ├── retry_gm13.asm ├── retry_gm14.asm ├── retry_gm15.asm ├── retry_gm16.asm └── retry_gm19.asm ├── library └── retry.asm ├── retry_config ├── code │ ├── api.asm │ ├── check_incompatibilities.asm │ ├── fade_to_level.asm │ ├── fade_to_overworld.asm │ ├── game_over.asm │ ├── gm14_end │ │ ├── death_routine.asm │ │ ├── prompt_oam.asm │ │ └── set_checkpoint.asm │ ├── hijacks │ │ ├── custom_midway.asm │ │ ├── death_counter.asm │ │ ├── hex_edits.asm │ │ ├── hurry_up.asm │ │ ├── initial_facing_fix.asm │ │ ├── item_box_fix.asm │ │ ├── multiple_midways.asm │ │ ├── remove_status_bar.asm │ │ ├── sram.asm │ │ ├── switch_palace_message_fix.asm │ │ ├── vanilla_boss_gm13.asm │ │ └── vanilla_midway.asm │ ├── in_level.asm │ ├── include │ │ ├── misc.asm │ │ ├── rom.asm │ │ └── tables.asm │ ├── level_init_1.asm │ ├── level_init_2.asm │ ├── level_init_3.asm │ ├── level_transition.asm │ ├── load_overworld.asm │ ├── nmi.asm │ ├── prompt.asm │ ├── shared.asm │ ├── sprite_status_bar.asm │ ├── startup.asm │ └── time_up.asm ├── extra.asm ├── gfx │ ├── bonus_stars.bin │ ├── coins.bin │ ├── digits.bin │ ├── indicator.bin │ ├── item_box_16x16.bin │ ├── item_box_8x8.bin │ ├── letters1.bin │ ├── letters2.bin │ ├── lives.bin │ └── timer.bin ├── legacy │ └── tables.asm ├── ram.asm ├── settings_global.asm ├── settings_local.asm └── sram_tables.asm └── retry_unpatch.asm /.github/workflows/release-zip.yml: -------------------------------------------------------------------------------- 1 | name: Create Zip on Release 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | build-zip: 9 | name: Build Release Zip 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: Checkout Code 14 | uses: actions/checkout@v3 15 | 16 | - name: Define Exclusions and Create Zip 17 | run: | 18 | # rsync exclusions 19 | EXCLUDES=( 20 | ".git*" 21 | ".gitkeep" 22 | ".gitignore" 23 | ".github" 24 | "README.md" 25 | "docs/_template.html" 26 | ) 27 | 28 | # Create args for rsync 29 | EXCLUDE_ARGS="" 30 | for item in "${EXCLUDES[@]}"; do 31 | EXCLUDE_ARGS+="--exclude=${item} " 32 | done 33 | 34 | # Create zip with rsync 35 | mkdir out 36 | rsync -av --progress ./ ./out/ ${EXCLUDE_ARGS} --exclude=out 37 | ( 38 | cd out || exit 1 39 | zip -r ../retry-system_${{ github.event.release.tag_name }}.zip . 40 | ) 41 | 42 | # Clean up 43 | rm -rf ./out 44 | 45 | - name: Install GitHub CLI 46 | run: | 47 | sudo apt-get install -y gh 48 | 49 | - name: Upload Release Asset 50 | env: 51 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 52 | run: | 53 | gh release upload ${{ github.event.release.tag_name }} retry-system_${{ github.event.release.tag_name }}.zip 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.zip 3 | *~ 4 | *.smc 5 | *.sfc 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Retry System 2 | 3 | This patch is meant as a spiritual successor to worldpeace's [Retry patch](https://www.smwcentral.net/?p=section&a=details&id=26078). While having the same functionalities, it features cleaner and more documented code, new features and a lot less hijacks, which makes it compatible with much more patches than before. Requires [UberASM Tool](https://www.smwcentral.net/?p=section&a=details&id=19982). 4 | 5 | See [Documentation](https://kkevinm.github.io/retry-system/) for more details. 6 | -------------------------------------------------------------------------------- /Readme.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /amk_resources/music/01 Miss (no intro).txt: -------------------------------------------------------------------------------- 1 | #SPC 2 | { 3 | #author "Koji Kondo" 4 | #title "Miss!" 5 | #game "Super Mario World" 6 | } 7 | 8 | #samples 9 | { 10 | "EMPTY.brr" 11 | "EMPTY.brr" 12 | "EMPTY.brr" 13 | "default/03 SMW @3.brr" ; death 14 | "EMPTY.brr" 15 | "EMPTY.brr" 16 | "EMPTY.brr" 17 | "EMPTY.brr" 18 | "EMPTY.brr" 19 | "EMPTY.brr" 20 | "default/0A SMW @9.brr" 21 | "EMPTY.brr" 22 | "default/0C SMW @13.brr" 23 | } 24 | 25 | #option TempoImmunity 26 | #option NoLoop 27 | #option smwvtable 28 | 29 | #0 30 | 31 | $F0 y10 32 | t52 @9 q6E o6 33 | d+=12 e=12 d+=12 e=12 c=12 o5 34 | g=12 g+=12 a=12 d+=12 e=12 c=12 o4 35 | g=12 g+=12 a=12 d+=12 e=12 c=48 o3 36 | c=48 37 | 38 | #2 39 | @9 y10 q4E r=24 o4 40 | e=24 r=24 d=24 r=24 c=24 r=24 o3 41 | b=24 g=24 r=24 o2 42 | g=24 r=24 43 | 44 | #3 45 | @9 y10 q6E o3 46 | c=24 q4E o4 c=24 q6E o2 47 | a+=24 q4E o3 48 | a+=24 q6E o2 49 | a=24 q4E o3 50 | a=24 q6E o2 51 | g=24 q4E o3 52 | g=24 q6E o2 53 | c=24 r=24 c=48 54 | 55 | 56 | #amk 2 57 | -------------------------------------------------------------------------------- /amk_resources/sfx/Death Prelude.txt: -------------------------------------------------------------------------------- 1 | $DA $02 $04 $30 $B4 $B2 $B4 2 | -------------------------------------------------------------------------------- /credits.txt: -------------------------------------------------------------------------------- 1 | - Kevin: main programming and mantaining of the repository, with contributions by: 2 | - worldpeace: original Retry patch. 3 | - lx5: bugfixes to the original Retry patch, BW-RAM+ code. 4 | - imamelia, 0x400: ObjecTool code. 5 | - Thomas: death counter code. 6 | - Lui: remove status bar code. 7 | - dtothefourth: a couple new features ideas. 8 | - AmperSam: documentation help, 8x8 item box gfx, lives counter gfx, release workflow script, testing and feedback. 9 | - MiracleWater: Retry indicator idea and gfx, testing and feedback. 10 | - BabaYegha, Fyre150, Abdu, margot, simon.caio, LouisDoucet, SJandCharlieTheCat, Koopster, schema_tuna, Alex, Selicre, Mega, worldpeace, NixKillsMyths, mmBeefStew: testing and feedback. 11 | -------------------------------------------------------------------------------- /docs/_template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
Return to main page
13 | 14 | 15 | -------------------------------------------------------------------------------- /docs/api.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Retry API - Retry System UberASM 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Retry API

12 |

"Retry API" refers to a collection of routines that Retry provides that you can call from your UberASM files if needed.

13 |

NOTE: calling these routines from files in the "library" folder will result in an error, at least when using the standard UberASMTool.

14 | 15 |

Index

16 | 25 |
26 | 27 |

Respawn in level

28 |

JSL retry_api_respawn_in_level

29 |

Call this to make the player respawn in the current level at the last checkpoint. This has the same effect as dying and hitting Retry, or dying with instant Retry enabled, but skipping everything related to death (animation, music, prompt, etc.).

30 | 36 |
37 | 38 |

Save game

39 |

JSL retry_api_save_game

40 |

Call this to save the game, which will also save the addresses defined in the sram_tables.asm file.

41 | 47 |
48 | 49 |

Reset level checkpoint

50 |

JSL retry_api_reset_level_checkpoint

51 |

Call this to reset the checkpoint in the current level. Entering the level again or respawning will load the main sublevel's entrance. Note that this won't reflect to SRAM until the game is saved.

52 | 58 |
59 | 60 |

Reset all checkpoints

61 |

JSL retry_api_reset_all_checkpoints

62 |

Call this to reset the checkpoint for every level in the game, effectively making it as if it were a fresh game. Note that this won't reflect to SRAM until the game is saved.

63 | 69 |
70 | 71 |

Configure sprite status bar

72 |

NOTE: this routine has no effect unless !sprite_status_bar = 1 in settings_global.asm.

73 |

Call this in UberASM level init code to configure graphics for the sprite status bar items (item box, timer, coin counter, lives counter, bonus stars counter) for a specific level. Calling this will override the default settings found in settings_global.asm, in case you want to hide some or all of the elements in some level or if you need to change their tile or palette.

74 |

Each item's configuration is set with a 16 bit value $PTTT. The first digit P will be the item's palette, starting from palette 8 with P = 8 and ending with palette F with P = F. TTT will determine the tile number: you can see this in Lunar Magic's "8x8 Tile Editor" if you hover over the desired tile (more specifically, the upper left 8x8 tile of the 16x16 tile you want to use). In the bottom bar you'll see "Tile 0xYYY": then, TTT = YYY - $400. For example, the Smiling Coin tile is "Tile 0x4C2", which results in TTT = $4C2 - $400 = $0C2. So, for example, to reserve that tile and use palette F, the full value will be $F0C2.

75 |

If an item's value is $0000, the item will simply not be displayed.

76 |

Note that you can also just write the $PTTT value to the RAM address for a specific item yourself, this routine is just a shorthand so set all values at the same time. To see the RAM addresses names, see RAM Info.

77 | 94 |
95 | 96 |

Get Retry type

97 |

Routine to get the current Retry type, i.e. if currently the level is set to have Retry prompt, instant Retry or no Retry.

98 | 113 |
114 | 115 |

Get SRAM variable address

116 |

Routine to get the address in SRAM for a specific variable. By "variable" it's meant any of the RAM addresses that are saved to SRAM specified in the sram save table. The returned address will be coherent with the current save file loaded when this routine is called (so, make sure to not call it before a save file is loaded!).

117 |

This could be useful to read/write values in SRAM directly, for example if you need to update some SRAM value without the game being saved.

118 |

Note that if you call this on the title screen (for example, if you need to display something based on some value saved in the three files), you will need to set $010A to the value of the save file you want to check (0 for save file 1, 1 for save file 2, 2 for save file 3) before calling this.

119 |

NOTE: this will always return "variable not found" if !sram_feature = 0.

120 | 143 | 144 |
Return to main page
145 | 146 | 147 | -------------------------------------------------------------------------------- /docs/extra.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Retry Extra Settings - Retry System UberASM 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Retry Extra Settings

12 |

The Retry system can be configured to run additional code at specific times when inserted into the routines available in the retry_config/extra.asm file.

13 | 14 |

On SA-1 ROMs, most of these routines still run on the SNES CPU.

15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 28 | 31 | 32 | 33 | 34 | 37 | 38 | 39 | 40 | 44 | 45 | 46 | 47 | 50 | 51 | 52 | 53 | 58 | 59 | 60 | 61 | 65 | 66 | 67 | 68 | 72 | 73 | 74 | 75 | 80 | 81 | 82 | 83 | 89 | 90 |
RoutinePurpose
reset 23 | Called when the level is reset by the retry system or when entering from the overworld. Unlike UberASM level init routine, this won't be executed during regular level transitions. 24 |
death 29 | This routine will be executed everytime the player dies. 30 |
midway 35 | This routine will be called every time the player touches a midway (vanilla or custom midway object). 36 |
room_checkpoint 41 | This routine will be called every time the player gets a checkpoint through a room transition. 42 | Remember you can check for $13BF and $010B to know in which trans/sub-level you are. 43 |
prompt_exit 48 | This routine will be called every time the player selects "exit" on the retry prompt. 49 |
save_file 54 | This routine will be called every time the game is saved (before anything gets saved). 55 | Remember that you can check for the current save file in $010A. 56 | On SA-1 ROMs, this may run on either CPU, depending on what's calling the save routine. 57 |
load_file 62 | This routine will be called every time an existing save file is loaded (before anything gets loaded). 63 | Remember that you can check for the current save file in $010A. 64 |
load_new_file 69 | This routine will be called every time a new save file is loaded (before anything gets reset). 70 | Remember that you can check for the current save file in $010A. 71 |
game_over 76 | This routine will be called during the game over screen. 77 | This is called after the save file data is loaded from SRAM (only the data put before .not_game_over in retry_config/sram_tables.asm) but before all the data is saved again to SRAM. 78 | This can be useful if you want to initialize some addresses for the game over and/or have them saved to SRAM. 79 |
door_animation 84 | Called when Mario enters a door, every frame during the fade out. This could be useful since the door animation is the only one that can't be intercepted 85 | with level ASM or sprite ASM (since it immediately goes to the fading gamemode). 86 | If you need some level-specific action here, you can check the sublevel number in $010B (16 bit). 87 | If you need to only run the code for 1 frame, you can check for $0DB0 equal to 0. 88 |
91 |

92 | All these routines are called in 8-bit A/X/Y mode and DBR is already set. Don't worry about overwriting registers, they'll be restored afterwards (except for direct page). All the routines must end with RTS. 93 |

94 |
95 |
Return to main page
96 | 97 | 98 | -------------------------------------------------------------------------------- /docs/faq.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Frequently Asked Questions - Retry System UberASM 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |

Frequently Asked Questions

14 |
15 | 16 |

Q: Can I insert this in a ROM where I've already inserted worldpeace's Retry patch?

17 |

A: No, doing so will result in an error when running UberASM Tool. First, you need to remove the original patch: either try to use the Unpatcher tool (at your own risk) or port your hack over to a new ROM.

18 |
19 | 20 |

Q: I noticed that you don't lose lives when dying/retrying a level. Is it possible to change that?

21 |

A: Yes. If you want to disable infinite lives, you can use the !infinite_lives global setting (see Global Settings - Quality of Life Settings). If you want to keep infinite lives just for specific levels, you can do so using the %no_lose_lives local setting (see Local Settings - %no_lose_lives).

22 |
23 | 24 |

Q: Can I give the player a checkpoint automatically when entering a level?

25 |

A: Yes. Look at the Local Settings - %checkpoint page.

26 |
27 | 28 |

Q: Can I change the prompt type in specific sublevels?

29 |

A: Yes. Look at the Local Settings - %retry page.

30 |
31 | 32 |

Q: I saw some hacks use a different sound effect when dying. How do I change that?

33 |

A: You can do so with the !death_sfx option in settings_global.asm (see Global Settings - SFX for details). You can also find a custom death sfx file that replicates the vanilla death music intro under amk_resources/sfx (see AddmusicK Resources for details).

34 |
35 | 36 |

Q: Can I change the prompt type in specific situations (not necessarily on a sublevel basis)?

37 |

A: Yes. Additionally to the effect table, there's the !ram_prompt_override address that, when set, will replace both the table and the default option (see retry_config/ram.asm and RAM Map).

38 |

For example, you could use it to let the player choose the prompt type as they want (you still have to implement that, though, as this only handles setting the prompt type). 39 |

Note that this address by default is never reset outside of title screen load.

40 |
41 | 42 |

Q: Can I keep the Retry prompt but remove the black box?

43 |

A: Yes. Look at !no_prompt_box in retry_config/settings_global.asm. You can also remove it only under certain circumstances by setting !ram_disable_box to 1 (for more info, see retry_config/ram.asm and RAM Map). For example, you can do it in a Level ASM init to make a level not have the option.

44 |

Note that this address by default is never reset outside of title screen load.

45 |
46 | 47 |

Q: Can I keep the Retry prompt but remove the "exit" option?

48 |

A: Yes. Look at !no_exit_option in retry_config/settings_global.asm. You can also remove it only under certain circumstances by setting !ram_disable_exit to 1 (for more info, see retry_config/ram.asm and RAM Map). For example, you can do it in a Level ASM init to make a level not have the option.

49 |

Note that this address by default is never reset outside of title screen load.

50 |
51 | 52 |

Q: Can I change where the prompt is shown on the screen?

53 |

A: Yes. Look at !text_x_pos and !text_y_pos in retry_config/settings_global.asm. For example, using !text_x_pos = $08 and !text_y_pos = $D0 will place it on the lower left corner of the screen.

54 |

Additionally, you can also change it at runtime by writing to the !ram_prompt_x_pos and !ram_prompt_y_pos addresses (see RAM Map for more info). 55 |

Either way, if you want to change it you should disable the Retry box (either by setting !no_prompt_box = 1 or by writing to !ram_disable_box at runtime) as its position can't be changed easily. 56 |

57 |
58 | 59 |
Return to main page
60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /docs/files.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Files - Retry System UberASM 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Files

12 | 13 | 14 |

Contents

15 | 20 |
21 | 22 |

AddmusicK Resources

23 |

Inside the amk_resources folder you can find a custom a custom SFX file (amk_resources/sfx/Death Prelude.txt) and a custom death music file (amk_resources/music/01 Miss (no intro).txt). These can be used to keep a vanilla-feeling sound on death with Retry enabled.

24 |

The SFX is the intro to the vanilla death music, and it is recommended to use as the Retry death SFX. To do so, insert it as any other SFX in AddmusicK: move the txt file inside AMK's 1DFC folder, then add it as a new entry in the Addmusic_sound effects.txt file under SFX1DFC. To configure Retry to play this SFX on death, in settings_global.asm change !death_sfx to the value you used in Addmusic_sound effects.txt, and set !death_sfx_addr = $1DFC.

25 |

The music file is the vanilla death jingle but with the initial part removed (the part that is played in the custom SFX provided here). This can be used as an alternative death jingle for when choosing "Exit" in the Retry prompt: normally this plays the vanilla death jingle, but it might be weird to replay the death SFX part of it, so you can insert this alternative variant in your Addmusic_list.txt and configure Retry to play that only when using "Exit". To do so, change !death_jingle_alt in settings_global.asm to the number you inserted it as in AMK's list. Note that you shouldn't insert this as a global song.

26 |
27 | 28 | 31 | 32 |

Graphics

33 |

The graphic files used by Retry can be found in the retry_config/gfx folder. Note that these are uploaded dynamically to the sprite GFX pages when needed, so you don't need to insert them yourself in your GFX files, but you're free to edit them with tools like YY-CHR if you so wish (they're all 4bpp files).

34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 |
FilePurposeDefault Palette
letters1.binRetry prompt letters used in the prompt when !no_prompt_box = 08
letters2.binRetry prompt letters used in the prompt when !no_prompt_box = 18
coins.binTwo 8x8 tiles used by the sprite status bar coin counters (the first is used by the coin counter, the second by the Dragon Coin counter).8
digits.binNumbers used by the sprite status bar timer and coin counterAny
indicator.binSingle 8x8 tile used by the retry indicator9
item_box_8x8.binSingle 8x8 tile used to draw the smaller Item BoxB
item_box_16x16.binFour 8x8 tiles used to draw the full Item BoxB
timer.binSingle 8x8 tile used for the sprite status bar timer icon8
lives.binTwo 8x8 tile used for the sprite status bar lives counter icon (the first is used for Mario, the second for Luigi)9
bonus_stars.binSingle 8x8 tile used for the sprite status bar bonus stars counter icon9
91 |
92 | 93 |
Return to main page
94 | 95 | 96 | -------------------------------------------------------------------------------- /docs/getting_started.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Getting Started - Retry System UberASM 5 | 6 | 7 | 8 | 9 | 10 | 24 | 25 |

Getting Started

26 |

This section will help install the Retry System for your project.

27 | 28 |

Contents

29 | 35 |
36 | 37 |

Download UberASM Tool

38 |

The first step is to download UberASM Tool, which is the tool used to insert Retry and many other resources. Note that you need to use UberASM Tool version 2.0 or higher to insert Retry.

39 |
40 | 41 |

Copy Retry Files into Project

42 |

Now that you have UberASM Tool, you'll need to copy the Retry files into it.

43 |

Inside the main folder you can find the retry_install.bat file, which will do all the copying for you. Just double click it, and then drag and drop your UberASM Tool folder inside the terminal window that pops up. After that, the script will copy all the files in your folder, and you should see a success message. Additionally, if Retry was already present in your UberASM Tool folder, the script will backup up its files in a separate retry_old_backup folder, in case you need to port your settings from the previous version (feel free to delete this folder afterwards).

44 |

If you instead want to do it manually, follow these steps:

45 | 50 |

After running the script or copying the files manually, your UberASM Tool folder structure should look like this: 51 |

52 |
UberASM Tool Folder 53 | ├─ asm 54 | ├─ gamemode 55 | └─ retry_gm*.asm 56 | ├─ level 57 | ├─ library 58 | └─ retry.asm 59 | ├─ other 60 | ├─ overworld 61 | ├─ retry_config 62 | ├─ retry_old_backup (only present if old Retry backed up by install script) 63 | ├─ routines (only present in UberASM Tool 2.0+) 64 | ├─ ... 65 |
66 |
67 |

68 |
69 | 70 |

Insert Files with UberASM Tool

71 |

Now that the Retry files are in place, you need to tell UberASM Tool to insert them in your rom.

72 | 95 |
96 | 97 |

Further Steps

98 |

Now Retry is inserted in your rom, so if you start a new game and die in a level, you should see the Retry prompt pop up (since it is the default configuration). To customize it, you need to edit the configuration files in the retry_config folder. When you make changes, you can just run UberASM Tool again to see them applied in the game.

99 |

For more information about the customization options, check out the Configuration section.

100 | 101 |
Return to main page
102 | 103 | 104 | -------------------------------------------------------------------------------- /docs/hijack_map.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Hijack Map - Retry System UberASM 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Retry Hijack Map

12 |

While this version of the Retry System mostly uses UberASM Tool code to run, it still requires some hijacks for some functions that cannot be achieved otherwise. These hijacks are inserted automatically when inserting UberASM Tool, and they can be removed with the provided src/retry_unpatch.asm file if you need to remove Retry from your rom (see Uninstalling Retry for details).

13 |

If you're experiencing game crashes or weird problems after inserting some other patch, you can check here if there are conflicting hijacks with Retry, although that should be pretty rare compared to the old Retry patch which had much more frequent resource conflicts.

14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 86 | 87 | 88 | 89 | 90 | 94 | 95 | 96 | 97 | 98 | 102 | 103 | 104 | 105 | 106 | 110 | 111 | 112 | 113 | 114 | 118 | 119 | 120 | 121 | 122 | 126 | 127 | 128 | 129 | 130 | 134 | 135 | 136 | 137 | 138 | 142 | 143 | 144 | 145 | 146 | 150 | 151 | 152 | 153 | 154 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 |
AddressSizeDescription
$009E251Changes how many lives the save file starts with.
$05B31B2Fixes a bug where some sprite tiles disappear when closing a message box.
$00D0D85Disables the vanilla life loss code. It is equivalent to the infinite lives patch found on SMWCentral.
$008E5B4Sets a flag used by Retry when the "hurry up" effect happens. This hijack is also used by the "Individual Dragon Coins Save" patch to check for the presence of Retry in the rom.
$05DA1C4Fixes the initial sprite facing position and the "No Yoshi Sign 2" castle intro being forced for some levels. Depending on the values of !initial_facing_fix and !no_yoshi_intro_fix, this may be a JML or just a hex edit.
$00C5724Fixes being able to drop the item in reserve while Mario is dead. Depending on the value of !item_box_fix, this may be a JML or just a hex edit to restore the original code.
$0DA4154 55 | If !use_custom_midway_bar = 1, this inserts code to handle Retry's custom midway objects.
56 | If !use_custom_midway_bar = 0, this restores the original code (only the first time the setting is changed, and only if Objectool is present in the rom). 57 |
$05D8424Makes sure to load in the correct entrance when entering a level from the Overworld, depending on the level's last reached checkpoint.
$05D9DA4Makes sure to load in the correct entrance when loading the midway entrance of a level, depending on the sublevel's checkpoint setting.
$05D9EC4Makes sure to load Mario at the correct position when a checkpoint is a vanilla midway entrance.
$05DAA34Fixes a bug when loading a secondary entrance in a level with a "No Yoshi Intro" from the Overworld.
$008F494 83 | If !status_death_counter = 1, this writes the death counter in the status bar.
84 | If !status_death_counter = 0, it restores the original code (only the first time the setting is changed to 0). 85 |
$008C8912 91 | If !status_death_word = 1, it changes the status bar tilemap to show "DEATHS" instead of "MARIO".
92 | If !status_death_word = 0, it restores the original tilemap but only the first time that !status_death_counter is changed to 0. 93 |
$0081F43 99 | If !remove_vanilla_status_bar = 1, disables code to draw the vanilla status bar in normal levels.
100 | If !remove_vanilla_status_bar = 0, it restores the original code (only the first time the setting is changed to 0). 101 |
$0082755 107 | If !remove_vanilla_status_bar = 1, disables code to enable the vanilla status bar IRQ.
108 | If !remove_vanilla_status_bar = 0, it restores the original code (only the first time the setting is changed to 0). 109 |
$0082E83 115 | If !remove_vanilla_status_bar = 1, disables code to draw the vanilla status bar in mode 7 levels.
116 | If !remove_vanilla_status_bar = 0, it restores the original code (only the first time the setting is changed to 0). 117 |
$00985A3 123 | If !remove_vanilla_status_bar = 1, disables code to setup the initial vanilla status bar tilemap in mode 7 levels.
124 | If !remove_vanilla_status_bar = 0, it restores the original code (only the first time the setting is changed to 0). 125 |
$00A5A83 131 | If !remove_vanilla_status_bar = 1, disables code to setup the initial vanilla status bar tilemap in normal levels.
132 | If !remove_vanilla_status_bar = 0, it restores the original code (only the first time the setting is changed to 0). 133 |
$00FFD81 139 | If !sram_feature = 1 and SA-1 is not patched, it sets the SRAM size to 8KB (unless the SRAM size was already set to a bigger size by some other patch).
140 | If !sram_feature = 0 and SA-1 is not patched, is sets the SRAM size back to 2KB (unless the SRAM size was already set to a bigger size by some other patch). 141 |
$009BCB4 147 | If !sram_feature = 1, makes sure to save the addresses in Retry's save table to SRAM/BW-RAM whenever the game is saved.
148 | If !sram_feature = 0, it restores the original code (only the first time the setting is changed to 0). 149 |
$009CF54 155 | If !sram_feature = 1, makes sure to load the addresses in Retry's save table from SRAM/BW-RAM whenever the save file is loaded, or to load the values in Retry's sram_default table whenever a new save file is started.
156 | If !sram_feature = 0, it restores the original code (only the first time the setting is changed to 0). 157 |
$0098564Makes sure some of Retry's code is run during level load for vanilla mode 7 bosses.
$00F2D84Makes sure vanilla midways set the proper checkpoint depending on the current sublevel's settings, and prevents getting a mushroom at the midway if !midway_powerup = 0.
$0DA6914Makes sure to spawn or not spawn the midway bar object at level load depending on the current checkpoint.
$05B30E4Fixes a bug where the switch palace message boxes sprites become glitched if drawing sprites in UberASM Tool's 2.0 "end" label.
180 | 181 |
Return to main page
182 | 183 | 184 | -------------------------------------------------------------------------------- /docs/img/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kkevinm/retry-system/4b1bea10675012a8e471574675489a8723252fb2/docs/img/icon.png -------------------------------------------------------------------------------- /docs/img/insert_object.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kkevinm/retry-system/4b1bea10675012a8e471574675489a8723252fb2/docs/img/insert_object.png -------------------------------------------------------------------------------- /docs/img/midway_object.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kkevinm/retry-system/4b1bea10675012a8e471574675489a8723252fb2/docs/img/midway_object.png -------------------------------------------------------------------------------- /docs/img/multiple_midway_$00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kkevinm/retry-system/4b1bea10675012a8e471574675489a8723252fb2/docs/img/multiple_midway_$00.png -------------------------------------------------------------------------------- /docs/img/multiple_midway_$01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kkevinm/retry-system/4b1bea10675012a8e471574675489a8723252fb2/docs/img/multiple_midway_$01.png -------------------------------------------------------------------------------- /docs/img/multiple_midway_$02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kkevinm/retry-system/4b1bea10675012a8e471574675489a8723252fb2/docs/img/multiple_midway_$02.png -------------------------------------------------------------------------------- /docs/img/multiple_midway_$03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kkevinm/retry-system/4b1bea10675012a8e471574675489a8723252fb2/docs/img/multiple_midway_$03.png -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Readme - Retry System UberASM 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Retry System UberASM

12 |

The Retry System is a useful patch for both Kaizo hacks and generally hard hacks, as its primary function is to enable fast level reloading to skip going to the Overworld everytime the player dies (similarly to games like Super Meat Boy).

13 |

This package is a spiritual successor of the original Retry patch made by worldpeace, to expand its capabilities and to make it compatible with more resources as a consequence of it being primarily a UberASM resource.

14 |
15 | 16 |

Help & Getting Started

17 |

To get started using this on your project, check out the "Getting Started" page.

18 | 21 |

For some helpful general information, check out the following pages.

22 | 26 |

If you have additional questions or problems, you can PM me on SMW Central (Kevin) or DM me on Discord (kkevinm). Please make sure you have read this documentation carefully, and tried to solve the problem on your own first, before contacting me.

27 |
28 | 29 |

Configuration

30 |

The Retry System can be configured in a lot of ways, from basic general settings, to level specific settings, to more nuanced options for advanced users.

31 |

All the configuration files you can edit can be found in the retry_config folder and include some comments on how to use them and what they can do, but you can read more in depth explanation for each file below.

32 | 39 |

You can edit the files in the retry_config/code folder (which contains all the source code) to change the retry but this is not recommended unless you know exactly what you're doing.

40 |
41 | 42 |

Multiple Midways

43 |

The Retry system also provides for multiple level midways, both as midway objects and automatic midways on level entrance, and many more features. Read how to configure this feature at the following link.

44 | 47 |
48 | 49 |

Other Information

50 |

For other information, check out the following pages.

51 | 58 |
59 | 60 | 61 | -------------------------------------------------------------------------------- /docs/midway_instruction.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Setting up Multiple Midways - Retry System UberASM 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Setting up Multiple Midways

12 | 13 |

Inserting the Midway Bar Object in Lunar Magic

14 |

While in Layer 1 or Layer 2 editing mode, open the manual object insertion window either by pressing Insert, or via the menu: Edit > Insert manual....

15 | 16 |

The custom midway object is inserted into your ROM as 2D and this value goes in the Command field of this dialog.

17 | 18 |

Respawn Location

19 |

To change where Mario will respawn after collecting this midway, you will set a 4-digit value in the Extension Field. The value put here will dictate the entrance type as well as either the level number or a secondary entrance number where Mario will respawn.

20 | 26 | *This is obsolete in Lunar Magic 3.00+ 27 |

Keep in mind some values will need leading zeroes to work correctly, e.g. respawning at secondary entrance 12C would be 012C and not 12C.

28 |
Note: some of these settings can be used to make a midway respawn a player in any place in the game not just within the same level or connected sublevels.
29 |

Once inserted, it will appear in Lunar Magic as a green square, but will appear as the normal Midway Tape object in-game.

30 | 31 |
32 | 33 |

Multiple Midway Options in Retry System

34 |

The retry system has a per-level configuration setting for midways (see Local settings - %checkpoint for details), which sets the behavior of midways bars and level entrances in the specified sublevel.

35 | 36 |

Using the %checkpoint instruction in settings_local.asm you can set the midway behaviour, for each and every sublevel, with the one of following values:

37 | 43 |

Note: this setting can be used in conjunction with the midway objects detailed above.

44 | 45 |

Examples

46 |

47 | 48 | 49 | 50 | 51 |
Return to main page
52 | 53 | 54 | -------------------------------------------------------------------------------- /docs/objectool_info.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ObjecTool Information - Retry System UberASM 6 | 7 | 8 | 9 | 10 | 11 | 12 |

ObjecTool Information

13 |

If you want to insert custom objects using the ObjecTool patch, and you're using Retry's Custom Midway Object feature (!use_custom_midway_bar = 1 in the settings) you'll need to make an edit before inserting the patch.

14 |

Open objectool.asm and remove these lines (they're towards the top of the file):

15 | 16 |
17 | org $0DA415|!bank                   ; x6A615 (hijack normal object loading routine)
18 | 	autoclean JML NewNormObjects    ; E2 30 AD 31 19
19 | 	NOP                             ;
20 | 
21 | 22 |

After doing this, just patch objectool.asm.

23 | 24 |

One thing to keep in mind is that Retry will use slots 00-41 and 50-51 of the Custom Normal Objects (i.e., objects with id 2D) for its custom midway bars, meaning that you can't use them in ObjecTool.

25 |

You're free to use Custom Normal Objects 42-4F and 52-FF, as well as all Custom Extended Objects available.

26 | 27 |

Additionally, if you want to remove Retry's custom midway bar while keeping ObjecTool, you'll need to place back the code that you removed in objectool.asm (and make sure you run Retry with !use_custom_midway_bar = 0).

28 |
Return to main page
29 | 30 | 31 | -------------------------------------------------------------------------------- /docs/settings_local.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Local Settings - Retry System UberASM 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Local Retry Settings

12 |

Local settings are those Retry options that can be configured on a level-specific basis. These options must be inserted in the retry_config/settings_local.asm file. If you used older version of Retry, these are equivalent to the various tables you had to change the values of, but made simpler by not having to manage big tables of hex data.

13 |

If you still prefer the table approach, you can set !use_legacy_tables = 1 in settings_global.asm and edit the tables in legacy/tables.asm as you're used to. In this case, ignore this document and the settings_local.asm file.

14 |
15 | 16 |

Overview

17 |

This approach of configuring the level-specific settings uses instructions that enable some setting for a specified level number. Each instruction must be put on a separate line in the asm file.

18 |

There are various instruction types, but most times you'll probably only use one or two of them for any given level, if any.

19 |

The instruction types are the following:

20 | 21 | 31 |
32 | 33 |

%checkpoint(level, value)

34 |

This allows you to configure the checkpoint behavior for the specified level. value can have one of the following values:

35 | 41 |

If this option isn't specified for a level, then it will default to 0 (vanilla checkpoint behavior).

42 |

Examples:

43 | 47 |

Note that you can also use custom midway objects (that look like vanilla midway bars) to have multiple midways. See Custom Midway Instructions for more information.

48 |
49 | 50 |

%retry(level, value)

51 |

This allows to override the Retry type for the specified level. value can have one of the following values:

52 | 59 |

If this option isn't specified for a level, then it will default to 0 (follow the global setting).

60 |

Examples:

61 | 66 |
67 | 68 |

%checkpoint_retry(level, checkpoint, retry)

69 |

This is a shorthand to configure the checkpoint and Retry type for a level with the same instruction. checkpoint follows the %checkpoint format and retry follows the %retry format.

70 |

Examples:

71 | 75 |
76 | 77 |

%sfx_echo(level)

78 |

This will enable SFX echo in the specified sublevel. Note that this option only works if AddmusicK is used in the ROM, and the SFX uses the same echo as the music (if the music has no echo, then the SFX also won't have echo).

79 |

Examples:

80 | 83 |
84 | 85 |

%no_reset_rng(level)

86 |

Normally Retry resets the RNG seed every time a level is reloaded, to make setups consistent between deaths. Using this option will make the RNG not reset when retrying in this sublevel.

87 |

Examples:

88 | 91 |
92 | 93 |

%no_room_cp_sfx(level)

94 |

If a level uses the checkpoint type 2 or 3, then a SFX is played when the automatic checkpoint is triggered (the SFX is defined by !room_cp_sfx in settings_global.asm).

95 |

If you use this, then the automatic checkpoints in the specified sublevel won't have any SFX. If !room_cp_sfx = 0, you can ignore this.

96 |

Examples:

97 | 100 |
101 | 102 |

%no_lose_lives(level)

103 |

If infinite lives is disabled (!infinite_lives = 0 in settings_global.asm), you can prevent life loss in specific sublevels using this option (for example for tutorial rooms or cutscenes).

104 |

If !infinite_lives = 1, you can ignore this.

105 |

Examples:

106 | 109 |
110 | 111 |

%settings(level, checkpoint, retry, sfx_echo, no_reset_rng, no_room_cp_sfx, no_lose_lives)

112 |

This is a shorthand to configure all the settings for the specified level at the same time.

113 |

The arguments are:

114 | 123 | 124 |
Return to main page
125 | 126 | 127 | -------------------------------------------------------------------------------- /docs/sram_bwram_info.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SRAM & BW-RAM Information - Retry System UberASM 5 | 6 | 7 | 8 | 9 | 10 | 11 |

SRAM & BW-RAM Information

12 | 13 |

As the standard Retry patch, this Retry includes a built-in SRAM expansion patch that's used by default to save the custom checkpoints and death counter. Differently from the normal Retry, the patch also works on SA-1 (using BW-RAM instead of SRAM, but the result is the same), so this can be effectively used as an alternative to the SRAM/BW-RAM Plus patch and the likes.

14 |

If you've already patched SRAM/BW-RAM Plus, this feature will be turned off automatically (they can't coexist). Unlike SRAM Plus, this patch should also work on SNES Classic, so you should use it if you care about compatibility with that console. Also, the maximum amount of bytes you can save per save file is 2389 bytes.

15 | 16 |

Q: How do I add my own addresses to the save tables?

17 | 18 |

Open retry_config/sram_tables.asm and go to the save table. There, you can add your own addresses to save (more info in the file). Similarly to SRAM/BW-RAM Plus, for each address you put in the table, you also need to specify its default value(s) for when a new save file is loaded in the sram_defaults tables.

19 | 20 |

Some examples of addresses that may be useful (you can find more at SMW Central's RAM Map):

21 | 22 |
23 | ; 1-UP checkpoints flags.
24 | dl $7E1F3C : dw 12      ; $401F3C on SA-1.
25 | 
26 | ; 5 Dragon Coins collected flags.
27 | dl $7E1F2F : dw 12      ; $401F2F on SA-1.
28 | 
29 | ; Individual Dragon Coin Save patch tables. If you use that patch, you should include these.
30 | dl $7E1F2F : dw 12      ; $401F2F on SA-1.
31 | dl $7FA660 : dw $0300   ; $40A660 on SA-1.
32 | 
33 | 34 | (For all of these, the default values need to be all $00). 35 | 36 |

Q: I'm using SRAM/BW-RAM Plus and I want to save Retry's stuff with them. How do I do it?

37 |

A: If you really need to use those, then you can add these to the sram_table/bw_ram_table:

38 | 39 |
40 | dl !ram_checkpoint    : dw 192
41 | dl !ram_death_counter : dw 5
42 | 
43 | 44 |

Note: to have the Retry ram defines available in the patch, copy the contents of retry_config/ram.asm at the top of the SRAM+/BW-RAM+ table file. Also, if you're not using the death counter, you can omit the second line.

45 | 46 |

Then add these tables to the sram_defaults/bw_ram_defaults:

47 | 48 |
49 | ; Checkpoints.
50 | dw $0000,$0001,$0002,$0003,$0004,$0005,$0006,$0007
51 | dw $0008,$0009,$000A,$000B,$000C,$000D,$000E,$000F
52 | dw $0010,$0011,$0012,$0013,$0014,$0015,$0016,$0017
53 | dw $0018,$0019,$001A,$001B,$001C,$001D,$001E,$001F
54 | dw $0020,$0021,$0022,$0023,$0024,$0101,$0102,$0103
55 | dw $0104,$0105,$0106,$0107,$0108,$0109,$010A,$010B
56 | dw $010C,$010D,$010E,$010F,$0110,$0111,$0112,$0113
57 | dw $0114,$0115,$0116,$0117,$0118,$0119,$011A,$011B
58 | dw $011C,$011D,$011E,$011F,$0120,$0121,$0122,$0123
59 | dw $0124,$0125,$0126,$0127,$0128,$0129,$012A,$012B
60 | dw $012C,$012D,$012E,$012F,$0130,$0131,$0132,$0133
61 | dw $0134,$0135,$0136,$0137,$0138,$0139,$013A,$013B
62 | 
63 | ; Death counter.
64 | db $00,$00,$00,$00,$00
65 | 
66 | 67 |

Note: if you omitted the death counter in the previous table, then do it here too.

68 | 69 |
Return to main page
70 | 71 | 72 | -------------------------------------------------------------------------------- /docs/sram_tables.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Save & SRAM Tables - Retry System UberASM 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Save & SRAM Tables

12 |

The Retry System has a built-in saving system. You can configure what addresses it saves by editing two tables in retry_config/sram_tables.asm.

13 |

Save (SRAM) Table

14 |

This table can be used to save custom values to SRAM, so they can persist when the console is turned off. By default it saves the custom checkpoint ram (so multiple midways will save properly) and the death counter.

15 |
16 | save:
17 | 	dl !ram_checkpoint    : dw 192
18 | 	; Feel free to add your own stuff here.
19 | 
20 | .not_game_over:
21 | 	dl !ram_death_counter : dw 5
22 | 	; Feel free to add your own stuff here.
23 | 
24 |

Each line is formatted as follows:

25 |
26 | 	dl $XXXXXX : dw $YYYY
27 | 
28 |

Where $XXXXXX is what RAM address to save. Make sure it's always 3 bytes long (i.e. use $7E0019 instead of $19 or $0019) and $YYYY is how many bytes to save at that address (remove the $ to use a decimal value).

29 |

For example, adding dl $7E1F3C : dw 12 will make the 1-Up checkpoints for all levels save. Make sure to always put a colon between the two elements!

30 |

The addresses you put under .not_game_over will be saved like usual, but they won't be reloaded from SRAM when getting a game over. This can be useful if you want some things to retain even if the player got a game over before being able to save them.

31 |
32 | 33 |

New Save Table

34 |

Here you specify the "default" values of the addresses you want to save, for when a new save file is started.

35 |
36 | sram_defaults:
37 | 	; Default checkpoint values (don't edit this!).
38 | 	dw $0000,$0001,$0002,$0003,$0004,$0005,$0006,$0007
39 | 	dw $0008,$0009,$000A,$000B,$000C,$000D,$000E,$000F
40 | 	dw $0010,$0011,$0012,$0013,$0014,$0015,$0016,$0017
41 | 	dw $0018,$0019,$001A,$001B,$001C,$001D,$001E,$001F
42 | 	dw $0020,$0021,$0022,$0023,$0024,$0101,$0102,$0103
43 | 	dw $0104,$0105,$0106,$0107,$0108,$0109,$010A,$010B
44 | 	dw $010C,$010D,$010E,$010F,$0110,$0111,$0112,$0113
45 | 	dw $0114,$0115,$0116,$0117,$0118,$0119,$011A,$011B
46 | 	dw $011C,$011D,$011E,$011F,$0120,$0121,$0122,$0123
47 | 	dw $0124,$0125,$0126,$0127,$0128,$0129,$012A,$012B
48 | 	dw $012C,$012D,$012E,$012F,$0130,$0131,$0132,$0133
49 | 	dw $0134,$0135,$0136,$0137,$0138,$0139,$013A,$013B
50 | 	; Feel free to add your own stuff here.
51 | 
52 | .not_game_over:
53 | 	; Initial death counter value (don't edit this!).
54 | 	db $00,$00,$00,$00,$00
55 | 
56 | 	; Feel free to add your own stuff here.
57 | 
58 | 59 |

You can do db $XX,$XX,... for 1 byte values, dw $XXXX,$XXXX,... for 2 bytes values and dl $XXXXXX,$XXXXXX,... for 3 bytes values.

60 |

The amount of values of each entry should correspond to the dw $YYYY value in the save table (for example, the checkpoint values are 192, and the death counter values are 5).

61 |

Remember, if you have some addresses after .not_game_over in the save: table, put their default values after .not_game_over here also, in the same order.

62 | 63 |
64 | 65 |

Notes

66 | 71 |
72 | 73 |
Return to main page
74 | 75 | 76 | -------------------------------------------------------------------------------- /docs/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | max-width: 800px; 3 | margin: 0 auto; 4 | padding: 2em; 5 | padding-bottom: 4em; 6 | font-family: Arial, sans-serif; 7 | font-size: 1em; 8 | } 9 | body.wide { 10 | max-width: 1024px; 11 | } 12 | 13 | p, li, th, td { 14 | line-height: 140%; 15 | } 16 | 17 | 18 | pre { 19 | font-size: 1.09em; 20 | padding: 8px 16px; 21 | background: rgba(0, 0, 0, 0.05); 22 | color: rgba(0, 0, 0, 0.6); 23 | border-radius: 3px; 24 | user-select: all; 25 | line-height: 1.3; 26 | } 27 | 28 | u.dir, 29 | code { 30 | font-size: 1.09em; 31 | padding: 2px 3px; 32 | background: rgba(0,0,0,.05); 33 | border-radius: 2px; 34 | } 35 | 36 | u.dir { 37 | text-decoration: none; 38 | font-family: monospace; 39 | } 40 | 41 | blockquote { 42 | font-style: italic; 43 | } 44 | table { 45 | width: 100%; 46 | margin: 1em 0; 47 | border-collapse: collapse; 48 | text-align: center; 49 | } 50 | th { 51 | background-color: rgba(0,0,0,.05); 52 | font-size: 0.93em; 53 | } 54 | td,th { 55 | border: 1px solid rgba(0,0,0,.15); 56 | padding: 4px 8px; 57 | } 58 | td.has-table > table { 59 | margin-bottom: 0; 60 | } 61 | 62 | .left-align { 63 | text-align: left; 64 | } 65 | 66 | .right-align { 67 | text-align: right; 68 | } 69 | 70 | .center-align { 71 | text-align: center; 72 | } 73 | 74 | img { 75 | margin: 20px auto; 76 | max-width: 800px; 77 | display: block; 78 | } 79 | 80 | ul li { 81 | margin: 4px 0; 82 | } 83 | 84 | hr { 85 | background: rgba(0,0,0,.1); 86 | height: 1px; 87 | border: none; 88 | margin: 2em 0; 89 | } 90 | -------------------------------------------------------------------------------- /docs/troubleshooting.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Troubleshooting - Retry System UberASM 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Troubleshooting

12 |
13 | 14 |

Q: I applied a FG gradient code, and it appears above the Retry prompt as well!

15 |

A: You need to make a slight edit to the HDMA code. You should see something like this:

16 | 17 |
 18 | LDA #$17
 19 | STA $212C
 20 | LDA #$00
 21 | STA $212E
 22 | 
23 | 24 |

Change that to:

25 | 26 |
 27 | LDA #$17
 28 | STA $212C
 29 | LDA #$17	;<- change here
 30 | STA $212E
 31 | 
32 | 33 |
34 | 35 |

Q: I'm making the music in a level fade out using the following code (with AddmusicK) but the music doesn't reload when dying!

36 | 37 |
 38 | LDA #$FF
 39 | STA $1DFB|!addr
 40 | 
41 | 42 |

A: You want to also store #$FF to $0DDA, like this:

43 | 44 |
 45 | LDA #$FF
 46 | STA $1DFB|!addr
 47 | STA $0DDA|!addr	;<- change here
 48 | 
49 | 50 |
51 |

Q: When dying after getting the goal post or beating a boss, the music doesn't restart when respawning!

52 |

A: One common cause for this is a bug with AddmusicK that happens when you change certain songs to #$00 in the asm/tweaks.asm (or asm/UserDefines.asm) file, specifically: !Miss, !BossClear, !StageClear, !Keyhole or !IrisOut (maybe also !SwitchPalace, !RescueEgg and !StaffRoll). This can cause issues like the one mentioned here or the P-Switch/Star timers acting weirdly when activated

53 |

To fix this, open AMK's asm/SNES/patch.asm file and remove all instances of codes like this:

54 | 55 |
 56 | CMP !SongThatYouChangedTo0
 57 | BEQ Something
 58 | 
59 | 60 |

For example, if you changed !IrisOut to #$00, then you'd remove these codes (you can CTRL+F !IrisOut to find all instances in the file):

61 | 62 |
 63 | CMP !IrisOut
 64 | BEQ ++
 65 | 
66 |
 67 | CMP !IrisOut
 68 | BEQ LevelEndMusicChange
 69 | 
70 |
 71 | CMP !IrisOut
 72 | BEQ Okay
 73 | 
74 | 75 |

Run AddmusicK after applying the changes and the issue should be fixed. If it still happens but you didn't change the tweaks/UserDefines file, then DM me the issue.

76 |
77 | 78 |

Q: I'm using the "Single Screen" UberASM code, and sprites keep moving while Mario is dead!

79 |

A: To fix, add this code at the very start of the Single Screen's main code:

80 | 81 |
 82 |     LDA $71
 83 |     CMP #$09
 84 |     BNE +
 85 |     RTL
 86 | +
 87 | 
88 | 89 | 90 |
91 |

Q: When I enter a level from the overworld, it brings me to the bonus game!

92 |

A: After inserting Retry for the first time, don't load a save state that you made before inserting it and make sure to start from a new save file.

93 | 94 |
95 |

Q: I use a custom midway block/sprite, but it doesn't seem to work!

96 |

By default Retry only works with the vanilla midway tile, but it's fairly straightforward to make it work with your own blocks/sprites. Retry has a specific RAM address that can be used to set the midway in the current level (according to the checkpoint setting in retry_config/settings_local.asm). The address is !ram_set_checkpoint to have it always available in sprites/blocks, you can copy the contents of "ram.asm" into PIXI's asm/sa1def.asm, GPS's defines.asm and UberASM Tool's other/macro_library.asm.

97 |

The system works as follows: if you set the low byte (!ram_set_checkpoint) to #$00, it will trigger the current level's midway. If the checkpoint table for this sublevel is 0, it means it will give you the midway for the main level. While if it's 2 or 3, it will give you the midway for the current sublevel.

98 |

You can also set a completely custom entrance for the checkpoint, similarly to how Retry's custom midway objects work. To do this, you need to set the entire 16 bit address (!ram_set_checkpoint and !ram_set_checkpoint+1) to the entrance value you want to use. This value follows the format of $7E19B8 and $7E19D8 (where $7E19B8 should go in the first byte of the address, $7E19D8 in the second). For more info, check those addresses in SMWCentral's RAM Map. In practice, your midway block sprite should have a piece of code like this, to set the vanilla midway:

99 | 100 | 101 |
102 | LDA #$01
103 | STA $13CE
104 | 
105 | 106 |

To add multiple midway support, you'd just need to add this after it:

107 | 108 |
109 | LDA #$00
110 | STA !ram_set_checkpoint
111 | 
112 | 113 |

To make the midway take you to an arbitrary entrance, you need to set a different value depending on what entrance it is. For example, to make it use secondary exit number $0169, you'd use this code:

114 | 115 |
116 | REP #$20
117 | LDA #$0169	; Secondary exit number.
118 | ORA #$0200	; Set the "secondary exit" bit in the high byte (like $7E19D8).
119 | STA !ram_set_checkpoint
120 | SEP #$20
121 | 
122 | 123 |

Additionally, you can also reset the current level's checkpoint by setting !ram_set_checkpoint to #$80. This will respawn Mario in the current level's main entrance when dying.

124 | 125 | 130 | 131 |
132 |

Q: I patched the 32x32 Player Tilemap patch / lx5's Custom Powerups / lx5's Dynamic Spriteset System (DSS) / DKCR Status Bar (or other sprite status bars) and I get glitched graphics when dying! What do I do?

133 |

A: Those patches have a high chance of using the same spots in SP1 for their dynamic tiles as the Retry prompt. To fix it, open retry_config/settings_global.asm and towards the bottom you'll see a bunch of !tile_... defines. You need to edit some of those to other free spots in SP1 that aren't used by other patches.

134 | 135 |
136 |

Q: I'm using !prompt_freeze = 0 to make sprites move while Mario is dead, but it also causes autoscrollers to keep going. How do I stop them?

137 |

A: vanilla autoscrollers should already stop when dying with this options turned on, while custom autoscrollers need to be handled on a case-by-case basis by adding a check for Mario's state. This is usually simple to fix by adding a code like this at the beginning of your custom autoscroller's main code:

138 | 139 |
140 |     LDA $71
141 |     CMP #$09
142 |     BNE .run
143 |     RTL
144 | .run:
145 | 
146 | 147 |

(if your autoscroller code is in a routine that ends with RTS, use RTS instead of RTL before .run).

148 | 149 |
Return to main page
150 | 151 | 152 | -------------------------------------------------------------------------------- /docs/uninstall.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Uninstall - Retry System UberASM 5 | 6 | 7 | 8 | 9 | 10 | 11 |

Uninstalling Retry

12 |

If you wish to uninstall the Retry System, and you're not using a tool like Callisto that can rebuild the rom from scratch easily, it is easy to do following these steps:

13 | 21 |
Return to main page
22 | 23 | 24 | -------------------------------------------------------------------------------- /retry_install.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setlocal EnableDelayedExpansion 3 | 4 | set /p uber_folder="UberASM Tool folder where to install: " 5 | set uber_folder=!uber_folder:"=! 6 | set retry_folder=.\src 7 | 8 | echo. 9 | 10 | if exist "!retry_folder!\gamemode" if exist "!retry_folder!\library" if exist "!retry_folder!\retry_config" ( 11 | goto :retry_exist 12 | ) 13 | 14 | set /p retry_folder="Retry src folder to install: " 15 | set retry_folder=!retry_folder:"=! 16 | 17 | if not exist "!retry_folder!" ( 18 | echo Error: !retry_folder! does not exist^^! 19 | goto :end 20 | ) 21 | 22 | if exist "!retry_folder!\gamemode" if exist "!retry_folder!\library" if exist "!retry_folder!\retry_config" ( 23 | goto :retry_exist 24 | ) 25 | 26 | echo Error: !retry_folder! is not a Retry src folder^^! 27 | goto :end 28 | 29 | :retry_exist 30 | 31 | set backup_folder=retry_old_backup 32 | 33 | if not exist "!uber_folder!" ( 34 | echo Error: !uber_folder! does not exist^^! 35 | goto :end 36 | ) 37 | 38 | if exist "!uber_folder!\gamemode" if exist "!uber_folder!\library" if exist "!uber_folder!\list.txt" ( 39 | goto :ok 40 | ) 41 | echo Error: !uber_folder! is not a UberASM Tool folder^^! 42 | goto :end 43 | 44 | :ok 45 | 46 | if exist "!uber_folder!\gamemode\retry_gm*.asm" ( 47 | goto :backup_old 48 | ) 49 | if exist "!uber_folder!\library\retry.asm" ( 50 | goto :backup_old 51 | ) 52 | if exist "!uber_folder!\retry_config" ( 53 | goto :backup_old 54 | ) 55 | 56 | :install 57 | 58 | echo. 59 | echo Installing Retry... 60 | 61 | copy "!retry_folder!\gamemode\retry_gm*.asm" "!uber_folder!\gamemode" > nul 62 | copy "!retry_folder!\library\retry.asm" "!uber_folder!\library" > nul 63 | mkdir "!uber_folder!\retry_config" > nul 64 | xcopy /e /v "!retry_folder!\retry_config" "!uber_folder!\retry_config" > nul 65 | 66 | echo. 67 | echo Retry files copied successfully^^! 68 | 69 | echo. 70 | echo To complete the installation, copy these lines in your "list.txt" under gamemode: 71 | echo. 72 | echo 00 retry_gm00.asm 73 | echo 06 retry_gm06.asm 74 | echo 07 retry_gm07.asm 75 | echo 0C retry_gm0C.asm 76 | echo 0D retry_gm0D.asm 77 | echo 0F retry_gm0F.asm 78 | echo 10 retry_gm10.asm 79 | echo 11 retry_gm11.asm 80 | echo 12 retry_gm12.asm 81 | echo 13 retry_gm13.asm 82 | echo 14 retry_gm14.asm 83 | echo 15 retry_gm15.asm 84 | echo 16 retry_gm16.asm 85 | echo 19 retry_gm19.asm 86 | 87 | goto :end 88 | 89 | :backup_old 90 | 91 | echo Previous Retry installation found. Backing up old version... 92 | 93 | if exist "!uber_folder!\!backup_folder!" ( 94 | echo. 95 | echo Warning: old Retry backup found^^! 96 | echo If you wish to continue the installation, the old backup will be removed and replaced with the current Retry backup. 97 | set /p delete_backup_confirm="Continue? [y/n] " 98 | set delete_backup_confirm=!delete_backup_confirm:"=! 99 | 100 | if "!delete_backup_confirm!"=="y" ( 101 | goto :remove_old 102 | ) 103 | if "!delete_backup_confirm!"=="Y" ( 104 | goto :remove_old 105 | ) 106 | echo. 107 | echo Installation aborted. 108 | goto :end 109 | 110 | :remove_old 111 | rmdir /s /q "!uber_folder!\!backup_folder!" > nul 112 | 113 | echo. 114 | echo Old backup deleted successfully 115 | ) 116 | 117 | mkdir "!uber_folder!\!backup_folder!" > nul 118 | 119 | if exist "!uber_folder!\gamemode\retry_gm*.asm" ( 120 | mkdir "!uber_folder!\!backup_folder!\gamemode" > nul 121 | copy "!uber_folder!\gamemode\retry_gm*.asm" "!uber_folder!\!backup_folder!\gamemode" > nul 122 | del "!uber_folder!\gamemode\retry_gm*.asm" > nul 123 | ) 124 | 125 | if exist "!uber_folder!\library\retry.asm" ( 126 | mkdir "!uber_folder!\!backup_folder!\library" > nul 127 | copy "!uber_folder!\library\retry.asm" "!uber_folder!\!backup_folder!\library" > nul 128 | del "!uber_folder!\library\retry.asm" > nul 129 | ) 130 | 131 | if exist "!uber_folder!\retry_config" ( 132 | mkdir "!uber_folder!\!backup_folder!\retry_config" > nul 133 | xcopy /e /v "!uber_folder!\retry_config" "!uber_folder!\!backup_folder!\retry_config" > nul 134 | rmdir /s /q "!uber_folder!\retry_config" > nul 135 | ) 136 | 137 | echo. 138 | echo Previous version backed up at !uber_folder!\!backup_folder! 139 | 140 | goto :install 141 | 142 | :end 143 | 144 | echo. 145 | 146 | pause 147 | -------------------------------------------------------------------------------- /src/gamemode/retry_gm00.asm: -------------------------------------------------------------------------------- 1 | init: 2 | jsl retry_startup_init 3 | rtl 4 | -------------------------------------------------------------------------------- /src/gamemode/retry_gm06.asm: -------------------------------------------------------------------------------- 1 | init: 2 | jsl retry_level_init_3_init 3 | rtl 4 | 5 | main: 6 | jsl retry_level_init_3_main 7 | rtl 8 | -------------------------------------------------------------------------------- /src/gamemode/retry_gm07.asm: -------------------------------------------------------------------------------- 1 | main: 2 | jsl retry_in_level_main 3 | rtl 4 | 5 | end: 6 | jsl retry_in_level_end 7 | rtl 8 | -------------------------------------------------------------------------------- /src/gamemode/retry_gm0C.asm: -------------------------------------------------------------------------------- 1 | init: 2 | jsl retry_load_overworld_init 3 | rtl 4 | -------------------------------------------------------------------------------- /src/gamemode/retry_gm0D.asm: -------------------------------------------------------------------------------- 1 | init: 2 | jsl retry_fade_to_overworld_init 3 | rtl 4 | -------------------------------------------------------------------------------- /src/gamemode/retry_gm0F.asm: -------------------------------------------------------------------------------- 1 | init: 2 | jsl retry_fade_to_level_init 3 | rtl 4 | 5 | main: 6 | jsl retry_fade_to_level_main 7 | rtl 8 | -------------------------------------------------------------------------------- /src/gamemode/retry_gm10.asm: -------------------------------------------------------------------------------- 1 | init: 2 | jsl retry_level_transition_init 3 | rtl 4 | -------------------------------------------------------------------------------- /src/gamemode/retry_gm11.asm: -------------------------------------------------------------------------------- 1 | init: 2 | jsl retry_level_init_1_init 3 | jsl retry_level_transition_init 4 | rtl 5 | -------------------------------------------------------------------------------- /src/gamemode/retry_gm12.asm: -------------------------------------------------------------------------------- 1 | init: 2 | jsl retry_level_init_2_init 3 | rtl 4 | -------------------------------------------------------------------------------- /src/gamemode/retry_gm13.asm: -------------------------------------------------------------------------------- 1 | init: 2 | jsl retry_level_init_3_init 3 | rtl 4 | 5 | main: 6 | jsl retry_level_init_3_main 7 | rtl 8 | -------------------------------------------------------------------------------- /src/gamemode/retry_gm14.asm: -------------------------------------------------------------------------------- 1 | main: 2 | jsl retry_in_level_main 3 | rtl 4 | 5 | nmi: 6 | jsl retry_nmi_level 7 | rtl 8 | 9 | end: 10 | jsl retry_in_level_end 11 | rtl 12 | -------------------------------------------------------------------------------- /src/gamemode/retry_gm15.asm: -------------------------------------------------------------------------------- 1 | init: 2 | jsl retry_time_up_init 3 | rtl 4 | -------------------------------------------------------------------------------- /src/gamemode/retry_gm16.asm: -------------------------------------------------------------------------------- 1 | init: 2 | jsl retry_level_transition_init 3 | jsl retry_game_over_init 4 | rtl 5 | -------------------------------------------------------------------------------- /src/gamemode/retry_gm19.asm: -------------------------------------------------------------------------------- 1 | init: 2 | jsl retry_level_transition_init 3 | rtl 4 | -------------------------------------------------------------------------------- /src/library/retry.asm: -------------------------------------------------------------------------------- 1 | namespace nested off 2 | 3 | ; Macros to load files easily. 4 | macro incsrc(folder,file) 5 | namespace 6 | incsrc "../retry_config//.asm" 7 | namespace off 8 | endmacro 9 | 10 | macro incbin(folder,file) 11 | incbin "../retry_config//.bin" 12 | endmacro 13 | 14 | ;===================================== 15 | ; Load shared settings and defines. 16 | ;===================================== 17 | %incsrc(code/include,misc) 18 | %incsrc(code/include,rom) 19 | %incsrc("",ram) 20 | %incsrc("",settings_global) 21 | 22 | ;===================================== 23 | ; Check incompatibilities. 24 | ;===================================== 25 | %incsrc(code,check_incompatibilities) 26 | 27 | ;===================================== 28 | ; Load the Retry tables. 29 | ;===================================== 30 | if !use_legacy_tables 31 | %incsrc(legacy,tables) 32 | else 33 | %incsrc(code/include,tables) 34 | %incsrc("",settings_local) 35 | endif 36 | if !sram_feature 37 | %incsrc("",sram_tables) 38 | endif 39 | 40 | ;===================================== 41 | ; Load the letters gfx. 42 | ;===================================== 43 | retry_gfx: 44 | .box: 45 | %incbin(gfx,letters1) 46 | .no_box: 47 | %incbin(gfx,letters2) 48 | if !sprite_status_bar 49 | .digits: 50 | %incbin(gfx,digits) 51 | .coins: 52 | %incbin(gfx,coins) 53 | .timer: 54 | %incbin(gfx,timer) 55 | .lives: 56 | %incbin(gfx,lives) 57 | .bonus_stars: 58 | %incbin(gfx,bonus_stars) 59 | .item_box: 60 | if !8x8_item_box_tile 61 | %incbin(gfx,item_box_8x8) 62 | else 63 | %incbin(gfx,item_box_16x16) 64 | endif 65 | if !draw_retry_indicator 66 | .indicator: 67 | %incbin(gfx,indicator) 68 | endif 69 | endif 70 | 71 | ;===================================== 72 | ; Load the ASM files. 73 | ;===================================== 74 | %incsrc(code,shared) 75 | %incsrc("",extra) 76 | %incsrc(code,startup) 77 | %incsrc(code,fade_to_level) 78 | %incsrc(code,level_init_1) 79 | %incsrc(code,level_init_2) 80 | %incsrc(code,level_init_3) 81 | %incsrc(code,level_transition) 82 | %incsrc(code,in_level) 83 | %incsrc(code,prompt) 84 | %incsrc(code,nmi) 85 | %incsrc(code,load_overworld) 86 | %incsrc(code,fade_to_overworld) 87 | %incsrc(code,game_over) 88 | %incsrc(code,time_up) 89 | %incsrc(code,sprite_status_bar) 90 | %incsrc(code,api) 91 | 92 | ;===================================== 93 | ; Load the hijacks. 94 | ;===================================== 95 | %incsrc(code/hijacks,hex_edits) 96 | %incsrc(code/hijacks,multiple_midways) 97 | %incsrc(code/hijacks,vanilla_midway) 98 | %incsrc(code/hijacks,custom_midway) 99 | %incsrc(code/hijacks,sram) 100 | %incsrc(code/hijacks,hurry_up) 101 | %incsrc(code/hijacks,death_counter) 102 | %incsrc(code/hijacks,initial_facing_fix) 103 | %incsrc(code/hijacks,item_box_fix) 104 | %incsrc(code/hijacks,remove_status_bar) 105 | %incsrc(code/hijacks,vanilla_boss_gm13) 106 | %incsrc(code/hijacks,switch_palace_message_fix) 107 | -------------------------------------------------------------------------------- /src/retry_config/code/api.asm: -------------------------------------------------------------------------------- 1 | ;================================================ 2 | ; Routines that can be called by external UberASM files 3 | ;================================================ 4 | 5 | ;================================================ 6 | ; Routine to respawn in the level (at the current checkpoint), 7 | ; effectively the same as dying and hitting Retry, or dying with 8 | ; instant Retry enabled. 9 | ; 10 | ; Inputs: N/A 11 | ; Outputs: N/A 12 | ; Pre: A/X/Y 8 bits 13 | ; Post: A/X/Y 8 bits 14 | ; Example: JSL retry_api_respawn_in_level 15 | ;================================================ 16 | respawn_in_level: 17 | jml in_level_main_dying_respawn 18 | 19 | ;================================================ 20 | ; Routine to save the game, which will also save the addresses 21 | ; defined in the sram_tables.asm file. 22 | ; 23 | ; Inputs: N/A 24 | ; Outputs: N/A 25 | ; Pre: N/A 26 | ; Post: A/X/Y 8 bits, DB/X/Y preserved 27 | ; Example: JSL retry_api_save_game 28 | ;================================================ 29 | save_game: 30 | jsr shared_save_game 31 | rtl 32 | 33 | ;================================================ 34 | ; Routine to remove the current level's checkpoint, meaning 35 | ; entering it again will load the main sublevel's entrance. 36 | ; Only makes sense to be called during a level gamemode. 37 | ; 38 | ; Inputs: N/A 39 | ; Outputs: N/A 40 | ; Pre: A/X/Y 8 bits 41 | ; Post: A/X/Y 8 bits, DB/X/Y preserved 42 | ; Example: JSL retry_api_reset_level_checkpoint 43 | ;================================================ 44 | reset_level_checkpoint: 45 | jsr shared_reset_checkpoint 46 | rtl 47 | 48 | ;================================================ 49 | ; Routine to remove all levels checkpoints, effectively resetting 50 | ; their state as if it were a new game. If you're saving the CPs 51 | ; to SRAM, you'll need to call the save game routine afterwards to 52 | ; also reset the CPs state in SRAM. 53 | ; 54 | ; Inputs: N/A 55 | ; Outputs: N/A 56 | ; Pre: N/A 57 | ; Post: A/X/Y size preserved, DB/X/Y preserved 58 | ; Example: JSL retry_api_reset_all_checkpoints 59 | ;================================================ 60 | reset_all_checkpoints: 61 | ; A/X/Y 8 bits 62 | phx : phy : php 63 | sep #$30 64 | 65 | ; Initialize the checkpoint ram table. 66 | ldx #$BE 67 | ldy #$5F 68 | - tya : cmp #$25 : bcc + 69 | clc : adc #$DC 70 | + sta !ram_checkpoint,x 71 | lda #$00 : adc #$00 : sta !ram_checkpoint+1,x 72 | lda $1EA2|!addr,y : and #~$40 : sta $1EA2|!addr,y 73 | dex #2 74 | dey : bpl - 75 | 76 | ; Initialize respawn RAM in case it's called inside a level. 77 | %lda_13BF() : asl : tax 78 | rep #$20 79 | lda !ram_checkpoint,x : sta !ram_respawn 80 | 81 | ; Initialize "set checkpoint" handle to $FFFF. 82 | lda #$FFFF : sta !ram_set_checkpoint 83 | 84 | ; Restore X/Y/P 85 | plp : ply : plx 86 | rtl 87 | 88 | ;================================================ 89 | ; Routine to configure which tiles will be used by the sprite status 90 | ; bar. You can configure these elements: item box, timer, coin 91 | ; counter, lives counter and bonus stars counter. Each element needs a 92 | ; 16x16 sprite tile to be reserved. 93 | ; This routine should be called in UberASM level init code, to overwrite 94 | ; the default settings from "settings_global.asm", in case you want 95 | ; to hide some or all of the elements in some level or if you need to 96 | ; change their tile or palette. 97 | ; Each element needs a 16 bit value that determines which 16x16 tile 98 | ; it will use and what palette to use. The first digit is the palette 99 | ; row to use (8-F), while the other 3 digits are the tile number 100 | ; (000-1FF). If an element is set to $0000, it won't be displayed. 101 | ; 102 | ; Inputs: for each item, in order, you write the value after the JSL 103 | ; in the format described above (see example) 104 | ; Outputs: N/A 105 | ; Pre: N/A 106 | ; Post: A/X/Y 8 bit and clobbered, DB preserved 107 | ; Example: 108 | ; JSL retry_api_configure_sprite_status_bar 109 | ; dw $B080 ; Item box: palette B, tile 0x80 110 | ; dw $8088 ; Timer: palette 8, tile 0x88 111 | ; dw $80C2 ; Coin counter: palette 8, tile 0xC2 112 | ; dw $0000 ; Lives counter: hidden 113 | ; dw $0000 ; Bonus stars counter: hidden 114 | ; ... <- your code will continue here after the JSL 115 | ;================================================ 116 | configure_sprite_status_bar: 117 | if !sprite_status_bar 118 | phb 119 | ; Set DBR equal to caller routine bank 120 | sep #$30 121 | lda $04,s : pha : plb 122 | ; Use Y to read address after the routine call 123 | rep #$30 124 | lda $02,s : tay 125 | ; Copy the values from after the JSL to sprite status bar ram 126 | lda $0001,y : and #$7FFF : sta !ram_status_bar_item_box_tile 127 | lda $0003,y : and #$7FFF : sta !ram_status_bar_timer_tile 128 | lda $0005,y : and #$7FFF : sta !ram_status_bar_coins_tile 129 | lda $0007,y : and #$7FFF : sta !ram_status_bar_lives_tile 130 | lda $0009,y : and #$7FFF : sta !ram_status_bar_bonus_stars_tile 131 | plb 132 | endif 133 | ; Make sure the code returns at the right place 134 | rep #$20 135 | lda $01,s : clc : adc.w #2*5 : sta $01,s 136 | sep #$30 137 | rtl 138 | 139 | ;================================================ 140 | ; Routine to get the current Retry type, i.e. if currently the level is 141 | ; set to have Retry prompt, instant Retry or no Retry. 142 | ; The returned value has this format: 143 | ; - $01 = Retry prompt enabled & play the vanilla death song when the player dies 144 | ; - $02 = Retry prompt enabled & play only the death sfx when the player dies 145 | ; - $03 = instant Retry enabled 146 | ; - $04 = Retry disabled 147 | ; 148 | ; Inputs: N/A 149 | ; Outputs: A = Retry type 150 | ; Pre: A 8 bits 151 | ; Post: A/X/Y size preserved, DB/X/Y preserved 152 | ; Example: JSL retry_api_get_retry_type 153 | ;================================================ 154 | get_retry_type: 155 | jsr shared_get_prompt_type 156 | rtl 157 | 158 | ;================================================ 159 | ; Routine to get the address in SRAM for a specific variable. 160 | ; By "variable" it's meant any of the RAM addresses that are saved to SRAM 161 | ; specified in the sram save table. The returned address will be coherent 162 | ; with the current save file loaded when this routine is called (so, make 163 | ; sure to not call it before a save file is loaded!). 164 | ; This could be useful to read/write values in SRAM directly, for example 165 | ; if you need to update some SRAM value without the game being saved. 166 | ; Note: this will always return "variable not found" if !sram_feature = 0. 167 | ; 168 | ; Inputs: variable address to search for in ROM right after the JSL 169 | ; This means the call should look like this: 170 | ; JSL retry_api_get_sram_variable_address 171 | ; dl 172 | ; Outputs: Carry set = variable not found 173 | ; Carry clear = variable found -> SRAM address stored in $00-$02 174 | ; In this case the value in SRAM can be accessed indirectly with the 175 | ; LDA/STA [$00] and LDA/STA [$00],y instructions. 176 | ; Pre: N/A 177 | ; Post: A/X/Y 8 bit and clobbered, DB preserved 178 | ; Example: 179 | ; JSL retry_api_get_sram_variable_address 180 | ; dl retry_ram_death_counter ; Variable to search for 181 | ; BCS not_found 182 | ; found: 183 | ; LDY #$01 184 | ; LDA #$09 185 | ; STA [$00],y ; Set second death counter digit in SRAM to 9 186 | ; not_found: 187 | ; ... 188 | ;================================================ 189 | get_sram_variable_address: 190 | if !sram_feature 191 | phb 192 | ; Set DBR equal to caller routine bank 193 | sep #$30 194 | lda $04,s : pha : plb 195 | ; Use Y to read address after the routine call 196 | rep #$30 197 | lda $02,s : tay 198 | stz $00 199 | ldx #$0000 200 | .loop: 201 | ; Check if the current SRAM variables corresponds to the input 202 | lda.l sram_tables_save+0,x : cmp $0001,y : bne .next 203 | lda.l sram_tables_save+1,x : cmp $0002,y : bne .next 204 | .found: 205 | ; If so, add the calculated offset to the save file SRAM address 206 | jsr sram_get_sram_addr 207 | clc : adc $00 : sta $00 208 | sep #$20 209 | lda.b #!sram_addr>>16 : sta $02 210 | ; Clear carry (address found) 211 | clc 212 | bra .return 213 | .next: 214 | ; Update the SRAM offset with the current variable size 215 | lda.l sram_tables_save+3,x : clc : adc $00 : sta $00 216 | ; Go to the next SRAM variable 217 | txa : clc : adc #$0005 218 | ; If at the end of the SRAM table, end 219 | cmp.w #sram_tables_sram_defaults-sram_tables_save : bcs .not_found 220 | tax 221 | bra .loop 222 | .not_found: 223 | ; Set carry (address not found) 224 | sec 225 | .return: 226 | plb 227 | ; Make sure the code returns at the right place 228 | rep #$20 229 | lda $01,s : inc #3 : sta $01,s 230 | sep #$30 231 | rtl 232 | else 233 | ; Make sure the code returns at the right place 234 | rep #$20 235 | lda $01,s : clc : adc #$0003 : sta $01,s 236 | ; Set carry (address not found) 237 | sep #$31 238 | endif 239 | rtl 240 | -------------------------------------------------------------------------------- /src/retry_config/code/check_incompatibilities.asm: -------------------------------------------------------------------------------- 1 | ;if read1($05D9E3) != $5C 2 | ; error "You must save a level in Lunar Magic with the \"Separate midway entrance\" option checked before applying this. Insertion aborted." 3 | ;endif 4 | 5 | if read1($0FF0A0) == $FF 6 | error "You must save at least one level in Lunar Magic before inserting this patch. Insertion aborted." 7 | endif 8 | 9 | if read1($00A28A) == $5C && read1($05D8E6) == $5C 10 | error "This patch is not compatible with worldpeace's retry patch. Insertion aborted." 11 | endif 12 | 13 | if read1($05DAA3) == $5C 14 | error "This patch is not compatible with the Multiple Midway Points patch. Insertion aborted." 15 | endif 16 | 17 | ; Warn if SRAM/BW-RAM plus are patched in already and !sram_feature = 1 (also force it to 0). 18 | if !sram_feature && not(!sa1) && !sram_plus 19 | print "Warning: SRAM Plus was detected in your ROM. Retry's save feature won't be inserted." 20 | !sram_feature = 0 21 | endif 22 | 23 | if !sram_feature && !sa1 && !bwram_plus 24 | print "Warning: BW-RAM Plus was detected in your ROM. Retry's save feature won't be inserted." 25 | !sram_feature = 0 26 | endif 27 | 28 | ; UberASM Tool 2.0 is now required 29 | %require_uber_ver(2,0) 30 | -------------------------------------------------------------------------------- /src/retry_config/code/fade_to_level.asm: -------------------------------------------------------------------------------- 1 | ; Gamemode 0F 2 | 3 | init: 4 | if !sprite_status_bar 5 | jsr sprite_status_bar_init_ram 6 | endif 7 | 8 | ; If respawning or doing a level transition, skip. 9 | lda $141A|!addr : bne .transition 10 | 11 | if !enter_level_sfx != $00 12 | ; If not loading the level from a No Yoshi intro, play the SFX. 13 | lda $71 : cmp #$0A : beq + 14 | lda.b #!enter_level_sfx : sta !enter_level_sfx_addr|!addr 15 | lda.b #!enter_level_delay : sta $0DB1|!addr 16 | + 17 | endif 18 | 19 | if !pipe_entrance_freeze == 2 20 | ; Reset the $9D backup. 21 | lda #$00 : sta !ram_9D_backup 22 | endif 23 | bra main 24 | 25 | .transition: 26 | ; Check if we're respawning from Retry. 27 | lda !ram_is_respawning : beq .not_respawning 28 | 29 | .respawning: 30 | if !pipe_entrance_freeze == 2 31 | ; If yes, store the $9D backup to $9D. 32 | ; This makes pipe entrances consistent in how sprites behave during them. 33 | lda !ram_9D_backup : sta $9D 34 | endif 35 | bra main 36 | 37 | .not_respawning: 38 | if !pipe_entrance_freeze == 2 39 | ; If it's a normal transition, backup $9D... 40 | lda $9D : sta !ram_9D_backup 41 | endif 42 | 43 | ; ...and backup the current entrance value for later. 44 | ; (if warping to Yoshi Wings, change the entrance to the correct level 45 | ; and set the Yoshi Wings flag in the checkpoint RAM). 46 | lda $1B95|!addr : beq + 47 | %jsl_to_rts_db($05DBAC,$058125) 48 | lda $19D8|!addr,x : and #$FE : ora $010C|!addr : ora #$80 49 | bra ++ 50 | + jsr shared_get_screen_number 51 | lda $19D8|!addr,x 52 | ++ sta !ram_door_dest+1 53 | lda $19B8|!addr,x : sta !ram_door_dest+0 54 | 55 | main: 56 | if !fast_transitions 57 | ; Reset the mosaic timer. 58 | stz $0DB1|!addr 59 | endif 60 | 61 | ; If in the door animation, call the extra routine. 62 | lda $71 : cmp #$0D : bne .return 63 | phb : phk : plb 64 | php 65 | jsr extra_door_animation 66 | plp 67 | plb 68 | 69 | .return: 70 | rtl 71 | -------------------------------------------------------------------------------- /src/retry_config/code/fade_to_overworld.asm: -------------------------------------------------------------------------------- 1 | ; Gamemode 0D 2 | 3 | ; Tile used for empty space. By default it's the border "filled" tile. 4 | !empty_tile = $FE 5 | !empty_props = l3_prop(6,0) 6 | 7 | init: 8 | 9 | ; Draw the death counter in the Overworld. 10 | .death_counter: 11 | if !ow_death_counter 12 | ; Set the DBR to $7F to use the stripe table with ,y. 13 | %set_dbr(!stripe_table) 14 | 15 | ; Write the stripe image header. 16 | rep #$30 17 | ldy.w !stripe_index 18 | lda.w #str_header1(!ow_death_counter_x_pos,!ow_death_counter_y_pos) 19 | sta.w !stripe_table,y 20 | iny #2 21 | lda.w #str_header2((5*2)-1,0) 22 | sta.w !stripe_table,y 23 | iny #2 24 | 25 | ; Loop through all digits in the death counter 26 | ; and write them to the stripe image table. 27 | ldx #$0000 28 | sep #$20 29 | stz $00 30 | 31 | ..stripe_loop: 32 | ; If the current digit is zero, turn it into an empty tile, 33 | ; but only if no non-zero digit has been reached yet. 34 | lda.l !ram_death_counter,x : bne ...normal 35 | cpx.w #$0005-1 : beq ...normal 36 | lsr $00 : bcs ...normal 37 | lda.b #!empty_tile : sta.w !stripe_table,y 38 | lda.b #!empty_props 39 | bra + 40 | 41 | ...normal: 42 | clc : adc.b #!ow_digit_0 : sta.w !stripe_table,y 43 | lda #$01 : sta $00 44 | lda.b #!ow_death_counter_props 45 | + sta.w !stripe_table+1,y 46 | 47 | ...next: 48 | iny #2 49 | inx 50 | cpx #$0005 : bcc ..stripe_loop 51 | 52 | ...end: 53 | ; Write the terminator and update the stripe index. 54 | lda #$FF : sta.w !stripe_table,y 55 | sty.w !stripe_index 56 | sep #$10 57 | 58 | plb 59 | endif 60 | 61 | rtl 62 | -------------------------------------------------------------------------------- /src/retry_config/code/game_over.asm: -------------------------------------------------------------------------------- 1 | ; Gamemode 16 2 | 3 | init: 4 | ; Skip if it's not the "GAME OVER" screen. 5 | lda $143B|!addr : cmp #$14 : bne .return 6 | 7 | if !sram_feature 8 | ; Reload the save file. 9 | jsl sram_load_game_over 10 | endif 11 | 12 | ; Call the extra routine. 13 | phb : phk : plb 14 | php 15 | jsr extra_game_over 16 | plp 17 | plb 18 | 19 | ; If applicable, save the game. 20 | if !save_after_game_over 21 | jsr shared_save_game 22 | endif 23 | 24 | .return: 25 | rtl 26 | -------------------------------------------------------------------------------- /src/retry_config/code/gm14_end/death_routine.asm: -------------------------------------------------------------------------------- 1 | ;===================================== 2 | ; death_sfx routine 3 | ; 4 | ; Handles death music/sfx when dying, death counter and other stuff. 5 | ; This runs just before AMK, so we can kill the death song before it starts. 6 | ;===================================== 7 | death_routine: 8 | if not(!infinite_lives) 9 | ; Check if all lives were lost. 10 | lda $0DBE|!addr : bpl .no_game_over 11 | 12 | ; Check if the death sequence has finished. 13 | lda $1496|!addr : bne .game_over_return 14 | 15 | .game_over: 16 | ; If yes, go to game over 17 | %jsl_to_rts_db($00D0DD,$0084CF) 18 | 19 | ..return: 20 | rts 21 | 22 | .no_game_over: 23 | endif 24 | 25 | ; If the reload level flag is set... 26 | lda !ram_is_dying : bit #$40 : beq .no_reload 27 | 28 | ; Make sure Mario's animation timer is 0. 29 | stz $1496|!addr 30 | 31 | .reload: 32 | if !title_death_behavior != 0 33 | ; (Check if we need to reload a level or the title screen) 34 | bit #$20 : beq ..level 35 | 36 | ..title: 37 | ; ...reload the title screen! 38 | lda #$02 : sta $0100|!addr 39 | rts 40 | 41 | ..level: 42 | endif 43 | ; ...reload the level! 44 | lda #$0F : sta $0100|!addr 45 | rts 46 | 47 | .no_reload: 48 | ; Only update death counter and call the death routine once 49 | ; but handle the death song every frame to avoid issues with custom codes that call $00F606 every frame. 50 | cmp #$00 : bne .handle_song 51 | 52 | .first_frame: 53 | ; Set the dying flag. 54 | inc : sta !ram_is_dying 55 | 56 | ; Update the death counter. 57 | ldx #$04 58 | - lda !ram_death_counter,x : inc : sta !ram_death_counter,x 59 | cmp #10 : bcc + 60 | lda #$00 : sta !ram_death_counter,x 61 | dex : bpl - 62 | 63 | ; If we got here, it means the counter overflowed back to 0, so set it to 99999. 64 | ldx #$04 65 | lda #$09 66 | - sta !ram_death_counter,x 67 | dex : bpl - 68 | + 69 | ; Call the custom death routine. 70 | php : phb 71 | jsr extra_death 72 | plb : plp 73 | 74 | ; Kill score sprites if the option is enabled and Retry prompt is enabled. 75 | if !no_score_sprites_on_death 76 | jsr shared_get_prompt_type : cmp #$03 : bcs + 77 | ldx.b #$06-1 78 | - stz $16E1|!addr,x 79 | dex : bpl - 80 | + 81 | endif 82 | 83 | ; Reset some stuff related to lx5's Custom Powerups. 84 | if !custom_powerups == 1 85 | stz.w ($170B|!addr)+$08 86 | stz.w ($170B|!addr)+$09 87 | lda #$00 : sta !projectile_do_dma 88 | 89 | ldx #$07 90 | - lda $170B|!addr,x : cmp #$12 : bne + 91 | stz $170B|!addr,x 92 | + dex : bpl - 93 | 94 | lda !item_box_disable : ora #$02 : sta !item_box_disable 95 | endif 96 | 97 | if not(!infinite_lives) 98 | ; Don't decrement lives on the title screen. 99 | lda $0100|!addr : cmp #$0B : bcc .no_lose_lives 100 | 101 | ; Check if we need to decrement lives. 102 | jsr shared_get_bitwise_mask 103 | and.l tables_lose_lives,x : beq .no_lose_lives 104 | 105 | ; If yes, decrement them and don't reset music if about to game over. 106 | dec $0DBE|!addr : bmi .return 107 | 108 | .no_lose_lives: 109 | endif 110 | 111 | .handle_song: 112 | ; If the music is sped up, play the death song to make it normal again. 113 | lda !ram_hurry_up : bne .return 114 | 115 | ; If "Exit" was selected, don't disable the death music. 116 | lda !ram_prompt_phase : cmp #$05 : bcs .return 117 | 118 | ; Check if we have to disable the death music. 119 | jsr shared_get_prompt_type 120 | cmp #$02 : bcc .return 121 | cmp #$04 : bcs .return 122 | 123 | .no_death_song: 124 | ; Don't play the death song. 125 | stz $1DFB|!addr 126 | 127 | ; Undo the $0DDA change. 128 | ; This ensures the song won't be reloaded if it's the same after respawning. 129 | lda !ram_music_backup : sta $0DDA|!addr 130 | 131 | ; Only play the death SFX once per death. 132 | lda !ram_is_dying : bmi .return 133 | ora #$80 : sta !ram_is_dying 134 | 135 | ; Play the death SFX. 136 | if !death_sfx != $00 137 | lda.b #!death_sfx : sta !death_sfx_addr|!addr 138 | endif 139 | 140 | .return: 141 | rts 142 | -------------------------------------------------------------------------------- /src/retry_config/code/gm14_end/prompt_oam.asm: -------------------------------------------------------------------------------- 1 | if not(!no_prompt_draw) 2 | 3 | ; Check if palette values make sense. 4 | assert !letter_palette >= $08 && !letter_palette <= $0F, "Error: \!letter_palette should be between $08 and $0F." 5 | assert !cursor_palette >= $08 && !cursor_palette <= $0F, "Error: \!cursor_palette should be between $08 and $0F." 6 | 7 | ; Convert palettes from row number to YXPPCCCT format. 8 | !l_props #= ($30|((!letter_palette-8)<<1)) 9 | !c_props #= ($30|((!cursor_palette-8)<<1)) 10 | 11 | ; Function to add the T bit in the YXPPCCCT properties for tiles in page 1 12 | function props(prop,tile) = ((prop)|((tile>>8)&1)) 13 | 14 | ;===================================== 15 | ; prompt_oam routine 16 | ; 17 | ; This routine draws the Retry prompt tiles on the screen. 18 | ; The prompt will be drawn using as few OAM slots as possible: 19 | ; - If box and exit are enabled, 15 slots will be used (16 if using the oscillating cursor). 20 | ; - If box is disabled but exit is enabled, 11 slots will be used. 21 | ; - If box is enabled but exit is disabled, 8 slots will be used (9 if using the oscillating cursor). 22 | ; - If box and exit are disabled, 6 slots will be used. 23 | ; Before drawing, all the currently used OAM slots are moved at the end of the OAM table, then the new tiles are written from the start. 24 | ; This ensures that in most cases Retry won't overwrite other sprites, and that it will always have max priority w.r.t. other sprite tiles 25 | ; (so that other sprites will always go behind the prompt). 26 | ;===================================== 27 | prompt_oam: 28 | ; Get as many free slots as possible at the start of $0200. 29 | ; Skip this in Reznor/Morton/Roy's rooms to avoid glitching their BGs. 30 | lda $0D9B|!addr : cmp #$C0 : beq + 31 | jsr defrag_oam 32 | + 33 | ; Store the "hide cursor" mask in $00. 34 | if !cursor_setting == 1 35 | lda $1B91|!addr : eor #$1F : and #$18 : bne + 36 | lda #$03 37 | bra ++ 38 | + 39 | elseif !cursor_setting == 2 40 | lda $1B91|!addr : lsr #!cursor_oscillate_speed : and #$07 : tax 41 | lda.w .cursor_x_offset,x : sta $02 42 | endif 43 | ldx $1B92|!addr 44 | lda.w .hide_cursor_mask,x 45 | ++ sta $00 46 | 47 | ; Draw "RETRY" 48 | ldy #$00 : sty $01 49 | ldx.b #letters_retry-letters 50 | if !prompt_wave 51 | stz $03 52 | lda $1B92|!addr : bne + 53 | inc $03 54 | + 55 | endif 56 | jsr oam_draw 57 | jsr handle_cursor 58 | 59 | ; Draw "EXIT" if exit is enabled 60 | lda !ram_disable_exit : bne .no_exit 61 | sty $01 62 | ldx.b #letters_exit-letters 63 | if !prompt_wave 64 | stz $03 65 | lda $1B92|!addr : beq + 66 | inc $03 67 | + 68 | endif 69 | jsr oam_draw 70 | lsr $00 71 | jsr handle_cursor 72 | 73 | .no_exit: 74 | ; Draw filler tiles if the box is enabled 75 | lda !ram_disable_box : bne .no_box 76 | ldx.b #letters_box-letters 77 | lda !ram_disable_exit : beq + 78 | ldx.b #letters_box_no_exit-letters 79 | + jsr oam_draw 80 | 81 | .no_box: 82 | ; Make sure $0400 is up to date 83 | jsr shared_update_0400 84 | rts 85 | 86 | .hide_cursor_mask: 87 | db $02,$01 88 | 89 | if !cursor_setting == 2 90 | .cursor_x_offset: 91 | db -1,0,1,2,3,2,1,0 92 | endif 93 | 94 | ;===================================== 95 | ; handle_cursor routine 96 | ; 97 | ; This routine handles hiding the cursor when applicable, as well as setting its OAM size 98 | ; and offsetting its X position when !cursor_setting == 2. 99 | ; If the box is enabled, the cursor will be 16x16, and hidden by replacing it with a black tile. 100 | ; Otherwise, the cursor will be 8x8, and hidden by moving it offscreen. 101 | ; 102 | ; Inputs: 103 | ; $00 = LSB set if the cursor should be hidden 104 | ; $01 = OAM index of the cursor 105 | ; $02 = X offset of the cursor (when !cursor_setting == 2) 106 | ;===================================== 107 | handle_cursor: 108 | ; Set the OAM size. 109 | lda $01 : lsr #2 : tax 110 | lda !ram_disable_box : beq + 111 | lda #$00 112 | bra ++ 113 | + lda #$02 114 | ++ sta $0420|!addr,x 115 | 116 | ; Hide and offset the cursor. 117 | ldx $01 118 | lda $00 : and #$01 : bne .hide 119 | 120 | if !cursor_setting == 2 121 | ; If the box is enabled... 122 | lda !ram_disable_box : bne + 123 | 124 | ; Draw an additional black tile under the cursor. 125 | rep #$20 126 | lda $0200|!addr,x : sta $0200|!addr,y 127 | lda.w #(!l_props<<8)|(!tile_blk) : sta $0202|!addr,y 128 | sep #$20 129 | 130 | ; Make the black tile 16x16 and increase the OAM index. 131 | phy 132 | tya : lsr #2 : tay 133 | lda #$02 : sta $0420|!addr,y 134 | ply 135 | iny #4 136 | + 137 | ; Apply the X offset to the cursor 138 | lda $0200|!addr,x : clc : adc $02 : sta $0200|!addr,x 139 | 140 | ; Make the cursor 8x8. 141 | txa : lsr #2 : tax 142 | stz $0420|!addr,x 143 | endif 144 | rts 145 | 146 | .hide: 147 | lda !ram_disable_box : beq + 148 | lda #$F0 : sta $0201|!addr,x 149 | rts 150 | + lda.b #!tile_blk : sta $0202|!addr,x 151 | .return: 152 | rts 153 | 154 | ;===================================== 155 | ; erase_tiles routine 156 | ; 157 | ; This routine hides the Retry prompt tiles. 158 | ;===================================== 159 | erase_tiles: 160 | ; Erase the prompt's OAM tiles when in Reznor/Morton/Roy/Ludwig's rooms. 161 | ; This avoids the BG from glitching out when the prompt disappears. 162 | lda $0D9B|!addr : cmp #$C0 : bne .return 163 | 164 | ; Find how many tiles we need to erase. 165 | lda.b #(letters_retry_end-letters_retry)/5 : sta $00 166 | 167 | lda !ram_disable_exit : bne + 168 | lda $00 : clc : adc.b #(letters_exit_end-letters_exit)/5 : sta $00 169 | + 170 | lda !ram_disable_box : bne + 171 | lda $00 : clc : adc.b #(letters_box_end-letters_box)/5 172 | if !cursor_setting == 2 173 | inc 174 | endif 175 | sta $00 176 | + 177 | ; Put all the tiles offscreen. 178 | lda $00 : dec : asl #2 : tay 179 | lda #$F0 180 | .loop: 181 | sta $0201|!addr,y 182 | dey #4 : bpl .loop 183 | .return: 184 | rts 185 | 186 | ;===================================== 187 | ; oam_draw routine 188 | ; 189 | ; This routine draws one part of the Retry prompt on the screen. 190 | ; Inputs: 191 | ; X = index in the letters table 192 | ; Y = OAM index 193 | ;===================================== 194 | oam_draw: 195 | if !prompt_wave 196 | stz $0F 197 | endif 198 | 199 | ; Load X/Y position based on black box enabled flag 200 | lda !ram_disable_box : beq + 201 | lda !ram_prompt_x_pos : sta $0D 202 | lda !ram_prompt_y_pos : sta $0E 203 | bra .loop 204 | + lda.b #!default_text_x_pos : sta $0D 205 | lda.b #!default_text_y_pos : sta $0E 206 | 207 | .loop: 208 | ; Return if we reached the $FF terminator. 209 | lda.w letters,x : cmp #$FF : beq .return 210 | 211 | ; Store the X,Y positions and tile OAM properties. 212 | clc : adc $0D : sta $0200|!addr,y 213 | lda.w letters+1,x : clc : adc $0E : sta $0201|!addr,y 214 | if !prompt_wave 215 | ; Make the letters wave 216 | lda $03 : beq + 217 | lda.w letters+2,x : cmp.b #!tile_curs : beq + 218 | phx 219 | lda $1B91|!addr : lsr #!prompt_wave_speed 220 | clc : adc $0F : and #$07 : tax 221 | lda.w .y_offset,x : clc : adc $0201|!addr,y : sta $0201|!addr,y 222 | plx 223 | inc $0F 224 | + 225 | endif 226 | rep #$20 227 | lda.w letters+2,x : sta $0202|!addr,y 228 | sep #$20 229 | 230 | ; Store the OAM size. 231 | phy 232 | tya : lsr #2 : tay 233 | lda.w letters+4,x : sta $0420|!addr,y 234 | ply 235 | 236 | ; Go to the next tile. 237 | inx #5 238 | iny #4 239 | bra .loop 240 | .return: 241 | rts 242 | 243 | if !prompt_wave 244 | .y_offset: 245 | db -3,-2,-1,0,1,0,-1,-2 246 | endif 247 | 248 | ;===================================== 249 | ; OAM info for each tile (X,Y,T,P,S) 250 | ;===================================== 251 | letters: 252 | .retry: 253 | db $00,$00,!tile_curs,props(!c_props,!tile_curs),$00 ; Black/Cursor 254 | db $10,$00,!tile_r, props(!l_props,!tile_r), $00 ; R 255 | db $18,$00,!tile_e, props(!l_props,!tile_e), $00 ; E 256 | db $20,$00,!tile_t, props(!l_props,!tile_t), $00 ; T 257 | db $28,$00,!tile_r, props(!l_props,!tile_r), $00 ; R 258 | db $30,$00,!tile_y, props(!l_props,!tile_y), $00 ; Y 259 | ..end: 260 | db $FF 261 | 262 | .exit: 263 | db $00,$10,!tile_curs,props(!c_props,!tile_curs),$00 ; Black/Cursor 264 | db $10,$10,!tile_e, props(!l_props,!tile_e), $00 ; E 265 | db $18,$10,!tile_x, props(!l_props,!tile_x), $00 ; X 266 | db $20,$10,!tile_i, props(!l_props,!tile_i), $00 ; I 267 | db $28,$10,!tile_t, props(!l_props,!tile_t), $00 ; T 268 | ..end: 269 | db $FF 270 | 271 | .box: 272 | db $E0,$10,!tile_blk, props(!l_props,!tile_blk), $02 ; Black 273 | db $F0,$10,!tile_blk, props(!l_props,!tile_blk), $02 ; Black 274 | ..no_exit: 275 | db $E0,$00,!tile_blk, props(!l_props,!tile_blk), $02 ; Black 276 | db $F0,$00,!tile_blk, props(!l_props,!tile_blk), $02 ; Black 277 | ..end: 278 | db $FF 279 | 280 | ;===================================== 281 | ; defrag_oam routine 282 | ; 283 | ; This routine puts all used slots in OAM at the end of the table in contiguous spots. 284 | ; The result is that all free slots will be at the beginning of the table. 285 | ; This allows the letters to be drawn with max priority w.r.t. everything else, and to not overwrite other tiles. 286 | ; Returns with Y = $01FC and X = last free OAM slot. 287 | ;===================================== 288 | defrag_oam: 289 | ; Since we scan both $0200 and $0300, we need 16 bit indexes. 290 | rep #$10 291 | ; Y: index in the original OAM table. 292 | ldy #$01FC 293 | ; X: index in the rearranged table. 294 | ldx #$01FC 295 | 296 | ; First we find the first free slot from the end of the table. 297 | ; This prevents the main loop from hiding tiles when the end of the OAM table is filled. 298 | lda #$F0 299 | 300 | .setup_loop: 301 | cmp $0201|!addr,y : beq .main_loop 302 | dex #4 303 | dey #4 304 | bpl .setup_loop 305 | 306 | ..end: 307 | ; If we get here it means that the entire OAM table is full, so just return. 308 | sep #$10 309 | rts 310 | 311 | ; Now we move all the used slots in adjacent spots at the end of the OAM table. 312 | .main_loop: 313 | ; If the slot is free, go to the next one. 314 | cmp $0201|!addr,y : beq ..next 315 | 316 | ; Otherwise, copy the Y slot in the X slot... 317 | rep #$20 318 | lda $0200|!addr,y : sta $0200|!addr,x 319 | lda $0202|!addr,y : sta $0202|!addr,x 320 | 321 | ; ...and mark the Y slot as free. 322 | lda #$F0F0 : sta $0200|!addr,y 323 | 324 | phx : phy 325 | 326 | ; Compute the indexes in $0420. 327 | tya : lsr #2 : tay 328 | txa : lsr #2 : tax 329 | 330 | ; Copy the entry in $0420 as well. 331 | sep #$20 332 | lda $0420|!addr,y : sta $0420|!addr,x 333 | 334 | ply : plx 335 | 336 | ; Go to the next slot in the rearranged table. 337 | dex #4 338 | 339 | ; Reload value to compare $0201 to. 340 | lda #$F0 341 | 342 | ..next: 343 | ; Go to the next slot in the original table, and loop back if not the end. 344 | dey #4 : bpl .main_loop 345 | 346 | .end: 347 | sep #$10 348 | rts 349 | 350 | endif 351 | -------------------------------------------------------------------------------- /src/retry_config/code/gm14_end/set_checkpoint.asm: -------------------------------------------------------------------------------- 1 | ;===================================== 2 | ; set_checkpoint routine 3 | ;===================================== 4 | set_checkpoint: 5 | ; If the reset value is not set, set the checkpoint. 6 | lda !ram_set_checkpoint : cmp #$80 : bne .set 7 | 8 | .reset: 9 | ; Otherwise, reset the checkpoint. 10 | jsr shared_reset_checkpoint 11 | stz $13CE|!addr 12 | 13 | if !save_on_checkpoint 14 | jsr shared_save_game 15 | endif 16 | 17 | ; Always reload the samples, just to be safe. 18 | lda #$FF : sta !ram_music_backup 19 | bra .return 20 | 21 | .set: 22 | ; Save individual dcsave buffers. 23 | ; Needed because we skip over $00F2DD, where the routine is called. 24 | jsr shared_dcsave_midpoint 25 | 26 | ; Set midway flag, just to be safe. 27 | lda #$01 : sta $13CE|!addr 28 | 29 | ; Check if it's a normal or custom midway. 30 | lda !ram_set_checkpoint+1 : cmp #$FF : bne ..custom_destination 31 | 32 | ..normal_midway: 33 | ; If it's the intro level, skip. 34 | lda $0109|!addr : beq ...no_intro 35 | cmp.b #!intro_level+$24 : bne .return 36 | 37 | ...no_intro: 38 | ; Check if this midway sets the midway entrance for the sublevel or the main level. 39 | jsr shared_get_checkpoint_value 40 | cmp #$01 : beq ...sub_midway 41 | cmp #$03 : bcs ...sub_midway 42 | 43 | ...main_midway: 44 | jsr calc_entrance 45 | bra + 46 | ...sub_midway: 47 | jsr calc_entrance_2 48 | + 49 | lda $0DDA|!addr : sta !ram_music_backup 50 | bra .return2 51 | 52 | ..custom_destination: 53 | ; Set the checkpoint destination. 54 | rep #$20 55 | lda !ram_set_checkpoint : sta !ram_respawn 56 | sep #$20 57 | 58 | ; If we're in the Yoshi Wings level, set the flag if applicable. 59 | ldy $1B95|!addr : beq + 60 | xba : bit #$0A : bne + 61 | ora #$80 : sta !ram_respawn+1 62 | + 63 | ; Always reload the samples, just to be safe. 64 | lda #$FF : sta !ram_music_backup 65 | 66 | .return2: 67 | ; Save the midway entrance as a checkpoint. 68 | jsr shared_hard_save 69 | 70 | .return: 71 | ; Reset the set_checkpoint address. 72 | lda #$FF : sta !ram_set_checkpoint : sta !ram_set_checkpoint+1 73 | rts 74 | 75 | ;===================================== 76 | ; calc_entrance routine 77 | ;===================================== 78 | calc_entrance: 79 | ; If it's not the intro level, skip. 80 | %lda_13BF() : tax : bne .no_intro 81 | 82 | ; Set intro sublevel number as respawn point. 83 | jsr shared_get_intro_sublevel 84 | sta !ram_respawn 85 | sep #$20 86 | bra .check_midway 87 | 88 | .no_intro: 89 | ; Convert $13BF value to sublevel number. 90 | cmp #$25 : bcc + 91 | clc : adc #$DC 92 | + sta !ram_respawn 93 | lda #$00 : adc #$00 94 | ..store_entrance_high: 95 | sta !ram_respawn+1 96 | 97 | .check_midway: 98 | ; If the midway flag is not set, return. 99 | lda $1EA2|!addr,x : and #$40 : bne ..midway 100 | lda $13CE|!addr : beq .return 101 | 102 | ..midway: 103 | ; Set the midway flag in the respawn entrance. 104 | lda !ram_respawn+1 : ora #$08 : sta !ram_respawn+1 105 | 106 | .return: 107 | rts 108 | 109 | .2: 110 | ; Get $13BF value in X. 111 | %lda_13BF() : tax 112 | 113 | ; Set current sublevel number as the respawn point. 114 | lda $010B|!addr : sta !ram_respawn 115 | lda $010C|!addr : bra .no_intro_store_entrance_high 116 | -------------------------------------------------------------------------------- /src/retry_config/code/hijacks/custom_midway.asm: -------------------------------------------------------------------------------- 1 | ;===================================== 2 | ; This inserts the custom midway objects. 3 | ; Main custom object code taken from ObjecTool 0.5 by 0x400 and imamelia. 4 | ; Custom midway code by worldpeace. 5 | ;===================================== 6 | 7 | if !use_custom_midway_bar 8 | 9 | pushpc 10 | 11 | org $0DA415 12 | jml new_norm_objects 13 | 14 | pullpc 15 | 16 | new_norm_objects: 17 | sep #$30 18 | 19 | ; Check if it's a custom normal object. 20 | lda $5A : cmp #$2D : beq .custom 21 | 22 | .not_custom: 23 | lda $1931|!addr 24 | jml $0DA41A|!bank 25 | 26 | .custom: 27 | ; Store the first new settings byte. 28 | ldy #$00 29 | lda [$65],y : sta $5A 30 | 31 | ; Store the second new settings byte. 32 | iny 33 | lda [$65],y : sta $58 34 | 35 | ; Add 2 to the pointer so it ends up in the correct place. 36 | ; SMW expects them to have 3 bytes but this has 5 bytes. 37 | iny 38 | tya : clc : adc $65 : sta $65 39 | lda $66 : adc #$00 : sta $66 40 | 41 | ; If ObjecTool is inserted... 42 | lda.l !rom_objectool_byte : cmp #$5C : bne .no_objectool 43 | 44 | ; ...jump to its code if the custom object number is $42-$4F or $52-$FF. 45 | lda $5A : cmp #$42 : bcc .no_objectool 46 | cmp #$50 : beq .no_objectool 47 | cmp #$51 : beq .no_objectool 48 | 49 | ; Jump to ObjecTool's custom normal objects code. 50 | ; This jumps in the middle of the NewNormObjects routine, right before PHB : PHK : PLB, 51 | ; assuming the code won't change in future updates. 52 | rep #$20 53 | lda.l !rom_objectool_normal_code_address : clc : adc.w #68 : sta $00 54 | sep #$20 55 | lda.l !rom_objectool_normal_code_address+2 : sta $02 56 | jml [$0000|!dp] 57 | 58 | .no_objectool: 59 | ; If midways are overridden, don't spawn it. 60 | lda !ram_midways_override : and #$7F : bne .return 61 | 62 | ; We only care about object 2D. 63 | jsr custom_midway 64 | 65 | .return: 66 | ; Jump back to an rts. 67 | jml $0DA53C|!bank 68 | 69 | custom_midway: 70 | ; Backup $59 ($58-$59 used for entrance info). 71 | lda $59 : pha 72 | stz $59 73 | 74 | ; Check which type of entrance it's set in the extra bytes. 75 | lda $5A : cmp #$50 : bcs .midway_entrance 76 | cmp #$40 : bcs .main_entrance 77 | cmp #$20 : bcs .secondary_water_entrance 78 | 79 | .secondary_entrance: 80 | and #$01 : ora #$02 81 | bra + 82 | 83 | .secondary_water_entrance: 84 | and #$01 : ora #$0A 85 | + sta $59 86 | lda $5A : and #$1E : asl #3 : tsb $59 87 | bra .end 88 | 89 | .main_entrance: 90 | and #$01 91 | bra + 92 | 93 | .midway_entrance: 94 | and #$01 : ora #$08 95 | + sta $59 96 | 97 | .end: 98 | ; If there's already enough custom midway objects, return. 99 | lda !ram_cust_obj_num : cmp.b #!max_custom_midway_num : bcs .return 100 | 101 | ; Update the custom midway objects counter. 102 | inc : sta !ram_cust_obj_num 103 | 104 | dec : asl : tax 105 | lda $57 106 | rep #$20 107 | and #$00FF : clc : adc $6B 108 | 109 | ; Store index to $7EC800. 110 | sec : sbc #$C800 : sta !ram_cust_obj_data,x 111 | 112 | ; Store entrance info. 113 | lda $58 : sta !ram_cust_obj_entr,x 114 | 115 | ; If this is the midway that triggered the current checkpoint, don't make it spawn. 116 | lda !ram_respawn : eor $58 : and #$FBFF 117 | sep #$20 118 | beq .return 119 | 120 | .spawn_midway: 121 | ldy $57 122 | lda #$38 : sta [$6B],y 123 | lda #$00 : sta [$6E],y 124 | lda $57 : and #$0F : beq .return 125 | dey 126 | lda #$35 : sta [$6B],y 127 | lda #$00 : sta [$6E],y 128 | 129 | .return 130 | ; Restore $59. 131 | pla : sta $59 132 | rts 133 | 134 | else 135 | 136 | ; Restore code, in case settings are changed. 137 | if read1($0DA415) == $5C && read1(!rom_objectool_byte) != $5C 138 | 139 | pushpc 140 | 141 | org $0DA415 142 | sep #$30 143 | lda $1931|!addr 144 | 145 | pullpc 146 | 147 | endif 148 | 149 | endif 150 | -------------------------------------------------------------------------------- /src/retry_config/code/hijacks/death_counter.asm: -------------------------------------------------------------------------------- 1 | ; Position to write the counter to in the status bar. 2 | !counter_status_bar = $0F15|!addr 3 | 4 | ; YXPCCCT properties of the "DEATHS" word. 5 | ; The first number is the palette, the second is the GFX page (0 or 1). 6 | ; If you want to change the word itself, look at the table below. 7 | !death_word_props = l3_prop(6,0) 8 | 9 | if !status_death_word 10 | 11 | pushpc 12 | 13 | ; Here you can edit which tiles are drawn to the status bar. 14 | ; The first value in l3_tile is the tile number. 15 | org $008C89 16 | dw l3_tile($0D,!death_word_props) ; D 17 | dw l3_tile($0E,!death_word_props) ; E 18 | dw l3_tile($0A,!death_word_props) ; A 19 | dw l3_tile($1D,!death_word_props) ; T 20 | dw l3_tile($11,!death_word_props) ; H 21 | dw l3_tile($1C,!death_word_props) ; S 22 | 23 | pullpc 24 | 25 | elseif read1($008F49) == $5C 26 | 27 | pushpc 28 | 29 | ; Restore the original tilemap. 30 | ; Here I assume that people won't turn on the "DEATHS" display without also turning on the death counter display. 31 | org $008C89 32 | db $30,$28,$31,$28,$32,$28,$33,$28,$34,$28,$FC,$38 33 | 34 | pullpc 35 | 36 | endif 37 | 38 | if !status_death_counter 39 | 40 | pushpc 41 | 42 | org $008F49 43 | jml status_death_counter 44 | 45 | pullpc 46 | 47 | status_death_counter: 48 | ldx #$04 49 | .tiles_loop: 50 | lda !ram_death_counter,x : sta !counter_status_bar,x 51 | dex : bpl .tiles_loop 52 | .hide_loop: 53 | inx 54 | lda !ram_death_counter,x : bne .return 55 | cpx #$04 : beq .return 56 | lda #$FC : sta !counter_status_bar,x 57 | bra .hide_loop 58 | .return: 59 | jml $008F5B|!bank 60 | 61 | else 62 | 63 | pushpc 64 | 65 | ; Restore the hijack if settings are changed. 66 | if read1($008F49) == $5C 67 | org $008F49 68 | lda $0DBE|!addr 69 | inc 70 | endif 71 | 72 | pullpc 73 | 74 | endif 75 | -------------------------------------------------------------------------------- /src/retry_config/code/hijacks/hex_edits.asm: -------------------------------------------------------------------------------- 1 | pushpc 2 | 3 | ; Change initial life counter. 4 | org $009E25 5 | db !initial_lives-1 6 | 7 | ; Fix for old initial sprite facing fix. 8 | if read1($01AD33) == $94 9 | org $01AD33 10 | db $D1 11 | endif 12 | 13 | if read1($01AD3A) == $95 14 | org $01AD3A 15 | db $D2 16 | endif 17 | 18 | ; Fix Message Box erasing some sprite tiles when closing. 19 | org $05B31B 20 | rts : db $69 21 | 22 | ; Prevent vanilla decrementing lives. 23 | org $00D0D8 24 | nop #3 25 | bra $09 26 | 27 | pullpc 28 | -------------------------------------------------------------------------------- /src/retry_config/code/hijacks/hurry_up.asm: -------------------------------------------------------------------------------- 1 | pushpc 2 | 3 | ; We could probably handle this with UberASM alone, 4 | ; but the dcsave patch uses this jml to check if Retry is installed, so we'll replicate that. 5 | org $008E5B 6 | jml hurry_flag 7 | 8 | pullpc 9 | 10 | hurry_flag: 11 | if not(!disable_hurry_up) 12 | ; Restore original code. 13 | lda #$FF : sta $1DF9|!addr 14 | 15 | ; Set the hurry up flag. 16 | lda #$01 : sta !ram_hurry_up 17 | endif 18 | 19 | ; Return to the original code. 20 | jml $008E60|!bank 21 | 22 | if !disable_hurry_up 23 | ; The dcsave patch uses read3($008E5B)+8 to read the Retry freeram 24 | ; so we need to preserve that. 4 bytes already used for the JML. 25 | dd $69696969 26 | dl !ram_hurry_up 27 | endif 28 | -------------------------------------------------------------------------------- /src/retry_config/code/hijacks/initial_facing_fix.asm: -------------------------------------------------------------------------------- 1 | pushpc 2 | 3 | if !initial_facing_fix 4 | 5 | org $05DA1C 6 | jml initial_facing_fix 7 | 8 | else 9 | 10 | ; Restore the original code. 11 | ; Don't force "No Yoshi Sign 2" intro if the fix is enabled. 12 | org $05DA1C 13 | if not(!no_yoshi_intro_fix) 14 | cmp #$52 15 | bcc $04 16 | else 17 | bra $06 18 | nop #2 19 | endif 20 | 21 | endif 22 | 23 | pullpc 24 | 25 | if !initial_facing_fix 26 | 27 | initial_facing_fix: 28 | ; Copy the next frame position to the current frame's. 29 | ; This fixes the direction for sprites using the SubHorzPosBnk1 routine. 30 | rep #$10 31 | ldx $94 : stx $D1 32 | ldx $96 : stx $D3 33 | sep #$10 34 | 35 | ; Restore the original code. 36 | ; Don't force "No Yoshi Sign 2" intro if the fix is enabled. 37 | if not(!no_yoshi_intro_fix) 38 | cmp #$52 : bcc + 39 | jml $05DA20|!bank 40 | + 41 | endif 42 | jml $05DA24|!bank 43 | 44 | endif 45 | -------------------------------------------------------------------------------- /src/retry_config/code/hijacks/item_box_fix.asm: -------------------------------------------------------------------------------- 1 | pushpc 2 | 3 | if !item_box_fix 4 | 5 | org $00C572 6 | jml item_box_fix 7 | 8 | else 9 | 10 | if read1($00C572) == $5C 11 | 12 | org $00C572 13 | lda $15 14 | and #$08 15 | 16 | endif 17 | endif 18 | 19 | pullpc 20 | 21 | if !item_box_fix 22 | 23 | item_box_fix: 24 | ; Don't drop the item if Mario is dead. 25 | lda $71 : cmp #$09 : bne + 26 | jml $00C58F|!bank 27 | + 28 | ; Restore original code. 29 | lda $15 : and #$08 30 | jml $00C576|!bank 31 | 32 | endif 33 | -------------------------------------------------------------------------------- /src/retry_config/code/hijacks/multiple_midways.asm: -------------------------------------------------------------------------------- 1 | pushpc 2 | 3 | ; Hijack level loading routine to load correct sublevel. 4 | org $05D842 5 | jml mmp_main 6 | 7 | ; Make midway entrances work correctly. 8 | org $05D9DA 9 | jml midway_entrance 10 | 11 | ; Make vanilla midway entrances work correctly 12 | org $05D9EC 13 | jml vanilla_midway_destination_fix 14 | 15 | ; Make secondary exits compatible with "No Yoshi" intros. 16 | org $05DAA3 17 | jsl no_yoshi 18 | 19 | pullpc 20 | 21 | ; Write a small identifier string in ROM. 22 | db "Retry patch v!version by KevinM" 23 | 24 | mmp_main: 25 | ; If not entering from the overworld, return. 26 | lda $141A|!addr : bne .return 27 | 28 | ; If it's a secondary exit, return. 29 | lda $1B93|!addr : bne .return 30 | 31 | ; If it's not the intro level, skip. 32 | lda $0109|!addr : beq .no_intro 33 | 34 | .intro: 35 | ; Filter title screen. 36 | cmp.b #!intro_level+$24 : bne ..return 37 | 38 | ; If the midway is set, load the level (use the backup since $1EA2 is reset earlier). 39 | lda $1EA2|!addr : and #$40 : bne ..midway 40 | 41 | ; Load the intro level. 42 | lda.b #!intro_level+$24 : bra ..return 43 | 44 | ..midway: 45 | ; Set to load level 0. 46 | ldx #$00 47 | ldy #$00 48 | bra .midway 49 | 50 | ..return: 51 | ; Return to level loading routine, after sta $13BF. 52 | jml $05D8A2|!bank 53 | 54 | .no_intro: 55 | ; Reset layer 1 and 2 X positions. 56 | rep #$20 57 | stz $1A 58 | stz $1E 59 | sep #$20 60 | 61 | ; Get current translevel number. 62 | jsr shared_get_translevel 63 | tay 64 | asl : tax 65 | 66 | ; If no midway was gotten, return. 67 | lda $1EA2|!addr,y : and #$40 : beq .return 68 | 69 | .midway: 70 | ; If we should load a secondary exit, branch. 71 | lda !ram_checkpoint+1,x : bit #$02 : bne .secondary_exit 72 | 73 | ; If we should load the Yoshi Wings level, do it. 74 | bit #$80 : beq + 75 | bit #$0A : bne + 76 | lda #$02 : sta $1B95|!addr 77 | dec : sta $0DC1|!addr 78 | + 79 | ; Store level number to load. 80 | rep #$20 81 | lda !ram_checkpoint,x : and #$01FF : sta $0E 82 | 83 | ; Return to level loading routine, after sta $0E/$0F. 84 | jml $05D8B7|!bank 85 | 86 | .return: 87 | ; Return to the beginning of level loading routine. 88 | jml $05D847|!bank 89 | 90 | .secondary_exit: 91 | ; Set entrance number. 92 | ora #$04 : sta $19D8|!addr 93 | lda !ram_checkpoint,x : sta $19B8|!addr 94 | stz $95 95 | stz $97 96 | 97 | ; Return to sublevel loading routine. 98 | jml $05D7B3|!bank 99 | 100 | midway_entrance: 101 | if !dynamic_ow_levels 102 | %lda_13BF() : tax 103 | lda $1EA2|!addr,x 104 | endif 105 | 106 | ; Restore original code. 107 | and #$40 : sta $13CF|!addr 108 | 109 | ; If no checkpoint was gotten, continue as normal. 110 | beq .normal 111 | 112 | .checkpoint: 113 | ; Check if the checkpoint destination is a midway entrance. 114 | phx 115 | txa : asl : tax 116 | lda.l !ram_checkpoint+1,x 117 | plx 118 | and #$0A : cmp #$08 : beq .midway 119 | 120 | .normal: 121 | jml $05D9EC|!bank 122 | 123 | .midway: 124 | lda $1EA2|!addr,x : and #$40 125 | ldx $1B93|!addr : bne .normal 126 | jml $05D9DE|!bank 127 | 128 | vanilla_midway_destination_fix: 129 | ; Skip if entering from the Overworld. 130 | lda $141A|!addr : beq .orig2 131 | 132 | ; Skip if not respawning in the level from Retry. 133 | lda !ram_is_respawning : beq .orig2 134 | 135 | ; Skip if the respawn entrance is not a midway entrance. 136 | lda !ram_respawn+1 : and #$0A : cmp #$08 : beq .midway 137 | 138 | .orig2: 139 | jmp .orig 140 | 141 | .midway: 142 | ; Get the destination level number in Y. 143 | rep #$30 144 | lda !ram_respawn : and #$01FF : tay 145 | sep #$20 146 | 147 | ; Check if the LM midway entrance patch is enabled. 148 | lda.l !rom_lm_midway_entrance_hack_byte : cmp #$22 : beq ..lm_midway_hack 149 | 150 | ..vanilla: 151 | ; If no separate entrances used, we just need to store the correct screen number. 152 | lda $F400,y : lsr #4 : sta $01 153 | jmp .orig 154 | 155 | ..lm_midway_hack: 156 | ; Backup $03 and $05 157 | pei ($03) 158 | pei ($05) 159 | 160 | ; Get the midway data pointer in $03 161 | lda.l $05D9E6|!bank : sta $05 162 | rep #$20 163 | lda.l $05D9E4|!bank : clc : adc #$000A : sta $03 164 | lda [$03] : pha 165 | inc $03 166 | lda [$03] : sta $04 167 | pla : sta $03 168 | sep #$20 169 | 170 | ; Set the screen number of midway entrance 171 | lda [$03],y : and #$10 : sta $01 172 | lda $F400,y : lsr #4 : ora $01 : sta $01 173 | 174 | ; Separate midway -> already set correctly 175 | lda [$03],y : bit #$20 : bne ..return 176 | 177 | ; Correct slippery/water flag for vanilla midway 178 | lda #$C0 : trb $192A|!addr 179 | lda $DE00,y : and #$C0 : ora $192A|!addr : sta $192A|!addr 180 | 181 | ; Correct the camera position for vanilla midway 182 | lda #$00 : xba 183 | lda $F400,y : sta $02 184 | and #$03 : tax 185 | lda $D70C,x : sta $20 186 | lda $02 : and #$0C : lsr #2 : tax 187 | lda $D708,x : sta $1C 188 | 189 | ; Correct the position if X/Y pos method 2 is used 190 | lda $D97D : cmp #$22 : bne ..return 191 | 192 | ; (now compatible with LM 3.00's routine at $05DD30) 193 | lda $D980 : sta $05 194 | rep #$20 195 | lda $D97E : clc : adc #$0004 : sta $03 196 | sep #$20 197 | jsl .jml 198 | 199 | ..return: 200 | ; Restore $03 and $05 201 | rep #$20 202 | pla : sta $05 203 | pla : sta $03 204 | sep #$20 205 | 206 | .orig: 207 | rep #$10 208 | lda $01 209 | jml $05D9F0|!bank 210 | 211 | .jml: 212 | jml [$0003|!dp] 213 | 214 | no_yoshi: 215 | ; Reset secondary exits flag. 216 | stz $1B93|!addr 217 | 218 | ; Restore original code. 219 | lda.l $05D78A|!bank,x 220 | rtl 221 | -------------------------------------------------------------------------------- /src/retry_config/code/hijacks/remove_status_bar.asm: -------------------------------------------------------------------------------- 1 | ; Adapted from Lui's "Remove Status Bar" patch 2 | 3 | if !remove_vanilla_status_bar 4 | 5 | pushpc 6 | 7 | org $0081F4 8 | bra $01 : db $69 9 | 10 | org $008275 11 | jml nmi_hijack : db $69 12 | 13 | org $0082E8 14 | bra $01 : db $69 15 | 16 | org $00985A 17 | bra $01 : db $69 18 | 19 | org $00A5A8 20 | bra $01 : db $69 21 | 22 | pullpc 23 | 24 | nmi_hijack: 25 | lda $0D9B|!addr : bne .special 26 | if !sa1 27 | ldx #$81 28 | else 29 | lda #$81 : sta $4200 30 | endif 31 | lda $22 : sta $2111 32 | lda $23 : sta $2111 33 | lda $24 : sta $2112 34 | lda $25 : sta $2112 35 | lda $3E : sta $2105 36 | lda $40 : sta $2131 37 | jml $0082B0|!bank 38 | .special: 39 | jml $00827A|!bank 40 | 41 | else 42 | 43 | pushpc 44 | 45 | if read1($0081F4+2) == $69 46 | org $0081F4 47 | jsr $8DAC 48 | endif 49 | 50 | if read1($008275+4) == $69 51 | org $008275 52 | lda $0D9B|!addr 53 | beq $18 54 | endif 55 | 56 | if read1($0082E8+2) == $69 57 | org $0082E8 58 | jsr $8DAC 59 | endif 60 | 61 | if read1($00985A+2) == $69 62 | org $00985A 63 | jsr $8CFF 64 | endif 65 | 66 | if read1($00A5A8+2) == $69 67 | org $00A5A8 68 | jsr $8CFF 69 | endif 70 | 71 | pullpc 72 | 73 | endif 74 | -------------------------------------------------------------------------------- /src/retry_config/code/hijacks/sram.asm: -------------------------------------------------------------------------------- 1 | ; This file handles expanding the normal SRAM and saving custom addresses to it. 2 | ; It works on both lorom (SRAM) and SA-1 (BW-RAM). 3 | 4 | ; Bank byte of the SRAM/BW-RAM address. 5 | !sram_bank = (!sram_addr>>16) 6 | !sram_defaults_bank = (tables_sram_defaults>>16) 7 | 8 | ; How big is the save table. 9 | !save_table_size = (tables_sram_defaults-tables_save) 10 | !save_table_size_game_over = (tables_save_not_game_over-tables_save) 11 | 12 | if !sram_feature 13 | 14 | pushpc 15 | 16 | ; Change SRAM size in the header. 17 | if read1($00FFD8) < !sram_size 18 | org $00FFD8 19 | db !sram_size 20 | endif 21 | 22 | ; Hijack save game routine. 23 | org $009BCB 24 | jml save_game 25 | 26 | ; Hijack load game routine. 27 | org $009CF5 28 | jml load_game 29 | 30 | pullpc 31 | 32 | ; Some helper macros. 33 | macro transfer(src,dst) 34 | pla 35 | mvn , 36 | bra ..next 37 | endmacro 38 | 39 | macro next_iteration() 40 | lda $02 : clc : adc $04 : sta $02 41 | plb : plx 42 | txa : clc : adc #$0005 : tax 43 | cpx $06 : bcc .loop 44 | endmacro 45 | 46 | ;===================================== 47 | ; save_game routine 48 | ;===================================== 49 | save_game: 50 | ; Set the DBR. 51 | phk : plb 52 | 53 | ; Call the custom save routine. 54 | php : phb 55 | jsr extra_save_file 56 | plb : plp 57 | 58 | jsr get_sram_addr : sta $02 59 | lda.w #!save_table_size : sta $06 60 | ldx #$0000 61 | .loop: 62 | lda.w tables_save,x : sta $00 63 | phx : phb 64 | lda.w tables_save+3,x : sta $04 65 | dec : pha 66 | lda.w tables_save+2,x 67 | ldx $00 68 | ldy $02 69 | and #$00FF : beq ..use_00 70 | cmp #$007E : beq ..use_7E 71 | if !sa1 72 | cmp #$007F : beq ..use_7F 73 | cmp #$0040 : beq ..use_40 74 | ..use_41: 75 | %transfer($41,!sram_bank) 76 | ..use_40: 77 | %transfer($40,!sram_bank) 78 | endif 79 | ..use_7F: 80 | %transfer($7F,!sram_bank) 81 | ..use_7E: 82 | %transfer($7E,!sram_bank) 83 | ..use_00: 84 | %transfer($00|!bank8,!sram_bank) 85 | ..next: 86 | %next_iteration() 87 | .end: 88 | sep #$30 89 | 90 | ; Restore original code and jump back. 91 | plb 92 | ldx $010A|!addr 93 | jml $009BCF|!bank 94 | 95 | ;===================================== 96 | ; load_game routine 97 | ;===================================== 98 | load_game: 99 | ; Load or init the file 100 | beq + 101 | jmp init_file 102 | + 103 | ; Preserve DB, X, Y, P. 104 | phb : phk : plb 105 | phx : phy : php 106 | 107 | ; Call the custom load routine. 108 | sep #$30 109 | php : phb 110 | jsr extra_load_file 111 | plb : plp 112 | 113 | ; Set the save table size. 114 | rep #$30 115 | lda.w #!save_table_size : sta $06 116 | 117 | ; Load the save file. 118 | jsr load_file 119 | 120 | ; Restore DBR, P, X and Y. 121 | plp : ply : plx 122 | plb 123 | 124 | ; Restore original code and jump back. 125 | phx 126 | stz $0109|!addr 127 | jml $009CFB|!bank 128 | 129 | load_game_over: 130 | ; Preserve DB, X, Y, P. 131 | phb : phk : plb 132 | phx : phy : php 133 | 134 | ; Set the save table size. 135 | rep #$30 136 | lda.w #!save_table_size_game_over : sta $06 137 | 138 | ; Load the save file. 139 | jsr load_file 140 | 141 | ; Restore DBR, P, X and Y. 142 | plp : ply : plx 143 | plb 144 | rtl 145 | 146 | load_file: 147 | jsr get_sram_addr : sta $02 148 | ldx #$0000 149 | .loop: 150 | lda.w tables_save,x : tay 151 | phx : phb 152 | lda.w tables_save+3,x : sta $04 153 | dec : pha 154 | lda.w tables_save+2,x 155 | ldx $02 156 | and #$00FF : beq ..use_00 157 | cmp #$007E : beq ..use_7E 158 | if !sa1 159 | cmp #$007F : beq ..use_7F 160 | cmp #$0040 : beq ..use_40 161 | ..use_41: 162 | %transfer(!sram_bank,$41) 163 | ..use_40: 164 | %transfer(!sram_bank,$40) 165 | endif 166 | ..use_7F: 167 | %transfer(!sram_bank,$7F) 168 | ..use_7E: 169 | %transfer(!sram_bank,$7E) 170 | ..use_00: 171 | %transfer(!sram_bank,$00|!bank8) 172 | ..next: 173 | %next_iteration() 174 | .end: 175 | rts 176 | 177 | init_file: 178 | ; Preserve X and Y. 179 | phx : phy 180 | 181 | ; Set 8 bit X/Y for the custom routine. 182 | sep #$10 183 | 184 | ; Set DBR. 185 | phb : phk : plb 186 | 187 | ; Call the custom load routine. 188 | php : phb 189 | jsr extra_load_new_file 190 | plb : plp 191 | 192 | rep #$30 193 | lda.w #tables_sram_defaults : sta $02 194 | lda.w #!save_table_size : sta $06 195 | ldx #$0000 196 | .loop: 197 | lda.w tables_save,x : tay 198 | phx : phb 199 | lda.w tables_save+3,x : sta $04 200 | dec : pha 201 | lda.w tables_save+2,x 202 | ldx $02 203 | and #$00FF : beq ..use_00 204 | cmp #$007E : beq ..use_7E 205 | if !sa1 206 | cmp #$007F : beq ..use_7F 207 | cmp #$0040 : beq ..use_40 208 | ..use_41: 209 | %transfer(!sram_defaults_bank,$41) 210 | ..use_40: 211 | %transfer(!sram_defaults_bank,$40) 212 | endif 213 | ..use_7F: 214 | %transfer(!sram_defaults_bank,$7F) 215 | ..use_7E: 216 | %transfer(!sram_defaults_bank,$7E) 217 | ..use_00: 218 | %transfer(!sram_defaults_bank,$00|!bank8) 219 | ..next: 220 | %next_iteration() 221 | ..end: 222 | ; Initialize the intro level checkpoint. 223 | jsr shared_get_intro_sublevel 224 | sta !ram_checkpoint 225 | 226 | ; Keep 16 bit X/Y for the original code. 227 | sep #$20 228 | 229 | ; Restore DBR, Y and X. 230 | plb : ply : plx 231 | 232 | ; Jump back. 233 | jml $009D22|!bank 234 | 235 | ;===================================== 236 | ; get_sram_addr routine. 237 | ; 238 | ; Small routine to get the low and high byte of the destination address into $02. 239 | ;===================================== 240 | get_sram_addr: 241 | rep #$30 242 | lda $010A|!addr : and #$00FF : asl : tax 243 | lda.l .sram_addr,x 244 | rts 245 | 246 | .sram_addr: 247 | dw !sram_addr,!sram_addr+!file_size,!sram_addr+(2*!file_size) 248 | 249 | else 250 | 251 | ; Restore code, in case settings are changed. 252 | if not(!sram_plus) && not(!bwram_plus) 253 | 254 | pushpc 255 | 256 | if read1($00FFD8) == !sram_size 257 | org $00FFD8 258 | db $01 259 | endif 260 | 261 | if read1($009BCB) == $5C 262 | org $009BCB 263 | plb 264 | ldx $010A|!addr 265 | endif 266 | 267 | if read1($009CF5) == $5C 268 | org $009CF5 269 | bne $2B 270 | phx 271 | stz $0109|!addr 272 | endif 273 | 274 | pullpc 275 | 276 | endif 277 | 278 | endif 279 | -------------------------------------------------------------------------------- /src/retry_config/code/hijacks/switch_palace_message_fix.asm: -------------------------------------------------------------------------------- 1 | ; This fixes the switch palace message sprite tiles having the wrong size 2 | ; when drawing sprites using UberASM Tool's gamemode 14 end label. 3 | ; This happens because vanilla only sets $0400 but not $0420. 4 | 5 | pushpc 6 | 7 | org $05B30E 8 | jsl switch_palace_message_fix 9 | 10 | pullpc 11 | 12 | switch_palace_message_fix: 13 | phy 14 | sep #$20 15 | tya : lsr #2 : tay 16 | lda #$00 : sta $0420|!addr,y 17 | rep #$20 18 | ply 19 | dey #4 20 | rtl 21 | -------------------------------------------------------------------------------- /src/retry_config/code/hijacks/vanilla_boss_gm13.asm: -------------------------------------------------------------------------------- 1 | ;============================================ 2 | ; This hijacks runs the level_init_3 code during the 3 | ; vanilla mode 7 bosses level loading. 4 | ; This is needed because gamemode 13 UberASM code 5 | ; isn't run when loading these levels. 6 | ;============================================ 7 | 8 | pushpc 9 | 10 | org $009856 11 | jsl vanilla_boss_gm13 12 | 13 | pullpc 14 | 15 | vanilla_boss_gm13: 16 | ; Restore original code 17 | lda #$20 : sta $44 18 | 19 | ; Run gamemode 13 code 20 | jmp level_init_3_init 21 | -------------------------------------------------------------------------------- /src/retry_config/code/hijacks/vanilla_midway.asm: -------------------------------------------------------------------------------- 1 | ;===================================== 2 | ; Hijack to the midway interaction routine to correctly handle checkpoints. 3 | ; Also handles skipping the midway powerup if applicable. 4 | ;===================================== 5 | 6 | pushpc 7 | 8 | org $00F2D8 9 | jml midway_main 10 | 11 | org $0DA691 12 | jml midway_spawn 13 | 14 | pullpc 15 | 16 | ;===================================== 17 | ; midway_main routine 18 | ; 19 | ; Handles giving the correct checkpoint when touching a midway. 20 | ;===================================== 21 | midway_main: 22 | ; Get the index of this tile in the map16 table. 23 | phx 24 | rep #$20 25 | pei ($04) 26 | jsr get_tile_index 27 | sep #$20 28 | 29 | ; If there's no custom midways in this sublevel, skip. 30 | lda !ram_cust_obj_num : dec : bmi .not_custom 31 | 32 | ; Loop through all custom midways IDs to see if this one is custom. 33 | asl : tax 34 | rep #$20 35 | .find_custom_midway_loop: 36 | lda !ram_cust_obj_data,x : cmp $04 : bne ..next 37 | jmp .custom 38 | ..next: 39 | dex #2 : bpl .find_custom_midway_loop 40 | sep #$20 41 | 42 | .not_custom: 43 | ; Signal that we have to set a normal midway. 44 | lda #$00 : sta !ram_set_checkpoint 45 | bra .return 46 | 47 | .custom: 48 | ; Set the respawn entrance value. 49 | lda !ram_cust_obj_entr,x : sta !ram_set_checkpoint 50 | 51 | .return: 52 | ; Restore $04. 53 | rep #$20 54 | pla : sta $04 55 | sep #$20 56 | 57 | ; Call the custom midway routine. 58 | ; (we already did PHX earlier). 59 | phy : php : phb : phk : plb 60 | jsr extra_midway 61 | plb : plp : ply : plx 62 | 63 | ; Only run the powerup code if applicable. 64 | ; If using the "SMB2-Styled" Health Bar patch, this should prevent healing 65 | ; at midways unless the flag is set. 66 | lda !ram_midway_powerup : beq + 67 | jml $00F2E0|!bank 68 | + jml $00F2E8|!bank 69 | 70 | ;===================================== 71 | ; Routine to get a block's $7EC800 index in $04 (16 bit). 72 | ; It should be run during the block interaction process. 73 | ;===================================== 74 | get_tile_index: 75 | phy : phx : php 76 | sep #$30 77 | lda $5B : lsr : bcs .vert 78 | 79 | .horz: 80 | lda $1933|!addr : beq + 81 | lda $9B : ora #$10 82 | bra ++ 83 | + lda $9B 84 | ++ tax 85 | 86 | lda.l !rom_lm_version : cmp #$33 87 | rep #$20 88 | bcc + 89 | lda $13D7|!addr 90 | bra ++ 91 | + lda #$01B0 92 | ++ sta $04 93 | 94 | jsr .multiply 95 | 96 | lda $9A : and #$00F0 : lsr #4 97 | clc : adc $04 : sta $04 98 | lda $98 : and #$FFF0 99 | clc : adc $04 : sta $04 100 | 101 | plp : plx : ply 102 | rts 103 | 104 | .vert: 105 | lda $1933|!addr : beq + 106 | lda $9B : clc : adc #$0E 107 | bra ++ 108 | + lda $9B 109 | ++ asl : ora $99 : sta $05 110 | 111 | lda $9A : lsr #4 : sta $04 112 | lda $98 : and #$F0 : tsb $04 113 | 114 | plp : plx : ply 115 | rts 116 | 117 | ;===================================== 118 | ; Input: 119 | ; X: a, 8bit, unsigned. 120 | ; $04: b, 16bit, unsigned. 121 | ; output: 122 | ; $04: a*b, 16bit (least significant), unsigned. 123 | ;===================================== 124 | .multiply 125 | pei ($00) 126 | pei ($02) 127 | sep #$20 128 | 129 | stz $02 130 | 131 | if !sa1 == 0 132 | stx $4202 133 | lda $04 : sta $4203 134 | nop #3 135 | rep #$20 136 | lda $4216 : sta $00 137 | sep #$20 138 | 139 | ;stx $4202 140 | lda $05 : sta $4203 141 | rep #$20 142 | lda $01 : clc : adc $4216 : sta $01 143 | else 144 | stz $2250 145 | 146 | rep #$20 147 | txa : and #$00FF : sta $2251 148 | lda $04 : and #$00FF : sta $2253 149 | bra $00 150 | lda $2306 : sta $00 151 | 152 | stz $2250 153 | txa : and #$00FF : sta $2251 154 | lda $05 : and #$00FF : sta $2253 155 | lda $01 : clc : adc $2306 : sta $01 156 | endif 157 | 158 | lda $00 : sta $04 159 | pla : sta $02 160 | pla : sta $00 161 | rts 162 | 163 | ;===================================== 164 | ; midway_spawn routine 165 | ; 166 | ; Handles spawning the midway if the current checkpoint wasn't from itself. 167 | ;===================================== 168 | midway_spawn: 169 | ; If midways are overridden, don't spawn it. 170 | lda !ram_midways_override : and #$7F : bne .no_spawn 171 | 172 | ; Filter title screen, etc. 173 | lda $0109|!addr : beq .no_intro 174 | cmp.b #!intro_level+$24 : bne .spawn 175 | 176 | .no_intro: 177 | lda $1EA2|!addr,x : and #$40 : bne .checkpoint 178 | lda $13CE|!addr : bne .checkpoint 179 | 180 | .spawn: 181 | jml $0DA69E|!bank 182 | 183 | .checkpoint: 184 | ; Check if the checkpoint is for the main or sublevel. 185 | jsr shared_get_checkpoint_value 186 | cmp #$01 : bcs ..sublevel 187 | 188 | ..main: 189 | %lda_13BF() : bne ...no_intro 190 | jsr shared_get_intro_sublevel 191 | bra + 192 | 193 | ...no_intro: 194 | rep #$20 195 | and #$00FF : cmp #$0025 : bcc + 196 | clc : adc #$00DC 197 | bra + 198 | 199 | ..sublevel: 200 | rep #$20 201 | lda $010B|!addr 202 | + ora #$0C00 : eor !ram_respawn : and #$FBFF 203 | sep #$20 204 | bne .spawn 205 | 206 | .no_spawn: 207 | jml $0DA6B0|!bank 208 | -------------------------------------------------------------------------------- /src/retry_config/code/include/misc.asm: -------------------------------------------------------------------------------- 1 | ; Miscellaneous stuff used by Retry. 2 | ; You usually shouldn't edit this file. 3 | 4 | ; Retry version number to write in ROM. 5 | !version = "0.8.1" 6 | 7 | ; What button exits the level while the game is paused (by default, select). 8 | !exit_level_buttons_addr = $16 9 | !exit_level_buttons_bits = $20 10 | 11 | ; Level number of the intro level (automatically adjusted to $01C5 when necessary). 12 | !intro_level = $00C5 13 | 14 | ; Read death time from ROM. 15 | !death_time #= read1($00F61C) 16 | 17 | ; Check which channel is used for windowing HDMA, for SA-1 v1.35 (H)DMA remap compatibility. 18 | ; It will be 7 on lorom or with SA-1 <1.35, and 1 with SA-1 >=1.35. 19 | !window_mask #= read1($0092A1) 20 | !window_channel #= log2(!window_mask) 21 | 22 | ; DMA channel used to upload the Retry prompt tiles. 23 | ; You should never need to edit this. 24 | !prompt_channel = 2 25 | 26 | ; Where in VRAM the prompt tiles will be uploaded to. 27 | ; You should never need to edit this. 28 | !sprite_vram = $6000 29 | 30 | ; Default amount of Yoshi Coins per level, used for the sprite status bar. 31 | ; Note that usually this is not used, as the value is read from the ROM. 32 | ; In case of patches editing the area around $00F346 (except for the 33 | ; "Per Level Yoshi Coins Amount" patch) then this value will be used. 34 | !default_dc_amount = 5 35 | 36 | ; Default X/Y position values for the Retry prompt text. 37 | ; These values are used when the black box is enabled, otherwise the values 38 | ; in setting.asm (or in the respective RAM addresses if used) are used. 39 | ; These are not recommended to be changed unless you also change the 40 | ; black box windowing configuration. 41 | !default_text_x_pos = $58 42 | !default_text_y_pos = $6F 43 | 44 | ; Stripe image table defines. 45 | !stripe_index = $7F837B 46 | !stripe_table = $7F837D 47 | 48 | ; Address for the custom midway amount. 49 | !ram_cust_obj_num = !ram_cust_obj_data+(!max_custom_midway_num*4) 50 | 51 | ; Address for the custom midway entrance value. 52 | !ram_cust_obj_entr = !ram_cust_obj_data+(!max_custom_midway_num*2) 53 | 54 | ; Define the custom sprites load table address. 55 | %define_sprite_table(sprite_load_table, $7FAF00, $418A00) 56 | 57 | ; SRAM size in the ROM header. Actual size is (2^!sram_size) KB. 58 | ; Not used on SA-1 roms. 59 | !sram_size = $03 60 | 61 | ; How big (in bytes) each save file is in SRAM/BW-RAM. 62 | !file_size = $0955 63 | 64 | ; SRAM/BW-RAM address to save to. 65 | if !sa1 66 | !sram_addr = $41A000 67 | else 68 | !sram_addr = $700400 69 | endif 70 | 71 | ; OW translevel number table. 72 | if !sa1 73 | !7ED000 = $40D000 74 | else 75 | !7ED000 = $7ED000 76 | endif 77 | 78 | ; Detect the SRAM Plus patch. 79 | if read1($009B42) == $04 80 | !sram_plus = 1 81 | else 82 | !sram_plus = 0 83 | endif 84 | 85 | ; Detect the BW-RAM Plus patch. 86 | if read1($009BD2) == $5C 87 | !bwram_plus = 1 88 | else 89 | !bwram_plus = 0 90 | endif 91 | 92 | ; Detects lx5's Custom Powerups. 93 | if read2($00D067) == $DEAD 94 | !custom_powerups = 1 95 | else 96 | !custom_powerups = 0 97 | endif 98 | 99 | ; Detects the "Level Depending on Ram" and similar patches. 100 | if read1($05DCDD) == $22 || read1($05DCE2) == $22 101 | !dynamic_ow_levels = 1 102 | else 103 | !dynamic_ow_levels = 0 104 | endif 105 | 106 | ; Detects if SA-1 MaxTile is inserted. 107 | if read1($00FFD5) == $23 && read3($0084C0) == $5A123 && read1($0084C3) >= 140 108 | !maxtile = 1 109 | !maxtile_buffer_max = $6180 110 | !maxtile_buffer_high = $6190 111 | !maxtile_buffer_normal = $61A0 112 | !maxtile_buffer_low = $61B0 113 | else 114 | !maxtile = 0 115 | endif 116 | -------------------------------------------------------------------------------- /src/retry_config/code/include/rom.asm: -------------------------------------------------------------------------------- 1 | ; Defines for useful ROM addresses 2 | ; Most of them are used to check for the presence and hijack different tools and patches. 3 | !rom_death_pose #= $00D0B9|!bank 4 | !rom_death_song #= $00F60B|!bank 5 | !rom_timer_ticks #= $008D8B|!bank 6 | !rom_green_star_block_count #= $0091AC|!bank 7 | !rom_yoshi_tongue_extend_speed #= $01F319|!bank 8 | !rom_lm_version #= $0FF0B4|!bank 9 | !rom_lm_get_screen_routine #= $03BCDC|!bank 10 | !rom_objectool_byte #= $0DA106|!bank 11 | !rom_objectool_normal_code_address #= $0DA107|!bank 12 | !rom_amk_byte #= $008075|!bank 13 | !rom_dcsave_byte #= $05D7AB|!bank 14 | !rom_dcsave_init_address #= $05D7AC|!bank 15 | !rom_dcsave_midpoint_byte #= $00CA2B|!bank 16 | !rom_dcsave_midpoint_address #= $00CA2C|!bank 17 | !rom_sprite_load_orig #= $01AC9F|!bank 18 | !rom_initial_submap #= $009EF0|!bank 19 | !rom_sprite_19_fix_byte #= $01E762|!bank 20 | !rom_sumo_bro_lightning_y_speed #= $02DEB6|!bank 21 | !rom_dc_amount_cmp_byte #= $00F349|!bank 22 | !rom_dc_perlevel_patch_byte #= $00F346|!bank 23 | !rom_lm_midway_entrance_hack_byte #= $05D9E3|!bank 24 | -------------------------------------------------------------------------------- /src/retry_config/code/include/tables.asm: -------------------------------------------------------------------------------- 1 | checkpoint_effect: 2 | fillbyte $00 : fill $200 3 | 4 | sfx_echo: 5 | fillbyte $00 : fill $40 6 | 7 | reset_rng: 8 | fillbyte $FF : fill $40 9 | 10 | disable_room_cp_sfx: 11 | fillbyte $00 : fill $40 12 | 13 | lose_lives: 14 | fillbyte $FF : fill $40 15 | 16 | macro _check_level(level, macro_name) 17 | if < 0 || > $1FF 18 | error "Error: % level values needs to be between $000 and $1FF!" 19 | endif 20 | endmacro 21 | 22 | macro _define_bitwise_index(level) 23 | !__idx #= ()>>3 24 | endmacro 25 | 26 | function _bitwise_table_value(level) = (1<<(7-((level)&7))) 27 | 28 | macro checkpoint(level, val) 29 | %_check_level(, "checkpoint") 30 | if < 0 || > 3 31 | error "Error: %checkpoint value needs to be between 0 and 3!" 32 | endif 33 | 34 | !__idx #= 35 | !{_checkpoint_effect_!{__idx}} ?= 0 36 | !{_checkpoint_effect_!{__idx}} #= !{_checkpoint_effect_!{__idx}}|() 37 | 38 | pushpc 39 | 40 | org tables_checkpoint_effect+!__idx 41 | db !{_checkpoint_effect_!{__idx}} 42 | 43 | pullpc 44 | endmacro 45 | 46 | macro retry(level, val) 47 | %_check_level(, "retry") 48 | if < 0 || > 4 49 | error "Error: %retry value needs to be between 0 and 4!" 50 | endif 51 | 52 | !__idx #= 53 | !{_checkpoint_effect_!{__idx}} ?= 0 54 | !{_checkpoint_effect_!{__idx}} #= !{_checkpoint_effect_!{__idx}}|(()<<4) 55 | 56 | pushpc 57 | 58 | org tables_checkpoint_effect+!__idx 59 | db !{_checkpoint_effect_!{__idx}} 60 | 61 | pullpc 62 | endmacro 63 | 64 | macro sfx_echo(level) 65 | %_check_level(, "sfx_echo") 66 | 67 | %_define_bitwise_index() 68 | !{_sfx_echo_!{__idx}} ?= 0 69 | !{_sfx_echo_!{__idx}} #= !{_sfx_echo_!{__idx}}|_bitwise_table_value() 70 | 71 | pushpc 72 | 73 | org tables_sfx_echo+!__idx 74 | db !{_sfx_echo_!{__idx}} 75 | 76 | pullpc 77 | endmacro 78 | 79 | macro no_reset_rng(level) 80 | %_check_level(, "no_reset_rng") 81 | 82 | %_define_bitwise_index() 83 | !{_no_reset_rng_!{__idx}} ?= 0 84 | !{_no_reset_rng_!{__idx}} #= !{_no_reset_rng_!{__idx}}|_bitwise_table_value() 85 | 86 | pushpc 87 | 88 | org tables_reset_rng+!__idx 89 | db !{_no_reset_rng_!{__idx}}^$FF 90 | 91 | pullpc 92 | endmacro 93 | 94 | macro no_room_cp_sfx(level) 95 | %_check_level(, "no_room_cp_sfx") 96 | 97 | %_define_bitwise_index() 98 | !{no_room_cp_sfx_!{__idx}} ?= 0 99 | !{no_room_cp_sfx_!{__idx}} #= !{no_room_cp_sfx_!{__idx}}|_bitwise_table_value() 100 | 101 | pushpc 102 | 103 | org tables_disable_room_cp_sfx+!__idx 104 | db !{no_room_cp_sfx_!{__idx}} 105 | 106 | pullpc 107 | endmacro 108 | 109 | macro no_lose_lives(level) 110 | %_check_level(, "no_lose_lives") 111 | 112 | %_define_bitwise_index() 113 | !{_no_lose_lives_!{__idx}} ?= 0 114 | !{_no_lose_lives_!{__idx}} #= !{_no_lose_lives_!{__idx}}|_bitwise_table_value() 115 | 116 | pushpc 117 | 118 | org tables_lose_lives+!__idx 119 | db !{_no_lose_lives_!{__idx}}^$FF 120 | 121 | pullpc 122 | endmacro 123 | 124 | macro checkpoint_retry(level, checkpoint, retry) 125 | %checkpoint(, ) 126 | %retry(, ) 127 | endmacro 128 | 129 | macro settings(level, checkpoint, retry, sfx_echo, no_reset_rng, no_room_cp_sfx, no_lose_lives) 130 | %checkpoint_retry(, , ) 131 | if != 0 132 | %sfx_echo() 133 | endif 134 | if != 0 135 | %no_reset_rng() 136 | endif 137 | if != 0 138 | %no_room_cp_sfx() 139 | endif 140 | if != 0 141 | %no_lose_lives() 142 | endif 143 | endmacro 144 | -------------------------------------------------------------------------------- /src/retry_config/code/level_init_1.asm: -------------------------------------------------------------------------------- 1 | ; Gamemode 11 2 | 3 | init: 4 | ; Reset frame counters and layer 1 and 2 X positions. 5 | rep #$20 6 | stz $13 7 | stz $1A 8 | stz $1E 9 | sep #$20 10 | 11 | ; Reset the custom midway object counter. 12 | lda #$00 : sta !ram_cust_obj_num 13 | 14 | ; Don't trigger the prompt by accident, and reset the death flag. 15 | sta !ram_prompt_phase 16 | sta !ram_is_dying 17 | 18 | ; Check if we entered from the overworld. 19 | lda $141A|!addr : bne .skip 20 | 21 | ; The game sets $13BF a bit later so we need to do it ourselves 22 | ; (unless it's right after a "No Yoshi" cutscene). 23 | lda $71 : cmp #$0A : bne + 24 | %lda_13BF() 25 | bra ++ 26 | + jsr shared_get_translevel 27 | ++ asl : tax 28 | 29 | ; Don't trigger Yoshi init. 30 | lda #$00 : sta !ram_is_respawning 31 | 32 | ; Reset hurry up flag. 33 | sta !ram_hurry_up 34 | 35 | ; Call the custom reset routine. 36 | phx : php 37 | phb : phk : plb 38 | jsr extra_reset 39 | plb 40 | plp : plx 41 | 42 | ; Set the destination from the level's checkpoint value. 43 | rep #$20 44 | lda !ram_checkpoint,x : sta !ram_respawn 45 | sep #$20 46 | 47 | .skip: 48 | ; Reset Yoshi, but only if respawning, not during the Yoshi Wings entrance 49 | ; and not parked outside of a Castle/Ghost House. 50 | lda !ram_is_respawning : beq + 51 | lda $1B95|!addr : bne + 52 | if !counterbreak_yoshi != 1 && !counterbreak_yoshi != 2 53 | lda $1B9B|!addr : bne + 54 | endif 55 | stz $0DC1|!addr 56 | + 57 | rtl 58 | -------------------------------------------------------------------------------- /src/retry_config/code/level_init_2.asm: -------------------------------------------------------------------------------- 1 | ; Gamemode 12 2 | 3 | init: 4 | ; Reset the "play CP sfx" flag. 5 | lda #$00 : sta !ram_play_sfx 6 | 7 | ; Set layer 2 interaction offsets 8 | ; (prevents layer 2 interaction from glitching on level load) 9 | jsl $05BC72|!bank 10 | 11 | ; Check if we entered from the overworld. 12 | lda $141A|!addr : beq .return 13 | 14 | ; Check if it's a normal room transition. 15 | lda !ram_is_respawning : bne .return 16 | 17 | .room_transition: 18 | ; Otherwise, check if we should count this entrance as a checkpoint. 19 | jsr shared_get_checkpoint_value 20 | cmp #$02 : bcc .return 21 | 22 | ; If entrance checkpoints are overridden, skip it. 23 | lda !ram_midways_override : bmi .return 24 | 25 | ..set_checkpoint: 26 | ; Set the checkpoint to the current entrance. 27 | rep #$20 28 | lda !ram_door_dest : sta !ram_respawn 29 | sep #$20 30 | 31 | ; Update the checkpoint value. 32 | jsr shared_hard_save 33 | 34 | ; Call the custom checkpoint routine. 35 | php : phb : phk : plb 36 | jsr extra_room_checkpoint 37 | plb : plp 38 | 39 | ; Set the "play CP sfx" flag if applicable. 40 | if !room_cp_sfx != $00 41 | jsr shared_get_bitwise_mask 42 | and.l tables_disable_room_cp_sfx,x : bne + 43 | lda #$01 : sta !ram_play_sfx 44 | + 45 | endif 46 | 47 | ; Save individual dcsave buffers. 48 | jsr shared_dcsave_midpoint 49 | 50 | .return: 51 | rtl 52 | -------------------------------------------------------------------------------- /src/retry_config/code/level_init_3.asm: -------------------------------------------------------------------------------- 1 | ; Gamemode 6, 13 2 | 3 | init: 4 | if !pipe_entrance_freeze < 2 5 | ; If in the pipe entrance animation, lock/unlock sprites. 6 | lda $71 : cmp #$05 : bcc + 7 | cmp #$07 : bcs + 8 | lda.b #!pipe_entrance_freeze : sta $9D 9 | + 10 | endif 11 | 12 | ; If goal walk is in progress, reset the music to play. 13 | ; This ensures the song will be reloaded if dying and respawning in the same sublevel. 14 | lda $1493|!addr : beq + 15 | lda #$FF : sta $0DDA|!addr 16 | + 17 | ; Play the silent checkpoint SFX if applicable. 18 | if !room_cp_sfx != $00 19 | lda !ram_play_sfx : beq + 20 | lda.b #!room_cp_sfx : sta !room_cp_sfx_addr|!addr 21 | + 22 | endif 23 | 24 | ; If AMK is inserted, send the disable/enable SFX echo command 25 | ; depending on the current sublevel's sfx_echo setting. 26 | ; Also set a flag in RAM if SFX echo is enabled. 27 | lda.l !rom_amk_byte : cmp #$5C : bne + 28 | ldy #$05 29 | jsr shared_get_bitwise_mask 30 | and.l tables_sfx_echo,x : beq ++ 31 | iny 32 | lda !ram_play_sfx : ora #$80 : sta !ram_play_sfx 33 | ++ sty $1DFA|!addr 34 | + 35 | ; Reset DSX sprites. 36 | if !reset_dsx 37 | stz $06FE|!addr 38 | endif 39 | 40 | ; Reset vanilla Boo rings. 41 | if !reset_boo_rings == 2 42 | rep #$20 43 | stz $0FAE|!addr 44 | stz $0FB0|!addr 45 | sep #$20 46 | endif 47 | 48 | ; Reset timer frame counter 49 | lda.l !rom_timer_ticks : sta $0F30|!addr 50 | 51 | ; If not entering from the overworld, skip. 52 | lda $141A|!addr : bne .room_transition 53 | 54 | ; Backup the timer value. 55 | rep #$20 56 | lda $0F31|!addr : sta !ram_timer+0 57 | sep #$20 58 | lda $0F33|!addr : sta !ram_timer+2 59 | 60 | .room_transition: 61 | ; Check if we're respawning or in a transition checkpoint. 62 | lda !ram_is_respawning : bne ..respawning 63 | jsr shared_get_checkpoint_value 64 | cmp #$02 : bcc .normal 65 | 66 | ..respawning: 67 | ; Fix issues with the "level ender" sprite. 68 | stz $1493|!addr 69 | stz $13C6|!addr 70 | 71 | ; Reset mode 7 values. 72 | rep #$20 73 | stz $36 74 | stz $38 75 | stz $3A 76 | stz $3C 77 | sep #$20 78 | 79 | ; Backup the music that should play. 80 | lda $0DDA|!addr : sta !ram_music_to_play 81 | 82 | .normal: 83 | ; Reset the respawning flag. 84 | lda #$00 : sta !ram_is_respawning 85 | 86 | if !sprite_status_bar 87 | ; Initialize and draw the status bar during the fadein 88 | jsr sprite_status_bar_init 89 | jsr sprite_status_bar_main 90 | endif 91 | 92 | main: 93 | if !fast_transitions 94 | ; Reset the mosaic timer. 95 | stz $0DB1|!addr 96 | endif 97 | 98 | rtl 99 | -------------------------------------------------------------------------------- /src/retry_config/code/level_transition.asm: -------------------------------------------------------------------------------- 1 | ; Gamemode 10, 11, 16, 19 2 | 3 | init: 4 | ; Disable HDMA. 5 | stz $0D9F|!addr 6 | rtl 7 | -------------------------------------------------------------------------------- /src/retry_config/code/load_overworld.asm: -------------------------------------------------------------------------------- 1 | ; Gamemode 0C 2 | 3 | init: 4 | 5 | ; Reset various counters. 6 | .counterbreak: 7 | if !counterbreak_yoshi == 1 || !counterbreak_yoshi == 3 8 | stz $13C7|!addr 9 | stz $187A|!addr 10 | endif 11 | 12 | if !counterbreak_powerup == 1 || !counterbreak_powerup == 3 13 | ; Reset powerup. 14 | stz $19 15 | endif 16 | 17 | if !counterbreak_item_box == 1 || !counterbreak_powerup == 3 18 | ; Reset item box. 19 | stz $0DC2|!addr 20 | endif 21 | 22 | if !counterbreak_coins == 1 || !counterbreak_coins == 3 23 | ; Reset coin counter. 24 | stz $0DBF|!addr 25 | endif 26 | 27 | if !counterbreak_bonus_stars == 1 || !counterbreak_bonus_stars == 3 28 | ; Reset bonus stars counter. 29 | stz $0F48|!addr 30 | stz $0F49|!addr 31 | endif 32 | 33 | if !counterbreak_score == 1 || !counterbreak_score == 3 34 | ; Reset score counter. 35 | rep #$20 36 | stz $0F34|!addr 37 | stz $0F36|!addr 38 | stz $0F38|!addr 39 | sep #$20 40 | endif 41 | 42 | ; Reset the current level's checkpoint if the level was beaten. 43 | .reset_checkpoint: 44 | ; Skip if the level wasn't just beaten. 45 | lda $0DD5|!addr : beq ..skip 46 | bmi ..skip 47 | 48 | ; Remove the checkpoint for the current level. 49 | jsr shared_reset_checkpoint 50 | 51 | ..skip: 52 | rtl 53 | -------------------------------------------------------------------------------- /src/retry_config/code/nmi.asm: -------------------------------------------------------------------------------- 1 | ; Gamemode 14 2 | 3 | ;===================================== 4 | ; nmi routine 5 | ; 6 | ; I know that uploading each tile individually is slow, but it makes it easy 7 | ; to change where the tiles are uploaded to for the user, and easier to manage 8 | ; the case where the "exit" option is left out. 9 | ;===================================== 10 | 11 | level: 12 | if !sprite_status_bar 13 | ; Update the sprite status bar graphics. 14 | jsr sprite_status_bar_nmi 15 | endif 16 | 17 | if !no_prompt_draw 18 | rtl 19 | else 20 | ; Skip if it's not time to upload the tiles. 21 | lda !ram_update_request : bne .upload 22 | rtl 23 | 24 | .upload: 25 | ; Only upload on this frame. 26 | dec : sta !ram_update_request 27 | 28 | ; With 5+ cycle iterations it saves time over doing lda.l. 29 | phb : phk : plb 30 | 31 | ; Loop to upload all the tiles. 32 | ; If the exit option is disabled, we skip the XI tiles. 33 | lda !ram_disable_exit : beq + 34 | lda #$01 35 | + tay 36 | ldx.w .index,y 37 | 38 | ; Push GFX address depending on the box being enabled or not. 39 | ; Additionally the size to upload for the cursor is pushed as well. 40 | lda !ram_disable_box : beq + 41 | lda #$02 42 | + tay 43 | rep #$20 44 | lda.w .cursor_size,y : pha 45 | lda.w .gfx_addr,y : pha 46 | 47 | ; These values are the same for all uploads, so put them out of the loop. 48 | ldy.b #$80 : sty $2115 49 | lda.w #$1801 : sta.w prompt_dma($4300) 50 | ldy.b #retry_gfx>>16 : sty.w prompt_dma($4304) 51 | ldy.b #1<>16 : sta.w window_dma($4304) 271 | rts 272 | 273 | ; Windowing table to use normally 274 | .window: 275 | ; all cover / layer123 cover 276 | db $5D : db $FF,$00,$FF,$00 277 | db $12 : db $38,$C8,$FF,$00 278 | db $08 : db $90,$C8,$38,$C8 279 | db $08 : db $38,$C8,$FF,$00 280 | db $08 : db $88,$C8,$38,$C8 281 | db $0D : db $38,$C8,$FF,$00 282 | db $4C : db $FF,$00,$FF,$00 283 | db $00 284 | 285 | ; Windowing table to use when exit is disabled 286 | .window_no_exit: 287 | ; all cover / layer123 cover 288 | db $5D : db $FF,$00,$FF,$00 289 | db $12 : db $38,$C8,$FF,$00 290 | db $08 : db $90,$C8,$38,$C8 291 | db $1D : db $38,$C8,$FF,$00 292 | db $4C : db $FF,$00,$FF,$00 293 | db $00 294 | -------------------------------------------------------------------------------- /src/retry_config/code/shared.asm: -------------------------------------------------------------------------------- 1 | ;================================================ 2 | ; Shared routines and macros. 3 | ;================================================ 4 | 5 | ;================================================ 6 | ; Macro to push the current code's DB to the stack 7 | ; and set the DBR to label's bank. 8 | ; Note: remember to PLB when finished! 9 | ;================================================ 10 | macro set_dbr(label) 11 | ?- pea.w (