feat: add InstantLevelSelectExtra

This commit is contained in:
sup39 2024-02-09 16:12:17 +09:00
parent a2e4b33742
commit 4b1f983cd1
Signed by: sup39
GPG key ID: 111C00916C1641E5
7 changed files with 810 additions and 1 deletions

BIN
.img/levelselect.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View file

@ -11,7 +11,7 @@
### Level Select
Press `{the following button combination} + B + D-Pad Up` to warp to other area instantly.
![Level Select Combinations](/img/levelselect.png)
![Level Select Combinations](../.img/levelselect.png)
- For `Z + B + D-Pad Up`, the current area will be restarted, but the **respawn position will be reset**. It is like B+Up, but the respawn position will be the default position instead of the previous one
- For `Y + B + D-Pad Up`, it will restart from the **previous selected area**. For example, if you select SB4 with this code, and enter hotel/casino then press Y+B+Up, it will restart from SB4 beach (instead of hotel/casino if you use B+Up or Z+B+Up)

View file

@ -0,0 +1,388 @@
<code>
<category>misc</category>
<title lang="en-US">Instant Level Select Extra</title>
<title lang="ja-JP">レベル選択EX</title>
<author>sup39(サポミク)</author>
<version>1.0</version>
<date>Feb 09, 2024</date>
<description lang="en-US">
::: warning
Do not use this code when opening/closing Z menu, or the game may crash!
:::
#### Instant Restart
- Press `D-Pad Up` to **restart the current area**
- The **respawn position** will be the same. It can be used to practice Honey Skip or stage movement in Delfino Plaza
#### Reset to Shine Select
- Press `D-Pad Down` to **reset to shine select of current stage**
- Pressing `D-Pad Down` in Plaza has no effect
#### Level Select
Press `{the following button combination} + D-Pad Up` to warp to other area instantly:
![Level Select Combinations](/img/levelselect.png)
- For `Z + D-Pad Up`, the current area will be restarted, but the **respawn position will be reset**. It is like `D-Pad Up`, but the respawn position will be the default position instead of the previous one
- For `Y + D-Pad Up`, it will restart from the **previous selected area**. For example, if you select SB4 with this code, and enter hotel/casino then press `Y+D-Pad Up`, it will restart from SB4 beach (instead of hotel/casino if you use `D-Pad Up` or `Z+D-Pad Up`)
#### Area Lock
- Press `R + D-Pad Left/Right` to enable/disable **Area Lock**
- With Area Lock, warps will restart the current area instead of sending Mario to other areas, which can be used to practice specific area (e.g. outside of BH2 wildmill, secret stage entering)
- Restarting acts like `D-Pad Up`, and therefore can be used to practice Honey Skip, etc.
#### Example of Usage: Practising Honey Skip
1. Press `R + D-Pad Left` to enable Area Lock
2. Press `C-Stick LeftDown + D-Pad Up` to go to Pianta Village
3. Press `C-Stick RightDown + Y + D-Pad Up` to go to Pinna unlock plaza
4. Practice Honey Skip as much as you want! It will restart automatically when you are going to leave the area so you don't need to reset manually. You can also restart with `D-Pad Up` if you want.
</description>
<description lang="ja-JP">
::: warning
Zメニューを開く・閉じる最中にこのコードを使うとクラッシュする可能性があります
:::
#### ポーズせずにやり直し
- `十字キー上`で**現在のエリアをやり直す**
- ドルピックタウンでは同じ開始位置からやり直すので、ハニスキといったステージ移動の練習も可能
#### シャイン選択画面からやり直し
- `十字キー下`で**現在のステージのシャイン選択画面からやり直す**
#### レベル選択
`{次のボタン}+十字キー上`でレベル選択
![レベル選択](/img/levelselect.png)
- `Z+十字キー上`は**現在のエリアをやり直す**が、ドルピックタウンでの**開始位置がリセット**され、デフォルトの開始位置からとなる(`十字キー上`の場合はリセットされない)
- `Y+十字キー上`は**前回選択したレベル**からやり直す(例えばSB4を選択し、ホテル・カジに入って`Y+十字キー`を押すと、ホテル外からやり直すことになる)
#### エリアロック
`R+十字キー左/右`でエリアロック/ロック解除
- エリアロックするとステージ移動がやり直しに置き換え、ヒミツINといった特定のエリアの練習が可能
- やり直しの仕様は`十字キー上`と同じなので、ハニスキなどの練習にも使える
#### 使用例:ハニスキの練習
1. `R + 十字キー左`でエリアロック
2. `Cスティック左下 + 十字キー上`でモンテの村に移動
3. `Cスティック右下 + Y + 十字キー上`でピンナ解放のドルピックタウンに移動
4. これで好きなだけハニスキを練習できます。他のエリアに入ろうとする時に自動的にやり直すので、手動でやり直す必要がありません。必要であれば`十字キー上`でやり直すこともできます。
</description>
<source version="GMSJ01">
C20F9B74 0000004D
3C80817F 816D97D0
3D808040 80AC0D80
20050022 540A043D
41820008 8804002B
540007FF 9804002B
28830001 4C451102
40A2000C 38A00008
90AC0D80 7C7D1B79
41820220 70A00004
41A20034 881F000E
3D40803B 394A40E8
7CEA00AE 2C070001
40810200 38070001
5400EFFE 7CE70214
54E7403E 60E700FF
480000F8 70A00008
41A201E0 4800003D
00141516 0017181D
34000090 2F2E3020
32293328 2A1FBA3C
371E213A 0E2C3900
00010507 08090200
123457D0 24567000
12234070 23467001
7D2802A6 54A6CF38
50A6F77A 50A6E7BC
50A6D7FE 54A0C738
50A0B77C 7CC60378
54A3873F 41820054
2C030009 41820098
3C00C84A 6000C004
1C630003 5C031F7E
5465103A 2C06000C
408000BC 2C06000A
408000D4 2C060008
40800090 3C005689
60000234 546C103A
5C0C652E 7CC76378
54C8077E 480000C4
A0FF000E 2C060000
41820028 2C060004
41820028 2C06000A
41820028 7C0930AE
540744AE 5408CFFE
1D080007 48000094
A01F000A B01F000E
890B00DF 4800008C
A0E40028 8904002A
48000078 3989000C
7C0C30AE 540744AE
5007CFFE 3C00AC1A
60005CA2 1D860003
5C08677E 48000054
39890018 7C0C18AE
540744AE 3C001373
60002301 5C082F7E
48000038 3989FFF8
54C016B8 7C0C006E
5C072F7E 5007252E
800C0004 5C082F7E
48000018 3C001578
60009200 5C072F3E
60E70100 39000000
B0E40028 9904002A
38000001 980400B3
990B00DF 38000000
900B00D8 A00B00CC
60004000 54000524
B00B00CC B0FF0012
54E0C63E 819F0020
2C000007 2C80000E
4C423382 3800003B
41820008 38000000
B00C00E4 A00C00E2
540007FA B00C00E2
54FDD7BE 3BBD0005
60000000 00000000
</source>
<source version="GMSE01">
C22A6170 0000004D
3C80817F 816D9FA0
3D808040 80AC4484
20050022 540A043D
41820008 8804002B
540007FF 9804002B
28830001 4C451102
40A2000C 38A00008
90AC4484 7C7D1B79
41820220 70A00004
41A20034 881F000E
3D40803E 394AF498
7CEA00AE 2C070001
40810200 38070001
5400EFFE 7CE70214
54E7403E 60E700FF
480000F8 70A00008
41A201E0 4800003D
00141516 0017181D
34000090 2F2E3020
32293328 2A1FBA3C
371E213A 0E2C3900
00010507 08090200
123457D0 24567000
12234070 23467001
7D2802A6 54A6CF38
50A6F77A 50A6E7BC
50A6D7FE 54A0C738
50A0B77C 7CC60378
54A3873F 41820054
2C030009 41820098
3C00C84A 6000C004
1C630003 5C031F7E
5465103A 2C06000C
408000BC 2C06000A
408000D4 2C060008
40800090 3C005689
60000234 546C103A
5C0C652E 7CC76378
54C8077E 480000C4
A0FF000E 2C060000
41820028 2C060004
41820028 2C06000A
41820028 7C0930AE
540744AE 5408CFFE
1D080007 48000094
A01F000A B01F000E
890B00DF 4800008C
A0E40028 8904002A
48000078 3989000C
7C0C30AE 540744AE
5007CFFE 3C00AC1A
60005CA2 1D860003
5C08677E 48000054
39890018 7C0C18AE
540744AE 3C001373
60002301 5C082F7E
48000038 3989FFF8
54C016B8 7C0C006E
5C072F7E 5007252E
800C0004 5C082F7E
48000018 3C001578
60009200 5C072F3E
60E70100 39000000
B0E40028 9904002A
38000001 980400B3
990B00DF 38000000
900B00D8 A00B00CC
60004000 54000524
B00B00CC B0FF0012
54E0C63E 819F0020
2C000007 2C80000E
4C423382 3800003B
41820008 38000000
B00C00E4 A00C00E2
540007FA B00C00E2
54FDD7BE 3BBD0005
60000000 00000000
</source>
<source version="GMSP01">
C229E080 0000004D
3C80817F 816D9EC8
3D808040 80ACBC24
20050022 540A043D
41820008 8804002B
540007FF 9804002B
28830001 4C451102
40A2000C 38A00008
90ACBC24 7C7D1B79
41820220 70A00004
41A20034 881F000E
3D40803D 394A6DB0
7CEA00AE 2C070001
40810200 38070001
5400EFFE 7CE70214
54E7403E 60E700FF
480000F8 70A00008
41A201E0 4800003D
00141516 0017181D
34000090 2F2E3020
32293328 2A1FBA3C
371E213A 0E2C3900
00010507 08090200
123457D0 24567000
12234070 23467001
7D2802A6 54A6CF38
50A6F77A 50A6E7BC
50A6D7FE 54A0C738
50A0B77C 7CC60378
54A3873F 41820054
2C030009 41820098
3C00C84A 6000C004
1C630003 5C031F7E
5465103A 2C06000C
408000BC 2C06000A
408000D4 2C060008
40800090 3C005689
60000234 546C103A
5C0C652E 7CC76378
54C8077E 480000C4
A0FF000E 2C060000
41820028 2C060004
41820028 2C06000A
41820028 7C0930AE
540744AE 5408CFFE
1D080007 48000094
A01F000A B01F000E
890B00DF 4800008C
A0E40028 8904002A
48000078 3989000C
7C0C30AE 540744AE
5007CFFE 3C00AC1A
60005CA2 1D860003
5C08677E 48000054
39890018 7C0C18AE
540744AE 3C001373
60002301 5C082F7E
48000038 3989FFF8
54C016B8 7C0C006E
5C072F7E 5007252E
800C0004 5C082F7E
48000018 3C001578
60009200 5C072F3E
60E70100 39000000
B0E40028 9904002A
38000001 980400B3
990B00DF 38000000
900B00D8 A00B00CC
60004000 54000524
B00B00CC B0FF0012
54E0C63E 819F0020
2C000007 2C80000E
4C423382 3800003B
41820008 38000000
B00C00E4 A00C00E2
540007FA B00C00E2
54FDD7BE 3BBD0005
60000000 00000000
</source>
<source version="GMSJ0A">
C2285FCC 0000004D
3C80817F 816D9E60
3D80803F 80AC5458
20050022 540A043D
41820008 8804002B
540007FF 9804002B
28830001 4C451102
40A2000C 38A00008
90AC5458 7C7D1B79
41820220 70A00004
41A20034 881F000E
3D40803D 394AF9B8
7CEA00AE 2C070001
40810200 38070001
5400EFFE 7CE70214
54E7403E 60E700FF
480000F8 70A00008
41A201E0 4800003D
00141516 0017181D
34000090 2F2E3020
32293328 2A1FBA3C
371E213A 0E2C3900
00010507 08090200
123457D0 24567000
12234070 23467001
7D2802A6 54A6CF38
50A6F77A 50A6E7BC
50A6D7FE 54A0C738
50A0B77C 7CC60378
54A3873F 41820054
2C030009 41820098
3C00C84A 6000C004
1C630003 5C031F7E
5465103A 2C06000C
408000BC 2C06000A
408000D4 2C060008
40800090 3C005689
60000234 546C103A
5C0C652E 7CC76378
54C8077E 480000C4
A0FF000E 2C060000
41820028 2C060004
41820028 2C06000A
41820028 7C0930AE
540744AE 5408CFFE
1D080007 48000094
A01F000A B01F000E
890B00DF 4800008C
A0E40028 8904002A
48000078 3989000C
7C0C30AE 540744AE
5007CFFE 3C00AC1A
60005CA2 1D860003
5C08677E 48000054
39890018 7C0C18AE
540744AE 3C001373
60002301 5C082F7E
48000038 3989FFF8
54C016B8 7C0C006E
5C072F7E 5007252E
800C0004 5C082F7E
48000018 3C001578
60009200 5C072F3E
60E70100 39000000
B0E40028 9904002A
38000001 980400B3
990B00DF 38000000
900B00D8 A00B00CC
60004000 54000524
B00B00CC B0FF0012
54E0C63E 819F0020
2C000007 2C80000E
4C423382 3800003B
41820008 38000000
B00C00E4 A00C00E2
540007FA B00C00E2
54FDD7BE 3BBD0005
60000000 00000000
</source>
</code>

