home *** CD-ROM | disk | FTP | other *** search
/ World of Graphics / WOGRAPH.BIN / 437.UNIVESA.ASM < prev    next >
Assembly Source File  |  1993-03-07  |  34KB  |  1,238 lines

  1. ;****************************************************************************
  2. ;*
  3. ;*                          The Universal VESA TSR
  4. ;*
  5. ;*                  Copyright (C) 1993 Kendall Bennett.
  6. ;*                            All rights reserved.
  7. ;*
  8. ;* Filename:    $RCSfile: univesa.asm $
  9. ;* Version:        $Revision: 1.2 $
  10. ;*
  11. ;* Language:    80386 Assembler
  12. ;* Environment:    IBM PC (MS DOS)
  13. ;*
  14. ;* Description:    This source file contains the code for a Universal VESA
  15. ;*                TSR's, to implement the VESA video BIOS extensions for
  16. ;*                supported SuperVGA's.
  17. ;*
  18. ;*                Must be assembled in the large memory model.
  19. ;*
  20. ;* $Id: univesa.asm 1.2 1993/03/07 04:05:36 kjb Exp $
  21. ;*
  22. ;* Revision History:
  23. ;* -----------------
  24. ;*
  25. ;* $Log: univesa.asm $
  26. ;* Revision 1.2  1993/03/07  04:05:36  kjb
  27. ;* Bug fixes.
  28. ;*
  29. ;* Revision 1.1  1993/03/03  10:27:33  kjb
  30. ;* Initial revision
  31. ;*
  32. ;****************************************************************************
  33.  
  34.         IDEAL
  35.         DOSSEG
  36.         JUMPS
  37.         P386                        ; Use 386 instructions
  38.  
  39. INCLUDE "MODEL.MAC"                    ; Memory model macros
  40.  
  41. header  uvesa                       ; Link with uvesa.c
  42.  
  43. ;----------------------------------------------------------------------------
  44. ;         Internal Equates and Macros
  45. ;----------------------------------------------------------------------------
  46.  
  47. INCLUDE    "MGRAPH.EQU"                ; Include Equates for Mgraph Routines
  48.  
  49. CRTC            EQU    3D4h            ; Port of CRTC registers
  50. VGABufferSeg    EQU    0A000h            ; Segment of VGA display memory
  51. NL                EQU <0dh, 0ah>        ; New Line marker
  52. EOS             EQU '$'             ; End of String marker
  53. PSPSize            EQU    100h            ; Size of program PSP
  54. SUCCESS            EQU    004Fh            ; Return value on success
  55. FAILURE            EQU    014Fh            ; Return value on failure
  56. VESA_FUNCTIONS    EQU    04Fh            ; VESA Control function value (AH)
  57. MAX_FUNCTION    EQU    7                ; Highest VESA function number supported
  58. VESA_VERSION    EQU    0102h            ; Version 1.2
  59.  
  60. ; Macro to get the value of an interrupt vector. Returns the result in
  61. ; ES:BX.
  62.  
  63. MACRO    GetVector    intnum
  64.         mov        ah,35h
  65.         mov        al,intnum
  66.         int        21h
  67. ENDM
  68.  
  69. ; Macro to set the value of an interrupt vector.
  70.  
  71. MACRO    SetVector    intnum, handler
  72.         push    ds
  73.         mov        dx,seg handler
  74.         mov        ds,dx
  75.         mov        dx,offset handler
  76.         mov        ah,25h
  77.         mov        al,intnum
  78.         int        21h
  79.         pop        ds
  80. ENDM
  81.  
  82. begcodeseg    uvesa
  83.  
  84.         EXTRN   _testISR:FAR
  85.  
  86. endcodeseg    uvesa
  87.  
  88. begcodeseg    modes
  89.  
  90.         EXTRN    _MGL_availableModes:FAR
  91.  
  92. endcodeseg    modes
  93.  
  94. begcodeseg    uvesa
  95.  
  96. ;----------------------------------------------------------------------------
  97. ;         Resident Data
  98. ;----------------------------------------------------------------------------
  99.  
  100. ; Signature used to determine if the TSR is already installed.
  101.  
  102. Signature:            db    'Universal VESA TSR',0
  103. SigLen                =    $-Signature
  104.  
  105. LABEL        OldInt10    DWORD
  106. OldInt10off            dw    ?                    ; Place to save int 10h vector
  107. OldInt10seg            dw    ?
  108.  
  109. ; Globals used by resident generic SuperVGA routines
  110.  
  111. CntDriver            dw    0                    ; Graphics driver number
  112. CntMode                dw    0                    ; Graphics mode number
  113. CntDAC                dw    0                    ; Video DAC ID
  114. CntChipID            dw    0                    ; Graphics driver chip ID
  115. CntColors            dw    0                    ; Current color mode
  116. CntVESAMode            dw    0                    ; Current VESA mode number
  117. CntMemory            dw    0                    ; Amount of memory on chip
  118. CntStartX            dw    0                    ; Current display start X
  119. CntStartY            dw    0                    ; Current display start Y
  120.  
  121. ; Dispatch table for supported function calls
  122.  
  123. DispatchTable        dw    offset SuperVGAInfo
  124.                     dw    offset SuperVGAModeInfo
  125.                     dw    offset SuperVGASetMode
  126.                     dw    offset SuperVGAGetMode
  127.                     dw    offset SuperVGAVideoState
  128.                     dw    offset SuperVGABankSwitch
  129.                     dw    offset SuperVGAScanlineLength
  130.                     dw    offset SuperVGADisplayStart
  131.  
  132. Status                dw    0                    ; Return status code
  133.  
  134. ; VGA Information block returned to the user program
  135.  
  136. VGAInfo                db    'VESA'                ; Signature value
  137.                     dw    VESA_VERSION        ; VESA Version number
  138.                     dw    offset Signature    ; OEM Name offset
  139.                     dw    seg Signature        ; OEM Name segment
  140.                     db    4 DUP (0)            ; Capabilities bits
  141.                     dw    offset ModeTable    ; Video mode table offset
  142.                     dw    seg ModeTable        ; Video mode table segment
  143. VGAInfoSize            =    $-VGAInfo
  144.  
  145. ; List of all possible supported VESA video modes. If any of the modes
  146. ; are not supported by the installed SuperVGA, they are zeroed from the
  147. ; table.
  148.  
  149. ModeTable            dw    100h                ; grSVGA_640x400x256
  150.                     dw    101h                ; grSVGA_640x480x256
  151.                     dw    102h                ; grSVGA_800x600x16
  152.                     dw    103h                ; grSVGA_800x600x256
  153.                     dw    104h                ; grSVGA_1024x768x16
  154.                     dw    105h                ; grSVGA_1024x768x256
  155.                     dw    106h                ; grSVGA_1280x1024x16
  156.                     dw    107h                ; grSVGA_1280x1024x256
  157.                     dw    10Dh                ; grSVGA_320x200x32k
  158.                     dw    10Fh                ; grSVGA_320x200x16m
  159.                     dw    110h                ; grSVGA_640x480x32k
  160.                     dw    112h                ; grSVGA_640x480x16m
  161.                     dw    113h                ; grSVGA_800x600x32k
  162.                     dw    115h                ; grSVGA_800x600x16m
  163.                     dw    116h                ; grSVGA_1024x768x32k
  164.                     dw    118h                ; grSVGA_1024x768x16m
  165.                     dw    119h                ; grSVGA_1280x1024x32k
  166.                     dw    11Bh                ; grSVGA_1280x1024x16m
  167.                     dw    0FFFFh                ; Terminate the list
  168.  
  169. ; Define the memory model type numbers
  170.  
  171. memPL16                EQU    3                    ; Planar
  172. memPK256            EQU 4                    ; Packed pixel
  173. memPKD                EQU    6                    ; Direct
  174.  
  175. ; Video mode information for the currently active video mode. BIOS
  176. ; output is generally supported by most video modes, but we can never
  177. ; be sure so we turn this off for all modes.
  178.  
  179. ModeInfo            dw    011011b                ; Mode Attributes
  180.                     db    0111b                ; Window A attributes
  181. WinBAttr            db    0011b                ; Window B attributes
  182.                     dw    64                    ; Window granularity (in K)
  183.                     dw    64                    ; Window size (in K)
  184.                     dw    VGABufferSeg        ; Start segment of Window A
  185.                     dw    VGABufferSeg        ; Start segment of Window B
  186.                     dw    offset SuperVGABankSwitch
  187.                     dw    seg SuperVGABankSwitch
  188. BytesPerLine        dw    0                    ; Bytes per logical scanline
  189. XRes                dw    0                    ; X resolution
  190. YRes                dw    0                    ; Y resolution
  191. CWidth                db    8                    ; Character width
  192. CHeight                db    8                    ; Character height
  193. Planes                db    0                    ; Number of planes
  194. BitsPerPixel        db    0                    ; Bits per pixel
  195. Banks                db    0                    ; Number of banks??
  196. MemMode                db    0                    ; Memory mode
  197.                     db    0
  198. Pages                db    0                    ; Number of image pages
  199. ModeInfoSize        =    $-ModeInfo
  200.  
  201. ; Lookup table for filling in the optional mode information in the above
  202. ; structure.
  203.  
  204. mode800x600x16        dw    800,600
  205.                     db    8,8,4,4,1,memPL16
  206. mode1024x768x16        dw    1024,768
  207.                     db    8,8,4,4,1,memPL16
  208. mode1280x1024x16    dw    1280,1024
  209.                     db    8,8,4,4,1,memPL16
  210. PartialInfoSize        =    $-mode1280x1024x16
  211.  
  212. mode640x350x256        dw    640,350
  213.                     db    8,8,1,8,1,memPK256
  214. mode640x400x256        dw    640,400
  215.                     db    8,8,1,8,1,memPK256
  216. mode640x480x256        dw    640,480
  217.                     db    8,8,1,8,1,memPK256
  218. mode800x600x256        dw    800,600
  219.                     db    8,8,1,8,1,memPK256
  220. mode1024x768x256    dw    1024,768
  221.                     db    8,8,1,8,1,memPK256
  222. mode1280x1024x256    dw    1280,1024
  223.                     db    8,8,1,8,1,memPK256
  224.  
  225. mode320x200x32k        dw    320,200
  226.                     db    8,8,1,15,1,memPKD
  227. mode640x350x32k        dw    640,350
  228.                     db    8,8,1,15,1,memPKD
  229. mode640x400x32k        dw    640,400
  230.                     db    8,8,1,15,1,memPKD
  231. mode640x480x32k        dw    640,480
  232.                     db    8,8,1,15,1,memPKD
  233. mode800x600x32k        dw    800,600
  234.                     db    8,8,1,15,1,memPKD
  235. mode1024x768x32k    dw    1024,768
  236.                     db    8,8,1,15,1,memPKD
  237. mode1280x1024x32k    dw    1280,1024
  238.                     db    8,8,1,15,1,memPKD
  239.  
  240. mode320x200x16m        dw    320,200
  241.                     db    8,8,1,24,1,memPKD
  242. mode640x350x16m        dw    640,350
  243.                     db    8,8,1,24,1,memPKD
  244. mode640x400x16m        dw    640,400
  245.                     db    8,8,1,24,1,memPKD
  246. mode640x480x16m        dw    640,480
  247.                     db    8,8,1,24,1,memPKD
  248. mode800x600x16m        dw    800,600
  249.                     db    8,8,1,24,1,memPKD
  250. mode1024x768x16m    dw    1024,768
  251.                     db    8,8,1,24,1,memPKD
  252. mode1280x1024x16m    dw    1280,1024
  253.                     db    8,8,1,24,1,memPKD
  254.  
  255. ;----------------------------------------------------------------------------
  256. ;         Resident Code
  257. ;----------------------------------------------------------------------------
  258.  
  259.         ASSUME  cs:uvesa_TEXT, ds:NOTHING, es:NOTHING
  260.  
  261. INCLUDE "SV_PORTS.ASM"
  262. INCLUDE "SV_BANKS.ASM"
  263. INCLUDE "SV_MODES.ASM"
  264. INCLUDE "SV_PAGE.ASM"
  265. INCLUDE "SV_MAXPG.ASM"
  266.  
  267. ;----------------------------------------------------------------------------
  268. ; Int10ISR    - Video BIOS hook.
  269. ;----------------------------------------------------------------------------
  270. ;
  271. ; This routine is called whenever an application program makes a call to
  272. ; the Video BIOS routines. We check to see if the calls and VESA functions
  273. ; calls, and handle them appropriately, or else we simply pass the call
  274. ; to the old Video BIOS handler.
  275. ;
  276. ;----------------------------------------------------------------------------
  277. PROC    Int10ISR    far
  278.  
  279.         cmp        ah,VESA_FUNCTIONS    ; Is this a VESA function?
  280.         je        @@VesaFunction        ; Yes, so handle it
  281.  
  282. ; Check to see if this is the Set Video Mode function, in which case we
  283. ; need to check if we are trying to set a standard VGA video mode.
  284.  
  285.         or        ah,ah
  286.         jnz        @@ToOldBIOS
  287.         cmp        al,13h
  288.         ja        @@ToOldBIOS
  289.  
  290. ; Attempting to set a standard VGA video mode, so pass this call onto the
  291. ; SuperVGASetMode routine.
  292.  
  293.         mov        bx,ax                ; BX := video mode number
  294.         call    SuperVGASetMode        ; Set the video mode
  295.         iret
  296.  
  297. @@ToOldBIOS:
  298.         jmp        [OldInt10]            ; Jump to old VIDEO BIOS
  299.  
  300. ; This is a VESA function, so dispatch to the appropriate routine depending
  301. ; on the subfunction number.
  302.  
  303. @@VesaFunction:
  304.         cmp        al,MAX_FUNCTION
  305.         ja        @@NotSupported        ; VESA Function is not supported
  306.  
  307.         cmp        al,5                ; Bank Switching call?
  308.         jne        @@NotBankSwitch        ; No, handle normally
  309.  
  310. ; The bank switch routine can be called as a far function, so we can't
  311. ; handle this routine with a simple lookup table.
  312.  
  313.         call    far SuperVGABankSwitch
  314.         iret
  315.  
  316. @@NotBankSwitch:
  317.         xor        ah,ah
  318.         shl        al,1                ; AX := index into table
  319.         xchg    ax,bx
  320.         mov        bx,[DispatchTable + bx]
  321.         xchg    ax,bx
  322.         mov        [Status],FAILURE
  323.         push    ds                    ; Save value of DS
  324.         call    ax                    ; Call the appropriate function
  325.         pop        ds                    ; Restor value of DS
  326.         mov        ax,[Status]            ; Return status code
  327.         iret
  328.  
  329. @@NotSupported:
  330.         xor        al,al                ; Function is not supported
  331.         iret
  332.  
  333. ENDP    Int10ISR
  334.  
  335. ;----------------------------------------------------------------------------
  336. ; SuperVGAInfo    - Get SuperVGA Information
  337. ;----------------------------------------------------------------------------
  338. ;
  339. ; Function to return information about the SuperVGA video card.
  340. ;
  341. ; Entry:        ES:DI    -> 256byte buffer for SuperVGA information
  342. ;
  343. ; Exit:         AX        - VESA status code
  344. ;
  345. ;----------------------------------------------------------------------------
  346. PROC    SuperVGAInfo    near
  347.  
  348.         pusha                        ; Save register values
  349.         push    ds                    ; Save DS
  350.  
  351.         cld
  352.         mov        ax,cs
  353.         mov        ds,ax
  354.         mov        si,offset VGAInfo    ; DS:SI -> VGAInfo Table
  355.         mov        cx,VGAInfoSize
  356.     rep    movsb                        ; Copy the data across
  357.         mov        [Status],SUCCESS    ; Return status code
  358.  
  359.         pop        ds                    ; Restore DS
  360.         popa                        ; Restore register values
  361.         ret
  362.  
  363. ENDP    SuperVGAInfo
  364.  
  365. ;----------------------------------------------------------------------------
  366. ; SuperVGAModeInfo    - Get SuperVGA Video Mode Information
  367. ;----------------------------------------------------------------------------
  368. ;
  369. ; Function to return information about a specific VESA SuperVGA video mode.
  370. ;
  371. ; Entry:        CX        - SuperVGA video mode
  372. ;                ES:DI    -> 256 byte buffer for mode information
  373. ;
  374. ; Exit:            AX        - VESA status code
  375. ;
  376. ;----------------------------------------------------------------------------
  377. PROC    SuperVGAModeInfo    near
  378.  
  379.         pusha                        ; Save register values
  380.  
  381.         call    VESAToMGLMode        ; AX := MGL mode number
  382.         cmp        ax,-1
  383.         je        @@Invalid            ; Mode is invalid to us!
  384.  
  385.         push    [BytesPerLine]        ; Save current bytes per line value
  386.         push    ax                    ; Save MGL mode number
  387.  
  388.         xor        ebx,ebx
  389.         mov        bx,[CntMemory]
  390.         shl     ebx,10                ; EBX := memory in bytes
  391.         call    numPages            ; Compute number of video pages
  392.         mov        [Pages],al            ; Store number of video pages
  393.         mov        [BytesPerLine],cx    ; Stote bytes per line value
  394.  
  395. ; Copy the information specific to the video mode
  396.  
  397.         pop        ax                    ; AX := MGL mode number
  398.         sub        ax,grSVGA_800x600x16
  399.         mov        cx,PartialInfoSize
  400.         mul        cl
  401.         mov        si,offset mode800x600x16
  402.         add        si,ax
  403.         push    es                    ; Save ES:DI
  404.         push    di
  405.         mov        ax,cs
  406.         mov        ds,ax                ; DS:SI -> correct mode info
  407.         mov        es,ax
  408.         mov        di,offset XRes        ; ES:DI -> mode specific info
  409.         cld
  410.     rep    movsb                        ; Copy the data across
  411.  
  412.         pop        di                    ; Restore ES:DI
  413.         pop        es
  414.  
  415. ; Copy the mode information across
  416.  
  417.         mov        si,offset ModeInfo    ; DS:SI -> VGAInfo Table
  418.         mov        cx,ModeInfoSize
  419.     rep    movsb                        ; Copy the data across
  420.  
  421.         pop        [BytesPerLine]        ; Restore bytes per line value
  422.         mov        [Status],SUCCESS
  423.         popa
  424.         ret
  425.  
  426. ; The video mode is invalid, but the underlying video BIOS may be VESA
  427. ; compatible, and the mode number may mean something to it, so we pass it
  428. ; on to it.
  429.  
  430. @@Invalid:
  431.         popa
  432.         mov        ax,4F01h
  433.         pushf
  434.         call    [OldInt10]            ; Call the old BIOS
  435.         mov        [Status],ax            ; Save the status of the call
  436.         ret
  437.  
  438. ENDP    SuperVGAModeInfo
  439.  
  440. ;----------------------------------------------------------------------------
  441. ; SuperVGASetMode    - Set SuperVGA Video Mode
  442. ;----------------------------------------------------------------------------
  443. ;
  444. ; Function to set a specific VESA SuperVGA video mode. Only graphics modes
  445. ; are supported by this TSR.
  446. ;
  447. ; Entry:        BX    - VESA video mode number (bit 15 means don't clear mem).
  448. ;
  449. ; Exit:            AX    - VESA status code.
  450. ;
  451. ;----------------------------------------------------------------------------
  452. PROC    SuperVGASetMode        near
  453.  
  454.         pusha                        ; Save register values
  455.         push    es
  456.  
  457.         mov        cx,bx
  458.         and        cl,07Fh
  459.         cmp        cx,13h
  460.         ja        @@VesaMode
  461.  
  462. ; Attempting to set a standard VGA video mode, so convert the mode number
  463. ; into an MGL video mode number and skip the stuff below to set a
  464. ; VESA video mode.
  465.  
  466.         push    cx
  467.         push    bx
  468.  
  469.         push    cs
  470.         pop        es
  471.         mov        di,offset VGAModes    ; ES:DI -> list of VGA video modes
  472.         mov        ax,cx
  473.         mov        cx,12
  474.         repne    scasw                ; Search for entry
  475.         inc        cx
  476.         shr        cx,1
  477.         sub        cx,6
  478.         neg        cx                    ; CX := MGL mode number
  479.         mov        [CntMode],cx
  480.  
  481.         pop        ax
  482.         pushf
  483.         call    [OldInt10]            ; Set the video mode
  484.         pop        cx
  485.         jmp        @@StandardVGAMode
  486.  
  487. @@VesaMode:
  488.         push    bx                    ; Save VESA mode number for later
  489.         mov        cx,bx
  490.         and        ch,07Fh                ; Clear memory clear bit
  491.         push    cx
  492.         call    VESAToMGLMode        ; AX := internal MGL video mode
  493.         cmp        ax,-1
  494.         jne        @@1
  495.  
  496.         pop        bx
  497.         pop        bx
  498.         jmp        @@InvalidMode        ; Video mode is invalid to us!
  499.  
  500. @@1:    mov        [CntMode],ax        ; Save internal MGL video mode
  501.         mov        bx,ax                ; BX := current video mode
  502.         mov        ax,[CntDriver]        ; AX := current video driver
  503.         call    loadSVGAMode        ; AX,BX := correct value for Int 10h
  504.         pop        cx                    ; CX := VESA mode number
  505.         and        ch,80h                ; isolate clear memory bit
  506.         jz        @@SetMode            ; Bit is not set, so simply set the mode
  507.  
  508. ; Request was made to _not_ clear the video memory, so attempt to set the
  509. ; correct bit for the OEM video modes.
  510.  
  511.         or        bx,bx                ; BX := 0, so AX := video mode number
  512.         jz        @@SetAX
  513.         or        bh,bh
  514.         jz        @@SetBL
  515.  
  516.         or        bh,80h                ; Set the memory clear bit
  517.         jmp        @@SetMode
  518.  
  519. @@SetAX:
  520.         or        al,80h                ; Set the memory clear bit
  521.         jmp        @@SetMode
  522.  
  523. @@SetBL:
  524.         or        bl,80h                ; Set the memory clear bit
  525.  
  526. @@SetMode:
  527.         pushf
  528.         call    [OldInt10]            ; Set the video mode
  529.  
  530.         pop        cx                    ; CX := VESA mode number
  531.  
  532.         mov        ax,40h
  533.         mov        es,ax
  534.         cmp        [BYTE es:49h],3        ; Mode is still text mode, did not set
  535.         jbe        @@ModeSetFailed
  536.  
  537. @@StandardVGAMode:
  538.         mov        [CntVESAMode],cx    ; Save VESA mode now set
  539.         call    SetupBanks
  540.         call    [InitSVGA]            ; Initialise bank switching on SuperVGA's
  541.         call    SetupPaging
  542.  
  543.         mov        ax,[CntMode]        ; AX := current video mode number
  544.         mov        ebx,4096 shl 10        ; Compute with maximum video memory
  545.         call    numPages            ; Compute bytes per line value
  546.         mov        [BytesPerLine],cx    ; Save BytesPerLine value
  547.  
  548. ; Determine the color resolution of the video mode and save for later
  549.  
  550.         mov        ax,[CntMode]        ; AX := current MGL video mode
  551.         cmp        ax,grVGA_320x200x256
  552.         je        @@Colors256
  553.         cmp        ax,grSVGA_1280x1024x16
  554.         jbe        @@Colors16
  555.         cmp        ax,grSVGA_1280x1024x256
  556.         jbe        @@Colors256
  557.         cmp        ax,grSVGA_1280x1024x32k
  558.         jbe        @@Colors32k
  559.  
  560.         mov        [CntColors],gr16mColor
  561.         jmp        @@Done
  562.  
  563. @@Colors16:
  564.         mov        [CntColors],gr16Color
  565.         jmp        @@Done
  566. @@Colors256:
  567.         mov        [CntColors],gr256Color
  568.         jmp        @@Done
  569. @@Colors32k:
  570.         mov        [CntColors],gr32kColor
  571.  
  572. @@Done:
  573.         mov        [CntStartX],0
  574.         mov        [CntStartY],0
  575.         mov        [Status],SUCCESS
  576.  
  577. @@ModeSetFailed:
  578.         pop        es
  579.         popa
  580.         ret
  581.  
  582. ; The mode number was invalid to us, but may make sense to an underlying
  583. ; VESA compatible BIOS.
  584.  
  585. @@InvalidMode:
  586.         pop        es
  587.         popa
  588.         mov        ax,4F02h
  589.         pushf
  590.         call    [OldInt10]            ; Call the old BIOS
  591.         mov        [Status],ax            ; Save the status value
  592.         mov        [CntVESAMode],-1    ; Flag that mode is unknown to us!
  593.         ret
  594.  
  595. ENDP    SuperVGASetMode
  596.  
  597. ;----------------------------------------------------------------------------
  598. ; SuperVGAGetMode    - Get Current SuperVGA Video Mode
  599. ;----------------------------------------------------------------------------
  600. ;
  601. ; Function to return the mode number of the current set video mode. If the
  602. ; mode is a normal VGA video mode, the normal mode number is returned,
  603. ; otherwise the VESA video mode number for the mode is returned.
  604. ;
  605. ; Exit:            AX    - VESA status code
  606. ;                BX    - Current video mode
  607. ;
  608. ;----------------------------------------------------------------------------
  609. PROC    SuperVGAGetMode        near
  610.  
  611.         push    es
  612.         mov        ax,40h
  613.         mov        es,ax
  614.         xor        bx,bx
  615.         mov        bl,[BYTE es:49h]
  616.         cmp        bl,13h
  617.         mov        [Status],SUCCESS
  618.         jbe        @@VGAMode
  619.  
  620.         mov        bx,[CntVESAMode]    ; VESA Video mode is active, so return it
  621.         cmp        bx,-1
  622.         jne        @@VGAMode
  623.  
  624. ; The mode was not know to us, so it may be an underlying VESA video mode.
  625.  
  626.         mov        ax,4F03h
  627.         pushf
  628.         call    [OldInt10]
  629.         mov        [Status],ax
  630.  
  631. @@VGAMode:
  632.         pop        es
  633.         ret
  634.  
  635. ENDP    SuperVGAGetMode
  636.  
  637. ;----------------------------------------------------------------------------
  638. ; SuperVGAVideoState    - Save/Restore SuperVGA video state
  639. ;----------------------------------------------------------------------------
  640. ;
  641. ; Function to save save/restore the SuperVGA video state. This function
  642. ; would be very tricky to implement for all supported SuperVGA's if we
  643. ; want to save the entire state. In order to do as best as job as possible,
  644. ; we save the state of the hardware as much as possible using the normal
  645. ; Video BIOS routines, along with the current video BIOS mode number. To
  646. ; restore the state we first reset the current video mode, then call the
  647. ; BIOS to reset the hardware state, which should work correctly for most
  648. ; SuperVGA situations.
  649. ;
  650. ; Entry:        DL        - Subfunction number
  651. ;                          00h    - Get state buffer size
  652. ;                          01h    - Save video state
  653. ;                          02h    - Restore video state
  654. ;                ES:BX    -> Video buffer to save state in
  655. ;                CX        - Flags for what to save
  656. ;                          bit 0    - Video hardware state
  657. ;                          bit 1 - Video BIOS state
  658. ;                          bit 2 - Video DAC state
  659. ;                          bit 3 - SuperVGA state
  660. ;
  661. ; Exit:            AH        - VESA Status code
  662. ;                BX        - Number of 64 byte blocks needed to save state
  663. ;
  664. ;----------------------------------------------------------------------------
  665. PROC    SuperVGAVideoState    near
  666.  
  667. ; First try calling the underlying video BIOS which may be VESA compatible.
  668.  
  669.         pusha
  670.         pushf
  671.         call    [OldInt10]            ; Call the old BIOS
  672.         mov        [Status],ax
  673.         popa
  674.         cmp        [Status],SUCCESS
  675.         je        @@Done                ; Succeeded, we are all done!
  676.  
  677. ; Otherwise try to do as much as possible with as little knowledge as
  678. ; possible.
  679.  
  680.         push    dx
  681.         push    cx
  682.         mov        ah,1Ch                ; Save/Restore video state BIOS call
  683.         mov        al,dl                ; AL := subfunction number
  684.         pushf
  685.         call    [OldInt10]            ; Call the old BIOS
  686.         pop        cx
  687.         pop        dx
  688.         cmp        al,1Ch
  689.         jne        @@Failure
  690.  
  691.         test    cx,010b
  692.         jz        @@Done
  693.         cmp        dl,2
  694.         jne        @@Done
  695.  
  696. ; The Video BIOS state was saved, so call the BIOS to set the current
  697. ; video mode again, and then restore the video state once more to complete
  698. ; things.
  699.  
  700.         push    cx
  701.         push    dx
  702.         push    es
  703.         mov        ax,40h
  704.         mov        es,ax
  705.         xor        ah,ah
  706.         mov        al,[BYTE es:49h]
  707.         pushf
  708.         call    [OldInt10]            ; Set the old video mode
  709.         pop        es
  710.         pop        dx
  711.         pop        cx
  712.  
  713.         mov        ah,1Ch
  714.         mov        al,2
  715.         pushf
  716.         call    [OldInt10]            ; Restore video state again
  717.  
  718. @@Done:
  719.         mov        [Status],SUCCESS
  720.  
  721. @@Failure:
  722.         ret
  723.  
  724. ENDP    SuperVGAVideoState
  725.  
  726. ;----------------------------------------------------------------------------
  727. ; SuperVGABankSwitch    - CPU Video Memory Control
  728. ;----------------------------------------------------------------------------
  729. ;
  730. ; Function to switch video banks for the SuperVGA. This function can be
  731. ; called as a far function call, rather than through the Int 10h mechanism
  732. ; for speed.
  733. ;
  734. ; Entry:        BH    - Subfunction number
  735. ;                      00h - Select video memory window
  736. ;                      01h - Get video memory window
  737. ;                BL    - Window number
  738. ;                      00h - Window A
  739. ;                      01h - Window B
  740. ;                DX    - Window address in video memory (granularity units)
  741. ;
  742. ; Exit:            AX    - VESA status code.
  743. ;                DX    - Window address in video memory (when requested)
  744. ;
  745. ;----------------------------------------------------------------------------
  746. PROC    SuperVGABankSwitch    far
  747.  
  748.         pusha
  749.         or        bh,bh
  750.         jnz        @@Done                ; Simply return the current window
  751.  
  752.         mov        ax,dx                ; AX := bank number
  753.         or        bl,bl
  754.         jnz        @@WindowB
  755.         call    [NewBank]            ; Set new read/write bank
  756.         jmp        @@Done
  757.  
  758. @@WindowB:
  759.         call    [ReadBank]            ; Set new read bank
  760.  
  761. @@Done:
  762.         popa
  763.         mov        dx,[CurBank]        ; Return the current bank number
  764.         mov        [Status],SUCCESS
  765.         mov        ax,SUCCESS
  766.         ret
  767.  
  768. ENDP    SuperVGABankSwitch
  769.  
  770. ;----------------------------------------------------------------------------
  771. ; SuperVGAScanlineWidth    - Get/Set Logical Scanline Length
  772. ;----------------------------------------------------------------------------
  773. ;
  774. ; Function to get/set the logical scanline length. This value is specified
  775. ; in pixels, but may require rounding to the next available value. The
  776. ; actual value set will be returned.
  777. ;
  778. ; Entry:        BL    - Subfunction number
  779. ;                      00h - Set scanline length
  780. ;                      01h - Get scanline length
  781. ;                CX    - Desired scanline length in pixels
  782. ;
  783. ; Exit:            AX    - VESA status code
  784. ;                BX    - Bytes per scanline
  785. ;                CX    - Pixels per scanline
  786. ;               DX    - Maximum number of scanlines
  787. ;
  788. ;----------------------------------------------------------------------------
  789. PROC    SuperVGAScanlineLength    near
  790.  
  791.         pusha
  792.         mov        ax,[CntColors]
  793.         mov        [Status],SUCCESS
  794.         or        bh,bh
  795.         jnz        @@GetScanlineLength
  796.  
  797. ; We are attempting to set the scanline width for the mode. First we need
  798. ; to adjust the value into bytes, and then set the CRTC offset register
  799.  
  800.         cmp        ax,gr16Color
  801.         je        @@Colors16
  802.         cmp        ax,gr256Color
  803.         je        @@SetOffsetReg
  804.         cmp        ax,gr32kColor
  805.         je        @@Colors32k
  806.  
  807.         mov        ax,cx
  808.         shl        cx,1
  809.         add        cx,ax                ; CX := bytes per scanline
  810.         and        cx,0FFF8h            ; Mask off bottom three bits
  811.         mov        [BytesPerLine],cx    ; Save BytesPerLine value
  812.         shr        cx,3                ; Shift value for offset register
  813.         jmp        @@SetOffsetReg
  814.  
  815. @@Colors16:
  816.         shr        cx,3
  817.         and        cx,0FFF0h            ; Mask off bottom four bits
  818.         mov        [BytesPerLine],cx    ; Save BytesPerLine value
  819.         shr        cx,4                ; Shift value for offset register
  820.         jmp        @@SetOffsetReg        ; CX := bytes per scanline
  821.  
  822. @@Colors256:
  823.         and        cx,0FFF8h            ; Mask off bottom three bits
  824.         mov        [BytesPerLine],cx    ; Save BytesPerLine value
  825.         shr        cx,3                ; Shift value for offset register
  826.         jmp        @@SetOffsetReg
  827.  
  828. @@Colors32k:
  829.         shl        cx,1
  830.         and        cx,0FFF8h            ; Mask off bottom three bits
  831.         mov        [BytesPerLine],cx    ; Save BytesPerLine value
  832.         shr        cx,3                ; Shift value for offset register
  833.  
  834. @@SetOffsetReg:
  835.         mov        dx,CRTC
  836.         mov        ah,cl
  837.         mov        al,13h
  838.         out        dx,ax                ; Program the CRTC offset value
  839.  
  840. ; Now return the scanline length
  841.  
  842. @@GetScanlineLength:
  843.         popa
  844.         mov        bx,[BytesPerLine]    ; BX := bytes per scanline
  845.         cmp        ax,gr16Color
  846.         je        @@GetColors16
  847.         cmp        ax,gr256Color
  848.         je        @@GetColors256
  849.         cmp        ax,gr32kColor
  850.         je        @@GetColors32k
  851.  
  852.         mov        ax,cx
  853.         shr        cx,1
  854.         sub        cx,ax                ; CX := pixels per scanline
  855.         ret
  856.  
  857. @@GetColors16:
  858.         shl        cx,3                ; CX := pixels per scanline
  859.         ret
  860.  
  861. @@GetColors256:
  862.         ret
  863.  
  864. @@GetColors32k:
  865.         shr        cx,1                ; CX := pixels per scanline
  866.         ret
  867.  
  868. ENDP    SuperVGAScanlineLength
  869.  
  870. ;----------------------------------------------------------------------------
  871. ; SuperVGADisplayStart    - Get/Set Display Start
  872. ;----------------------------------------------------------------------------
  873. ;
  874. ; Set the display start address for the current SuperVGA video mode.
  875. ;
  876. ; Entry:        BH    - 00h
  877. ;                BL    - Subfunction number
  878. ;                      00h - Set display start
  879. ;                      01h - Get display start
  880. ;                CX    - Leftmost displayed pixel in scanline
  881. ;                DX    - First displayed scanline
  882. ;
  883. ; Exit:            CX    - Leftmost displayed pixel in scanline
  884. ;                DX    - First displayed scanline
  885. ;
  886. ;----------------------------------------------------------------------------
  887. PROC    SuperVGADisplayStart
  888.  
  889.         cmp        [NewPage],offset NONE_page
  890.         je        @@Failure
  891.  
  892.         pusha
  893.         or        bh,bh
  894.         jnz        @@GetDisplayStart
  895.  
  896. ; Set the starting display address.
  897.  
  898.         xor        eax,eax
  899.         and        edx,0FFFFh            ; EDX := first scanline
  900.         and        ecx,0FFFFh            ; ECX := leftmost pixel
  901.         mov        ax,[BytesPerLine]
  902.         mul        edx                    ; EAX := y * bytesPerLine
  903.  
  904.         mov        bx,[CntColors]
  905.         cmp        bx,gr16Color
  906.         je        @@Colors16
  907.         cmp        bx,gr256Color
  908.         je        @@Colors256
  909.         cmp        bx,gr32kColor
  910.         je        @@Colors32k
  911.  
  912. ; Video mode is a 24 bit video mode
  913.  
  914.         add        eax,ecx                ; EAX := x + y * bytesPerLine
  915.         shl        ecx,1
  916.         add        eax,ecx                ; EAX := x * 3 + y * bytesPerLine
  917.         shr        eax,2                ; Adjust to lie on plane boundary
  918.         jmp        @@SetDisplayStart
  919.  
  920. ; Video mode is a 16 color video mode
  921.  
  922. @@Colors16:
  923.         shr        ecx,3
  924.         add        eax,ecx                ; EAX := x/8 + y * bytesPerLine
  925.         jmp        @@SetDisplayStart
  926.  
  927. ; Video mode is a 256 color video mode
  928.  
  929. @@Colors256:
  930.         add        eax,ecx                ; EAX := x + y * bytesPerLine
  931.         shr        eax,2                ; Adjust to lie on plane boundary
  932.         jmp        @@SetDisplayStart
  933.  
  934. ; Video mode is a 32k color video mode
  935.  
  936. @@Colors32k:
  937.         shl        ecx,1
  938.         add        eax,ecx                ; EAX := x + y * bytesPerLine
  939.         shr        eax,2                ; Adjust to lie on plane boundary
  940.  
  941. @@SetDisplayStart:
  942.         mov        cl,0Ch                ; CL := Start Address High register
  943.         mov        ch,ah                ; CH := high byte of new address
  944.         mov        bh,al                ; BH := low byte of new address
  945.         mov        bl,0Dh                ; BL := Start Address Low register
  946.         shr        eax,16
  947.         mov        si,ax                ; SI := Bits 16+ for SuperVGA's
  948.  
  949.         call    [NewPage]            ; Program the start address
  950.  
  951.         mov        [CntStartX],cx        ; Save the display starting coordinates
  952.         mov        [CntStartY],dx
  953.         mov        [Status],SUCCESS
  954.         popa
  955.         ret
  956.  
  957. @@GetDisplayStart:
  958.         popa
  959.         mov        cx,[CntStartX]        ; Return saved starting coordinates
  960.         mov        dx,[CntStartY]
  961.         mov        [Status],SUCCESS
  962. @@Failure:
  963.         ret
  964.  
  965. ENDP    SuperVGADisplayStart
  966.  
  967. ;----------------------------------------------------------------------------
  968. ; VESAToMGLMode    - Converts a VESA mode number to an MGL mode number
  969. ;----------------------------------------------------------------------------
  970. ;
  971. ; Internal routine to convert a VESA mode number to an MGL mode number.
  972. ; MGL Mode numbers are the ones that we use internally, since the code is
  973. ; based on that from the MegaGraph graphics library.
  974. ;
  975. ; Entry:        CX    - VESA mode number
  976. ;
  977. ; Exit:            AX    - MGL mode number (-1 if not found)
  978. ;
  979. ; Registers:    AX,CX
  980. ;
  981. ;----------------------------------------------------------------------------
  982. PROC    VESAToMGLMode    near
  983.  
  984.         push    bx
  985.         push    ds
  986.         push    si
  987.         push    di
  988.  
  989. ; First check to ensure that the VESA mode number is valid for the currently
  990. ; installed SuperVGA adapter.
  991.  
  992.         push    cs
  993.         pop        ds
  994.         mov        si,offset ModeTable    ; DS:SI -> Valid VESA mode table
  995.  
  996. @@VESALoop:
  997.         lodsw                        ; Load next valid VESA mode number
  998.         cmp        ax,-1
  999.         je        @@InvalidMode        ; Hit the end of the table
  1000.         cmp        ax,cx                ; Is this the one?
  1001.         je        @@ValidMode            ; Yes, so mode is valid
  1002.         jmp        @@VesaLoop            ; No, so keep looking...
  1003.  
  1004. ; Convert the VESA mode number to the MGL mode number by searching the
  1005. ; conversion table.
  1006.  
  1007. @@ValidMode:
  1008.         mov        si,offset VesaModes    ; DS:SI -> VESA/MGL mode table
  1009.  
  1010. @@ModeLoop:
  1011.         lodsw                        ; AX := VESA mode number
  1012.         or        ax,ax
  1013.         jz        @@InvalidMode        ; Exit if mode is invalid
  1014.         mov        bx,ax                ; BX := VESA mode number
  1015.         lodsw                        ; AX := MGL mode number
  1016.         cmp        bx,cx                ; Found the video mode?
  1017.         je        @@Exit                ; Yes, found the mode...
  1018.         jmp        @@ModeLoop
  1019.  
  1020. @@InvalidMode:
  1021.         mov        ax,-1                ; Video mode not found
  1022.  
  1023. @@Exit:
  1024.         pop        di
  1025.         pop        si
  1026.         pop        ds
  1027.         pop        bx
  1028.         ret
  1029.  
  1030. ENDP    VESAToMGLMode
  1031.  
  1032. EndResident:                        ; End of resident code
  1033.  
  1034. ;----------------------------------------------------------------------------
  1035. ;        Transient Code.
  1036. ;----------------------------------------------------------------------------
  1037.  
  1038.         ASSUME  cs:uvesa_TEXT, ds:DGROUP, es:NOTHING
  1039.  
  1040. ;----------------------------------------------------------------------------
  1041. ; bool isLoaded(void)
  1042. ;----------------------------------------------------------------------------
  1043. ; Returns true if the Universal VESA TSR is already loaded in memory.
  1044. ;----------------------------------------------------------------------------
  1045. procstart    _isLoaded
  1046.  
  1047.         enter    0,0
  1048.         push    ds
  1049.  
  1050.         GetVector    10h                ; ES:BX -> Current INT10h vector
  1051.         mov        di,bx
  1052.         sub        di,offset Int10ISR - offset Signature
  1053.                                     ; ES:DI -> Signature in loaded TSR
  1054.         push    cs
  1055.         pop        ds
  1056.         mov        si,offset Signature    ; DS:SI -> Signature in .COM file
  1057.         mov        cx,SigLen            ; CX := length of signature string
  1058.         cld
  1059.         mov        ax,1                ; Assume already loaded
  1060.         repe    cmpsb
  1061.         jcxz    @@AlreadyLoaded        ; Driver is already loaded!
  1062.  
  1063.         xor        ax,ax                ; Driver is not loaded
  1064.  
  1065. @@AlreadyLoaded:
  1066.         pop        ds
  1067.         leave
  1068.         ret
  1069.  
  1070. procend        _isLoaded
  1071.  
  1072. ;----------------------------------------------------------------------------
  1073. ; void goTSR(int driver,int chipID,int memory,int dac)
  1074. ;----------------------------------------------------------------------------
  1075. ;
  1076. ; This routine installs the VESA driver for the specified SuperVGA
  1077. ; configuration, and exits to the operating system leaving the required
  1078. ; code resident in memory.
  1079. ;
  1080. ; If we are in testing mode, the routine does not go TSR but simply
  1081. ; calls the 'C' testing routine, unhooks the interrupts and exits.
  1082. ;
  1083. ; Registers:    all
  1084. ;
  1085. ;----------------------------------------------------------------------------
  1086. procstart    _goTSR
  1087.  
  1088.         ARG        driver:WORD, chipID:WORD, memory:WORD, dac:WORD
  1089.  
  1090.         enter    0,0
  1091.  
  1092. ; Store the values for the SuperVGA configuration.
  1093.  
  1094.         mov        ax,[driver]
  1095.         mov        [CntDriver],ax
  1096.         mov        ax,[chipID]
  1097.         mov        [CntChipID],ax
  1098.         mov        ax,[memory]
  1099.         mov        [CntMemory],ax
  1100.         mov        ax,[dac]
  1101.         mov        [CntDac],ax
  1102.  
  1103. ; Now determine the list of available video modes for this adapter.
  1104.  
  1105.         push    [CntMemory]
  1106.         push    [CntDriver]
  1107.         call    _MGL_availableModes    ; Determine available video modes
  1108.         add     sp,4
  1109.  
  1110.         push    ds
  1111.         mov        ds,dx
  1112.         mov        si,ax                ; DS:SI -> MGL video mode table
  1113.         push    cs
  1114.         pop        es
  1115.         mov        di,offset ModeTable    ; ES:DI -> Video Mode Table
  1116.         mov        bx,offset VesaModes ; CS:BX -> All VESA Modes
  1117.  
  1118. @@ModeLoop:
  1119.         mov        cx,[cs:bx]            ; CX := VESA Mode Number
  1120.         jcxz    @@DoneModes            ; Quit when table exhausted
  1121.         mov        dx,[cs:bx+2]        ; DX := MGL Mode Number
  1122.         add        bx,4                ; CS:BX -> next mode in table
  1123.  
  1124.         push    si                    ; Save start of MGL mode table
  1125.  
  1126. @@FindMode:
  1127.         lodsw                        ; AX := MGL video mode number
  1128.         cmp        ax,-1
  1129.         je        @@NotFound            ; Mode was not found
  1130.         cmp        ax,dx
  1131.         je        @@Found                ; Mode number was found
  1132.         jmp        @@FindMode            ; Continue till mode is found
  1133.  
  1134. @@Found:
  1135.         mov        ax,cx
  1136.         stosw                        ; Store the appropriate mode number
  1137.  
  1138. @@NotFound:
  1139.         pop        si                    ; DS:SI -> MGL video mode table
  1140.         jmp        @@ModeLoop            ; Continue till table exhausted
  1141.  
  1142. ; Setup the bank switching and page flipping code, and determine if dual
  1143. ; banking is supported, modifying the video mode information table if
  1144. ; not.
  1145.  
  1146. @@DoneModes:
  1147.         mov        ax,0FFFFh
  1148.         stosw                        ; Terminate the mode list
  1149.         pop        ds                    ; Restore DS
  1150.         call    SetupBanks            ; Setup bank switching
  1151.         call    [InitSVGA]            ; Initialise SuperVGA code
  1152.         call    SetupPaging            ; Setup page flipping
  1153.         cmp        [TwoBanks],true
  1154.         je        @@DualBank
  1155.  
  1156.         mov        [WinBAttr],0        ; Remove support for second video bank
  1157.  
  1158. @@DualBank:
  1159.         call    HookVectors            ; Hook interrupt vectors
  1160.  
  1161. ifndef  TESTING
  1162.  
  1163. ; Now setup to go TSR with resident code.
  1164.  
  1165.         mov        ah,31h
  1166.         xor        al,al
  1167.         mov        dx,offset EndResident
  1168.         add        dx,PSPSize + 15        ; PSP is always resident!!
  1169.         shr        dx,4
  1170.         int        21h                    ; Go TSR!
  1171.  
  1172. else
  1173.  
  1174. ; Call the C testing routine, unhook vectors and quit.
  1175.  
  1176.         call    _testISR            ; Call the test routine
  1177.         call    UnhookVectors        ; Unhook vectors
  1178.         mov        ah,04Ch
  1179.         mov        al,1                ; Error code of 1
  1180.         int        21h                    ; Exit to DOS
  1181.  
  1182. endif
  1183.  
  1184. procend        _goTSR
  1185.  
  1186. ;----------------------------------------------------------------------------
  1187. ; HookVectors    - Hook into the interrupt vectors that we require.
  1188. ;----------------------------------------------------------------------------
  1189. ;
  1190. ; Saves the value of the old interrupt vectors that we require, and
  1191. ; install's hooks to our code for the vectors.
  1192. ;
  1193. ; Registers:    all
  1194. ;
  1195. ;----------------------------------------------------------------------------
  1196. PROC    HookVectors    near
  1197.  
  1198. ; Save old interrupt vectors
  1199.  
  1200.         GetVector    10h
  1201.         mov        [cs:OldInt10Off],bx
  1202.         mov        [cs:OldInt10Seg],es
  1203.  
  1204. ; Insert our interrupt vectors into vector table
  1205.  
  1206.         SetVector    10h, Int10ISR
  1207.         ret
  1208.  
  1209. ENDP    HookVectors
  1210.  
  1211. ;----------------------------------------------------------------------------
  1212. ; UnhookVectors    - Unhook from all interrupt vectors that we own.
  1213. ;----------------------------------------------------------------------------
  1214. ;
  1215. ; Restores the interrupt vector table to what it was before we installed
  1216. ; ourselves.
  1217. ;
  1218. ; Registers:    all
  1219. ;
  1220. ;----------------------------------------------------------------------------
  1221. PROC    UnhookVectors
  1222.  
  1223.         push    ds
  1224.         mov        dx,[OldInt10Seg]
  1225.         mov        ds,dx
  1226.         mov        dx,[OldInt10Off]
  1227.         mov        ah,25h
  1228.         mov        al,10h
  1229.         int        21h
  1230.         pop        ds
  1231.         ret
  1232.  
  1233. ENDP    UnhookVectors
  1234.  
  1235. endcodeseg    uvesa
  1236.  
  1237.         END
  1238.