.data? cityRayX3D dd SCREEN_W dup(?) cityRayY3D dd SCREEN_W dup(?) .code ; Exterior-only materials do not consume or overwrite the hall's texture slots. ResolveCitySurface3D PROC material:DWORD mov eax,material cmp eax,HF_PAINTING_MATERIAL jne hf_not_painting mov eax,hfPaintingArt.pixels mov ecx,512 mov edx,256 ret hf_not_painting: cmp eax,HF_WALL jb hf_surface_other cmp eax,HF_LAVA+3 ja hf_surface_other shl eax,16 add eax,OFFSET texturesBuffer mov ecx,128 mov edx,128 ret hf_surface_other: cmp hallLevel3D,HALL_BACKROOMS jne br_surface_other_world cmp eax,BR_WALL jb @F cmp eax,BR_EXIT ja @F shl eax,16 add eax,OFFSET texturesBuffer mov ecx,128 mov edx,128 ret @@: br_surface_other_world: cmp eax,BW_MATERIAL jb @F cmp eax,BW_LAST_MATERIAL ja @F invoke ResolveBowlingSurface3D,material ret @@: cmp eax,MATERIAL_JACKBOX_FRONT jb @F cmp eax,MATERIAL_JACKBOX_BACK ja @F invoke ResolveJackboxSurface3D,material ret @@: cmp eax,ROOF_DECK jb @F cmp eax,ROOF_LAST_MATERIAL ja @F invoke ResolveRoofSurface3D,material ret @@: cmp eax,160 jne @F call ResolveDartsSurface3D ret @@: cmp eax,132 jb @F cmp eax,159 ja @F invoke ResolveFortuneMaterial3D,material ret @@: cmp eax,122 jb @F cmp eax,131 ja @F invoke ResolveUpperMaterial3D,material ret @@: cmp eax,118 jb @F cmp eax,122 jae @F invoke ResolveTerminalSurface3D,material ret @@: cmp eax,115 jb @F cmp eax,118 jae @F invoke ResolveDressingSurface3D,material ret @@: cmp eax,111 jb city_surface_shared cmp eax,115 jae city_surface_shared cmp cityDecorPack3D.pixels,0 je city_surface_missing sub eax,111 shl eax,16 add eax,cityDecorPack3D.pixels mov ecx,128 mov edx,128 ret city_surface_missing: xor eax,eax ret city_surface_shared: invoke ResolveWorldSurface3D,material ret ResolveCitySurface3D ENDP PrepareCityDepth3D PROC uses ebx esi edi lea edi, cityDepthBuffer3D mov ebx, SCREEN_H city_depth_row: lea esi, zBuffer xor ecx, ecx city_depth_column: mov eax, [esi+ecx*4] cmp outdoorRender3D, 0 je city_depth_store ; Preserve per-pixel district depth when foreground walls have no hit. cmp eax, [edi] jle city_depth_store mov eax, [edi] city_depth_store: stosd inc ecx cmp ecx, SCREEN_W jb city_depth_column dec ebx jnz city_depth_row call PrepareCityRays3D ret PrepareCityDepth3D ENDP PrepareCityRays3D PROC uses ebx esi xor ebx, ebx city_prepare_ray: mov eax, ebx imul eax, 2*FP_1 xor edx, edx mov ecx, SCREEN_W div ecx sub eax, FP_1 mov esi, eax imul playerPlaneX shrd eax, edx, 16 add eax, playerDirX mov cityRayX3D[ebx*4], eax mov eax, esi imul playerPlaneY shrd eax, edx, 16 add eax, playerDirY mov cityRayY3D[ebx*4], eax inc ebx cmp ebx, SCREEN_W jb city_prepare_ray ret PrepareCityRays3D ENDP CityRayPlane3D PROC coordinate:DWORD,origin:DWORD,direction:DWORD local farDelta:DWORD mov ecx, direction mov eax, ecx test eax, eax jns @F neg eax @@: cmp eax, 256 jb city_ray_parallel ; A long city ray can overflow IDIV before its depth is clipped. Reject ; intersections beyond the exterior far plane before forming the dividend. shl eax,10 mov farDelta,eax mov eax,coordinate sub eax,origin cdq xor eax,edx sub eax,edx cmp eax,farDelta jae city_ray_parallel mov eax, coordinate sub eax, origin cdq shld edx, eax, 16 shl eax, 16 idiv ecx ret city_ray_parallel: mov eax, 7FFFFFFFh ret CityRayPlane3D ENDP ; Vertical surfaces intersect actual rays, rather than turning to face the camera. DrawCityVertical3D PROC uses ebx esi edi axis:DWORD,coordinate:DWORD,loBound:DWORD,hiBound:DWORD,zLow:DWORD,zHigh:DWORD,material:DWORD local depth:DWORD,top:DWORD,bottom:DWORD,span:DWORD,column:DWORD local sourceX:DWORD,stepY:DWORD,sourceY:DWORD,destination:DWORD,row:DWORD,texture:DWORD local textureW:DWORD,textureH:DWORD,faceLight:DWORD local endColumn:DWORD,firstX:DWORD,firstDepth:DWORD,clipX:DWORD,clipY:DWORD invoke ResolveCitySurface3D,material test eax, eax jz city_vertical_done mov texture, eax mov textureW, ecx mov textureH, edx mov faceLight,230 cmp roofCityPass3D,0 je city_vertical_setup cmp axis,0 jne city_vertical_light_y mov eax,playerX cmp eax,coordinate jl city_vertical_setup mov faceLight,142 jmp city_vertical_setup city_vertical_light_y: mov faceLight,165 mov eax,playerY cmp eax,coordinate jl city_vertical_setup mov faceLight,218 city_vertical_setup: mov column, 0 mov endColumn,SCREEN_W cmp hallLevel3D,HALL_ROOF je city_vertical_clip cmp hallLevel3D,HALL_BOWLING jne city_vertical_column city_vertical_clip: mov eax,coordinate mov edx,loBound cmp axis,0 je @F xchg eax,edx @@: invoke ProjectCityPoint3D,eax,edx mov firstX,eax mov firstDepth,edx mov eax,coordinate mov edx,hiBound cmp axis,0 je @F xchg eax,edx @@: invoke ProjectCityPoint3D,eax,edx cmp edx,4096 jg city_vertical_clip_second cmp firstDepth,4096 jle city_vertical_done jmp city_vertical_column city_vertical_clip_second: cmp firstDepth,4096 jle city_vertical_column mov edx,firstX cmp eax,edx jge @F xchg eax,edx @@: sub edx,2 add eax,3 test edx,edx jns @F xor edx,edx @@: cmp eax,SCREEN_W jle @F mov eax,SCREEN_W @@: cmp edx,eax jge city_vertical_done mov column,edx mov endColumn,eax city_vertical_column: mov ebx, column cmp axis, 0 jne city_vertical_y_plane invoke CityRayPlane3D, coordinate, playerX, cityRayX3D[ebx*4] cmp eax, 4096 jle city_vertical_next_column cmp cityBackdrop3D, 0 jne @F cmp eax, zBuffer[ebx*4] jae city_vertical_next_column @@: mov depth, eax imul cityRayY3D[ebx*4] shrd eax, edx, 16 add eax, playerY jmp city_vertical_along city_vertical_y_plane: invoke CityRayPlane3D, coordinate, playerY, cityRayY3D[ebx*4] cmp eax, 4096 jle city_vertical_next_column cmp cityBackdrop3D, 0 jne @F cmp eax, zBuffer[ebx*4] jae city_vertical_next_column @@: mov depth, eax imul cityRayX3D[ebx*4] shrd eax, edx, 16 add eax, playerX city_vertical_along: cmp eax, loBound jl city_vertical_next_column cmp eax, hiBound jge city_vertical_next_column sub eax, loBound imul eax, textureW cdq mov ecx, hiBound sub ecx, loBound idiv ecx cmp cityBackdrop3D, 0 je @F imul ecx shrd eax, edx, 16 mov edx, textureW dec edx and eax, edx @@: ; Door lettering faces the viewer on either wall face. Other worlds keep UVs. cmp hallLevel3D,HALL_BACKROOMS jne br_door_uv_done cmp material,BR_EXIT jne br_door_uv_done cmp axis,0 jne br_door_uv_y mov edx,playerX cmp edx,coordinate jle br_door_uv_done jmp br_door_uv_flip br_door_uv_y: mov edx,playerY cmp edx,coordinate jge br_door_uv_done br_door_uv_flip: mov edx,textureW dec edx sub edx,eax mov eax,edx br_door_uv_done: mov sourceX, eax mov eax, viewEye3D sub eax, zHigh mov ecx,SCREEN_H imul ecx idiv depth add eax, viewHorizon3D mov top, eax mov eax, viewEye3D sub eax, zLow mov ecx,SCREEN_H imul ecx idiv depth add eax, viewHorizon3D mov bottom, eax sub eax, top jle city_vertical_next_column mov span, eax mov eax, textureH shl eax, 16 xor edx, edx div span cmp cityBackdrop3D, 0 je @F mov ecx, zHigh sub ecx, zLow imul ecx shrd eax, edx, 16 @@: mov stepY, eax mov eax, top test eax, eax jns @F xor eax, eax @@: mov row, eax sub eax, top imul eax, stepY mov sourceY, eax cmp bottom, SCREEN_H jle @F mov bottom, SCREEN_H @@: mov eax, row cmp eax, bottom jge city_vertical_next_column imul eax, SCREEN_W add eax, column shl eax, 2 mov destination, eax city_vertical_pixel: mov edi, destination mov eax, depth cmp portalRendering3D,0 je @F mov ebx,column cmp eax,portalClipDepth3D[ebx*4] jb city_vertical_next_pixel @@: cmp eax, cityDepthBuffer3D[edi] ja city_vertical_next_pixel mov eax, sourceY shr eax, 16 mov edx, textureH dec edx and eax, edx imul eax, textureW add eax, sourceX mov esi, texture mov eax, [esi+eax*4] cmp material, 104 jb @F cmp eax, 80000000h jb city_vertical_next_pixel @@: mov edx, depth mov cityDepthBuffer3D[edi], edx cmp roofCityPass3D,0 jne city_vertical_scene_color and eax, 00FFFFFFh city_vertical_scene_color: cmp cityBackdrop3D, 0 je @F push eax push ecx invoke IsCityEmissive3D, eax, material pop ecx test eax, eax pop eax jnz @F and eax, 00FEFEFEh shr eax, 1 add eax, 00101828h @@: cmp roofCityPass3D,0 je city_vertical_color_ready invoke ShadeRoofCityPixel3D,eax,depth,faceLight,material mov ebx,edi shr ebx,2 mov ecx,roofPixelGlow3D mov roofGlowMask3D[ebx],cl city_vertical_color_ready: mov screenBuffer[edi], eax cmp hallLevel3D,HALL_ROOF jne city_vertical_next_pixel mov ebx,edi shr ebx,2 mov ecx,roofCityPass3D mov roofCityMask3D[ebx],cl city_vertical_next_pixel: mov eax, stepY add sourceY, eax add destination, SCREEN_W*4 inc row mov eax, row cmp eax, bottom jb city_vertical_pixel city_vertical_next_column: inc column mov eax,endColumn cmp column,eax jb city_vertical_column city_vertical_done: ret DrawCityVertical3D ENDP DrawCityHorizontal3D PROC uses ebx esi edi xMin:DWORD,xMax:DWORD,yMin:DWORD,yMax:DWORD,z:DWORD,material:DWORD local left:DWORD,right:DWORD,top:DWORD,bottom:DWORD,corner:DWORD,pointX:DWORD,pointY:DWORD local depth:DWORD,row:DWORD,column:DWORD,stepX:DWORD,stepY:DWORD,scaleX:DWORD,scaleY:DWORD,texture:DWORD local textureW:DWORD,textureH:DWORD,nearClipped:DWORD,visibleCorners:DWORD invoke ResolveCitySurface3D,material test eax, eax jz city_horizontal_done mov texture, eax mov textureW, ecx mov textureH, edx mov nearClipped, 0 mov visibleCorners,0 mov left, SCREEN_W mov right, 0 mov top, SCREEN_H mov bottom, 0 mov corner, 0 city_horizontal_corner: mov eax, xMin test corner, 1 jz @F mov eax, xMax @@: mov ebx, yMin test corner, 2 jz @F mov ebx, yMax @@: invoke ProjectCityPoint3D, eax, ebx cmp edx, 4096 jg city_horizontal_visible_corner mov nearClipped, 1 jmp city_horizontal_next_corner city_horizontal_visible_corner: inc visibleCorners mov esi, edx cmp eax, left jge @F mov left, eax @@: cmp eax, right jle @F mov right, eax @@: mov eax, viewEye3D sub eax, z mov ecx,SCREEN_H imul ecx idiv esi add eax, viewHorizon3D cmp eax, top jge @F mov top, eax @@: cmp eax, bottom jle @F mov bottom, eax @@: city_horizontal_next_corner: inc corner cmp corner, 4 jb city_horizontal_corner cmp hallLevel3D,HALL_ROOF je city_horizontal_check_visible cmp hallLevel3D,HALL_BOWLING jne @F city_horizontal_check_visible: cmp visibleCorners,0 je city_horizontal_done @@: cmp nearClipped, 0 je @F ; Ray bounds/depth below clip the polygon; a behind-camera corner cannot discard it. mov left, 0 mov right, SCREEN_W-1 mov top, 0 mov bottom, SCREEN_H-1 @@: cmp left, 0 jge @F mov left, 0 @@: cmp right, SCREEN_W-1 jle @F mov right, SCREEN_W-1 @@: cmp top, 0 jge @F mov top, 0 @@: cmp bottom, SCREEN_H-1 jle @F mov bottom, SCREEN_H-1 @@: mov eax, left cmp eax, right jge city_horizontal_done mov eax, top cmp eax, bottom jge city_horizontal_done mov row, eax xor eax, eax mov edx, textureW mov ecx, xMax sub ecx, xMin idiv ecx mov scaleX, eax xor eax, eax mov edx, textureH mov ecx, yMax sub ecx, yMin idiv ecx mov scaleY, eax city_horizontal_row: mov ecx, row sub ecx, viewHorizon3D jz city_horizontal_next_row mov eax, viewEye3D sub eax, z mov ebx,SCREEN_H imul ebx idiv ecx cmp eax, 4096 jle city_horizontal_next_row mov depth, eax mov ebx, left imul cityRayX3D[ebx*4] shrd eax, edx, 16 add eax, playerX mov pointX, eax mov eax, depth imul cityRayY3D[ebx*4] shrd eax, edx, 16 add eax, playerY mov pointY, eax mov eax, depth imul playerPlaneX shrd eax, edx, 16 shl eax, 1 cdq mov ecx, SCREEN_W idiv ecx mov stepX, eax mov eax, depth imul playerPlaneY shrd eax, edx, 16 shl eax, 1 cdq idiv ecx mov stepY, eax mov column, ebx mov eax, row imul eax, SCREEN_W*4 lea edi, [eax+ebx*4] city_horizontal_pixel: mov eax, pointX cmp eax, xMin jl city_horizontal_advance cmp eax, xMax jge city_horizontal_advance mov eax, pointY cmp eax, yMin jl city_horizontal_advance cmp eax, yMax jge city_horizontal_advance mov eax, depth cmp portalRendering3D,0 je @F mov ebx,column cmp eax,portalClipDepth3D[ebx*4] jb city_horizontal_advance @@: cmp eax, cityDepthBuffer3D[edi] ja city_horizontal_advance mov eax, pointX sub eax, xMin imul scaleX mov esi, edx mov ecx, textureW dec ecx and esi, ecx mov eax, pointY sub eax, yMin imul scaleY mov ecx, textureH dec ecx and edx, ecx imul edx, textureW add esi, edx mov ebx, texture mov eax, [ebx+esi*4] cmp outdoorRender3D,0 je city_horizontal_alpha cmp material,72 jne city_horizontal_alpha mov ecx,depth shr ecx,14 neg ecx add ecx,256 cmp ecx,55 jge @F mov ecx,55 @@: invoke ShadeCityGround3D,eax,pointX,pointY,ecx city_horizontal_alpha: cmp material, 104 jb @F cmp eax, 80000000h jb city_horizontal_advance @@: mov ecx, depth mov cityDepthBuffer3D[edi], ecx and eax, 00FFFFFFh cmp roofCityPass3D,0 je city_horizontal_color_ready cmp material,ROOF_CITY_ROAD jne @F invoke SampleRoofGroundLight3D,eax,pointX,pointY @@: invoke ShadeRoofCityPixel3D,eax,depth,244,material mov ebx,edi shr ebx,2 mov ecx,roofPixelGlow3D mov roofGlowMask3D[ebx],cl city_horizontal_color_ready: mov screenBuffer[edi], eax cmp hallLevel3D,HALL_ROOF jne city_horizontal_advance mov ebx,edi shr ebx,2 mov ecx,roofCityPass3D mov roofCityMask3D[ebx],cl city_horizontal_advance: mov eax, stepX add pointX, eax mov eax, stepY add pointY, eax add edi, 4 inc column mov eax, column cmp eax, right jbe city_horizontal_pixel city_horizontal_next_row: inc row mov eax, row cmp eax, bottom jbe city_horizontal_row city_horizontal_done: ret DrawCityHorizontal3D ENDP DrawCityBoxSides3D PROC xMin:DWORD,xMax:DWORD,yMin:DWORD,yMax:DWORD,zLow:DWORD,zHigh:DWORD,material:DWORD cmp hallLevel3D,HALL_ROOF jne city_box_all_sides mov eax,playerX cmp eax,xMin jge @F invoke DrawCityVertical3D,0,xMin,yMin,yMax,zLow,zHigh,material @@: mov eax,playerX cmp eax,xMax jle @F invoke DrawCityVertical3D,0,xMax,yMin,yMax,zLow,zHigh,material @@: mov eax,playerY cmp eax,yMin jge @F invoke DrawCityVertical3D,1,yMin,xMin,xMax,zLow,zHigh,material @@: mov eax,playerY cmp eax,yMax jle @F invoke DrawCityVertical3D,1,yMax,xMin,xMax,zLow,zHigh,material @@: ret city_box_all_sides: invoke DrawCityVertical3D, 0, xMin, yMin, yMax, zLow, zHigh, material invoke DrawCityVertical3D, 0, xMax, yMin, yMax, zLow, zHigh, material invoke DrawCityVertical3D, 1, yMin, xMin, xMax, zLow, zHigh, material invoke DrawCityVertical3D, 1, yMax, xMin, xMax, zLow, zHigh, material ret DrawCityBoxSides3D ENDP DrawCityBinBodies3D PROC cmp cityBinPack3D.pixels, 0 je city_bin_bodies_done invoke DrawCityBoxSides3D, FP_1*181/20,FP_1*197/20,FP_1*261/10,FP_1*55/2,FP_1/12,FP_1*2/3,73 invoke DrawCityBoxSides3D, FP_1*163/20,FP_1*44/5,FP_1*132/5,FP_1*139/5,FP_1/12,FP_1*13/20,73 city_bin_bodies_done: ret DrawCityBinBodies3D ENDP RenderCityBins3D PROC uses ebx esi edi local wx:DWORD,wy:DWORD cmp cityBinPack3D.pixels, 0 je city_bins_done ; Ground contact patches and closed, low-profile dumpster lids. invoke DrawCityHorizontal3D, FP_1*179/20,FP_1*199/20,26*FP_1,FP_1*138/5,FP_1/1000,76 invoke DrawCityHorizontal3D, FP_1*161/20,FP_1*89/10,FP_1*263/10,FP_1*279/10,FP_1/1000,76 call DrawCityBinBodies3D invoke DrawCityBoxSides3D, FP_1*163/20-FP_1/40,FP_1*44/5+FP_1/40,FP_1*132/5-FP_1/40,FP_1*139/5+FP_1/40,FP_1*13/20,FP_1*7/10,76 invoke DrawCityHorizontal3D, FP_1*163/20-FP_1/40,FP_1*44/5+FP_1/40,FP_1*132/5-FP_1/40,FP_1*139/5+FP_1/40,FP_1*7/10,74 invoke DrawCityBoxSides3D, FP_1*83/10,FP_1*43/5,FP_1*133/5,FP_1*267/10,FP_1*7/10,FP_1*3/4,76 invoke DrawCityHorizontal3D, FP_1*83/10,FP_1*43/5,FP_1*133/5,FP_1*267/10,FP_1*3/4,74 invoke DrawCityHorizontal3D, FP_1*181/20,FP_1*197/20,FP_1*261/10,FP_1*55/2,FP_1*11/20,75 invoke DrawCityHorizontal3D, FP_1*181/20,FP_1*181/20+FP_1/24,FP_1*261/10,FP_1*55/2,FP_1*2/3,73 invoke DrawCityHorizontal3D, FP_1*197/20-FP_1/24,FP_1*197/20,FP_1*261/10,FP_1*55/2,FP_1*2/3,73 invoke DrawCityHorizontal3D, FP_1*181/20,FP_1*197/20,FP_1*261/10,FP_1*261/10+FP_1/24,FP_1*2/3,73 invoke DrawCityHorizontal3D, FP_1*181/20,FP_1*197/20,FP_1*55/2-FP_1/24,FP_1*55/2,FP_1*2/3,73 invoke DrawCityBoxSides3D, FP_1*181/20-FP_1/40,FP_1*197/20+FP_1/40,FP_1*261/10,FP_1*55/2,FP_1*2/3,FP_1*3/4,76 invoke DrawCityHorizontal3D, FP_1*181/20-FP_1/40,FP_1*197/20+FP_1/40,FP_1*261/10,FP_1*55/2,FP_1*3/4,74 invoke DrawCityBoxSides3D, FP_1*93/10,FP_1*48/5,FP_1*261/10-FP_1/20,FP_1*261/10,FP_1*11/20,FP_1*3/5,76 invoke DrawCityBoxSides3D, FP_1*17/2,FP_1*171/20,FP_1*132/5-FP_1/20,FP_1*132/5,FP_1*11/20,FP_1*3/5,76 xor esi, esi city_bin_wheel: mov wx, FP_1*183/20 mov wy, FP_1*263/10 test esi, 1 jz @F mov wx, FP_1*193/20 @@: test esi, 2 jz @F mov wy, FP_1*273/10 @@: mov ebx, wx add ebx, FP_1/8 mov edi, wy add edi, FP_1/8 invoke DrawCityBoxSides3D, wx,ebx,wy,edi,0,FP_1/10,76 add wx, -(FP_1) mov eax, wx add eax, FP_1/8 invoke DrawCityBoxSides3D, wx,eax,wy,edi,0,FP_1/10,76 inc esi cmp esi, 4 jb city_bin_wheel invoke ProjectCityPoint3D, FP_1*189/20,FP_1*134/5 mov cityMouthX3D, eax mov esi, edx cmp esi, 4096 jle city_bins_done mov eax, viewEye3D sub eax, FP_1*11/20 imul eax, SCREEN_H cdq idiv esi add eax, viewHorizon3D mov cityMouthY3D, eax city_bins_done: ret RenderCityBins3D ENDP