;=========================================================================== ; File: L4SVGA16.asm ; Project: MUNGA ; Contents: SVGA 16-bit buffered graphics operations ;--------------------------------------------------------------------------- ; Date Who Modification ; -------- --- ----------------------------------------------------------- ; 03/08/95 CPB Initial coding (started from VGAbuf8.asm) ;--------------------------------------------------------------------------- ; Copyright (C) 1995, Virtual World Entertainment, Inc. ; All Rights reserved worldwide ; This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL ;=========================================================================== include l4asm.inc include pcdpmi.inc ;=========================================================================== ; Equates ;=========================================================================== ;-------------------------------------------------------------- ; VGA CRTC registers (in color mode: monochrome is different!) ; monochrome is 3B4/3B5 respectively ;-------------------------------------------------------------- CRTC_INDEX equ 03D4h CRTC_DATA equ 03D5h CRTC_INDEX_HTOTAL equ 00h CRTC_INDEX_HDISPENEND equ 01h CRTC_INDEX_HBSTART equ 02h CRTC_INDEX_HBEND equ 03h CRTC_INDEX_HRSTART equ 04h CRTC_INDEX_HREND equ 05h CRTC_INDEX_VTOTAL equ 06h CRTC_INDEX_OVERFLOW equ 07h CRTC_INDEX_PRSCAN equ 08h CRTC_INDEX_MAXSCAN equ 09h CRTC_INDEX_CUR_START equ 0Ah CRTC_INDEX_CUR_END equ 0Bh CRTC_INDEX_STARTHIGH equ 0Ch CRTC_INDEX_STARTLOW equ 0Dh CRTC_INDEX_CURSORHIGH equ 0Eh CRTC_INDEX_CURSORLOW equ 0Fh CRTC_INDEX_VRSTART equ 10h CRTC_INDEX_VREND equ 11h ;;bit 7=1 to write-protect 0..7 CRTC_INDEX_VDENABEND equ 12h CRTC_INDEX_OFFSET equ 13h CRTC_INDEX_UNDERLINE equ 14h CRTC_INDEX_VBSTART equ 15h CRTC_INDEX_VBEND equ 16h CRTC_INDEX_MODECTL equ 17h CRTC_INDEX_LINECMP equ 18h ;-------------------------------------------------------------- ; VGA sequencer registers ;-------------------------------------------------------------- SRX equ 03C4h SRDATA equ 03C5h SR0 equ 000h ;reset SR1 equ 001h ;clocking mode SR2 equ 002h ;plane mask SR3 equ 003h ;character map select SR4 equ 004h ;memory mode ;-------------------------------------------------------------- ; VGA graphics controller registers ;-------------------------------------------------------------- GRX equ 03CEh GRDATA equ 03CFh GR0 equ 000h ;set/reset GR1 equ 001h ;set/reset enable GR2 equ 002h ;color compare GR3 equ 003h ;data rotate GR4 equ 004h ;read map select GR5 equ 005h ;mode GR6 equ 006h ;miscellaneous GR7 equ 007h ;color don't care GR8 equ 008h ;bit mask ;-------------------------------------------------------------- ; VGA attribute controller registers ;-------------------------------------------------------------- ARX equ 03C0h ;???? ARDATA equ 03C1h PEL_WRITE_ADDR equ 03C8h ;write begins "write" operation PEL_READ_ADDR equ 03C7h ;write begins "read" operation PEL_STATE equ 03C7h ;read returns DAC state PEL_DATA equ 03C9h ;-------------------------------------------------------------- ; VWE LBE4 video splitter board addresses ;-------------------------------------------------------------- VWE_HC_ON equ 031Ah ;write to this port turns on high-color divider VWE_HC_OFF equ 0319h ;write to this port turns off high-color divider ;-------------------------------------------------------------- ; Video buffer base address ;-------------------------------------------------------------- VIDEO_BUFFER EQU 0000h VIDEO_SEGMENT EQU 0A000h BIOS_SEGMENT EQU 0C000h ;=========================================================================== ; Macros ;=========================================================================== ;=========================================================================== ; Structures ;=========================================================================== PixelMap STRUC pmX dd ? pmY dd ? pmPtr dd ? PixelMap ENDS BitMap STRUC bmX dd ? bmY dd ? bmWords dd ? bmPtr dd ? BitMap ENDS ;=========================================================================== ; Data segment ;=========================================================================== BEGIN_DATA regs DPMIrealModeRegs <> video_descriptor dw ? pageFunction dd ? ;THE ORDER OF THESE TWO IS CRITICAL! BIOS_descriptor dw ? ;(they constitute a far pointer in 32-bits) bitMapFcn dd ? ;used by Buf16DrawBitMap tempColor db 256*3 dup () ;; testWord dw 0 badVideoActive db 0 ;flag indicating deliberately bad video is on crtc_htotal db ? ;horizontal total END_DATA ;=========================================================================== ; Code segment ;=========================================================================== BEGIN_CODE ;------------------------------------------------------------------------- ; SVGASetMode() ; Set requested VESA display mode ;------------------------------------------------------------------------- ; Enter: ; LWord mode = requested display mode ;------------------------------------------------------------------------- ; Returns: ; (void) ;------------------------------------------------------------------------- BEGIN_C_PROC SVGASetMode ARG_DWORD sm_mode ARG_CPTR sm_ptr BUILD_STACK_FRAME mov eax,sm_ptr mov pageFunction,eax mov eax,sm_mode cmp eax,0100h jae short smUseVESA ;-------------------------------------------------------------- ; Prepare for BIOS call ;-------------------------------------------------------------- ;ah=00 for mode set, al=mode mov regs.realEAX,eax jmp short smGo smUseVESA: ;-------------------------------------------------------------- ; Prepare for VESA call ;-------------------------------------------------------------- mov ax,04F02h ;ah=4F for VESA, al=02 for set mode mov regs.realEAX,eax mov eax,sm_mode ;bx = mode mov regs.realEBX,eax ;-------------------------------------- ; Simulate real interrupt through DPMI ;-------------------------------------- smGo: mov bx,010h ;bh=0, bl=interrupt number xor cx,cx ;copy zero words from stack mov ax,ds ;es:edi points to regs mov es,ax ;es:edi points to regs mov edi,OFFSET regs DPMI_SIMULATE_REAL_INT ;-------------------------------------------------------------- ; Generate descriptor for video buffer at segment A000 ;-------------------------------------------------------------- mov bx,VIDEO_SEGMENT ;segment to map DPMI_MAP_SEG_TO_DESC mov video_descriptor,ax END_C_PROC ;------------------------------------------------------------------------- ; SVGAFunkyVideo() ; Deliberately create bad video sync ;------------------------------------------------------------------------- ; Enter: ; LWord mode = on/off (MUNGA "Logical") ;------------------------------------------------------------------------- ; Returns: ; (void) ;------------------------------------------------------------------------- BEGIN_C_PROC SVGAFunkyVideo ARG_DWORD fv_mode BUILD_STACK_FRAME ;-------------------------------------------------------------- ; Enable writing to lowest seven CRTC registers ;-------------------------------------------------------------- mov dx,CRTC_INDEX ;point to vrend register mov al,CRTC_INDEX_VREND out dx,al mov dx,CRTC_DATA ;get the current setting in al,dx mov cl,al ;save in cl and al,07Fh ;turn off MSB (turns off write-protect) out dx,al ;write it out ;-------------------------------------------------------------- ; Point to CRTC htotal register ;-------------------------------------------------------------- mov dx,CRTC_INDEX ;point to htotal register mov al,CRTC_INDEX_HTOTAL out dx,al mov dx,CRTC_DATA ;point dx at data port ;-------------------------------------------------------------- ; Set or restore? ;-------------------------------------------------------------- mov eax,fv_mode or eax,eax je short bvOff mov al,badVideoActive ;already in bad video? or al,al jnz bvExit ;yes, bail out mov badVideoActive,1 ;flag as 'bad' ;-------------------------------------------------------------- ; Read CRTC value, save it ;-------------------------------------------------------------- in al,dx ;get the current setting mov crtc_htotal,al ;-------------------------------------------------------------- ; Set screwed up CRTC value ;-------------------------------------------------------------- sub al,9 ;generate funky htotal out dx,al ;write it out jmp short bvExit ;-------------------------------------------------------------- ; Restore proper CRTC value ;-------------------------------------------------------------- bvOff: mov al,crtc_htotal out dx,al mov badVideoActive,0 ;flag as 'good' bvExit: ;-------------------------------------------------------------- ; Restore VREND register ;-------------------------------------------------------------- mov dx,CRTC_INDEX ;point to vrend register mov al,CRTC_INDEX_VREND out dx,al mov dx,CRTC_DATA mov al,cl ;get the old value out dx,al ;write it out END_C_PROC ;------------------------------------------------------------------------- ; SVGASetSplitterClock() ; Turn on/off special VWE splitter clock divider ;------------------------------------------------------------------------- ; Enter: ; LWord state = requested clock mode (True:on, False:off) ;------------------------------------------------------------------------- ; Returns: ; (void) ;------------------------------------------------------------------------- BEGIN_C_PROC SVGASetSplitterClock ARG_DWORD state BUILD_STACK_FRAME mov eax,state or eax,eax jz short ssc_off ;-------------------------------------------------------------- ; Turn on special splitter card clock divider ;-------------------------------------------------------------- mov dx,VWE_HC_ON jmp short ssc_write ;-------------------------------------------------------------- ; Turn off special splitter card clock divider ;-------------------------------------------------------------- ssc_off: mov dx,VWE_HC_OFF ssc_write: out dx,al ;any value will do END_C_PROC ;------------------------------------------------------------------------- ; SVGASetPage() ; Set SVGA display page ;------------------------------------------------------------------------- ; Enter: ; int page = requested SVGA page ;------------------------------------------------------------------------- ; Returns: ; (void) ;------------------------------------------------------------------------- BEGIN_C_PROC SVGASetPage ARG_DWORD sp_page BUILD_STACK_FRAME mov edx,sp_page and edx,00FFh ;remove upper bits mov bx,0000h ;bh=set bank, bl=window # mov ax,4F05h ;int 10h function 4F subfcn 05 ;; cmp pageFunction,0 ;does the direct call exist? ;; je setBankIrq ;no, use interrupt ;; call cs:fword ptr [pageFunction] ;THIS DOES NOT WORK, ;; jmp setBankRest ;I suspect we must use a DPMI call. ;;setBankIrq: mov ax,04F05h ;ah=4F for VESA, al=05 for set bank mov regs.realEAX,eax xor eax,eax ;bh = subfunction, bl=window mov regs.realEBX,eax mov regs.realEDX,edx ;dx = addr in granularity units mov bx,010h ;bh=0, bl=interrupt number xor cx,cx ;copy zero words from stack mov ax,ds ;es:edi points to regs mov es,ax mov edi,OFFSET regs DPMI_SIMULATE_REAL_INT END_C_PROC ;------------------------------------------------------------------------- ; SVGATransfer32() ; Copy modified portions of buffer to SVGA display buffer ;------------------------------------------------------------------------- ; Enter: ; LWord offset = offset into display buffer ; Word *ptr = pointer to source pixels ; LWord bits = bits indicating which pixels to write ;------------------------------------------------------------------------- ; Returns: ; int number of bits transferred ;------------------------------------------------------------------------- BEGIN_C_PROC SVGATransfer32 ARG_DWORD t_dest_offset ARG_DPTR t_source_ptr ARG_DWORD t_bits BUILD_STACK_FRAME ;----------------------------- ; Get source ptr in ds:si ;----------------------------- mov esi,t_source_ptr ;----------------------------- ; Get dest ptr in es:di ;----------------------------- mov ax,video_descriptor ;es:di points to destination mov es,ax mov edi,t_dest_offset ;----------------------------- ; Clear bit count ;----------------------------- xor edx,edx ;----------------------------- ; Check 32 pixels ;----------------------------- mov ebx,t_bits ;bx has bits mov ecx,32 cld ;make sure esi, edi are INCREMENTED tx_loop: lodsw ;get source word shl ebx,1 ;is bit set? jnc tx_nope ;no, don't copy ;----------------------------- ; Bit set, copy the pixel ;----------------------------- ;; mov ax,testWord ;; inc ax ;; mov testWord,ax stosw ;yes, copy inc edx ;increment bit count loop tx_loop jmp short tx_done ;----------------------------- ; Bit clear, skip the pixel ;----------------------------- tx_nope: add edi,2 loop tx_loop tx_done: ;----------------------------- ; All done, exit ;----------------------------- mov eax,edx ;return count in eax END_C_PROC ;------------------------------------------------------------------------- ; SVGATransfer32x() ; Copy LOWER BYTE of modified portions of buffer to SVGA display buffer ;------------------------------------------------------------------------- ; Enter: ; LWord offset = offset into display buffer ; Word *ptr = pointer to source pixels ; LWord bits = bits indicating which pixels to write ;------------------------------------------------------------------------- ; Returns: ; int number of bits transferred ;------------------------------------------------------------------------- BEGIN_C_PROC SVGATransfer32x ARG_DWORD t_dest_offsetx ARG_DPTR t_source_ptrx ARG_DWORD t_bitsx BUILD_STACK_FRAME ;----------------------------- ; Get source ptr in ds:si ;----------------------------- mov esi,t_source_ptrx ;----------------------------- ; Get dest ptr in es:di ;----------------------------- mov ax,video_descriptor ;es:di points to destination mov es,ax mov edi,t_dest_offsetx ;----------------------------- ; Clear bit count ;----------------------------- xor edx,edx ;----------------------------- ; Check 32 pixels ;----------------------------- mov ebx,t_bitsx ;bx has bits mov ecx,32 cld ;make sure esi, edi are INCREMENTED tx_loopx: lodsw ;get source word shl ebx,1 ;is bit set? jnc tx_nopex ;no, don't copy ;----------------------------- ; Bit set, copy the pixel ;----------------------------- stosb ;yes, copy LOWER BYTE inc edx ;increment bit count loop tx_loopx jmp short tx_donex ;----------------------------- ; Bit clear, skip the pixel ;----------------------------- tx_nopex: inc edi ;; LOWER BYTE ONLY loop tx_loopx tx_donex: ;----------------------------- ; All done, exit ;----------------------------- mov eax,edx ;return count in eax END_C_PROC ;------------------------------------------------------------------------- ; SVGAZeroPalette(port) ; Clear entire 256-color palette in hardware ; ASSUMES that the port is correct. ;------------------------------------------------------------------------- ; Enter: ; Word port = base port address ;------------------------------------------------------------------------- ; Returns: ; (void) ;------------------------------------------------------------------------- BEGIN_C_PROC SVGAZeroPalette ARG_WORD zp_port BUILD_STACK_FRAME ;-------------------------------------------------------------- ; Signal CLUT that color data will be written ;-------------------------------------------------------------- mov dx,zp_port ;get port base address xor al,al ;start with color zero add dx,2 ;move to "write address" register out dx,al ;set the address ;-------------------------------------------------------------- ; Write the color data ;-------------------------------------------------------------- inc dx ;move to "data" register mov ecx,256*3 ;clear entire palette zpLoop: out dx,al loop zpLoop END_C_PROC ;------------------------------------------------------------------------- ; SVGAWriteFullPalette(palette_ptr, port) ; Write entire 256-color palette to hardware ; ASSUMES that the palette pointer is correct. ; ASSUMES that the port is correct. ;------------------------------------------------------------------------- ; Enter: ; Palette8 *wp_source = pointer to FIRST COLOR TRIPLET ; Word port = base port address ;------------------------------------------------------------------------- ; Returns: ; (void) ;------------------------------------------------------------------------- BEGIN_C_PROC SVGAWriteFullPalette ARG_DPTR wfp_source ARG_WORD wfp_port BUILD_STACK_FRAME ;-------------------------------------------------------------- ; Convert color bytes to 6-bit VGA palette values ;-------------------------------------------------------------- mov esi,wfp_source ;get pointer to FIRST TRIPLET mov edi,offset tempColor mov ecx,256*3 ;transfer entire palette cld ;make sure the pointers INCREMENT! wfpLoop: lodsb ;get the byte shr al,2 ;change to six bits stosb ;save the shifted data loop wfpLoop ;do 'em all ;-------------------------------------------------------------- ; Signal CLUT that color data will be written ;-------------------------------------------------------------- mov dx,wfp_port ;get port base address xor al,al ;start with color zero add dx,2 ;move to "write address" register out dx,al ;set the address ;-------------------------------------------------------------- ; Write the color data ;-------------------------------------------------------------- inc dx ;move to "data" register mov esi,offset tempColor ;point to shifted data mov ecx,256*3 ;transfer entire palette rep outsb END_C_PROC ;------------------------------------------------------------------------- ; SVGAReadFullPalette(palette_ptr, port) ; Read entire 256-color palette from hardware ; ASSUMES that the palette pointer is correct. ; ASSUMES that the port is correct. ;------------------------------------------------------------------------- ; Enter: ; Palette8 *rp_dest = pointer to FIRST COLOR TRIPLET ; Word port = base port address ;------------------------------------------------------------------------- ; Returns: ; (void) ;------------------------------------------------------------------------- BEGIN_C_PROC SVGAReadFullPalette ARG_DPTR rfp_dest ARG_WORD rfp_port BUILD_STACK_FRAME ;-------------------------------------------------------------- ; Signal CLUT that color data will be read ;-------------------------------------------------------------- mov dx,rfp_port ;get port base address xor al,al ;start with color zero add dx,1 ;move to "read address" register out dx,al ;set the address ;-------------------------------------------------------------- ; Read the color data ;-------------------------------------------------------------- add dx,2 ;move to "data" register mov edi,rfp_dest ;point to destination mov ecx,256*3 ;transfer entire palette rfpLoop: in al,dx ;get the color shl al,2 ;convert to 8-bit data stosb ;save it loop rfpLoop END_C_PROC ;------------------------------------------------------------------------- ; SVGAWritePaletteMask(port, mask) ; Set hardware palette mask ; ASSUMES that the port is correct. ;------------------------------------------------------------------------- ; Enter: ; Word port = base port address ; Byte mask = new mask value ;------------------------------------------------------------------------- ; Returns: ; (void) ;------------------------------------------------------------------------- BEGIN_C_PROC SVGAWritePaletteMask ARG_WORD wpm_port ARG_BYTE wpm_mask BUILD_STACK_FRAME ;-------------------------------------------------------------- ; Write the mask ;-------------------------------------------------------------- mov dx,wpm_port ;get port base address mov al,wpm_mask out dx,al END_C_PROC END_CODE END