home *** CD-ROM | disk | FTP | other *** search
/ World of Graphics / WOGRAPH.BIN / 431.SVGA256.ASM < prev    next >
Assembly Source File  |  1993-03-07  |  17KB  |  614 lines

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