;*
;* tmap.nas
;* The texture-mapping inner loops in pure assembly language.
;*
;*---------------------------------------------------------------------------
;* Copyright 1998-2006 Randy Heit
;* All rights reserved.
;*
;* Redistribution and use in source and binary forms, with or without
;* modification, are permitted provided that the following conditions
;* are met:
;*
;* 1. Redistributions of source code must retain the above copyright
;*    notice, this list of conditions and the following disclaimer.
;* 2. Redistributions in binary form must reproduce the above copyright
;*    notice, this list of conditions and the following disclaimer in the
;*    documentation and/or other materials provided with the distribution.
;* 3. The name of the author may not be used to endorse or promote products
;*    derived from this software without specific prior written permission.
;*
;* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
;* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
;* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
;* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
;* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
;* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
;* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
;* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
;* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
;* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;*---------------------------------------------------------------------------
;*

BITS 32

%include "valgrind.inc"

; Segment/section definition macros. 

	SECTION .data

%define SPACEFILLER4 (0x44444444)

; If you change this in r_draw.c, be sure to change it here, too!
FUZZTABLE	equ	50

%ifndef M_TARGET_LINUX

%define ylookup			_ylookup
%define centery			_centery
%define fuzzpos			_fuzzpos
%define fuzzoffset		_fuzzoffset
%define NormalLight		_NormalLight
%define viewheight		_viewheight
%define fuzzviewheight	_fuzzviewheight
%define CPU				_CPU

%define dc_pitch		_dc_pitch
%define dc_colormap		_dc_colormap
%define dc_color		_dc_color
%define dc_iscale		_dc_iscale
%define dc_texturefrac	_dc_texturefrac
%define dc_srcblend		_dc_srcblend
%define dc_destblend	_dc_destblend
%define dc_source		_dc_source
%define dc_yl			_dc_yl
%define dc_yh			_dc_yh
%define dc_x			_dc_x
%define dc_count		_dc_count
%define dc_dest			_dc_dest
%define dc_destorg		_dc_destorg

%define Col2RGB8		_Col2RGB8
%define RGB32k			_RGB32k

%define dc_ctspan		_dc_ctspan
%define dc_temp			_dc_temp

%define ds_xstep		_ds_xstep
%define ds_ystep		_ds_ystep
%define ds_colormap		_ds_colormap
%define ds_source		_ds_source
%define ds_x1			_ds_x1
%define ds_x2			_ds_x2
%define ds_xfrac		_ds_xfrac
%define ds_yfrac		_ds_yfrac
%define ds_y			_ds_y

%define ds_cursource	_ds_cursource
%define ds_curcolormap	_ds_curcolormap

%define R_SetSpanSource_ASM		_R_SetSpanSource_ASM
%define R_SetSpanSize_ASM		_R_SetSpanSize_ASM
%define R_SetSpanColormap_ASM	_R_SetSpanColormap_ASM
%define R_SetupShadedCol		_R_SetupShadedCol
%define R_SetupAddCol			_R_SetupAddCol
%define R_SetupAddClampCol		_R_SetupAddClampCol

%endif

EXTERN ylookup
EXTERN centery
EXTERN fuzzpos
EXTERN fuzzoffset
EXTERN NormalLight
EXTERN viewheight
EXTERN fuzzviewheight
EXTERN CPU

EXTERN dc_pitch
EXTERN dc_colormap
EXTERN dc_color
EXTERN dc_iscale
EXTERN dc_texturefrac
EXTERN dc_srcblend
EXTERN dc_destblend
EXTERN dc_source
EXTERN dc_yl
EXTERN dc_yh
EXTERN dc_x
EXTERN dc_count
EXTERN dc_dest
EXTERN dc_destorg

EXTERN dc_ctspan
EXTERN dc_temp

EXTERN Col2RGB8
EXTERN RGB32k

EXTERN ds_xstep
EXTERN ds_ystep
EXTERN ds_colormap
EXTERN ds_source
EXTERN ds_x1
EXTERN ds_x2
EXTERN ds_xfrac
EXTERN ds_yfrac
EXTERN ds_y

GLOBAL ds_cursource
GLOBAL ds_curcolormap


ds_cursource:
	DD 0

ds_curcolormap:
	DD 0


; Local stuff:
lastAddress	DD 0
pixelcount	DD 0

	SECTION .text


GLOBAL @R_SetSpanSource_ASM@4
GLOBAL R_SetSpanSource_ASM

R_SetSpanSource_ASM:
	mov	ecx,[esp+4]

@R_SetSpanSource_ASM@4:
	mov	[spreada+2],ecx
	mov	[spreadb+2],ecx
	mov	[spreadc+2],ecx
	mov	[spreadd+2],ecx
	mov	[spreade+2],ecx
	mov	[spreadf+2],ecx
	mov	[spreadg+2],ecx

	mov	[mspreada+2],ecx
	mov	[mspreadb+2],ecx
	mov	[mspreadc+2],ecx
	mov	[mspreadd+2],ecx
	mov	[mspreade+2],ecx
	mov	[mspreadf+2],ecx
	mov	[mspreadg+2],ecx
	
	selfmod spreada, mspreadg+6

	mov	[ds_cursource],ecx
	ret

GLOBAL @R_SetSpanColormap_ASM@4
GLOBAL R_SetSpanColormap_ASM

R_SetSpanColormap_ASM:
	mov ecx,[esp+4]

@R_SetSpanColormap_ASM@4:
	mov	[spmapa+2],ecx
	mov	[spmapb+2],ecx
	mov	[spmapc+2],ecx
	mov	[spmapd+2],ecx
	mov	[spmape+2],ecx
	mov	[spmapf+2],ecx
	mov	[spmapg+2],ecx

	mov	[mspmapa+2],ecx
	mov	[mspmapb+2],ecx
	mov	[mspmapc+2],ecx
	mov	[mspmapd+2],ecx
	mov	[mspmape+2],ecx
	mov	[mspmapf+2],ecx
	mov	[mspmapg+2],ecx
	
	selfmod spmapa, mspmapg+6

	mov	[ds_curcolormap],ecx
	ret

GLOBAL R_SetSpanSize_ASM

EXTERN	SetTiltedSpanSize

R_SetSpanSize_ASM:
	mov	edx,[esp+4]
	mov	ecx,[esp+8]
	call	SetTiltedSpanSize
	
	mov	[dsy1+2],dl
	mov	[dsy2+2],dl
	
	mov	[dsx1+2],cl
	mov	[dsx2+2],cl
	mov	[dsx3+2],cl
	mov	[dsx4+2],cl
	mov	[dsx5+2],cl
	mov	[dsx6+2],cl
	mov	[dsx7+2],cl
	
	mov	[dmsy1+2],dl
	mov	[dmsy2+2],dl
	
	mov	[dmsx1+2],cl
	mov	[dmsx2+2],cl
	mov	[dmsx3+2],cl
	mov	[dmsx4+2],cl
	mov	[dmsx5+2],cl
	mov	[dmsx6+2],cl
	mov	[dmsx7+2],cl

	push	ecx
	add	ecx,edx
	mov	eax,1
	shl	eax,cl
	dec	eax
	mov	[dsm1+2],eax
	mov	[dsm5+1],eax
	mov	[dsm6+1],eax
	mov	[dsm7+1],eax
	
	mov	[dmsm1+2],eax
	mov	[dmsm5+1],eax
	mov	[dmsm6+1],eax
	mov	[dmsm7+1],eax
	pop	ecx
	ror	eax,cl
	mov	[dsm2+2],eax
	mov	[dsm3+2],eax
	mov	[dsm4+2],eax

	mov	[dmsm2+2],eax
	mov	[dmsm3+2],eax
	mov	[dmsm4+2],eax
	and	eax,0xffff
	not	eax
	mov	[dsm8+2],eax
	mov	[dsm9+2],eax

	mov	[dmsm8+2],eax
	mov	[dmsm9+2],eax
	
	neg	dl
	mov	[dsy3+2],dl
	mov	[dsy4+2],dl

	mov	[dmsy3+2],dl
	mov	[dmsy4+2],dl
	
	selfmod dsy1, dmsm7+6
	
