;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                                                              ;;
;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;;
;; Distributed under terms of the GNU General Public License    ;;
;;                                                              ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

$Revision$

struc VBE_VGAInfo {
  .VESASignature          dd ?    ; char
  .VESAVersion            dw ?    ; short
  .OemStringPtr           dd ?    ; char *
  .Capabilities           dd ?    ; ulong
  .VideoModePtr           dd ?    ; ulong
  .TotalMemory            dw ?    ; short
  ; VBE 2.0+
  .OemSoftwareRev         db ?    ; short
  .OemVendorNamePtr       dw ?    ; char *
  .OemProductNamePtr      dw ?    ; char *
  .OemProductRevPtr       dw ?    ; char *
  .reserved               rb 222  ; char
  .OemData                rb 256  ; char
}

struc VBE_ModeInfo {
  .ModeAttributes         dw ?    ; short
  .WinAAttributes         db ?    ; char
  .WinBAttributes         db ?    ; char
  .WinGranularity         dw ?    ; short
  .WinSize                dw ?    ; short
  .WinASegment            dw ?    ; ushort
  .WinBSegment            dw ?    ; ushort
  .WinFuncPtr             dd ?    ; void *
  .BytesPerScanLine       dw ?    ; short
  .XRes                   dw ?    ; short
  .YRes                   dw ?    ; short
  .XCharSize              db ?    ; char
  .YCharSize              db ?    ; char
  .NumberOfPlanes         db ?    ; char
  .BitsPerPixel           db ?    ; char
  .NumberOfBanks          db ?    ; char
  .MemoryModel            db ?    ; char
  .BankSize               db ?    ; char
  .NumberOfImagePages     db ?    ; char
  .res1                   db ?    ; char
  .RedMaskSize            db ?    ; char
  .RedFieldPosition       db ?    ; char
  .GreenMaskSize          db ?    ; char
  .GreenFieldPosition     db ?    ; char
  .BlueMaskSize           db ?    ; char
  .BlueFieldPosition      db ?    ; char
  .RsvedMaskSize          db ?    ; char
  .RsvedFieldPosition     db ?    ; char
  .DirectColorModeInfo    db ?    ; char ; MISSED IN THIS TUTORIAL!! SEE ABOVE
  ; VBE 2.0+
  .PhysBasePtr            dd ?    ; ulong
  .OffScreenMemOffset     dd ?    ; ulong
  .OffScreenMemSize       dw ?    ; short
  ; VBE 3.0+
  .LinbytesPerScanLine    dw ?    ; short
  .BankNumberOfImagePages db ?    ; char
  .LinNumberOfImagePages  db ?    ; char
  .LinRedMaskSize         db ?    ; char
  .LinRedFieldPosition    db ?    ; char
  .LingreenMaskSize       db ?    ; char
  .LinGreenFieldPosition  db ?    ; char
  .LinBlueMaskSize        db ?    ; char
  .LinBlueFieldPosition   db ?    ; char
  .LinRsvdMaskSize        db ?    ; char
  .LinRsvdFieldPosition   db ?    ; char
  .MaxPixelClock          dd ?    ; ulong
  .res2                   rb 190  ; char
}

virtual at $A000
  vi VBE_VGAInfo
  mi VBE_ModeInfo
modes_table:
end virtual
cursor_pos  dw 0         ;временное хранение курсора.
cursor_pos_old  dw 0
home_cursor dw 0    ;current shows rows a table
end_cursor  dw 0     ;end of position current shows rows a table
scroll_start dw 0    ;start position of scroll bar
scroll_end  dw 0     ;end position of scroll bar
long_v_table equ 9   ;long of visible video table
size_of_step equ 10
scroll_area_size equ (long_v_table-2)
int2str:
        dec     bl
        jz      @f
        xor     edx, edx
        div     ecx
        push    edx
        call    int2str
        pop     eax
    @@:
        or      al, 0x30
        mov     [ds:di], al
        inc     di
        ret

int2strnz:
        cmp     eax, ecx
        jb      @f
        xor     edx, edx
        div     ecx
        push    edx
        call    int2strnz
        pop     eax
    @@:
        or      al, 0x30
        mov     [es:di], al
        inc     di
        ret

;-------------------------------------------------------
;Write message about incorrect v_mode and write message about jmp on swith v_mode
v_mode_error:
        _setcursor 19,2
        mov     si, fatalsel
        call    printplain
        _setcursor 20,2
        mov     si, pres_key
        call    printplain
        xor     eax, eax
        int     16h
        jmp     cfgmanager.d