View file

@ -0,0 +1,30 @@
# Instant Level Select Extra
## Caveats
- Do not use this code when opening/closing Z menu, or the game may crash!
## Usage
### Instant Restart
- Press `D-Pad Up` to **restart the current area**
- The **respawn position** will be the same. It can be used to practice Honey Skip or stage movement in Delfino Plaza
### Reset to Shine Select
- Press `D-Pad Down` to **reset to shine select of current stage**
- Pressing `D-Pad Down` in Plaza has no effect
### Level Select
Press `{the following button combination} + D-Pad Up` to warp to other area instantly:
![Level Select Combinations](../.img/levelselect.png)
- For `Z + D-Pad Up`, the current area will be restarted, but the **respawn position will be reset**. It is like `D-Pad Up`, but the respawn position will be the default position instead of the previous one
- For `Y + D-Pad Up`, it will restart from the **previous selected area**. For example, if you select SB4 with this code, and enter hotel/casino then press `Y+D-Pad Up`, it will restart from SB4 beach (instead of hotel/casino if you use `D-Pad Up` or `Z+D-Pad Up`)
### Area Lock
- Press `R + D-Pad Left/Right` to enable/disable **Area Lock**
- With Area Lock, warps will restart the current area instead of sending Mario to other areas, which can be used to practice specific area (e.g. outside of BH2 wildmill, secret stage entering)
- Restarting acts like `D-Pad Up`, and therefore can be used to practice Honey Skip, etc.
### Example of Usage: Practising Honey Skip
1. Press `R + D-Pad Left` to enable Area Lock
2. Press `C-Stick LeftDown + D-Pad Up` to go to Pianta Village
3. Press `C-Stick RightDown + Y + D-Pad Up` to go to Pinna unlock plaza
4. Practice Honey Skip as much as you want! It will restart automatically when you are going to leave the area so you don't need to reset manually. You can also restart with `D-Pad Up` if you want.

