From 92856fd4b4908939ff4998a84369d4b9ac097b7a Mon Sep 17 00:00:00 2001 From: Ash Ketchum Date: Wed, 15 Jul 2026 15:46:49 +0200 Subject: EXPLORE/SAVER: clamp camera into map bounds after a connection cross Crossing a map connection applies the connection's alignment offset blindly. At an edge position the connection doesn't span, the resulting coord lands outside the neighbour (e.g. Y = -8 = $f8), and since the bounds checks then operate on the wrapped value the camera roams far outside the map, rendering whatever WRAM lies past wOverworldMap as on-screen garbage. SlopClampCoords (run in .renderView, i.e. after every entry/cross LoadMapData) clamps wYCoord to [0,maxY] and wXCoord to [0,maxX] of the freshly-loaded map. Verified: 120-sample saver soak across 19 maps -> 0 out-of-bounds; manual EXPLORE crossing unaffected. --- engine/slop_menu.asm | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/engine/slop_menu.asm b/engine/slop_menu.asm index 7e534015..4c93e2ed 100644 --- a/engine/slop_menu.asm +++ b/engine/slop_menu.asm @@ -275,6 +275,7 @@ SlopExploreShared: ld a, $ff ld [wUpdateSpritesEnabled], a call ClearSprites + call SlopClampCoords ; a cross can land outside the new map -> clamp call SlopExploreRenderBG ; fresh render to vBGMap0, hardware scroll reset .renderArrows call LoadFontTilePatterns ; arrow glyphs ($ed/$ee) into VRAM for the OBJ layer @@ -616,6 +617,38 @@ SlopExploreShared: and a ; carry clear -> back to SL0P menu ret +; Clamp wYCoord to [0,maxY] and wXCoord to [0,maxX] of the current map. Crossing a +; connection applies its alignment offset blindly, so at an edge position the +; connection doesn't span the camera can land outside the neighbour; rendering +; that reads past wOverworldMap into other WRAM = on-screen garbage. +SlopClampCoords: + ld a, [wCurrentMapHeight2] + dec a + ld b, a ; maxY + ld a, [wYCoord] + call .clamp + ld [wYCoord], a + ld a, [wCurrentMapWidth2] + dec a + ld b, a ; maxX + ld a, [wXCoord] + call .clamp + ld [wXCoord], a + ret +; a = coord, b = max -> a clamped to [0,max]. Out-of-range values >= $80 are +; treated as "past the near edge" (negative) and clamped to 0, otherwise to max. +.clamp + cp b + ret c + ret z + bit 7, a + jr nz, .zero + ld a, b + ret +.zero + xor a + ret + ; wCurrentTileBlockMapViewPointer = wOverworldMap + (wYCoord/2 + 1)*stride + wXCoord/2 SlopSetViewPtr: ld a, [wCurMapWidth] -- cgit v1.3.1-sl0p