;Copyright (C) 1997-2001 ZSNES Team ( zsknight@zsnes.com / _demo_@zsnes.com ) ; ;This program is free software; you can redistribute it and/or ;modify it under the terms of the GNU General Public License ;as published by the Free Software Foundation; either ;version 2 of the License, or (at your option) any later ;version. ; ;This program is distributed in the hope that it will be useful, ;but WITHOUT ANY WARRANTY; without even the implied warranty of ;MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;GNU General Public License for more details. ; ;You should have received a copy of the GNU General Public License ;along with this program; if not, write to the Free Software ;Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. %include "macros.mac" EXTSYM printnum EXTSYM DosExit,ZSNESBase,Change_Dir,PrintStr,newengen EXTSYM HalfTransB,HalfTransC EXTSYM InitDrive,gotoroot,InitDir,fulladdtab ; EXTSYM printhex ; EXTSYM printhex EXTSYM UnusedBit,HalfTrans,UnusedBitXor,ngrposng,nggposng,ngbposng ; EXTSYM printhex EXTSYM Init_2xSaIMMX NEWSYM Vesa2AsmStart ; add 0214h video mode anticrash times 10 db 0 ALIGN32 NEWSYM vesa2_usbit, dd 0 ; Unused bit in proper bit location NEWSYM vesa2_clbit, dd 0 ; clear all bit 0's if AND is used NEWSYM vesa2_clbitng, dd 0 ; clear all bit 0's if AND is used NEWSYM vesa2_clbitng2, dd 0,0 ; clear all bit 0's if AND is used NEWSYM vesa2_clbitng3, dd 0 ; clear all bit 0's if AND is used NEWSYM vesa2_x, dd 320 ; Desired screen width NEWSYM vesa2_y, dd 240 ; Height NEWSYM vesa2selec, dd 0 ; VESA2 Selector Location NEWSYM vesa2_bits, dd 8 ; Bits per pixel NEWSYM vesa2_rpos, dd 0 ; Red bit position NEWSYM vesa2_gpos, dd 0 ; Green bit position NEWSYM vesa2_bpos, dd 0 ; Blue bit position NEWSYM vesa2_rposng, dd 0 ; Red bit position NEWSYM vesa2_gposng, dd 0 ; Green bit position NEWSYM vesa2_bposng, dd 0 ; Blue bit position NEWSYM vesa2_rtrcl, dd 0 ; red transparency clear (bit+4) NEWSYM vesa2_rtrcla, dd 0 ; red transparency (AND) clear (not(bit+4)) NEWSYM vesa2_rfull, dd 0 ; red max (or bit*1Fh) NEWSYM vesa2_gtrcl, dd 0 ; red transparency clear (bit+4) NEWSYM vesa2_gtrcla, dd 0 ; red transparency (AND) clear (not(bit+4)) NEWSYM vesa2_gfull, dd 0 ; red max (or bit*1Fh) NEWSYM vesa2_btrcl, dd 0 ; red transparency clear (bit+4) NEWSYM vesa2_btrcla, dd 0 ; red transparency (AND) clear (not(bit+4)) NEWSYM vesa2_bfull, dd 0 ; red max (or bit*1Fh) NEWSYM vesa2red10, dd 0 ; red position at bit 10 NEWSYM videotroub, dd 0 ; red position at bit 10 NEWSYM vesa3en, dd 0 NEWSYM VESAAddr, dd 0 NEWSYM ExitFromGUI, db 0 NEWSYM ErrorPointer, dd 0 NEWSYM TripBufAvail, db 0 NEWSYM dcolortab, times 256 dd 0 NEWSYM genfulladdtab ; Write to buffer cmp byte[newengen],1 jne .notneweng cmp byte[vesa2red10],0 jne near genfulladdtabred .notneweng xor ecx,ecx .loopers mov ax,cx test [vesa2_rtrcl],cx jz .nor and ax,[vesa2_rtrcla] or ax,[vesa2_rfull] .nor test [vesa2_gtrcl],cx jz .nog and ax,[vesa2_gtrcla] or ax,[vesa2_gfull] .nog test [vesa2_btrcl],cx jz .nob and ax,[vesa2_btrcla] or ax,[vesa2_bfull] .nob shl ax,1 mov [fulladdtab+ecx*2],ax dec cx jnz .loopers ret NEWSYM genfulladdtabred NEWSYM genfulladdtabng ; Write to buffer xor ecx,ecx .loopers mov ax,cx test cx,0100000000000000b jz .nor and ax,1011111111111111b or ax, 0011110000000000b .nor test cx,0000001000000000b jz .nog and ax,1111110111111111b or ax, 0000000111100000b .nog test cx,0000000000010000b jz .nob and ax,1111111111101111b or ax, 0000000000001111b .nob shl ax,1 mov [fulladdtab+ecx*2],ax dec cx jnz .loopers ret NEWSYM VESA2EXITTODOS mov byte[videotroub],1 cmp byte[ExitFromGUI],0 je .nogui mov [ErrorPointer],edx ret .nogui mov ax,0003h int 10h push edx mov edx,.exitfromvesa2 call PrintStr pop edx call PrintStr mov edx,.return call PrintStr mov dl,[InitDrive] mov ebx,InitDir call Change_Dir jmp DosExit .exitfromvesa2 db 'Unable to Initialize VESA2 : ',0 .return db 10,13,0 ;******************************************************* ; Set up Vesa 2 ;******************************************************* NEWSYM InitVesa2 ;-------------------------------------------------; ; First - allocate some bytes in DOS memory for ; ; communication with VBE ; ;-------------------------------------------------; mov eax,0100h mov ebx,512/16 ; 512 bytes int 31h ; Function 31h,100h - Allocate ; DOS memory (512 bytes) jnc .gotmem mov edx,.nomemmessage jmp VESA2EXITTODOS .nomemmessage db 'Unable to locate DOS memory.',0 .gotmem mov fs,dx ; FS now points to the DOS ; buffer ;--------------------------------------------------; ; Now, get information about the video card into ; ; a data structure ; ;--------------------------------------------------; mov edi,RMREGS mov dword[fs:0],'VBE2' ; Request VBE 2.0 info mov dword[RMREGS.eax],4f00h mov word[RMREGS.es],ax ; Real mode segment of DOS ; buffer mov dword[RMREGS.edi],0 push es push ds pop es mov eax,300h mov ebx,10h xor ecx,ecx int 31h ; Simulate real mode interrupt pop es jnc .int1ok mov edx,.noint1message jmp VESA2EXITTODOS .noint1message db 'Simulated real mode interrupt failed.',0 .int1ok ; Real mode int successful!!! mov eax,[RMREGS.eax] cmp al,4fh ; Check vbe interrupt went OK jz .vbedetected mov edx,.novbemessage jmp VESA2EXITTODOS .novbemessage db 'VBE not detected!!',0 .vbedetected cmp dword[fs:0000],'VESA' jz .vesadetected ; Check for presence of vesa mov edx,.novesamessage jmp VESA2EXITTODOS .novesamessage db 'VESA not detected!',0 .vesadetected cmp word[fs:0004],200h jae .vesa2detected ; Check we've got VESA 2.0 or greater mov edx,.novesa2message jmp VESA2EXITTODOS .novesa2message db 'VESA 2.0 or greater required!',0 ;-----------------------------------------------------; ; OK - vesa 2.0 or greater has been detected. Copy ; ; mode information into VESAmodelist ; ;-----------------------------------------------------; .vesa2detected mov dword[vesa3en],0 cmp word[fs:004],300h jb .notvbe3 mov dword[vesa3en],1 .notvbe3 mov ax,[fs:12h] ; Get no. of 64k blocks mov [noblocks],ax mov ax, 2 mov bx,[fs:10h] int 31h jnc .wegottheselector mov edx, .oopsnoselector jmp VESA2EXITTODOS .oopsnoselector db 'Failed to allocate vesa display selector!',0 .wegottheselector mov gs,ax xor eax,eax mov ebp,VESAmodelist mov ecx,512 mov ax,[fs:0eh] .loopcopymodes mov bx,[gs:eax] mov [ebp],bx cmp bx,0ffffh jz .copiedmodes add ebp,2 add eax,2 dec ecx jz .outofmodelistspace jmp .loopcopymodes .outofmodelistspace mov edx,.outofmodelistspacemessage jmp VESA2EXITTODOS .outofmodelistspacemessage db 'Out of VESA2 mode list space!',0 ;----------------------------------------------; ; OK - Scan the mode list to find a matching ; ; mode for vesa2_x, vesa2_y and vesa2_depth ; ;----------------------------------------------; .copiedmodes mov ebp,VESAmodelist xor ecx,ecx .loopcheckmodes mov cx, [ebp] cmp cx, 0ffffh jnz .notendoflist mov edx,.endoflist jmp VESA2EXITTODOS .endoflist db 'This VESA2 mode does not work on your video card / driver.',0 .whichwin db 0 .notendoflist mov edi, RMREGS mov dword[RMREGS.eax],4f01h mov dword[RMREGS.ebx],0 mov dword[RMREGS.ecx],ecx mov dword[RMREGS.edi],0 push es push ds pop es mov eax,300h mov ebx,10h xor ecx,ecx int 31h ; Simulate real mode interrupt pop es jnc .modecheckok mov edx,.modecheckfail jmp VESA2EXITTODOS .modecheckfail db 'Real mode interrupt failure while checking vesa mode',0 .modecheckok add ebp,2 test word[fs:0000h],1b jz near .loopcheckmodes ; If mode is not available ; ; xor eax,eax ; mov ax,[fs:12h] ; call printnum ; mov ah,02h ; mov dl,'x' ; int 21h ; mov ax,[fs:14h] ; call printnum ; mov ah,02h ; mov dl,'x' ; int 21h ; xor ah,ah ; mov al,[fs:19h] ; call printnum ; mov ah,02h ; mov dl,13 ; int 21h ; mov dl,10 ; int 21h mov eax,[vesa2_x] cmp [fs:12h],ax ; Check that the height matches jnz near .loopcheckmodes mov eax,[vesa2_y] cmp [fs:14h],ax ; Check that the width matches jnz near .loopcheckmodes mov al,[vesa2_bits] cmp [fs:19h],al ; Check bits/pixel for match jnz near .loopcheckmodes ; mov ax,3 ; int 10h ; xor eax,eax ; mov ax,[fs:0h] ; call printnum ; jmp DosExit mov byte[TripBufAvail],1 test word[fs:0000h],400h jz .notbuf mov byte[TripBufAvail],1 .notbuf ; jz .notvesa3 ; xor eax,eax ; mov ax,[fs:0000h] ; call printhex ; jmp DosExit .notvesa3 ; mov ah,07h ; int 21h ; D0 = Window supported ; 0 = Window is not supported ; 1 = Window is supported ; D1 = Window readable ; 0 = Window is not readable ; 1 = Window is readable ; D2 = Window writeable ; 0 = Window is not writeable ; 1 = Window is writeable ; D3-D7 = Reserved mov byte[.whichwin],0 mov al,[fs:2] ; Get window A attributes and al,0100b cmp al,0100b je .foundwin ; Mode supported mov al,[fs:3] ; Get window B attributes and al,0100b cmp al,0100b jne .foundwin ; Mode not supported mov byte[.whichwin],1 .foundwin ; Success - a match has been found!! sub ebp,2 mov ax,[ebp] mov [vesamode],ax ; Store vesa 2 mode number ; call printhex ; jmp DosExit mov ax,[fs:10h] mov byte[vesa2red10],0 mov byte[vesa2_rposng],11 mov byte[vesa2_gposng],6 mov byte[vesa2_bposng],0 mov dword[vesa2_clbitng],1111011111011110b mov dword[vesa2_clbitng2],11110111110111101111011111011110b mov dword[vesa2_clbitng2+4],11110111110111101111011111011110b mov dword[vesa2_clbitng3],0111101111101111b mov [bytesperscanline],ax ; Store bytes per scan line cmp byte[fs:20h],10 jne near .nored10 mov byte[fs:20h],11 mov byte[vesa2red10],1 mov byte[vesa2_rposng],10 mov byte[vesa2_gposng],5 mov dword[vesa2_clbitng],0111101111011110b mov dword[vesa2_clbitng2],01111011110111100111101111011110b mov dword[vesa2_clbitng2+4],01111011110111100111101111011110b mov dword[vesa2_clbitng3],0011110111101111b mov dword[UnusedBit], 10000000000000001000000000000000b mov dword[HalfTrans], 01111011110111100111101111011110b mov dword[UnusedBitXor], 01111111111111110111111111111111b mov dword[UnusedBit+4], 10000000000000001000000000000000b mov dword[HalfTrans+4], 01111011110111100111101111011110b mov dword[UnusedBitXor+4],01111111111111110111111111111111b mov dword[HalfTransB], 00000100001000010000010000100001b mov dword[HalfTransB+4], 00000100001000010000010000100001b mov dword[HalfTransC], 01111011110111100111101111011110b mov dword[HalfTransC+4], 01111011110111100111101111011110b mov dword[ngrposng],10 mov dword[nggposng],5 mov dword[ngbposng],0 .nored10 ; fix up bit lengths mov al,16 sub al,[fs:20h] mov ah,[fs:22h] sub ah,[fs:20h] mov bl,[fs:24h] sub bl,[fs:20h] mov bh,al cmp bh,ah jb .scheck1 mov bh,ah .scheck1 cmp bh,bl jb .scheck2 mov bh,bl .scheck2 mov byte[fs:19h],5 mov al,16 sub al,[fs:22h] mov ah,[fs:20h] sub ah,[fs:22h] mov bl,[fs:24h] sub bl,[fs:22h] mov bh,al cmp bh,ah jb .scheck1b mov bh,ah .scheck1b cmp bh,bl jb .scheck2b mov bh,bl .scheck2b mov [fs:21h],bh mov al,16 sub al,[fs:24h] mov ah,[fs:20h] sub ah,[fs:24h] mov bl,[fs:22h] sub bl,[fs:24h] mov bh,al cmp bh,ah jb .scheck1c mov bh,ah .scheck1c cmp bh,bl jb .scheck2c mov bh,bl .scheck2c mov [fs:23h],bh mov word[vesa2_clbit],0 cmp byte[fs:20h],10 jne .nottopbit mov word[vesa2_usbit],8000h .nottopbit ; Process Red Stuff mov al,[fs:20h] ; bit sizes = [fs:19h,21h,23h] mov cl,al mov bx,1 shl bx,cl cmp byte[fs:19h],6 jne .no6bit mov [vesa2_usbit],bx inc al .no6bit or [vesa2_clbit],bx mov [vesa2_rpos],al dec al mov cl,al mov bx,001Fh cmp cl,0FFh je .shrr shl bx,cl jmp .shlr .shrr shr bx,1 .shlr mov word[vesa2_rfull],bx add al,5 mov bx,1 mov cl,al shl bx,cl mov word[vesa2_rtrcl],bx xor bx,0FFFFh mov word[vesa2_rtrcla],bx ; mov ax,03h ; int 10h ; mov ax,[vesa2_rfull] ; call printhex ; jmp DosExit ; Process Green Stuff mov al,[fs:22h] mov cl,al mov bx,1 shl bx,cl cmp byte[fs:21h],6 jne .no6bitb mov [vesa2_usbit],bx inc al .no6bitb or [vesa2_clbit],bx mov [vesa2_gpos],al dec al mov cl,al mov bx,001Fh cmp cl,0FFh je .shrg shl bx,cl jmp .shlg .shrg shr bx,1 .shlg mov word[vesa2_gfull],bx add al,5 mov bx,1 mov cl,al shl bx,cl mov word[vesa2_gtrcl],bx xor bx,0FFFFh mov word[vesa2_gtrcla],bx ; Process Blue Stuff mov al,[fs:24h] mov cl,al mov bx,1 shl bx,cl cmp byte[fs:23h],6 jne .no6bitc mov [vesa2_usbit],bx inc al .no6bitc or [vesa2_clbit],bx mov [vesa2_bpos],al dec al mov cl,al mov bx,001Fh cmp cl,0FFh je .shrb shl bx,cl jmp .shlb .shrb shr bx,1 .shlb mov word[vesa2_bfull],bx add al,5 mov bx,1 mov cl,al shl bx,cl mov word[vesa2_btrcl],bx xor bx,0FFFFh mov word[vesa2_btrcla],bx xor word[vesa2_clbit],0FFFFh ;vesa2_rtrcl dw 0 ; red transparency clear (bit+4) ;vesa2_rtrcla dw 0 ; red transparency (AND) clear (not(bit+4)) ;vesa2_rfull dw 0 ; red max (or (bit-1)*1Fh) call genfulladdtab test word[fs:0h],10000000b ; Check if linear available jnz .linearavailable mov edx,.nolframebuffer jmp VESA2EXITTODOS ; None available .nolframebuffer db 'Linear Frame Buffer not Detected.',0 ;---------------------------------------------; ; OK - now set the vesa 2 mode based on the ; ; information gleaned... ; ;---------------------------------------------; .linearavailable or word[vesamode],4000h ; Convert mode to its LFB ; equivalent mov ebx,[fs:28h] ; Read in physical base ptr mov cx,bx shr ebx,16 mov si,[noblocks] xor edi,edi ; Since noblocks = number of ; 64k blocks, these lines leave ; si:di holding byte size mov eax,800h int 31h jnc .mappedphysicalarea mov edx,.unablemap jmp VESA2EXITTODOS ; Failure!!! .unablemap db 'Unable to map physical area.',0 .mappedphysicalarea shl ebx,16 mov bx,cx mov [LFBpointer],ebx mov eax,ebx sub eax,[ZSNESBase] mov [VESAAddr],eax xor eax,eax xor ebx,ebx xor ecx,ecx xor edx,edx mov ax,4f02h mov bx,[vesamode] int 10h ; Set the vesa mode cmp ax,004fh jz .modesetok mov edx,.unableset jmp VESA2EXITTODOS ; Failure!!! .unableset db 'Unable to initialize video mode.',0 .modesetok ;******************************* EXTRA BIT **************************** ; cmp byte[.whichwin],1 ; Check if Write is at Window B ; jne .nowinB ; ; mov ax,4F05h ; mov bx,1 ; mov dx,0 ; int 10h ; ;.nowinB ; Check logical scanline length mov eax,4f06h mov ebx,1 int 10h cmp cx,[vesa2_x] je .correctwidth mov eax,4f06h ; VBE Set/Get logical scan line ; length mov ebx,0 ; Set scan line length in ; pixels mov ecx, [vesa2_x] ; Desired screen width int 10h cmp ax,04fh jz .correctwidth mov edx, .unablescan jmp VESA2EXITTODOS ; Failure!!! .unablescan db 'Unable to set scan line length.',0 .correctwidth ;*************************** END OF EXTRA BIT ************************* xor eax,eax mov ecx,1 int 31h ; Allocate a descriptor mov bx,ax ; Move our selector into bx mov ecx,[LFBpointer] mov dx,cx shr ecx,16 mov eax,7 int 31h ; Set our selector to LFB jnc .selectornowset mov edx,.unablelfb jmp VESA2EXITTODOS ; Failure!!! .unablelfb db 'Unable to set selector to LFB.',0 .selectornowset xor ecx,ecx mov cx,[noblocks] shl ecx,6 ; Multiply by 64 shl ecx,10 ; And again by 1024 sub ecx,1 ; Necessary!!! mov dx,cx shr ecx,16 ; CX:DX size of screen mov eax,8 int 31h ; Set size of selector jnc .ok mov edx,.unablesets jmp VESA2EXITTODOS ; Failure!!! .unablesets db 'Unable to set size of selector.',0 .ok lar ecx,ebx shr ecx,8 and cl,60h or cl,93h and ch,0c0h ; Keep granularity bit mov ax,9 int 31h ; Set selector access rights jnc .accessrightsset mov edx,.unablesetar jmp VESA2EXITTODOS .unablesetar db 'Unable to set selector access rights.',0 .accessrightsset mov [vesa2selec],bx cmp byte[vesa2red10],1 je .red10 mov eax,565 jmp .red11 .red10 mov eax,555 .red11 push eax call Init_2xSaIMMX pop eax ret NEWSYM LFBpointer dd 0 NEWSYM noblocks dw 0 NEWSYM bytesperscanline dw 0 NEWSYM vesamode dw 0 ;---------------------------------------------------------------------- NEWSYM VESAmodelist times 512 dw 0 ;---------------------------------------------------------------------- NEWSYM RMREGS .edi dd 0 .esi dd 0 .ebp dd 0 .esp dd 0 .ebx dd 0 .edx dd 0 .ecx dd 0 .eax dd 0 .flags dw 0 .es dw 0 .ds dw 0 .fs dw 0 .gs dw 0 .ip dw 0 .cs dw 0 .sp dw 0 .ss dw 0 .spare times 20 dd 0 ;---------------------------------------------------------------------- NEWSYM Vesa2AsmEnd