
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

ln_top db 1
ln_num db 6
ln_cnt db ?
db ?

ln_top2 db ?
ln_num2 db ?
ln_cnt2 db ?
db ?

vm_row db 2
vm_col db 2

print_vesa_info:
        push    0
        pop     es

        _setcursor 3,2

        mov     [es:vi.VESASignature],'VBE2'
        mov     ax,$4F00
        mov     di,vi
        int     $10
        or      ah,ah
        jz      @f
        mov     [es:vi.VESASignature],'VESA'
        mov     ax,$4F00
        mov     di,vi
        int     $10
        or      ah,ah
        jnz     .exit
  @@:
        cmp     [es:vi.VESASignature],'VESA'
        jne     .exit
        cmp     [es:vi.VESAVersion],$0100
        jb      .exit
        jmp     .vesaok2

  .exit:
        ;pushad
        push    0
        pop     es
        mov     si,novesa-0x10000
        call    printplain
        ret
        ;pushw   'bb'
        ;jmp     enum_modes.modes_ok

  .vesaok2:
        mov     ecx,0x00200000
        mov     ax,[es:vi.TotalMemory]
        shr     ax,4
        mov     bl,10
        div     bl
        mov     ch,ah
        and     ax,0x00FF
        div     bl
        shl     ecx,8
        mov     cx,ax
        add     ecx,'000'

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

        push    0x1000
        pop     es
        mov     [es:s_vesa.ver-0x10000], ah
        mov     [es:s_vesa.ver+2-0x10000], al
        mov     dword[es:s_vesa.mem-0x10000],ecx
        mov     si,s_vesa-0x10000
        call    printplain

if 0 ; mm
        _setcursor 5,2
        mov     si,_oem-0x10000
        call    printplain
end if ; mm

        push    0
        pop     es
        mov     si,word[es:vi.OemStringPtr]
        mov     di,si
        push    word[es:vi.OemStringPtr+2]
        pop     es
if 0 ; mm
;       mov     al,0x0A
        pop     es
        mov     ax,es
        mov     ds,ax
        call    printplain
        pop     es
end if ; mm
        push    0x1000
        pop     ds
        mov     si,s_ven_intel-0x10000
        call    substr
        mov     al,1
        je      .vendor_ok
        mov     si,s_ven_s3-0x10000
        call    substr
        mov     al,2
        je      .vendor_ok
        mov     al,3
  .vendor_ok:
        push    0 0x1000
        pop     ds es
        mov     [es:0x9035],al
        ret

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

