diff options
| -rw-r--r-- | SL0P.md | 22 | ||||
| -rw-r--r-- | engine/slop_menu.asm | 218 | ||||
| -rw-r--r-- | home/overworld.asm | 4 | ||||
| -rw-r--r-- | home/yes_no.asm | 13 |
4 files changed, 211 insertions, 46 deletions
@@ -37,23 +37,25 @@ A table-driven cheat menu. Cursor + A to pick, B to back out / close. | **ITEMS** | submenu: give ×99 of balls, Rare Candy, Full Restore, Max Revive, Max Elixer, PP Up, and all five evolution stones | | **NOWILD** | toggle wild encounters off (shows `ON`) | | **REPEL** | refill repel steps | -| **EXPLORE** | toggle noclip free-roam: disables collision so you (and Pikachu) walk through walls/NPCs/ledges and cross map connection seams seamlessly across the whole overworld. Pick it again to turn off. | +| **EXPLORE** | a screen-paging overworld camera: each d-pad press instantly redraws the next screenful of the world (no walking), hopping to the connected map at each edge. B returns to the menu. | Everything is in `engine/slop_menu.asm`. Adding a new entry = add a name to `SlopMenuText`, a `dw Handler` to `SlopMenuHandlers`, and bump `SLOP_MENU_COUNT`. Handlers return carry set (a warp/exit was started) or clear (back to the menu), and can be submenus or one-shot actions. -Persistent toggle flags: `wUnusedFlag` (NOWILD) and `wSlopNoclip` (EXPLORE, the -repurposed unused `wUnusedObtainedBadges` at D356). +Persistent toggle flag: `wUnusedFlag` (NOWILD). -**EXPLORE / noclip** hooks the home `CollisionCheckOnLand` (5-byte early-out when -`wSlopNoclip` is set; ROM0 room was reclaimed by deleting the unreferenced -`Func_0db5` dead farcall in `LoadMapHeader`). The engine's own player-walk + -connection-crossing code then carries you seamlessly across the world -- see -`tools/render_overworld.py` for the ground-truth map that proved connections join -maps along shared edges with an offset. (The player is left visible on purpose: -hiding it orphaned the Pikachu follower into a lone wandering sprite.) +**EXPLORE** is a self-contained camera loop in `engine/slop_menu.asm`. It renders +straight out of the map block buffer (`wOverworldMap`): compute a view pointer +`wOverworldMap + (by+1)*stride + bx` (by/bx = player block, stride = width+6), +`LoadCurrentMapView`, push to VRAM, OBJ off. A d-pad press moves the camera coords +by ~one screen (`SLOP_PAGE_X/Y`) and re-renders; at a map edge it crosses using +that connection's `*Alignment` offset (vertical: Y=align, X+=align; horizontal: +X=align, Y+=align) and `LoadMapData`s the neighbour, or clamps if there's none. +No walk engine, no character movement. See `tools/render_overworld.py` for the +ground-truth map that proved connections join maps along shared edges with an +offset -- the same math this camera uses to cross seams. ## Build diff --git a/engine/slop_menu.asm b/engine/slop_menu.asm index b4b7f78e..66a8a482 100644 --- a/engine/slop_menu.asm +++ b/engine/slop_menu.asm @@ -216,30 +216,206 @@ WarpMapTable: ; =========================================================================== -; EXPLORE (P1): overworld map-connection browser. Renders the current map (no -; NPCs), and U/D/L/R jump to the connected map in that direction if one exists -; (via wCurMapConnections + the connection headers). B restores the original -; map and returns to the SL0P menu. No warping yet - read-only browse. -; =========================================================================== -; =========================================================================== -; EXPLORE: toggle noclip free-roam. With noclip on, CollisionCheckOnLand is -; bypassed, so you glide through walls / NPCs / ledges and cross map connection -; seams exactly as the world data defines them. Closes the menu so you drop -; straight back into the overworld to roam. Pick it again to turn it off. +; EXPLORE: a screen-paging overworld camera. Each d-pad press INSTANTLY redraws +; the next screenful of the world -- no character walking. At a map edge it hops +; to the connected map using that connection's alignment offset (or clamps if +; there's none). B restores the origin view and returns to the SL0P menu. It is +; self-contained: it renders straight from the map block buffer (wOverworldMap) +; and never touches the walk engine. ; =========================================================================== +DEF SLOP_PAGE_X EQU 10 ; coords moved per horizontal page (~one screen) +DEF SLOP_PAGE_Y EQU 8 ; coords moved per vertical page + SlopExplore: - ld a, [wSlopNoclip] - xor $01 - ld [wSlopNoclip], a -; close the menu the same way the B button does (rebuild the overworld) instead -; of .exitProceed, which only bare-returns and assumes a warp will redraw. - pop hl ; drop the pushed .afterHandler return address - call SlopMenuRestoreFlags - ld a, $01 - ld [wUpdateSpritesEnabled], a - ldh a, [hLoadedROMBank] +; save origin (map, coords, block coords, view pointer) to restore on exit + ld a, [wYCoord] + ld b, a + ld a, [wXCoord] + ld c, a + push bc + ld a, [wYBlockCoord] + ld b, a + ld a, [wXBlockCoord] + ld c, a + push bc + ld a, [wCurrentTileBlockMapViewPointer] + ld b, a + ld a, [wCurrentTileBlockMapViewPointer + 1] + ld c, a + push bc + ld a, [wCurMap] push af - jp CloseTextDisplay + call LoadMapData ; reload current map + tileset (menu clobbered VRAM) +.renderView +; block-aligned camera; view pointer = wOverworldMap + (by+1)*stride + bx, +; where by = wYCoord/2, bx = wXCoord/2, stride = wCurMapWidth + 2*MAP_BORDER. + xor a + ld [wYBlockCoord], a + ld [wXBlockCoord], a + ld a, [wCurMapWidth] + add MAP_BORDER * 2 + ld c, a + ld b, 0 + ld a, [wYCoord] + srl a + inc a + ld hl, 0 +.mulRow + add hl, bc + dec a + jr nz, .mulRow + ld a, [wXCoord] + srl a + add l + ld l, a + jr nc, .noCarry + inc h +.noCarry + ld bc, wOverworldMap + add hl, bc + ld a, l + ld [wCurrentTileBlockMapViewPointer], a + ld a, h + ld [wCurrentTileBlockMapViewPointer + 1], a + call LoadCurrentMapView + ld b, HIGH(vBGMap0) + call CopyScreenTileBufferToVRAM + ldh a, [rLCDC] ; hide sprites for a clean camera + res B_LCDC_OBJS, a + ldh [rLCDC], a + ld a, $90 + ldh [hWY], a +.input + call DelayFrame + call JoypadLowSensitivity + ldh a, [hJoyPressed] + ld d, a + bit B_PAD_B, d + jp nz, .exit + bit B_PAD_UP, d + jr z, .ckDown + ld a, [wYCoord] + sub SLOP_PAGE_Y + jp nc, .setY + ld hl, wNorthConnectedMap + ld de, wNorthConnectedMapYAlignment + ld a, 0 ; clamp target = top + jp .crossV +.ckDown + bit B_PAD_DOWN, d + jr z, .ckLeft + ld a, [wCurrentMapHeight2] + dec a + ld b, a ; b = max Y + ld a, [wYCoord] + add SLOP_PAGE_Y + cp b + jp c, .setY + jp z, .setY + ld hl, wSouthConnectedMap + ld de, wSouthConnectedMapYAlignment + ld a, b ; clamp target = max Y + jp .crossV +.ckLeft + bit B_PAD_LEFT, d + jr z, .ckRight + ld a, [wXCoord] + sub SLOP_PAGE_X + jp nc, .setX + ld hl, wWestConnectedMap + ld de, wWestConnectedMapYAlignment + ld a, 0 + jp .crossH +.ckRight + bit B_PAD_RIGHT, d + jp z, .input + ld a, [wCurrentMapWidth2] + dec a + ld b, a ; b = max X + ld a, [wXCoord] + add SLOP_PAGE_X + cp b + jp c, .setX + jp z, .setX + ld hl, wEastConnectedMap + ld de, wEastConnectedMapYAlignment + ld a, b + jp .crossH +.setY + ld [wYCoord], a + jp .renderView +.setX + ld [wXCoord], a + jp .renderView +; vertical cross (up/down): hl -> connected-map byte, de -> its YAlignment, +; a = Y to clamp to when there is no connection. +.crossV + ld b, a + ld a, [hl] + inc a + jr z, .clampY ; $ff -> no connection + ld a, [de] ; YAlignment -> new Y (absolute) + ld c, a + inc de + ld a, [de] ; XAlignment -> added to X + ld b, a + ld a, [wXCoord] + add b + ld [wXCoord], a + ld a, c + ld [wYCoord], a + ld a, [hl] + ld [wCurMap], a + call LoadMapData + jp .renderView +.clampY + ld a, b + ld [wYCoord], a + jp .renderView +; horizontal cross (left/right): hl -> connected-map byte, de -> its YAlignment, +; a = X to clamp to when there is no connection. +.crossH + ld b, a + ld a, [hl] + inc a + jr z, .clampX + ld a, [de] ; YAlignment -> added to Y + ld c, a + inc de + ld a, [de] ; XAlignment -> new X (absolute) + ld [wXCoord], a + ld a, [wYCoord] + add c + ld [wYCoord], a + ld a, [hl] + ld [wCurMap], a + call LoadMapData + jp .renderView +.clampX + ld a, b + ld [wXCoord], a + jp .renderView +.exit + pop af + ld [wCurMap], a + pop bc + ld a, b + ld [wCurrentTileBlockMapViewPointer], a + ld a, c + ld [wCurrentTileBlockMapViewPointer + 1], a + pop bc + ld a, b + ld [wYBlockCoord], a + ld a, c + ld [wXBlockCoord], a + pop bc + ld a, b + ld [wYCoord], a + ld a, c + ld [wXCoord], a + call LoadMapData ; restore origin view (renders from restored pointer) + and a ; carry clear -> back to SL0P menu + ret ; =========================================================================== ; ITEMS submenu: give 99 of the chosen item (stacks via GiveItem) diff --git a/home/overworld.asm b/home/overworld.asm index 95b94646..bac16375 100644 --- a/home/overworld.asm +++ b/home/overworld.asm @@ -1218,9 +1218,6 @@ SignLoop:: ; function to check if the player will jump down a ledge and check if the tile ahead is passable (when not surfing) ; sets the carry flag if there is a collision, and unsets it if there isn't a collision CollisionCheckOnLand:: - ld a, [wSlopNoclip] ; SL0P noclip: walk through everything (carry clear) - and a - ret nz ld a, [wMovementFlags] bit BIT_LEDGE_OR_FISHING, a jr nz, .noCollision @@ -1232,7 +1229,6 @@ CollisionCheckOnLand:: ld d, a ld a, [wSpritePlayerStateData1CollisionData] and d ; check if a sprite is in the direction the player is trying to go - nop ; ??? why is this in the code jr nz, .collision xor a ldh [hTextID], a diff --git a/home/yes_no.asm b/home/yes_no.asm index 8d995832..befcd3c4 100644 --- a/home/yes_no.asm +++ b/home/yes_no.asm @@ -5,11 +5,7 @@ YesNoChoice:: call InitYesNoTextBoxParameters jr DisplayYesNoChoice -TwoOptionMenu:: ; unreferenced - ld a, TWO_OPTION_MENU - ld [wTextBoxID], a - call InitYesNoTextBoxParameters - jp DisplayTextBoxID +; SL0P: removed unreferenced TwoOptionMenu to reclaim ROM0 for the noclip guard. InitYesNoTextBoxParameters:: xor a ; YES_NO_MENU @@ -26,12 +22,7 @@ YesNoChoicePokeCenter:: lb bc, 8, 12 jr DisplayYesNoChoice -WideYesNoChoice:: ; unreferenced - call SaveScreenTilesToBuffer1 - ld a, WIDE_YES_NO_MENU - ld [wTwoOptionMenuID], a - hlcoord 12, 7 - lb bc, 8, 13 +; SL0P: removed unreferenced WideYesNoChoice to reclaim ROM0. DisplayYesNoChoice:: ld a, TWO_OPTION_MENU |