;-------------------------------------------------------
;



;-------------------------------------------------------
print_vesa_info:
        _setcursor 5,2

        mov     [es:vi.VESASignature], 'VBE2'
        mov     ax, 0x4F00
        mov     di, vi     ;0xa000
        int     0x10
        or      ah, ah
        jz      @f
        mov     [es:vi.VESASignature], 'VESA'
        mov     ax, $4F00
        mov     di, vi
        int     0x10
        or      ah, ah
        jnz     .exit
  @@:
        cmp     [es:vi.VESASignature], 'VESA'
        jne     .exit
        cmp     [es:vi.VESAVersion], 0x0100
        jb      .exit
        jmp     .vesaok2

  .exit:
        mov     si, novesa
        call    printplain
        ret

  .vesaok2:
        mov     ax, [es:vi.VESAVersion]
        add     ax, '00'

        mov     [s_vesa.ver], ah
        mov     [s_vesa.ver+2], al
        mov     si, s_vesa
        call    printplain

        _setcursor 4,2
        mov     si, word[es:vi.OemStringPtr]
        mov     di, si

        push    ds
        mov     ds, word[es:vi.OemStringPtr+2]
        call    printplain
        pop     ds

        ret
;-----------------------------------------------------------------------------

calc_vmodes_table:
        pushad

;        push    0
;        pop     es

        lfs     si, [es:vi.VideoModePtr]

        mov     bx, modes_table
;save no vesa mode of work 320x200, EGA/CGA 256 梥⮢ and 640x480, VGA 16 梥⮢
        mov     word [es:bx], 640
        mov     word [es:bx+2], 480
        mov     word [es:bx+6], 0x13
        
        mov     word [es:bx+10], 640
        mov     word [es:bx+12], 480
        mov     word [es:bx+16], 0x12
        add     bx, 20
  .next_mode:
        mov     cx, word [fs:si]; mode number
        cmp     cx, -1
        je      .modes_ok.2

        mov     ax, 0x4F01
        mov     di, mi
        int     0x10

        or      ah, ah
        jnz     .modes_ok.2;vesa_info.exit

        test    [es:mi.ModeAttributes], 00000001b  ;videomode support ?
        jz      @f
        test    [es:mi.ModeAttributes], 00010000b  ;picture ?
        jz      @f
        test    [es:mi.ModeAttributes], 10000000b  ;LFB ?
        jz      @f

        cmp     [es:mi.BitsPerPixel], 16   ;List only supported videomodes (16, 24 and 32 bpp)
        jb      @f

; 16 bpp might actually be 15 bpp
        cmp     [es:mi.BitsPerPixel], 16 
        jne     .l0
        cmp     [es:mi.GreenMaskSize], 5
        jne     .l0
;        mov     [es:mi.BitsPerPixel],15
        jmp     @f                         ; 15 bpp isnt supported ATM


.l0:
        cmp     [es:mi.XRes], 640
        jb      @f
        cmp     [es:mi.YRes], 480
        jb      @f
;        cmp     [es:mi.BitsPerPixel],8
;        jb      @f

        mov     ax, [es:mi.XRes]
        mov     [es:bx+0], ax              ; +0[2] : resolution X
        mov     ax, [es:mi.YRes]
        mov     [es:bx+2], ax              ; +2[2] : resolution Y
        mov     ax, [es:mi.ModeAttributes]
        mov     [es:bx+4], ax              ; +4[2] : attributes

        cmp     [s_vesa.ver], '2'
;        jb      .lp1
        jb      @f    ; We do not use Vesa 1.2 mode is now

        or      cx, 0x4000 ; use LFB
.lp1:
        mov     [es:bx+6], cx              ; +6 : mode number
        movzx   ax, byte [es:mi.BitsPerPixel]
        mov     word [es:bx+8], ax              ; +8 : bits per pixel
        add     bx, size_of_step                ; size of record

    @@:
        add     si, 2
        jmp     .next_mode

  .modes_ok.2:

        mov     word[es:bx], -1 ;end video table
        mov     word[end_cursor], bx    ;save end cursor position
