.data bindingPath db 'binding.dat',0 badBindingPath db 'badbinding.dat',0 badBindingBoundsPath db 'badbindingbounds.dat',0 badBindingDuplicatePath db 'badbindingduplicate.dat',0 .code RunStudioChecks PROC uses ebx esi edi invoke LoadSublevelBinary, OFFSET bindingPath, -1, -1, 0 CHECK eax, 1 ; ASM loader accepts valid authored door binding invoke LoadSublevelBinary, OFFSET badBindingPath, -1, -1, 0 CHECK eax, 0 ; ASM loader rejects switch binding to a non-door invoke LoadSublevelBinary, OFFSET badBindingBoundsPath, -1, -1, 0 CHECK eax, 0 ; ASM loader rejects out-of-bounds switch target invoke LoadSublevelBinary, OFFSET badBindingDuplicatePath, -1, -1, 0 CHECK eax, 0 ; ASM loader rejects duplicate switch target bindings call ResetSimulationFixture mov keyForward, 0 mov playerX, 160 mov playerY, 160 mov playerAngle, 0 mov spriteCount, 1 mov [spriteList].SpriteStruct.x, 160 mov [spriteList].SpriteStruct.y, 160 mov [spriteList].SpriteStruct.textureId, 12 mov [spriteList].SpriteStruct.scale, FIXED_ONE ; target (3,2), key-unlockable switch binding mov [spriteList].SpriteStruct.flags, 0203A905h mov BYTE PTR [gameMap+2*MAP_W+3], CELL_DOOR call InitEntities mov playerKeys, 0 mov keyAction, 1 call InteractDoor movzx eax, BYTE PTR [gameMap+2*MAP_W+3] CHECK eax, CELL_DOOR ; bound door stays locked without a key movzx eax, keyAction CHECK eax, 0 ; locked door consumes action before nearby switches mov playerKeys, 2 call InteractDoor movzx eax, BYTE PTR [gameMap+2*MAP_W+3] CHECK eax, CELL_DOOR_OPEN ; key opens the explicitly authored locked door CHECK playerKeys, 1 ; first unlock consumes exactly one key call InteractDoor call InteractDoor CHECK playerKeys, 1 ; unlocked door never consumes a second key movzx eax, BYTE PTR [gameMap+2*MAP_W+3] CHECK eax, CELL_DOOR_OPEN ; unlocked door remains reusable call InitEntities movzx eax, BYTE PTR [doorUnlocked+2*MAP_W+3] CHECK eax, 0 ; room entity initialization clears temporary unlocks mov [spriteList].SpriteStruct.flags, 0203A805h mov BYTE PTR [gameMap+2*MAP_W+3], CELL_DOOR mov keyAction, 1 call InteractDoor movzx eax, BYTE PTR [gameMap+2*MAP_W+3] CHECK eax, CELL_DOOR ; switch-only door cannot be bypassed with keys mov playerAngle, 256 ; face away from door so E reaches nearby switch mov keyAction, 1 call UpdateEntities movzx eax, BYTE PTR [gameMap+2*MAP_W+3] CHECK eax, CELL_DOOR_OPEN ; authored switch opens its target door CHECK entityState, 1 ; switch state reflects the resulting door state mov keyAction, 1 call UpdateEntities movzx eax, BYTE PTR [gameMap+2*MAP_W+3] CHECK eax, CELL_DOOR ; second switch action closes target door mov BYTE PTR [gameMap+2*MAP_W+3], CELL_DOOR_OPEN mov playerX, 3*64-8 ; body overlaps target door mov [spriteList].SpriteStruct.x, 3*64-8 mov keyAction, 1 call UpdateEntities movzx eax, BYTE PTR [gameMap+2*MAP_W+3] CHECK eax, CELL_DOOR_OPEN ; remote switch cannot close a door across player body mov playerX, 160 mov playerAngle, 0 mov [spriteList].SpriteStruct.flags, 6405h ; legacy switch has no binding marker mov BYTE PTR [gameMap+2*MAP_W+3], CELL_DOOR call InitEntities mov playerKeys, 0 mov keyAction, 1 call InteractDoor call UpdateEntities movzx eax, BYTE PTR [gameMap+2*MAP_W+3] CHECK eax, CELL_DOOR_OPEN ; ordinary doors remain free on legacy maps CHECK entityState, 0 ; one action cannot open a door and toggle a nearby legacy switch invoke ToggleDoorCell, 32, 32 CHECK eax, 0 ; invalid switch targets are bounded at runtime ret RunStudioChecks ENDP