calc_vmodes_table:
        push    0 0x1000
        pop     ds es
        ;movzx   eax,byte [es:preboot_graph-0x10000]
        ;cmp     eax,0
        ;jne     pre_graph
        ;_setcursor 9,2
        ;mov     si,gr_mode-0x10000
        ;call    printplain
  .enum_modes:
        pushad
        push    0x0000
        pop     es
        ;mov     si,s_mode1-0x10000
        ;call    printplain
        mov     si,word[es:vi.VideoModePtr]
        push    word[es:vi.VideoModePtr+2]
        pop     fs
        ;pushw   1

        mov     bx,modes_table;-0x10000
  .next_mode:
        mov     cx,[fs:si] ; mode number
        cmp     cx,-1
        je      .modes_ok.2

        mov     ax,$4F01
        mov     di,mi
        int     $10

        or      ah,ah
        jnz     .modes_ok.2;vesa_info.exit
        test    [es:mi.ModeAttributes],00000001b
        jz      @f
        test    [es:mi.ModeAttributes],00010000b
        jz      @f

        cmp     [es:mi.BitsPerPixel],16
        jne     .l0
        cmp     [es:mi.GreenMaskSize],5
        jne     .l0
        mov     [es:mi.BitsPerPixel],15
  .l0:

        cmp     [es:mi.XRes],640
        jb      @f
        cmp     [es:mi.YRes],480
        jb      @f
        cmp     [es:mi.BitsPerPixel],15
        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-0x10000],'2'
        jb      .lp1
        or      cx,0x4000  ; use LFB
  .lp1: mov     [es:bx+6],cx               ; +6[2] : mode number
        mov     al,[es:mi.BitsPerPixel]
        mov     [es:bx+8],al               ; +8[1] : bits per pixel

        add     bx,10

    @@:
        add     si,2
        jmp     .next_mode

  .modes_ok.2:

        mov     si,modes_table;-0x10000;m_info

    @@: add     si,10
        cmp     si,bx
        jae     @f
        mov     ax,[es:si+0-10]
        cmp     ax,[es:si+0]
        ja      .xch
        jb      @b
        mov     ax,[es:si+2-10]
        cmp     ax,[es:si+2]
        ja      .xch
        jb      @b
        mov     al,[es:si+8-10]
        cmp     al,[es:si+8]
        ja      .xch
        jb      @b
        pushad
  .del: push    dword[es:si+0] dword[es:si+4]  word[es:si+8] dword[es:si+0+10] dword[es:si+4+10]  word[es:si+8+10]
        pop      word[es:si+8] dword[es:si+4] dword[es:si+0]  word[es:si+8+10] dword[es:si+4+10] dword[es:si+0+10]
        add     si,10
        cmp     si,bx
        jb      .del
        popad
        mov     si,modes_table
        sub     bx,10
        jmp     @b
  .xch: push    dword[es:si+0] dword[es:si+4]  word[es:si+8] dword[es:si+0-10] dword[es:si+4-10]  word[es:si+8-10]
        pop      word[es:si+8] dword[es:si+4] dword[es:si+0]  word[es:si+8-10] dword[es:si+4-10] dword[es:si+0-10]
        mov     si,modes_table;-0x10000;m_info
        jmp     @b

    @@:

        push    0
        pop     es
        mov     word[es:bx],-1
        mov     si,modes_table
        mov     di,0x0AC00
        pushw   [es:si+2] [es:si+0]
        mov     bp,sp
        mov     [ds:ln_cnt],0
        mov     word[es:si-10],0
        jmp     .wr.2

    @@:
        cmp     word[es:si-10],-1
        je      @f

        mov     ax,[es:si+0]
        cmp     ax,[ss:bp+0]
        jne     .wr
        mov     ax,[es:si+2]
        cmp     ax,[ss:bp+2]
        jne     .wr

  .ww:  mov     al,[es:si+8]
        mov     bx,4
        cmp     al,4
        je      .l1
        add     bx,4
        cmp     al,8
        je      .l1
        add     bx,4
        cmp     al,15
        je      .l1
        add     bx,4
        cmp     al,16
        je      .l1
        add     bx,4
        cmp     al,24
        je      .l1
        add     bx,4
  .l1:  mov     eax,[es:si+4]      ; mode attributes & number
        mov     [es:di+bx],eax

        add     si,10
        jmp     @b

  .wr:
        pushw   [ss:bp+0] [ss:bp+2]
        popw    [es:di+2] [es:di+0]
        add     di,4+6*4
        inc     [ds:ln_cnt]
        pushw   [es:si+0] [es:si+2]
        popw    [ss:bp+2] [ss:bp+0]
  .wr.2:
        mov     cx,(4+6*4)/2
        xor     ax,ax
        push    di
        cld
        rep     stosw
        pop     di
        jmp     .ww

    @@: add     sp,4
        popad
        ret

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

vm_bpp db 4,8,15,16,24,32

draw_current_vmode:
        push    es ds 0 0x1000
        pop     es ds
        movzx   ax,[es:vm_row]
        mov     dx,4+6*4
        mul     dx
        mov     si,ax
        add     si,0x0AC00
        mov     di,0x0A000
        movzx   eax,word[si+0]
        mov     ecx,10
        call    int2strnz
        mov     byte[ds:di],'x'
        inc     di
        movzx   eax,word[si+2]
        call    int2strnz
        mov     byte[ds:di],'x'
        inc     di
        movzx   bx,[es:vm_col]
        movzx   eax,[es:bx+vm_bpp]
        call    int2strnz
        mov     byte[ds:di],0
        mov     si,0x0A000
        call    printplain
        pop     ds es
        ret

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