;;;;;;;;;;;;;;;;;;
;Sort array
;        mov     si,modes_table
;.new_mode:
;        mov     ax,word [es:si]
;        cmp     ax,-1
;        je      .exxit
;        add     ax,word [es:si+2]
;        add     ax,word [es:si+8]
;        mov     bp,si
;.again:
;        add     bp,12
;        mov     bx,word [es:bp]
;        cmp     bx,-1
;        je      .exit
;        add     bx,word [es:bp+2]
;        add     bx,word [es:bp+8]
;
;        cmp     ax,bx
;        ja      .loops
;        jmp     .again
;.loops:
;        push    dword [es:si]
;        push    dword [es:si+4]
;        push    dword [es:si+8]
;        push    dword [es:bp]
;        push    dword [es:bp+4]
;        push    dword [es:bp+8]
;
;        pop     dword [es:si+8]
;        pop     dword [es:si+4]
;        pop     dword [es:si]
;        pop     dword [es:bp+8]
;        pop     dword [es:bp+4]
;        pop     dword [es:bp]
;        jmp     .new_mode
;
;.exit:  add     si,12
;        jmp     .new_mode
;.exxit:
        popad
        ret

;-----------------------------------------------------------------------------

draw_current_vmode:
        push    0
        pop     es

        mov     si, word [cursor_pos]

        cmp     word [es:si+6], 0x12
        je      .no_vesa_0x12

        cmp     word [es:si+6], 0x13
        je      .no_vesa_0x13

if defined extended_primary_loader
        mov     di, config_file_variables
else
        mov     di, loader_block_error
end if
        movzx   eax, word[es:si+0]
        mov     ecx, 10
        call    int2strnz
        mov     byte[es:di], 'x'
        inc     di
        movzx   eax, word[es:si+2]
        call    int2strnz
        mov     byte[es:di], 'x'
        inc     di
        movzx   eax, word[es:si+8]
        call    int2strnz
        mov     dword[es:di], 0x00000d0a
if defined extended_primary_loader
        mov     si, config_file_variables
else
        mov     si, loader_block_error
end if
        push    ds
        push    es
        pop     ds
        call    printplain
        pop     ds
        ret
.no_vesa_0x13:
        mov     si, mode0
        jmp     .print
.no_vesa_0x12:
        mov     si, mode9
.print:
        call    printplain
        ret
;-----------------------------------------------------------------------------
check_first_parm:
if defined extended_primary_loader
        mov     cx, [number_vm]
        jcxz    .novbemode
        mov     si, modes_table
.findvbemode:
        cmp     [es:si+6], cx
        jnz     @f
        cmp     word [es:si+8], 32
        je      .ok_found_mode
        cmp     word [es:si+8], 24
        je      .ok_found_mode
        cmp     word [es:si+8], 16
        je      .ok_found_mode
@@:
        add     si, size_of_step
        cmp     word [es:si], -1
        jnz     .findvbemode
.novbemode:
        mov     ax, [x_save]
        test    ax, ax
        jz      .zerro
        mov     bx, [y_save]
        mov     si, modes_table
        call    .loops
        test    ax, ax
        jz      .ok_found_mode
else
        mov     si, word [preboot_graph]
        test    si, si
        jnz     .no_zero         ;if no zero
end if
.zerro:
;        mov     ax,modes_table
;        mov     word [cursor_pos],ax
;        mov     word [home_cursor],ax
;        mov     word [preboot_graph],ax
;SET default video of mode first probe will fined a move of work 1024x768@32
        mov     cx, 32
  .find_mode:
        mov     ax, 1024
        mov     bx, 768
        mov     si, modes_table
        call    .loops
        test    ax, ax
        jz      .ok_found_mode
        mov     ax, 800
        mov     bx, 600
        mov     si, modes_table
        call    .loops
        test    ax, ax
        jz      .ok_found_mode
        mov     ax, 640
        mov     bx, 480
        mov     si, modes_table
        call    .loops
        test    ax, ax
        jz      .ok_found_mode
        sub     cx, 8
        jnz     .find_mode

        mov     si, modes_table
if ~ defined extended_primary_loader
        jmp     .ok_found_mode



.no_zero:
        mov     bp, word [number_vm]
        cmp     bp, word [es:si+6]
        jz      .ok_found_mode
        mov     ax, word [x_save]
        mov     bx, word [y_save]
        mov     si, modes_table
        call    .loops
        test    ax, ax
        jz      .ok_found_mode

        mov     si, modes_table
;        cmp     ax,modes_table
;        jb      .zerro           ;check on correct if bellow
;        cmp     ax,word [end_cursor]
;        ja      .zerro           ;check on correct if anymore
end if

