org 100h
use16
        mov     ax,cs           ; Don't have to do this for com files
        mov     es,ax           ; but just in case I'm mistaken
        mov     ds,ax
        mov     ax,0x4f00       ; Get VESA VBE stats
        mov     di,vga_buf
        int     10h
        cld
        call    print_cs        ; Print Version Number
        db 'Vesa VBE Version ',0
        mov     ah,2
        mov     dl,[vga_buf+5]
        or      dl,30h
        int     21h
        call    print_cs
        db '.',0
        mov     ah,2
        mov     dl,[vga_buf+4]
        or      dl,30h
        int     21h
        call    print_cs        ; Print Video Card Name
        db 0ah,0dh,0
        mov     si,[vga_buf+6]
        mov     ds,[vga_buf+8]
        call    print_si
        cmp     byte [cs:vga_buf+5],2        ; VBE 2 info
        jb      .done_vbe2
        call    print_cs        ; Print Software Revision
        db 0ah,0dh,'Software Revision: ',0
        mov     ah,2
        mov     dl,[cs:vga_buf+21]
        or      dl,30h
        int     21h
        call    print_cs
        db '.',0
        mov     ah,2
        mov     dl,[cs:vga_buf+20]
        or      dl,30h
        int     21h
        call    print_cs        ; Print Vendor Name
        db 0ah,0dh,'Vendor Name: ',0
        mov     si,[cs:vga_buf+22]
        mov     ds,[cs:vga_buf+24]
        call    print_si
        call    print_cs        ; Print Product Name
        db 0ah,0dh,'Product Name: ',0
        mov     si,[cs:vga_buf+26]
        mov     ds,[cs:vga_buf+28]
        call    print_si
        call    print_cs        ; Print Revision Name
        db 0ah,0dh,'Product Revision: ',0
        mov     si,[cs:vga_buf+30]
        mov     ds,[cs:vga_buf+32]
        call    print_si
  .done_vbe2:
        call    print_cs        ; Print Memory
        db 0ah,0dh,'Memory: ',0
        mov     ax,[cs:vga_buf+18]
        shl     ax,6            ; Multiply by 64 to find out K
        call    print_dec
        call    print_cs        ; Print Capabilities
        db 'K',0ah,0dh,0ah,0dh,0
        bt      word [cs:vga_buf+10],0
        jc      .dac8
        call    print_cs
        db '6 bit DAC only',0ah,0dh,0
        jmp     .dac6
  .dac8:
        call    print_cs
        db 'DAC switchable to 8bits per primary color',0ah,0dh,0
  .dac6:
        bt      word [cs:vga_buf+10],1
        jc      .non_vga
        call    print_cs
        db 'VGA compatible controller',0ah,0dh,0
        jmp     .vga
  .non_vga:
        call    print_cs
        db 'Controller is not VGA compatible',0ah,0dh,0
  .vga:
        bt      word [cs:vga_buf+10],2
        jc      .abnormal_ramdac
        call    print_cs
        db 'Normal RAMDAC operation',0ah,0dh,0
        jmp     .normal_ramdac
  .abnormal_ramdac:
        call    print_cs
        db 'Use blank bit for RAMDAC operations',0ah,0dh,0
  .normal_ramdac:
        bt      word [cs:vga_buf+10],3
        jc      .stereoscopic
        call    print_cs
        db 'Hardware stereoscopic signaling not supported',0ah,0dh,0
        jmp     .no_stereo
  .stereoscopic:
        bt      word [cs:vga_buf+10],4
        jc      .evc
        call    print_cs
        db 'Stero signaling supported via external VESA stereo connector',0ah,0dh,0
        jmp     .no_stereo
  .evc:
        call    print_cs
        db 'Stero signaling supported via VESA EVC connector',0ah,0dh,0
  .no_stereo:
        call    print_cs        ; Print Video Modes
        db 0ah,0dh,'Vesa Supported Video Modes',0ah,0dh,'==========================',0ah,0dh,0
        mov     si,[cs:vga_buf+14]
        mov     ds,[cs:vga_buf+16]
loop_vid_mode:
        lodsw
        cmp     ax,-1
        je      done
        push    si
        push    ax
        call    print_hex       ; Print Video Mode
        call    print_cs
        db ': ',0
        mov     ax,0x4f01       ; Get information on current mode
        pop     cx
        mov     di,mode_info
        int     10h
        mov     ax,[cs:mode_info+18]    ; X resolution
        call    print_dec_nc
        call    print_cs
        db 'x',0
        mov     ax,[cs:mode_info+20]    ; Y resolution
        call    print_dec_nc
        call    print_cs
        db ' ',0
        xor     ah,ah
        mov     al,[cs:mode_info+25]    ; Number bits per pixel
        call    print_dec_nc
        call    print_cs
        db 'bpp',0
        bt      word [cs:mode_info],5
        jc      .non_vga
        call    print_cs                ; VGA compatible mode
        db ' VGA',0
        jmp     .vga
  .non_vga:                             ; non-VGA compatible mode
        call    print_cs
        db ' Non-VGA',0
  .vga:
        bt      word [cs:mode_info],2
        jnc     .notty
        call    print_cs                ; tty supported
        db ' TTY',0
  .notty:
        bt      word [cs:mode_info],6
        jc      .nowindow
        call    print_cs                ; windowed memory mode available
        db ' Windowed',0
  .nowindow:
        bt      word [cs:mode_info],3
        jc      .color
        call    print_cs                ; monochrome mode
        db ' Monochrome',0
        jmp     .mono
  .color:                               ; color mode
        call    print_cs
        db ' Color',0
  .mono:
        bt      word [cs:mode_info],4
        jc      .graphics
        call    print_cs                ; text mode
        db ' Text',0
        jmp     .text
  .graphics:                            ; graphics mode
        call    print_cs
        db ' Graphics',0
  .text:
        bt      word [cs:mode_info],0
        jc      .sup
        call    print_cs                ; not supported in current config
        db ' Not currently supported',0
        jmp     .nosup
  .sup:                                 ; currently supported
        call    print_cs
        db ' Currently supported',0
  .nosup:
        test    byte [cs:mode_info+1],11111b    ; check for misc features
        jz      .no_additional
        call    print_cs
        db 0ah,0dh,'    ',0
        bt      word [cs:mode_info],8
        jnc     .no_double
        call    print_cs                ; double scan
        db ' Double Scan',0
  .no_double:
        bt      word [cs:mode_info],9
        jnc     .no_interlaced
        call    print_cs                ; interlaced
        db ' Interlaced',0
  .no_interlaced:
        bt      word [cs:mode_info],10
        jnc     .no_triple
        call    print_cs                ; Triple Buffering
        db ' Triple Buf',0
  .no_triple:
        bt      word [cs:mode_info],11
        jnc     .no_stereo
        call    print_cs                ; Stereoscopic
        db ' Stereoscopic',0
  .no_stereo:
        bt      word [cs:mode_info],11
        jnc     .no_dual
        call    print_cs                ; Dual display
        db ' Dual Display',0
  .no_dual:
  .no_additional:
        call    print_cs
        db 0ah,0dh,'    ',0   
        bt      word [cs:mode_info],6   ; Windows mode supported?
        jc      no_windows
