diff options
| author | Ash Ketchum <no-reply@sl0p.foo> | 2026-07-15 12:15:50 +0200 |
|---|---|---|
| committer | Ash Ketchum <no-reply@sl0p.foo> | 2026-07-15 12:15:50 +0200 |
| commit | 259c6b8ec4524dcd4a75da065106107f2165b202 (patch) | |
| tree | f7aaba15cd3a45c5620dab7f338522ff4480fa2b | |
| parent | tools: render_overworld.py - build seamless Kanto map from source (diff) | |
| download | pokeyellow-259c6b8ec4524dcd4a75da065106107f2165b202.tar.gz pokeyellow-259c6b8ec4524dcd4a75da065106107f2165b202.tar.xz pokeyellow-259c6b8ec4524dcd4a75da065106107f2165b202.zip | |
explore: pivot to noclip free-roam camera
Ground-truth from render_overworld.py showed Kanto is ONE seamless world joined
along shared edges with per-connection offsets -- so a map-by-map browser is the
wrong model. Replaced it with noclip free-roam that leans on the engine's own
player-walk + connection-crossing machinery (which already handles seams/offsets
correctly):
- wSlopNoclip flag (reused the dead wUnusedObtainedBadges byte at D356, 0 r/w,
not unioned, in the saved region -> safe).
- CollisionCheckOnLand: 5-byte hook at the top -> when noclip is set, return
no-collision. Freed the room in ROM0 by deleting the unreferenced Func_0db5
(dead farcall LoadToggleableObjectData) in LoadMapHeader.
- EXPLORE menu entry now just toggles wSlopNoclip and closes the menu, dropping
you into the overworld to glide through walls/NPCs/ledges and walk across map
connections exactly as the world data defines them.
Verified: Pallet -> (walk north through the fences) -> seam-cross into Route 1 at
y=35 -> continue north; toggle off restores collision (player blocked).
| -rw-r--r-- | engine/movie/oak_speech/init_player_data.asm | 2 | ||||
| -rw-r--r-- | engine/slop_menu.asm | 152 | ||||
| -rw-r--r-- | home/overworld.asm | 9 | ||||
| -rw-r--r-- | ram/wram.asm | 2 |
4 files changed, 17 insertions, 148 deletions
diff --git a/engine/movie/oak_speech/init_player_data.asm b/engine/movie/oak_speech/init_player_data.asm index 90fb8f0e..589f4b5f 100644 --- a/engine/movie/oak_speech/init_player_data.asm +++ b/engine/movie/oak_speech/init_player_data.asm @@ -39,7 +39,7 @@ DEF START_MONEY EQU $3000 ld hl, wObtainedBadges ld [hli], a - ASSERT wObtainedBadges + 1 == wUnusedObtainedBadges + ASSERT wObtainedBadges + 1 == wSlopNoclip ld [hl], a ld hl, wPlayerCoins diff --git a/engine/slop_menu.asm b/engine/slop_menu.asm index fcac7d10..e3b07fe6 100644 --- a/engine/slop_menu.asm +++ b/engine/slop_menu.asm @@ -221,149 +221,17 @@ WarpMapTable: ; (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. +; =========================================================================== SlopExplore: -; save origin map + coords on the stack - ld a, [wYCoord] - ld b, a - ld a, [wXCoord] - ld c, a - push bc ; origin Y,X - ld a, [wCurrentTileBlockMapViewPointer] - ld b, a - ld a, [wCurrentTileBlockMapViewPointer + 1] - ld c, a - push bc ; origin view pointer - ld a, [wCurMap] - push af ; origin map -.render -; LoadMapData loads the map header + block map into wOverworldMap, but it renders -; using a STALE wCurrentTileBlockMapViewPointer -- the game only ever sets that -; from warp / connection / walk data, never from wXCoord/wYCoord. So load the -; map, then compute a centered view pointer ourselves and redraw the view. - call LoadMapData -; stride = wCurMapWidth + MAP_BORDER*2 ; bufRow = height/2 + 1 ; bufCol = width/2 -; wCurrentTileBlockMapViewPointer = wOverworldMap + bufRow*stride + bufCol - ld a, [wCurMapWidth] - add MAP_BORDER * 2 - ld c, a - ld b, 0 ; bc = row stride (blocks) - ld hl, 0 - ld a, [wCurMapHeight] - srl a - inc a ; bufRow (>= 1) -.viewRowLoop - add hl, bc - dec a - jr nz, .viewRowLoop - ld a, [wCurMapWidth] - srl a ; bufCol = width/2 - add l - ld l, a - jr nc, .viewNoCarry - inc h -.viewNoCarry - ld bc, wOverworldMap - add hl, bc - ld a, l - ld [wCurrentTileBlockMapViewPointer], a - ld a, h - ld [wCurrentTileBlockMapViewPointer + 1], a - xor a - ld [wYBlockCoord], a - ld [wXBlockCoord], a - call LoadCurrentMapView ; redraw wTileMap centered on the map - ldh a, [rLCDC] ; hide ALL sprites (player + actors) via LCDC - res B_LCDC_OBJS, a - ldh [rLCDC], a - ld a, $90 - ldh [hWY], a ; window off-screen -> the BG map is visible -; overlay direction markers at the screen edges for the legit connections - call LoadFontTilePatterns - ld a, [wCurMapConnections] - ld e, a - bit NORTH_F, e - jr z, .noN - hlcoord 9, 0 - ld [hl], $8D -.noN - bit SOUTH_F, e - jr z, .noS - hlcoord 9, 15 - ld [hl], $92 -.noS - bit WEST_F, e - jr z, .noW - hlcoord 0, 8 - ld [hl], $96 -.noW - bit EAST_F, e - jr z, .noE - hlcoord 18, 8 - ld [hl], $84 -.noE - ld b, HIGH(vBGMap0) - call CopyScreenTileBufferToVRAM ; push map + markers to VRAM -.input - call DelayFrame - call JoypadLowSensitivity - ldh a, [hJoyPressed] - ld d, a - bit B_PAD_B, d - jr nz, .exit - bit B_PAD_UP, d - jr z, .chkDown - ld a, [wCurMapConnections] - bit NORTH_F, a - jp z, .input - ld a, [wNorthConnectedMap] - ld [wCurMap], a - jp .render -.chkDown - bit B_PAD_DOWN, d - jr z, .chkLeft - ld a, [wCurMapConnections] - bit SOUTH_F, a - jp z, .input - ld a, [wSouthConnectedMap] - ld [wCurMap], a - jp .render -.chkLeft - bit B_PAD_LEFT, d - jr z, .chkRight - ld a, [wCurMapConnections] - bit WEST_F, a - jp z, .input - ld a, [wWestConnectedMap] - ld [wCurMap], a - jp .render -.chkRight - bit B_PAD_RIGHT, d - jp z, .input - ld a, [wCurMapConnections] - bit EAST_F, a - jp z, .input - ld a, [wEastConnectedMap] - ld [wCurMap], a - jp .render -.exit - pop af - ld [wCurMap], a ; restore origin map - pop bc ; restore origin view pointer - ld a, b - ld [wCurrentTileBlockMapViewPointer], a - ld a, c - ld [wCurrentTileBlockMapViewPointer + 1], a - pop bc ; restore origin Y,X - ld a, b - ld [wYCoord], a - and $1 - ld [wYBlockCoord], a - ld a, c - ld [wXCoord], a - and $1 - ld [wXBlockCoord], a - call LoadMapData ; reload origin, rendered from the restored pointer - and a ; carry clear -> back to SL0P menu + ld a, [wSlopNoclip] + xor $01 + ld [wSlopNoclip], a + scf ; carry set -> close menu, back to overworld ret ; =========================================================================== diff --git a/home/overworld.asm b/home/overworld.asm index a41a7ba8..95b94646 100644 --- a/home/overworld.asm +++ b/home/overworld.asm @@ -1218,6 +1218,9 @@ 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 @@ -1797,10 +1800,8 @@ LoadPlayerSpriteGraphicsCommon:: ; function to load data from the map header LoadMapHeader:: farcall MarkTownVisitedAndLoadToggleableObjects - jr asm_0dbd - -Func_0db5:: ; unreferenced - farcall LoadToggleableObjectData +; SL0P: removed unreferenced Func_0db5 (farcall LoadToggleableObjectData) to make +; room in ROM0 for the noclip hook in CollisionCheckOnLand. asm_0dbd: ld a, [wCurMapTileset] ld [wUnusedCurMapTilesetCopy], a diff --git a/ram/wram.asm b/ram/wram.asm index 62ef1c44..e0488e62 100644 --- a/ram/wram.asm +++ b/ram/wram.asm @@ -1943,7 +1943,7 @@ wOptions:: db wObtainedBadges:: flag_array NUM_BADGES -wUnusedObtainedBadges:: db +wSlopNoclip:: db ; SL0P: nonzero = noclip free-roam (walk through walls) wLetterPrintingDelayFlags:: db |