View file

@ -0,0 +1,68 @@
<code>
<category>misc</category>
<title lang="en-US">Instant Level Select Extra</title>
<title lang="ja-JP">レベル選択EX</title>
<author>sup39(サポミク)</author>
<version>1.0</version>
<date>Feb 09, 2024</date>
<description lang="en-US">
::: warning
Do not use this code when opening/closing Z menu, or the game may crash!
:::
#### Instant Restart
- Press `D-Pad Up` to **restart the current area**
- The **respawn position** will be the same. It can be used to practice Honey Skip or stage movement in Delfino Plaza
#### Reset to Shine Select
- Press `D-Pad Down` to **reset to shine select of current stage**
- Pressing `D-Pad Down` in Plaza has no effect
#### Level Select
Press `{the following button combination} + D-Pad Up` to warp to other area instantly:
![Level Select Combinations](/img/levelselect.png)
- For `Z + D-Pad Up`, the current area will be restarted, but the **respawn position will be reset**. It is like `D-Pad Up`, but the respawn position will be the default position instead of the previous one
- For `Y + D-Pad Up`, it will restart from the **previous selected area**. For example, if you select SB4 with this code, and enter hotel/casino then press `Y+D-Pad Up`, it will restart from SB4 beach (instead of hotel/casino if you use `D-Pad Up` or `Z+D-Pad Up`)
#### Area Lock
- Press `R + D-Pad Left/Right` to enable/disable **Area Lock**
- With Area Lock, warps will restart the current area instead of sending Mario to other areas, which can be used to practice specific area (e.g. outside of BH2 wildmill, secret stage entering)
- Restarting acts like `D-Pad Up`, and therefore can be used to practice Honey Skip, etc.
#### Example of Usage: Practising Honey Skip
1. Press `R + D-Pad Left` to enable Area Lock
2. Press `C-Stick LeftDown + D-Pad Up` to go to Pianta Village
3. Press `C-Stick RightDown + Y + D-Pad Up` to go to Pinna unlock plaza
4. Practice Honey Skip as much as you want! It will restart automatically when you are going to leave the area so you don't need to reset manually. You can also restart with `D-Pad Up` if you want.
</description>
<description lang="ja-JP">
::: warning
Zメニューを開く・閉じる最中にこのコードを使うとクラッシュする可能性があります
:::
#### ポーズせずにやり直し
- `十字キー上`で**現在のエリアをやり直す**
- ドルピックタウンでは同じ開始位置からやり直すので、ハニスキといったステージ移動の練習も可能
#### シャイン選択画面からやり直し
- `十字キー下`で**現在のステージのシャイン選択画面からやり直す**
#### レベル選択
`{次のボタン}+十字キー上`でレベル選択
![レベル選択](/img/levelselect.png)
- `Z+十字キー上`は**現在のエリアをやり直す**が、ドルピックタウンでの**開始位置がリセット**され、デフォルトの開始位置からとなる(`十字キー上`の場合はリセットされない)
- `Y+十字キー上`は**前回選択したレベル**からやり直す(例えばSB4を選択し、ホテル・カジに入って`Y+十字キー`を押すと、ホテル外からやり直すことになる)
#### エリアロック
`R+十字キー左/右`でエリアロック/ロック解除
- エリアロックするとステージ移動がやり直しに置き換え、ヒミツINといった特定のエリアの練習が可能
- やり直しの仕様は`十字キー上`と同じなので、ハニスキなどの練習にも使える
#### 使用例:ハニスキの練習
1. `R + 十字キー左`でエリアロック
2. `Cスティック左下 + 十字キー上`でモンテの村に移動
3. `Cスティック右下 + Y + 十字キー上`でピンナ解放のドルピックタウンに移動
4. これで好きなだけハニスキを練習できます。他のエリアに入ろうとする時に自動的にやり直すので、手動でやり直す必要がありません。必要であれば`十字キー上`でやり直すこともできます。
</description>
</code>