aret:	ret

%ifdef M_TARGET_MACHO
	SECTION .text align=64
%else
	SECTION .rtext	progbits alloc exec write align=64
%endif

%ifdef M_TARGET_MACHO
GLOBAL _rtext_tmap_start
_rtext_tmap_start:
%endif

rtext_start:

GLOBAL @R_DrawSpanP_ASM@0
GLOBAL _R_DrawSpanP_ASM
GLOBAL R_DrawSpanP_ASM

; eax: scratch
; ebx: zero
; ecx: yfrac at top end, xfrac int part at low end
; edx: xfrac frac part at top end
; edi: dest
; ebp: scratch
; esi: count
; [esp]: xstep
; [esp+4]: ystep

	align	16

@R_DrawSpanP_ASM@0:
_R_DrawSpanP_ASM:
R_DrawSpanP_ASM:
	mov	eax,[ds_x2]
	 mov	ecx,[ds_x1]
	sub	eax,ecx
	 jl	near rdspret		; count < 0: nothing to do, so leave

	push	ebx
	push	edi
	push	ebp
	push	esi
	sub		esp, 8

	mov	edi,ecx
	add	edi,[dc_destorg]
	 mov	ecx,[ds_y]
	add	edi,[ylookup+ecx*4]
	 mov	edx,[ds_xstep]
dsy1:	shl	edx,6
	 mov	ebp,[ds_xstep]
dsy3:	shr	ebp,26
	 xor	ebx,ebx
	lea	esi,[eax+1]
	 mov	[esp],edx
	mov	edx,[ds_ystep]
	 mov	ecx,[ds_xfrac]
dsy4:	shr	ecx,26
dsm8:	 and	edx,strict dword 0xffffffc0
	or	ebp,edx
	 mov	[esp+4],ebp
	mov	ebp,[ds_yfrac]
	 mov	edx,[ds_xfrac]
dsy2:	shl	edx,6
dsm9:	 and	ebp,strict dword 0xffffffc0
	or	ecx,ebp
	 shr	esi,1
	jnc	dseven1

; do odd pixel

		mov	ebp,ecx
dsx1:		rol	ebp,6
dsm1:		and	ebp,0xfff
		 add	edx,[esp]
		adc	ecx,[esp+4]
spreada		 mov	bl,[ebp+SPACEFILLER4]
spmapa		mov	bl,[ebx+SPACEFILLER4]
		mov	[edi],bl
		 inc	edi

dseven1		shr	esi,1
		 jnc	dsrest

; do two more pixels
		mov	ebp,ecx
		 add	edx,[esp]
		adc	ecx,[esp+4]
dsm2:		 and	ebp,0xfc00003f
dsx2:		rol	ebp,6
		mov	eax,ecx
		 add	edx,[esp]
		adc	ecx,[esp+4]
spreadb		 mov	bl,[ebp+SPACEFILLER4]	;read texel1
dsx3:		rol	eax,6
dsm6:		and	eax,0xfff
spmapb		 mov	bl,[ebx+SPACEFILLER4]	;map texel1
		mov	[edi],bl		;store texel1
		 add	edi,2
spreadc		mov	bl,[eax+SPACEFILLER4]	;read texel2
spmapc		mov	bl,[ebx+SPACEFILLER4]	;map texel2
		mov	[edi-1],bl		;store texel2

; do the rest

dsrest		test	esi,esi
		jz near	dsdone

		align 16

dsloop		mov	ebp,ecx
spstep1d	 add	edx,[esp]
spstep2d	adc	ecx,[esp+4]
dsm3:		 and	ebp,0xfc00003f
dsx4:		rol	ebp,6
		mov	eax,ecx
spstep1e	 add	edx,[esp]
spstep2e	adc	ecx,[esp+4]
spreadd		 mov	bl,[ebp+SPACEFILLER4]	;read texel1
dsx5:		rol	eax,6
dsm5:		and	eax,0xfff
spmapd		 mov	bl,[ebx+SPACEFILLER4]	;map texel1
		mov	[edi],bl		;store texel1
		 mov	ebp,ecx
spreade		mov	bl,[eax+SPACEFILLER4]	;read texel2
spstep1f	 add	edx,[esp]
spstep2f	adc	ecx,[esp+4]
dsm4:		 and	ebp,0xfc00003f
dsx6:		rol	ebp,6
spmape		mov	bl,[ebx+SPACEFILLER4]	;map texel2
		 mov	eax,ecx
		mov	[edi+1],bl		;store texel2
spreadf		 mov	bl,[ebp+SPACEFILLER4]	;read texel3
spmapf		mov	bl,[ebx+SPACEFILLER4]	;map texel3
		 add	edi,4
dsx7:		rol	eax,6
dsm7:		and	eax,0xfff
		 mov	[edi-2],bl		;store texel3
spreadg		mov	bl,[eax+SPACEFILLER4]	;read texel4
spstep1g	 add	edx,[esp]
spstep2g	adc	ecx,[esp+4]
spmapg		 mov	bl,[ebx+SPACEFILLER4]	;map texel4
		dec	esi
		 mov	[edi-1],bl		;store texel4
		jnz near dsloop

dsdone	add esp,8
	pop	esi
	pop	ebp
	pop	edi
	pop	ebx

rdspret	ret

; This is the same as the previous routine, except it doesn't draw pixels
; where the texture's color value is 0.

GLOBAL @R_DrawSpanMaskedP_ASM@0
GLOBAL _R_DrawSpanMaskedP_ASM
GLOBAL R_DrawSpanMaskedP_ASM

; eax: scratch
; ebx: zero
; ecx: yfrac at top end, xfrac int part at low end
; edx: xfrac frac part at top end
; edi: dest
; ebp: scratch
; esi: count
; [esp]: xstep
; [esp+4]: ystep

	align	16

@R_DrawSpanMaskedP_ASM@0:
_R_DrawSpanMaskedP_ASM:
R_DrawSpanMaskedP_ASM:
	mov	eax,[ds_x2]
	 mov	ecx,[ds_x1]
	sub	eax,ecx
	 jl	rdspret		; count < 0: nothing to do, so leave

	push	ebx
	push	edi
	push	ebp
	push	esi
	sub		esp,8

	mov	edi,ecx
	add	edi,[dc_destorg]
	 mov	ecx,[ds_y]
	add	edi,[ylookup+ecx*4]
	 mov	edx,[ds_xstep]
dmsy1:	shl	edx,6
	 mov	ebp,[ds_xstep]
dmsy3:	shr	ebp,26
	 xor	ebx,ebx
	lea	esi,[eax+1]
	 mov	[esp],edx
	mov	edx,[ds_ystep]
	 mov	ecx,[ds_xfrac]