draw_vmodes_table:
        _setcursor 9,2
        mov     si,gr_mode-0x10000
        call    printplain
        ;mov    ah,9
        ;mov    dx,_tl
        ;int    $21
        mov     si,_tl-0x10000
        call    printplain
        push    0
        pop     es
        movzx   ax,[ds:ln_top]
        mov     dx,4+6*4
        mul     dx
        mov     si,ax
        add     si,0x0AC00

        mov     eax,dword[ds:ln_top]
        mov     dword[ds:ln_top2],eax ; top+num+cnt

        movzx   cx,[ds:ln_num2]
    @@: push    cx

        movzx   eax,word[es:si+0]
        mov     di,_rs-0x10000+2+14
        mov     ecx,10
        mov     bl,4
        call    int2str
        movzx   eax,word[es:si+2]
        inc     di
        mov     bl,4
        call    int2str

        add     si,4
        add     di,4
        mov     cx,6
  .lp0: mov     al,' '
        cmp     word[es:si],0
        je      .lp1
        mov     al,0xFB ; check
  .lp1: mov     [ds:di],al
        add     si,4
        add     di,6
        loop    .lp0

        push    si
        mov     si,_rs-0x10000
        call    printplain
        pop     si

        pop     cx
        loop    @b

        mov     si,_bt-0x10000
        call    printplain
        ret

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

draw_vmodes_table_cursor: ; 9+5
        mov     al,[vm_row]
        sub     al,[ln_top]
        add     al,13
        mov     dh,al
        mov     al,[vm_col]
        mov     dl,6
        mul     dl
        add     al,28
        mov     dl,al
        call    setcursor
        mov     si,_sel1-0x10000
        mov     [si],ch
        call    printplain
        add     dl,2
        call    setcursor
        mov     si,_sel2-0x10000
        mov     [si],cl
        call    printplain
        dec     dl
        call    setcursor
        ret

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

macro qwe
{
  pushad
  pushfd
  push es ds 0 0x1000
  pop ds es
  mov si,badsect-2-0x10000
  call printplain
  pop ds es
  popfd
  popad
}

set_vmode:
        push    0 0x1000
        pop     ds es
        movzx   ax,[ds:vm_row]
        mov     dx,4+6*4
        mul     dx
        add     ax,0x0AC00
        mov     si,ax
        mov     cx,[es:si+0]            ; resolution X
        mov     dx,[es:si+2]            ; resolution Y
        movzx   bx,[ds:vm_col]
        shl     bx,2
        mov     bx,[es:si+4+bx+2]         ; mode number

;        mov     bx,0x4118
;        mov     cx,1024
;        mov     dx,768
;        mov     byte[es:0x9000],24

        cmp     bx,0x12
        je      .gml00
        cmp     bx,0x13
        je      .sgml1

        movzx   bp,[ds:vm_col]
        mov     al,[ds:bp+vm_bpp]
        mov     [es:0x9000],al
        jmp     .gml10

       .sgml1:
        mov     [es:0x9000],byte 32
        jmp     .gml10

       .gml00:
        mov     [es:0x9000],byte 4

    .gml10:
        mov     [es:0x9008],bx
        mov     [es:0x900A],cx
        mov     [es:0x900C],dx
        mov     al,[s_vesa.ver-0x10000]
        mov     [es:0x9034],al
;       push    0x1000
;       pop     es
        mov     [s_bpp.bpp-0x10000],'8 '
        cmp     bx,0x13
        je      .bppl;nov
        mov     [s_bpp.bpp-0x10000],'4 '
        cmp     bx,0x12
        je      .bppl;nov

; bx - mode : cx - x size : dx - y size

; FIND VESA 2.0 LFB & BPP

        mov     ax,0x4f01
        mov     cx,bx
        and     cx,0xfff
        push    0x0000
        pop     es
        mov     di,mi;0xa000
        int     0x10
        ; LFB
        mov     eax,[es:mi.PhysBasePtr];di+0x28]
        mov     [es:0x9018],eax
        ; BPP
;        cmp     [es:mi.BitsPerPixel],16
;        jne     .l0
;        cmp     [es:mi.GreenMaskSize],5
;        jne     .l0
;        mov     [es:mi.BitsPerPixel],15
;  .l0:  mov     al,[es:mi.BitsPerPixel];di+0x19]
;        mov     [es:0x9000],al
        ; ---- vbe voodoo
        ;BytesPerScanLine equ 0x10
        push ax
        mov ax, [es:mi.BytesPerScanLine];di+BytesPerScanLine]
        mov [es:0x9001],ax
        pop ax
        ; -----
    .nov:
        mov     al,[es:0x9000]

        cmp     al,15
        jnz     .nbpp15
        mov     [s_bpp.bpp-0x10000],'15'
        jmp     .bppl
    .nbpp15:
        cmp     al,16
        jnz     .nbpp16
        mov     [s_bpp.bpp-0x10000],'16'
        jmp     .bppl
    .nbpp16:
        cmp     al,24
        jnz     .nbpp24
        mov     [s_bpp.bpp-0x10000],'24'
        jmp     .bppl
    .nbpp24:
        cmp     al,32
        jnz     .nbpp32
        mov     [s_bpp.bpp-0x10000],'32'
        jmp     .bppl
    .nbpp32:
        mov     [s_bpp.bpp-0x10000],'??'
        mov     si,s_bpp-0x10000
        call    printplain
        jmp     $
    .bppl:
        mov     si,s_bpp-0x10000
        call    printplain


