section .data
    IA              dd 16807
    IM              dd 2147483647
    IQ              dd 127773
    IR              dd 2836
    NTAB            dd 32
    NDIV            dd (1 + (2147483646 / 32))
    MAX_RANDOM_RANGE dd 0x7FFFFFFF
    AM              dd 0x3E800000 ; 1.0 / 2147483647.0 (approximated in hex)
    EPS             dd 0x34D9C1AD ; 1.2e-7 (approximated in hex)
    RNMX            dd 0x3F7FFFFF ; 1.0 - 1.2e-7 (approximated in hex)
    
    m_idum          dd 0
    m_iy            dd 0
    m_iv            times 32 dd 0

section .bss

section .text
    global _start

_start:
    ; Example usage of functions

    ; Set seed
    push dword 12345
    call SetSeed
    add esp, 4

    ; Generate a random number
    call GenerateRandomNumber
    ; Result is in eax

    ; Exit program
    mov eax, 1          ; sys_exit
    xor ebx, ebx        ; return 0
    int 0x80

SetSeed:
    ; Arguments: [esp + 4] = seed
    mov eax, [esp + 4]
    test eax, eax
    js .negative_seed
    neg eax
.negative_seed:
    mov [m_idum], eax
    xor eax, eax
    mov [m_iy], eax
    ret

GenerateRandomNumber:
    ; Local variables
    push ebx
    push ecx
    push edx

    ; Check if seed is set
    mov eax, [m_idum]
    test eax, eax
    jg .generate

    ; Initialize seed
    cmp eax, -1
    jl .set_initial_seed
    mov eax, -1
.set_initial_seed:
    mov [m_idum], eax
    mov ecx, NTAB + 8

.init_loop:
    ; Perform initial shuffling
    mov eax, [m_idum]
    mov edx, IQ
    div edx
    mov ecx, eax
    mov eax, [m_idum]
    imul eax, IA
    sub eax, ecx
    imul ecx, IR
    sub eax, ecx
    jns .positive_idum
    add eax, IM
.positive_idum:
    mov [m_idum], eax
    loop .init_loop

    ; Save initial state
    mov eax, [m_iv]
    mov [m_iy], eax

.generate:
    ; Generate a random number
    mov eax, [m_idum]
    mov edx, IQ
    div edx
    mov ecx, eax
    mov eax, [m_idum]
    imul eax, IA
    sub eax, ecx
    imul ecx, IR
    sub eax, ecx
    jns .positive_idum2
    add eax, IM
.positive_idum2:
    mov [m_idum], eax
    mov ecx, NDIV
    div ecx
    mov ecx, eax
    mov eax, [m_iy]
    add ecx, eax
    mov eax, [m_iv + ecx * 4]
    mov [m_iy], eax
    mov [m_iv + ecx * 4], eax

    ; Return random number
    pop edx
    pop ecx
    pop ebx
    ret

RandomFloat:
    ; Arguments: [esp + 4] = flLow, [esp + 8] = flHigh
    call GenerateRandomNumber
    fild dword [esp + 4]    ; Load random number as float
    fmul dword [AM]
    fld dword [RNMX]
    fcomi st, st1
    jae .use_rnmx
    jmp .continue

.use_rnmx:
    fld dword [RNMX]

.continue:
    fld dword [esp + 8]
    fsub dword [esp + 4]
    fmul st, st1
    fadd dword [esp + 4]
    ret 8

RandomFloatExp:
    ; Arguments: [esp + 4] = flMinVal, [esp + 8] = flMaxVal, [esp + 12] = flExponent
    call GenerateRandomNumber
    fild dword [esp + 4]    ; Load random number as float
    fmul dword [AM]
    fld dword [RNMX]
    fcomi st, st1
    jae .use_rnmx_exp
    jmp .continue_exp

.use_rnmx_exp:
    fld dword [RNMX]

.continue_exp:
    fld dword [esp + 12]
    fld st1
    fyl2x
    fscale
    fld dword [esp + 8]
    fsub dword [esp + 4]
    fmul st, st1
    fadd dword [esp + 4]
    ret 12

RandomInt:
    ; Arguments: [esp + 4] = iLow, [esp + 8] = iHigh
    mov eax, [esp + 8]
    sub eax, [esp + 4]
    inc eax

    cmp eax, 1
    jbe .return_ilow

    mov ecx, MAX_RANDOM_RANGE
    cmp eax, ecx
    ja .return_ilow

    call GenerateRandomNumber
    mov edx, ecx
    sub edx, eax
    inc edx
    div edx

    add eax, [esp + 4]
    ret 8