.ok_found_mode:
        mov     word [home_cursor], si
;        mov     word [cursor_pos],si
        mov     word [preboot_graph], si
        mov     ax, si

        mov     ecx, long_v_table

.loop:
        add     ax, size_of_step
        cmp     ax, word [end_cursor]
        jae     .next_step
        loop    .loop
.next_step:
        sub     ax, size_of_step*long_v_table
        cmp     ax, modes_table
        jae     @f
        mov     ax, modes_table
@@:

        mov     word [home_cursor], ax
        mov     si, [preboot_graph]
        mov     word [cursor_pos], si

        push    word [es:si]
        pop     word [x_save]
        push    word [es:si+2]
        pop     word [y_save]
        push    word [es:si+6]
        pop     word [number_vm]

        ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;
.loops:
        cmp     ax, word [es:si]
        jne     .next
        cmp     bx, word [es:si+2]
        jne     .next
        cmp     cx, word [es:si+8]
        jne     .next
        xor     ax, ax
        ret
.next:
        add     si, size_of_step
        cmp     word [es:si], -1
        je      .exit
        jmp     .loops
.exit:
        or      ax, -1
        ret


;-----------------------------------------------------------------------------

;default_vmode:

;-----------------------------------------------------------------------------
draw_vmodes_table:
        _setcursor 9, 2
        mov     si, gr_mode
        call    printplain

        mov     si, _st
        call    printplain

        push    word [cursor_pos]
        pop     ax
        push    word [home_cursor]
        pop     si
        mov     cx, si

        cmp     ax, si
        je      .ok
        jb      .low


        add     cx, size_of_step*long_v_table

        cmp     ax, cx
        jb      .ok

        sub     cx, size_of_step*long_v_table
        add     cx, size_of_step
        cmp     cx, word[end_cursor]
        jae     .ok
        add     si, size_of_step
        push    si
        pop     word [home_cursor]
        jmp     .ok


.low:
        sub     cx, size_of_step
        cmp     cx, modes_table
        jb      .ok
        push    cx
        push    cx
        pop     word [home_cursor]
        pop     si


.ok:
; calculate scroll position
        push    si
        mov     ax, [end_cursor]
        sub     ax, modes_table
        mov     bx, size_of_step
        cwd
        div     bx
        mov     si, ax          ; si = size of list
        mov     ax, [home_cursor]
        sub     ax, modes_table
        cwd
        div     bx
        mov     di, ax
        mov     ax, scroll_area_size*long_v_table
        cwd
        div     si
        test    ax, ax
        jnz     @f
        inc     ax
@@:
        cmp     al, scroll_area_size
        jb      @f
        mov     al, scroll_area_size
@@:
        mov     cx, ax
; cx = scroll height
; calculate scroll pos
        xor     bx, bx          ; initialize scroll pos
        sub     al, scroll_area_size+1
        neg     al
        sub     si, long_v_table-1
        jbe     @f
        mul     di
        div     si
        mov     bx, ax
@@:
        inc     bx
        imul    ax, bx, size_of_step
        add     ax, [home_cursor]
        mov     [scroll_start], ax
        imul    cx, size_of_step
        add     ax, cx
        mov     [scroll_end], ax
        pop     si
        mov     bp, long_v_table              ;show rows
.@@_next_bit:
;clear cursor
        mov     ax, '  '
        mov     word[ds:_r1+21], ax
        mov     word[ds:_r1+50], ax

        mov     word[ds:_r2+21], ax
        mov     word[ds:_r2+45], ax

        mov     word[ds:_rs+21], ax
        mov     word[ds:_rs+46], ax
; draw string
        cmp     word [es:si+6], 0x12
        je      .show_0x12
        cmp     word [es:si+6], 0x13
        je      .show_0x13

        movzx   eax, word[es:si]
        cmp     ax, -1
        je      .@@_end
        mov     di, _rs+23
        mov     ecx, 10
        mov     bl, 4
        call    int2str
        movzx   eax, word[es:si+2]
        inc     di
        mov     bl, 4
        call    int2str

        movzx   eax, word[es:si+8]
        inc     di
        mov     bl, 2
        call    int2str

        cmp     si, word [cursor_pos]
        jne     .next
;draw   cursor
        mov     word[ds:_rs+21], '>>'
        mov     word[ds:_rs+46], '<<'



.next:
        push    si
        mov     si, _rs