; FIND VESA 1.2 PM BANK SWITCH ADDRESS

        cmp     [s_vesa.ver-0x10000],'2'
        jb      @f

        mov     ax,0x4f0A
        mov     bx,0x0
        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
        jmp     .lp1
    @@:

        mov     dword[es:0x9018],0x000A0000
  .lp1:

        ret

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

; DISPLAY VESA INFORMATION
vesa_info:
macro sdfawgsgwaew {
        push    0
        pop     es

        mov     [es:vi.VESASignature],'VBE2'
        mov     ax,$4F00
        mov     di,vi
        int     $10
        or      ah,ah
        jz      @f
        mov     [es:vi.VESASignature],'VESA'
        mov     ax,$4F00
        mov     di,vi
        int     $10
        or      ah,ah
        jnz     .exit
  @@:
        cmp     [es:vi.VESASignature],'VESA'
        jne     .exit
        cmp     [es:vi.VESAVersion],$0100
        jb      .exit
        jmp     vesaok2

  .exit:
        pushad
        push    0
        pop     es
        mov     si,s_mode1-0x10000
        call    printplain
;       mov     si,word[es:vi.VideoModePtr]
;       push    word[es:vi.VideoModePtr+2]
;       pop     fs
        pushw   'bb'
        jmp     enum_modes.modes_ok
;       push    0x1000
;       pop     es
;       mov     si,novesa-0x10000
;       call    print
;       mov     ax,16
;       jmp     $;novesafound

  vesaok2:
        mov     ecx,0x00200000
        mov     ax,[es:vi.TotalMemory]
        shr     ax,4
        mov     bl,10
        div     bl
        mov     ch,ah
        and     ax,0x00FF
        div     bl
        shl     ecx,8
        mov     cx,ax
        add     ecx,'000'

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

        push    0x1000
        pop     es
        mov     [es:s_vesa.ver-0x10000], ah
        mov     [es:s_vesa.ver+2-0x10000], al
        mov     dword[es:s_vesa.mem-0x10000],ecx
        mov     si,s_vesa-0x10000
        call    print

;// mike.dld, 2005-08-20 [
        mov     si,_oem-0x10000
        call    print

        push    0
        pop     es
        mov     si,word[es:vi.OemStringPtr]
        mov     di,si
        push    word[es:vi.OemStringPtr+2]
        pop     es
        mov     al,0x0A
        push    es
        call    draw_text
        pop     es

        push    0x1000
        pop     ds
        mov     si,s_ven_intel-0x10000
        call    substr
        mov     al,1
        je      vendor_ok
        mov     si,s_ven_s3-0x10000
        call    substr
        mov     al,2
        je      vendor_ok
        mov     al,3
  vendor_ok:
        push    0 0x1000
        pop     ds es
        mov     [es:0x9035],al
;// mike.dld, 2005-08-20 ]

      novesafound:
;!!     call    setbase1000

; ASK GRAPHICS MODE

        movzx   eax,byte [es:preboot_graph-0x10000]
        cmp     eax,0
        jne     pre_graph
        mov     si,gr_mode-0x10000
        call    printplain
  enum_modes:
        pushad
        push    0x0000
        pop     es
        mov     si,s_mode1-0x10000
        call    printplain
        mov     si,word[es:vi.VideoModePtr]
        push    word[es:vi.VideoModePtr+2]
        pop     fs
        pushw   1

        mov     bx,modes_table;-0x10000
  .next_mode:
        mov     cx,[fs:si] ; mode number
        cmp     cx,-1
        je      .modes_ok.2

        mov     ax,$4F01
        mov     di,mi
        int     $10

        or      ah,ah
        jnz     .modes_ok.2;vesa_info.exit
        test    [es:mi.ModeAttributes],00000001b
        jz      @f
        test    [es:mi.ModeAttributes],00010000b
        jz      @f

        cmp     [es:mi.BitsPerPixel],16
        jne     .l0
        cmp     [es:mi.GreenMaskSize],5
        jne     .l0
        mov     [es:mi.BitsPerPixel],15
  .l0:

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

        mov     ax,[es:mi.XRes]
        mov     [es:bx+0],ax
        mov     ax,[es:mi.YRes]
        mov     [es:bx+2],ax
        mov     ax,[es:mi.ModeAttributes]
        mov     [es:bx+4],ax
        cmp     [s_vesa.ver-0x10000],'2'
        jb      .lp1
        or      cx,0x4000  ; use LFB
  .lp1: mov     [es:bx+6],cx
        mov     al,[es:mi.BitsPerPixel]
        mov     [es:bx+8],al

        add     bx,10

    @@:
        add     si,2
        jmp     .next_mode

  .modes_ok.2:

        mov     si,modes_table;-0x10000;m_info

    @@: add     si,10
        cmp     si,bx
        jae     @f
        mov     ax,[es:si+0-10]
        cmp     ax,[es:si+0]
        ja      .xch
        jb      @b
        mov     ax,[es:si+2-10]
        cmp     ax,[es:si+2]
        ja      .xch
        jb      @b
        mov     al,[es:si+8-10]
        cmp     al,[es:si+8]
        ja      .xch
        jb      @b
        pushad
  .del: push    dword[es:si+0] dword[es:si+4]  word[es:si+8] dword[es:si+0+10] dword[es:si+4+10]  word[es:si+8+10]
        pop      word[es:si+8] dword[es:si+4] dword[es:si+0]  word[es:si+8+10] dword[es:si+4+10] dword[es:si+0+10]
        add     si,10
        cmp     si,bx
        jb      .del
        popad
        mov     si,modes_table
        sub     bx,10
        jmp     @b
  .xch: push    dword[es:si+0] dword[es:si+4]  word[es:si+8] dword[es:si+0-10] dword[es:si+4-10]  word[es:si+8-10]
        pop      word[es:si+8] dword[es:si+4] dword[es:si+0]  word[es:si+8-10] dword[es:si+4-10] dword[es:si+0-10]
        mov     si,modes_table;-0x10000;m_info
        jmp     @b

    @@: ;mov    ah,9
        ;mov    dx,_tl
        ;int    $21
        mov     si,_tl-0x10000
        push    bx
        call    printplain
        pop     bx
        push    0
        pop     es
        mov     word[es:bx],-1
        mov     si,modes_table;-0x10000;m_info
        pushw   [es:si+0] [es:si+2] 'c'
        mov     bp,sp

    @@:
        cmp     word[es:si-10],-1
        je      @f
;       cmp     si,bx
;       jae     @f
        mov     ax,[es:si+0]
        cmp     ax,[ss:bp+4]
        jne     .wr
        mov     ax,[es:si+2]
        cmp     ax,[ss:bp+2]
        jne     .wr

  .ww:  push    bx
        movzx   eax,word[es:si+0]
        mov     di,_rs-0x10000+2
        mov     ecx,10
        mov     bl,4
        call    int2str
        movzx   eax,word[es:si+2]
        inc     di
        mov     bl,4
        call    int2str

        mov     al,[es:si+8]
        mov     di,_rs-0x10000+16
        cmp     al,4
        je      .l1
        add     di,5
        cmp     al,8
        je      .l1
        add     di,5
        cmp     al,15
        je      .l1
        add     di,5
        cmp     al,16
        je      .l1
        add     di,5
        cmp     al,24
        je      .l1
        add     di,5
  .l1:  mov     al,[ss:bp]
        cmp     byte[ds:di],'-'
        jne     .lp0
        mov     [ds:di],al
        inc     byte[ss:bp]
        jmp     .lp2
  .lp0:
  .lp2:
        pop     bx
        add     si,10
        jmp     @b;.sk

  .wr:  ;mov    ah,9
        ;mov    dx,_rs
        ;int    $21
        push    bx si
        mov     si,_rs-0x10000
        call    printplain
        pop     si bx

        mov     byte[ds:_rs-0x10000+16+5*0],'-'
        mov     byte[ds:_rs-0x10000+16+5*1],'-'
        mov     byte[ds:_rs-0x10000+16+5*2],'-'
        mov     byte[ds:_rs-0x10000+16+5*3],'-'
        mov     byte[ds:_rs-0x10000+16+5*4],'-'
        mov     byte[ds:_rs-0x10000+16+5*5],'-'

        pushw   [es:si+0] [es:si+2]
        popw    [ss:bp+2] [ss:bp+4]

  .sk:
        jmp     .ww;@b

    @@: ;add    sp,6

        pop     bx
        add     sp,6
        sub     bl,2
        shl     bx,8
        push    bx
;       mov     ah,9
;       mov     dx,_bt
;       int     $21
        mov     si,_bt-0x10000
        call    printplain

  .modes_ok:
        pop     bx
        mov     bp,sp
        mov     [ss:bp+4*4],bx
        popad

       gml0:
        mov     bl,'a'
        call    getkey ; !! getchar
       pre_graph:
        or      al,al
        jz      gml00
        cmp     al,1
        je      sgml1
        ;shl    ax,4
        sub     ax,2
        mov     si,10
        mul     si
        add     ax,modes_table;-0x10000
        mov     si,ax
        mov     bx,[es:si+6]
        mov     cx,[es:si+0]
        mov     dx,[es:si+2]
        jmp     gml10
       sgml1:
;        cmp     al,9
;        jnz     gml00
        mov     bx,0x13
        mov     cx,640
        mov     dx,480
        push    0x0
        pop     es
        mov     [es:0x9000],byte 32
;        push    0x1000
;        pop     es
        jmp     gml10
       gml00:
;        cmp     al,0xa
;        jnz     gml02
        mov     bx,0x12
        mov     cx,640
        mov     dx,480
        push    0x0
        pop     es
        mov     [es:0x9000],byte 4;32

    gml10:
        push    0x0000
        pop     es
        mov     [es:0x9008],bx
        mov     [es:0x900A],cx
        mov     [es:0x900C],dx
        mov     al,[s_vesa.ver-0x10000]
        mov     [es:0x9034],al
        push    0x1000
        pop     es
        mov     [s_bpp.bpp-0x10000],'8 '
        cmp     bx,0x13
        je      .bppl;nov
        mov     [s_bpp.bpp-0x10000],'4 '
        cmp     bx,0x12
        je      .bppl;nov

; bx - mode : cx - x size : dx - y size

; FIND VESA 2.0 LFB & BPP

        mov     ax,0x4f01
        mov     cx,bx
        and     cx,0xfff
        push    0x0000
        pop     es
        mov     di,mi;0xa000
        int     0x10
        ; LFB
        mov     eax,[es:mi.PhysBasePtr];di+0x28]
        mov     [es:0x9018],eax
        ; BPP
        cmp     [es:mi.BitsPerPixel],16
        jne     .l0
        cmp     [es:mi.GreenMaskSize],5
        jne     .l0
        mov     [es:mi.BitsPerPixel],15
  .l0:  mov     al,[es:mi.BitsPerPixel];di+0x19]
        mov     [es:0x9000],al
        ; ---- vbe voodoo
        ;BytesPerScanLine equ 0x10
        push ax
        mov ax, [es:mi.BytesPerScanLine];di+BytesPerScanLine]
        mov [es:0x9001],ax
        pop ax
        ; -----
    .nov:
        cmp     al,15
        jnz     .nbpp15
        mov     [s_bpp.bpp-0x10000],'15'
        jmp     .bppl
    .nbpp15:
        cmp     al,16
        jnz     .nbpp16
        mov     [s_bpp.bpp-0x10000],'16'
        jmp     .bppl
    .nbpp16:
        cmp     al,24
        jnz     .nbpp24
        mov     [s_bpp.bpp-0x10000],'24'
        jmp     .bppl
    .nbpp24:
        cmp     al,32
        jnz     .nbpp32
        mov     [s_bpp.bpp-0x10000],'32'
        jmp     .bppl
    .nbpp32:
        mov     [s_bpp.bpp-0x10000],'??'
        call    print
        jmp     $
    .bppl:
        mov     si,s_bpp-0x10000
        call    printplain


; FIND VESA 1.2 PM BANK SWITCH ADDRESS

        cmp     [s_vesa.ver-0x10000],'2'
        jb      @f

        mov     ax,0x4f0A
        mov     bx,0x0
        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
        jmp     .lp1
    @@:

        mov     dword[es:0x9018],0x000A0000
  .lp1:
        push    0x1000
        pop     es
}
