; ============================================================================== ; 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