home *** CD-ROM | disk | FTP | other *** search
/ World of Graphics / WOGRAPH.BIN / 430.SVGA16.ASM < prev    next >
Assembly Source File  |  1993-03-07  |  20KB  |  700 lines

  1. ;****************************************************************************
  2. ;*
  3. ;*                           SuperVGA Test Library
  4. ;*
  5. ;*                  Copyright (C) 1993 Kendall Bennett.
  6. ;*                            All rights reserved.
  7. ;*
  8. ;* Filename:    $RCSfile: svga16.asm $
  9. ;* Version:        $Revision: 1.2 $
  10. ;*
  11. ;* Language:    80386 Assembler
  12. ;* Environment:    IBM PC (MS DOS)
  13. ;*
  14. ;* Description:    This source file contains code to initialise the SuperVGA
  15. ;*                for bank switching and extended page flipping.
  16. ;*
  17. ;*                It also contains code to draw pixels, clear the display
  18. ;*                and perform page flipping for SuperVGA 16 color video modes.
  19. ;*
  20. ;* $Id: svga16.asm 1.2 1993/03/07 04:05:36 kjb Exp $
  21. ;*
  22. ;* Revision History:
  23. ;* -----------------
  24. ;*
  25. ;* $Log: svga16.asm $
  26. ;* Revision 1.2  1993/03/07  04:05:36  kjb
  27. ;* Bug fixes.
  28. ;*
  29. ;* Revision 1.1  1993/03/03  10:25:25  kjb
  30. ;* Initial revision
  31. ;*
  32. ;****************************************************************************
  33.  
  34.         IDEAL
  35.         JUMPS
  36.         P386                    ; Use 386 instructions
  37.  
  38. INCLUDE "model.mac"                ; Memory model macros
  39.  
  40. header        svga16
  41.  
  42. INCLUDE    "MGRAPH.EQU"            ; Include Equates for Mgraph Routines
  43.  
  44. CRTC            EQU    3D4h        ; Port of CRTC registers
  45. VGABufferSeg    EQU    0A000h        ; Segment of VGA display memory
  46. FIRSTMODE        EQU    grEGA_320x200x16
  47. MAXMODE            EQU    grSVGA_1280x1024x16
  48.  
  49. begcodeseg    svga16
  50.  
  51. ; Globals used by driver
  52.  
  53. OldBIOSMode            db    0            ; Old video mode before graphics
  54. Old50Lines            db    0            ; 1 if old mode was 50 line VGA
  55. CntDriver            dw    0            ; Graphics driver number
  56. CntMode                dw    0            ; Graphics mode number
  57. CntChipID            dw    0            ; Graphics driver chip ID
  58. CntColors            dw    gr16Color    ; This is a 16 color driver
  59.  
  60. ; The following information held in the status status area changes depending
  61. ; on which mode the driver is set up to be used in:
  62.  
  63. StatusArea:
  64.  
  65. XRes                dw    0            ; Device resolution in x direction - 1
  66. YRes                dw    0            ; Device resolution in y direction - 1
  67. BytesPerLine        dw    0            ; Number of bytes in a line
  68. PageSize            dd    0            ; Graphics page size
  69.  
  70. MaxPage                dw    0            ; Maximum number of video pages
  71. OriginOffset        dw    0            ; Offset of 0,0 into buffer
  72.  
  73. ; Here we set up a series of tables that can be used to fill in the start of
  74. ; the status area for each mode supported by this driver, and the address's
  75. ; of the routines required for each particular driver mode:
  76.  
  77. ModeTabStart:
  78.  
  79. ModeEGA_320x200x16    dw    319            ; XRes
  80.                     dw    199            ; YRes
  81.                     dw    40            ; BytesPerLine
  82. ModeEGA_640x200x16    dw    639            ; XRes
  83.                     dw    199            ; YRes
  84.                     dw    80            ; BytesPerLine
  85. ModeEGA_640x350x16    dw    639            ; XRes
  86.                     dw    349            ; YRes
  87.                     dw    80            ; BytesPerLine
  88. ModeVGA_640x400x16    dw    639            ; XRes
  89.                     dw    399            ; YRes
  90.                     dw    80            ; BytesPerLine
  91. ModeVGA_640x480x16    dw    639            ; XRes
  92.                     dw    479            ; YRes
  93.                     dw    80            ; BytesPerLine
  94. ModeSVGA_800x600:    dw    799            ; XRes
  95.                     dw    599            ; YRes
  96.                     dw    100            ; BytesPerLine
  97. ModeSVGA_1024x768:    dw    1023        ; XRes
  98.                     dw    767            ; YRes
  99.                     dw    128            ; BytesPerLine
  100. ModeSVGA_1280x1024:    dw    1279        ; XRes
  101.                     dw    1023        ; YRes
  102.                     dw    160            ; BytesPerLine
  103. ModeTabSize            =    ($-ModeSVGA_1280x1024)    ; Size of table in bytes
  104.  
  105. INCLUDE "SV_PORTS.ASM"
  106. INCLUDE "SV_BANKS.ASM"
  107. INCLUDE "SV_MODES.ASM"
  108. INCLUDE "SV_PAGE.ASM"
  109. INCLUDE "SV_MAXPG.ASM"
  110.  
  111. ;----------------------------------------------------------------------------
  112. ; int _initSuperVGA(int driver,int chipID,int mode,int memory)
  113. ;----------------------------------------------------------------------------
  114. ; Routine to initialise the bank switching code for the SuperVGA, and setup
  115. ; internal tables of information about the video mode. If the video mode
  116. ; is not supported, we return -1.
  117. ;
  118. ; The value returned is a status number, where bit 0 represents extended
  119. ; page flipping is available, bit 1 that separate read/write banks are
  120. ; available.
  121. ;----------------------------------------------------------------------------
  122. procstart    __initSuperVGA
  123.  
  124.         ARG        driver:WORD, ChipID:WORD, mode:WORD, memory:WORD
  125.  
  126.         enter    0,0
  127.         push    si
  128.         push    di
  129.  
  130. ; Save the driver number and chip ID for later
  131.  
  132.         mov        ax,[ChipID]
  133.         mov        [CntChipID],ax
  134.         mov        ax,[driver]
  135.         mov        [CntDriver],ax
  136.  
  137. ; Load the Status area with info for the currently selected mode:
  138.  
  139.         mov        ax,[mode]
  140.         mov        [CntMode],ax
  141.         cmp        ax,MAXMODE            ; AX := desired mode
  142.         jg        @@Invalid            ; invalid if greater than maximum
  143.         cmp        ax,FIRSTMODE
  144.         jl        @@Invalid            ; invalid if less than first mode
  145.         cmp        ax,grVGA_640x480x16
  146.         jle        @@ValidVGAMode
  147.         cmp        ax,grSVGA_800x600x16
  148.         jl        @@Invalid            ; Mode is invalid
  149.  
  150.         add        ax,grVGA_640x480x16 - grSVGA_800x600x16 + 1
  151.         jmp        @@LoadValues
  152.  
  153. @@ValidVGAMode:
  154.         sub        ax,FIRSTMODE
  155.  
  156. @@LoadValues:
  157.         mov        cx,ModeTabSize        ; Put size of table into cx
  158.         mul        cl                    ; AX := Mode * ModeTabSize
  159.         mov        si,ax
  160.         lea        si,[ModeTabStart + si]
  161.         push    cs
  162.         pop        es                    ; Set up es to point to code seg
  163.         lea        di,[StatusArea]        ; DI := Start of status area
  164.  
  165.         cld
  166.     rep    movs     [BYTE es:di],[BYTE es:si]
  167.  
  168.         mov        ax,[driver]
  169.         mov        bx,[mode]
  170.         call    loadSVGAMode        ; Load the SuperVGA video mode
  171.         or        ax,ax
  172.         jz        @@Invalid            ; Mode not supported on this adapter!
  173.  
  174.         mov        [maxpage],0            ; Clear maxpage variable
  175.         call    SetupBanks            ; Setup SuperVGA bank switching
  176.         call    [InitSVGA]            ; Initialise the SuperVGA
  177.         call    SetupPaging            ; Setup SuperVGA page flipping
  178.         mov        ax,0                ; Assume no paging available
  179.         jc        @@NoFlip
  180.         mov        ax,1                ; Flipping available
  181.  
  182. @@NoFlip:
  183.         push    ax                    ; Save flag for later
  184.  
  185. ; Determine the number of pages available for the mode and the video page
  186. ; size.
  187.  
  188.         xor        ebx,ebx
  189.         mov        bx,[memory]
  190.         or        ax,ax
  191.         jnz        @@ExtendedFlip
  192.  
  193.         cmp        [mode],grSVGA_800x600x16
  194.         jge        @@Done                ; Don't calculate for SVGA modes then
  195.         mov        bx,256                ; Extended flipping not available
  196.  
  197. @@ExtendedFlip:
  198.         shl        ebx,10                ; EBX := video memory in bytes
  199.         mov        ax,[mode]
  200.         call    numPages            ; Calculate the number of video pages
  201.         dec        ax
  202.         mov        [MaxPage],ax        ; Save maximum page number
  203.         mov        [DWORD pageSize],ebx
  204.         mov        [WORD bytesPerLine],cx
  205.  
  206. @@Done:
  207.         pop        ax                    ; AX := extended page flipping flag
  208.         mov        bx,[TwoBanks]
  209.         shl        bx,1
  210.         or        ax,bx                ; Set the two banks flag
  211.         jmp        @@Exit
  212.  
  213. @@Invalid:
  214.         mov        ax,-1                ; Return failure!
  215.  
  216. @@Exit:
  217.         pop        di
  218.         pop        si
  219.         leave
  220.         ret
  221.  
  222. procend        __initSuperVGA
  223.  
  224. ;----------------------------------------------------------------------------
  225. ; int _setSuperVGAMode(void);
  226. ;----------------------------------------------------------------------------
  227. ; Routine sets the system into the SuperVGA graphics mode setup by the
  228. ; initSuperVGA routine. Note that this routine remembers if the EGA/VGA
  229. ; 43/50 line mode was set.
  230. ;
  231. ; If the video mode was not correctly set, we return false.
  232. ;----------------------------------------------------------------------------
  233. procstart    __setSuperVGAMode
  234.  
  235.         push    bp                    ; INT 10h Kills this!!!
  236.         push    si                    ; so save all regs...
  237.         push    di
  238.         push    ds
  239.  
  240.         mov        ah,0Fh                ; Get current video mode service
  241.         int        10h
  242.         mov        [OldBIOSMode],al    ; Save old video mode
  243.         mov        [Old50Lines],0        ; Default to non-50 line mode
  244.  
  245.         mov        ax,1130h            ; AH := INT 10h function number
  246.                                     ; AL := Get character gen information
  247.         mov        bh,00                ; Get contents of INT 1Fh
  248.         xor        dl,dl                ; Clear dl
  249.         int        10h                    ; Determine number of lines (in dl)
  250.         cmp        dl,49                ; 50 line mode?
  251.         jne        @@SetMode            ; No, must have been 25 lines
  252.         mov        [Old50Lines],1        ; Yes, 50 line mode was on
  253.  
  254. @@SetMode:
  255.         mov        ax,[CntDriver]
  256.         mov        bx,[CntMode]
  257.         call    loadSVGAMode        ; AX,BX := correct values for mode
  258.         int        10h                    ; Set the video mode
  259.  
  260.         mov        ax,40h
  261.         mov        es,ax
  262.         xor        ax,ax
  263.         cmp        [BYTE es:49h],3        ; Mode is still text mode, did not set
  264.         jbe        @@Exit
  265.  
  266.         call    [InitSVGA]            ; Initialise bank switching on SuperVGA's
  267.         mov        ax,1                ; Mode was correctly set
  268.  
  269. @@Exit:
  270.         pop        ds
  271.         pop        di                    ; Restore regs
  272.         pop        si
  273.         pop        bp                    ; Restore bp (after INT 10 trashes it)
  274.         ret
  275.  
  276. procend        __setSuperVGAMode
  277.  
  278. ;----------------------------------------------------------------------------
  279. ; void restoreMode(void)
  280. ;----------------------------------------------------------------------------
  281. ; Routine restores the original video mode that was set before graphics mode
  282. ; was entered.
  283. ;----------------------------------------------------------------------------
  284. procstart    _restoreMode
  285.  
  286.         push    bp                    ; INT 10h kills bp sometimes
  287.         push    si                    ; Save all regs...
  288.         push    di
  289.  
  290.         call    [ExitSVGA]            ; Uninitialise the SuperVGA
  291.  
  292.         mov        ah,0                ; Set video mode service
  293.         mov        al,[OldBIOSMode]    ; Get old BIOS mode number
  294.         int        10h                    ; Set the video mode
  295.  
  296.         cmp        [Old50Lines],0        ; Was 50 line mode set?
  297.         je        @@Exit                ; No, don't set it up
  298.  
  299. ; Load video BIOS 8x8 characters into alphanumeric character generator
  300.  
  301.         mov        ax,1112h            ; AH := INT 10h function number
  302.                                     ; AL := 8x8 character set load
  303.         mov        bl,0                ; BL := block to load
  304.         int        10h                    ; load 8x8 characters into RAM
  305.  
  306. @@Exit:
  307.         pop        di                    ; Restore regs
  308.         pop        si
  309.         pop        bp                    ; Restore bp
  310.         ret
  311.  
  312. procend        _restoreMode
  313.  
  314. ;----------------------------------------------------------------------------
  315. ; void _getVideoInfo(int *xres,int *yres,int *bytesperline,int *maxpage)
  316. ;----------------------------------------------------------------------------
  317. ; Returns information about the currently selected video mode. The video
  318. ; mode must have been set for this info to be entirely valid.
  319. ;----------------------------------------------------------------------------
  320. procstart    __getVideoInfo
  321.  
  322.         ARG        _xres:DWORD, _yres:DWORD, _bytesperline:DWORD, _maxpage:DWORD
  323.  
  324.         enter    0,0
  325.  
  326.         les        bx,[_xres]
  327.         mov        ax,[xres]
  328.         mov        [es:bx],ax        ; Return the x resolution
  329.  
  330.         les        bx,[_yres]
  331.         mov        ax,[yres]
  332.         mov        [es:bx],ax        ; Return the y resolution
  333.  
  334.         les        bx,[_bytesperline]
  335.         mov        ax,[bytesperline]
  336.         mov        [es:bx],ax        ; Return the bytes per line value
  337.  
  338.         les        bx,[_maxpage]
  339.         mov        ax,[maxpage]
  340.         mov        [es:bx],ax        ; Return the maximum page number
  341.  
  342.         leave
  343.         ret
  344.  
  345. procend        __getVideoInfo
  346.  
  347. ;----------------------------------------------------------------------------
  348. ; void putPixel(int x,int y,int color)
  349. ;----------------------------------------------------------------------------
  350. ; Routine sets the value of a pixel in native VGA graphics modes.
  351. ;
  352. ; Entry:        x        -    X coordinate of pixel to draw
  353. ;                y        -    Y coordinate of pixel to draw
  354. ;                color    -    Color of pixel to draw
  355. ;
  356. ;----------------------------------------------------------------------------
  357. procstart    _putPixel
  358.  
  359.         ARG        x:WORD, y:WORD, color:WORD
  360.  
  361.         push    bp                    ; Set up stack frame
  362.         mov        bp,sp
  363.  
  364. ; Compute the pixel's address in video buffer
  365.  
  366.         mov        ax,[y]
  367.         mov        bx,[x]
  368.         mul        [BytesPerLine]        ; DX:AX := y * BytesPerLine
  369.  
  370.         mov        cl,bl                ; CL := low-order byte of x
  371.  
  372.         shr        bx,3                ; BX := x/8
  373.         add        bx,ax
  374.         adc        dx,0                ; DX:BX := y*BytesPerLine + x/8
  375.         add        bx,[OriginOffset]    ; DX:BX := byte offset in video buffer
  376.         adc        dx,[BankOffset]
  377.  
  378.         cmp        dl,[BYTE CurBank]
  379.         je        @@NoChange
  380.  
  381.         mov        ax,dx
  382.         call    [NewBank]
  383.  
  384. @@NoChange:
  385.         mov        ax,VGABufferSeg
  386.         mov        es,ax                ; ES:BX := byte address of pixel
  387.  
  388.         mov        ah,1                ; AH := unshifted bit mask
  389.         and        cl,7                ; CL := x & 7
  390.         xor        cl,7                ; CL := # bits to shift left
  391.  
  392. ; set Graphics Controller Bit Mask register
  393.  
  394.         shl        ah,cl                ; AH := bit mask in proper postion
  395.         mov        dx,3CEh                ; GC address register port
  396.         mov        al,8                ; AL := Bit Mask Register number
  397.         out        dx,ax
  398.  
  399. ; set Graphics Controller Mode register
  400.  
  401.         mov        ax,0205h            ; AL := Mode register number
  402.                                     ; AH := Write mode 2 (bits 0,1)
  403.                                     ;    Read mode 0 (bit 3)
  404.         out        dx,ax
  405.  
  406. ; set data rotate/Function Select register
  407.  
  408.         mov        ax,3                ; AL := Data Rotate/Func select reg #
  409.         out        dx,ax
  410.  
  411. ; set the pixel value
  412.  
  413.         mov        al,[es:bx]            ; latch one byte from each bit plane
  414.         mov        ax,[color]            ; AL := pixel value
  415.         mov        [es:bx],al            ; update all bit planes
  416.  
  417. ; restore default Graphics Controller registers
  418.  
  419.         mov        ax,0FF08h            ; default bit mask
  420.         out        dx,ax
  421.  
  422.         mov        ax,0005                ; default mode register
  423.         out        dx,ax
  424.  
  425.         mov        ax,0003                ; default function select
  426.         out        dx,ax
  427.  
  428.         pop        bp
  429.         ret
  430.  
  431. procend        _putPixel
  432.  
  433. ;----------------------------------------------------------------------------
  434. ; void clear(void)
  435. ;----------------------------------------------------------------------------
  436. ; Routine to clear the screen. Works even if the display contains more than
  437. ; one bank, so will work for 1024x768 and 1280x1024 video modes.
  438. ;----------------------------------------------------------------------------
  439. procstart    _clear
  440.  
  441.         push    bp                    ; Set up stack frame
  442.         mov        bp,sp
  443.         push    si                    ; Save registers
  444.         push    di
  445.  
  446. ; Setup graphics controller
  447.  
  448.         mov        dx,3CEh                ; DX := Graphics Controller I/O port
  449.  
  450.         mov        ah,0                ; AH := Background color
  451.         xor        al,al                ; AL := 0 (Set/Reset register number)
  452.         out        dx,ax                ; load set/reset register
  453.  
  454.         mov        ax,0F01h            ; AH := 1111b (mask for Enable set/reset)
  455.                                     ; AL := 1 (enable Set/reset reg number)
  456.         out        dx,ax                ; load enable set/reset reg
  457.  
  458.         mov        ax,[YRes]
  459.         inc        ax
  460.         mul        [BytesPerLine]        ; DX:AX := number of bytes to fill
  461.         mov        bx,ax                ; BX := bytes in last bank to fill
  462.         mov        dh,dl                ; DH := number of full banks to fill
  463.  
  464.         mov        ax,VGABufferSeg
  465.         mov        es,ax
  466.         mov        di,[OriginOffset]    ; ES:DI -> video buffer
  467.         mov        al,[BYTE BankOffset]; AL := starting bank number
  468.         cld                            ; Moves go up in memory
  469.  
  470.         or        dh,dh                ; More than one bank to fill?
  471.         jz        @@SingleBank        ; No, only fill a single bank
  472.  
  473. ; Fill all of the full 64k banks first
  474.  
  475. @@OuterLoop:
  476.         call    [NewBank]
  477.         mov        cx,4000h            ; Need to set 4000h double words per bank
  478.     rep    stosd
  479.         inc        al
  480.         dec        dh
  481.         jnz        @@OuterLoop
  482.  
  483. ; Now fill the last partial bank
  484.  
  485. @@SingleBank:
  486.         call    [NewBank]
  487.         mov        cx,bx
  488.         shr        cx,2                ; CX := number of double words to set
  489.     rep    stosd
  490.  
  491. ; Restore graphics controller
  492.  
  493.         mov        dx,3CEh                ; DX := Graphics Controller I/O port
  494.         xor        ax,ax                ; AH := 0, AL := 0
  495.         out        dx,ax                ; Restore default Set/Reset register
  496.  
  497.         inc        ax                    ; AH := 0, AL := 1
  498.         out        dx,ax                ; Restore enable Set/Reset register
  499.  
  500.         pop        di
  501.         pop        si
  502.         pop        bp
  503.         ret
  504.  
  505. procend        _clear
  506.  
  507. ;----------------------------------------------------------------------------
  508. ; void _copyTest(void)
  509. ;----------------------------------------------------------------------------
  510. ; Routine to copy the top half of video memory to the bottom half of
  511. ; video memory. To ensure that we a moving across a bank boundary in
  512. ; 16 color modes, we copy the data to the second video page.
  513. ;----------------------------------------------------------------------------
  514. procstart    __copyTest
  515.  
  516.         push    si                    ; Save registers
  517.         push    di
  518.         push    ds
  519.  
  520.         mov        ax,[YRes]
  521.         inc        ax
  522.         shr        ax,1                ; AX := (Yres+1) / 2
  523.         mul        [BytesPerLine]
  524.         mov        cx,ax                ; CX := Number of bytes to move
  525.  
  526. ; Set up graphics controller
  527.  
  528.         mov        dx,3CEh                ; DX := Graphics Controller address port
  529.         mov        ax,0105h            ; AH := 1 (read mode 0, write mode 1)
  530.                                     ; AL := 5 (Mode register number)
  531.         out        dx,ax                ; Set up mode
  532.  
  533.         mov        di,[WORD PageSize]    ; ES:DI := offset into destination buffer
  534.         mov        al,[BYTE PageSize+2]
  535.         add        di,cx
  536.         adc        al,0
  537.         call    [NewBank]            ; Set the read/write bank number
  538.  
  539.         xor        si,si                ; DS:SI := offset into source buffer
  540.         xor        al,al
  541.         call    [ReadBank]            ; Set the read bank number
  542.  
  543.         mov        ax,VGABufferSeg
  544.         mov        ds,ax                ; DS:SI -> source buffer
  545.         mov        es,ax                ; ES:DI -> destination buffer
  546.         cld                            ; Moves go up in memory
  547.  
  548.     rep    movsb                        ; Move all data in bank FAST!
  549.  
  550. ; Restore default graphics controller state
  551.  
  552.         mov        ax,0005h            ; default mode register value
  553.         out        dx,ax
  554.  
  555.         pop        ds
  556.         pop        di
  557.         pop        si
  558.         ret
  559.  
  560. procend        __copyTest
  561.  
  562. ;----------------------------------------------------------------------------
  563. ; void setActivePage(int which)
  564. ;----------------------------------------------------------------------------
  565. ; Routine to set the video page for active output.
  566. ;
  567. ; Entry:        page    - Page number of page to use
  568. ;
  569. ;----------------------------------------------------------------------------
  570. procstart    _setActivePage
  571.  
  572.         ARG        which:WORD
  573.  
  574.         push    bp                    ; Set up stack frame
  575.         mov        bp,sp
  576.  
  577. ; Calculate 18 bit address of page in video memory
  578.  
  579.         xor        eax,eax
  580.         mov        ax,[which]            ; EAX := page number
  581.         mul        [PageSize]            ; EDX:EAX := result
  582.         mov        [OriginOffset],ax    ; Save video buffer offset
  583.         shr        eax,16
  584.         mov        [BankOffset],ax        ; Save video bank offset
  585.  
  586.         pop        bp
  587.         ret
  588.  
  589. procend        _setActivePage
  590.  
  591. ;----------------------------------------------------------------------------
  592. ; void setVisualPage(int which)
  593. ;----------------------------------------------------------------------------
  594. ; Routine to set the visible video page.
  595. ;
  596. ; Entry:        page    - Page number of page to use
  597. ;
  598. ;----------------------------------------------------------------------------
  599. procstart        _setVisualPage
  600.  
  601.         ARG        which:WORD
  602.  
  603.         push    bp                    ; Set up stack frame
  604.         mov        bp,sp
  605.         push    si
  606.  
  607. ; Calculate 18 bit address of page in video memory
  608.  
  609.         xor        eax,eax
  610.         mov        ax,[which]            ; EAX := page number
  611.         mul        [PageSize]            ; EDX:EAX := result
  612.         mov        bx,ax                ; BX := bottom 16 bits of address
  613.         shr        eax,16
  614.         push    ax                    ; Save top 2 bits of address
  615.  
  616. ; Wait for display enable to be active (active low), to be sure that
  617. ; both halves of the start address will take place in one frame. We
  618. ; preload a few values here to save time after the DE has been
  619. ; detected.
  620.  
  621.         mov        cl,0Ch                ; CL := Start Address High register
  622.         mov        ch,bh                ; CH := high byte of new address
  623.         mov        bh,bl                ; BH := low byte of new address
  624.         mov        bl,0Dh                ; BL := Start Address Low register
  625.         mov        dx,03DAh            ; DX := video status port
  626.  
  627. @@WaitDE:
  628.         in        al,dx
  629.         test    al,1
  630.         jnz        @@WaitDE            ; Wait for Display Enable
  631.  
  632.         cli
  633.         pop        si                    ; SI := Bits 16+ for SuperVGA's
  634.         call    [NewPage]            ; Program the start address
  635.         sti
  636.  
  637. ; Now wait for the start of the vertical sync, to ensure that the old
  638. ; page will be invisible before anything is drawn on it.
  639.  
  640.         mov        dx,03DAh            ; DX := video status port
  641. @@WaitStartVert:
  642.         in        al,dx                ; Wait for start of vertical retrace
  643.         test    al,8
  644.         jz        @@WaitStartVert
  645.  
  646. @@Exit:
  647.         pop        si
  648.         pop        bp
  649.         ret
  650.  
  651. procend        _setVisualPage
  652.  
  653. ;----------------------------------------------------------------------------
  654. ; void setBank(int bank)
  655. ;----------------------------------------------------------------------------
  656. ; Sets the current read and write bank to the specified 64k bank number.
  657. ;----------------------------------------------------------------------------
  658. procstart    _setBank
  659.  
  660.         ARG        bank:WORD
  661.  
  662.         enter    0,0
  663.  
  664.         mov        al,[BYTE bank]
  665.         cmp        al,[BYTE CurBank]
  666.         je        @@NoChange
  667.  
  668.         call    [NewBank]
  669.  
  670. @@NoChange:
  671.         leave
  672.         ret
  673.  
  674. procend        _setBank
  675.  
  676. ;----------------------------------------------------------------------------
  677. ; void setReadBank(int bank)
  678. ;----------------------------------------------------------------------------
  679. ; Sets the current read bank to the specified 64k bank. If you wish to set
  680. ; the read and write banks separately, call setBank() first, followed by
  681. ; setReadBank().
  682. ;----------------------------------------------------------------------------
  683. procstart    _setReadBank
  684.  
  685.         ARG        bank:WORD
  686.  
  687.         enter    0,0
  688.  
  689.         mov        al,[BYTE bank]
  690.         call    [ReadBank]
  691.  
  692.         leave
  693.         ret
  694.  
  695. procend        _setReadBank
  696.  
  697. endcodeseg    svga16
  698.  
  699.         END
  700.