window_a:
        test    byte [cs:mode_info+2],110b      ; Window A attributes
        jz      window_b
        call    print_cs
        db ' WinA(',0
        mov     ax,[cs:mode_info+8]
        call    print_hex
        call    print_cs
        db ') ',0
        bt      word [cs:mode_info+2],0   ; Windows relocateable
        jnc     .no_relocate
        call    print_cs
        db 'Relocateable ',0
  .no_relocate:
        bt      word [cs:mode_info+2],1   ; Windows readable
        jnc     .no_read
        call    print_cs
        db 'R',0
  .no_read:
        bt      word [cs:mode_info+2],2   ; Windows writeable
        jnc     .no_write
        call    print_cs
        db 'W',0
  .no_write:        
window_b:
        test    byte [cs:mode_info+3],110b      ; Window B attributes
        jz      .no_windows
        call    print_cs
        db ' WinB(',0
        mov     ax,[cs:mode_info+10]
        call    print_hex
        call    print_cs
        db ') ',0
        bt      word [cs:mode_info+3],0   ; Windows relocateable
        jnc     .no_relocate
        call    print_cs
        db 'Relocateable ',0
  .no_relocate:
        bt      word [cs:mode_info+3],1   ; Windows readable
        jnc     .no_read
        call    print_cs
        db 'R',0
  .no_read:
        bt      word [cs:mode_info+3],2   ; Windows writeable
        jnc     .no_write
        call    print_cs
        db 'W',0
  .no_write:
  .no_windows:
        call    print_cs                ; Spit out windows stats
        db 0ah,0dh,'     Window Size: ',0   
        mov     ax,[cs:mode_info+6]
        call    print_dec
        call    print_cs
        db 'K,  Granularity: ',0   
        mov     ax,[cs:mode_info+4]
        call    print_dec
        call    print_cs
        db 'K,  Bytes per line: ',0   
        mov     ax,[cs:mode_info+16]
        call    print_dec
        call    print_cs                
        db 0ah,0dh,'     Planes: ',0
        xor     ah,ah
        mov     al,[cs:mode_info+24]
        call    print_dec
        call    print_cs
        db '  Image Pages: ',0   
        xor     ah,ah
        mov     al,[cs:mode_info+29]
        inc     al
        call    print_dec
no_windows:
        call    print_cs
        db '  Linear Frame Buffer: ',0
        mov     eax,[cs:mode_info+40]
        call    print_hex_big
        call    print_cs
        db 0ah,0dh,0
        pop     si
        jmp     loop_vid_mode
done:
        int     20h

print_cs:
        pop     si
        push    ds
        push    cs
        pop     ds
  .loop:
        lodsb
        or      al,al
        jz      .end
        mov     ah,2
        mov     dl,al
        int     21h
        jmp     .loop
  .end:
        pop     ds
        jmp     si

print_si:
  .loop:
        lodsb
        or      al,al
        jz      .end
        mov     ah,2
        mov     dl,al
        int     21h
        jmp     .loop
  .end:
        ret

print_dec_nc:
        push    word 0
        mov     cx,1000
        jmp     print_dec.loop
print_dec:
        push    word 0
  .zero_loop:
        mov     cx,3
  .loop:
        xor     dx,dx
        mov     bx,10
        div     bx
        or      dl,30h
        push    dx
        or      ax,ax
        jz      .end_numb
        loop    .loop
        push    word ','+0e00h
        jmp     .zero_loop
  .end_numb:
        pop     dx
        or      dx,dx
        jz      .end
        mov     ah,2
        int     21h
        jmp     .end_numb
  .end:
        ret

print_hex:
        push    ax
        xor     eax,eax
        pop     ax
print_hex_big:
        push    word 0
  .loop:
        push    eax
	and	al,0fh
	cmp	al,10
	cmc
	adc	al,30h
	daa
        mov     bl,al
        pop     eax
        push    bx
        shr     eax,4
        or      eax,eax
        jz      print_dec.end_numb
        jmp     .loop

vga_buf:
        db 'VBE2'
        rb 508
mode_info:
        rb 256