dmsy4:	shr	ecx,26
dmsm8:	 and	edx,strict dword 0xffffffc0
	or	ebp,edx
	 mov	[esp+4],ebp
	mov	ebp,[ds_yfrac]
	 mov	edx,[ds_xfrac]
dmsy2:	shl	edx,6
dmsm9:	 and	ebp,strict dword 0xffffffc0
	or	ecx,ebp
	 shr	esi,1
	jnc	dmseven1

; do odd pixel

		mov	ebp,ecx
dmsx1:		rol	ebp,6
dmsm1:		and	ebp,0xfff
		 add	edx,[esp]
		adc	ecx,[esp+4]
mspreada	 mov	bl,[ebp+SPACEFILLER4]
		cmp	bl,0
		 je	mspskipa
mspmapa		mov	bl,[ebx+SPACEFILLER4]
		mov	[edi],bl
mspskipa:	 inc	edi

dmseven1	shr	esi,1
		 jnc	dmsrest

; do two more pixels
		mov	ebp,ecx
		 add	edx,[esp]
		adc	ecx,[esp+4]
dmsm2:		 and	ebp,0xfc00003f
dmsx2:		rol	ebp,6
		mov	eax,ecx
		 add	edx,[esp]
		adc	ecx,[esp+4]
mspreadb	 mov	bl,[ebp+SPACEFILLER4]	;read texel1
dmsx3:		rol	eax,6
dmsm6:		and	eax,0xfff
		cmp	bl,0
		 je	mspskipb
mspmapb		 mov	bl,[ebx+SPACEFILLER4]	;map texel1
		mov	[edi],bl		;store texel1
mspskipb	 add	edi,2
mspreadc	mov	bl,[eax+SPACEFILLER4]	;read texel2
		cmp	bl,0
		 je	dmsrest
mspmapc		mov	bl,[ebx+SPACEFILLER4]	;map texel2
		mov	[edi-1],bl		;store texel2

; do the rest

dmsrest		test	esi,esi
		jz near	dmsdone

		align 16

dmsloop		mov	ebp,ecx
mspstep1d	 add	edx,[esp]
mspstep2d	adc	ecx,[esp+4]
dmsm3:		 and	ebp,0xfc00003f
dmsx4:		rol	ebp,6
		mov	eax,ecx
mspstep1e	 add	edx,[esp]
mspstep2e	adc	ecx,[esp+4]
mspreadd	 mov	bl,[ebp+SPACEFILLER4]	;read texel1
dmsx5:		rol	eax,6
dmsm5:		and	eax,0xfff
		 cmp	bl,0
		mov	ebp,ecx
		 je	mspreade
mspmapd		mov	bl,[ebx+SPACEFILLER4]	;map texel1
		mov	[edi],bl		;store texel1
mspreade	mov	bl,[eax+SPACEFILLER4]	;read texel2
mspstep1f	 add	edx,[esp]
mspstep2f	adc	ecx,[esp+4]
dmsm4:		 and	ebp,0xfc00003f
dmsx6:		rol	ebp,6
		 cmp	bl,0
		mov	eax,ecx
		 je	mspreadf
mspmape		mov	bl,[ebx+SPACEFILLER4]	;map texel2
		mov	[edi+1],bl		;store texel2
mspreadf	 mov	bl,[ebp+SPACEFILLER4]	;read texel3
		add	edi,4
dmsx7:		rol	eax,6
dmsm7:		and	eax,0xfff
		cmp	bl,0
		 je	mspreadg
mspmapf		mov	bl,[ebx+SPACEFILLER4]	;map texel3
		 mov	[edi-2],bl		;store texel3
mspreadg	mov	bl,[eax+SPACEFILLER4]	;read texel4
mspstep1g	 add	edx,[esp]
mspstep2g	adc	ecx,[esp+4]
		cmp	bl,0
		 je	mspskipg
mspmapg		 mov	bl,[ebx+SPACEFILLER4]	;map texel4
		mov	[edi-1],bl		;store texel4
mspskipg	dec	esi
		 jnz near dmsloop

dmsdone	add esp,8
	pop	esi
	pop	ebp
	pop	edi
	pop	ebx

	ret




;*----------------------------------------------------------------------
;*
;* R_DrawColumnP
;*
;*----------------------------------------------------------------------

GLOBAL	@R_DrawColumnP_ASM@0
GLOBAL	_R_DrawColumnP_ASM
GLOBAL	R_DrawColumnP_ASM

	align 16

R_DrawColumnP_ASM:
_R_DrawColumnP_ASM:
@R_DrawColumnP_ASM@0:

; count = dc_yh - dc_yl;

	mov	ecx,[dc_count]
	test	ecx,ecx
	jle	near rdcpret		; count <= 0: nothing to do, so leave

	push	ebp			; save registers
	 push	ebx
	push	edi
	 push	esi

; dest = ylookup[dc_yl] + dc_x + dc_destorg;

	mov	edi,[dc_dest]
	mov	ebp,ecx
	mov	ebx,[dc_texturefrac]	; ebx = frac
rdcp1:	sub	edi,SPACEFILLER4
	mov	ecx,ebx
	shr	ecx,16
	mov	esi,[dc_source]
	mov	edx,[dc_iscale]
	mov	eax,[dc_colormap]

	cmp	BYTE [CPU+66],byte 5
	jg	rdcploop2

	align 16

; The registers should now look like this:
;
;	[31  ..  16][15 .. 8][7 .. 0]
; eax	[colormap		    ]
; ebx	[yi	   ][yf		    ]
; ecx	[scratch		    ]
; edx	[dyi	   ][dyf	    ]
; esi	[source texture column	    ]
; edi	[destination screen pointer ]
; ebp	[counter		    ]
;


; Note the partial register stalls on anything better than a Pentium
; That's why there are two versions of this loop.

rdcploop:
	mov	cl,[esi+ecx]		; Fetch texel
	 xor	ch,ch
	add	ebx,edx			; increment frac
rdcp2:	 add	edi,SPACEFILLER4	; increment destination pointer
	mov	cl,[eax+ecx]		; colormap texel
	mov	[edi],cl		; Store texel
	 mov	ecx,ebx
	shr	ecx,16
	 dec	ebp
	jnz	rdcploop		; loop

	pop	esi
	 pop	edi
	pop	ebx
	 pop	ebp
rdcpret:
	ret
	
	align 16

rdcploop2:
	movzx	ecx,byte [esi+ecx]	; Fetch texel
	add	ebx,edx			; increment frac
	mov	cl,[eax+ecx]		; colormap texel
rdcp3:	add	edi,SPACEFILLER4	; increment destination pointer
	mov	[edi],cl		; Store texel
	mov	ecx,ebx
	shr	ecx,16
	dec	ebp
	jnz	rdcploop2		; loop

	pop	esi
	pop	edi
	pop	ebx
	pop	ebp
	ret
	


;*----------------------------------------------------------------------
;*
;* R_DrawFuzzColumnP
;*
;*----------------------------------------------------------------------

GLOBAL	@R_DrawFuzzColumnP_ASM@0
GLOBAL	_R_DrawFuzzColumnP_ASM
GLOBAL	R_DrawFuzzColumnP_ASM

	align 16

R_DrawFuzzColumnP_ASM:
_R_DrawFuzzColumnP_ASM:
@R_DrawFuzzColumnP_ASM@0:

