From fe1e76466b293c83e6cd3a7d4639fb3c49da26ad Mon Sep 17 00:00:00 2001 From: Rangi <35663410+Rangi42@users.noreply.github.com> Date: Wed, 7 Jan 2026 22:05:20 -0500 Subject: Use macros to enforce "missable/hide/show object" constraints, and rename them to "toggleable objects" (#557) --- engine/events/pick_up_item.asm | 16 +- engine/movie/oak_speech/init_player_data.asm | 2 +- engine/overworld/auto_movement.asm | 4 +- engine/overworld/missable_objects.asm | 212 -------------------------- engine/overworld/movement.asm | 2 +- engine/overworld/toggleable_objects.asm | 213 +++++++++++++++++++++++++++ 6 files changed, 225 insertions(+), 224 deletions(-) delete mode 100644 engine/overworld/missable_objects.asm create mode 100644 engine/overworld/toggleable_objects.asm (limited to 'engine') diff --git a/engine/events/pick_up_item.asm b/engine/events/pick_up_item.asm index 8fbdcfa2..a55c604a 100644 --- a/engine/events/pick_up_item.asm +++ b/engine/events/pick_up_item.asm @@ -3,19 +3,19 @@ PickUpItem: ldh a, [hSpriteIndex] ld b, a - ld hl, wMissableObjectList -.missableObjectsListLoop + ld hl, wToggleableObjectList +.toggleableObjectsListLoop ld a, [hli] cp $ff ret z cp b - jr z, .isMissable + jr z, .isToggleable inc hl - jr .missableObjectsListLoop + jr .toggleableObjectsListLoop -.isMissable +.isToggleable ld a, [hl] - ldh [hMissableObjectIndex], a + ldh [hToggleableObjectIndex], a ld hl, wMapSpriteExtraData ldh a, [hSpriteIndex] @@ -30,8 +30,8 @@ PickUpItem: call GiveItem jr nc, .BagFull - ldh a, [hMissableObjectIndex] - ld [wMissableObjectIndex], a + ldh a, [hToggleableObjectIndex] + ld [wToggleableObjectIndex], a predef HideObject ld a, 1 ld [wDoNotWaitForButtonPressAfterDisplayingText], a diff --git a/engine/movie/oak_speech/init_player_data.asm b/engine/movie/oak_speech/init_player_data.asm index 843eb96e..bd4f86a4 100644 --- a/engine/movie/oak_speech/init_player_data.asm +++ b/engine/movie/oak_speech/init_player_data.asm @@ -45,7 +45,7 @@ DEF START_MONEY EQU $3000 ld bc, wGameProgressFlagsEnd - wGameProgressFlags call FillMemory ; clear all game progress flags - jp InitializeMissableObjectsFlags + jp InitializeToggleableObjectsFlags InitializeEmptyList: xor a ; count diff --git a/engine/overworld/auto_movement.asm b/engine/overworld/auto_movement.asm index 13d30cca..dc5fc385 100644 --- a/engine/overworld/auto_movement.asm +++ b/engine/overworld/auto_movement.asm @@ -148,8 +148,8 @@ PalletMovementScript_Done: ld a, [wSimulatedJoypadStatesIndex] and a ret nz - ld a, HS_PALLET_TOWN_OAK - ld [wMissableObjectIndex], a + ld a, TOGGLE_PALLET_TOWN_OAK + ld [wToggleableObjectIndex], a predef HideObject ld hl, wStatusFlags5 res BIT_SCRIPTED_MOVEMENT_STATE, [hl] diff --git a/engine/overworld/missable_objects.asm b/engine/overworld/missable_objects.asm deleted file mode 100644 index 8ea79980..00000000 --- a/engine/overworld/missable_objects.asm +++ /dev/null @@ -1,212 +0,0 @@ -MarkTownVisitedAndLoadMissableObjects:: - ld a, [wCurMap] - cp FIRST_ROUTE_MAP - jr nc, .notInTown - ld c, a - ld b, FLAG_SET - ld hl, wTownVisitedFlag ; mark town as visited (for flying) - predef FlagActionPredef -.notInTown - ld hl, MapHSPointers - ld a, [wCurMap] - ld b, $0 - ld c, a - add hl, bc - add hl, bc - ld a, [hli] ; load missable objects pointer in hl - ld h, [hl] - ld l, a - push hl - ld de, MissableObjects ; calculate difference between out pointer and the base pointer - ld a, l - sub e - jr nc, .noCarry - dec h -.noCarry - ld l, a - ld a, h - sub d - ld h, a - ld a, h - ldh [hDividend], a - ld a, l - ldh [hDividend+1], a - xor a - ldh [hDividend+2], a - ldh [hDividend+3], a - ld a, $3 - ldh [hDivisor], a - ld b, $2 - call Divide ; divide difference by 3, resulting in the global offset (number of missable items before ours) - ld a, [wCurMap] - ld b, a - ldh a, [hDividend+3] - ld c, a ; store global offset in c - ld de, wMissableObjectList - pop hl -.writeMissableObjectsListLoop - ld a, [hli] - cp -1 - jr z, .done ; end of list - cp b - jr nz, .done ; not for current map anymore - ld a, [hli] - inc hl - ld [de], a ; write (map-local) sprite ID - inc de - ld a, c - inc c - ld [de], a ; write (global) missable object index - inc de - jr .writeMissableObjectsListLoop -.done - ld a, -1 - ld [de], a ; write sentinel - ret - -InitializeMissableObjectsFlags: - ld hl, wMissableObjectFlags - ld bc, wMissableObjectFlagsEnd - wMissableObjectFlags - xor a - call FillMemory ; clear missable objects flags - ld hl, MissableObjects - xor a - ld [wMissableObjectCounter], a -.missableObjectsLoop - ld a, [hli] - cp -1 ; end of list - ret z - push hl - inc hl - ld a, [hl] - cp HIDE - jr nz, .skip - ld hl, wMissableObjectFlags - ld a, [wMissableObjectCounter] - ld c, a - ld b, FLAG_SET - call MissableObjectFlagAction ; set flag if Item is hidden -.skip - ld hl, wMissableObjectCounter - inc [hl] - pop hl - inc hl - inc hl - jr .missableObjectsLoop - -; tests if current sprite is a missable object that is hidden/has been removed -IsObjectHidden: - ldh a, [hCurrentSpriteOffset] - swap a - ld b, a - ld hl, wMissableObjectList -.loop - ld a, [hli] - cp -1 - jr z, .notHidden ; not missable -> not hidden - cp b - ld a, [hli] - jr nz, .loop - ld c, a - ld b, FLAG_TEST - ld hl, wMissableObjectFlags - call MissableObjectFlagAction - ld a, c - and a - jr nz, .hidden -.notHidden - xor a -.hidden - ldh [hIsHiddenMissableObject], a - ret - -; adds missable object (items, leg. pokemon, etc.) to the map -; [wMissableObjectIndex]: index of the missable object to be added (global index) -ShowObject: -ShowObject2: - ld hl, wMissableObjectFlags - ld a, [wMissableObjectIndex] - ld c, a - ld b, FLAG_RESET - call MissableObjectFlagAction ; reset "removed" flag - jp UpdateSprites - -; removes missable object (items, leg. pokemon, etc.) from the map -; [wMissableObjectIndex]: index of the missable object to be removed (global index) -HideObject: - ld hl, wMissableObjectFlags - ld a, [wMissableObjectIndex] - ld c, a - ld b, FLAG_SET - call MissableObjectFlagAction ; set "removed" flag - jp UpdateSprites - -MissableObjectFlagAction: -; identical to FlagAction - - push hl - push de - push bc - - ; bit - ld a, c - ld d, a - and 7 - ld e, a - - ; byte - ld a, d - srl a - srl a - srl a - add l - ld l, a - jr nc, .ok - inc h -.ok - - ; d = 1 << e (bitmask) - inc e - ld d, 1 -.shift - dec e - jr z, .shifted - sla d - jr .shift -.shifted - - ld a, b - and a - jr z, .reset - cp FLAG_TEST - jr z, .read - -; set - ld a, [hl] - ld b, a - ld a, d - or b - ld [hl], a - jr .done - -.reset - ld a, [hl] - ld b, a - ld a, d - xor $ff - and b - ld [hl], a - jr .done - -.read - ld a, [hl] - ld b, a - ld a, d - and b - -.done - pop bc - pop de - pop hl - ld c, a - ret diff --git a/engine/overworld/movement.asm b/engine/overworld/movement.asm index a353c4f1..be8d6f62 100644 --- a/engine/overworld/movement.asm +++ b/engine/overworld/movement.asm @@ -478,7 +478,7 @@ InitializeSpriteScreenPosition: ; tests if sprite is off screen or otherwise unable to do anything CheckSpriteAvailability: predef IsObjectHidden - ldh a, [hIsHiddenMissableObject] + ldh a, [hIsToggleableObjectOff] and a jp nz, .spriteInvisible ld h, HIGH(wSpriteStateData2) diff --git a/engine/overworld/toggleable_objects.asm b/engine/overworld/toggleable_objects.asm new file mode 100644 index 00000000..bfb3576c --- /dev/null +++ b/engine/overworld/toggleable_objects.asm @@ -0,0 +1,213 @@ +MarkTownVisitedAndLoadToggleableObjects:: + ld a, [wCurMap] + cp FIRST_ROUTE_MAP + jr nc, .notInTown + ld c, a + ld b, FLAG_SET + ld hl, wTownVisitedFlag ; mark town as visited (for flying) + predef FlagActionPredef +.notInTown + ld hl, ToggleableObjectMapPointers + ld a, [wCurMap] + ld b, $0 + ld c, a + add hl, bc + add hl, bc + ld a, [hli] ; load toggleable objects pointer in hl + ld h, [hl] + ld l, a + push hl + ld de, ToggleableObjectStates ; calculate difference between out pointer and the base pointer + ld a, l + sub e + jr nc, .noCarry + dec h +.noCarry + ld l, a + ld a, h + sub d + ld h, a + ; divide difference by 3, resulting in the global offset (number of toggleable items before ours) + ld a, h + ldh [hDividend], a + ld a, l + ldh [hDividend+1], a + xor a + ldh [hDividend+2], a + ldh [hDividend+3], a + ld a, $3 + ldh [hDivisor], a + ld b, $2 + call Divide + ld a, [wCurMap] + ld b, a + ldh a, [hDividend+3] + ld c, a ; store global offset in c + ld de, wToggleableObjectList + pop hl +.writeToggleableObjectsListLoop + ld a, [hli] + cp -1 + jr z, .done ; end of list + cp b + jr nz, .done ; not for current map anymore + ld a, [hli] + inc hl + ld [de], a ; write (map-local) sprite ID + inc de + ld a, c + inc c + ld [de], a ; write (global) toggleable object index + inc de + jr .writeToggleableObjectsListLoop +.done + ld a, -1 + ld [de], a ; write sentinel + ret + +InitializeToggleableObjectsFlags: + ld hl, wToggleableObjectFlags + ld bc, wToggleableObjectFlagsEnd - wToggleableObjectFlags + xor a + call FillMemory ; clear toggleable objects flags + ld hl, ToggleableObjectStates + xor a + ld [wToggleableObjectCounter], a +.toggleableObjectsLoop + ld a, [hli] + cp -1 ; end of list + ret z + push hl + inc hl + ld a, [hl] + cp OFF + jr nz, .skip + ld hl, wToggleableObjectFlags + ld a, [wToggleableObjectCounter] + ld c, a + ld b, FLAG_SET + call ToggleableObjectFlagAction ; set flag if object is toggled off +.skip + ld hl, wToggleableObjectCounter + inc [hl] + pop hl + inc hl + inc hl + jr .toggleableObjectsLoop + +; tests if current object is toggled off/has been hidden +IsObjectHidden: + ldh a, [hCurrentSpriteOffset] + swap a + ld b, a + ld hl, wToggleableObjectList +.loop + ld a, [hli] + cp -1 + jr z, .notHidden ; not toggleable -> not hidden + cp b + ld a, [hli] + jr nz, .loop + ld c, a + ld b, FLAG_TEST + ld hl, wToggleableObjectFlags + call ToggleableObjectFlagAction + ld a, c + and a + jr nz, .hidden +.notHidden + xor a +.hidden + ldh [hIsToggleableObjectOff], a + ret + +; adds toggleable object (items, leg. pokemon, etc.) to the map +; [wToggleableObjectIndex]: index of the toggleable object to be added (global index) +ShowObject: +ShowObject2: + ld hl, wToggleableObjectFlags + ld a, [wToggleableObjectIndex] + ld c, a + ld b, FLAG_RESET + call ToggleableObjectFlagAction ; reset "removed" flag + jp UpdateSprites + +; removes toggleable object (items, leg. pokemon, etc.) from the map +; [wToggleableObjectIndex]: index of the toggleable object to be removed (global index) +HideObject: + ld hl, wToggleableObjectFlags + ld a, [wToggleableObjectIndex] + ld c, a + ld b, FLAG_SET + call ToggleableObjectFlagAction ; set "removed" flag + jp UpdateSprites + +ToggleableObjectFlagAction: +; identical to FlagAction + + push hl + push de + push bc + + ; bit + ld a, c + ld d, a + and 7 + ld e, a + + ; byte + ld a, d + srl a + srl a + srl a + add l + ld l, a + jr nc, .ok + inc h +.ok + + ; d = 1 << e (bitmask) + inc e + ld d, 1 +.shift + dec e + jr z, .shifted + sla d + jr .shift +.shifted + + ld a, b + and a + jr z, .reset + cp FLAG_TEST + jr z, .read + +; set + ld a, [hl] + ld b, a + ld a, d + or b + ld [hl], a + jr .done + +.reset + ld a, [hl] + ld b, a + ld a, d + xor $ff + and b + ld [hl], a + jr .done + +.read + ld a, [hl] + ld b, a + ld a, d + and b + +.done + pop bc + pop de + pop hl + ld c, a + ret -- cgit v1.3.1-sl0p