home *** CD-ROM | disk | FTP | other *** search
/ World of Graphics / WOGRAPH.BIN / 433.SVGA16M.ASM < prev    next >
Assembly Source File  |  1993-03-07  |  16KB  |  584 lines

  1. ;****************************************************************************
  2. ;*
  3. ;*                           SuperVGA Test Library
  4. ;*
  5. ;*                  Copyright (C) 1993 Kendall Bennett.
  6. ;*                            All rights reserved.
  7. ;*
  8. ;* Filename:    $RCSfile: svga16m.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 16m color modes.
  19. ;*
  20. ;* $Id: svga16m.asm 1.2 1993/03/07 04:05:36 kjb Exp $
  21. ;*
  22. ;* Revision History:
  23. ;* -----------------
  24. ;*
  25. ;* $Log: svga16m.asm $
  26. ;* Revision 1.2  1993/03/07  04:05:36  kjb
  27. ;* Bug fixes.
  28. ;*
  29. ;* Revision 1.1  1993/03/03  10:26:06  kjb
  30. ;* Initial revision
  31. ;*
  32. ;****************************************************************************
  33.  
  34.         IDEAL
  35.         JUMPS
  36.         P386                    ; Use 80386 instructions
  37.  
  38. INCLUDE "model.mac"                ; Memory model macros
  39.  
  40. header        init
  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    grSVGA_320x200x16m
  47. MAXMODE            EQU    grSVGA_1280x1024x16m
  48.  
  49. begcodeseg    svga16m
  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    gr16MColor    ; This is a 16 million 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. ModeSVGA_320x200:    dw    319            ; XRes
  80.                     dw    199            ; YRes
  81.                     dw    960            ; BytesPerLine
  82. ModeSVGA_640x350:    dw    639            ; XRes
  83.                     dw    349            ; YRes
  84.                     dw    2048        ; BytesPerLine
  85. ModeSVGA_640x400:    dw    639            ; XRes
  86.                     dw    399            ; YRes
  87.                     dw    2048        ; BytesPerLine
  88. ModeSVGA_640x480:    dw    639            ; XRes
  89.                     dw    479            ; YRes
  90.                     dw    2048        ; BytesPerLine
  91. ModeSVGA_800x600:    dw    799            ; XRes
  92.                     dw    599            ; YRes
  93.                     dw    2400        ; BytesPerLine
  94. ModeSVGA_1024x768:    dw    1023        ; XRes
  95.                     dw    767            ; YRes
  96.                     dw    3072        ; BytesPerLine
  97. ModeSVGA_1280x1024:    dw    1279        ; XRes
  98.                     dw    1023        ; YRes
  99.                     dw    3840        ; BytesPerLine
  100. ModeTabSize            =    ($-ModeSVGA_1280x1024)    ; Size of table in bytes
  101.  
  102. INCLUDE "SV_PORTS.ASM"
  103. INCLUDE "SV_BANKS.ASM"
  104. INCLUDE "SV_MODES.ASM"
  105. INCLUDE "SV_PAGE.ASM"
  106. INCLUDE "SV_MAXPG.ASM"
  107.  
  108. ;----------------------------------------------------------------------------
  109. ; int _initSuperVGA(int driver,int chipID,int mode,int memory)
  110. ;----------------------------------------------------------------------------
  111. ; Routine to initialise the bank switching code for the SuperVGA, and setup
  112. ; internal tables of information about the video mode. If the video mode
  113. ; is not supported, we return -1.
  114. ;
  115. ; The value returned is a status number, where bit 0 represents extended
  116. ; page flipping is available, bit 1 that separate read/write banks are
  117. ; available.
  118. ;----------------------------------------------------------------------------
  119. procstart    __initSuperVGA
  120.  
  121.         ARG        driver:WORD, ChipID:WORD, mode:WORD, memory:WORD
  122.  
  123.         enter    0,0
  124.         push    si
  125.         push    di
  126.  
  127. ; Save the driver number and chip ID for later
  128.  
  129.         mov        ax,[ChipID]
  130.         mov        [CntChipID],ax
  131.         mov        ax,[driver]
  132.         mov        [CntDriver],ax
  133.  
  134. ; Load the Status area with info for the currently selected mode:
  135.  
  136.         mov        ax,[mode]
  137.         mov        [CntMode],ax
  138.         cmp        ax,MAXMODE            ; AX := desired mode
  139.         jg        @@Invalid            ; invalid if greater than maximum
  140.         cmp        ax,FIRSTMODE
  141.         jl        @@Invalid            ; invalid if less than first mode
  142.  
  143.         mov        cx,ModeTabSize        ; Put size of table into cx
  144.         sub        ax,FIRSTMODE
  145.         mul        cl                    ; AX := Mode * ModeTabSize
  146.         mov        si,ax
  147.         lea        si,[ModeTabStart + si]
  148.         push    cs
  149.         pop        es                    ; Set up es to point to code seg
  150.         lea        di,[StatusArea]        ; DI := Start of status area
  151.  
  152.         cld
  153.     rep    movs     [BYTE es:di],[BYTE es:si]
  154.  
  155.         mov        ax,[driver]
  156.         mov        bx,[mode]
  157.         call    loadSVGAMode        ; Load the SuperVGA video mode
  158.         or        ax,ax
  159.         jz        @@Invalid            ; Mode not supported on this adapter!
  160.  
  161.         mov        [maxpage],0            ; Clear maxpage variable
  162.         call    SetupBanks            ; Setup SuperVGA bank switching
  163.         call    [InitSVGA]            ; Setup bank switching code
  164.         call    SetupPaging            ; Setup SuperVGA page flipping
  165.         mov        ax,0                ; Assume no paging available
  166.         jc        @@Done                ; Extended page flipping not available
  167.  
  168. ; Determine the number of pages available for the mode and the video page
  169. ; size.
  170.  
  171.         xor        ebx,ebx
  172.         mov        bx,[memory]
  173.         shl        ebx,10                ; EBX := video memory in bytes
  174.         mov        ax,[mode]
  175.         call    numPages            ; Calculate the number of video pages
  176.         dec        ax
  177.         mov        [MaxPage],ax        ; Save maximum page number
  178.         mov        [DWORD pageSize],ebx
  179.         mov        [WORD bytesPerLine],cx
  180.         mov        ax,1                ; Extended paging is available
  181.  
  182. @@Done:
  183.         mov        bx,[TwoBanks]
  184.         shl        bx,1
  185.         or        ax,bx                ; Set the two banks flag
  186.         jmp        @@Exit
  187.  
  188. @@Invalid:
  189.         mov        ax,-1                ; Return failure!
  190.  
  191. @@Exit:
  192.         pop        di
  193.         pop        si
  194.         leave
  195.         ret
  196.  
  197. procend        __initSuperVGA
  198.  
  199. ;----------------------------------------------------------------------------
  200. ; int _setSuperVGAMode(void);
  201. ;----------------------------------------------------------------------------
  202. ; Routine sets the system into the SuperVGA graphics mode setup by the
  203. ; initSuperVGA routine. Note that this routine remembers if the EGA/VGA
  204. ; 43/50 line mode was set.
  205. ;
  206. ; If the video mode was not correctly set, we return false.
  207. ;----------------------------------------------------------------------------
  208. procstart    __setSuperVGAMode
  209.  
  210.         push    bp                    ; INT 10h Kills this!!!
  211.         push    si                    ; so save all regs...
  212.         push    di
  213.         push    ds
  214.  
  215.         mov        ah,0Fh                ; Get current video mode service
  216.         int        10h
  217.         mov        [OldBIOSMode],al    ; Save old video mode
  218.         mov        [Old50Lines],0        ; Default to non-50 line mode
  219.  
  220.         mov        ax,1130h            ; AH := INT 10h function number
  221.                                     ; AL := Get character gen information
  222.         mov        bh,00                ; Get contents of INT 1Fh
  223.         xor        dl,dl                ; Clear dl
  224.         int        10h                    ; Determine number of lines (in dl)
  225.         cmp        dl,49                ; 50 line mode?
  226.         jne        @@SetMode            ; No, must have been 25 lines
  227.         mov        [Old50Lines],1        ; Yes, 50 line mode was on
  228.  
  229. @@SetMode:
  230.         mov        ax,[CntDriver]
  231.         mov        bx,[CntMode]
  232.         call    loadSVGAMode        ; AX,BX := correct values for mode
  233.         int        10h                    ; Set the video mode
  234.  
  235.         mov        ax,40h
  236.         mov        es,ax
  237.         xor        ax,ax
  238.         cmp        [BYTE es:49h],3        ; Mode is still text mode, did not set
  239.         jbe        @@Exit
  240.  
  241.         call    [InitSVGA]            ; Initialise bank switching on SuperVGA's
  242.         mov        ax,1                ; Mode was correctly set
  243.  
  244. @@Exit:
  245.         pop        ds
  246.         pop        di                    ; Restore regs
  247.         pop        si
  248.         pop        bp                    ; Restore bp (after INT 10 trashes it)
  249.         ret
  250.  
  251. procend        __setSuperVGAMode
  252.  
  253. ;----------------------------------------------------------------------------
  254. ; void restoreMode(void)
  255. ;----------------------------------------------------------------------------
  256. ; Routine restores the original video mode that was set before graphics mode
  257. ; was entered.
  258. ;----------------------------------------------------------------------------
  259. procstart    _restoreMode
  260.  
  261.         push    bp                    ; INT 10h kills bp sometimes
  262.         push    si                    ; Save all regs...
  263.         push    di
  264.  
  265.         call    [ExitSVGA]            ; Uninitialise the SuperVGA
  266.  
  267.         mov        ah,0                ; Set video mode service
  268.         mov        al,[OldBIOSMode]    ; Get old BIOS mode number
  269.         int        10h                    ; Set the video mode
  270.  
  271.         cmp        [Old50Lines],0        ; Was 50 line mode set?
  272.         je        @@Exit                ; No, don't set it up
  273.  
  274. ; Load video BIOS 8x8 characters into alphanumeric character generator
  275.  
  276.         mov        ax,1112h            ; AH := INT 10h function number
  277.                                     ; AL := 8x8 character set load
  278.         mov        bl,0                ; BL := block to load
  279.         int        10h                    ; load 8x8 characters into RAM
  280.  
  281. @@Exit:
  282.         pop        di                    ; Restore regs
  283.         pop        si
  284.         pop        bp                    ; Restore bp
  285.         ret
  286.  
  287. procend        _restoreMode
  288.  
  289. ;----------------------------------------------------------------------------
  290. ; void _getVideoInfo(int *xres,int *yres,int *bytesperline,int *maxpage)
  291. ;----------------------------------------------------------------------------
  292. ; Returns information about the currently selected video mode. The video
  293. ; mode must have been set for this info to be entirely valid.
  294. ;----------------------------------------------------------------------------
  295. procstart    __getVideoInfo
  296.  
  297.         ARG        _xres:DWORD, _yres:DWORD, _bytesperline:DWORD, _maxpage:DWORD
  298.  
  299.         enter    0,0
  300.  
  301.         les        bx,[_xres]
  302.         mov        ax,[xres]
  303.         mov        [es:bx],ax        ; Return the x resolution
  304.  
  305.         les        bx,[_yres]
  306.         mov        ax,[yres]
  307.         mov        [es:bx],ax        ; Return the y resolution
  308.  
  309.         les        bx,[_bytesperline]
  310.         mov        ax,[bytesperline]
  311.         mov        [es:bx],ax        ; Return the bytes per line value
  312.  
  313.         les        bx,[_maxpage]
  314.         mov        ax,[maxpage]
  315.         mov        [es:bx],ax        ; Return the maximum page number
  316.  
  317.         leave
  318.         ret
  319.  
  320. procend        __getVideoInfo
  321.  
  322. ;----------------------------------------------------------------------------
  323. ; void putPixel(int x,int y,long color)
  324. ;----------------------------------------------------------------------------
  325. ; Routine sets the value of a pixel in native VGA graphics modes.
  326. ;
  327. ; Entry:        x        -    X coordinate of pixel to draw
  328. ;                y        -    Y coordinate of pixel to draw
  329. ;                color    -    Color of pixel to draw
  330. ;
  331. ;----------------------------------------------------------------------------
  332. procstart    _putPixel
  333.  
  334.         ARG        x:WORD, y:WORD, color:DWORD
  335.  
  336.         push    bp                    ; Set up stack frame
  337.         mov        bp,sp
  338.  
  339.         mov        ax,[y]
  340.         mul        [BytesPerLine]
  341.         mov        bx,[x]
  342.         add        ax,bx
  343.         adc        dx,0
  344.         shl        bx,1
  345.         add        ax,bx
  346.         adc        dx,0                ; DX:AX := y * BytesPerLine + x * 3
  347.         add        ax,[OriginOffset]
  348.         adc        dl,[BYTE BankOffset]; DL := bank number
  349.         mov        bx,ax                ; BX := Offset in buffer
  350.         cmp        dl,[BYTE CurBank]
  351.         je        @@NoChange
  352.         mov        al,dl
  353.         call    [NewBank]
  354.  
  355. @@NoChange:
  356.         mov        ax,VGABufferSeg
  357.         mov        es,ax                ; ES:BX := byte address of pixel
  358.         mov        al,[BYTE color]
  359.         mov        [es:bx],al             ; Replace the first byte
  360.         cmp        bx,0FFFFh
  361.         jne        @@NotSplit1
  362.  
  363. ; Arrghh!! We have a case where a single pixel can be split across a
  364. ; bank boundary, if the bytes per line value is 1920. This can cause the
  365. ; machine to hang (and produce strange pixels).
  366.  
  367.         inc        dl
  368.         mov        al,dl
  369.         call    [NewBank]            ; Change video banks
  370.  
  371. @@NotSplit1:
  372.         mov        al,[BYTE color+1]
  373.         mov        [es:bx+1],al        ; Replace the middle
  374.         cmp        bx,0FFFEh
  375.         jne        @@NotSplit2
  376.  
  377.         inc        dl
  378.         mov        al,dl
  379.         call    [NewBank]            ; Change video banks
  380.  
  381. @@NotSplit2:
  382.         mov        al,[BYTE color+2]
  383.         mov        [es:bx+2],al        ; Replace the last byte
  384.         pop        bp
  385.         ret
  386.  
  387. procend        _putPixel
  388.  
  389. ;----------------------------------------------------------------------------
  390. ; void clear(void)
  391. ;----------------------------------------------------------------------------
  392. ; Routine to clear the screen. Assumes pages begin on bank boundaries
  393. ; for simplicity of coding.
  394. ;----------------------------------------------------------------------------
  395. procstart    _clear
  396.  
  397.         push    di
  398.         mov        ax,[YRes]
  399.         inc        ax
  400.         mul        [BytesPerLine]        ; DX:AX := number of bytes to fill
  401.         mov        bx,ax                ; BX := bytes in last bank to fill
  402.         mov        dh,dl                ; DH := number of full banks to fill
  403.  
  404.         mov        ax,VGABufferSeg
  405.         mov        es,ax
  406.         xor        di,di                ; ES:DI -> video buffer
  407.         mov        dl,[BYTE BankOffset]; DL := starting bank number
  408.         cld                            ; Moves go up in memory
  409.  
  410. ; Fill all of the full 64k banks first
  411.  
  412. @@OuterLoop:
  413.         mov        al,dl
  414.         call    [NewBank]
  415.         xor        eax,eax                ; Clear to black
  416.         mov        cx,4000h            ; Need to set 4000h double words per bank
  417.     rep    stosd
  418.         inc        dl
  419.         dec        dh
  420.         jnz        @@OuterLoop
  421.  
  422. ; Now fill the last partial bank
  423.  
  424.         mov        al,dl
  425.         call    [NewBank]
  426.         xor        eax,eax                ; Clear to black
  427.         mov        cx,bx
  428.         shr        cx,2                ; CX := number of double words to set
  429.     rep    stosd
  430.  
  431.         pop        di
  432.         ret
  433.  
  434. procend        _clear
  435.  
  436. ;----------------------------------------------------------------------------
  437. ; void setActivePage(int which)
  438. ;----------------------------------------------------------------------------
  439. ; Routine to set the video page for active output.
  440. ;
  441. ; Entry:        page    - Page number of page to use
  442. ;
  443. ;----------------------------------------------------------------------------
  444. procstart    _setActivePage
  445.  
  446.         ARG        which:WORD
  447.  
  448.         push    bp                    ; Set up stack frame
  449.         mov        bp,sp
  450.  
  451. ; Calculate 18 bit address of page in video memory
  452.  
  453.         xor        eax,eax
  454.         mov        ax,[which]            ; EAX := page number
  455.         mul        [PageSize]            ; EDX:EAX := result
  456.         mov        [OriginOffset],ax    ; Save video buffer offset
  457.         shr        eax,16
  458.         mov        [BankOffset],ax        ; Save video bank offset
  459.  
  460.         pop        bp
  461.         ret
  462.  
  463. procend        _setActivePage
  464.  
  465. ;----------------------------------------------------------------------------
  466. ; void setVisualPage(int which)
  467. ;----------------------------------------------------------------------------
  468. ; Routine to set the visible video page.
  469. ;
  470. ; Entry:        page    - Page number of page to use
  471. ;
  472. ;----------------------------------------------------------------------------
  473. procstart    _setVisualPage
  474.  
  475.         ARG        which:WORD
  476.  
  477.         push    bp                    ; Set up stack frame
  478.         mov        bp,sp
  479.         push    si
  480.  
  481. ; Calculate 18 bit address of page in video memory
  482.  
  483.         xor        eax,eax
  484.         mov        ax,[which]            ; EAX := page number
  485.         mul        [PageSize]            ; EDX:EAX := result
  486.         cmp        [CntDriver],grSVGA
  487.         je        @@HaveVESA
  488.  
  489. ; For Non-VESA SuperVGA's we need to shift the page offset right 2 bits
  490. ; for 32k color video modes, so that the origin is located on a
  491. ; plane boundary.
  492.  
  493.         shr        eax,2
  494.  
  495. @@HaveVESA:
  496.         mov        bx,ax                ; BX := bottom 16 bits of address
  497.         shr        eax,16
  498.         push    ax                    ; Save top 2 bits of address
  499.  
  500. ; Wait for display enable to be active (active low), to be sure that
  501. ; both halves of the start address will take place in one frame. We
  502. ; preload a few values here to save time after the DE has been
  503. ; detected.
  504.  
  505.         mov        cl,0Ch                ; CL := Start Address High register
  506.         mov        ch,bh                ; CH := high byte of new address
  507.         mov        bh,bl                ; BH := low byte of new address
  508.         mov        bl,0Dh                ; BL := Start Address Low register
  509.         mov        dx,03DAh            ; DX := video status port
  510.  
  511. @@WaitDE:
  512.         in        al,dx
  513.         test    al,1
  514.         jnz        @@WaitDE            ; Wait for Display Enable
  515.  
  516.         cli
  517.         pop        si                    ; SI := Bits 16+ for SuperVGA's
  518.         call    [NewPage]            ; Program the start address
  519.         sti
  520.  
  521. ; Now wait for the start of the vertical sync, to ensure that the old
  522. ; page will be invisible before anything is drawn on it.
  523.  
  524.         mov        dx,03DAh            ; DX := video status port
  525. @@WaitStartVert:
  526.         in        al,dx                ; Wait for start of vertical retrace
  527.         test    al,8
  528.         jz        @@WaitStartVert
  529.  
  530. @@Exit:
  531.         pop        si
  532.         pop        bp
  533.         ret
  534.  
  535. procend        _setVisualPage
  536.  
  537. ;----------------------------------------------------------------------------
  538. ; void setBank(int bank)
  539. ;----------------------------------------------------------------------------
  540. ; Sets the current read and write bank to the specified 64k bank number.
  541. ;----------------------------------------------------------------------------
  542. procstart    _setBank
  543.  
  544.         ARG        bank:WORD
  545.  
  546.         enter    0,0
  547.  
  548.         mov        al,[BYTE bank]
  549.         cmp        al,[BYTE CurBank]
  550.         je        @@NoChange
  551.  
  552.         call    [NewBank]
  553.  
  554. @@NoChange:
  555.         leave
  556.         ret
  557.  
  558. procend        _setBank
  559.  
  560. ;----------------------------------------------------------------------------
  561. ; void setReadBank(int bank)
  562. ;----------------------------------------------------------------------------
  563. ; Sets the current read bank to the specified 64k bank. If you wish to set
  564. ; the read and write banks separately, call setBank() first, followed by
  565. ; setReadBank().
  566. ;----------------------------------------------------------------------------
  567. procstart    _setReadBank
  568.  
  569.         ARG        bank:WORD
  570.  
  571.         enter    0,0
  572.  
  573.         mov        al,[BYTE bank]
  574.         call    [ReadBank]
  575.  
  576.         leave
  577.         ret
  578.  
  579. procend        _setReadBank
  580.  
  581. endcodeseg    svga16m
  582.  
  583.         END
  584.