ifndef                  _HSCROLLTEXT_ASM
_BMP_ASM                equ     1

; ------------------------------------------------------
; Includes
                        include Fonts.asm

; ------------------------------------------------------
; Structure
HSCROLLTEXT             struct
_Text                   dd      ?
mText                   dd      ?
Text_Restart            dd      ?
Positions               dd      ?
Letters_Ptr             dd      ?
Max_Nbr_Letters         dd      ?
Chars_In_Line           dd      ?
y                       dd      ?
Speed                   dd      ?
Font                    dd      ?
Color                   RGB     <?>
HSCROLLTEXT             ends

; ------------------------------------------------------
; Name: Create_HScrollText
; Desc: Fill a SCROLLTEXT structure
Create_HScrollText      proc    uses ebx esi edi ScrollText_Struct:dword
                        local   Min_Size:dword
                        
                        mov     esi, ScrollText_Struct

                        ; Determine the minimum number of chars required
                        mov     eax, [esi + HSCROLLTEXT.Font]
                        mov     ebx, [eax + BITMAP_FONT.Size_Table]
                        mov     ecx, [eax + BITMAP_FONT.Nbr_Chars]
                        mov     Min_Size, 07fffffffh
Check_Min_Size:         mov     eax, [ebx]
                        .if     eax < Min_Size
                                push    eax
                                pop     Min_Size
                        .endif
                        add     ebx, 4
                        loop    Check_Min_Size
                        mov     eax, SCREEN_WIDTH
                        cdq
                        idiv    Min_Size
                        add     eax, 2
                        mov     [esi + HSCROLLTEXT.Chars_In_Line], eax

                        shl     eax, 2
                        mov     eax, ALLOCMEM(eax)
                        .if     eax == NULL
                                xor     eax, eax
                                ret
                        .endif
                        mov     [esi + HSCROLLTEXT.Positions], eax
                        mov     eax, [esi + HSCROLLTEXT.Chars_In_Line]
                        shl     eax, 2
                        mov     eax, ALLOCMEM(eax)
                        .if     eax == NULL
                                xor     eax, eax
                                ret
                        .endif
                        mov     [esi + HSCROLLTEXT.Letters_Ptr], eax
                        invoke  lstrlen, [esi + HSCROLLTEXT._Text]
                        add     eax, [esi + HSCROLLTEXT.Chars_In_Line]
                        mov     [esi + HSCROLLTEXT.Max_Nbr_Letters], eax
                        push    eax
                        inc     eax
                        mov     eax, ALLOCMEM(eax)
                        .if     eax == NULL
                                pop     eax
                                xor     eax, eax
                                ret
                        .endif
                        mov     [esi + HSCROLLTEXT.mText], eax
                        pop     ecx
                        push    esi
                        mov     edi, [esi + HSCROLLTEXT.mText]
                        add     edi, [esi + HSCROLLTEXT.Chars_In_Line]
                        mov     [esi + HSCROLLTEXT.Text_Restart], edi
                        sub     ecx, [esi + HSCROLLTEXT.Chars_In_Line]
                        mov     esi, [esi + HSCROLLTEXT._Text]
                        rep     movsb
                        pop     esi
                        mov     edi, [esi + HSCROLLTEXT.Letters_Ptr]
                        mov     ecx, [esi + HSCROLLTEXT.Chars_In_Line]
                        mov     ebx, [esi + HSCROLLTEXT.mText]
Set_Scroll_Letters_Ptr: mov     [edi], ebx
                        add     edi, 4
                        inc     ebx
                        mov     eax, ebx
                        sub     eax, [esi + HSCROLLTEXT.mText]
                        sub     eax, [esi + HSCROLLTEXT.Max_Nbr_Letters]
                        .if     sdword ptr eax >= 0
                                mov     ebx, [esi + HSCROLLTEXT.Text_Restart]
                        .endif
                        loop    Set_Scroll_Letters_Ptr
                        mov     edx, [esi + HSCROLLTEXT.Positions]
                        mov     edi, [esi + HSCROLLTEXT.Letters_Ptr]
                        mov     ecx, [esi + HSCROLLTEXT.Chars_In_Line]
                        xor     ebx, ebx
Set_Letters_Pos:        push    ecx
                                fld     INT2FLT(ebx)
                                fstp    dword ptr [edx]
                                mov     eax, [edi]
                                movzx   eax, byte ptr [eax]
                                push    edx
                                invoke  Get_Char_Size, [esi + HSCROLLTEXT.Font], eax
                                pop     edx
                                add     ebx, eax
                                add     edx, 4
                                add     edi, 4
                        pop     ecx
                        loop    Set_Letters_Pos
                        mov     eax, TRUE
                        ret
Create_HScrollText      endp

; ------------------------------------------------------
; Name: Destroy_HScrollText
; Desc: Free the allocated resources
Destroy_HScrollText     proc    uses esi ScrollText_Struct:dword
                        mov     esi, ScrollText_Struct
                        .if     esi != NULL
                                FREEMEM [esi + HSCROLLTEXT.Positions]
                                FREEMEM [esi + HSCROLLTEXT.Letters_Ptr]
                                FREEMEM [esi + HSCROLLTEXT.mText]
                        .endif
                        ret
Destroy_HScrollText     endp