; Adjust borders. Low...
	mov	eax,[dc_yl]
	 push	ebx
	push	esi
	 push	edi
	push	ebp

	 cmp	eax,0
	jg	.ylok

	mov	eax,1
	nop

; ...and high.
.ylok	mov	edx,[fuzzviewheight]
	 mov	esi,[dc_yh]
	cmp	esi,edx
	 jle	.yhok

	mov	esi,edx
	nop

.yhok	mov	edx,[dc_x]
	 sub	esi,eax			; esi = count
	js	near .dfcdone		; Zero length (or less)

	mov	edi,[ylookup+eax*4]
	 mov	ebx,edx
	add	edi,[dc_destorg]
	 mov	eax,[NormalLight]
	mov	ecx,[fuzzpos]
	 add	edi,ebx
	add	eax,256*6
	 inc	esi
	mov	ebp,[dc_pitch]
	 mov	edx,FUZZTABLE
	test	ecx,ecx
	 je	.fuzz0

;
; esi = count
; edi = dest
; ecx = fuzzpos
; eax = colormap 6
;

; first loop: end with fuzzpos or count 0, whichever happens first

	sub	edx,ecx			; edx = # of entries left in fuzzoffset
	 mov	ebx,esi
	cmp	esi,edx
	 jle	.enuf
	mov	esi,edx
.enuf	sub	ebx,esi
	 mov	edx,[fuzzoffset+ecx*4]
	push	ebx
	 xor	ebx,ebx

.loop1	inc	ecx
	 mov	bl,[edi+edx]
	dec	esi
	 mov	bl,[eax+ebx]
	mov	[edi],bl
	 lea	edi,[edi+ebp]
	mov	edx,[fuzzoffset+ecx*4]
	 jnz	.loop1

; second loop: Chunk it into groups of FUZZTABLE-sized spans and do those

	pop	esi
	 cmp	ecx,FUZZTABLE
	jl	.savefuzzpos
	xor	ecx,ecx
	 nop
.fuzz0	cmp	esi,FUZZTABLE
	 jl	.chunked

.oloop	lea	edx,[esi-FUZZTABLE]
	 mov	esi,FUZZTABLE
	push	edx
	 mov	edx,[fuzzoffset+ecx*4]

.iloop	inc	ecx
	 mov	bl,[edi+edx]
	dec	esi
	 mov	bl,[eax+ebx]
	mov	[edi],bl
	 lea	edi,[edi+ebp]
	mov	edx,[fuzzoffset+ecx*4]
	 jnz	.iloop

	pop	esi
	 xor	ecx,ecx
	cmp	esi,FUZZTABLE
	 jge	.oloop

; third loop: Do whatever is left

.chunked:
	test	esi,esi
	 jle	.savefuzzpos
	mov	edx,[fuzzoffset+ecx*4]
	 nop

.loop3	inc	ecx
	 mov	bl,[edi+edx]
	dec	esi
	 mov	bl,[eax+ebx]
	mov	[edi],bl
	 lea	edi,[edi+ebp]
	mov	edx,[fuzzoffset+ecx*4]
	 jnz	.loop3

.savefuzzpos:
	mov	[fuzzpos],ecx
.dfcdone:
	pop	ebp
	pop	edi
	pop	esi
	pop	ebx
	ret


;*----------------------------------------------------------------------
;*
;* R_DrawColumnHorizP_ASM
;*
;*----------------------------------------------------------------------

GLOBAL	@R_DrawColumnHorizP_ASM@0
GLOBAL	_R_DrawColumnHorizP_ASM
GLOBAL	R_DrawColumnHorizP_ASM

	align 16

@R_DrawColumnHorizP_ASM@0:
_R_DrawColumnHorizP_ASM:
R_DrawColumnHorizP_ASM:

; count = dc_yh - dc_yl;

	mov	eax,[dc_yh]
	mov	ecx,[dc_yl]
	sub	eax,ecx
	mov	edx,[dc_x]

	jl	near .leave		; count < 0: nothing to do, so leave

	push	ebp			; save registers
	push	ebx
	push	edi
	push	esi

	inc	eax			; make 0 count mean 0 pixels
	 and	edx,3
	push	eax
	 mov	eax,[dc_temp]
	mov	esi,[dc_ctspan+edx*4]
	 add	eax,edx
	lea	eax,[eax+ecx*4] ; eax = top of column in buffer
	 mov	ebp,[dc_yh]
	mov	[esi],ecx
	 mov	[esi+4],ebp
	add	esi,8
	 mov	edi,[dc_source]
	mov	[dc_ctspan+edx*4],esi
	 mov	esi,[dc_iscale]
	mov	ecx,[dc_texturefrac]	; ecx = frac
	 mov	dl,[edi]		; load cache
	mov	ebx,[esp]
	 and	ebx,0xfffffff8
	jnz	.mthan8

; Register usage in the following code is:
;
; eax: dest
; edi: source
; ecx: frac (16.16)
; esi: fracstep (16.16)
; ebx: add1
; ebp: add2
;  dl: texel1
;  dh: texel2
;[esp] count

; there are fewer than 8 pixels to draw

	mov	ebx,[esp]
.lthan8	shr	ebx,1
	 jnc	.even

; do one pixel before loop (little opportunity for pairing)

	mov	ebp,ecx			; copy frac to ebx
	 add	ecx,esi			; increment frac
	shr	ebp,16			; shift frac over to low end
	 add	eax,4
	mov	dl,[edi+ebp]
	mov	[eax-4],dl

.even	test	ebx,ebx
	jz	near .done

.loop2	mov	[esp],ebx		; save counter
	 mov	ebx,ecx			; copy frac for texel1 to ebx
	shr	ebx,16			; shift frac for texel1 to low end
	 add	ecx,esi			; increment frac
	mov	ebp,ecx			; copy frac for texel2 to ebp
	shr	ebp,16			; shift frac for texel2 to low end
	 add	ecx,esi			; increment frac
	 mov	dl,[edi+ebx]		; read texel1
	mov	ebx,[esp]		; fetch counter
	 mov	dh,[edi+ebp]		; read texel2
	mov	[eax],dl		; write texel1
	 mov	[eax+4],dh		; write texel2
	add	eax,8			; increment dest
	 dec	ebx			; decrement counter
	jnz	.loop2			; loop until it hits 0

	jmp	.done

; there are more than 8 pixels to draw. position eax as close to a 32 byte
; boundary as possible, then do whatever is left.

.mthan8 test	eax,4
	jz	.try2

	mov	ebp,ecx			; frac: in ebp
	 add	ecx,esi			; step
	shr	ebp,16			; frac: shift
	 add	eax,4			; increment dest
	 mov	ebx,[esp]		; fetch counter
	mov	dl,[edi+ebp]		; tex:  read
	 dec	ebx			; decrement counter
	mov	[eax-4],dl		; tex:  write
	 mov	[esp],ebx		; store counter

.try2	test	eax,8
	jz	.try4

	mov	ebx,ecx			; frac1: in ebx
	 add	ecx,esi			; step
	shr	ebx,16			; frac1: shift
	 mov	ebp,ecx			; frac2: in ebp
	shr	ebp,16			; frac2: shift
	 add	ecx,esi			; step
	mov	dl,[edi+ebx]		; tex1:  read
	 mov	ebx,[esp]		; fetch counter
	mov	dh,[edi+ebp]		; tex2:  read
	 mov	[eax],dl		; tex1:  write
	mov	[eax+4],dh		; tex2:  write
	 sub	ebx,2			; decrement counter
	add	eax,8			; increment dest
	 mov	[esp],ebx		; store counter

