; Events are processed on one thread. No secondary window or console is created. WindowEvents3D PROC uses ebx esi edi hwnd:DWORD, uMsg:DWORD, wp:DWORD, lp:DWORD cmp uMsg, 100h je event_key_down cmp uMsg, 104h jne @F cmp wp, 0Dh je event_fullscreen @@: cmp uMsg, 101h je event_key_up cmp uMsg, 8 je event_focus_lost cmp uMsg, 14h je event_erase cmp uMsg, 0Fh je event_paint cmp uMsg, WM_CLOSE je event_close cmp uMsg, WM_DESTROY je event_close invoke DefWindowProcA, hwnd, uMsg, wp, lp ret event_key_down: mov ecx, wp cmp ecx, 255 ja event_done test lp, 40000000h jnz event_done mov keys3D[ecx], 1 mov pressedKeys3D[ecx], 1 jmp event_done event_key_up: mov ecx, wp cmp ecx, 255 ja event_done mov keys3D[ecx], 0 jmp event_done event_fullscreen: test lp, 40000000h jnz event_done call ToggleFullscreen3D jmp event_done event_focus_lost: lea edi, keys3D xor eax, eax mov ecx, 128 rep stosd jmp event_done event_erase: mov eax, 1 ret event_paint: invoke BeginPaint, hwnd, OFFSET paint3D cmp h3DDC, 0 je @F call Present3D @@: invoke EndPaint, hwnd, OFFSET paint3D jmp event_done event_close: invoke PostQuitMessage, 0 event_done: xor eax, eax ret WindowEvents3D ENDP Pressed3D PROC key:DWORD mov ecx, key xor eax, eax cmp ecx, 255 ja @F cmp pressedKeys3D[ecx], 0 je @F mov pressedKeys3D[ecx], 0 mov eax, 8000h @@: ret Pressed3D ENDP InitPaths3D PROC uses esi edi invoke GetModuleFileNameA, 0, OFFSET directory3D, SIZEOF directory3D test eax, eax jz path_done lea esi, directory3D mov edi, esi path_scan: mov al, [esi] test al, al jz path_found cmp al, '\' jne @F mov edi, esi @@: inc esi jmp path_scan path_found: mov BYTE PTR [edi], 0 invoke SetCurrentDirectoryA, OFFSET directory3D invoke GetFileAttributesA, OFFSET szTexturesRelPath cmp eax, -1 jne path_done ; Also support launching bin/poker.exe without a working directory. invoke SetCurrentDirectoryA, OFFSET parent3D path_done: ret InitPaths3D ENDP Create3DWindow PROC uses ebx esi edi local widthPx:DWORD local heightPx:DWORD invoke GetModuleHandleA, OFFSET user32Name3D invoke GetProcAddress, eax, OFFSET dpiName3D test eax, eax jz @F call eax @@: invoke GetModuleHandleA, 0 mov h3DInst, eax mov wc3D.hInstance, eax invoke LoadIconA, eax, 1 mov wc3D.hIcon, eax mov wc3D.hIconSm, eax invoke LoadCursorA, 0, 32512 mov wc3D.hCursor, eax mov wc3D.cbSize, SIZEOF C3D_WNDCLASSEX mov wc3D.style, CS_HREDRAW or CS_VREDRAW mov wc3D.lpfnWndProc, OFFSET Casino3DWndProc mov wc3D.lpszClassName, OFFSET sz3DClassName invoke RegisterClassExA, OFFSET wc3D mov bmi3D.bmiHeader.biSize, SIZEOF C3D_BITMAPINFOHEADER mov bmi3D.bmiHeader.biWidth, SCREEN_W mov bmi3D.bmiHeader.biHeight, -SCREEN_H mov bmi3D.bmiHeader.biPlanes, 1 mov bmi3D.bmiHeader.biBitCount, 32 mov bmi3D.bmiHeader.biSizeImage, SCREEN_SIZE * 4 invoke GetSystemMetrics, 0 mov esi, eax sub eax, 80 cmp eax, 1120 jle @F mov eax, 1120 @@: mov widthPx, eax invoke GetSystemMetrics, 1 mov edi, eax sub eax, 120 mov heightPx, eax mov eax, widthPx imul eax, 3 shr eax, 2 cmp eax, heightPx jle @F mov eax, heightPx imul eax, 4 xor edx, edx mov ecx, 3 div ecx mov widthPx, eax @@: mov eax, widthPx imul eax, 3 shr eax, 2 mov clientRect3D[12], eax mov eax, widthPx mov clientRect3D[8], eax invoke AdjustWindowRectEx, OFFSET clientRect3D, WS_OVERLAPPEDWINDOW, 0, 0 mov eax, clientRect3D[8] sub eax, clientRect3D mov widthPx, eax sub esi, eax sar esi, 1 mov eax, clientRect3D[12] sub eax, clientRect3D[4] mov heightPx, eax sub edi, eax sar edi, 1 invoke CreateWindowExA, 0, OFFSET sz3DClassName, OFFSET sz3DWindowTitle, WS_OVERLAPPEDWINDOW, esi, edi, widthPx, heightPx, 0, 0, h3DInst, 0 test eax, eax jz window_failed mov h3DWnd, eax invoke GetDC, h3DWnd mov h3DDC, eax invoke SetStretchBltMode, h3DDC, 3 invoke ShowWindow, h3DWnd, SW_SHOW invoke UpdateWindow, h3DWnd invoke SetForegroundWindow, h3DWnd mov eax, 1 window_failed: ret Create3DWindow ENDP LoadTextures3D PROC uses ebx local count:DWORD invoke CreateFileA, OFFSET szTexturesRelPath, 80000000h, 1, 0, 3, 80h, 0 cmp eax, -1 je assets_failed mov ebx, eax invoke ReadFile, ebx, OFFSET texturesBuffer, SIZEOF texturesBuffer, ADDR count, 0 push eax invoke CloseHandle, ebx pop eax test eax, eax jz assets_failed cmp count, SIZEOF texturesBuffer jne assets_failed mov eax, 1 ret assets_failed: invoke MessageBoxA, h3DWnd, OFFSET textMissing3D, OFFSET sz3DWindowTitle, 10h xor eax, eax ret LoadTextures3D ENDP Present3D PROC uses ebx esi edi local viewW:DWORD local viewH:DWORD local offsetX:DWORD local offsetY:DWORD invoke GetClientRect, h3DWnd, OFFSET clientRect3D mov esi, clientRect3D[8] mov edi, clientRect3D[12] test esi, esi jz present_done test edi, edi jz present_done mov viewW, esi mov eax, esi imul eax, 3 shr eax, 2 cmp eax, edi jle @F mov eax, edi imul eax, 4 xor edx, edx mov ecx, 3 div ecx mov viewW, eax mov eax, edi @@: mov viewH, eax mov ebx, esi sub ebx, viewW shr ebx, 1 mov offsetX, ebx mov ebx, edi sub ebx, viewH shr ebx, 1 mov offsetY, ebx ; Only clear the letterbox bars, never erase under the next frame. invoke PatBlt, h3DDC, 0, 0, esi, offsetY, 42h mov eax, offsetY add eax, viewH mov ecx, edi sub ecx, eax invoke PatBlt, h3DDC, 0, eax, esi, ecx, 42h invoke PatBlt, h3DDC, 0, 0, offsetX, edi, 42h mov eax, offsetX add eax, viewW mov ecx, esi sub ecx, eax invoke PatBlt, h3DDC, eax, 0, ecx, edi, 42h invoke StretchDIBits, h3DDC, offsetX, offsetY, viewW, viewH, 0, 0, SCREEN_W, SCREEN_H, OFFSET screenBuffer, OFFSET bmi3D, 0, SRCCOPY present_done: ret Present3D ENDP ToggleFullscreen3D PROC uses ebx esi edi cmp fullscreen3D, 0 jne restore_window invoke GetWindowRect, h3DWnd, OFFSET savedRect3D invoke MonitorFromWindow, h3DWnd, 2 invoke GetMonitorInfoA, eax, OFFSET monitor3D test eax, eax jz fullscreen_done invoke SetWindowLongA, h3DWnd, -16, 90000000h mov eax, monitor3D[12] sub eax, monitor3D[4] mov ebx, monitor3D[16] sub ebx, monitor3D[8] invoke SetWindowPos, h3DWnd, 0, monitor3D[4], monitor3D[8], eax, ebx, 20h mov fullscreen3D, 1 ret restore_window: invoke SetWindowLongA, h3DWnd, -16, WS_OVERLAPPEDWINDOW or 10000000h mov eax, savedRect3D[8] sub eax, savedRect3D mov ebx, savedRect3D[12] sub ebx, savedRect3D[4] invoke SetWindowPos, h3DWnd, 0, savedRect3D, savedRect3D[4], eax, ebx, 20h mov fullscreen3D, 0 fullscreen_done: ret ToggleFullscreen3D ENDP UpdateCamera3D PROC uses ebx mov eax, playerAngle and eax, 511 mov ebx, tableCos[eax*4] mov playerDirX, ebx mov eax, tableSin[eax*4] mov playerDirY, eax imul eax, -66 cdq mov ecx, 100 idiv ecx mov playerPlaneX, eax mov eax, playerDirX imul eax, 66 cdq idiv ecx mov playerPlaneY, eax ret UpdateCamera3D ENDP ; Four corners of a 0.3-tile-wide body; bounds checked before every map read. CanWalk3D PROC uses ebx esi edi px:DWORD, py:DWORD mov esi, -9830 walk_corner_x: mov edi, -9830 walk_corner_y: mov eax, px add eax, esi sar eax, 16 cmp eax, MAP_WIDTH jae walk_blocked mov ebx, eax mov eax, py add eax, edi sar eax, 16 cmp eax, MAP_HEIGHT jae walk_blocked shl eax, 5 add eax, ebx cmp BYTE PTR casinoMap[eax], 0 jne walk_blocked add edi, 19660 cmp edi, 9830 jle walk_corner_y add esi, 19660 cmp esi, 9830 jle walk_corner_x mov eax, 1 ret walk_blocked: xor eax, eax ret CanWalk3D ENDP LoadProgress3D PROC uses ebx mov bankroll, 10000 invoke CreateFileA, OFFSET savePath3D, 80000000h, 1, 0, 3, 80h, 0 cmp eax, -1 je progress_loaded mov ebx, eax invoke ReadFile, ebx, OFFSET saveData3D, 16, OFFSET saveIo3D, 0 invoke CloseHandle, ebx cmp saveIo3D, 16 jne progress_loaded cmp saveData3D, 32443343h jne progress_loaded mov eax, saveData3D[4] cmp eax, 1000000000 ja progress_loaded mov bankroll, eax mov eax, saveData3D[8] and eax, 15 or eax, 1 mov ownedBacks3D, eax mov ecx, saveData3D[12] cmp ecx, 3 ja progress_loaded bt eax, ecx jnc progress_loaded mov selectedBack3D, ecx progress_loaded: ret LoadProgress3D ENDP SaveProgress3D PROC uses ebx invoke CreateDirectoryA, OFFSET runtime3D, 0 mov saveData3D, 32443343h mov eax, bankroll mov saveData3D[4], eax mov eax, ownedBacks3D mov saveData3D[8], eax mov eax, selectedBack3D mov saveData3D[12], eax invoke CreateFileA, OFFSET savePath3D, 40000000h, 0, 0, 2, 80h, 0 cmp eax, -1 je progress_saved mov ebx, eax invoke WriteFile, ebx, OFFSET saveData3D, 16, OFFSET saveIo3D, 0 invoke CloseHandle, ebx progress_saved: ret SaveProgress3D ENDP