.return_ilow:
    mov eax, [esp + 4]
    ret 8




section .data
    iBase           dd 0
    SWCS_SPREAD_SHARE_SEED db 0      ; Assuming it's false for simplicity
    SWCS_SPREAD_MAX_SEEDS dd 0xFFFFFFFF
    owner_is_player db 1             ; Assuming owner is a player
    owner_last_cmd_num dd 1234       ; Example value
    engine_tick_count dd 5678        ; Example value
    self_ent_index dd 1              ; Example value

section .bss

section .text
    global _start

_start:
    ; Example: call GetRandomSeed function
    call GetRandomSeed
    ; Random seed is now in eax

    ; Exit program
    mov eax, 1
    xor ebx, ebx
    int 0x80

GetRandomSeed:
    ; Check if SWCS_SPREAD_SHARE_SEED is true or false
    mov eax, [SWCS_SPREAD_SHARE_SEED]
    test eax, eax
    jz .not_shared
    ; If shared
    xor eax, eax
    jmp .check_owner

.not_shared:
    ; If not shared, set iBase to self:GetUnsharedSeed()
    ; Assuming self:GetUnsharedSeed() returns 0 for simplicity
    xor eax, eax

.check_owner:
    ; Check if owner is player
    movzx ecx, byte [owner_is_player]
    test ecx, ecx
    jz .not_player

    ; If owner is player
    mov eax, [owner_last_cmd_num]
    add eax, [iBase]
    jmp .finalize_seed

.not_player:
    ; If owner is not player
    mov eax, [engine_tick_count]
    add eax, [self_ent_index]
    add eax, [iBase]

.finalize_seed:
    ; Apply bitwise AND with SWCS_SPREAD_MAX_SEEDS
    and eax, [SWCS_SPREAD_MAX_SEEDS]
    ret

section .data
    owner_is_valid db 1              ; Assuming owner is valid
    weapon_accuracy_nospread db 0    ; Example value
    weapon_accuracy_forcespread dd 0 ; Example value
    owner_is_player db 1             ; Assuming owner is a player
    owner_velocity dd 0              ; Example velocity value
    fMaxSpeed dd 250                 ; Example max speed
    fAccuracy dd 0                   ; Example accuracy penalty
    CS_PLAYER_SPEED_DUCK_MODIFIER dd 0.34
    MOVEMENT_CURVE01_EXPONENT dd 1.5
    FL_ONGROUND db 1                 ; Example flag state
    weapon_air_spread_scale dd 1.0

section .bss

section .text
    global _start

_start:
    ; Example: call GetInaccuracy function
    call GetInaccuracy
    ; Inaccuracy value is now in eax

    ; Exit program
    mov eax, 1
    xor ebx, ebx
    int 0x80

GetInaccuracy:
    ; Check if owner is valid
    movzx eax, byte [owner_is_valid]
    test eax, eax
    jz .return_zero

    ; Check if nospread is enabled
    movzx eax, byte [weapon_accuracy_nospread]
    test eax, eax
    jnz .return_zero

    ; Check if forcespread is greater than 0
    mov eax, [weapon_accuracy_forcespread]
    test eax, eax
    jz .calculate_inaccuracy

    ; Return forcespread
    fld dword [weapon_accuracy_forcespread]
    fistp dword [esp-4]
    mov eax, [esp-4]
    jmp .end

.return_zero:
    xor eax, eax
    jmp .end

.calculate_inaccuracy:
    ; Load max speed and accuracy penalty
    mov eax, [fMaxSpeed]
    fld dword [fMaxSpeed]
    fld dword [fAccuracy]

    ; Load velocity (assuming 2D length for simplicity)
    mov eax, [owner_velocity]
    fld dword [owner_velocity]

    ; Compute movement inaccuracy scale
    fld st1
    fmul dword [CS_PLAYER_SPEED_DUCK_MODIFIER]
    fld st1
    fmul dword [0.95]
    fdiv
    fld1
    fsub
    fstp dword [esp-4]
    mov eax, [esp-4]
    
    ; Check if movement inaccuracy scale is greater than 0
    test eax, eax
    jle .jump_inaccuracy

    ; Apply movement inaccuracy curve if player is moving
    movzx eax, byte [owner_is_player]
    test eax, eax
    jz .apply_movement_inaccuracy

    ; Apply walking condition
    ; Assuming walking state is stored in a variable
    ; if not (owner:KeyDown(IN_WALK))
    ; then
    ; pow(movement_scale, MOVEMENT_CURVE01_EXPONENT)

