;; Copyright (c) 1992,1993-1995 Argonaut Technologies Limited. All rights reserved. ;; ;; $Id: TT15_PIZ.ASM 1.2 1996/12/10 16:46:56 jon Exp $ ;; $Locker: $ ;; ;; 15 bit RGB_555 5 bit mode ;; ;; Triangle scan convertion and rendering ;; ;; Perfect scan, integer vertices, Z buffered ;; .386p .model flat,c include drv.inc include 586_macs.inc if 1 SHOW_CODESIZE macro _name,_total %out _name = _total endm else SHOW_CODESIZE macro x,y endm endif X equ 0 Y equ 1 Z equ 2 _X equ 0 _Y equ 4 _Z equ 8 ;; Setup some macros that are used to put colour, texture and depth buffers in different ;; segments ;; if 0 CSEG equ es: DSEG equ TSEG equ SETUP_SEGS macro push es mov es,word ptr work.colour.base+4 endm RESTORE_SEGS macro pop es endm else CSEG equ DSEG equ TSEG equ SETUP_SEGS macro endm RESTORE_SEGS macro endm endif ;; Various macros for generating the triangle renderers ;; ; Divide edx:eax by g_divisor with no overflow ; ; Assumes Z flag has sign of numerator ; ; Trashes ebx ; ; GDIVIDE macro dirn local negative,done,overflow mov ebx,g_divisor js negative cmp ebx,edx jbe overflow div ebx ifidni , neg eax endif jmp done overflow: xor eax,eax jmp done negative: neg edx neg eax sbb edx,0 cmp ebx,edx jbe overflow div ebx ifidni , neg eax endif done: endm ; Comparison that change sense with rendering direction ; CMP_f macro a,b cmp a,b endm CMP_b macro a,b cmp b,a endm ; Setup of an integer, perfect scan triangle ; ; Leave g_divisor in eax, with sign of g_divisor in flags ; SETUP_PI macro _setup_start = $ ; Get pixel width of colour and z buffer from fw.output->width ; Get Y components of vertices ; mov eax,[esi].brp_vertex.comp[C_SY*4] mov ebx,[edi].brp_vertex.comp[C_SY*4] mov ecx,[ebp].brp_vertex.comp[C_SY*4] ; Sort pointers and values in order of y value ; cmp eax,ebx jg short sort_3 cmp ebx,ecx jle short sort_done ; abc cmp eax,ecx jg short sort_2 ; acb SWAP edi,ebp jmp short sort_done sort_2: ; cab SWAP edi,ebp SWAP esi,edi jmp short sort_done sort_3: cmp ecx,ebx jg short sort_4 ; cba SWAP esi,ebp jmp short sort_done sort_4: cmp eax,ecx jg short sort_5 ; bac SWAP esi,edi jmp short sort_done sort_5: ; bca SWAP esi,edi SWAP edi,ebp sort_done: if 1 ; Work out integer vertex values ; ; XXX Should really do this at projection time ; mov eax,[esi].brp_vertex.comp[C_SX*4] mov ebx,[edi].brp_vertex.comp[C_SX*4] mov ecx,[ebp].brp_vertex.comp[C_SX*4] sar eax,16 sar ebx,16 sar ecx,16 mov vertex_0[_X],eax mov vertex_1[_X],ebx mov vertex_2[_X],ecx mov eax,[esi].brp_vertex.comp[C_SY*4] mov ebx,[edi].brp_vertex.comp[C_SY*4] mov ecx,[ebp].brp_vertex.comp[C_SY*4] sar eax,16 sar ebx,16 sar ecx,16 mov vertex_0[_Y],eax mov vertex_1[_Y],ebx mov vertex_2[_Y],ecx endif ; Work out top.count and bot.count - the heights of each part ; of the triangle ; cmp eax,ecx ; Check for zero height polys je quit ; Work out deltas and gradients along edges ; ; top short edge ; mov edx,vertex_1[_X] ; work.top.x sub edx,vertex_0[_X] mov work.top.x,edx mov ebx,vertex_1[_Y] ; work.top.y sub ebx,vertex_0[_Y] mov work.top.y,ebx mov work.top.count,ebx je short no_top FIX_DIV ; work.top.grad = work.top.x/work.top.y idiv ebx mov work.top.grad,eax mov word ptr work.top.d_f+2,ax sar eax,16 add eax,work.colour.stride_p mov work.top.d_i,eax no_top: ; bottom short edge (don't need to save deltas) ; mov edx,vertex_2[_X] ; work.bot.x sub edx,vertex_1[_X] mov ebx,vertex_2[_Y] ; work.bot.y sub ebx,vertex_1[_Y] mov work.bot.count,ebx je short no_bottom FIX_DIV ; work.bot.grad = work.bot.x/work.bot.y idiv ebx mov work.bot.grad,eax mov word ptr work.bot.d_f+2,ax sar eax,16 add eax,work.colour.stride_p mov work.bot.d_i,eax no_bottom: ; long edge ; mov edx,vertex_2[_X] ; work.main.x sub edx,vertex_0[_X] mov work.main.x,edx mov ebx,vertex_2[_Y] ; work.main.y sub ebx,vertex_0[_Y] mov work.main.y,ebx FIX_DIV ; work.main.grad = work.main.x/work.main.y idiv ebx mov work.main.grad,eax mov word ptr work.main.d_f+2,ax sar eax,16 add eax,work.colour.stride_p mov work.main.d_i,eax ; Work out start values for edges as pixel offsets ; mov ebx,work.colour.stride_p mov eax,vertex_0[_Y] imul ebx add eax,vertex_0[_X] mov work.main.f,080000000h mov work.main.i,eax mov work.top.f,080000000h mov work.top.i,eax mov eax,vertex_1[_Y] imul ebx add eax,vertex_1[_X] mov work.bot.f,080000000h mov work.bot.i,eax if 0 mov eax,work.main.grad sar eax,1 mov edx,eax shl eax,16 sar edx,16 add work.main.f,eax adc work.main.i,edx mov eax,work.top.grad sar eax,1 mov edx,eax sar edx,16 shl eax,16 add work.top.f,eax adc work.top.i,edx mov eax,work.bot.grad sar eax,1 mov edx,eax sar edx,16 shl eax,16 add work.bot.f,eax adc work.bot.i,edx endif ; Work out divisor for use in parameter gradient calcs. ; mov eax,work.main.x imul work.top.y mov ebx,eax mov eax,work.top.x imul work.main.y sub eax,ebx je quit ; quit if g_divisor is 0 ; Leave g_divisor in eax endm ; Per parameter initialisation of perfect scan, integer vertex triangle ; PARAM_PI_DIRN macro vparam,param,dirn,unsigned:=<0> ; d_p_x = (d_p_1.work.main.y - d_p_2.work.top.y)/g_denom ; mov eax,[ebp].brp_vertex.vparam ; d_p_2 sub eax,[esi].brp_vertex.vparam push eax imul work.top.y mov ebx,eax mov ecx,edx mov eax,[edi].brp_vertex.vparam ; d_p_1 sub eax,[esi].brp_vertex.vparam push eax imul work.main.y sub eax,ebx sbb edx,ecx GDIVIDE dirn mov param.grad_x,eax ; d_p_y = (d_p_2.work.top.x - d_p_1.work.main.x)/g_denom ; pop eax ; d_p_1 imul work.main.x mov ebx,eax mov ecx,edx pop eax ; d_p_2 imul work.top.x sub eax,ebx sbb edx,ecx GDIVIDE dirn mov param.grad_y,eax ; Initialise parameter from top vertex ; mov eax,[esi].brp_vertex.vparam mov ebx,param.grad_x sar ebx,1 adc eax,ebx ; mov ebx,param.grad_y ; sar ebx,1 ; adc eax,ebx if unsigned xor eax,080000000h endif mov param.current,eax ; Work out parameter increments per scanline ; movsx eax,word ptr work.main.grad+2 imul param.grad_x add eax,param.grad_y mov param.d_nocarry,eax add eax,param.grad_x mov param.d_carry,eax endm .data db '$Id: TT15_PIZ.ASM 1.2 1996/12/10 16:46:56 jon Exp $',0 align 4 ;colour_row_width dd 0 temp_b dd 0 temp_g dd 0 temp_r dd 0 temp_colour dd 0 p0_offset_x dd 0 ; Offset of start pixel centre from vertex 0 p0_offset_y dd 0 temp_i dd 0 temp_u dd 0 temp_v dd 0 ; Integer vertex poitisions ; vertex_0 dd 2 dup(?) vertex_1 dd 2 dup(?) vertex_2 dd 2 dup(?) g_divisor dd 0 ; Bottom of param. gradient calc. .code if PARTS and PART_15Z ; void TriangleRenderPIZ2_RGB_555(struct br_vertex *pvertex_0, ; struct br_vertex *pvertex_1, ; struct br_vertex *pvertex_2); ; ; C stub directly to triangle renderer ; TriangleRenderPIZ2_RGB_555 proc uses eax ebx ecx edx esi edi, pblock : ptr dword, pvertex_0 : ptr word, pvertex_1 : ptr word, pvertex_2 : ptr word ; Get pointers to vertex structures and colour ; ; esi = vertex 0 ; edi = vertex 1 ; ebp = vertex 2 ; push ebp SETUP_SEGS mov esi,pvertex_0 mov edi,pvertex_1 mov ebp,pvertex_2 call RawTriangle_PIZ2_RGB_555 RESTORE_SEGS pop ebp ret TriangleRenderPIZ2_RGB_555 endp ; Trapezoid loop for flat shaded z (16 bit) buffered faces ; ; Arguments control: ; whether loop uses 'top' or 'bottom' variables ; which direction scanline are rendered from the long edge ; TRAPEZOID_PIZ2_RGB_555 macro half,dirn local scan_loop,pixel_loop,pixel_behind,no_pixels local start_carried,done_trapezoid cmp work.half.count,0 je done_trapezoid mov ecx,work.half.i ; Prepare for next iteration of loop ; scan_loop: push esi push edx push ecx mov edi,work.depth.base mov ebx,work.colour.base lea edi,[edi+esi*2] ; z buffer lea esi,[esi*2] ; colour buffer lea ecx,[ecx*2] ; Render same colour pixels along scanline (forwards or backwards) ; ; bl: colour ; ecx: address of end of scanline ; edx: z (16.16) ; ebp: z delta (16.16) ; esi: frame buffer ptr ; edi: z buffer ptr ; CMP_&dirn esi,ecx jae short no_pixels pixel_loop: ifidni , sub edx,ebp ; z -= d_z_z sub edi,2 ; z_ptr-- sub esi,2 ; ptr-- endif mov eax,edx shr eax,16 cmp ax, DSEG [edi] ; if (z > *zptr) jae short pixel_behind mov DSEG [edi],ax ; *zptr = z mov eax,temp_colour mov CSEG [esi+ebx],ax ; xrgb 1 5 5 5 pixel_behind: ifidni , add edx,ebp ; z += d_z_z add edi,2 ; z_ptr++ add esi,2 ; ptr++ endif CMP_&dirn esi,ecx jb short pixel_loop no_pixels: ; Updates for next scanline: ; pop ecx pop edx pop esi mov edi,work.half.d_f mov eax,work.main.d_f add work.half.f,edi ; x_end += work.main.grad_end (fraction) adc ecx,work.half.d_i ; endptr += integer(dx_end)+CARRY add work.main.f,eax ; x+= work.main.grad (fraction) jc start_carried add esi,work.main.d_i ; fb_offset+=delta+CARRY add edx,work.pz.d_nocarry dec work.half.count jne scan_loop jmp short done_trapezoid start_carried: adc esi,work.main.d_i ; fb_offset+=delta+CARRY add edx,work.pz.d_carry dec work.half.count jne scan_loop done_trapezoid: endm ; Triangle_PIZ2_RGB_555 ; ; Render a triangle into frame buffer ; ; Flat colour ; Z buffer ; Integer vertices ; Perfect point sampling ; ; esi = vertex 0 pointer ; edi = vertex 1 pointer ; ebp = vertex 2 pointer ; RawTriangle_PIZ2_RGB_555 proc if 1 ; Construct colour word ; mov eax,[esi].brp_vertex.comp[C_R*4] mov ebx,[esi].brp_vertex.comp[C_G*4] mov ecx,[esi].brp_vertex.comp[C_B*4] push ebp mov ebp,0f80000h and eax,ebp and ebx,ebp and ecx,ebp shr eax,9 shr ebx,14 shr ecx,19 or eax,ebx or eax,ecx mov temp_colour,eax pop ebp endif SETUP_PI jl reversed mov g_divisor,eax ; Scan forwards ; PARAM_PI_DIRN comp[C_SZ*4],work.pz,f,1 ; Load up registers for first time around inner loop ; mov esi,work.main.i mov edx,work.pz.current mov ebp,work.pz.grad_x TRAPEZOID_PIZ2_RGB_555 top,f TRAPEZOID_PIZ2_RGB_555 bot,f quit: ret ; Scan backwards ; reversed: neg eax mov g_divisor,eax PARAM_PI_DIRN comp[C_SZ*4],work.pz,b,1 ; Load up registers for first time around inner loop ; mov esi,work.main.i mov edx,work.pz.current mov ebp,work.pz.grad_x TRAPEZOID_PIZ2_RGB_555 top,b TRAPEZOID_PIZ2_RGB_555 bot,b ret SHOW_CODESIZE ,<%($-_setup_start)> RawTriangle_PIZ2_RGB_555 endp endif if PARTS and PART_15Z ; void TriangleRenderPIZ2I_RGB_555(struct br_vertex *pvertex_0, ; struct br_vertex *pvertex_1, ; struct br_vertex *pvertex_2); ; ; C stub directly to triangle renderer ; TriangleRenderPIZ2I_RGB_555 proc uses eax ebx ecx edx esi edi, pblock : ptr dword, pvertex_0 : ptr word, pvertex_1 : ptr word, pvertex_2 : ptr word ; Get pointers to vertex structures and colour ; ; eax = colour ; esi = vertex 0 ; edi = vertex 1 ; ebp = vertex 2 ; push ebp SETUP_SEGS mov esi,pvertex_0 mov edi,pvertex_1 mov ebp,pvertex_2 call RawTriangle_PIZ2I_RGB_555 RESTORE_SEGS pop ebp ret TriangleRenderPIZ2I_RGB_555 endp ; Trapezoid loop for gouraud shaded z buffered faces ; ; Arguments control: ; whether loop uses 'top' or 'bottom' variables ; which direction scanline are rendered from the long edge ; TRAPEZOID_PIZ2I_RGB_555 macro half,dirn local scan_loop,pixel_loop,pixel_behind,no_pixels local start_carried,done_trapezoid cmp work.half.count,0 je done_trapezoid mov ecx,work.half.i ; Prepare for next iteration of loop ; scan_loop: push esi push edx push ecx mov eax,work.pr.current mov temp_r,eax mov eax,work.pg.current mov temp_g,eax mov eax,work.pb.current mov temp_b,eax mov edi,work.depth.base mov ebx,work.colour.base lea edi,[edi+esi*2] ; z buffer lea esi,[esi*2] ; colour buffer lea ecx,[ecx*2] ; Render same colour pixels along scanline (forwards or backwards) ; ; bl: colour ; ecx: address of end of scanline ; edx: z (16.16) ; ebp: z delta (16.16) ; esi: frame buffer ptr ; edi: z buffer ptr ; CMP_&dirn esi,ecx jae short no_pixels pixel_loop: ifidni , sub edx,ebp ; z -= d_z_z mov eax,work.pr.grad_x sub temp_r,eax mov eax,work.pg.grad_x sub temp_g,eax mov eax,work.pb.grad_x sub temp_b,eax sub edi,2 ; z_ptr-- sub esi,2 ; ptr-- endif mov eax,edx shr eax,16 cmp ax, DSEG [edi] ; if (z > *zptr) jae short pixel_behind mov DSEG [edi],ax ; *zptr = z push ecx xor ecx,ecx mov cl,byte ptr temp_r+2 shr cl,3 mov eax,ecx shl eax,5 mov cl,byte ptr temp_g+2 shr cl,3 or al,cl shl eax,5 mov cl,byte ptr temp_b+2 shr cl,3 or al,cl mov CSEG [esi+ebx],ax ; xrgb 1 5 5 5 pop ecx pixel_behind: ifidni , add edx,ebp ; z += d_z_z mov eax,work.pr.grad_x add temp_r,eax mov eax,work.pg.grad_x add temp_g,eax mov eax,work.pb.grad_x add temp_b,eax add edi,2 ; z_ptr++ add esi,2 ; ptr++ endif CMP_&dirn esi,ecx jb short pixel_loop no_pixels: ; Updates for next scanline: ; pop ecx pop edx pop esi mov edi,work.half.d_f mov eax,work.main.d_f add work.half.f,edi ; x_end += work.main.grad_end (fraction) adc ecx,work.half.d_i ; endptr += integer(dx_end)+CARRY add work.main.f,eax ; x+= work.main.grad (fraction) jc start_carried add esi,work.main.d_i ; fb_offset+=delta+CARRY add edx,work.pz.d_nocarry ; z mov eax,work.pr.d_nocarry ; red add work.pr.current,eax ; red mov eax,work.pg.d_nocarry ; green add work.pg.current,eax ; green mov eax,work.pb.d_nocarry ; blue add work.pb.current,eax ; blue dec work.half.count jne scan_loop jmp short done_trapezoid start_carried: adc esi,work.main.d_i ; fb_offset+=delta+CARRY add edx,work.pz.d_carry mov eax,work.pr.d_carry ; red add work.pr.current,eax ; red mov eax,work.pg.d_carry ; green add work.pg.current,eax ; green mov eax,work.pb.d_carry ; blue add work.pb.current,eax ; blue dec work.half.count jne scan_loop done_trapezoid: endm ; RawTriangle_PIZ2I_RGB_555 ; ; Render a triangle into frame buffer ; ; Linear interpolated colour index ; Linear interpolated Z value ; Integer vertices ; Perfect point sampling ; ; esi = vertex 0 pointer ; edi = vertex 1 pointer ; ebp = vertex 2 pointer ; RawTriangle_PIZ2I_RGB_555 proc SETUP_PI jl reversed mov g_divisor,eax PARAM_PI_DIRN comp[C_SZ*4],work.pz,f,1 PARAM_PI_DIRN comp[C_R*4],work.pr,f PARAM_PI_DIRN comp[C_G*4],work.pg,f PARAM_PI_DIRN comp[C_B*4],work.pb,f ; Load up registers for first time around inner loop ; mov esi,work.main.i mov edx,work.pz.current mov ebp,work.pz.grad_x TRAPEZOID_PIZ2I_RGB_555 top,f TRAPEZOID_PIZ2I_RGB_555 bot,f quit: ret ; Scan backwards ; reversed: neg eax mov g_divisor,eax PARAM_PI_DIRN comp[C_SZ*4],work.pz,b,1 PARAM_PI_DIRN comp[C_R*4],work.pr,b PARAM_PI_DIRN comp[C_G*4],work.pg,b PARAM_PI_DIRN comp[C_B*4],work.pb,b ; Load up registers for first time around inner loop ; mov esi,work.main.i mov edx,work.pz.current mov ebp,work.pz.grad_x TRAPEZOID_PIZ2I_RGB_555 top,b TRAPEZOID_PIZ2I_RGB_555 bot,b ret SHOW_CODESIZE ,<%($-_setup_start)> RawTriangle_PIZ2I_RGB_555 endp endif if PARTS and PART_15Z4 ; void TriangleRenderPIZ4_RGB_555(struct br_vertex *pvertex_0, ; struct br_vertex *pvertex_1, ; struct br_vertex *pvertex_2); ; ; C stub directly to triangle renderer ; TriangleRenderPIZ4_RGB_555 proc uses eax ebx ecx edx esi edi, pblock : ptr dword, pvertex_0 : ptr word, pvertex_1 : ptr word, pvertex_2 : ptr word ; Get pointers to vertex structures and colour ; ; eax = colour ; esi = vertex 0 ; edi = vertex 1 ; ebp = vertex 2 ; push ebp SETUP_SEGS mov esi,pvertex_0 mov edi,pvertex_1 mov ebp,pvertex_2 call RawTriangle_PIZ4_RGB_555 RESTORE_SEGS pop ebp ret TriangleRenderPIZ4_RGB_555 endp ; Trapezoid loop for flat shaded z (32 bit) buffered faces ; ; Arguments control: ; whether loop uses 'top' or 'bottom' variables ; which direction scanline are rendered from the long edge ; TRAPEZOID_PIZ4_RGB_555 macro half,dirn local scan_loop,pixel_loop,pixel_behind,no_pixels local start_carried,done_trapezoid cmp work.half.count,0 je done_trapezoid mov ecx,work.half.i ; Prepare for next iteration of loop ; scan_loop: push esi push edx push ecx mov edi,work.depth.base mov ebx,work.colour.base lea edi,[edi+esi*4] ; z buffer lea esi,[esi*2] ; colour buffer lea ecx,[ecx*2] ; Render same colour pixels along scanline (forwards or backwards) ; ; bl: colour ; ecx: address of end of scanline ; edx: z (16.16) ; ebp: z delta (16.16) ; esi: frame buffer ptr ; edi: z buffer ptr ; CMP_&dirn esi,ecx jae short no_pixels pixel_loop: ifidni , sub edx,ebp ; z -= d_z_z sub edi,4 ; z_ptr-- sub esi,2 ; ptr-- endif cmp edx, DSEG [edi] ; if (z > *zptr) jae short pixel_behind mov DSEG [edi],edx ; *zptr = z xor ax,ax mov al,byte ptr temp_r+2 shl ax,5 or al,byte ptr temp_g+2 shl ax,5 or al,byte ptr temp_b+2 mov CSEG [esi+ebx],ax ; xrgb 1 5 5 5 pixel_behind: ifidni , add edx,ebp ; z += d_z_z add edi,4 ; z_ptr++ add esi,2 ; ptr++ endif CMP_&dirn esi,ecx jb short pixel_loop no_pixels: ; Updates for next scanline: ; pop ecx pop edx pop esi mov edi,work.half.d_f mov eax,work.main.d_f add work.half.f,edi ; x_end += work.main.grad_end (fraction) adc ecx,work.half.d_i ; endptr += integer(dx_end)+CARRY add work.main.f,eax ; x+= work.main.grad (fraction) jc start_carried add esi,work.main.d_i ; fb_offset+=delta+CARRY add edx,work.pz.d_nocarry dec work.half.count jne scan_loop jmp short done_trapezoid start_carried: adc esi,work.main.d_i ; fb_offset+=delta+CARRY add edx,work.pz.d_carry dec work.half.count jne scan_loop done_trapezoid: endm ; Triangle_PIZ4_RGB_555 ; ; Render a triangle into frame buffer ; ; Flat colour ; Z buffer ; Integer vertices ; Perfect point sampling ; ; esi = vertex 0 pointer ; edi = vertex 1 pointer ; ebp = vertex 2 pointer ; RawTriangle_PIZ4_RGB_555 proc SETUP_PI jl reversed mov g_divisor,eax ; Scan forwards ; PARAM_PI_DIRN comp[C_SZ*4],work.pz,f,1 ; Load up registers for first time around inner loop ; mov esi,work.main.i mov edx,work.pz.current mov ebp,work.pz.grad_x mov ax,word ptr work.pr.current+2 shr ax,3 mov word ptr work.pr.current+2,ax mov ax,word ptr work.pg.current+2 shr ax,3 mov word ptr work.pg.current+2,ax mov ax,word ptr work.pb.current+2 shr ax,3 mov word ptr work.pb.current+2,ax mov eax,work.pr.current mov temp_r,eax mov eax,work.pg.current mov temp_g,eax mov eax,work.pb.current mov temp_b,eax TRAPEZOID_PIZ4_RGB_555 top,f TRAPEZOID_PIZ4_RGB_555 bot,f quit: ret ; Scan backwards ; reversed: neg eax mov g_divisor,eax PARAM_PI_DIRN comp[C_SZ*4],work.pz,b,1 ; Load up registers for first time around inner loop ; mov esi,work.main.i mov edx,work.pz.current mov ebp,work.pz.grad_x mov ax,word ptr work.pr.current+2 shr ax,3 mov word ptr work.pr.current+2,ax mov ax,word ptr work.pg.current+2 shr ax,3 mov word ptr work.pg.current+2,ax mov ax,word ptr work.pb.current+2 shr ax,3 mov word ptr work.pb.current+2,ax mov eax,work.pr.current mov temp_r,eax mov eax,work.pg.current mov temp_g,eax mov eax,work.pb.current mov temp_b,eax TRAPEZOID_PIZ4_RGB_555 top,b TRAPEZOID_PIZ4_RGB_555 bot,b ret SHOW_CODESIZE ,<%($-_setup_start)> RawTriangle_PIZ4_RGB_555 endp endif if PARTS and PART_15Z4 ; void TriangleRenderPIZ4I_RGB_555(struct br_vertex *pvertex_0, ; struct br_vertex *pvertex_1, ; struct br_vertex *pvertex_2); ; ; C stub directly to triangle renderer ; TriangleRenderPIZ4I_RGB_555 proc uses eax ebx ecx edx esi edi, pblock : ptr dword, pvertex_0 : ptr word, pvertex_1 : ptr word, pvertex_2 : ptr word ; Get pointers to vertex structures and colour ; ; eax = colour ; esi = vertex 0 ; edi = vertex 1 ; ebp = vertex 2 ; push ebp SETUP_SEGS mov esi,pvertex_0 mov edi,pvertex_1 mov ebp,pvertex_2 call RawTriangle_PIZ4I_RGB_555 RESTORE_SEGS pop ebp ret TriangleRenderPIZ4I_RGB_555 endp ; Trapezoid loop for gouraud shaded z buffered faces ; ; Arguments control: ; whether loop uses 'top' or 'bottom' variables ; which direction scanline are rendered from the long edge ; TRAPEZOID_PIZ4I_RGB_555 macro half,dirn local scan_loop,pixel_loop,pixel_behind,no_pixels local start_carried,done_trapezoid cmp work.half.count,0 je done_trapezoid mov ecx,work.half.i ; Prepare for next iteration of loop ; scan_loop: push esi push edx push ecx mov eax,work.pr.current mov temp_r,eax mov eax,work.pg.current mov temp_g,eax mov eax,work.pb.current mov temp_b,eax mov edi,work.depth.base mov ebx,work.colour.base lea edi,[edi+esi*4] ; z buffer lea esi,[esi*2] ; colour buffer lea ecx,[ecx*2] ; Render same colour pixels along scanline (forwards or backwards) ; ; bl: colour ; ecx: address of end of scanline ; edx: z (16.16) ; ebp: z delta (16.16) ; esi: frame buffer ptr ; edi: z buffer ptr ; CMP_&dirn esi,ecx jae short no_pixels pixel_loop: ifidni , sub edx,ebp ; z -= d_z_z mov eax,work.pr.grad_x sub temp_r,eax mov eax,work.pg.grad_x sub temp_g,eax mov eax,work.pb.grad_x sub temp_b,eax sub edi,4 ; z_ptr-- sub esi,2 ; ptr-- endif cmp edx, DSEG [edi] ; if (z > *zptr) jae short pixel_behind mov DSEG [edi],edx ; *zptr = z push ecx xor ax,ax xor cx,cx mov cl,byte ptr temp_r+2 shr cl,3 or al,cl shl ax,5 mov cl,byte ptr temp_g+2 shr cl,3 or al,cl shl ax,5 mov cl,byte ptr temp_b+2 shr cl,3 or al,cl mov CSEG [esi+ebx],ax ; xrgb 1 5 5 5 pop ecx pixel_behind: ifidni , add edx,ebp ; z += d_z_z mov eax,work.pr.grad_x add temp_r,eax mov eax,work.pg.grad_x add temp_g,eax mov eax,work.pb.grad_x add temp_b,eax add edi,4 ; z_ptr++ add esi,2 ; ptr++ endif CMP_&dirn esi,ecx jb short pixel_loop no_pixels: ; Updates for next scanline: ; pop ecx pop edx pop esi mov edi,work.half.d_f mov eax,work.main.d_f add work.half.f,edi ; x_end += work.main.grad_end (fraction) adc ecx,work.half.d_i ; endptr += integer(dx_end)+CARRY add work.main.f,eax ; x+= work.main.grad (fraction) jc start_carried add esi,work.main.d_i ; fb_offset+=delta+CARRY add edx,work.pz.d_nocarry ; z mov eax,work.pr.d_nocarry ; red add work.pr.current,eax ; red mov eax,work.pg.d_nocarry ; green add work.pg.current,eax ; green mov eax,work.pb.d_nocarry ; blue add work.pb.current,eax ; blue dec work.half.count jne scan_loop jmp short done_trapezoid start_carried: adc esi,work.main.d_i ; fb_offset+=delta+CARRY add edx,work.pz.d_carry mov eax,work.pr.d_carry ; red add work.pr.current,eax ; red mov eax,work.pg.d_carry ; green add work.pg.current,eax ; green mov eax,work.pb.d_carry ; blue add work.pb.current,eax ; blue dec work.half.count jne scan_loop done_trapezoid: endm ; RawTriangle_PIZ4I_RGB_555 ; ; Render a triangle into frame buffer ; ; Linear interpolated colour index ; Linear interpolated Z value ; Integer vertices ; Perfect point sampling ; ; esi = vertex 0 pointer ; edi = vertex 1 pointer ; ebp = vertex 2 pointer ; RawTriangle_PIZ4I_RGB_555 proc SETUP_PI jl reversed mov g_divisor,eax PARAM_PI_DIRN comp[C_SZ*4],work.pz,f,1 PARAM_PI_DIRN comp[C_R*4],work.pr,f PARAM_PI_DIRN comp[C_G*4],work.pg,f PARAM_PI_DIRN comp[C_B*4],work.pb,f mov ax,word ptr work.pr.current+2 shr ax,3 mov word ptr work.pr.current+2,ax mov ax,word ptr work.pg.current+2 shr ax,3 mov word ptr work.pg.current+2,ax mov ax,word ptr work.pb.current+2 shr ax,3 mov word ptr work.pb.current+2,ax ; Load up registers for first time around inner loop ; mov esi,work.main.i mov edx,work.pz.current mov ebp,work.pz.grad_x TRAPEZOID_PIZ4I_RGB_555 top,f TRAPEZOID_PIZ4I_RGB_555 bot,f quit: ret ; Scan backwards ; reversed: neg eax mov g_divisor,eax PARAM_PI_DIRN comp[C_SZ*4],work.pz,b,1 PARAM_PI_DIRN comp[C_R*4],work.pr,b PARAM_PI_DIRN comp[C_G*4],work.pg,b PARAM_PI_DIRN comp[C_B*4],work.pb,b mov ax,word ptr work.pr.current+2 shr ax,3 mov word ptr work.pr.current+2,ax mov ax,word ptr work.pg.current+2 shr ax,3 mov word ptr work.pg.current+2,ax mov ax,word ptr work.pb.current+2 shr ax,3 mov word ptr work.pb.current+2,ax ; Load up registers for first time around inner loop ; mov esi,work.main.i mov edx,work.pz.current mov ebp,work.pz.grad_x TRAPEZOID_PIZ4I_RGB_555 top,b TRAPEZOID_PIZ4I_RGB_555 bot,b ret SHOW_CODESIZE ,<%($-_setup_start)> RawTriangle_PIZ4I_RGB_555 endp endif end