; 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-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. .386 _DATA SEGMENT BYTE PUBLIC USE32 'DATA' INCLUDE psmacros.inc INCLUDE TWEAK.INC INCLUDE VGAREGS.INC extd _gr_var_bwidth extd _modex_line_vertincr extd _modex_line_incr1 extd _modex_line_incr2 _modex_line_routine dd ? extd _modex_line_x1 extd _modex_line_y1 extd _modex_line_x2 extd _modex_line_y2 extb _modex_line_Color SavedColor db ? LEFT_MASK1 = 1000b LEFT_MASK2 = 1100b LEFT_MASK3 = 1110b RIGHT_MASK1 = 0001b RIGHT_MASK2 = 0011b RIGHT_MASK3 = 0111b ALL_MASK = 1111b tmppal db 768 dup (0) fb_pal dd ? fb_add dw ? fb_count dd ? MaskTable1 db ALL_MASK AND RIGHT_MASK1, ALL_MASK AND RIGHT_MASK2, ALL_MASK AND RIGHT_MASK3, ALL_MASK, LEFT_MASK3 AND RIGHT_MASK1, LEFT_MASK3 AND RIGHT_MASK2, LEFT_MASK3 AND RIGHT_MASK3, LEFT_MASK3, LEFT_MASK2 AND RIGHT_MASK1, LEFT_MASK2 AND RIGHT_MASK2, LEFT_MASK2 AND RIGHT_MASK3, LEFT_MASK2, LEFT_MASK1 AND RIGHT_MASK1, LEFT_MASK1 AND RIGHT_MASK2, LEFT_MASK1 AND RIGHT_MASK3, LEFT_MASK1, MaskTable2 db ALL_MASK,RIGHT_MASK1, ALL_MASK,RIGHT_MASK2, ALL_MASK,RIGHT_MASK3, ALL_MASK,ALL_MASK, LEFT_MASK3,RIGHT_MASK1, LEFT_MASK3,RIGHT_MASK2, LEFT_MASK3,RIGHT_MASK3, LEFT_MASK3,ALL_MASK, LEFT_MASK2,RIGHT_MASK1, LEFT_MASK2,RIGHT_MASK2, LEFT_MASK2,RIGHT_MASK3, LEFT_MASK2,ALL_MASK, LEFT_MASK1,RIGHT_MASK1, LEFT_MASK1,RIGHT_MASK2, LEFT_MASK1,RIGHT_MASK3, LEFT_MASK1,ALL_MASK DrawTable dd DrawMR, DrawMR, DrawMR, DrawM, DrawLMR, DrawLMR, DrawLMR, DrawLM, DrawLMR, DrawLMR, DrawLMR, DrawLM, DrawLMR, DrawLMR, DrawLMR, DrawLM _DATA ENDS DGROUP GROUP _DATA _TEXT SEGMENT BYTE PUBLIC USE32 'CODE' ASSUME DS:_DATA ASSUME CS:_TEXT PUBLIC gr_sync_display_ gr_sync_display_: push ax push dx mov dx, VERT_RESCAN VS2A: in al, dx and al, 08h jnz VS2A ; Loop until not in vertical retrace VS2B: in al, dx and al, 08h jz VS2B ; Loop until in vertical retrace pop dx pop ax ret PUBLIC gr_modex_uscanline_ gr_modex_uscanline_: push edi ; EAX = X1 (X1 and X2 don't need to be sorted) ; EDX = X2 ; EBX = Y ; ECX = Color mov SavedColor, cl ;mov ebx, _RowOffset[ebx*4] mov edi, _gr_var_bwidth imul edi, ebx add edi, 0A0000h cmp eax, edx jle @f xchg eax, edx @@: mov bl, al shl bl, 2 mov bh, dl and bh, 011b or bl, bh and ebx, 0fh ; BX = LeftRight switch command. (4bit) shr eax, 2 shr edx, 2 add edi, eax ; EDI = Offset into video memory mov ecx, edx sub ecx, eax ; ECX = X2/4 - X1/4 - 1 jnz LargerThan4 ;======================= ONE GROUP OF 4 OR LESS TO DRAW ==================== mov dx, SC_INDEX mov al, SC_MAP_MASK out dx, al inc dx mov al, MaskTable1[ebx] out dx, al mov al, SavedColor mov [edi], al ; Write the one pixel pop edi ret LargerThan4: dec ecx jnz LargerThan8 ;===================== TWO GROUPS OF 4 OR LESS TO DRAW ==================== mov cx, WORD PTR MaskTable2[ebx*2] mov bl, SavedColor mov dx, SC_INDEX mov al, SC_MAP_MASK out dx, al inc dx mov al, cl out dx, al mov [edi], bl ; Write the left pixel mov al, ch out dx, al mov [edi+1], bl ; Write the right pixel pop edi ret ;========================= MANY GROUPS OF 4 TO DRAW ====================== LargerThan8: mov dx, SC_INDEX mov al, SC_MAP_MASK out dx, al inc dx ; DX = SC_INDEX mov al, SavedColor mov ah, al ; AL,AH = color of pixel jmp NEAR32 PTR DrawTable[ebx*4] DrawM: ;AH=COLOR, EDI=DEST, CX=X2/4-X1/4-1, BX=Table Index mov al, ALL_MASK out dx, al mov al, ah cld add ecx, 2 shr ecx, 1 rep stosw ; Write the middle pixels jnc @F stosb ; Write the middle odd pixel @@: pop edi ret DrawLM: ;AH=COLOR, EDI=DEST, CX=X2/4-X1/4-1, BX=Table Index mov al, BYTE PTR MaskTable2[ebx*2] out dx, al mov [edi], ah ; Write leftmost pixels inc edi mov al, ALL_MASK out dx, al mov al, ah cld inc ecx shr ecx, 1 rep stosw ; Write the middle pixels jnc @F stosb ; Write the middle odd pixel @@: pop edi ret DrawLMR: ;AH=COLOR, EDI=DEST, CX=X2/4-X1/4-1, BX=Table Index mov bx, WORD PTR MaskTable2[ebx*2] mov al, bl out dx, al mov [edi], ah ; Write leftmost pixels inc edi mov al, ALL_MASK out dx, al mov al, ah cld shr ecx, 1 rep stosw ; Write the middle pixels jnc @F stosb ; Write the middle odd pixel @@: mov al, bh out dx, al mov [edi], ah ; Write the rightmost pixels pop edi ret DrawMR: ;AH=COLOR, EDI=DEST, CX=X2/4-X1/4-1, BX=Table Index mov bx, WORD PTR MaskTable2[ebx*2] mov al, ALL_MASK out dx, al mov al, ah cld inc ecx shr ecx, 1 rep stosw ; Write the middle pixels jnc @F stosb ; Write the middle odd pixel @@: mov al, bh out dx, al mov [edi], ah ; Write the rightmost pixels pop edi ret PUBLIC gr_modex_setmode_ gr_modex_setmode_: push ebx push ecx push edx push esi push edi mov ecx, eax dec ecx cmp ecx, LAST_X_MODE jbe @f mov ecx, 0 @@: ;call turn_screen_off push ecx ; some bios's dont preserve cx ;mov ax, 1201h ;mov bl, 31h ; disable palette loading at mode switch ;int 10h mov ax,13h ; let the BIOS set standard 256-color int 10h ; mode (320x200 linear) ;mov ax, 1200h ;mov bl, 31h ; enable palette loading at mode switch ;int 10h pop ecx mov dx,SC_INDEX mov ax,0604h out dx,ax ; disable chain4 mode mov dx,SC_INDEX mov ax,0100h out dx,ax ; synchronous reset while setting Misc ; Output for safety, even though clock ; unchanged mov esi, dword ptr ModeTable[ecx*4] lodsb or al,al jz DontSetDot mov dx,MISC_OUTPUT out dx,al ; select the dot clock and Horiz ; scanning rate ;mov dx,SC_INDEX ;mov al,01h ;out dx,al ;inc dx ;in al, dx ;or al, 1000b ;out dx, al DontSetDot: mov dx,SC_INDEX mov ax,0300h out dx,ax ; undo reset (restart sequencer) mov dx,CRTC_INDEX ; reprogram the CRT Controller mov al,11h ; VSync End reg contains register write out dx,al ; protect bit inc dx ; CRT Controller Data register in al,dx ; get current VSync End register setting and al,07fh ; remove write protect on various out dx,al ; CRTC registers dec dx ; CRT Controller Index cld xor ecx,ecx lodsb mov cl,al SetCRTParmsLoop: lodsw ; get the next CRT Index/Data pair out dx,ax ; set the next CRT Index/Data pair loop SetCRTParmsLoop mov dx,SC_INDEX mov ax,0f02h out dx,ax ; enable writes to all four planes mov edi, 0A0000h ; point ES:DI to display memory xor ax,ax ; clear to zero-value pixels mov ecx,8000h ; # of words in display memory rep stosw ; clear all of display memory ; Set pysical screen dimensions xor eax, eax lodsw ; Load scrn pixel width mov cx, ax shl eax, 16 mov dx,CRTC_INDEX mov al,CRTC_OFFSET out dx,al inc dx mov ax,cx shr ax,3 out dx,al ;mov si, 360 ;@@: ;mov ax, 04f06h ;mov bl, 0 ;mov cx, si ;int 10h ;cmp cx, si ;je @f ;inc si ;jmp @B ;@@: ;movzx eax, si lodsw ; Load Screen Phys. Height ;call turn_screen_on pop edi pop esi pop edx pop ecx pop ebx ret PUBLIC gr_modex_setplane_ gr_modex_setplane_: push cx push dx mov cl, al ; SELECT WRITE PLANE and cl,011b ;CL = plane mov ax,0100h + MAP_MASK ;AL = index in SC of Map Mask reg shl ah,cl ;set only the bit for the required ; plane to 1 mov dx,SC_INDEX ;set the Map Mask to enable only the out dx,ax ; pixel's plane ; SELECT READ PLANE mov ah,cl ;AH = plane mov al,READ_MAP ;AL = index in GC of the Read Map reg mov dx,GC_INDEX ;set the Read Map to read the pixel's out dx,ax ; plane pop dx pop cx ret PUBLIC gr_modex_setstart_ gr_modex_setstart_: ; EAX = X ; EDX = Y ; EBX = Wait for retrace push ebx push ecx push ebx mov ecx, _gr_var_bwidth imul ecx, edx shr eax, 2 add eax, ecx mov ch, ah mov bh, al mov bl, CC_START_LO mov cl, CC_START_HI cli mov dx, VERT_RESCAN WaitDE: in al, dx test al, 01h jnz WaitDE mov dx, CRTC_INDEX mov ax, bx out dx, ax ; Start address low mov ax, cx out dx, ax ; Start address high sti pop ebx cmp ebx, 0 je NoWaitVS mov dx, VERT_RESCAN WaitVS: in al, dx test al, 08h jz WaitVS ; Loop until in vertical retrace NoWaitVS: pop ecx pop ebx ret ModeXAddr macro ; given: ebx=x, eax=y, return cl=plane mask, ebx=address, trash eax mov cl, bl and cl, 3 shr ebx, 2 imul eax, _gr_var_bwidth add ebx, eax add ebx, 0A0000h endm ;----------------------------------------------------------------------- ; ; Line drawing function for all MODE X 256 Color resolutions ; Based on code from "PC and PS/2 Video Systems" by Richard Wilton. PUBLIC gr_modex_line_ gr_modex_line_: pusha mov dx,SC_INDEX ; setup for plane mask access ; check for vertical line mov esi,_gr_var_bwidth mov ecx,_modex_line_x2 sub ecx,_modex_line_x1 jz VertLine ; force x1 < x2 jns L01 neg ecx mov ebx,_modex_line_x2 xchg ebx,_modex_line_x1 mov _modex_line_x2,ebx mov ebx,_modex_line_y2 xchg ebx,_modex_line_y1 mov _modex_line_y2,ebx ; calc dy = abs(y2 - y1) L01: mov ebx,_modex_line_y2 sub ebx,_modex_line_y1 jnz short skip jmp HorizLine skip: jns L03 neg ebx neg esi ; select appropriate routine for slope of line L03: mov _modex_line_vertincr,esi mov _modex_line_routine,offset LoSlopeLine cmp ebx,ecx jle L04 mov _modex_line_routine,offset HiSlopeLine xchg ebx,ecx ; calc initial decision variable and increments L04: shl ebx,1 mov _modex_line_incr1,ebx sub ebx,ecx mov esi,ebx sub ebx,ecx mov _modex_line_incr2,ebx ; calc first pixel address push ecx mov eax,_modex_line_y1 mov ebx,_modex_line_x1 ModeXAddr mov edi,ebx mov al,1 shl al,cl mov ah,al ; duplicate nybble shl al,4 add ah,al mov bl,ah pop ecx inc ecx jmp [_modex_line_routine] ; routine for verticle lines VertLine: mov eax,_modex_line_y1 mov ebx,_modex_line_y2 mov ecx,ebx sub ecx,eax jge L31 neg ecx mov eax,ebx L31: inc ecx mov ebx,_modex_line_x1 push ecx ModeXAddr mov ah,1 shl ah,cl mov al,MAP_MASK out dx,ax pop ecx mov ax, word ptr _modex_line_Color ; draw the line L32: mov [ebx],al add ebx,esi loop L32 jmp Lexit ; routine for horizontal line HorizLine: mov eax,_modex_line_y1 mov ebx,_modex_line_x1 ModeXAddr mov edi,ebx ; set dl = first byte mask mov dl,00fh shl dl,cl mov ecx,_modex_line_x2 ; set dh = last byte mask and cl,3 mov dh,00eh shl dh,cl not dh ; determine byte offset of first and last pixel in line mov eax,_modex_line_x2 mov ebx,_modex_line_x1 shr eax,2 ; set ax = last byte column shr ebx,2 ; set bx = first byte column mov ecx,eax ; cx = ax - bx sub ecx,ebx mov eax,edx ; mov end byte masks to ax mov dx,SC_INDEX ; setup dx for VGA outs mov bl,_modex_line_Color ; set pixels in leftmost byte of line or ecx,ecx ; is start and end pt in same byte jnz L42 ; no ! and ah,al ; combine start and end masks jmp short L44 L42: push eax mov ah,al mov al,MAP_MASK out dx,ax mov al,bl stosb dec ecx ; draw remainder of the line L43: mov ah,0Fh mov al,MAP_MASK out dx,ax mov al,bl rep stosb pop eax ; set pixels in rightmost byte of line L44: mov al,MAP_MASK out dx, ax mov byte ptr [edi],bl jmp Lexit ; routine for dy >= dx (slope <= 1) LoSlopeLine: mov al,MAP_MASK mov bh,byte ptr _modex_line_Color L10: mov ah,bl L11: or ah,bl rol bl,1 jc L14 ; bit mask not shifted out or esi,esi jns L12 add esi,_modex_line_incr1 loop L11 out dx,ax mov [edi],bh jmp short Lexit L12: add esi,_modex_line_incr2 out dx,ax mov [edi],bh add edi,_modex_line_vertincr loop L10 jmp short Lexit ; bit mask shifted out L14: out dx,ax mov [edi],bh inc edi or esi,esi jns L15 add esi,_modex_line_incr1 loop L10 jmp short Lexit L15: add esi,_modex_line_incr2 add edi,_modex_line_vertincr loop L10 jmp short Lexit ; routine for dy > dx (slope > 1) HiSlopeLine: mov ebx,_modex_line_vertincr mov al,MAP_MASK L21: out dx,ax push eax mov al,_modex_line_Color mov [edi],al pop eax add edi,ebx L22: or esi,esi jns L23 add esi,_modex_line_incr1 loop L21 jmp short Lexit L23: add esi,_modex_line_incr2 rol ah,1 adc edi,0 lx21: loop L21 ; return to caller Lexit: popa ret _TEXT ENDS END