ResolveHellAssetPath PROC uses ebx esi edi, inPath:DWORD, outPathBuf:DWORD cmp tournamentMode, 1 jne resolve_orig mov esi, inPath test esi, esi jz resolve_orig xor ecx, ecx xor edx, edx find_dot_loop: mov al, byte ptr [esi+edx] test al, al jz check_dot cmp al, '.' jne next_char mov ecx, edx next_char: inc edx jmp find_dot_loop check_dot: test ecx, ecx jz resolve_orig mov edi, outPathBuf xor edx, edx copy_base: cmp edx, ecx jae append_suffix mov al, byte ptr [esi+edx] mov byte ptr [edi], al inc edi inc edx jmp copy_base append_suffix: mov byte ptr [edi], '-' mov byte ptr [edi+1], 'h' mov byte ptr [edi+2], 'e' mov byte ptr [edi+3], 'l' mov byte ptr [edi+4], 'l' add edi, 5 copy_ext: mov al, byte ptr [esi+ecx] mov byte ptr [edi], al inc edi inc ecx test al, al jnz copy_ext invoke GetFileAttributesA, outPathBuf cmp eax, 0FFFFFFFFh je resolve_orig mov eax, outPathBuf ret resolve_orig: mov eax, inPath ret ResolveHellAssetPath ENDP LoadAnimPack3D PROC uses ebx esi edi pack:DWORD,path:DWORD local io:DWORD,heap:DWORD,allocation:DWORD local resolvedPath[260]:BYTE mov esi, pack cmp [esi].AnimPack3D.pixels, 0 jne anim_load_success invoke ResolveHellAssetPath, path, ADDR resolvedPath invoke CreateFileA, eax, 80000000h, 1, 0, 3, 80h, 0 cmp eax, -1 je anim_load_failure mov ebx, eax invoke ReadFile, ebx, esi, 20, ADDR io, 0 test eax, eax jz anim_close_failure cmp io, 20 jne anim_close_failure cmp [esi].AnimPack3D.magic, 314D4E41h jne anim_close_failure mov eax, [esi].AnimPack3D.imageWidth test eax, eax jz anim_close_failure cmp eax, 640 ja anim_close_failure mov ecx, [esi].AnimPack3D.height test ecx, ecx jz anim_close_failure cmp ecx, 1024 ja anim_close_failure imul eax, ecx shl eax, 2 mov ecx, [esi].AnimPack3D.frames test ecx, ecx jz anim_close_failure cmp esi,OFFSET characterCast3D jne anim_regular_pack ; Only the fixed, shared cast may exceed the ordinary 64-frame/32-MiB cap. cmp [esi].AnimPack3D.imageWidth,192 jne anim_close_failure cmp [esi].AnimPack3D.height,224 jne anim_close_failure cmp ecx,CAST_COUNT*CAST_STRIDE jne anim_close_failure mov eax,192*224*CAST_COUNT*CAST_STRIDE*4 jmp anim_check_payload anim_regular_pack: cmp ecx, 64 ja anim_close_failure imul eax, ecx cmp eax, 32*1024*1024 ja anim_close_failure anim_check_payload: cmp eax, [esi].AnimPack3D.bytes jne anim_close_failure invoke GetFileSize, ebx, 0 mov ecx, [esi].AnimPack3D.bytes add ecx, 20 cmp eax, ecx jne anim_close_failure invoke GetProcessHeap mov heap, eax invoke HeapAlloc, eax, 0, [esi].AnimPack3D.bytes test eax, eax jz anim_close_failure mov allocation, eax invoke ReadFile, ebx, allocation, [esi].AnimPack3D.bytes, ADDR io, 0 test eax, eax jz anim_free_failure mov eax, io cmp eax, [esi].AnimPack3D.bytes jne anim_free_failure invoke CloseHandle, ebx mov eax, allocation mov [esi].AnimPack3D.pixels, eax anim_load_success: mov eax, 1 ret anim_free_failure: invoke HeapFree, heap, 0, allocation anim_close_failure: invoke CloseHandle, ebx anim_load_failure: ; A parsed header is not a loaded asset. Leave no misleading frame count. mov edi, esi xor eax, eax mov ecx, SIZEOF AnimPack3D/4 rep stosd xor eax, eax ret LoadAnimPack3D ENDP FreeAnimPack3D PROC uses esi pack:DWORD mov esi, pack cmp [esi].AnimPack3D.pixels, 0 je @F invoke GetProcessHeap invoke HeapFree, eax, 0, [esi].AnimPack3D.pixels mov [esi].AnimPack3D.pixels, 0 @@: ret FreeAnimPack3D ENDP ; Physical framebuffer coordinates. Clip before sampling; fractional alpha is preserved. DrawAnimSprite3D PROC uses ebx esi edi pack:DWORD,frame:DWORD,x:DWORD,y:DWORD,w:DWORD,h:DWORD local columnPx:DWORD,rowPx:DWORD,sx:DWORD,sy:DWORD,xStep:DWORD,yStep:DWORD local xFirst:DWORD,xLast:DWORD,yLast:DWORD,sourceRow:DWORD,pixel:DWORD local alpha:DWORD,inverse:DWORD,result:DWORD mov esi, pack cmp [esi].AnimPack3D.pixels, 0 je anim_draw_done cmp w, 0 jle anim_draw_done cmp h, 0 jle anim_draw_done cmp w, 4096 ja anim_draw_done cmp h, 4096 ja anim_draw_done mov eax, frame cmp eax, [esi].AnimPack3D.frames jae anim_draw_done imul eax, [esi].AnimPack3D.imageWidth imul eax, [esi].AnimPack3D.height shl eax, 2 add eax, [esi].AnimPack3D.pixels mov sourceRow, eax mov eax, [esi].AnimPack3D.imageWidth shl eax, 16 xor edx, edx div w mov xStep, eax mov eax, [esi].AnimPack3D.height shl eax, 16 xor edx, edx div h mov yStep, eax mov eax, x add eax, w cmp eax, 640 jle @F mov eax, 640 @@: mov xLast, eax mov eax, x test eax, eax jns @F xor eax, eax @@: mov xFirst, eax cmp eax, xLast jge anim_draw_done mov eax, y add eax, h cmp eax, 480 jle @F mov eax, 480 @@: mov yLast, eax mov eax, y test eax, eax jns @F xor eax, eax @@: mov rowPx, eax sub eax, y imul eax, yStep mov sy, eax anim_draw_row: mov eax, rowPx cmp eax, yLast jge anim_draw_done imul eax, 640*4 add eax, OFFSET screenBuffer mov ecx, xFirst lea edi, [eax+ecx*4] mov eax, sy shr eax, 16 imul eax, [esi].AnimPack3D.imageWidth shl eax, 2 add eax, sourceRow mov ebx, eax mov columnPx, ecx sub ecx, x imul ecx, xStep mov sx, ecx anim_draw_column: mov eax, sx shr eax, 16 mov eax, [ebx+eax*4] mov pixel, eax shr eax, 24 test eax, eax jz anim_draw_next cmp animOpacity3D, 255 je @F imul eax, animOpacity3D mov edx, eax shr edx, 8 add eax, edx inc eax shr eax, 8 test eax, eax jz anim_draw_next @@: cmp eax, 250 jb anim_blend mov eax, pixel and eax, 00FFFFFFh mov [edi], eax jmp anim_draw_next anim_blend: mov alpha, eax mov ecx, 255 sub ecx, eax mov inverse, ecx mov result, 0 push ebx xor ebx, ebx anim_blend_channel: mov ecx, ebx mov eax, pixel shr eax, cl and eax, 255 imul eax, alpha mov edx, [edi] shr edx, cl and edx, 255 imul edx, inverse add eax, edx ; Exact rounded /255 for the bounded 0..65025 channel sum. add eax, 128 mov edx, eax shr edx, 8 add eax, edx shr eax, 8 mov ecx, ebx shl eax, cl or result, eax add ebx, 8 cmp ebx, 24 jb anim_blend_channel pop ebx mov eax, result mov [edi], eax anim_draw_next: add edi, 4 mov eax, xStep add sx, eax inc columnPx mov eax, columnPx cmp eax, xLast jl anim_draw_column mov eax, yStep add sy, eax inc rowPx jmp anim_draw_row anim_draw_done: ret DrawAnimSprite3D ENDP LoadArrivalAssets3D PROC invoke LoadAnimPack3D, OFFSET guardPack3D, OFFSET guardPath3D invoke LoadAnimPack3D, OFFSET merchantPack3D, OFFSET merchantPath3D invoke LoadAnimPack3D, OFFSET propsPack3D, OFFSET propsPath3D invoke LoadAnimPack3D, OFFSET backsPack3D, OFFSET backsPath3D invoke LoadAnimPack3D, OFFSET handsPack3D, OFFSET handsPath3D invoke LoadAnimPack3D, OFFSET activeTablePack3D, OFFSET activeTablePath3D call InstallHallProps3D call LoadHallAssets3D ret LoadArrivalAssets3D ENDP InstallHallProps3D PROC uses ebx esi edi ; Keep the user's existing interior materials; the exterior has separate slots. hall_install_props: cmp propsPack3D.pixels, 0 je @F cmp propsPack3D.imageWidth, 128 jne @F cmp propsPack3D.height, 128 jne @F cmp propsPack3D.frames, 9 jne @F mov esi, propsPack3D.pixels mov edi, OFFSET texturesBuffer+(48*128*128*4) mov ecx, 9*128*128 props_copy_pixel: lodsd cmp eax, 80000000h jae props_copy_opaque mov eax, CHROMA_KEY jmp props_copy_store props_copy_opaque: and eax, 00FFFFFFh props_copy_store: stosd loop props_copy_pixel mov casinoSprites[3*SIZEOF SpriteObject].baseTexId, 48 mov casinoSprites[4*SIZEOF SpriteObject].baseTexId, 50 mov casinoSprites[5*SIZEOF SpriteObject].baseTexId, 49 mov casinoSprites[9*SIZEOF SpriteObject].baseTexId, 51 mov casinoSprites[12*SIZEOF SpriteObject].baseTexId, 54 mov casinoSprites[14*SIZEOF SpriteObject].baseTexId, 52 mov casinoSprites[17*SIZEOF SpriteObject].baseTexId, 55 mov casinoSprites[18*SIZEOF SpriteObject].baseTexId, 53 mov casinoSprites[19*SIZEOF SpriteObject].baseTexId, 55 @@: ret InstallHallProps3D ENDP FreeArrivalAssets3D PROC call FreeScratchArt3D call FreeNativeDiceArt3D call FreeHallAssets3D invoke FreeAnimPack3D, OFFSET streetPack3D invoke FreeAnimPack3D, OFFSET guardPack3D invoke FreeAnimPack3D, OFFSET merchantPack3D invoke FreeAnimPack3D, OFFSET propsPack3D invoke FreeAnimPack3D, OFFSET backsPack3D invoke FreeAnimPack3D, OFFSET handsPack3D invoke FreeAnimPack3D, OFFSET materialsPack3D invoke FreeAnimPack3D, OFFSET activeTablePack3D invoke FreeAnimPack3D, OFFSET cityTilesPack3D invoke FreeAnimPack3D, OFFSET cityHandsPack3D invoke FreeAnimPack3D, OFFSET cityPropsPack3D invoke FreeAnimPack3D, OFFSET citySmokePack3D invoke FreeAnimPack3D, OFFSET cityCarsPack3D invoke FreeAnimPack3D, OFFSET cityBinPack3D invoke FreeAnimPack3D, OFFSET cityCloudPack3D invoke FreeAnimPack3D, OFFSET cityWakePack3D invoke FreeAnimPack3D, OFFSET citySleevePack3D invoke FreeAnimPack3D, OFFSET cityDecorPack3D invoke FreeAnimPack3D, OFFSET cityLighterPack3D invoke FreeAnimPack3D, OFFSET cityKneesPack3D ret FreeArrivalAssets3D ENDP QueueTableHand3D PROC x:DWORD,y:DWORD,timeMs:DWORD,kind:DWORD mov eax, timeMs cmp eax, TABLE_FLIGHT_MS jae @F mov tableHandTime3D, eax mov eax, x mov tableHandX3D, eax mov eax, y mov tableHandY3D, eax mov eax, kind mov tableHandKind3D, eax mov tableHandQueued3D, 1 @@: ret QueueTableHand3D ENDP DrawQueuedTableHand3D PROC uses ebx esi edi local drawX:DWORD,drawY:DWORD cmp tableHandQueued3D, 0 je table_hand_done cmp handsPack3D.pixels, 0 je table_hand_done cmp handsPack3D.imageWidth, 144 jne table_hand_done cmp handsPack3D.height, 192 jne table_hand_done cmp handsPack3D.frames, 8 jne table_hand_done mov eax, tableHandTime3D mov ebx, 0 cmp eax, 60 jb table_hand_frame inc ebx cmp eax, 120 jb table_hand_frame inc ebx cmp eax, 260 jb table_hand_frame inc ebx cmp eax, 300 jb table_hand_frame inc ebx cmp eax, 340 jb table_hand_frame inc ebx table_hand_frame: cmp tableHandKind3D, 1 jne @F mov ebx, 6 cmp tableHandTime3D, 250 jb @F inc ebx @@: mov eax, tableHandX3D shl eax, 1 add eax, 24 sub eax, tableHandAnchorX3D[ebx*4] mov drawX, eax mov eax, tableHandY3D shl eax, 1 add eax, 12 sub eax, tableHandAnchorY3D[ebx*4] mov drawY, eax cmp ebx, 4 jb table_hand_draw cmp ebx, 6 jae table_hand_draw mov eax, tableHandTime3D sub eax, 300 shr eax, 1 sub drawY, eax table_hand_draw: ; Composite above the actual cards, preserving the header and action buttons. lea esi, screenBuffer lea edi, tableProtectedRows3D mov ecx, 640*88 rep movsd lea esi, screenBuffer[640*444*4] mov ecx, 640*36 rep movsd cmp ebx, 6 jae table_hand_player invoke DrawDealerArm3D, ebx, drawX, drawY jmp table_hand_restore table_hand_player: invoke DrawAnimSprite3D, OFFSET handsPack3D, ebx, drawX, drawY, 144, 192 table_hand_restore: lea esi, tableProtectedRows3D lea edi, screenBuffer mov ecx, 640*88 rep movsd lea edi, screenBuffer[640*444*4] mov ecx, 640*36 rep movsd table_hand_done: ret DrawQueuedTableHand3D ENDP ; A non-owning view keeps the hand undistorted while the sleeve reaches from the shoulder. DrawDealerArm3D PROC uses ebx esi edi frame:DWORD,x:DWORD,y:DWORD local framePtr:DWORD,endY:DWORD,row:DWORD,span:DWORD,part:AnimPack3D mov part.imageWidth, 144 mov part.height, 124 mov part.frames, 1 mov eax, frame imul eax, 144*192*4 add eax, handsPack3D.pixels mov framePtr, eax add eax, 68*144*4 mov part.pixels, eax mov eax, y add eax, 68 mov endY, eax invoke DrawAnimSprite3D, ADDR part, 0, x, endY, 144, 124 cmp endY, 64 jle dealer_arm_done mov eax, endY sub eax, 64 mov span, eax mov part.height, 1 mov row, 64 dealer_arm_row: mov eax, row sub eax, 64 imul eax, 68 xor edx, edx div span imul eax, 144*4 add eax, framePtr mov part.pixels, eax mov eax, x sub eax, 310 mov ecx, row sub ecx, 64 imul eax, ecx cdq idiv span add eax, 310 invoke DrawAnimSprite3D, ADDR part, 0, eax, row, 144, 1 inc row mov eax, row cmp eax, endY jl dealer_arm_row dealer_arm_done: ret DrawDealerArm3D ENDP