.@@_sh:
; add to the string pseudographics for scrollbar
        pop     bx
        push    bx
        mov     byte [si+53], ' '
        cmp     bx, [scroll_start]
        jb      @f
        cmp     bx, [scroll_end]
        jae     @f
        mov     byte [si+53], 0xDB ; filled bar
@@:
        push    bx
        add     bx, size_of_step
        cmp     bx, [end_cursor]
        jnz     @f
        mov     byte [si+53], 31 ; 'down arrow' symbol
@@:
        sub     bx, [home_cursor]
        cmp     bx, size_of_step*long_v_table
        jnz     @f
        mov     byte [si+53], 31 ; 'down arrow' symbol
@@:
        pop     bx
        cmp     bx, [home_cursor]
        jnz     @f
        mov     byte [si+53], 30 ; 'up arrow' symbol
@@:
        call    printplain
        pop     si
        add     si, size_of_step

        dec     bp
        jnz     .@@_next_bit

.@@_end:
        mov     si, _bt
        call    printplain
        ret
.show_0x13:
        push    si

        cmp     si, word [cursor_pos]
        jne     @f
        mov     word[ds:_r1+21], '>>'
        mov     word[ds:_r1+50], '<<'
@@:
        mov     si, _r1
        jmp     .@@_sh
.show_0x12:
        push    si
        cmp     si, word [cursor_pos]
        jne     @f

        mov     word[ds:_r2+21], '>>'
        mov     word[ds:_r2+45], '<<'
@@:
        mov     si, _r2
        jmp     .@@_sh

;-----------------------------------------------------------------------------
;Clear arrea of current video page (0xb800)
clear_vmodes_table:
        pusha
       ; draw frames
        push    es
        push    0xb800
        pop     es
        mov     di, 1444
        xor     ax, ax
        mov     ah, 1*16+15
        mov     cx, 77
        mov     bp, 12
.loop_start:
        rep stosw
        mov     cx, 77
        add     di, 6
        dec     bp
        jns     .loop_start
        pop     es
        popa
        ret

;-----------------------------------------------------------------------------

set_vmode:
        push    0 ;0;x1000
        pop     es

        mov     si, word [preboot_graph]           ;[preboot_graph]
        mov     cx, word [es:si+6]           ; number of mode
        

        mov     ax, word [es:si+0]           ; resolution X
        mov     bx, word [es:si+2]           ; resolution Y


        mov     word [es:BOOT_X_RES], ax             ; resolution X
        mov     word [es:BOOT_Y_RES], bx             ; resolution Y
        mov     word [es:BOOT_VESA_MODE], cx             ; number of mode

        cmp     cx, 0x12
        je      .mode0x12_0x13
        cmp     cx, 0x13
        je      .mode0x12_0x13


;        cmp     byte [s_vesa.ver], '2'
;        jb      .vesa12

;  VESA 2 and Vesa 3

        mov     ax, 0x4f01
        and     cx, 0xfff
        mov     di, mi;0xa000
        int     0x10
        ; LFB
        mov     eax, [es:mi.PhysBasePtr];di+0x28]
        mov     [es:BOOT_LFB], eax
        ; ---- vbe voodoo
        BytesPerLine equ 0x10
        mov     ax, [es:di+BytesPerLine]
        mov     [es:BOOT_PITCH], ax
        ; BPP
        cmp     [es:mi.BitsPerPixel], 16
        jne     .l0
        cmp     [es:mi.GreenMaskSize], 5
        jne     .l0
        mov     [es:mi.BitsPerPixel], 15
.l0:
        mov     al, byte [es:di+0x19]
        mov     [es:BOOT_BPP], al
        jmp     .exit

.mode0x12_0x13:
        mov     byte [es:BOOT_BPP], 32
        or      dword [es:BOOT_LFB], 0xFFFFFFFF; 0x800000


;  VESA 1.2 PM BANK SWITCH ADDRESS

;.vesa12:
;        mov     ax, 0x4f0A
;        xor     bx, bx
;        int     0x10
;        xor     eax, eax
;        xor     ebx, ebx
;        mov     ax, es
;        shl     eax, 4
;        mov     bx, di
;        add     eax, ebx
;        movzx   ebx, word[es:di]
;        add     eax, ebx
;        push    0x0000
;        pop     es
;        mov     [es:0x9014], eax
  .exit:
        ret

;=============================================================================
;=============================================================================
;=============================================================================