Decouple gameplay from presentation and preserve signed movement fractions. Separate cinematic camera ownership with safe body handoff and transactional current-room restarts. Resample input latches on focus regain, discard modal timing debt, and attach cinematic lighting to the view to match editor preview. Verify editor 137/137 and ASM 288/288, cinematic traces, RGB bake and IPC framebuffer parity without changing project assets.
253 lines
5.7 KiB
PHP
253 lines
5.7 KiB
PHP
; Fixed 60 Hz simulation and QPC scheduler. No presentation or keyboard APIs in
|
|
; Engine_Tick. AdvanceSimulation accepts elapsed QPC counts for deterministic tests.
|
|
.code
|
|
QueryPerformanceCounter PROTO :DWORD
|
|
QueryPerformanceFrequency PROTO :DWORD
|
|
|
|
GetSimulationState PROC
|
|
mov eax, SIM_UNFOCUSED
|
|
cmp inputFocused, 0
|
|
je state_ready
|
|
mov eax, SIM_PAUSED
|
|
cmp isGamePaused, 0
|
|
jne state_ready
|
|
mov eax, SIM_DIALOG
|
|
cmp gameDialogActive, 0
|
|
jne state_ready
|
|
mov eax, SIM_TRANSITION
|
|
cmp fadeState, 0
|
|
jne state_ready
|
|
mov eax, SIM_DEAD
|
|
cmp isPlayerDead, 0
|
|
jne state_ready
|
|
mov eax, SIM_CUTSCENE
|
|
cmp isCutsceneActive, 0
|
|
jne state_ready
|
|
cmp cutscenePending, 0
|
|
jne state_ready
|
|
mov eax, SIM_PLAYING
|
|
state_ready:
|
|
ret
|
|
GetSimulationState ENDP
|
|
|
|
; UI edges execute on ticks, never during polling or drawing.
|
|
ApplyInputCommands PROC
|
|
cmp keyPause, 0
|
|
je command_menu
|
|
xor isGamePaused, 1
|
|
mov clockReset, 1
|
|
command_menu:
|
|
cmp isGamePaused, 0
|
|
je command_hud
|
|
cmp keyMenu1, 0
|
|
je @F
|
|
mov isGamePaused, 0
|
|
mov clockReset, 1
|
|
@@:
|
|
cmp keyMenu2, 0
|
|
je @F
|
|
xor enableWeapons, 1
|
|
mov eax, enableWeapons
|
|
mov gameMode, eax
|
|
mov showCrosshair, eax
|
|
mov playerWeapon, WEAPON_NONE
|
|
test eax, eax
|
|
jz @F
|
|
mov playerWeapon, WEAPON_PISTOL
|
|
@@:
|
|
cmp keyMenu3, 0
|
|
je @F
|
|
xor hudStyle, 1
|
|
@@:
|
|
cmp keyMenu4, 0
|
|
je @F
|
|
call RestartCurrentRoom
|
|
; A failed reload stays paused with all room/gameplay state intact.
|
|
@@:
|
|
cmp keyMenu5, 0
|
|
je command_done
|
|
mov isRunning, 0
|
|
ret
|
|
command_hud:
|
|
cmp keyMap, 0
|
|
je @F
|
|
xor keyShowMap, 1
|
|
@@:
|
|
cmp keyHud, 0
|
|
je @F
|
|
xor hudStyle, 1
|
|
@@:
|
|
call GetSimulationState
|
|
cmp eax, SIM_PLAYING
|
|
jne command_done
|
|
cmp keyFlashlight, 0
|
|
je @F
|
|
xor isFlashlightOn, 1
|
|
@@:
|
|
cmp keyLightMode, 0
|
|
je @F
|
|
inc lightingMode
|
|
cmp lightingMode, 3
|
|
jb @F
|
|
mov lightingMode, 0
|
|
@@:
|
|
cmp enableWeapons, 0
|
|
je command_done
|
|
cmp gameMode, GAME_MODE_ACTION
|
|
jne command_done
|
|
cmp keyWeapon1, 0
|
|
je @F
|
|
mov playerWeapon, WEAPON_KNIFE
|
|
@@:
|
|
cmp keyWeapon2, 0
|
|
je @F
|
|
mov playerWeapon, WEAPON_PISTOL
|
|
@@:
|
|
cmp keyWeapon3, 0
|
|
je command_done
|
|
mov playerWeapon, WEAPON_SHOTGUN
|
|
command_done:
|
|
ret
|
|
ApplyInputCommands ENDP
|
|
|
|
Engine_Tick PROC
|
|
inc simulationTicks
|
|
mov gameplayTickBlocked, 1
|
|
call GetSimulationState
|
|
mov simulationState, eax
|
|
cmp eax, SIM_UNFOCUSED
|
|
je tick_done
|
|
call ApplyInputCommands
|
|
cmp clockReset, 0
|
|
jne tick_done
|
|
call GetSimulationState
|
|
mov simulationState, eax
|
|
cmp eax, SIM_PAUSED
|
|
je tick_done
|
|
cmp eax, SIM_DIALOG
|
|
je tick_dialog
|
|
cmp eax, SIM_TRANSITION
|
|
je tick_transition
|
|
cmp eax, SIM_DEAD
|
|
je tick_dead
|
|
cmp mapErrorFrames, 0
|
|
je @F
|
|
dec mapErrorFrames
|
|
@@:
|
|
call UpdatePlayer
|
|
call IsGameplayBlocked
|
|
test eax, eax
|
|
jnz tick_cinematic
|
|
call UpdateEntities
|
|
call IsGameplayBlocked
|
|
test eax, eax
|
|
jnz tick_done
|
|
call UpdateCombat
|
|
call IsGameplayBlocked
|
|
test eax, eax
|
|
jnz tick_done
|
|
call Game_OnTick
|
|
call IsGameplayBlocked
|
|
test eax, eax
|
|
jnz tick_done
|
|
call UpdateDynamicLights
|
|
cmp gameToastTimer, 0
|
|
jle tick_done
|
|
dec gameToastTimer
|
|
jmp tick_done
|
|
tick_cinematic:
|
|
cmp isCutsceneActive, 0
|
|
je tick_done
|
|
call UpdateDynamicLights
|
|
jmp tick_done
|
|
tick_dialog:
|
|
mov al, keyAction
|
|
or al, keyDismiss
|
|
or al, keyAttack
|
|
jz tick_done
|
|
call CloseGameDialog
|
|
mov clockReset, 1
|
|
jmp tick_done
|
|
tick_transition:
|
|
call UpdateScreenFade
|
|
jmp tick_done
|
|
tick_dead:
|
|
cmp keyRestart, 0
|
|
je tick_done
|
|
call RestartCurrentRoom
|
|
tick_done:
|
|
call ConsumeInputEdges
|
|
ret
|
|
Engine_Tick ENDP
|
|
|
|
InitSimulationClock PROC
|
|
invoke QueryPerformanceFrequency, OFFSET qpcFrequency
|
|
invoke QueryPerformanceCounter, OFFSET qpcPrevious
|
|
mov DWORD PTR tickAccumulator, 0
|
|
mov DWORD PTR tickAccumulator+4, 0
|
|
mov clockReset, 0
|
|
ret
|
|
InitSimulationClock ENDP
|
|
|
|
AdvanceSimulation PROC uses ebx esi edi, deltaLow:DWORD, deltaHigh:DWORD
|
|
; Drop elapsed stalls over 250ms, backwards time, and explicit pause/focus
|
|
; debt. Bound catch-up to 8 ticks even on an overloaded machine.
|
|
cmp clockReset, 0
|
|
jne clock_discard
|
|
mov eax, DWORD PTR qpcFrequency
|
|
mov edx, DWORD PTR qpcFrequency+4
|
|
shrd eax, edx, 2
|
|
shr edx, 2
|
|
cmp deltaHigh, edx
|
|
ja clock_discard
|
|
jb clock_add
|
|
cmp deltaLow, eax
|
|
ja clock_discard
|
|
clock_add:
|
|
mov eax, deltaLow
|
|
mov ebx, 60
|
|
mul ebx
|
|
imul ebx, deltaHigh
|
|
add edx, ebx
|
|
add DWORD PTR tickAccumulator, eax
|
|
adc DWORD PTR tickAccumulator+4, edx
|
|
mov esi, 8
|
|
clock_tick:
|
|
mov edx, DWORD PTR tickAccumulator+4
|
|
cmp edx, DWORD PTR qpcFrequency+4
|
|
jb clock_done
|
|
ja clock_step
|
|
mov eax, DWORD PTR tickAccumulator
|
|
cmp eax, DWORD PTR qpcFrequency
|
|
jb clock_done
|
|
clock_step:
|
|
mov eax, DWORD PTR qpcFrequency
|
|
mov edx, DWORD PTR qpcFrequency+4
|
|
sub DWORD PTR tickAccumulator, eax
|
|
sbb DWORD PTR tickAccumulator+4, edx
|
|
call Engine_Tick
|
|
cmp clockReset, 0
|
|
jne clock_discard
|
|
dec esi
|
|
jnz clock_tick
|
|
clock_discard:
|
|
mov DWORD PTR tickAccumulator, 0
|
|
mov DWORD PTR tickAccumulator+4, 0
|
|
mov clockReset, 0
|
|
clock_done:
|
|
ret
|
|
AdvanceSimulation ENDP
|
|
|
|
PumpSimulationClock PROC uses ebx
|
|
invoke QueryPerformanceCounter, OFFSET qpcNow
|
|
mov eax, DWORD PTR qpcNow
|
|
mov edx, DWORD PTR qpcNow+4
|
|
sub eax, DWORD PTR qpcPrevious
|
|
sbb edx, DWORD PTR qpcPrevious+4
|
|
mov ebx, DWORD PTR qpcNow
|
|
mov DWORD PTR qpcPrevious, ebx
|
|
mov ebx, DWORD PTR qpcNow+4
|
|
mov DWORD PTR qpcPrevious+4, ebx
|
|
invoke AdvanceSimulation, eax, edx
|
|
ret
|
|
PumpSimulationClock ENDP
|