.apply_movement_inaccuracy:
    fld dword [MOVEMENT_CURVE01_EXPONENT]
    fyl2x
    f2xm1
    fadd st, st1
    fscale
    fstp dword [esp-4]
    mov eax, [esp-4]

.jump_inaccuracy:
    ; Check if player is in the air
    movzx eax, byte [owner_is_player]
    test eax, eax
    jz .final_inaccuracy

    ; Assuming jumping state is stored in a variable
    ; Apply jump inaccuracy logic here

.final_inaccuracy:
    ; Return final inaccuracy value
    fld dword [fAccuracy]
    fistp dword [esp-4]
    mov eax, [esp-4]

.end:
    ret

section .data
    iSpreadIndex dd 0
    self_bullets dd 1
    rand dd 0
    spread_seed dd 0
    m_SpreadData times 64 dd 0

section .bss

section .text
    global _start

_start:
    ; Example: call GetSpreadOffset function
    call GetSpreadOffset
    ; Spread offset values (theta and curve density) are in eax and edx

    ; Exit program
    mov eax, 1
    xor ebx, ebx
    int 0x80

GetSpreadOffset:
    ; Check if spread seed and bullets conditions are met
    mov eax, [spread_seed]
    test eax, eax
    jz .random_values

    mov eax, [self_bullets]
    cmp eax, 1
    jle .random_values

    mov eax, [iSpreadIndex]
    cmp eax, 64
    jge .random_values

    ; Retrieve data from m_SpreadData
    mov ecx, [iSpreadIndex]
    mov eax, [m_SpreadData + ecx * 8]
    mov edx, [m_SpreadData + ecx * 8 + 4]
    jmp .end

.random_values:
    ; Generate random values
    call GenerateRandomFloat  ; Assuming a function to generate random float
    fstp dword [esp-4]
    mov eax, [esp-4]

    call GenerateRandomFloat
    fstp dword [esp-8]
    mov edx, [esp-8]

.end:
    ret


section .data
    self_bullets dd 10
    spread_seed dd 0
    data times 64 dd 0

section .bss

section .text
    global _start

_start:
    ; Example: call GenerateSpreadTable function
    call GenerateSpreadTable
    ; Spread table is now populated

    ; Exit program
    mov eax, 1
    xor ebx, ebx
    int 0x80

GenerateSpreadTable:
    ; Initialize bullets in shot
    mov eax, [self_bullets]
    cmp eax, 1
    jle .end

    cmp eax, 64
    jle .set_bullets
    mov eax, 64
.set_bullets:
    mov [self_bullets], eax

    ; Check spread seed
    mov eax, [spread_seed]
    test eax, eax
    jz .generate_seed

.generate_seed:
    ; Assume seed generation based on CRC (omitted for brevity)

    ; Initialize random number generator
    ; Assuming a function to initialize RNG with a seed
    call InitializeRandomGenerator

    ; Loop to fill spread data
    mov ecx, 64
    xor edx, edx

.loop_start:
    ; Generate random values for theta and curve density
    call GenerateRandomFloat
    fstp dword [esp-4]
    mov eax, [esp-4]

    call GenerateRandomFloat
    fstp dword [esp-8]
    mov ebx, [esp-8]

    ; Store values in data array
    mov [data + edx * 8], eax
    mov [data + edx * 8 + 4], ebx

    inc edx
    loop .loop_start

.end:
    ret

section .data
    swcs_weapon_sync_seed db 0 ; Assuming false
    weapon_accuracy_nospread db 0 ; Assuming false
    weapon_debug_max_inaccuracy db 0 ; Assuming false
    weapon_debug_inaccuracy_only_up db 0 ; Assuming false
    math_pi dd 3.141592653589793
    UniformRandomStream_seed dd 0
    SWEP_Inaccuracy dd 0
    SWEP_Spread dd 0

section .bss

section .text
    global _start

_start:
    ; Call CalculateCurrentCone function
    call CalculateCurrentCone

    ; Exit program
    mov eax, 1
    xor ebx, ebx
    int 0x80

