home *** CD-ROM | disk | FTP | other *** search
- PAGE 80,132
- TITLE - XTASM.ASM - Assembly routines for 3D engine
- ;;;.286P
- ;==============================================================================
- ; COMMAND LINE ASSEMBLY
- ; MASM /B63 /Z /D_Mx FILENAME;
- ;
- ; WHERE Mx SPECIFIES MODEL (l OR c) FOR LARGE OR COMPACT MODELS
- ;==============================================================================
- INCLUDE ET.EQU
- INCLUDE ET.MAC
-
- ANGLE_30 equ 160
- ANGLE_360 equ 1920
-
- extrn _bMaps:DWORD
- extrn _oMaps:DWORD
- extrn _bdfp:DWORD
- extrn _PageBegin:WORD
- extrn _InvCosTable:DWORD
- extrn _InvSinTable:DWORD
- extrn _LongCosTable:DWORD
- extrn _DistanceTable:WORD
- extrn _AdjustTable:DWORD
- extrn _CenterRow:WORD
- extrn _MaxDistance:WORD
- extrn _TopColor:WORD
- extrn _BottomColor:WORD
-
- extrn _lowmask:BYTE
- extrn _Walls:WORD
-
-
- extrn _xRay:NEAR
- extrn _yRay:NEAR
- extrn N_LDIV@:FAR
-
-
- PUBLIC _graphinit
- PUBLIC _usepage
- PUBLIC _flippage
- PUBLIC _SetPalette
- PUBLIC _DrawWalls
- PUBLIC _DrawOneObject
-
- SC_INDEX equ 03c4h ;Sequence Controller Index
- CRTC_INDEX equ 03d4h ;CRT Controller Index
- MISC_OUTPUT equ 03c2h ;Miscellaneous Output register
- SCREEN_SEG equ 0a000h ;segment of display memory in mode X
-
-
- _TEXT segment byte public 'CODE'
- DGROUP group _DATA,_BSS
- assume cs:_TEXT,ds:DGROUP
- _ViewPage dw 0 ; The address of the current view page
- _WritePage dw 0 ; The address of the current write page
- PageTable dw 4 dup (0) ; Address of 4 pages
- ScreenWidth dw 320/4 ; The width of the screen
- PageSize dw 320/4*240 ; The size of each page
- CRTParms label word
- dw 00d06h ;vertical total
- dw 03e07h ;overflow (bit 8 of vertical counts)
- dw 04209h ;cell height (2 to double-scan)
- dw 0ea10h ;v sync start
- dw 0ac11h ;v sync end and protect cr0-cr7
- dw 0df12h ;vertical displayed
- dw 00014h ;turn off dword mode
- dw 0e715h ;v blank start
- dw 00616h ;v blank end
- dw 0e317h ;turn on byte mode
- CRT_PARM_LENGTH equ (($-CRTParms)/2)
-
- _TEXT ends
- _DATA segment word public 'DATA'
- ; Index/data pairs for CRT Controller registers that differ between
- ; mode 13h and mode X.
- _d@ label byte
- _DATA ends
- _BSS segment word public 'BSS'
- _b@ label byte
- _BSS ends
-
-
- public _graphinit
- public _ViewPage,_WritePage
- public ScreenWidth,PageSize,PageTable
-
-
- _TEXT SEGMENT byte public 'CODE'
- ASSUME cs:_TEXT
-
- ;==============================================================================
- ; void graphinit(int width,int psize,int mask)
- ; width - width of the screen in bytes/plane (defaults to 320/4 if 0)
- ; psize - size of each page in bytes/plane (defaults to 320*200/4 if 0)
- ;==============================================================================
- PBEGIN _graphinit
- push bp
- mov bp,sp
- push si
- push di
- push ds
-
- mov ax,cs
- mov ds,ax
- mov es,ax
-
- mov bx,320/4
- mov cs:[ScreenWidth],bx
- mov bx,320/4*240
- mov cs:[PageSize],bx
-
- ; Set up the page table
-
- xor ax,ax
- mov bx,cs:[PageSize]
- lea di,cs:[PageTable]
- mov cx,4
- init4:
- stosw
- add ax,bx
- loop init4
-
-
- ; Now set up the graphics mode
-
- mov ax,13h
- int 10h ; Set 320x200x256
-
- mov dx,3d4h
- mov al,13h
- out dx,al
- inc dx
- mov al,2dh ;Set bytes per line at 90
- out dx,al
-
- mov dx,3c4h
- mov al,4
- out dx,al
- inc dx
- in al,dx
- and al,0f7h ;Turn off chain4 mode
- out dx,al
-
- mov dx,3d4h
- mov al,17h
- out dx,al
- inc dx
- in al,dx
- or al,40h ;Turn on byte mode
- out dx,al
-
- mov dx,3d4h
- mov al,14h
- out dx,al
- inc dx
- in al,dx
- and al,0bfh ;Turn off double-word mode
- out dx,al
-
- mov dx,3dah
- in al,dx
- mov dx,3c0h
- mov al,30h ;Select Attribute index 10h
- out dx,al
- mov al,71h ;Turn on PCS, PPC and G/A
- out dx,al
-
- mov ax,SCREEN_SEG ;now clear all display memory, 8 pixels
- mov es,ax ; at a time
- sub di,di ;point ES:DI to display memory
- sub ax,ax ;clear to zero-value pixels
- mov cx,8000h ;# of words in display memory
- rep stosw ;clear all of display memory
-
- pop ds
- pop di ;restore C register vars
- pop si
- pop bp ;restore caller's stack frame
- ret
- _graphinit endp
-
- ;==============================================================================
- ; void SetVGAmode(void);
- ;==============================================================================
- PBEGIN _SetVGAmode
- push bp
- mov ax,13h
- int 10h ; Set 320x200x256
- pop bp
- ret
- _SetVGAmode endp
-
- ;==============================================================================
- ; void usepage(int page)
- ;==============================================================================
- UPnum equ [bp+ABASE]
-
- PBEGIN _usepage
- push bp
- mov bp,sp
- mov bx,UPnum
- and bx,3
- shl bx,1
- mov ax,cs:PageTable[bx]
- mov cs:[_WritePage],ax
- pop bp
- ret
- _usepage endp
-
- ;==============================================================================
- ; void flippage()
- ;
- ; NOTE: Some lines have been commented out for test purposes. If you experience
- ; flicker when the page flips, un-comment the lines waiting for vertical
- ; retrace.
- ;==============================================================================
- PBEGIN _flippage
- mov cx,cs:[_ViewPage]
- xchg cx,cs:[_WritePage]
- mov cs:[_ViewPage],cx ; An ISR will set the VGA at the next retrace
-
- mov bh,0dH
- mov bl,cl
- mov dx,3dah
-
- Ret1:
- ;;;; in al,dx
- ;;;; test al,1
- ;;;; jnz Ret1 ; Wait for display enable
-
-
-
- ; cli
- mov al,0ch
- mov ah,ch
- mov dx,3d4h
- out dx,ax ; set the displayed offset (high)
- ; inc al
- ; mov ah,cl
- ;;; mov ax,bx
- ;;; out dx,ax ; set the displayed offset (low)
- ; sti
-
- ;; mov dx,3dah
- Ret2:
- ;; in al,dx
- ;; test al,8
- ;; jz Ret2 ; Wait for the video card to use the address just set
-
- ret
- _flippage endp
-
-
- ;==============================================================================
- ; void SetPalette(unsigned char far *PalBuf);
- ;==============================================================================
- SPbuf equ [bp+ABASE]
-
- PBEGIN _SetPalette
- push bp
- mov bp,sp
- push ds
- push si
-
- lds si,dword ptr SPbuf
- mov cx,256
- xor bx,bx
- cld
- mov dx,3C8H
- sp010:
- mov al,bl
- out dx,al
- inc dx
- lodsb
- out dx,al
- lodsb
- out dx,al
- lodsb
- out dx,al
- dec dx
- inc bx
- loop sp010
-
- pop si
- pop ds
- pop bp
- ret
- _SetPalette endp
-
- ;==============================================================================
- ; void DrawWalls(void);
- ;==============================================================================
- Y2 equ [bp-2]
- AVLOW equ [bp-4]
- AVHI equ [bp-6]
- VCOL equ [bp-8]
- BOFFLOW equ [bp-10]
- BOFFHI equ [bp-12]
- sColor equ [bp-14]
- fColor equ [bp-16]
-
- PBEGIN _DrawWalls
- push bp
- mov bp,sp
- sub sp,18
- push ds
- push si
- push di
-
- mov dx,3c4H
- mov ax,0F02H
- out dx,ax ;Select map mask and all planes
-
- mov bx,word ptr DGROUP:_MaxDistance ; Get max distance to wall
- shl bx,1 ; Make a word index
- mov ax,word ptr DGROUP:_DistanceTable[bx] ;Look up actual height
- cmp ax,200 ; Full screen height?
- jae drw000 ; Yes, nothing to fill in
-
- and ax,0FFFEH ; Strip any odd values
- mov bx,ax ; Save height
- mov si,ax ; Again save height
- shr bx,1 ; Get Height / 2
- mov dx,100 ; Pick up our center row
- sub dx,bx ; and sub ht/2
- mov bx,dx ; Save new value
-
- mov ax,90
- imul dx
- mov bx,ax
- mov ax,90
- imul si
- mov si,ax
-
- ; mov cl,6 ; Get ready to mult by 80
- ; shl bx,cl ; first mult by 64
- ; shl si,cl ; also mult the original ht
- ; mov cl,4 ; No do a mult by 16
- ; shl dx,cl ; to top layer
- ; shl ax,cl ; and initial height
- ; add bx,dx ; Add x64 and x16 for x80
- ; add si,ax ; do same with height
-
- mov ax,0A000H
- mov es,ax
- mov di,cs:_WritePage ;get start of buffer
-
- mov ax,ds:_TopColor
- mov ah,al
- shr bx,1 ;only fill words
- mov cx,bx ;get amount to fill in
- rep stosw
- add di,si ;then skip amount of wall
- mov ax,ds:_BottomColor
- mov ah,al
- mov cx,bx
- rep stosw
-
-
- drw000:
- xor bx,bx ;Initial loop/plane counter
-
- drw010:
- push bx ;save loop/plane counter
- mov VCOL,bx ;Set beginning video column
- mov dx,3c5H
- mov al,byte ptr DGROUP:_lowmask[bx]
- out dx,al ;select mask to write to
- mov si,offset _Walls ; Point to wall array
- shl bx,1
- shl bx,1
- shl bx,1 ;x 8 for correct wall structure
- add si,bx
-
- mov cx,80 ;Number of walls to display
- drw020:
- push ds ;save data segment
- push si ;save wall pointer
- push cx ;save wall count
- lodsw ;Get bitmap number
- xchg ax,bx ;use bx as the index
- shl bx,1
- shl bx,1 ;dword index into bitmap table
- mov di,word ptr DGROUP:_bMaps[bx] ;offset to bitmap
- mov es,word ptr DGROUP:_bMaps[bx+2] ;segment of bitmap
- lodsw ;get bitmap column to display
- mov cl,6
- shl ax,cl ;x64 to get correct row
- add di,ax ;and add to bitmap offset
- lodsw ;get bitmap distance
- shl ax,1 ; Make word index for table lookup
- mov si,ax ;save distance
- mov bx,word ptr DGROUP:_DistanceTable[si] ;get height of bitmap
-
- mov cx,100
- mov ax,bx ; Pick up the height
- shr ax,1 ; Divide by two
- sub cx,ax ; And subtract from center for Y1
-
- mov ax,cx ; Start with Y1
- add ax,bx ; and add height to it for Y2
-
- cmp ax,199 ; Don't let Y2 go beyond screen height
- jle short drw030
- mov ax,199 ; Else force it to screen height
- drw030:
- mov Y2,ax ;save y2
- shl si,1 ; Turn object distance into dword index
-
- mov ax,word ptr DGROUP:_AdjustTable[si+2]
- mov dx,word ptr DGROUP:_AdjustTable[si]
-
- mov AVHI,ax ; Get (64 * 65536) / height
- mov AVLOW,dx
- xchg si,di ;si now points to bitmap
- mov di,VCOL ; Video column to display at
- sar di,1 ; Divide by 4 to get correct planar col
- sar di,1 ; Divide by 4 to get correct planar col
- add di,word ptr cs:_WritePage ; Add in page offset
- mov ax,es ; Pick up segment to bitmap
- mov ds,ax ; now ds:si points to bitmap
- mov ax,0A000H ; Video segment
- mov es,ax ; now es:di points to screen
- mov word ptr BOFFLOW,0 ; Initialize the current bitmap offset
- mov word ptr BOFFHI,0
-
- cmp cx,word ptr Y2 ; is Y1 > Y2?
- jge short drw090 ; Yes, get on out
- or cx,cx ; Y1 <= 0?
- jle drw050 ; Yes, no sky color needed
-
- ; mov ax,cx ; Get copy of Y1
- ; mov bx,cx ; and another copy
- ; mov cl,6
- ; shl ax,cl ; do a mult 64
- ; add di,ax ; and add to video offset
- ; mov cl,4
- ; mov ax,bx ; get original Y1
- ; shl ax,cl ; do a mult 16
- ; add di,ax ; and add to video for a mult 80
- ; xchg cx,bx ; restore original Y1
-
- mov ax,90
- imul cx
- add di,ax
-
- drw050:
- mov bx,89 ; Offset to next video row
- mov dx,AVLOW ; Hold onto lsb of adjustment
- mov ax,AVHI ; Pick up msb of bitmap adjustment
-
- ;------------------------------------------------------------------------------
- ; Here is where the actual bitmap is transferred to the screen. Better
- ; optimization could be done by precalculating the adjustment factor instead
- ; of looping until Y1 >= 0. This has not been tried so I don't know if the
- ; speed would make it worth it....
- ;------------------------------------------------------------------------------
- drw060:
- or cx,cx ; Is Y1 still < 0 ?
- jl short drw070 ; Yes, don't start drawing yet
-
- movsb ;Move bitmap to video
- dec si
- add di,bx ;next row of video
-
- drw070:
- add word ptr BOFFLOW,dx ; Add lsb to current offset
- adc si,ax ; Use msb to get next bitmap location
- inc cx ; Next y1
- cmp cx,word ptr Y2 ; Beyond Y2 yet?
- jl short drw060 ; Nope, keep looping
-
- drw090:
- pop cx ;get wall count
- pop si ;recover structure pointer
- pop ds
- add si,32 ;Wall structure size * 4
- add word ptr VCOL,4 ;next video column to display at
- dec cx
- jz drw100
- jmp drw020 ;next wall to display
-
- drw100:
- pop bx ;recover loop/plane counter
- inc bx
- cmp bx,4 ;all 4 planes?
- je drwDone
- jmp drw010
-
- drwDone:
- mov dx,3c5H
- mov al,0FFH ;Enable all planes again
- out dx,al
- pop di
- pop si
- pop ds
- mov sp,bp
- pop bp
- ret
- _DrawWalls endp
-
- ;==============================================================================
- ; +4 +6 +8 +10 +12
- ; void DrawOneObject(int ObjNum,int ObjCol,int ObjDist,int VidCol,int PageNum);
- ;==============================================================================
- PBEGIN _DrawOneObject
- push bp
- mov bp,sp
- sub sp,20
- push si
- push di
- push ds
-
- mov cx,word ptr [bp+10] ; Video column
- and cx,3 ; Only need lower three bits
- mov ah,11h
- rol ah,cl
- mov al,2
- mov dx,3c4h
- out dx,ax
-
- mov bx,word ptr [bp+8] ; Get the distance to the bitmap
- shl bx,1 ; Make word index for table lookup
- mov si,bx ; Save index for now
- mov bx,word ptr DGROUP:_DistanceTable[bx]
-
- dob010:
- mov cx,100
- mov ax,bx ; Pick up the height
- shr ax,1 ; Divide by two
- sub cx,ax ; And subtract from center for Y1
-
- mov di,cx ; Start with Y1
- add di,bx ; and add height to it for Y2
-
- cmp di,199 ; Don't let Y2 go beyond screen height
- jle short dob020
- mov di,199 ; Else force it to screen height
-
- dob020:
- mov word ptr [bp-2],di ;save y2
- shl si,1 ; Turn object distance into dword index
-
- mov ax,word ptr DGROUP:_AdjustTable[si+2]
- mov dx,word ptr DGROUP:_AdjustTable[si]
-
- mov word ptr [bp-14],ax ; Get (64 * 65536) / height
- mov word ptr [bp-16],dx
-
- mov bx,word ptr [bp+4] ; Bitmap number to display
- shl bx,1 ; dword index
- shl bx,1 ; dword index
- mov ax,word ptr DGROUP:_oMaps[bx+2]
- mov dx,word ptr DGROUP:_oMaps[bx]
-
- mov bx,word ptr [bp+6] ; Bitmap column to display
- shl bx,1
- shl bx,1
- shl bx,1
- shl bx,1
- shl bx,1
- shl bx,1 ; x 64 to get correct bitmap row
- add dx,bx ; then add to start of bitmap
- mov word ptr [bp-6],ax
- mov word ptr [bp-8],dx
-
- mov di,word ptr [bp+10] ; Video column to display at
- sar di,1 ; Divide by 4 to get correct planar col
- sar di,1 ; Divide by 4 to get correct planar col
- mov bx,word ptr [bp+12] ; Page number to display at
- shl bx,1 ; Make a word index
- add di,word ptr DGROUP:_PageBegin[bx] ;Pick up actual offset
- mov ax,0A000H ; Video segment
- mov es,ax
- mov word ptr [bp-18],0 ; Initialize the current bitmap offset
- mov word ptr [bp-20],0
-
- or cx,cx ; Is Y1 > 0 ?
- jle short dob030 ; Nope, start above video
-
- ; xchg si,cx ; hold onto original value
- ; mov ax,si ; get Y1 coordinate
- ; mov cl,6 ; mult by 64
- ; shl ax,cl
- ; mov dx,si ; get back Y1
- ; mov cl,4
- ; shl dx,cl ; mult by 16
- ; add ax,dx ; now add to Y1 * 64 to get Y1 * 80
- ; add di,ax ; and add to start of video
- ; xchg cx,si ; get back original Y1
-
- mov ax,90
- imul cx
- add di,ax
-
- dob030:
- cmp cx,word ptr [bp-2] ; is Y1 > Y2?
- jge short dob090 ; Yes, get on out
-
- mov bx,90 ;Amount to next row of video
- lds si,dword ptr [bp-8] ;Get image buffer
- mov dx,word ptr [bp-16] ; Hold onto lsb of adjustment
-
- dob040:
- or cx,cx ; Is Y1 still < 0 ?
- jl short dob080 ; Yes, don't start drawing yet
-
- lodsb
- dec si
- or al,al ;Transparent color?
- jz dob050 ;Yes, don't write it to video
- mov byte ptr es:[di],al ;place character in video
-
- dob050:
- add di,bx ;next row of video
-
- dob080:
- mov ax,word ptr [bp-14] ; Pick up msb of bitmap adjustment
- add word ptr [bp-20],dx ; and add to current offset
- adc si,ax ; Keep the msb correct
- inc cx ; Next y1
- cmp cx,word ptr [bp-2] ; Beyond Y2 yet?
- jl short dob040 ; Nope, keep looping
-
- dob090:
- pop ds
- pop di
- pop si
- mov sp,bp
- pop bp
- ret
- _DrawOneObject endp
-
-
- _TEXT ENDS
- END
-