home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 409_01 / svga.asm < prev    next >
Encoding:
Assembly Source File  |  1993-10-22  |  33.8 KB  |  1,024 lines

  1. ;****************************************************************************
  2. ;*
  3. ;*                         SuperVGA Test Library
  4. ;*
  5. ;*                  Copyright (C) 1993 SciTech Software
  6. ;*                          All rights reserved.
  7. ;*
  8. ;* Filename:    $RCSfile: svga.asm $
  9. ;* Version:     $Revision: 1.2 $
  10. ;*
  11. ;* Language:    80386 Assembler
  12. ;* Environment: IBM PC (MS DOS)
  13. ;*
  14. ;* Description: Assembly language support routines for the SuperVGA test
  15. ;*              library.
  16. ;*
  17. ;* $Id: svga.asm 1.2 1993/10/22 08:58:40 kjb release $
  18. ;*
  19. ;****************************************************************************
  20.  
  21.         IDEAL
  22.         JUMPS
  23.         P386                    ; Use 386 instructions
  24.  
  25.         MODEL   large
  26.  
  27. CRTC            EQU 3D4h        ; Port of CRTC registers
  28. VGABufferSeg    EQU 0A000h      ; Segment of VGA display memory
  29.  
  30.         DATASEG
  31.  
  32.         COMM    _maxx:WORD
  33.         COMM    _maxy:WORD
  34.         COMM    _maxcolor:DWORD
  35.         COMM    _bytesperline:WORD
  36.         COMM    _pagesize:DWORD
  37.         COMM    _curBank:WORD
  38.         COMM    _bankSwitch:DWORD
  39.         COMM    _extendedflipping:WORD
  40.         COMM    _bankAdjust:WORD
  41.         COMM    _writeBank:DWORD; Relocated write bank routine
  42.         COMM    _readBank:DWORD ; Relocated read bank routine
  43.         COMM    _pageFlip:DWORD ; Relocated page flip routine
  44.  
  45. OriginOffset    dw  0           ; Starting offset within bank
  46. BankOffset      dw  0           ; Starting bank in video memory
  47.  
  48.         CODESEG
  49.  
  50. MACRO   procstart name          ; Set up model independant proc
  51. PROC    name
  52.         PUBLIC name
  53. ENDM
  54.  
  55. MACRO   procend name            ; End procedure macro
  56. ENDP    name
  57. ENDM
  58.  
  59. ;----------------------------------------------------------------------------
  60. ; void putPixel16(int x,int y,long color)
  61. ;----------------------------------------------------------------------------
  62. ; Routine sets the value of a pixel in native VGA graphics modes.
  63. ;
  64. ; Entry:        x       -   X coordinate of pixel to draw
  65. ;               y       -   Y coordinate of pixel to draw
  66. ;               color   -   Color of pixel to draw
  67. ;
  68. ;----------------------------------------------------------------------------
  69. procstart   __putPixel16
  70.  
  71.         ARG     x:WORD, y:WORD, color:DWORD
  72.  
  73.         push    bp                  ; Set up stack frame
  74.         mov     bp,sp
  75.  
  76. ; Compute the pixel's address in video buffer
  77.  
  78.         mov     ax,[y]
  79.         mov     bx,[x]
  80.         mul     [_bytesPerLine]     ; DX:AX := y * BytesPerLine
  81.  
  82.         mov     cl,bl               ; CL := low-order byte of x
  83.  
  84.         shr     bx,3                ; BX := x/8
  85.         add     bx,ax
  86.         adc     dx,0                ; DX:BX := y*BytesPerLine + x/8
  87.         add     bx,[OriginOffset]   ; DX:BX := byte offset in video buffer
  88.         adc     dx,[BankOffset]
  89.  
  90.         cmp     dl,[BYTE _curBank]
  91.         je      @@NoChange
  92.  
  93.         mov     ax,dx
  94.         call    setBank
  95.  
  96. @@NoChange:
  97.         mov     ax,VGABufferSeg
  98.         mov     es,ax               ; ES:BX := byte address of pixel
  99.  
  100.         mov     ah,1                ; AH := unshifted bit mask
  101.         and     cl,7                ; CL := x & 7
  102.         xor     cl,7                ; CL := # bits to shift left
  103.  
  104. ; set Graphics Controller Bit Mask register
  105.  
  106.         shl     ah,cl               ; AH := bit mask in proper postion
  107.         mov     dx,3CEh             ; GC address register port
  108.         mov     al,8                ; AL := Bit Mask Register number
  109.         out     dx,ax
  110.  
  111. ; set Graphics Controller Mode register
  112.  
  113.         mov     ax,0205h            ; AL := Mode register number
  114.                                     ; AH := Write mode 2 (bits 0,1)
  115.                                     ;   Read mode 0 (bit 3)
  116.         out     dx,ax
  117.  
  118. ; set data rotate/Function Select register
  119.  
  120.         mov     ax,3                ; AL := Data Rotate/Func select reg #
  121.         out     dx,ax
  122.  
  123. ; set the pixel value
  124.  
  125.         mov     al,[es:bx]          ; latch one byte from each bit plane
  126.         mov     al,[BYTE color]     ; AL := pixel value
  127.         mov     [es:bx],al          ; update all bit planes
  128.  
  129. ; restore default Graphics Controller registers
  130.  
  131.         mov     ax,0FF08h           ; default bit mask
  132.         out     dx,ax
  133.  
  134.         mov     ax,0005             ; default mode register
  135.         out     dx,ax
  136.  
  137.         mov     ax,0003             ; default function select
  138.         out     dx,ax
  139.  
  140.         pop     bp
  141.         ret
  142.  
  143. procend     __putPixel16
  144.  
  145. ;----------------------------------------------------------------------------
  146. ; void putPixel256(int x,int y,long color)
  147. ;----------------------------------------------------------------------------
  148. ; Routine sets the value of a pixel in native VGA graphics modes.
  149. ;
  150. ; Entry:        x       -   X coordinate of pixel to draw
  151. ;               y       -   Y coordinate of pixel to draw
  152. ;               color   -   Color of pixel to draw
  153. ;
  154. ;----------------------------------------------------------------------------
  155. procstart   __putPixel256
  156.  
  157.         ARG     x:WORD, y:WORD, color:DWORD
  158.  
  159.         push    bp                  ; Set up stack frame
  160.         mov     bp,sp
  161.  
  162.         mov     ax,[y]
  163.         mul     [_bytesperline]
  164.         add     ax,[x]
  165.         adc     dx,0                ; DX:AX := y * BytesPerLine + x
  166.         add     ax,[OriginOffset]
  167.         adc     dl,[BYTE BankOffset]; DL := bank number
  168.         mov     bx,ax               ; BX := Offset in buffer
  169.         cmp     dl,[BYTE _curBank]
  170.         je      @@NoChange
  171.  
  172.         mov     ax,dx
  173.         call    setBank
  174.  
  175. @@NoChange:
  176.         mov     ax,VGABufferSeg
  177.         mov     es,ax               ; ES:BX := byte address of pixel
  178.         mov     al,[BYTE color]
  179.         mov     [es:bx],al          ; Replace the pixel
  180.         pop     bp
  181.         ret
  182.  
  183. procend     __putPixel256
  184.  
  185. ;----------------------------------------------------------------------------
  186. ; void putPixel32k(int x,int y,long color)
  187. ;----------------------------------------------------------------------------
  188. ; Routine sets the value of a pixel in native VGA graphics modes.
  189. ;
  190. ; Entry:        x       -   X coordinate of pixel to draw
  191. ;               y       -   Y coordinate of pixel to draw
  192. ;               color   -   Color of pixel to draw
  193. ;
  194. ;----------------------------------------------------------------------------
  195. procstart   __putPixel32k
  196.  
  197.         ARG     x:WORD, y:WORD, color:DWORD
  198.  
  199.         push    bp                  ; Set up stack frame
  200.         mov     bp,sp
  201.  
  202.         mov     ax,[y]
  203.         mul     [_bytesperline]
  204.         mov     bx,[x]
  205.         shl     bx,1
  206.         add     ax,bx
  207.         adc     dx,0                ; DX:AX := y * BytesPerLine + x * 2
  208.         add     ax,[OriginOffset]
  209.         adc     dl,[BYTE BankOffset]; DL := bank number
  210.         mov     bx,ax               ; BX := Offset in buffer
  211.         cmp     dl,[BYTE _curBank]
  212.         je      @@NoChange
  213.  
  214.         mov     al,dl
  215.         call    setBank
  216.  
  217. @@NoChange:
  218.         mov     ax,VGABufferSeg
  219.         mov     es,ax               ; ES:BX := byte address of pixel
  220.         mov     ax,[WORD color]
  221.         mov     [es:bx],ax          ; Replace the pixel
  222.         pop     bp
  223.         ret
  224.  
  225. procend     __putPixel32k
  226.  
  227. ;----------------------------------------------------------------------------
  228. ; void putPixel64k(int x,int y,long color)
  229. ;----------------------------------------------------------------------------
  230. ; Routine sets the value of a pixel in native VGA graphics modes.
  231. ;
  232. ; Entry:        x       -   X coordinate of pixel to draw
  233. ;               y       -   Y coordinate of pixel to draw
  234. ;               color   -   Color of pixel to draw
  235. ;
  236. ;----------------------------------------------------------------------------
  237. procstart   __putPixel64k
  238.  
  239.         ARG     x:WORD, y:WORD, color:DWORD
  240.  
  241.         push    bp                  ; Set up stack frame
  242.         mov     bp,sp
  243.  
  244.         mov     ax,[y]
  245.         mul     [_bytesperline]
  246.         mov     bx,[x]
  247.         shl     bx,1
  248.         add     ax,bx
  249.         adc     dx,0                ; DX:AX := y * BytesPerLine + x * 2
  250.         add     ax,[OriginOffset]
  251.         adc     dl,[BYTE BankOffset]; DL := bank number
  252.         mov     bx,ax               ; BX := Offset in buffer
  253.         cmp     dl,[BYTE _curBank]
  254.         je      @@NoChange
  255.  
  256.         mov     al,dl
  257.         call    setBank
  258.  
  259. @@NoChange:
  260.         mov     ax,VGABufferSeg
  261.         mov     es,ax               ; ES:BX := byte address of pixel
  262.         mov     ax,[WORD color]
  263.         mov     [es:bx],ax          ; Replace the pixel
  264.         pop     bp
  265.         ret
  266.  
  267. procend     __putPixel64k
  268.  
  269. ;----------------------------------------------------------------------------
  270. ; void putPixel16m(int x,int y,long color)
  271. ;----------------------------------------------------------------------------
  272. ; Routine sets the value of a pixel in native VGA graphics modes.
  273. ;
  274. ; Entry:        x       -   X coordinate of pixel to draw
  275. ;               y       -   Y coordinate of pixel to draw
  276. ;               color   -   Color of pixel to draw
  277. ;
  278. ;----------------------------------------------------------------------------
  279. procstart   __putPixel16m
  280.  
  281.         ARG     x:WORD, y:WORD, color:DWORD
  282.  
  283.         push    bp                  ; Set up stack frame
  284.         mov     bp,sp
  285.  
  286.         mov     ax,[y]
  287.         mul     [_bytesperline]
  288.         mov     bx,[x]
  289.         add     ax,bx
  290.         adc     dx,0
  291.         shl     bx,1
  292.         add     ax,bx
  293.         adc     dx,0                ; DX:AX := y * BytesPerLine + x * 3
  294.         add     ax,[OriginOffset]
  295.         adc     dl,[BYTE BankOffset]; DL := bank number
  296.         mov     bx,ax               ; BX := Offset in buffer
  297.         cmp     dl,[BYTE _curBank]
  298.         je      @@NoChange
  299.  
  300.         mov     al,dl
  301.         call    setBank
  302.  
  303. @@NoChange:
  304.         mov     ax,VGABufferSeg
  305.         mov     es,ax               ; ES:BX := byte address of pixel
  306.         mov     al,[BYTE color]
  307.         mov     [es:bx],al          ; Replace the first byte
  308.         cmp     bx,0FFFFh
  309.         jne     @@NotSplit1
  310.  
  311. ; Arrghh!! We have a case where a single pixel can be split across a
  312. ; bank boundary, if the bytes per line value is 1920. This can cause the
  313. ; machine to hang (and produce strange pixels).
  314.  
  315.         inc     dl
  316.         mov     al,dl
  317.         call    setBank         ; Change video banks
  318.  
  319. @@NotSplit1:
  320.         mov     al,[BYTE color+1]
  321.         mov     [es:bx+1],al        ; Replace the middle
  322.         cmp     bx,0FFFEh
  323.         jne     @@NotSplit2
  324.  
  325.         inc     dl
  326.         mov     al,dl
  327.         call    setBank     ; Change video banks
  328.  
  329. @@NotSplit2:
  330.         mov     al,[BYTE color+2]
  331.         mov     [es:bx+2],al        ; Replace the last byte
  332.         pop     bp
  333.         ret
  334.  
  335. procend     __putPixel16m
  336.  
  337. ;----------------------------------------------------------------------------
  338. ; void clear16(void)
  339. ;----------------------------------------------------------------------------
  340. ; Routine to clear the screen. Works even if the display contains more than
  341. ; one bank, so will work for 1024x768 and 1280x1024 video modes.
  342. ;----------------------------------------------------------------------------
  343. procstart   __clear16
  344.  
  345.         push    bp                  ; Set up stack frame
  346.         mov     bp,sp
  347.         push    si                  ; Save registers
  348.         push    di
  349.  
  350. ; Setup graphics controller
  351.  
  352.         mov     dx,3CEh             ; DX := Graphics Controller I/O port
  353.  
  354.         mov     ah,0                ; AH := Background color
  355.         xor     al,al               ; AL := 0 (Set/Reset register number)
  356.         out     dx,ax               ; load set/reset register
  357.  
  358.         mov     ax,0F01h            ; AH := 1111b (mask for Enable set/reset)
  359.                                     ; AL := 1 (enable Set/reset reg number)
  360.         out     dx,ax               ; load enable set/reset reg
  361.  
  362.         mov     ax,[_maxy]
  363.         inc     ax
  364.         mul     [_bytesperline]     ; DX:AX := number of bytes to fill
  365.         mov     bx,ax               ; BX := bytes in last bank to fill
  366.         mov     dh,dl               ; DH := number of full banks to fill
  367.  
  368.         mov     ax,VGABufferSeg
  369.         mov     es,ax
  370.         mov     di,[OriginOffset]   ; ES:DI -> video buffer
  371.         mov     ax,[BankOffset]     ; AX := starting bank number
  372.         cld                         ; Moves go up in memory
  373.  
  374.         or      dh,dh               ; More than one bank to fill?
  375.         jz      @@SingleBank        ; No, only fill a single bank
  376.  
  377. ; Fill all of the full 64k banks first
  378.  
  379. @@OuterLoop:
  380.         call    setBank
  381.         mov     cx,4000h            ; Need to set 4000h double words per bank
  382.     rep stosd
  383.         inc     al
  384.         dec     dh
  385.         jnz     @@OuterLoop
  386.  
  387. ; Now fill the last partial bank
  388.  
  389. @@SingleBank:
  390.         call    setBank
  391.         mov     cx,bx
  392.         shr     cx,2                ; CX := number of double words to set
  393.     rep stosd
  394.  
  395. ; Restore graphics controller
  396.  
  397.         mov     dx,3CEh             ; DX := Graphics Controller I/O port
  398.         xor     ax,ax               ; AH := 0, AL := 0
  399.         out     dx,ax               ; Restore default Set/Reset register
  400.  
  401.         inc     ax                  ; AH := 0, AL := 1
  402.         out     dx,ax               ; Restore enable Set/Reset register
  403.  
  404.         pop     di
  405.         pop     si
  406.         pop     bp
  407.         ret
  408.  
  409. procend     __clear16
  410.  
  411. ;----------------------------------------------------------------------------
  412. ; void clear256(void)
  413. ;----------------------------------------------------------------------------
  414. ; Routine to clear the screen. Assumes pages begin on bank boundaries
  415. ; for simplicity of coding.
  416. ;----------------------------------------------------------------------------
  417. procstart   __clear256
  418.  
  419.         push    di
  420.         mov     ax,[_maxy]
  421.         inc     ax
  422.         mul     [_bytesperline]     ; DX:AX := number of bytes to fill
  423.         mov     bx,ax               ; BX := bytes in last bank to fill
  424.         mov     dh,dl               ; DH := number of full banks to fill
  425.  
  426.         mov     ax,VGABufferSeg
  427.         mov     es,ax
  428.         mov     di,[OriginOffset]   ; ES:DI -> video buffer
  429.         mov     dl,[BYTE BankOffset]; DL := starting bank number
  430.         cld                         ; Moves go up in memory
  431.  
  432.         or      dh,dh               ; More than one bank to fill?
  433.         jz      @@SingleBank        ; No, only fill a single bank
  434.  
  435. ; Fill all of the full 64k banks first
  436.  
  437. @@OuterLoop:
  438.         mov     al,dl
  439.         call    setBank
  440.         xor     eax,eax             ; Clear to black
  441.         mov     cx,4000h            ; Need to set 4000h double words per bank
  442.     rep stosd
  443.         inc     dl
  444.         dec     dh
  445.         jnz     @@OuterLoop
  446.  
  447. ; Now fill the last partial bank
  448.  
  449. @@SingleBank:
  450.         mov     al,dl
  451.         call    setBank
  452.         xor     eax,eax             ; Clear to black
  453.         mov     cx,bx
  454.         shr     cx,2                ; CX := number of double words to set
  455.     rep stosd
  456.  
  457.         pop     di
  458.         ret
  459.  
  460. procend     __clear256
  461.  
  462. ;----------------------------------------------------------------------------
  463. ; void clear32k(void)
  464. ;----------------------------------------------------------------------------
  465. ; Routine to clear the screen. Assumes pages begin on bank boundaries
  466. ; for simplicity of coding.
  467. ;----------------------------------------------------------------------------
  468. procstart   __clear32k
  469.  
  470.         push    di
  471.         mov     ax,[_maxy]
  472.         inc     ax
  473.         mul     [_bytesperline]     ; DX:AX := number of bytes to fill
  474.         mov     bx,ax               ; BX := bytes in last bank to fill
  475.         mov     dh,dl               ; DH := number of full banks to fill
  476.  
  477.         mov     ax,VGABufferSeg
  478.         mov     es,ax
  479.         mov     di,[OriginOffset]   ; ES:DI -> video buffer
  480.         mov     dl,[BYTE BankOffset]; DL := starting bank number
  481.         cld                         ; Moves go up in memory
  482.  
  483. ; Fill all of the full 64k banks first
  484.  
  485. @@OuterLoop:
  486.         mov     al,dl
  487.         call    setBank
  488.         xor     eax,eax             ; Clear to black
  489.         mov     cx,4000h            ; Need to set 4000h double words per bank
  490.     rep stosd
  491.         inc     dl
  492.         dec     dh
  493.         jnz     @@OuterLoop
  494.  
  495. ; Now fill the last partial bank
  496.  
  497.         mov     al,dl
  498.         call    setBank
  499.         xor     eax,eax             ; Clear to black
  500.         mov     cx,bx
  501.         shr     cx,2                ; CX := number of double words to set
  502.     rep stosd
  503.  
  504.         pop     di
  505.         ret
  506.  
  507. procend     __clear32k
  508.  
  509. ;----------------------------------------------------------------------------
  510. ; void clear64k(void)
  511. ;----------------------------------------------------------------------------
  512. ; Routine to clear the screen. Assumes pages begin on bank boundaries
  513. ; for simplicity of coding.
  514. ;----------------------------------------------------------------------------
  515. procstart   __clear64k
  516.  
  517.         push    di
  518.         mov     ax,[_maxy]
  519.         inc     ax
  520.         mul     [_bytesperline]     ; DX:AX := number of bytes to fill
  521.         mov     bx,ax               ; BX := bytes in last bank to fill
  522.         mov     dh,dl               ; DH := number of full banks to fill
  523.  
  524.         mov     ax,VGABufferSeg
  525.         mov     es,ax
  526.         mov     di,[OriginOffset]   ; ES:DI -> video buffer
  527.         mov     dl,[BYTE BankOffset]; DL := starting bank number
  528.         cld                         ; Moves go up in memory
  529.  
  530. ; Fill all of the full 64k banks first
  531.  
  532. @@OuterLoop:
  533.         mov     al,dl
  534.         call    setBank
  535.         xor     eax,eax             ; Clear to black
  536.         mov     cx,4000h            ; Need to set 4000h double words per bank
  537.     rep stosd
  538.         inc     dl
  539.         dec     dh
  540.         jnz     @@OuterLoop
  541.  
  542. ; Now fill the last partial bank
  543.  
  544.         mov     al,dl
  545.         call    setBank
  546.         xor     eax,eax             ; Clear to black
  547.         mov     cx,bx
  548.         shr     cx,2                ; CX := number of double words to set
  549.     rep stosd
  550.  
  551.         pop     di
  552.         ret
  553.  
  554. procend     __clear64k
  555.  
  556. ;----------------------------------------------------------------------------
  557. ; void clear16m(void)
  558. ;----------------------------------------------------------------------------
  559. ; Routine to clear the screen. Assumes pages begin on bank boundaries
  560. ; for simplicity of coding.
  561. ;----------------------------------------------------------------------------
  562. procstart   __clear16m
  563.  
  564.         push    di
  565.         mov     ax,[_maxy]
  566.         inc     ax
  567.         mul     [_bytesperline]     ; DX:AX := number of bytes to fill
  568.         mov     bx,ax               ; BX := bytes in last bank to fill
  569.         mov     dh,dl               ; DH := number of full banks to fill
  570.  
  571.         mov     ax,VGABufferSeg
  572.         mov     es,ax
  573.         xor     di,di               ; ES:DI -> video buffer
  574.         mov     dl,[BYTE BankOffset]; DL := starting bank number
  575.         cld                         ; Moves go up in memory
  576.  
  577. ; Fill all of the full 64k banks first
  578.  
  579. @@OuterLoop:
  580.         mov     al,dl
  581.         call    setBank
  582.         xor     eax,eax             ; Clear to black
  583.         mov     cx,4000h            ; Need to set 4000h double words per bank
  584.     rep stosd
  585.         inc     dl
  586.         dec     dh
  587.         jnz     @@OuterLoop
  588.  
  589. ; Now fill the last partial bank
  590.  
  591.         mov     al,dl
  592.         call    setBank
  593.         xor     eax,eax             ; Clear to black
  594.         mov     cx,bx
  595.         shr     cx,2                ; CX := number of double words to set
  596.     rep stosd
  597.  
  598.         pop     di
  599.         ret
  600.  
  601. procend     __clear16m
  602.  
  603. ;----------------------------------------------------------------------------
  604. ; void _copyTest16(void)
  605. ;----------------------------------------------------------------------------
  606. ; Routine to copy the top half of video memory to the bottom half of
  607. ; video memory. To ensure that we a moving across a bank boundary in
  608. ; 16 color modes, we copy the data to the second video page.
  609. ;----------------------------------------------------------------------------
  610. procstart   __copyTest16
  611.  
  612.         push    si                  ; Save registers
  613.         push    di
  614.         push    ds
  615.  
  616.         mov     ax,[_maxy]
  617.         inc     ax
  618.         shr     ax,1                ; AX := (Yres+1) / 2
  619.         mul     [_bytesperline]
  620.         mov     cx,ax               ; CX := Number of bytes to move
  621.  
  622. ; Set up graphics controller
  623.  
  624.         mov     dx,3CEh             ; DX := Graphics Controller address port
  625.         mov     ax,0105h            ; AH := 1 (read mode 0, write mode 1)
  626.                                     ; AL := 5 (Mode register number)
  627.         out     dx,ax               ; Set up mode
  628.  
  629.         mov     di,[WORD _pagesize] ; ES:DI := offset into destination buffer
  630.         mov     ax,[WORD _pagesize+2]
  631.         add     di,cx
  632.         adc     al,0
  633.         call    setBank             ; Set the read/write bank number
  634.  
  635.         xor     si,si               ; DS:SI := offset into source buffer
  636.         xor     ax,ax
  637.         call    setReadBank         ; Set the read bank number
  638.  
  639.         mov     ax,VGABufferSeg
  640.         mov     ds,ax               ; DS:SI -> source buffer
  641.         mov     es,ax               ; ES:DI -> destination buffer
  642.         cld                         ; Moves go up in memory
  643.  
  644.     rep movsb                       ; Move all data in bank FAST!
  645.  
  646. ; Restore default graphics controller state
  647.  
  648.         mov     ax,0005h            ; default mode register value
  649.         out     dx,ax
  650.  
  651.         pop     ds
  652.         pop     di
  653.         pop     si
  654.         ret
  655.  
  656. procend     __copyTest16
  657.  
  658. ;----------------------------------------------------------------------------
  659. ; void _copyTest256(void)
  660. ;----------------------------------------------------------------------------
  661. ; Routine to copy the top half of video memory to the bottom half of
  662. ; video memory, to test moving data across bank boundaries using separate
  663. ; read/write banks. To simplify the coding we move the first 100 scan
  664. ; lines down to start at scanline 205. This ensure allows us to move data
  665. ; from bank 0 to bank 2 in 640x??? display modes.
  666. ;----------------------------------------------------------------------------
  667. procstart   __copyTest256
  668.  
  669.         push    si                  ; Save registers
  670.         push    di
  671.         push    ds
  672.  
  673.         mov     ax,100
  674.         mul     [_bytesperline]
  675.         mov     cx,ax               ; CX := Number of bytes to move
  676.         shr     cx,1                ; CX := Number of words to move
  677.  
  678.         mov     ax,205
  679.         mul     [_bytesperline]
  680.         mov     di,ax               ; DI := offset into destination bank
  681.         mov     al,dl
  682.         call    setBank             ; Set the read/write bank number
  683.  
  684.         xor     si,si               ; DS:SI := offset into source buffer
  685.         xor     al,al
  686.         call    setReadBank         ; Set the read bank number
  687.  
  688.         mov     ax,VGABufferSeg
  689.         mov     ds,ax               ; DS:SI -> source buffer
  690.         mov     es,ax               ; ES:DI -> destination buffer
  691.         cld                         ; Moves go up in memory
  692.  
  693.     rep movsw                       ; Move all data in bank FAST!
  694.  
  695.         pop     ds
  696.         pop     di
  697.         pop     si
  698.         ret
  699.  
  700. procend     __copyTest256
  701.  
  702. ;----------------------------------------------------------------------------
  703. ; void setActivePage(int which)
  704. ;----------------------------------------------------------------------------
  705. ; Routine to set the video page for active output.
  706. ;
  707. ; Entry:        page    - Page number of page to use
  708. ;
  709. ;----------------------------------------------------------------------------
  710. procstart   _setActivePage
  711.  
  712.         ARG     which:WORD
  713.  
  714.         push    bp                  ; Set up stack frame
  715.         mov     bp,sp
  716.  
  717. ; Calculate 18 bit address of page in video memory
  718.  
  719.         xor     eax,eax
  720.         mov     ax,[which]          ; EAX := page number
  721.         mul     [_pagesize]         ; EDX:EAX := result
  722.         mov     [OriginOffset],ax   ; Save video buffer offset
  723.         shr     eax,16
  724.         mov     [BankOffset],ax     ; Save video bank offset
  725.  
  726.         pop     bp
  727.         ret
  728.  
  729. procend     _setActivePage
  730.  
  731. ;----------------------------------------------------------------------------
  732. ; void setVisualPage(int which)
  733. ;----------------------------------------------------------------------------
  734. ; Routine to set the visible video page.
  735. ;
  736. ; Entry:        page    - Page number of page to use
  737. ;
  738. ;----------------------------------------------------------------------------
  739. procstart       _setVisualPage
  740.  
  741.         ARG     which:WORD
  742.  
  743.         push    bp                  ; Set up stack frame
  744.         mov     bp,sp
  745.         push    si
  746.  
  747. ; Calculate 18 bit address of page in video memory
  748.  
  749.         xor     eax,eax
  750.         mov     ax,[which]          ; EAX := page number
  751.         mul     [_pagesize]         ; EAX := starting address in memory
  752.         mov     edx,eax
  753.         shr     edx,16              ; DX:AX := starting address in memory
  754.  
  755.         cmp     [_extendedflipping],0
  756.         je      @@VGAFlip           ; We have no extended page flipping
  757.  
  758.         cmp     [WORD _pageFlip+2],0
  759.         je      @@VBEFlip
  760.  
  761. ; Set up to call the relocated version of the page flip routine loaded
  762. ; on the heap. This allows us to bypass the int10h interface for speed
  763. ; (well, not much different in real mode, but in protected mode this
  764. ; will be significant).
  765.  
  766.         cmp     [WORD _maxColor],15
  767.         je      @@Colors16
  768.         shr     eax,2               ; Adjust to lie on plane boundary
  769.         mov     edx,eax
  770.         shr     edx,16              ; DX:AX := starting address in memory
  771.  
  772. @@Colors16:
  773.         push    dx                  ; Save top bits of address
  774.  
  775. ; Wait for display enable to be active (active low), to be sure that
  776. ; both halves of the start address will take place in one frame. We
  777. ; preload a few values here to save time after the DE has been
  778. ; detected.
  779.  
  780.         mov     cl,0Ch              ; CL := Start Address High register
  781.         mov     ch,ah               ; CH := high byte of new address
  782.         mov     bh,al               ; BH := low byte of new address
  783.         mov     bl,0Dh              ; BL := Start Address Low register
  784.         mov     dx,03DAh            ; DX := video status port
  785.  
  786. @@WaitDE:
  787.         in      al,dx
  788.         test    al,1
  789.         jnz     @@WaitDE            ; Wait for Display Enable
  790.  
  791.         cli
  792.         pop     si                  ; SI := Bits 16+ for SuperVGA's
  793.         call    [_pageFlip]         ; Program the start address
  794.         sti
  795.         jmp     @@Done
  796.  
  797. @@VBEFlip:
  798.         div     [_bytesperline]     ; AX := starting scanline,
  799.                                     ; DX := starting byte
  800.         mov     cx,dx
  801.         cmp     [WORD _maxcolor],0Fh
  802.         je      @@16Color
  803.         cmp     [WORD _maxcolor],0FFh
  804.         je      @@SetIt
  805.         cmp     [WORD _maxcolor+2],0FFh
  806.         je      @@16MColor
  807.  
  808.         shr     cx,1                ; CX := starting pixel in buffer
  809.         jmp     @@SetIt
  810.  
  811. @@16Color:
  812.         shl     cx,3                ; CX := starting pixel in buffer
  813.         jmp     @@SetIt
  814.  
  815. @@16MColor:
  816.         xor     dx,dx
  817.         mov     ax,cx
  818.         mov     cx,3
  819.         div     cx
  820.         mov     cx,ax               ; CX := starting pixel in buffer
  821.  
  822. @@SetIt:
  823.         mov     bx,ax               ; BX := starting scanline in buffer
  824.  
  825. ; Wait for display enable to be active (active low), to be sure that
  826. ; both halves of the start address will take place in one frame.
  827.  
  828.         mov     dx,03DAh            ; DX := video status port
  829.  
  830. @@WaitDEVBE:
  831.         in      al,dx
  832.         test    al,1
  833.         jnz     @@WaitDEVBE         ; Wait for Display Enable
  834.  
  835.         mov     ax,04F07h
  836.         mov     dx,bx               ; DX := starting scanline number
  837.         xor     bx,bx               ; BX := 0 - set display start
  838.         int     10h                 ; Set the display start address
  839.         jmp     @@Done
  840.  
  841. @@VGAFlip:
  842.         mov     bx,ax               ; BX := bottom 16 bits of address
  843.  
  844.  
  845. ; Wait for display enable to be active (active low), to be sure that
  846. ; both halves of the start address will take place in one frame. We
  847. ; preload a few values here to save time after the DE has been
  848. ; detected.
  849.  
  850.         mov     cl,0Ch              ; CL := Start Address High register
  851.         mov     ch,bh               ; CH := high byte of new address
  852.         mov     bh,bl               ; BH := low byte of new address
  853.         mov     bl,0Dh              ; BL := Start Address Low register
  854.         mov     dx,03DAh            ; DX := video status port
  855.  
  856. @@WaitDEVGA:
  857.         in      al,dx
  858.         test    al,1
  859.         jnz     @@WaitDEVGA         ; Wait for Display Enable
  860.  
  861.         cli
  862.         mov     dx,03D4h            ; DX := CRTC I/O port (3D4h)
  863.         mov     ax,bx
  864.         out     dx,ax
  865.         mov     ax,cx
  866.         out     dx,ax
  867.         sti
  868.  
  869. ; Now wait for the start of the vertical sync, to ensure that the old
  870. ; page will be invisible before anything is drawn on it.
  871.  
  872. @@Done:
  873.         mov     dx,03DAh            ; DX := video status port
  874. @@WaitStartVert:
  875.         in      al,dx               ; Wait for start of vertical retrace
  876.         test    al,8
  877.         jz      @@WaitStartVert
  878.  
  879. @@Exit:
  880.         pop     si
  881.         pop     bp
  882.         ret
  883.  
  884. procend     _setVisualPage
  885.  
  886. ;----------------------------------------------------------------------------
  887. ; setBank   Sets the read/write bank from assembly language
  888. ;----------------------------------------------------------------------------
  889. ;
  890. ; Entry:        AX  - New read/write bank number
  891. ;
  892. ; Exit:         AX  - New read/write bank number
  893. ;
  894. ; Registers:    All preserved!
  895. ;
  896. ;----------------------------------------------------------------------------
  897. procstart   setBank
  898.  
  899.         mov     [_curBank],ax       ; Save current write bank number
  900.         cmp     [WORD _writeBank+2],0
  901.         je      @@VESABank
  902.         call    [_writeBank]        ; Call relocated version
  903.         ret
  904.  
  905. @@VESABank:
  906.         push    ax
  907.         push    bx
  908.         push    dx
  909.         mul     [_bankAdjust]       ; Adjust to VESA granularity
  910.         push    ax
  911.         mov     dx,ax               ; DX := bank number
  912.         xor     bx,bx               ; BX := select window A
  913.         call    [_bankSwitch]       ; Set write window
  914.  
  915. ; Note that some VESA BIOSes and TSR's set the first window to be
  916. ; write only and the second window to be read only, so we need to set both
  917. ; windows for most common operations to the same value. The Universal
  918. ; VESA VBE sets both the read and write banks to the same value for
  919. ; Window A, and changed the read bank only for Window B, hence the second
  920. ; call is _not_ required when the Universal VESA VBE is installed. You can
  921. ; determine what the window does by looking at the WindowAAttributes in
  922. ; the SuperVGAInfo block returned by function 00h. You could use this
  923. ; information to optimise bank switching when using faster VBE's like
  924. ; the Universal VESA VBE (but I have no bothered to do that here).
  925.  
  926.         pop     dx
  927.         inc     bx
  928.         call    [_bankSwitch]       ; Set read window
  929.         pop     dx
  930.         pop     bx
  931.         pop     ax
  932.         ret
  933.  
  934. procend     setBank
  935.  
  936. ;----------------------------------------------------------------------------
  937. ; setReadBank   Sets the read bank from assembly language
  938. ;----------------------------------------------------------------------------
  939. ;
  940. ; Entry:        AX  - New read bank number
  941. ;
  942. ; Exit:         AX  - New read bank number
  943. ;
  944. ; Registers:    All preserved!
  945. ;
  946. ;----------------------------------------------------------------------------
  947. procstart   setReadBank
  948.  
  949.         mov     [_curBank],-1       ; Ensure banking will be re-loaded
  950.         cmp     [WORD _readBank+2],0
  951.         je      @@VESABank
  952.         call    [_readBank]         ; Call relocated version
  953.         ret
  954.  
  955. @@VESABank:
  956.         push    ax
  957.         push    bx
  958.         push    dx
  959.         mov     dx,ax               ; DX := bank number
  960.         mov     bx,1                ; BX := select window B
  961.         call    [_bankSwitch]
  962.         pop     dx
  963.         pop     bx
  964.         pop     ax
  965.         ret
  966.  
  967. procend     setReadBank
  968.  
  969. ;----------------------------------------------------------------------------
  970. ; void setBank(int bank)
  971. ;----------------------------------------------------------------------------
  972. ; Sets the new read/write bank number from C
  973. ;----------------------------------------------------------------------------
  974. procstart   _setBank
  975.  
  976.         ARG     bank:WORD
  977.  
  978.         push    bp
  979.         mov     bp,sp
  980.         mov     ax,[bank]
  981.         call    setBank
  982.         pop     bp
  983.         ret
  984.  
  985. procend     _setBank
  986.  
  987. ;----------------------------------------------------------------------------
  988. ; void setReadBank(int bank)
  989. ;----------------------------------------------------------------------------
  990. ; Sets the new reading bank number from C
  991. ;----------------------------------------------------------------------------
  992. procstart   _setReadBank
  993.  
  994.         ARG     bank:WORD
  995.  
  996.         push    bp
  997.         mov     bp,sp
  998.         mov     ax,[bank]
  999.         call    setReadBank
  1000.         pop     bp
  1001.         ret
  1002.  
  1003. procend     _setReadBank
  1004.  
  1005. ;----------------------------------------------------------------------------
  1006. ; void *getFontVec(void)
  1007. ;----------------------------------------------------------------------------
  1008. ; Gets a pointer to the currently installed bitmap font from the BIOS.
  1009. ;----------------------------------------------------------------------------
  1010. procstart   _getFontVec
  1011.  
  1012.         push    bp
  1013.         mov     ax,1130h
  1014.         mov     bx,0600h
  1015.         int     10h
  1016.         mov     dx,es
  1017.         mov     ax,bp               ; DX:AX -> installed font
  1018.         pop     bp
  1019.         ret
  1020.  
  1021. procend     _getFontVec
  1022.  
  1023.         END
  1024.