- Stage 1: Eliminate fish-eye distortion with precomputed tangential ray offset table and fractional DDA depth - Stage 2: Full asset management in EblanStudio (stb_image/stb_image_write, 128x128 BGRA texture packaging, WAV sound manager) - Stage 3: Multi-level room streaming, LevelTransition/CELL_PORTAL trigger system, 16-frame screen fade to black - Stage 4: 60Hz cutscene engine in pure x86 ASM (v4 binary track, waypoint camera motion, shortest-arc pan, CP1251 Russian subtitles, letterbox overlay, audio) - Stage 5: EblanStudio cutscene timeline (F6) and windowless Live ASM Viewport over shared-memory IPC directly rendered into DX11 - Tooling & Tests: comprehensive regression test suite (94 editor + 107 engine tests), IPC tests, and cutscene demo
147 lines
4.2 KiB
PHP
147 lines
4.2 KiB
PHP
; ==============================================================================
|
|
; EBLAN ENGINE - Math, Fixed-Point Trigonometry & RNG
|
|
; ==============================================================================
|
|
|
|
.data
|
|
fAngleDiv REAL4 256.0
|
|
fFixedScale REAL4 65536.0
|
|
fScreenHalfW REAL4 160.0
|
|
fTanHalfFov REAL4 0.66817864 ; tan(48 * PI / 256) = tan(33.75 deg)
|
|
fRadToAngle REAL4 81.48733 ; 256.0 / PI
|
|
|
|
.code
|
|
|
|
; ------------------------------------------------------------------------------
|
|
; InitMathTables: Builds 512-entry Sin & Cos tables in 16.16 fixed point,
|
|
; and 320-entry tangential ray angle offset table for flat-plane projection.
|
|
; ------------------------------------------------------------------------------
|
|
InitMathTables PROC uses eax ecx edi
|
|
LOCAL curVal:DWORD
|
|
|
|
; 1. Generate 512-entry Sin/Cos tables
|
|
mov ecx, 0
|
|
init_angle_loop:
|
|
mov curVal, ecx
|
|
|
|
fldpi
|
|
fimul curVal
|
|
fdiv fAngleDiv ; st(0) = (angle * PI) / 256
|
|
|
|
fsincos ; st(0) = cos, st(1) = sin
|
|
|
|
; Process Cosine
|
|
fmul fFixedScale
|
|
fistp DWORD PTR [tableCos + ecx*4]
|
|
|
|
; Process Sine
|
|
fmul fFixedScale
|
|
fistp DWORD PTR [tableSin + ecx*4]
|
|
|
|
inc ecx
|
|
cmp ecx, ANGLE_512
|
|
jl init_angle_loop
|
|
|
|
; 2. Generate 320-entry Ray Angle Offset table (tangential perspective correction)
|
|
; and precomputed cosine table for instant fish-eye correction.
|
|
; angleOffset = round( atan(((x - 160.0) / 160.0) * tan(FOV/2)) * (256.0 / PI) )
|
|
mov ecx, 0
|
|
init_ray_loop:
|
|
mov curVal, ecx
|
|
|
|
fild curVal ; st(0) = x
|
|
fsub fScreenHalfW ; st(0) = x - 160.0
|
|
fdiv fScreenHalfW ; st(0) = (x - 160.0) / 160.0 = cameraX
|
|
fmul fTanHalfFov ; st(0) = cameraX * tan(FOV/2)
|
|
fld1 ; st(0) = 1.0, st(1) = cameraX * tan(FOV/2)
|
|
fpatan ; st(0) = atan(st(1)/st(0)) = radOffset
|
|
fmul fRadToAngle ; st(0) = radOffset * (256.0 / PI)
|
|
fistp DWORD PTR [tableRayAngleOffset + ecx*4]
|
|
|
|
; Precompute tableRayCos[ecx] = cos(angleOffset)
|
|
mov eax, DWORD PTR [tableRayAngleOffset + ecx*4]
|
|
and eax, ANGLE_MASK
|
|
mov edx, [tableCos + eax*4]
|
|
mov DWORD PTR [tableRayCos + ecx*4], edx
|
|
|
|
inc ecx
|
|
cmp ecx, SCREEN_W
|
|
jl init_ray_loop
|
|
|
|
ret
|
|
InitMathTables ENDP
|
|
|
|
; ------------------------------------------------------------------------------
|
|
; RandomRange: Generates pseudo-random uint in [0, maxVal-1]
|
|
; Input: maxVal (eax)
|
|
; Output: eax
|
|
; ------------------------------------------------------------------------------
|
|
RandomRange PROC uses ecx edx, maxVal:DWORD
|
|
cmp maxVal, 1
|
|
jle rand_zero
|
|
|
|
mov eax, rngSeed
|
|
imul eax, 1103515245
|
|
add eax, 12345
|
|
mov rngSeed, eax
|
|
|
|
shr eax, 16
|
|
xor edx, edx
|
|
div maxVal
|
|
mov eax, edx
|
|
ret
|
|
|
|
rand_zero:
|
|
xor eax, eax
|
|
ret
|
|
RandomRange ENDP
|
|
|
|
; ------------------------------------------------------------------------------
|
|
; FixedMul: Multiplies two 16.16 fixed-point numbers
|
|
; Input: a, b
|
|
; Output: eax = (a * b) >> 16
|
|
; ------------------------------------------------------------------------------
|
|
FixedMul PROC uses edx, valA:DWORD, valB:DWORD
|
|
mov eax, valA
|
|
imul valB
|
|
shrd eax, edx, 16
|
|
ret
|
|
FixedMul ENDP
|
|
|
|
; ------------------------------------------------------------------------------
|
|
; FixedDiv: Divides two 16.16 fixed-point numbers
|
|
; Input: a, b
|
|
; Output: eax = (a << 16) / b
|
|
; ------------------------------------------------------------------------------
|
|
FixedDiv PROC uses ebx edx, valA:DWORD, valB:DWORD
|
|
mov eax, valA
|
|
mov ebx, valB
|
|
test ebx, ebx
|
|
jz div_zero
|
|
|
|
cdq
|
|
shld edx, eax, 16
|
|
shl eax, 16
|
|
idiv ebx
|
|
ret
|
|
|
|
div_zero:
|
|
mov eax, 7FFFFFFFh ; Return max int on divide-by-zero
|
|
ret
|
|
FixedDiv ENDP
|
|
|
|
; ------------------------------------------------------------------------------
|
|
; ClampInt: Clamps value between minVal and maxVal
|
|
; ------------------------------------------------------------------------------
|
|
ClampInt PROC val:DWORD, minVal:DWORD, maxVal:DWORD
|
|
mov eax, val
|
|
cmp eax, minVal
|
|
jge @F
|
|
mov eax, minVal
|
|
ret
|
|
@@:
|
|
cmp eax, maxVal
|
|
jle @F
|
|
mov eax, maxVal
|
|
@@:
|
|
ret
|
|
ClampInt ENDP
|