.try4	test	eax,16
	jz	.try8

	mov	ebx,ecx			; frac1: in ebx
	 add	ecx,esi			; step
	shr	ebx,16			; frac1: shift
	 mov	ebp,ecx			; frac2: in ebp
	shr	ebp,16			; frac2: shift
	 add	ecx,esi			; step
	mov	dl,[edi+ebx]		; tex1:  read
	 mov	ebx,ecx			; frac3: in ebx
	shr	ebx,16			; frac3: shift
	 mov	dh,[edi+ebp]		; tex2:  read
	add	ecx,esi			; step
	 mov	[eax],dl		; tex1:  write
	mov	[eax+4],dh		; tex2:  write
	 mov	ebp,ecx			; frac4: in ebp
	shr	ebp,16			; frac4: shift
	 add	ecx,esi			; step
	mov	dl,[edi+ebx]		; tex3:  read
	 mov	ebx,[esp]		; fetch counter
	mov	dh,[edi+ebp]		; tex4:  read
	 sub	ebx,4			; decrement counter
	mov	[esp],ebx		; store counter
	 mov	[eax+8],dl		; tex3:  write
	mov	[eax+12],dh		; tex4:  write
	 add	eax,16			; increment dest

.try8	mov	ebx,[esp]		; make counter count groups of 8
	sub	esp,4
	shr	ebx,3
	jmp	.tail8

	align	16

.loop8	mov	[esp],ebx		; save counter
	 mov	ebx,ecx			; frac1: in ebx
	shr	ebx,16			; frac1: shift
	 add	ecx,esi			; step
	mov	ebp,ecx			; frac2: in ebp
	shr	ebp,16			; frac2: shift
	 add	ecx,esi			; step
	 mov	dl,[edi+ebx]		; tex1:  read
	mov	ebx,ecx			; frac3: in ebx
	 mov	dh,[edi+ebp]		; tex2:  read
	shr	ebx,16			; frac3: shift
	 add	ecx,esi			; step
	mov	[eax],dl		; tex1:  write
	 mov	[eax+4],dh		; tex2:  write
	mov	ebp,ecx			; frac4: in ebp
	shr	ebp,16			; frac4: shift
	 add	ecx,esi			; step
	 mov	dl,[edi+ebx]		; tex3:  read
	mov	ebx,ecx			; frac5: in ebx
	 mov	dh,[edi+ebp]		; tex4:  read
	shr	ebx,16			; frac5: shift
	 mov	[eax+8],dl		; tex3:  write
	mov	[eax+12],dh		; tex4:  write
	 add	ecx,esi			; step
	mov	ebp,ecx			; frac6: in ebp
	shr	ebp,16			; frac6: shift
	 mov	dl,[edi+ebx]		; tex5:  read
	 add	ecx,esi			; step
	mov	ebx,ecx			; frac7: in ebx
	 mov	[eax+16],dl		; tex5:  write
	shr	ebx,16			; frac7: shift
	 mov	dh,[edi+ebp]		; tex6:  read
	 add	ecx,esi			; step
	mov	ebp,ecx			; frac8: in ebp
	 mov	[eax+20],dh		; tex6:  write
	shr	ebp,16			; frac8: shift
	 add	eax,32			; increment dest pointer
	 mov	dl,[edi+ebx]		; tex7:  read
	mov	ebx,[esp]		; fetch counter
	 mov	[eax-8],dl		; tex7:  write
	mov	dh,[edi+ebp]		; tex8:  read
	 add	ecx,esi			; step
	mov	[eax-4],dh		; tex8:  write
	 mov	dl,[eax]		; load cache
	dec	ebx			; decrement counter
.tail8	 jnz	near .loop8		; loop if more to do
	
	pop	ebp
	mov	ebx,[esp]
	and	ebx,7
	jnz	near .lthan8

.done	pop	eax
	pop	esi
	pop	edi
	pop	ebx
	pop	ebp
.leave	ret


;*----------------------------------------------------------------------
;*
;* rt_copy1col_asm
;*
;* ecx = hx
;* edx = sx
;* [esp+4] = yl
;* [esp+8] = yh
;*
;*----------------------------------------------------------------------

GLOBAL	@rt_copy1col_asm@16
GLOBAL	_rt_copy1col_asm
GLOBAL	rt_copy1col_asm

	align 16

rt_copy1col_asm:
_rt_copy1col_asm:
	pop	eax
	mov	edx,[esp+4*3]
	mov	ecx,[esp+4*2]
	push	edx
	push	ecx
	mov	ecx,[esp+4*2]
	mov	edx,[esp+4*3]
	push	eax

@rt_copy1col_asm@16:
	mov	eax, [esp+4]
	push	ebx
	mov	ebx, [esp+12]
	push	esi
	sub	ebx, eax
	push	edi
	js	.done

	lea	esi,[eax*4]
	inc	ebx			; ebx = count
	mov	eax,edx
	add ecx,esi
	mov	edi,[ylookup+esi]
	add ecx,[dc_temp]	; ecx = source
	mov	esi,[dc_pitch]		; esi = pitch
	add	eax,edi			; eax = dest
	add	eax,[dc_destorg]

	shr	ebx,1
	jnc	.even

	mov	dl,[ecx]
	add	ecx,4
	mov	[eax],dl
	add	eax,esi

.even	and	ebx,ebx
	jz	.done

.loop	mov	dl,[ecx]
	mov	dh,[ecx+4]
	mov	[eax],dl
	mov	[eax+esi],dh
	add	ecx,8
	lea	eax,[eax+esi*2]
	dec	ebx
	jnz	.loop

.done	pop	edi
	pop	esi
	pop	ebx
	ret	8

;*----------------------------------------------------------------------
;*
;* rt_copy4cols_asm
;*
;* ecx = sx
;* edx = yl
;* [esp+4] = yh
;*
;*----------------------------------------------------------------------

GLOBAL	@rt_copy4cols_asm@12
GLOBAL	_rt_copy4cols_asm
GLOBAL	rt_copy4cols_asm

	align 16

rt_copy4cols_asm:
_rt_copy4cols_asm:
	pop	eax
	mov	ecx,[esp+8]
	mov	edx,[esp+4]
	push	ecx
	mov	ecx,[esp+4]
	push	eax

@rt_copy4cols_asm@12:
	push	ebx
	mov	ebx,[esp+8]
	push	esi
	sub	ebx,edx
	push	edi
	js	.done

	inc	ebx			; ebx = count
	mov	eax,ecx
	mov	esi,[ylookup+edx*4]
	mov ecx,[dc_temp]
	add	eax,esi			; eax = dest
	add	eax,[dc_destorg]
	lea	ecx,[ecx+edx*4]	; ecx = source
	mov	edx,[dc_pitch]		; edx = pitch

	shr	ebx,1
	jnc	.even

	mov	esi,[ecx]
	add	ecx,4
	mov	[eax],esi
	add	eax,edx

.even	and	ebx,ebx
	jz	.done

.loop	mov	esi,[ecx]
	mov	edi,[ecx+4]
	mov	[eax],esi
	mov	[eax+edx],edi
	add	ecx,8
	lea	eax,[eax+edx*2]
	dec	ebx
	jnz	.loop

.done	pop	edi
	pop	esi
	pop	ebx
	ret	4

;*----------------------------------------------------------------------
;*
;* rt_map1col_asm
;*
;* ecx = hx
;* edx = sx
;* [esp+4] = yl
;* [esp+8] = yh
;*
;*----------------------------------------------------------------------

GLOBAL	@rt_map1col_asm@16
GLOBAL	_rt_map1col_asm
GLOBAL	rt_map1col_asm

	align 16

rt_map1col_asm:
_rt_map1col_asm:
	pop	eax
	mov	edx,[esp+4*3]
	mov	ecx,[esp+4*2]
	push	edx
	push	ecx
	mov	ecx,[esp+4*2]
	mov	edx,[esp+4*3]
	push	eax

@rt_map1col_asm@16:	
	mov	eax,[esp+4]
	push	ebx
	mov	ebx,[esp+12]
	push	ebp
	push	esi
	sub	ebx, eax
	push	edi
	js	.done

	lea	edi,[eax*4]
	mov	esi,[dc_colormap]		; esi = colormap
	inc	ebx				; ebx = count
	mov	eax,edx
	lea	ebp,[ecx+edi]		; ebp = source
	add ebp,[dc_temp]
	mov	ecx,[ylookup+edi]
	mov	edi,[dc_pitch]			; edi = pitch
	add	eax,ecx				; eax = dest
	xor	ecx,ecx
	xor	edx,edx
	add	eax,[dc_destorg]

	shr	ebx,1
	jnc	.even

	mov	dl,[ebp]
	add	ebp,4
	mov	dl,[esi+edx]
	mov	[eax],dl
	add	eax,edi

.even	and	ebx,ebx
	jz	.done

.loop	mov	dl,[ebp]
	mov	cl,[ebp+4]
	add	ebp,8
	mov	dl,[esi+edx]
	mov	cl,[esi+ecx]
	mov	[eax],dl
	mov	[eax+edi],cl
	dec	ebx
	lea	eax,[eax+edi*2]
	jnz	.loop

.done	pop	edi
	pop	esi
	pop	ebp
	pop	ebx
	ret	8

;*----------------------------------------------------------------------
;*
;* rt_map4cols_asm
;*
;* rt_map4cols_asm1 is for PPro and above
;* rt_map4cols_asm2 is for Pentium and below
;*
;* ecx = sx
;* edx = yl
;* [esp+4] = yh
;*
;*----------------------------------------------------------------------

GLOBAL	@rt_map4cols_asm1@12
GLOBAL	_rt_map4cols_asm1
GLOBAL	rt_map4cols_asm1

	align 16

rt_map4cols_asm1:
_rt_map4cols_asm1:
	pop	eax
	mov	ecx,[esp+8]
	mov	edx,[esp+4]
	push	ecx
	mov	ecx,[esp+4]
	push	eax

@rt_map4cols_asm1@12:
	push	ebx
	mov	ebx,[esp+8]
	push	ebp
	push	esi
	sub	ebx,edx
	push	edi
	js	near .done

	mov	esi,[dc_colormap]	; esi = colormap
	shl	edx,2
	mov	eax,ecx
	inc	ebx			; ebx = count
	mov	edi,[ylookup+edx]
	mov	ebp,[dc_temp]
	add ebp,edx		; ebp = source
	add	eax,edi			; eax = dest
	mov	edi,[dc_pitch]		; edi = pitch
	add	eax,[dc_destorg]
	xor	ecx,ecx
	xor	edx,edx

	shr	ebx,1
	jnc	.even

	mov	dl,[ebp]
	 mov	cl,[ebp+1]
	add	ebp,4
	 mov	dl,[esi+edx]
	mov	cl,[esi+ecx]
	 mov	[eax],dl
	mov	[eax+1],cl
	 mov	dl,[ebp-2]
	mov	cl,[ebp-1]
	 mov	dl,[esi+edx]
	mov	cl,[esi+ecx]
	 mov	[eax+2],dl
	mov	[eax+3],cl
	 add	eax,edi

.even	and	ebx,ebx
	jz	.done

.loop:
	mov	dl,[ebp]
	 mov	cl,[ebp+1]
	add	ebp,8
	 mov	dl,[esi+edx]
	mov	cl,[esi+ecx]
	 mov	[eax],dl
	mov	[eax+1],cl
	 mov	dl,[ebp-6]
	mov	cl,[ebp-5]
	 mov	dl,[esi+edx]
	mov	cl,[esi+ecx]
	 mov	[eax+2],dl
	mov	[eax+3],cl
	 mov	dl,[ebp-4]
	mov	cl,[ebp-3]
	 mov	dl,[esi+edx]
	mov	cl,[esi+ecx]
	 mov	[eax+edi],dl
	mov	[eax+edi+1],cl
	 mov	dl,[ebp-2]
	mov	cl,[ebp-1]
	 mov	dl,[esi+edx]
	mov	cl,[esi+ecx]
	 mov	[eax+edi+2],dl
	mov	[eax+edi+3],cl
	 lea	eax,[eax+edi*2]
	dec	ebx

	jnz	.loop

.done	pop	edi
	pop	esi
	pop	ebp
	pop	ebx
	ret	4

GLOBAL	@rt_map4cols_asm2@12
GLOBAL	_rt_map4cols_asm2
GLOBAL	rt_map4cols_asm2

	align 16

rt_map4cols_asm2:
_rt_map4cols_asm2:
	pop	eax
	mov	ecx,[esp+8]
	mov	edx,[esp+4]
	push	ecx
	mov	ecx,[esp+4]
	push	eax

@rt_map4cols_asm2@12:
	push	ebx
	mov	ebx,[esp+8]
	push	ebp
	push	esi
	sub	ebx,edx
	push	edi
	js	near .done

	mov	esi,[dc_colormap]	; esi = colormap
	shl	edx,2
	mov	eax,ecx
	inc	ebx			; ebx = count
	mov	edi,[ylookup+edx]
	mov ebp,[dc_temp]
	add ebp,edx		; ebp = source
	add	eax,edi			; eax = dest
	mov	edi,[dc_pitch]		; edi = pitch
	add	eax,[dc_destorg]
	xor	ecx,ecx
	xor	edx,edx

	shr	ebx,1
	jnc	.even

	mov	dl,[ebp]
	 mov	cl,[ebp+1]
	add	ebp,4
	 mov	dl,[esi+edx]
	mov	cl,[esi+ecx]
	 mov	[eax],dl
	mov	[eax+1],cl
	 mov	dl,[ebp-2]
	mov	cl,[ebp-1]
	 mov	dl,[esi+edx]
	mov	cl,[esi+ecx]
	 mov	[eax+2],dl
	mov	[eax+3],cl
	 add	eax,edi

.even	and	ebx,ebx
	jz	.done

.loop:
	mov	dl,[ebp+3]
	mov	ch,[esi+edx]
	mov	dl,[ebp+2]
	mov	cl,[esi+edx]
	shl	ecx,16
	mov	dl,[ebp+1]
	mov	ch,[esi+edx]
	mov	dl,[ebp]
	mov	cl,[esi+edx]
	mov	[eax],ecx
	add	eax,edi

	mov	dl,[ebp+7]
	mov	ch,[esi+edx]
	mov	dl,[ebp+6]
	mov	cl,[esi+edx]
	shl	ecx,16
	mov	dl,[ebp+5]
	mov	ch,[esi+edx]
	mov	dl,[ebp+4]
	mov	cl,[esi+edx]
	mov	[eax],ecx
	add	eax,edi
	add	ebp,8
	dec	ebx

	jnz	.loop

.done	pop	edi
	pop	esi
	pop	ebp
	pop	ebx
	ret	4

	align 16

GLOBAL rt_shaded4cols_asm
GLOBAL _rt_shaded4cols_asm

rt_shaded4cols_asm:
_rt_shaded4cols_asm:
		mov		ecx,[esp+8]
		push	ebp
		mov		ebp,[esp+16]
		sub		ebp,ecx
		js		near s4nil
		mov		eax,[ylookup+ecx*4]
		add		eax,[dc_destorg]				; eax = destination
		push	ebx
		push	esi
		mov		esi,[dc_temp]
		inc		ebp								; ebp = count
		add		eax,[esp+16]
		push	edi
		lea		esi,[esi+ecx*4]				; esi = source

		align	16

s4loop:	movzx	edx,byte [esi]
		movzx	ecx,byte [esi+1]
s4cm1:	movzx	edx,byte [SPACEFILLER4+edx]		; colormap
s4cm2:	movzx	edi,byte [SPACEFILLER4+ecx]		; colormap
		shl		edx,8
		movzx	ebx,byte [eax]
		shl		edi,8
		movzx	ecx,byte [eax+1]
		sub		ebx,edx
		sub		ecx,edi
		mov		ebx,[Col2RGB8+0x10000+ebx*4]
		mov		ecx,[Col2RGB8+0x10000+ecx*4]
s4fg1:	add		ebx,[SPACEFILLER4+edx*4]
s4fg2:	add		ecx,[SPACEFILLER4+edi*4]
		or		ebx,0x1f07c1f
		or		ecx,0x1f07c1f
		mov		edx,ebx
		shr		ebx,15
		mov		edi,ecx
		shr		ecx,15
		and		edx,ebx
		and		ecx,edi
		mov		bl,[RGB32k+edx]
		movzx	edx,byte [esi+2]
		mov		bh,[RGB32k+ecx]
		movzx	ecx,byte [esi+3]
		mov		[eax],bl
		mov		[eax+1],bh

s4cm3:	movzx	edx,byte [SPACEFILLER4+edx]		; colormap
s4cm4:	movzx	edi,byte [SPACEFILLER4+ecx]		; colormap
		shl		edx,8
		movzx	ebx,byte [eax+2]
		shl		edi,8
		movzx	ecx,byte [eax+3]
		sub		ebx,edx
		sub		ecx,edi
		mov		ebx,[Col2RGB8+0x10000+ebx*4]
		mov		ecx,[Col2RGB8+0x10000+ecx*4]
s4fg3:	add		ebx,[SPACEFILLER4+edx*4]
s4fg4:	add		ecx,[SPACEFILLER4+edi*4]
		or		ebx,0x1f07c1f
		or		ecx,0x1f07c1f
		mov		edx,ebx
		shr		ebx,15
		mov		edi,ecx
		shr		ecx,15
		and		edx,ebx
		and		ecx,edi
s4p:	add		eax,320							; pitch
		add		esi,4
		mov		bl,[RGB32k+edx]
		mov		bh,[RGB32k+ecx]
s4p2:	mov		[eax-320+2],bl
s4p3:	mov		[eax-320+3],bh
		dec		ebp
		jne		s4loop

		pop		edi
		pop		esi
		pop		ebx
s4nil:	pop		ebp
		ret

		align 16

GLOBAL	rt_add4cols_asm
GLOBAL	_rt_add4cols_asm

rt_add4cols_asm:
_rt_add4cols_asm:
		mov		ecx,[esp+8]
		push	edi
		mov		edi,[esp+16]
		sub		edi,ecx
		js		near a4nil
		mov		eax,[ylookup+ecx*4]
		add		eax,[dc_destorg]
		push	ebx
		push	esi
		mov		esi,[dc_temp]
		push	ebp
		inc		edi
		add		eax,[esp+20]
		lea		esi,[esi+ecx*4]
		
		align 16
a4loop:
		movzx	ebx,byte [esi]
		movzx	edx,byte [esi+1]
		movzx	ecx,byte [eax]
		movzx	ebp,byte [eax+1]
a4cm1:	movzx	ebx,byte [SPACEFILLER4+ebx]		; colormap
a4cm2:	movzx	edx,byte [SPACEFILLER4+edx]		; colormap
a4bg1:	mov		ecx,[SPACEFILLER4+ecx*4]		; bg2rgb
a4bg2:	mov		ebp,[SPACEFILLER4+ebp*4]		; bg2rgb
a4fg1:	add		ecx,[SPACEFILLER4+ebx*4]		; fg2rgb
a4fg2:	add		ebp,[SPACEFILLER4+edx*4]		; fg2rgb
		or		ecx,0x01f07c1f
		or		ebp,0x01f07c1f
		mov		ebx,ecx
		shr		ecx,15
		mov		edx,ebp
		shr		ebp,15
		and		ecx,ebx
		and		ebp,edx
		movzx	ebx,byte [esi+2]
		movzx	edx,byte [esi+3]
		mov		cl,[RGB32k+ecx]
		mov		ch,[RGB32k+ebp]
		mov		[eax],cl
		mov		[eax+1],ch

		movzx	ecx,byte [eax+2]
		movzx	ebp,byte [eax+3]
a4cm3:	movzx	ebx,byte [SPACEFILLER4+ebx]		; colormap
a4cm4:	movzx	edx,byte [SPACEFILLER4+edx]		; colormap
a4bg3:	mov		ecx,[SPACEFILLER4+ecx*4]		; bg2rgb
a4bg4:	mov		ebp,[SPACEFILLER4+ebp*4]		; bg2rgb
a4fg3:	add		ecx,[SPACEFILLER4+ebx*4]		; fg2rgb
a4fg4:	add		ebp,[SPACEFILLER4+edx*4]		; fg2rgb
		or		ecx,0x01f07c1f
		or		ebp,0x01f07c1f
		mov		ebx,ecx
		shr		ecx,15
		mov		edx,ebp
		shr		ebp,15
		and		ebx,ecx
		and		edx,ebp
		mov		cl,[RGB32k+ebx]
		mov		ch,[RGB32k+edx]
		mov		[eax+2],cl
		mov		[eax+3],ch

		add		esi,4
a4p:	add		eax,320							; pitch
		sub		edi,1
		jne		a4loop
		pop		ebp
		pop		esi
		pop		ebx
a4nil:	pop		edi
		ret

		align 16

GLOBAL	rt_addclamp4cols_asm
GLOBAL	_rt_addclamp4cols_asm

rt_addclamp4cols_asm:
_rt_addclamp4cols_asm:
		mov		ecx,[esp+8]
		push	edi
		mov		edi,[esp+16]
		sub		edi,ecx
		js		near ac4nil
		mov		eax,[ylookup+ecx*4]
		add		eax,[dc_destorg]
		push	ebx
		push	esi
		mov		esi,[dc_temp]
		push	ebp
		inc		edi
		add		eax,[esp+20]
		lea		esi,[esi+ecx*4]
		push	edi
		
		align	16
ac4loop:
		movzx	ebx,byte [esi]
		movzx	edx,byte [esi+1]
		mov		[esp],edi
ac4cm1:	movzx	ebx,byte [SPACEFILLER4+ebx]		; colormap
ac4cm2:	movzx	edx,byte [SPACEFILLER4+edx]		; colormap
		movzx	ecx,byte [eax]
		movzx	ebp,byte [eax+1]
ac4fg1:	mov		ebx,[SPACEFILLER4+ebx*4]		; fg2rgb
ac4fg2:	mov		edx,[SPACEFILLER4+edx*4]		; fg2rgb
ac4bg1:	add		ebx,[SPACEFILLER4+ecx*4]		; bg2rgb
ac4bg2:	add		edx,[SPACEFILLER4+ebp*4]		; bg2rgb
		mov		ecx,ebx
		or		ebx,0x01f07c1f
		and		ecx,0x40100400
		and		ebx,0x3fffffff
		mov		edi,ecx
		shr		ecx,5
		mov		ebp,edx
		sub		edi,ecx
		or		edx,0x01f07c1f
		or		ebx,edi
		mov		ecx,ebx
		shr		ebx,15
		and		ebp,0x40100400
		and		ebx,ecx
		and		edx,0x3fffffff
		mov		edi,ebp
		shr		ebp,5
		mov		cl,[RGB32k+ebx]
		sub		edi,ebp
		mov		[eax],cl
		or		edx,edi
		mov		ebp,edx
		shr		edx,15
		movzx	ebx,byte [esi+2]
		and		ebp,edx
		movzx	edx,byte [esi+3]
ac4cm3:	movzx	ebx,byte [SPACEFILLER4+ebx]		; colormap
		mov		cl,[RGB32k+ebp]
ac4cm4:	movzx	edx,byte [SPACEFILLER4+edx]		; colormap
		mov		[eax+1],cl
		movzx	ecx,byte [eax+2]
		movzx	ebp,byte [eax+3]
ac4fg3:	mov		ebx,[SPACEFILLER4+ebx*4]		; fg2rgb
ac4fg4:	mov		edx,[SPACEFILLER4+edx*4]		; fg2rgb
ac4bg3:	add		ebx,[SPACEFILLER4+ecx*4]		; bg2rgb
ac4bg4:	add		edx,[SPACEFILLER4+ebp*4]		; bg2rgb
		mov		ecx,ebx
		or		ebx,0x01f07c1f
		and		ecx,0x40100400
		and		ebx,0x3fffffff
		mov		edi,ecx
		shr		ecx,5
		mov		ebp,edx
		sub		edi,ecx
		or		edx,0x01f07c1f
		or		ebx,edi
		mov		ecx,ebx
		shr		ebx,15
		and		ebp,0x40100400
		and		ebx,ecx
		and		edx,0x3fffffff
		mov		edi,ebp
		shr		ebp,5
		mov		cl,[RGB32k+ebx]
		sub		edi,ebp
		mov		[eax+2],cl
		or		edx,edi
		mov		edi,[esp]
		mov		ebp,edx
		shr		edx,15
		add		esi,4
		and		edx,ebp
		mov		cl,[RGB32k+edx]
		mov		[eax+3],cl

ac4p:	add		eax,320							; pitch
		sub		edi,1
		jne		ac4loop
		pop		edi

		pop		ebp
		pop		esi
		pop		ebx
ac4nil:	pop		edi
		ret

rtext_end:
%ifdef M_TARGET_MACHO
GLOBAL _rtext_tmap_end
_rtext_tmap_end:
%endif
		align	16

;************************

	SECTION .text

GLOBAL	R_SetupShadedCol
GLOBAL	@R_SetupShadedCol@0

# Patch the values of dc_colormap and dc_color into the shaded column drawer.

R_SetupShadedCol:
@R_SetupShadedCol@0:
		mov		eax,[dc_colormap]
		cmp		[s4cm1+3],eax
		je		.cmdone
		mov		[s4cm1+3],eax
		mov		[s4cm2+3],eax
		mov		[s4cm3+3],eax
		mov		[s4cm4+3],eax
.cmdone	mov		eax,[dc_color]
		lea		eax,[Col2RGB8+eax*4]
		cmp		[s4fg1+3],eax
		je		.cdone
		mov		[s4fg1+3],eax
		mov		[s4fg2+3],eax
		mov		[s4fg3+3],eax
		mov		[s4fg4+3],eax
		selfmod s4cm1, s4fg4+7
.cdone	ret

GLOBAL	R_SetupAddCol
GLOBAL	@R_SetupAddCol@0

# Patch the values of dc_colormap, dc_srcblend, and dc_destblend into the
# unclamped adding column drawer.

R_SetupAddCol:
@R_SetupAddCol@0:
		mov		eax,[dc_colormap]
		cmp		[a4cm1+3],eax
		je		.cmdone
		mov		[a4cm1+3],eax
		mov		[a4cm2+3],eax
		mov		[a4cm3+3],eax
		mov		[a4cm4+3],eax
.cmdone	mov		eax,[dc_srcblend]
		cmp		[a4fg1+3],eax
		je		.sbdone
		mov		[a4fg1+3],eax
		mov		[a4fg2+3],eax
		mov		[a4fg3+3],eax
		mov		[a4fg4+3],eax
.sbdone	mov		eax,[dc_destblend]
		cmp		[a4bg1+3],eax
		je		.dbdone
		mov		[a4bg1+3],eax
		mov		[a4bg2+3],eax
		mov		[a4bg3+3],eax
		mov		[a4bg4+3],eax
		selfmod a4cm1, a4bg4+7
.dbdone	ret

GLOBAL	R_SetupAddClampCol
GLOBAL	@R_SetupAddClampCol@0

# Patch the values of dc_colormap, dc_srcblend, and dc_destblend into the
# add with clamping column drawer.

R_SetupAddClampCol:
@R_SetupAddClampCol@0:
		mov		eax,[dc_colormap]
		cmp		[ac4cm1+3],eax
		je		.cmdone
		mov		[ac4cm1+3],eax
		mov		[ac4cm2+3],eax
		mov		[ac4cm3+3],eax
		mov		[ac4cm4+3],eax
.cmdone	mov		eax,[dc_srcblend]
		cmp		[ac4fg1+3],eax
		je		.sbdone
		mov		[ac4fg1+3],eax
		mov		[ac4fg2+3],eax
		mov		[ac4fg3+3],eax
		mov		[ac4fg4+3],eax
.sbdone	mov		eax,[dc_destblend]
		cmp		[ac4bg1+3],eax
		je		.dbdone
		mov		[ac4bg1+3],eax
		mov		[ac4bg2+3],eax
		mov		[ac4bg3+3],eax
		mov		[ac4bg4+3],eax
		selfmod ac4cm1, ac4bg4+7
.dbdone	ret

EXTERN setvlinebpl_
EXTERN setpitch3

GLOBAL	@ASM_PatchPitch@0
GLOBAL	_ASM_PatchPitch
GLOBAL	ASM_PatchPitch

ASM_PatchPitch:
_ASM_PatchPitch:
@ASM_PatchPitch@0:
		mov		eax,[dc_pitch]
		mov		[rdcp1+2],eax
		mov		[rdcp2+2],eax
		mov		[rdcp3+2],eax
		mov		[s4p+1],eax
		mov		[a4p+1],eax
		mov		[ac4p+1],eax
		mov		ecx,eax
		neg		ecx
		inc		ecx
		inc		ecx
		mov		[s4p2+2],ecx
		inc		ecx
		mov		[s4p3+2],ecx
		selfmod rtext_start, rtext_end
		call	setpitch3
		jmp		setvlinebpl_
