ravenengine/SOURCE/RA_DRAW.ASM
2014-12-12 00:00:00 +00:00

577 lines
13 KiB
NASM

.386
.MODEL small
SKIPPRIMITIVES = 0 ; set to 1 to skip unwound drawing
INCLUDE viewsize.inc
INCLUDE macros.inc
SCREEN = 0a0000h
SCREENWIDTH = 320
PEL_WRITE_ADR = 03c8h
PEL_DATA = 03c9h
.DATA
EXTRN viewbuffer:WORD
EXTRN viewLocation:DWORD
EXTRN viewylookup;DWORD
EXTRN windowWidth:DWORD
EXTRN windowHeight:DWORD
.CODE
;============================================================================
;
; Fixed point math
;
;============================================================================
@Proc FIXEDMUL, <>, <<op1,DWORD>,<op2,DWORD>>
mov eax,op1
imul [op2]
shrd eax,edx,16
@exitp <>
ENDP
@Proc FIXEDDIV, <>, <<op1,DWORD>,<op2,DWORD>>
mov eax,op1
cdq
shld edx,eax,16
sal eax,16
idiv [op2]
endz:
@exitp <>
ENDP
;============================================================================
;
; RF_BlitView
;
;============================================================================
@Proc RF_BlitView, <ebx, esi, edi>
mov esi,OFFSET viewbuffer
mov edi,[viewLocation]
mov ebx,[windowHeight]
mov eax,SCREENWIDTH
sub eax,[windowWidth]
mov edx,eax ; x modulos
mov eax,[windowWidth]
shr eax,2
ALIGN 4
@@blitloop1:
mov ecx,eax
rep movsd
add edi,edx
dec ebx
jnz @@blitloop1
@exitp <ebx, esi, edi>
ENDP
;============================================================================
;
; ClearViewBuffer
;
;============================================================================
@Proc ClearViewBuffer, <ebx, esi, edi>
mov ebx,[windowHeight]
mov esi,[windowWidth]
mov edx,esi
shr esi,2
xor eax,eax
ALIGN 4
@@clearloop:
dec ebx
mov ecx,esi
mov edi,OFFSET viewylookup
mov edi,[edi+ebx*4]
rep stosd
add edi,edx
cmp ebx,0
jnz @@clearloop
@exitp <ebx, esi, edi>
ENDP
;============================================================================
;
; Merge
;
; merge two parts of the unsorted array to the sorted array
;
;============================================================================
.DATA
EXTRN src1:DWORD
EXTRN src2:DWORD
EXTRN dest:DWORD
EXTRN size1:DWORD
EXTRN size2:DWORD
PUBLIC mergefrom1
PUBLIC finishfrom1
PUBLIC mergefrom2
PUBLIC finishfrom2
PUBLIC mergedone
.CODE
@Proc Merge, <ebx,esi,edi>
mov ebx,[src1]
mov esi,[src2]
mov edi,[dest]
mov ecx,[size1]
mov edx,[size2]
mov eax,[ebx]
cmp eax,[esi]
jb SHORT mergefrom2 ; if (*src1 < *src2) goto mergefrom2;
mergefrom1:
stosd
add ebx,4 ; *dest++ = *src1++;
mov eax,[ebx]
dec ecx
jz finishfrom2 ; if (!--size1) goto finishfrom2;
cmp eax,[esi]
ja SHORT mergefrom1 ; if (*src1 > *src2) goto mergefrom1;
mergefrom2:
movsd ; *dest++ = *src2++;
dec edx
jz finishfrom1 ; if (!--size2) goto finishfrom1;
cmp eax,[esi]
ja SHORT mergefrom1 ; if (*src1 > *src2) goto mergefrom1;
jmp SHORT mergefrom2
ALIGN 4
finishfrom2:
movsd ; *dest++ = *src2++;
dec edx ; while (size2--)
jnz SHORT finishfrom2
jmp SHORT mergedone
ALIGN 4
finishfrom1:
stosd
add ebx,4 ; *dest++ = *src1++;
mov eax,[ebx]
loop SHORT finishfrom1 ; while (size1--)
mergedone:
mov [dest],edi
@exitp <ebx, esi, edi>
ENDP
;============================================================================
;
; unwound vertical scaling code
;
; eax light table pointer, 0 lowbyte overwritten
; ebx all 0, low byte overwritten
; ecx fractional step value
; edx fractional scale value
; esistart of source pixels
; edi bottom pixel in screenbuffer to blit into
;
; ebx should be set to 0 0 0 dh to feed the pipeline
;============================================================================
; the assembler creates vscale<MAXWINDOWHEIGHT-1>: numbers of the following
; code segement. LINE is used as the arg to SCALELABEL. there exists
; vscale<MAXWINDOWHEIGHT: to vscale0: units of code. vscale0 is used as
; the exit point.
SCALELABEL MACRO number
vscale&number:
ENDM
LINE = MAXWINDOWHEIGHT
REPT MAXWINDOWHEIGHT - 1
SCALELABEL %LINE ; LINE represents how many
; ypixels need to be drawn
mov al,[esi+ebx] ; get source pixel
add edx,ecx ; calculate next location
mov al,[eax] ; translate the color
xor ebx,ebx ; clear ebx
shld ebx,edx,16 ; get address of next location
mov [edi-(LINE-1)*MAXWINDOWWIDTH],al
LINE = LINE - 1
ENDM
vscale1:
mov al,[esi+ebx]
add edx,ecx
mov al,[eax]
mov [edi],al
vscale0:
ret
.DATA
; the following 2 macros allocate a block of dd or 4 byte locations that are
; ALIGN'ed on a 4 byte or 32 bit boundary. the starting 4 bytes may be
; referred to as scalecalls. the others may not because in the macro
; SCALEDEFINE they are not given a name. the label scalecalls refers to a
; position in the code which happens to be the start of the allocated block. there are
; MAXWINDOWHEIGHT + 1 4 byte word's are allocated and each word is initialized
; with the address of vscale<LINE>:. the value of LINE ranges from 0 to
; MAXWINDOWWIDTH. scalecalls is made visible to the other modules with the
; PUBLIC directive.
SCALEDEFINE MACRO number
dd vscale&number
ENDM
ALIGN 4
scalecalls LABEL UNKNOWN
LINE = 0
REPT MAXWINDOWHEIGHT + 1
SCALEDEFINE %LINE
LINE = LINE + 1
ENDM
scalecall dd 0
PUBLIC scalecalls
;=================================================
;
; parameters for RN_ScalePost
;
sp_dest dd 0
sp_count dd 0
sp_fracstep dd 0
sp_frac dd 0
sp_source dd 0
sp_colormap dd 0
PUBLIC sp_dest, sp_count, sp_fracstep, sp_frac, sp_source, sp_colormap
.CODE
;================
;
; ScalePost
;
;================
@Proc ScalePost, <ebx, esi, edi, ebp>
IFE SKIPPRIMITIVES
mov edx,[sp_frac]
mov ecx,[sp_fracstep]
mov esi,[sp_source]
mov eax,[sp_colormap]
mov edi,[sp_dest]
xor ebx,ebx
shld ebx,edx,16 ; get address of first location
mov ebp,[sp_count]
call [scalecalls+ebp*4]
ENDIF
@exitp <ebx, esi, edi, ebp>
ENDP
;============================================================================
@Proc GetScaleRoutines
mov eax,OFFSET vscale200
@exitp
ENDP
;
;============================================================================
;
; unwound masked vertical scaling code
;
; eax light table pointer, 0 lowbyte overwritten
; ebx all 0, low byte overwritten
; ecx all 0, low byte overwritten
; edx fractional scale value
; esi start of source pixels
; edi bottom pixel in screenbuffer to blit into
; ebp fractional step value
;
; ebx should be set to 0 0 0 dh to feed the pipeline
;============================================================================
; the assembler creates mvscale<MAXWINDOWHEIGHT-1>: numbers of the following
; code segement. all sections of the code are ALINGN'ed on a 32 bit
; boundary. LINE is used as the arg to MSCALELABEL. there exists
; mvscale<MAXWINDOWHEIGHT: to mvscale0: units of code. mvscale0 is used as
; the exit point.
ALIGN 4
MSCALELABEL MACRO number
mvscale&number:
ENDM
LINE = MAXWINDOWHEIGHT
REPT MAXWINDOWHEIGHT - 1
MSCALELABEL %LINE
mov al,[esi+ebx] ; get source pixel
add edx,ebp ; calculate next location
mov cl,al ; save original color for jcxz
mov al,[eax] ; translate the color
xor ebx,ebx
shld ebx,edx,16 ; get address of next location
jcxz $+9 ; jumps 14 bytes to start of next macro
mov [edi-(LINE-1)*MAXWINDOWWIDTH],al ; draw a pixel to the buffer
LINE = LINE - 1
ENDM
mvscale1:
mov al,[esi+ebx]
add edx,ecx
mov al,[eax]
test al,0
jz mvscale0
mov [edi],al
mvscale0:
ret
.DATA
; the following 2 macros allocate a block of dd or 4 byte locations that are
; ALIGN'ed on a 4 byte or 32 bit boundary. the starting 4 bytes may be
; referred to as mscalecalls. the others may not because in the macro
; MSCALEDEFINE they are not given a name. the label mscalecalls refers to a
; position in the code which happens to be the start of the allocated block. there are
; MAXWINDOWHEIGHT + 1 4 byte word's are allocated and each word is initialized
; with the address of mvscalev<LINE:. the value of LINE ranges from 0 to
; to MAXWINDOWHEIGHT. mscalecalls is made visible to the other modules with
; the PUBLIC directive.
MSCALEDEFINE MACRO number
dd mvscale&number
ENDM
ALIGN 4
mscalecalls LABEL UNKNOWN
LINE = 0
REPT MAXWINDOWHEIGHT + 1
MSCALEDEFINE %LINE
LINE = LINE + 1
ENDM
PUBLIC mscalecalls
mscalecall dd 0
.CODE
;================
;
; ScaleMaskedPost
;
; Same parameters as ScalePost, but 0 pixels are not drawn
;
;================
@Proc ScaleMaskedPost, <ebx, esi, edi, ebp>
IFE SKIPPRIMITIVES
mov ebp,[sp_count]
mov eax,[mscalecalls+ebp*4]
mov [mscalecall],eax
mov edx,[sp_frac]
mov ebp,[sp_fracstep]
mov esi,[sp_source]
mov eax,[sp_colormap]
mov edi,[sp_dest]
xor ebx,ebx
xor ecx,ecx
shld ebx,edx,16 ; get address of first location
call [mscalecall]
ENDIF
@exitp <ebx, esi, edi, ebp>
ENDP
;============================================================================
@Proc GetMScaleRoutines
mov eax,OFFSET mvscale200
@exitp
ENDP
;============================================================================
;
; unwound horizontal texture mapping code
;
; eax lighttable
; ebx xtotal 6 bits units 26 bits frac
; ecx ytotal 6 bits units 26 bits frac
; edx xstep
; esi start of block
; edi dest
; ebp scratch offset
;
; [ystep]
;
; ebp should by preset from ebx / ecx before calling
;============================================================================
; the assembler creates hmap<MAXWINDOWWIDTH>: numbers of the following
; code segement. all sections of the code are not ALINGN'ed on a 32 bit
; boundary. LINE is used as the arg to MAPLABEL. there exists
; hmapMAXWINDOWWIDTH: to hmap0: units of code. map0 is used as the exit
; point.
MAPLABEL MACRO number
hmap&number:
ENDM
LINE = MAXWINDOWWIDTH
REPT MAXWINDOWWIDTH
MAPLABEL %LINE
mov al,[esi+ebp] ; get source pixel
add ebx,edx ; xtotal += xstep
add ecx,[ystep] ; ytotal += ystep
xor ebp,ebp
mov al,[eax] ; translate color
shld ebp,ecx,6 ; shift in new y/x position
shld ebp,ebx,6
mov [edi-(LINE-1)],al ; write pixel
LINE = LINE - 1
ENDM
hmap0:
ret
.DATA
ystep dd 0
mapcall dd 0
; the following 2 macros allocate a block of dd or 4 byte locations that are
; ALIGN'ed on a 4 byte or 32 bit boundary. the starting 4 bytes may be
; referred to as mapcalls. the others may not because in the macro MAPDEFINE
; they are not given a name. the label mapcalls refers to a position in the
; code which happens to be the start of the allocated block. there are
; MAXWINDOWWIDTH + 1 4 byte word's are allocated and each word is initialized
; with the address of hmap<LINE>:. the value of LINE ranges from 0 to
; MAXWINDOWWIDTH. mapcalls is made visible to the other modules with the
; PUBLIC directive.
MAPDEFINE MACRO number
dd hmap&number
ENDM
ALIGN 4
mapcalls LABEL UNKNOWN
LINE = 0
REPT MAXWINDOWWIDTH + 1
MAPDEFINE %LINE
LINE = LINE + 1
ENDM
PUBLIC mapcalls
;
; parameters for RN_MapLine
;
mr_dest dd 0 ; pointer to first pixel in view buffer
mr_count dd 0
mr_picture dd 0 ; pointer to 4096 pixel block
mr_colormap dd 0 ; page aligned light table
mr_xfrac dd 0 ; 16 frac bits
mr_yfrac dd 0 ; 16 frac bits
mr_xstep dd 0
mr_ystep dd 0
PUBLIC mr_dest, mr_picture, mr_colormap, mr_xfrac
PUBLIC mr_yfrac, mr_xstep, mr_ystep, mr_count
.CODE
;================
;
; MapRow
;
; Horizontal texture mapping
;
;================
@Proc MapRow, <ebx, esi, edi>
IFE SKIPPRIMITIVES
mov eax,[mr_count]
mov ebx,[mapcalls+eax*4]
mov [mapcall],ebx ; spot to jump into unwound
mov edi,[mr_dest]
add edi,[mr_count]
dec edi
mov eax,[mr_ystep]
shl eax,10
mov [ystep],eax
mov eax,[mr_colormap]
mov ebx,[mr_xfrac]
shl ebx,10
mov ecx,[mr_yfrac]
shl ecx,10
mov edx,[mr_xstep]
shl edx,10
mov esi,[mr_picture]
xor ebp,ebp
shld ebp,ecx,6
shld ebp,ebx,6 ; do first step for pipeline
call [mapcall]
shr ebx,10
mov [mr_xfrac],ebx
shr ecx,10
mov [mr_yfrac],ecx
ENDIF
@exitp <ebx, esi, edi>
ENDP
END