;; Copyright (c) 1991,1993-1995 Argonaut Technologies Limited. All rights reserved. ;; ;; $Id: T_PIA.ASM 1.1 1996/09/26 19:04:08 JOHNG Exp $ ;; $Locker: $ ;; ;; Trapezoid rendering for arbitary width texture mapping ;; .386p .model c,flat include drv.inc WRAP equ 1 WRAPROW equ 1 TRANSP equ 1 .data noffset dd ? .code ; Macro to increment those parts of the per scan line ; increment that depend on whether there has been a carry ; from the fractional part of the current screen x coordinate scan_inc macro carry,LIGHT,SBPP local lab2 if LIGHT mov ebx,work.pi.current endif ; LIGHT if LIGHT mov ecx,work.pi.d_&carry& endif ; LIGHT add ebx,ecx mov work.pi.current,ebx mov ebx,work.awsl.u_current mov ecx,work.awsl.du_&carry& mov ebp,work.awsl.source_current mov edi,work.awsl.dsource_&carry& add ebx,ecx ; work.awsl.u_current += work.awsl.dsource_&carry& sbb ecx,ecx ; Save -carry add ebp,edi ; work.awsl.source_current += work.awsl.dsource_&carry& mov work.awsl.u_current,ebx if WRAP mov ebx,dword ptr work.awsl.u_int_current add ebx,work.awsl.du_int_&carry& sub ebx,ecx ; work.awsl.u_int_current += carry; mov dword ptr work.awsl.u_int_current,ebx endif ; WRAP ifidni ,<2> shl ecx,1 elseifidni ,<3> lea ecx,[ecx+ecx*2] elseifidni ,<4> shl ecx,2 endif ; sub ebp,ecx ; work.awsl.source_current += carry*SBPP mov ebx,work.awsl.v_current mov ecx,work.awsl.dv_&carry& add ebx,ecx mov work.awsl.v_current,ebx jnc lab2 mov edi,work.texture.stride_b add ebp,edi lab2: mov work.awsl.source_current,ebp endm TriangleRender macro fn,LIGHT,SBPP,DBPP,BUMP fn proc uses eax ebx ecx edx esi edi ebp outer: mov eax,work.awsl.edge mov ebx,[eax].scan_edge.count test ebx,ebx jz exit dec ebx ; work.awsl.edge->count-- mov [eax].scan_edge.count,ebx if BUMP mov ecx,work.bump.base sub ecx,work.texture.base mov noffset,ecx endif mov edi,work.awsl.start mov ebx,work.awsl._end cmp edi,ebx mov eax,work.awsl.u_current mov ebx,work.awsl.v_current mov al,byte ptr work.awsl.u_int_current if LIGHT mov ecx,work.pi.current mov work.pi.currentpix,ecx endif ; LIGHT mov ah,byte ptr work.awsl.u_int_current+1 mov esi,work.awsl.source_current jge scan_back ; Forward scan loopf: mov ecx,work.awsl._end cmp edi,ecx jge next if TRANSP ifidni ,<1> mov dl,[esi] test dl,dl jz failf ; Skip if transparent elseifidni ,<2> mov dl,[esi] mov dh,1[esi] or dl,dh jz failf elseifidni ,<3> mov dl,[esi] mov dh,1[esi] or dl,dh mov dh,2[esi] or dl,dh jz failf endif ; endif ; TRANSP if LIGHT xor ecx,ecx mov ch,byte ptr work.pi.currentpix+2 ; Get lighting index mov cl,[esi] ; Get texel mov edx,work.shade_table ifidni ,<1> add edx,ecx mov bl,[edx] ; Light texel mov [edi],bl ; Store texel inc edi ; ptr++ elseifidni ,<2> mov bx,[edx+ecx*2] ; Light texel mov [edi],bx ; Store texel lea edi,2[edi] ; ptr++ elseifidni ,<3> mov bx,[edx+ecx*4] ; Light texel mov [edi],bx ; Store texel mov bl,2[edx+ecx*4] ; Light texel mov 2[edi],bl ; Store texel lea edi,3[edi] ; ptr++ else ; SHOULDN'T GET HERE add edi,DBPP endif ; mov edx,work.pi.currentpix mov ecx,work.pi.grad_x ; i += di add edx,ecx mov work.pi.currentpix,edx jmp contf failf: ifidni ,<1> inc edi ; ptr++ else ; add edi,DBPP endif ; mov edx,work.pi.currentpix mov ecx,work.pi.grad_x ; i += di add edx,ecx mov work.pi.currentpix,edx elseif BUMP ; Bump mapping xor ecx,ecx mov cl,[esi] ; Get texel mov edx,noffset mov dl,[esi+edx] ; Get normal and edx,0ffh add edx,work.lighting_table ; Calculate light level from normal mov ch,[edx] mov edx,work.shade_table mov cl,[edx+ecx] ; Light texel mov [edi],cl ifidni ,<1> inc edi ; ptr++ else ; add edi,DBPP endif ; jmp contf failf: ifidni ,<1> inc edi ; ptr++ else ; add edi,DBPP endif ; else ; LIGHT ; No lighting ifidni ,<1> mov cl,[esi] ; Get texel mov [edi],cl elseifidni ,<2> mov cl,[esi] mov ch,1[esi] mov [edi],cl mov 1[edi],ch elseifidni ,<3> mov cl,[esi] ; Get texel mov [edi],cl mov ch,1[esi] mov 1[edi],ch ; Store green mov cl,2[esi] mov 2[edi],cl ; Store red elseifidni ,<4> mov ecx,[esi] mov [edi],ecx endif ; ifidni ,<1> inc edi ; ptr++ else ; add edi,DBPP endif ; jmp contf failf: ifidni ,<1> inc edi ; ptr++ else ; add edi,DBPP endif ; endif ; LIGHT contf: ; Redo this with high and low halfwords of du swapped mov ecx,work.awsl.du add eax,ecx ; u += du mov ecx,work.awsl.dsource sbb edx,edx ; edx = -carry add esi,ecx mov ecx,work.awsl.du_int sub eax,edx ; work.awsl.du += carry ifidni ,<2> shl edx,1 elseifidni ,<3> lea edx,[edx+2*edx] elseifidni ,<4> shl edx,2 endif ; sub esi,edx ; esi += carry add eax,ecx ; u_int += du_int mov ecx,work.awsl.dv mov edx,work.texture.stride_b; add ebx,ecx jnc nostridef add esi,edx nostridef: test ah,ah jl nowidthf mov ecx,work.texture.width_p add eax,ecx ifidni ,<1> add esi,ecx elseifidni ,<2> lea esi,[esi+2*ecx] elseifidni ,<3> lea ecx,[ecx+2*ecx] add esi,ecx elseifidni ,<4> lea esi,[esi+4*ecx] endif ; nowidthf: mov ecx,work.texture.base cmp esi,ecx ; Have we underrun? jge nosizef mov ecx,work.texture._size add esi,ecx nosizef: jmp loopf scan_back: ; Backwards scan loopb: mov ecx,work.awsl._end cmp edi,ecx jle next sub ecx,edx if LIGHT mov edx,work.pi.currentpix endif if LIGHT mov ecx,work.pi.grad_x ; i += di sub edx,ecx mov work.pi.currentpix,edx endif ; Redo this with high and low halfwords of du swapped mov ecx,work.awsl.du add eax,ecx ; u += du mov ecx,work.awsl.dsource sbb edx,edx ; edx = -carry add esi,ecx mov ecx,work.awsl.du_int sub eax,edx add eax,ecx ; u_int += du_int ifidni ,<1> sub esi,edx elseifidni ,<2> shl edx,1 sub esi,edx elseifidni ,<3> lea edx,[edx+edx*2] sub esi,edx elseifidni ,<4> shl edx,2 sub esi,edx endif mov ecx,work.awsl.dv add ebx,ecx jnc nostrideb mov ecx,work.texture.stride_b add esi,ecx nostrideb: test ah,ah jl nowidthb mov ecx,work.texture.width_p add eax,ecx ifidni ,<1> add esi,ecx elseifidni ,<2> lea esi,[esi+2*ecx] elseifidni ,<3> lea ecx,[ecx+2*ecx] add esi,ecx elseifidni ,<4> lea esi,[esi+4*ecx] endif ; nowidthb: mov ecx,work.texture.base cmp esi,ecx jge nosizeb mov ecx,work.texture._size add esi,ecx nosizeb: ifidni ,<1> dec edi ; ptr += 1 else ; sub edi,DBPP endif ; if TRANSP ifidni ,<1> mov bl,[esi] test bl,bl jz loopb ; Skip if transparent elseifidni ,<2> mov bl,[esi] mov bh,1[esi] or bl,bh jz failb elseifidni ,<3> mov bl,[esi] mov bh,1[esi] or bl,bh mov bh,2[esi] or bl,bh jz failb endif ; endif ; if LIGHT xor ecx,ecx mov ch,byte ptr work.pi.currentpix+2 mov edx,work.shade_table endif ; ifidni ,<1> mov cl,[esi] ; Get texel ifidni ,<1> if LIGHT mov cl,[ecx+edx] ; Light texel endif if BUMP and ecx,0ffh mov edx,noffset mov dl,[esi+edx] and edx,0ffh add edx,work.lighting_table ; Calculate light level from normal mov ch,[edx] mov edx,work.shade_table mov cl,[edx+ecx] ; Light texel endif mov [edi],cl elseifidni ,<2> if LIGHT mov cx,[edx+ecx*2] mov [edi],cx endif elseifidni ,<3> if LIGHT mov bx,[edx+ecx*4] mov [edi],bx mov bl,2[edx+ecx*4] mov 2[edi],bl endif endif ; DBPP elseifidni ,<2> mov cl,[esi] mov [edi],cl ; Store texel mov cl,1[esi] mov 1[edi],cl ; Store texel elseifidni ,<3> mov ecx,[esi] mov [edi],cl ; Store texel mov 1[edi],ch ; Store texel ror ecx,16 mov 2[edi],cl ; Store texel elseifidni ,<4> mov ecx,[esi] mov [edi],ecx ; Store texel endif ; failb: jmp loopb next: ; Per scan line updates assume eax:ptr scan_edge mov eax,work.awsl.edge mov ebx,[eax].f mov ecx,[eax].d_f add ebx,ecx ; edge->f += edge->d_f mov [eax].f,ebx mov ecx,[eax].d_i mov ebx,work.awsl._end ifidni ,<1> adc ebx,ecx ; work.awsl._end += edge->d_i+carry elseifidni ,<2> adc ecx,0 shl ecx,1 add ebx,ecx elseifidni ,<3> adc ecx,0 lea ecx,[ecx+2*ecx] add ebx,ecx ; work.awsl._end += 3*(edge->d_i+carry) elseifidni ,<4> adc ecx,0 shl ecx,2 add ebx,ecx endif ; mov work.awsl._end,ebx mov ebx,work.main.f mov ecx,work.main.d_f add ebx,ecx mov work.main.f,ebx mov ebx,work.awsl.start mov ecx,work.main.d_i jnc noscarry ; if (carry) ... adc ecx,0 lea esi,[esi+2*ecx] ifidni ,<1> add ebx,ecx elseifidni ,<2> lea ebx,[ebx+2*ecx] elseifidni ,<3> lea ecx,[ecx+2*ecx] add ebx,ecx elseifidni ,<4> lea ebx,[ebx+4*ecx] endif mov work.awsl.start,ebx scan_inc carry,LIGHT,SBPP jmp cont ; ... else ... noscarry: lea esi,[esi+2*ecx] ifidni ,<1> add ebx,ecx elseifidni ,<2> lea ebx,[ebx+2*ecx] elseifidni ,<3> lea ecx,[ecx+2*ecx] add ebx,ecx elseifidni ,<4> lea ebx,[ebx+4*ecx] endif mov work.awsl.start,ebx scan_inc nocarry,LIGHT,SBPP ; ... endif cont: mov ebx,dword ptr work.awsl.u_int_current test bh,bh ; Test sign of low halfword jl lab1 mov ecx,work.texture.width_p add ebx,ecx mov dword ptr work.awsl.u_int_current,ebx mov ebx,work.awsl.source_current ifidni ,<1> add ebx,ecx elseifidni ,<2> lea ebx,[ebx+2*ecx] elseifidni ,<3> lea ecx,[ecx+2*ecx] add ebx,ecx elseifidni ,<4> lea ebx,[ebx+4*ecx] endif mov work.awsl.source_current,ebx lab1: mov ebx,work.awsl.source_current mov ecx,work.texture.base cmp ebx,ecx jge outer mov ecx,work.texture._size add ebx,ecx mov work.awsl.source_current,ebx jmp outer exit: ret fn endp endm if PARTS and PART_8 TriangleRender TrapezoidRenderPITA,0,1,1,0 endif if PARTS and PART_BUMP TriangleRender TrapezoidRenderPITAN,0,1,1,1 endif if PARTS and PART_8 TriangleRender TrapezoidRenderPITIA,1,1,1,0 endif if PARTS and PART_15 TriangleRender TrapezoidRenderPITA15,0,2,2,0 endif if PARTS and PART_24 TriangleRender TrapezoidRenderPITA24,0,3,3,0 endif if PARTS and PART_24 TriangleRender TrapezoidRenderPITIA_RGB_888,1,1,3,0 endif if PARTS and PART_15 TriangleRender TrapezoidRenderPITIA_RGB_555,1,1,2,0 endif end