View file

@ -0,0 +1,13 @@
from supSMSGecko import make_xml, symbols
def main(g, ver):
S = symbols[ver]
# Instant Level Select main function
g.C2(0x220 + S['TApplication_gameLoop'], 'src/main.s', extra_as_input=[
'.set $LevelSelect.area, 0x817F0028',
'.set $LevelSelect.epFlag, 0x817F002A',
'.set $LevelSelect.AreaLock, 0x817F002B',
]);
make_xml(main)

View file

@ -0,0 +1,310 @@
.set rC, 3 # SHOULD NOT BE USE UNTIL checkAreaLock ENDS
.set r817F, 4
.set rBtn, 5
.set rC4, 5
.set rIdx, 6
.set rAns, 7
.set rAnsEp, 8
.set rD, 9 # BL trick
.set rFM, 11 # FlagManager
.set rTmp, 10
.set rApp, 31 # gpApplication
.set rNextGameMode, 29
.set crAreaLock, 7
.set $btnLevelSelect, 0x8 # D_UP
.set $btnShineSelect, 0x4 # D_DOWN
.L.prepare:
## prepare registers
lis r817F, 0x817F
lwz rFM, TFlagManager_smInstance$r13(r13)
## read button input: [M]*1 [C]*1 [btn]*2
lis r12, JUTGamePad_mPadButton@ha
lwz rBtn, JUTGamePad_mPadButton@l(r12)
/** NOTE: DO NOT CHANGE r12 UNTIL checkAreaLock ENDS */
.L.checkAreaLock:
## r0 = 0x22 - btn
subfic r0, rBtn, 0x22
### (lower 16 bit of r0 & ~1) == 0 => use r0&1 as AreaLock enable state
rlwinm. rTmp, r0, 0, 0x10, 0x1E
beq .L.checkAreaLock.1
### else, load r0 = current state from RAM
lbz r0, $LevelSelect.AreaLock@l(r817F)
.L.checkAreaLock.1:
## !cr0.eq: AreaLock enabled
rlwinm. r0, r0, 0, 0x1
## write current enable state to RAM
stb r0, $LevelSelect.AreaLock@l(r817F)
## activate AreaLock only if director finished (rNextGameMode > 1)
cmplwi cr1, r3, 1
crandc eq, 4*cr1+gt, eq
bne+ .L.checkAreaLock.done
## set button input to (handleRestartN) if AreaLock enabled
li rBtn, $btnLevelSelect
stw rBtn, JUTGamePad_mPadButton@l(r12)
.L.checkAreaLock.done:
## orig
mr. rNextGameMode, r3
## return now if still setting up
beq .L.done
## check button (Shine Select)
.L.checkButton.ShineSelect:
andi. r0, rBtn, $btnShineSelect
beq+ .L.checkButton.ShineSelect.done
.ShineSelect:
## rAns = shineStageTable[curArea]
lbz r0, 0xE(rApp) # current area
lis rTmp, shineStageTable@ha
la rTmp, shineStageTable@l(rTmp)
lbzx rAns, rTmp, r0
## ignore Plaza (rAns <= 1)
cmpwi rAns, 1
ble .L.done
## map 7~8 to 8~9
addi r0, rAns, 1
rlwinm r0, r0, 32-3, 0x1
add rAns, rAns, r0
## rAns = rAns << 8 | 0xff
rlwinm rAns, rAns, 8, 0, 31
ori rAns, rAns, 0xFF
## TODO handle invalid shine stage (0, 1, 0xFF)
b handleRestartZ
.L.checkButton.ShineSelect.done:
### check button (Level Select)
.L.checkButton.LevelSelect:
andi. r0, rBtn, $btnLevelSelect
beq+ .L.done
## Level Select
bl .L.LevelSelect
.D:
.D.Special:
# 8 bit/entry: [1bit] epFlag==7 | [7bit] area
.long 0x00141516
.long 0x0017181D
.long 0x34000090 # Red coin fish@NB8: 0x80|0x10
.D.Secrets:
# 8 bit/entry: [1bit] ep==1 | [7bit] area
.long 0x2F2E3020
.long 0x32293328
.long 0x2A1FBA3C
.D.Sublevels:
# 8 bit/entry
.long 0x371E213A
.long 0x0E2C3900
.D.Plaza:
.long 0x00010507
.long 0x08090200
.D.Extra:
.D.PinnaPark:
## ep: 0,1,2,3,4,5,7 | area=D
## epFlag: 0,2,4,5,6,7,0
.long 0x123457D0
.long 0x24567000
.D.SirenaHotel:
## ep: 0,1,2,2,3,4 | area=7
## episo: 1,2,3,4,6,7
.long 0x12234070
.long 0x23467001
.L.LevelSelect:
mflr rD
.L.main:
## calc index
## btn: S YXZA -LRZ ----
## XZRL=8,4,2,1
rlwinm rIdx, rBtn, 32-7, 0x8 # X=8
rlwimi rIdx, rBtn, 32-2, 0x4 # Z=4
rlwimi rIdx, rBtn, 32-4, 0x2 # R=2
rlwimi rIdx, rBtn, 32-6, 0x1 # L=1
## YSY=8,4,2
rlwinm r0, rBtn, 32- 8, 0x8 # Y=+8
rlwimi r0, rBtn, 32-10, 0x6 # S,Y=4,+2
## merge XZRL and YSY-
or rIdx, rIdx, r0
# TODO? handle rIdx>=12
## check C==0(Special) or 9(Secrets)
rlwinm. rC, rBtn, 32-16, 0xF
beq handleSpecial
cmpwi rC, 9
beq handleSecrets
## calc C index
### [(*), 6, 2, (*); 4, 5, 3, (*); 0, (*), 1]
### 110 0/10 00/0 100/ 101 0|11 00/0 000/ 000 0/01 00
.set CIdxMagic, 06204530001<<(32-3*10)
### CIdx = magic <<(3*C) &7
lis r0, CIdxMagic@h
ori r0, r0, CIdxMagic@l
mulli rC, rC, 3
rlwnm rC, r0, rC, 0x7
## prepare CIdx<<2 (destroy rBtn)
slwi rC4, rC, 2
## Y+Z(14) -> SirenaHotel
## X+Z(12) -> PinnaPark
cmpwi rIdx, 12
bge handleExtra
## Y(10) -> Plaza
cmpwi rIdx, 10
bge handlePlaza
## X(8) -> Sublevels
cmpwi rIdx, 8
bge handleSublevels
## stage
### area: [2, 3, 4, 5, 6, 8, 9, (*)]
### magic = 0x34568902 rotl sizeof(0xFF)
### ans = idx | (magic<<(Cidx<<2)) &0x0F00
### ep = idx
lis r0, 0x5689
ori r0, r0, 0x0234
slwi r12, rC, 2
rlwnm r12, r0, r12, 0x0F00
or rAns, rIdx, r12
rlwinm rAnsEp, rIdx, 0, 0x7
b .L.loadStage
handleSpecial:
lhz rAns, 0xE(rApp) # backup for handleRestartN
## neutral
cmpwi rIdx, 0
beq handleRestartN
## Z restart
cmpwi rIdx, 4
beq handleRestartZ
## Y restart
cmpwi rIdx, 10
beq handleRestartY
## Special
# rD = .D.Special
lbzx r0, rD, rIdx # offset = idx
rlwinm rAns, r0, 8, 0x3F00
rlwinm rAnsEp, r0, 32-7, 0x1
mulli rAnsEp, rAnsEp, 7
b .L.loadStage
handleRestartN:
## set prevMap = curMap
lhz r0, 0xA(rApp)
sth r0, 0xE(rApp)
handleRestartZ:
## load curMap, ep
lbz rAnsEp, 0xDF(rFM)
b .L.loadStageWithoutBackup
handleRestartY: # load 817F0000
lhz rAns, $LevelSelect.area@l(r817F)
lbz rAnsEp, $LevelSelect.epFlag@l(r817F)
b .L.loadStage
handleSecrets:
la r12, .D.Secrets-.D(rD)
lbzx r0, r12, rIdx
rlwinm rAns, r0, 8, 0x3F00
rlwimi rAns, r0, 32-7, 0x0001
# ep: 2,5,3,0,1,5,1,3,4,5,0,*
.set SecretEpMagic, 05301513450<<2 | 02
lis r0, SecretEpMagic@h
ori r0, r0, SecretEpMagic@l
mulli r12, rIdx, 3
rlwnm rAnsEp, r0, r12, 0x7
b .L.loadStage
handleSublevels:
la r12, .D.Sublevels-.D(rD)
lbzx r0, r12, rC # Cidx as index
rlwinm rAns, r0, 8, 0x3F00
# ep: 1,1,3,7,3,2,3
.set SublevelEpMagic, 0x13732301
lis r0, SublevelEpMagic@h
ori r0, r0, SublevelEpMagic@l
rlwnm rAnsEp, r0, rC4, 0x7
b .L.loadStage
handleExtra:
la r12, .D.Extra-.D-12*4(rD)
rlwinm r0, rIdx, 2, 0x38 # offset: {12,14}<<2
lwzux r0, r12, r0
rlwnm rAns, r0, rC4, 0x7 # ep
rlwimi rAns, r0, 4, 0x0F00 # a0 => aEE
lwz r0, 4(r12)
rlwnm rAnsEp, r0, rC4, 0x7
b .L.loadStage
handlePlaza:
## [0, 1, 5, 7; 8, 9, 2, (*)]
## 15789200
## ans == 0x0100 | (magic << (arr:=CIdx<<2) &0xF)
.set PlazaEpMagic, 0x15789200
lis r0, PlazaEpMagic@h
ori r0, r0, PlazaEpMagic@l
rlwnm rAns, r0, rC4, 0xF
ori rAns, rAns, 0x0100
li rAnsEp, 0
.L.loadStage:
### backup to 817F0000 (for Y)
sth rAns, $LevelSelect.area@l(r817F)
stb rAnsEp, $LevelSelect.epFlag@l(r817F)
/* rAns, rAnsEp, rFM, rApp, r817F */
.L.loadStageWithoutBackup:
## reset QFT
li r0, 1
stb r0, 0xB3(r817F)
## FlagManager
### epFlag(40003)
stb rAnsEp, 0xDF(rFM)
### reset coin counter(40002)
li r0, 0
stw r0, 0xD8(rFM)
##### set SGT Stop Stopwatch Flag = 0
# stw r0, 0x10C(r817F)
### set flag
lhz r0, 0xCC(rFM)
#### Got a Shine in previous stage (30006)
ori r0, r0, 0x4000
#### clear watched Pinna kidnap FMV flag (prevent spawn in PP unlocked position)
rlwinm r0, r0, 0, 0x14, 0x12
sth r0, 0xCC(rFM)
## rApp = gpApplication
### write nextArea
sth rAns, 0x12(rApp)
.set rMGP, 12
# SirenaHotel(0x07) or Casino(0x0E) ? 59 : 0
rlwinm r0, rAns, 32-8, 0xFF # area
lwz rMGP, 0x20(rApp) # TMarioGamePad*
cmpwi r0, 0x07 # SirenaHotel
cmpwi cr1, r0, 0x0E # Casino
cror eq, eq, 4*cr1+eq
li r0, 59
beq- .L.handleStickCD
li r0, 0
.L.handleStickCD:
sth r0, 0xe4(rMGP)
.L.handleStickFlag:
## clear 0x2 bit of 0xe2 flag
lhz r0, 0xe2(rMGP)
rlwinm r0, r0, 0, 31, 29
sth r0, 0xe2(rMGP)
## nextGameMode = nextArea == (shine select) ? 8 : 5
## ep==0xFF ? 3 : 0 (Note: all valid ep id < 0x40)
rlwinm rNextGameMode, rAns, 32-6, 0x3
addi rNextGameMode, rNextGameMode, 5
.L.done: