;* ;* 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 ; 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 %ifdef M_TARGET_LINUX EXTERN ylookup EXTERN centery EXTERN fuzzpos EXTERN fuzzoffset EXTERN NormalLight EXTERN realviewheight EXTERN fuzzviewheight EXTERN CPU EXTERN dc_pitch EXTERN dc_colormap EXTERN dc_iscale EXTERN dc_texturefrac 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 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 %else EXTERN _ylookup EXTERN _centery EXTERN _fuzzpos EXTERN _fuzzoffset EXTERN _NormalLight EXTERN _realviewheight EXTERN _fuzzviewheight EXTERN _CPU EXTERN _dc_pitch EXTERN _dc_colormap EXTERN _dc_iscale EXTERN _dc_texturefrac 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 _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 %define ylookup _ylookup %define centery _centery %define fuzzpos _fuzzpos %define fuzzoffset _fuzzoffset %define NormalLight _NormalLight %define realviewheight _realviewheight %define fuzzviewheight _fuzzviewheight %define CPU _CPU %define dc_pitch _dc_pitch %define dc_colormap _dc_colormap %define dc_iscale _dc_iscale %define dc_texturefrac _dc_texturefrac %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 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 R_SetSpanSource_ASM _R_SetSpanSource_ASM %define R_SetSpanSize_ASM _R_SetSpanSize_ASM %define R_SetSpanColormap_ASM _R_SetSpanColormap_ASM %endif _ds_cursource: ds_cursource: DD 0 _ds_curcolormap: 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 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 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 aret: ret SECTION .rtext progbits alloc exec write align=64 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 align 16 @R_DrawSpanP_ASM@0: _R_DrawSpanP_ASM: R_DrawSpanP_ASM: mov eax,[ds_x2] mov ecx,[ds_x1] sub eax,ecx jl aret ; count < 0: nothing to do, so leave push ebx push edi push ebp push esi 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 [ds_xstep],edx mov edx,[ds_ystep] mov ecx,[ds_xfrac] dsy4: shr ecx,26 dsm8: and edx,0xffffffc0 or ebp,edx mov [ds_ystep],ebp mov ebp,[ds_yfrac] mov edx,[ds_xfrac] dsy2: shl edx,6 dsm9: and ebp,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,[ds_xstep] adc ecx,[ds_ystep] 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,[ds_xstep] adc ecx,[ds_ystep] dsm2: and ebp,0xfc00003f dsx2: rol ebp,6 mov eax,ecx add edx,[ds_xstep] adc ecx,[ds_ystep] 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,[ds_xstep] spstep2d adc ecx,[ds_ystep] dsm3: and ebp,0xfc00003f dsx4: rol ebp,6 mov eax,ecx spstep1e add edx,[ds_xstep] spstep2e adc ecx,[ds_ystep] 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,[ds_xstep] spstep2f adc ecx,[ds_ystep] 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,[ds_xstep] spstep2g adc ecx,[ds_ystep] spmapg mov bl,[ebx+SPACEFILLER4] ;map texel4 dec esi mov [edi-1],bl ;store texel4 jnz near dsloop dsdone 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 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 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 [ds_xstep],edx mov edx,[ds_ystep] mov ecx,[ds_xfrac] dmsy4: shr ecx,26 dmsm8: and edx,0xffffffc0 or ebp,edx mov [ds_ystep],ebp mov ebp,[ds_yfrac] mov edx,[ds_xfrac] dmsy2: shl edx,6 dmsm9: and ebp,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,[ds_xstep] adc ecx,[ds_ystep] 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,[ds_xstep] adc ecx,[ds_ystep] dmsm2: and ebp,0xfc00003f dmsx2: rol ebp,6 mov eax,ecx add edx,[ds_xstep] adc ecx,[ds_ystep] 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,[ds_xstep] mspstep2d adc ecx,[ds_ystep] dmsm3: and ebp,0xfc00003f dmsx4: rol ebp,6 mov eax,ecx mspstep1e add edx,[ds_xstep] mspstep2e adc ecx,[ds_ystep] 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,[ds_xstep] mspstep2f adc ecx,[ds_ystep] 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,[ds_xstep] mspstep2g adc ecx,[ds_ystep] 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 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 ; need 12 bytes of filler to make it aligned db 0x8D,0x80,0,0,0,0 ; lea eax,[eax+00000000] db 0x8D,0xBF,0,0,0,0 ; lea edi,[edi+00000000] 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 esi,[dc_ctspan+edx*4] lea eax,[dc_temp+ecx*4+edx] ; 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 lea ecx,[dc_temp+ecx+esi] ; ecx = source mov edi,[ylookup+esi] 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] lea ecx,[dc_temp+edx*4] ; ecx = source mov edx,[dc_pitch] ; edx = pitch add eax,esi ; eax = dest add eax,[dc_destorg] 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,[dc_temp+ecx+edi] ; ebp = source 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] lea ebp,[dc_temp+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] lea ebp,[dc_temp+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 ;************************ SECTION .text 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 call setpitch3 jmp setvlinebpl_