; ------------------------------------------------------
; Name: Move_HScrollText
; Desc: Move the letters positions
Move_HScrollText        proc    uses ebx esi edi ScrollText_Struct:dword, FrameRate:real4
                        local   Max_Pos:real4
                        local   Cur_Speed:real4
                        local   Cur_Freq:real4
                        
                        mov     esi, ScrollText_Struct
                        fld     INT2FLT([esi + HSCROLLTEXT.Speed])
                        fstp    Cur_Speed
                        fld     INT2FLT(g_Screen_Frequency)
                        fstp    Cur_Freq

                        ; Move all the letters in 1 pass
                        mov     edx, [esi + HSCROLLTEXT.Positions]
                        mov     ecx, [esi + HSCROLLTEXT.Chars_In_Line]
Move_Letters_Pass1:     push    ecx
                        fld     Cur_Freq
                        fmul    Cur_Speed
                        fmul    FrameRate
                        fchs
                        fadd    dword ptr [edx]
                        fld     FrameRate
                        fmul    Cur_Speed
                        fsubp   st(1), st(0)
                        fstp    dword ptr [edx]
                        add     edx, 4
                        pop     ecx
                        loop    Move_Letters_Pass1
                        ; Now compute the new positions & letters pointers
                        mov     ecx, [esi + HSCROLLTEXT.Chars_In_Line]
                        mov     edx, [esi + HSCROLLTEXT.Positions]
                        mov     edi, [esi + HSCROLLTEXT.Letters_Ptr]
Move_Letters_Pass2:     push    ecx
                        mov     eax, [edi]
                        movzx   eax, byte ptr [eax]
                        push    edx
                        invoke  Get_Char_Size, [esi + HSCROLLTEXT.Font], eax
                        pop     edx
                        neg     eax
                        FCMP    dword ptr [edx], INT2FLT(eax)
                        ja      Left_Letter_Scroll
                        mov     Max_Pos, 0
                        push    edx
                        mov     edx, [esi + HSCROLLTEXT.Positions]
                        xor     ebx, ebx
                        xor     ecx, ecx
                        .while  ebx < [esi + HSCROLLTEXT.Chars_In_Line]
                                FCMP0   dword ptr [edx]
                                jbe     Min_Pos
                                FCMP    dword ptr [edx], Max_Pos
                                jbe     Min_Pos
                                mov     eax, dword ptr [edx]
                                mov     Max_Pos, eax
                                mov     ecx, ebx
Min_Pos:                        add     edx, 4
                                inc     ebx
                        .endw
                        pop     edx
                        ; Move the position
                        mov     ebx, ecx
                        mov     ecx, [esi + HSCROLLTEXT.Letters_Ptr]
                        mov     eax, [ecx + ebx * 4]
                        movzx   eax, byte ptr [eax]
                        push    edx
                        invoke  Get_Char_Size, [esi + HSCROLLTEXT.Font], eax
                        pop     edx
                        mov     ecx, [esi + HSCROLLTEXT.Positions]
                        fld     INT2FLT(eax)                            ; Use the size
                        fadd    dword ptr [ecx + ebx * 4]               ; And the pos to compute the new position
                        fstp    dword ptr [edx]                         ; Of the letter that went out of sight on the left
                        ; Move the letter pointer
                        mov     eax, [esi + HSCROLLTEXT.Chars_In_Line]
                        add     dword ptr [edi], eax
Check_Loop_Reset_Scroll:
                        mov     eax, [edi]
                        sub     eax, [esi + HSCROLLTEXT.mText]
                        sub     eax, [esi + HSCROLLTEXT.Max_Nbr_Letters]
                        .if     sdword ptr eax >= 0
                                push    [esi + HSCROLLTEXT.Text_Restart]
                                pop     dword ptr [edi]
                                add     [edi], eax
                                jmp     Check_Loop_Reset_Scroll
                        .endif
Left_Letter_Scroll:     pop     ecx
                        add     edx, 4
                        add     edi, 4
                        dec     ecx
                        jnz     Move_Letters_Pass2
                        ret
Move_HScrollText        endp

; ------------------------------------------------------
; Name: Move_HScrollText
; Desc: Move the letters positions
Display_HScrollText     proc    uses ebx esi edi ScrollText_Struct:dword
                        mov     esi, ScrollText_Struct
                        
                        invoke  glColor3f, [esi + HSCROLLTEXT.Color.r], [esi + HSCROLLTEXT.Color.g], [esi + HSCROLLTEXT.Color.b]
                        mov     edx, [esi + HSCROLLTEXT.Positions]
                        mov     edi, [esi + HSCROLLTEXT.Letters_Ptr]
                        xor     ebx, ebx
                        .while  ebx < [esi + HSCROLLTEXT.Chars_In_Line]
                                push    edx
                                FCMP    dword ptr [edx], INT2FLT(SCREEN_WIDTH)
                                jae     No_Display_Letter
                                invoke  Display_Bitmap_Text, [edx], INT2FLT([esi + HSCROLLTEXT.y]), [esi + HSCROLLTEXT.Font], [edi], 1
No_Display_Letter:              pop     edx
                                add     edx, 4
                                add     edi, 4
                                inc     ebx
                        .endw
                        ret
Display_HScrollText     endp

endif
