;THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX ;SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO ;END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ;ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS ;IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS ;SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE ;FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE ;CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS ;AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. ;COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. ; ; $Source: f:/miner/source/2d/rcs/vesa.asm $ ; $Revision: 1.20 $ ; $Author: john $ ; $Date: 1994/07/27 15:43:37 $ ; ; Routines to access VESA VGA memory ; ; $Log: vesa.asm $ ; Revision 1.20 1994/07/27 15:43:37 john ; Fixed bug with allocation dos memory more than once. ; ; Revision 1.19 1994/06/24 17:27:02 john ; Made rowsizes bigger than actual screen work with SVGA. ; ; Revision 1.18 1994/05/31 11:10:45 john ; *** empty log message *** ; ; Revision 1.17 1994/05/06 12:50:21 john ; Added supertransparency; neatend things up; took out warnings. ; ; Revision 1.16 1994/03/14 16:56:29 john ; Changed grs_bitmap structure to include bm_flags. ; ; Revision 1.15 1994/02/02 11:27:22 john ; *** empty log message *** ; ; Revision 1.14 1994/01/25 11:40:46 john ; Added gr_check_mode function. ; ; Revision 1.13 1994/01/13 14:41:51 unknown ; Fixed bug with Error 7 return Error 8. ; ; Revision 1.12 1993/12/21 19:58:38 john ; made rep movsb in scanline be rep movsw ; ; Revision 1.11 1993/12/09 16:05:51 john ; Made no VESA driver detection work correctly ; ; Revision 1.10 1993/12/09 15:02:41 john ; Changed palette stuff majorly ; ; Revision 1.9 1993/11/16 11:28:28 john ; *** empty log message *** ; ; Revision 1.8 1993/10/26 13:18:03 john ; *** empty log message *** ; ; Revision 1.7 1993/10/15 16:23:28 john ; y ; ; Revision 1.6 1993/09/29 17:31:10 john ; optimized gr_vesa_pixel ; ; Revision 1.5 1993/09/26 18:59:34 john ; fade stuff ; ; Revision 1.4 1993/09/20 14:47:20 john ; *** empty log message *** ; ; Revision 1.3 1993/09/13 17:54:07 john ; Minor bug fix ; ; Revision 1.2 1993/09/08 15:56:06 john ; Started adding DPMI support for SVGA paging. ; ; Revision 1.1 1993/09/08 11:41:25 john ; Initial revision ; ; ; .386 OPTION OLDSTRUCTS INCLUDE VGAREGS.INC INCLUDE GR.INC _DATA SEGMENT BYTE PUBLIC USE32 'DATA' PUBLIC __A0000 __A0000 dw ? BufferPtr dd 0 BufferSeg dw 0 GoalMode dw ? LastPage db 0FFh BPR dw ? TempReg dd ? ; Information from VESA return SuperVGA Information VESAVersion dw ? OEMStringPtr dd ? Capabilities dd ? VideoModePtr dd ? TotalMemory dw ? WinGranularity dw ? WinSize dw ? WinFuncPtr dd ? PageSizeShift db ? VESA_Signature = 041534556h REALREGS STRUCT RealEDI dd ? RealESI dd ? RealEBP dd ? Reserved dd ? RealEBX dd ? RealEDX dd ? RealECX dd ? RealEAX dd ? RealFlags dw ? RealES dw ? RealDS dw ? RealFS dw ? RealGS dw ? RealIP dw ? RealCS dw ? RealSP dw ? RealSS dw ? REALREGS ENDS regs REALREGS < > vesa_error dd ? SourceInc dd ? DestInc dw ? RowWidth dd ? extern _gr_var_color:dword, _gr_var_bwidth:dword _DATA ENDS DGROUP GROUP _DATA _TEXT SEGMENT BYTE PUBLIC USE32 'CODE' ASSUME DS:_DATA ASSUME CS:_TEXT MyStosd MACRO Width:REQ ; Assumes: EDI = Dest Address ; Width = a 32-bit value, can't be ECX or EDI ; Trashes: ECX will be zero ; EDI = Dest Address + Width ; EDX = ???? ; Width LOCAL Aligned cmp Width, 16 jbe Aligned mov ecx, edi and ecx, 3 jcxz Aligned neg ecx add ecx, 4 sub Width, ecx rep stosb Aligned: mov ecx, Width shr ecx, 2 rep stosd mov ecx, Width and ecx, 3 rep stosb ENDM ENTER_PROC MACRO push esi push edi push ebp push eax push ebx push ecx push edx ENDM EXIT_PROC MACRO cmp [esp-4], edx je @f ; YOU TRASHED EDX !!!!!!! int 3 @@: pop edx cmp [esp-4], ecx je @f ; YOU TRASHED ECX !!!!!!! int 3 @@: pop ecx cmp [esp-4], ebx je @f ; YOU TRASHED EBX !!!!!!! int 3 @@: pop ebx cmp [esp-4], eax je @f ; YOU TRASHED EAX !!!!!!! int 3 @@: pop eax cmp [esp-4], ebp je @f ; YOU TRASHED EBP !!!!!!! int 3 @@: pop ebp cmp [esp-4], edi je @f ; YOU TRASHED EDI !!!!!!! int 3 @@: pop edi cmp [esp-4], esi je @f ; YOU TRASHED ESI !!!!!!! int 3 @@: pop esi ENDM MyMovsd MACRO Width:REQ ; Assumes: EDI = Dest Address ; ESI = Source Address ; Width = a 32-bit value, can't be ECX or EDI or ESI ; Assumes that ESI is already aligned ; Trashes: ECX will be zero ; EDI = Dest Address + Width ; ESI = Source Address + Width ; EDX = ???? LOCAL Aligned cmp Width, 16 jbe Aligned mov ecx, edi and ecx, 3 jcxz Aligned neg ecx add ecx, 4 sub Width, ecx rep movsb Aligned: mov ecx, Width shr ecx, 2 rep movsd mov ecx, Width and ecx, 3 rep movsb ENDM EBXFarTo32: push ecx mov ecx, ebx and ecx, 0FFFF0000h shr ecx, 12 and ebx, 0FFFFh add ebx, ecx pop ecx ret PUBLIC gr_init_A0000_ gr_init_A0000_: push ebx mov ax, 0002h mov bx, 0a000h int 31h jc NoGo mov __A0000, ax pop ebx xor eax, eax ret NoGo: pop ebx mov eax, 1 ret PUBLIC gr_vesa_checkmode_ gr_vesa_checkmode_: pushad mov GoalMode, ax cmp BufferSeg, 0 jne GotDosMemory ; Allocate a 256 byte block of DOS memory using DPMI mov ax, 0100h mov bx, 16 int 31h jc NoMemory ; AX = real mode segment of allocated block and eax, 0FFFFh mov BufferSeg, ax shl eax, 4 ; EAX = 32-bit pointer to DOS memory mov BufferPtr, eax GotDosMemory: ; Get SuperVGA information mov ax, BufferSeg mov regs.RealEDI, 0 mov regs.RealESI, 0 mov regs.RealEBP, 0 mov regs.Reserved, 0 mov regs.RealEBX, 0 mov regs.RealEDX, 0 mov regs.RealECX, 0 mov regs.RealEAX, 04f00h mov regs.RealFlags, 0 mov regs.RealES, ax mov regs.RealDS, 0 mov regs.RealFS, 0 mov regs.RealGS, 0 mov regs.RealIP, 0 mov regs.RealCS, 0 mov regs.RealSP, 0 mov regs.RealSS, 0 mov bl, 10h xor bh, bh xor ecx, ecx mov edi, offset regs mov ax, 0300h int 31h mov eax, regs.RealEAX cmp ax, 04fh jne NoVESADriver ; Make sure there is a VESA signature mov eax, BufferPtr cmp dword ptr[eax+0], VESA_Signature jne NoVESADriver ; We now have a valid VESA driver loaded mov bx, word ptr [eax+4] mov VESAVersion, bx mov ebx, dword ptr [eax+6] call EBXFarTo32 mov OEMStringPtr, ebx mov ebx, dword ptr [eax+10] mov Capabilities, ebx mov bx, word ptr [eax+18] mov TotalMemory, bx mov ebx, dword ptr [eax+14] call EBXFarTo32 mov VideoModePtr, ebx TryAnotherMode: mov ax, word ptr [ebx] add ebx, 2 cmp ax, GoalMode je ModeSupported cmp ax, -1 je ModeNotSupported jmp TryAnotherMode ModeSupported: ; Get SuperVGA information mov ax, BufferSeg movzx ecx, GoalMode mov regs.RealEDI, 0 mov regs.RealESI, 0 mov regs.RealEBP, 0 mov regs.Reserved, 0 mov regs.RealEBX, 0 mov regs.RealEDX, 0 mov regs.RealECX, ecx mov regs.RealEAX, 04f01h mov regs.RealFlags, 0 mov regs.RealES, ax mov regs.RealDS, 0 mov regs.RealFS, 0 mov regs.RealGS, 0 mov regs.RealIP, 0 mov regs.RealCS, 0 mov regs.RealSP, 0 mov regs.RealSS, 0 mov bl, 10h xor bh, bh xor cx, cx mov edi, offset regs mov ax, 0300h int 31h mov eax, regs.RealEAX cmp ax, 04fh jne BadStatus ; Check if this mode supported by hardware. mov eax, BufferPtr mov bx, [eax] bt bx, 0 jnc HardwareNotSupported mov bx, [eax+4] cmp bx, 64 jne @f mov PageSizeShift, 0 jmp GranularityOK @@: cmp bx, 32 jne @f mov PageSizeShift, 1 jmp GranularityOK @@: cmp bx, 16 jne @f mov PageSizeShift, 2 jmp GranularityOK @@: cmp bx, 8 jne @f mov PageSizeShift, 3 jmp GranularityOK @@: cmp bx, 4 jne @f mov PageSizeShift, 4 jmp GranularityOK @@: cmp bx, 2 jne @f mov PageSizeShift, 5 jmp GranularityOK @@: cmp bx, 1 jne WrongGranularity mov PageSizeShift, 6 GranularityOK: shl bx, 10 mov WinGranularity, bx mov bx, [eax+6] mov WinSize, bx mov ebx, [eax+12] call EBXFarTo32 mov WinFuncPtr, ebx movzx ebx, word ptr [eax+16] NoError: mov vesa_error, 0 jmp Done WrongGranularity: mov vesa_error, 2 jmp Done HardwareNotSupported: mov vesa_error, 3 jmp Done ModeNotSupported: mov vesa_error, 4 jmp Done NoVESADriver: mov vesa_error, 5 jmp Done BadStatus: mov vesa_error, 6 jmp Done NoMemory: mov vesa_error, 7 jmp Done DPMIError: mov vesa_error, 8 Done: popad mov eax, vesa_error ret PUBLIC gr_get_dos_mem_ gr_get_dos_mem_: ; eax = how many bytes push ebx mov ebx, eax shr ebx, 4 mov eax, 0100h int 31h jc nomem and eax, 0ffffh shl eax, 4 pop ebx ret nomem: pop ebx mov eax,0 ret PUBLIC gr_vesa_setmodea_ gr_vesa_setmodea_: ; eax = mode pushad mov ebx, eax mov eax, 04f02h int 10h cmp ax, 04fh jne BadStatus jmp NoError PUBLIC gr_vesa_setpage_ gr_vesa_setpage_: ; EAX = 64K Page number cmp al, LastPage jne @f ret @@: mov LastPage, al push edx push ebx push ecx mov edx, eax mov cl, PageSizeShift shl edx, cl ; Convert from 64K pages to GranUnit pages. xor ebx, ebx ; BH=Select window, BL=Window A mov eax, 04f05h ; AX=Super VGA video memory window control int 10h pop ecx pop ebx pop edx ret PUBLIC gr_vesa_setaddress_ gr_vesa_setaddress_: ; EAX = Address of video memory to write to push edx push ebx push ecx mov edx, eax shl edx, 12 ; Convert from address pages to 4k GranUnit pages. xor ebx, ebx ; BH=Select window, BL=Window A mov eax, 04f05h ; AX=Super VGA video memory window control int 10h pop ecx pop ebx pop edx ret PUBLIC gr_vesa_incpage_ gr_vesa_incpage_: push eax push ebx push ecx push edx push ebp inc LastPage mov dl, LastPage mov cl, PageSizeShift shl edx, cl ; Convert from 64K pages to GranUnit pages. xor ebx, ebx ; BH=Select window, BL=Window A mov eax, 04f05h ; AX=Super VGA video memory window control int 10h pop ebp pop edx pop ecx pop ebx pop eax ret PUBLIC gr_vesa_setstart_ gr_vesa_setstart_: ; EAX = First column ; EDX = First row push ebx push ecx mov ecx, eax mov eax, 4f07h xor ebx, ebx int 10h pop ecx pop ebx ret PUBLIC gr_vesa_setlogical_ gr_vesa_setlogical_: ; EAX = line width push ebx push ecx push edx mov cx, ax mov ax, 04f06h mov bl, 0 int 10h and ebx, 0FFFFh mov ax, cx pop edx pop ecx pop ebx ret PUBLIC gr_vesa_scanline_ gr_vesa_scanline_: ; EAX = x1 ; EDX = x2 ; EBX = y ; ECX = color push edi cld cmp edx, eax jge @f xchg edx, eax @@: mov edi, ebx imul edi, _gr_var_bwidth add edi, eax ; EDI = y*bpr+x1 sub edx, eax ; ECX = x2-x1 inc edx mov eax, edi shr eax, 16 cmp al, LastPage je @f mov LastPage, al push edx push ecx mov edx, eax mov cl, PageSizeShift shl edx, cl ; Convert from 64K pages to GranUnit pages. xor ebx, ebx ; BH=Select window, BL=Window A mov eax, 04f05h ; AX=Super VGA video memory window control int 10h pop ecx pop edx @@: and edi, 00FFFFh or edi, 0A0000h ;mov eax, _Table8to32[ecx*4] mov ch, cl mov ax, cx shl eax, 16 mov ax, cx ; edx = width in bytes ; edi = dest mov bx, dx add bx, di jnc scanonepage sub dx, bx movzx ecx, dx shr ecx, 1 rep stosw adc ecx, ecx rep stosb movzx edx, bx cmp edx, 0 je scandone call gr_vesa_incpage_ mov edi, 0A0000h scanonepage: movzx ecx, dx shr ecx, 1 rep stosw adc ecx, ecx rep stosb scandone: pop edi ret PUBLIC gr_vesa_set_logical_ gr_vesa_set_logical_: ; EAX = logical width in pixels push ebx push ecx mov ecx, eax mov eax, 04f06h mov bl, 0 int 10h and ebx, 0ffffh movzx eax, cx pop ecx pop ebx ret PUBLIC gr_vesa_pixel_ gr_vesa_pixel_: ; EAX = color (in AL) ; EDX = offset from 0A0000 shld eax, edx, 16 and edx, 0ffffh cmp al, LastPage jne @f shr eax, 16 mov [edx+0A0000h], al ret @@: mov LastPage, al pushad and eax, 0fh mov edx, eax mov cl, PageSizeShift shl edx, cl ; Convert from 64K pages to GranUnit pages. xor ebx, ebx ; BH=Select window, BL=Window A mov eax, 04f05h ; AX=Super VGA video memory window control int 10h popad shr eax, 16 mov [edx+0A0000h], al ret PUBLIC gr_vesa_bitblt_ gr_vesa_bitblt_: ; EAX = source_ptr ; EDX = vesa_address ; EBX = height ; ECX = width push edi push esi mov esi, eax ; Point ESI to source bitmap ; Set the initial page mov eax, edx ; Move offset into SVGA into eax shr eax, 16 ; Page = offset / 64K call gr_vesa_setpage_ mov edi, edx ; EDI = offset into SVGA and edi, 0FFFFh ; EDI = offset into 64K page add edi, 0A0000h ; EDI = ptr to dest mov edx, _gr_var_bwidth sub edx, ecx ; EDX = amount to step each row mov eax, ecx NextScanLine: push eax MyMovsd eax pop eax dec ebx jz DoneBlt add di, dx jnc NextScanLine ; Need to increment page! call gr_vesa_incpage_ jmp NextScanLine DoneBlt: pop esi pop edi ret PUBLIC gr_vesa_bitmap_ gr_vesa_bitmap_: ; EAX = Source bitmap (LINEAR) ; EDX = Destination bitmap (SVGA) ; EBX = x ; ECX = y push esi push edi push ebp push es push eax mov eax, [edx].bm_data imul ecx, _gr_var_bwidth add eax, ecx add eax, ebx mov edi, eax ; EDI = offset into SVGA shr eax, 16 call gr_vesa_setpage_ mov ax, __A0000 mov es, ax pop eax mov esi, [eax].bm_data and edi, 0ffffh movzx ecx, [eax].bm_h NextScanLine1: push ecx movzx ecx, [eax].bm_w mov bx, cx add bx, di jnc OnePage sub cx,bx mov ebp, ecx MyMovsd ebp and edi, 00ffffh ; IN CASE IT WENT OVER 64K mov cx,bx call gr_vesa_incpage_ jcxz DoneWithLine OnePage: mov ebp, ecx MyMovsd ebp and edi, 00ffffh ; IN CASE IT WENT OVER 64K DoneWithLine: mov bx, [eax].bm_rowsize sub bx, [eax].bm_w and ebx, 0ffffh add esi, ebx mov bx, [edx].bm_rowsize sub bx, [eax].bm_w add di, bx jnc NoPageInc call gr_vesa_incpage_ NoPageInc: pop ecx dec ecx jz @f jmp NextScanLine1 @@: pop es pop ebp pop edi pop esi ret PUBLIC gr_vesa_update_ gr_vesa_update_: ; EAX = Source bitmap (LINEAR) ; EDX = Destination bitmap (SVGA) ; EBX = Old source bitmap (LINEAR) push ecx push esi push edi push ebp push fs push eax mov eax, [edx].bm_data mov ebp, eax ; EDI = offset into SVGA shr eax, 16 call gr_vesa_setpage_ mov ax, __A0000 mov fs, ax pop eax mov esi, [eax].bm_data and ebp, 0ffffh movzx ecx, [eax].bm_h mov edi, [ebx].bm_data movzx ebx, [eax].bm_rowsize sub bx, [eax].bm_w mov SourceInc, ebx movzx ebx, [edx].bm_rowsize sub bx, [eax].bm_w mov DestInc, bx movzx ebx, [eax].bm_w mov RowWidth, ebx NextScanLine3: push ecx mov ecx, RowWidth mov dx, cx add dx, bp jnc OnePage3 sub cx,dx mov ebx, esi InnerLoop3: repe cmpsb mov al, [esi-1] sub esi, ebx mov fs:[ebp+esi-1], al ; EDX = dest + size - bytes to end add esi, ebx cmp ecx, 0 jne InnerLoop3 sub esi, ebx add ebp, esi add esi, ebx and ebp, 00ffffh ; IN CASE IT WENT OVER 64K mov cx,dx call gr_vesa_incpage_ jcxz DoneWithLine3 OnePage3: mov ebx, esi mov edx, ecx and edx, 11b shr ecx, 2 InnerLoop4: repe cmpsd mov eax, [esi-4] sub esi, ebx mov fs:[ebp+esi-4], eax ; EDX = dest + size - bytes to end add esi, ebx cmp ecx, 0 jne InnerLoop4 mov ecx, edx jecxz EvenWidth InnerLoop5: repe cmpsb mov al, [esi-1] sub esi, ebx mov fs:[ebp+esi-1], al ; EDX = dest + size - bytes to end add esi, ebx cmp ecx, 0 jne InnerLoop5 EvenWidth: sub esi, ebx add ebp, esi add esi, ebx and ebp, 00ffffh ; IN CASE IT WENT OVER 64K DoneWithLine3: add esi, SourceInc add edi, SourceInc add bp, DestInc jnc NoPageInc3 call gr_vesa_incpage_ NoPageInc3: pop ecx dec ecx jnz NextScanLine3 pop fs pop ebp pop edi pop esi pop ecx ret _TEXT ENDS END