CalculateCurrentCone:
    ; Set seed for UniformRandomStream
    mov eax, [UniformRandomStream_seed]
    inc eax
    call UniformRandomStream_SetSeed

    ; Generate random float
    call UniformRandomStream_RandomFloat
    ; Assuming the result is in eax
    mov [flRadiusCurveDensity], eax

    ; Check if max inaccuracy debug is enabled
    movzx eax, byte [weapon_debug_max_inaccuracy]
    test eax, eax
    jz .check_inaccuracy_only_up

    ; If true, set flRadiusCurveDensity to 1
    mov [flRadiusCurveDensity], 1

.check_inaccuracy_only_up:
    ; Generate random float for theta
    call UniformRandomStream_RandomFloat
    ; Assuming the result is in eax
    mov [fTheta0], eax

    ; Check if inaccuracy only up debug is enabled
    movzx eax, byte [weapon_debug_inaccuracy_only_up]
    test eax, eax
    jz .calculate_radius0

    ; If true, set fTheta0 to pi/2
    fld dword [math_pi]
    fld1
    fld1
    fdiv
    fstp dword [fTheta0]

.calculate_radius0:
    ; Compute fRadius0 = flRadiusCurveDensity * SWEP:GetInaccuracy(false)
    fld dword [flRadiusCurveDensity]
    fld dword [SWEP_Inaccuracy]
    fmul
    fstp dword [fRadius0]

    ; Generate random float for fTheta1
    call UniformRandomStream_RandomFloat
    ; Assuming the result is in eax
    mov [fTheta1], eax

    ; Generate random float for fRadius1
    call UniformRandomStream_RandomFloat
    ; Assuming the result is in eax
    mov [flRandomFloat], eax

    ; Compute fRadius1 = flRandomFloat * SWEP:GetSpread()
    fld dword [flRandomFloat]
    fld dword [SWEP_Spread]
    fmul
    fstp dword [fRadius1]

    ; Compute result x = fRadius0 * cos(fTheta0) + fRadius1 * cos(fTheta1)
    fld dword [fRadius0]
    fld dword [fTheta0]
    fcos
    fmul
    fld dword [fRadius1]
    fld dword [fTheta1]
    fcos
    fmul
    fadd
    fstp dword [x]

    ; Compute result y = fRadius0 * sin(fTheta0) + fRadius1 * cos(fTheta1)
    fld dword [fRadius0]
    fld dword [fTheta0]
    fsin
    fmul
    fld dword [fRadius1]
    fld dword [fTheta1]
    fsin
    fmul
    fadd
    fstp dword [y]

    ; Return x and y
    mov eax, [x]
    mov edx, [y]
    ret

section .data
    swcs_weapon_sync_seed db 0 ; Assuming false
    weapon_accuracy_nospread db 0 ; Assuming false
    Ang_forward dd 0.0, 0.0, 1.0 ; Forward vector of Ang
    Ang_right dd 1.0, 0.0, 0.0 ; Right vector of Ang
    Ang_up dd 0.0, 1.0, 0.0 ; Up vector of Ang

section .bss

section .text
    global _start

_start:
    ; Call CalculateSpread function
    call CalculateSpread

    ; Exit program
    mov eax, 1
    xor ebx, ebx
    int 0x80

CalculateSpread:
    ; Check conditions
    movzx eax, byte [swcs_weapon_sync_seed]
    test eax, eax
    jz .bypass_aim_punch

    movzx eax, byte [weapon_accuracy_nospread]
    test eax, eax
    jz .calculate_current_cone

.bypass_aim_punch:
    ; Call GetUninterpolatedAimPunchAngle
    call GetUninterpolatedAimPunchAngle
    ; Assuming the result is in eax
    ; Subtract from Ang
    ; Result in eax
    sub eax, eax
    ret

.calculate_current_cone:
    ; Call CalculateCurrentCone
    call CalculateCurrentCone
    ; Assuming x is in eax and y is in edx

    ; Check if x or y is zero
    test eax, eax
    jz .return_ang

    test edx, edx
    jz .return_ang

    ; Compute RetVec = Ang
    ; Assuming forward, right, up vectors are predefined
    fld dword [Ang_forward]
    fld dword [Ang_right]
    fmul dword [eax] ; x
    fld dword [Ang_up]
    fmul dword [edx] ; y
    fadd ; Add vectors
    ; Convert to angle (omitted for brevity)

    ; Normalize RetVec (omitted for brevity)

    ; Subtract GetUninterpolatedAimPunchAngle from RetVec
    ; Assuming result is in eax
    sub eax, eax
    ret

.return_ang:
    ; Return Ang
    ret
