feat: update casino environments
This commit is contained in:
parent
5dedaf459f
commit
7e4f7d7be1
36 changed files with 2332 additions and 11 deletions
BIN
assets/sprites/backrooms/Backrooms_ceiling.jpg
Normal file
BIN
assets/sprites/backrooms/Backrooms_ceiling.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 846 KiB |
BIN
assets/sprites/backrooms/Backrooms_ceiling_lamp.jpg
Normal file
BIN
assets/sprites/backrooms/Backrooms_ceiling_lamp.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.1 MiB |
BIN
assets/sprites/backrooms/Backrooms_floor.jpg
Normal file
BIN
assets/sprites/backrooms/Backrooms_floor.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.7 MiB |
BIN
assets/sprites/backrooms/Backrooms_wall.jpg
Normal file
BIN
assets/sprites/backrooms/Backrooms_wall.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.6 MiB |
BIN
assets/sprites/backrooms/materials.bin
Normal file
BIN
assets/sprites/backrooms/materials.bin
Normal file
Binary file not shown.
BIN
bin/poker.exe
BIN
bin/poker.exe
Binary file not shown.
|
|
@ -8,7 +8,7 @@ namespace AssemblerCasinoLauncher
|
||||||
{
|
{
|
||||||
static class Program
|
static class Program
|
||||||
{
|
{
|
||||||
const string ExpectedPokerSha256 = "25FBDF78EDF3DFD3F6B72657E78C3156F74931A656B4CBDB15260D496C96849A";
|
const string ExpectedPokerSha256 = "B0F5CE31D9A2467CFE8AF66CA90CC545F75318F11D149473A4377A2A278C8B23";
|
||||||
|
|
||||||
[STAThread]
|
[STAThread]
|
||||||
static void Main()
|
static void Main()
|
||||||
|
|
|
||||||
Binary file not shown.
102
casino3d.inc
102
casino3d.inc
|
|
@ -171,6 +171,7 @@ include src_graphics\native_dice_data.inc
|
||||||
include src_graphics\scratch_data.inc
|
include src_graphics\scratch_data.inc
|
||||||
include src_graphics\hell_tower_data.inc
|
include src_graphics\hell_tower_data.inc
|
||||||
include src_graphics\charms_data.inc
|
include src_graphics\charms_data.inc
|
||||||
|
include src_graphics\backrooms_data.inc
|
||||||
include src_graphics\observer_data.inc
|
include src_graphics\observer_data.inc
|
||||||
include src_graphics\darts_data.inc
|
include src_graphics\darts_data.inc
|
||||||
include src_graphics\jackbox_data.inc
|
include src_graphics\jackbox_data.inc
|
||||||
|
|
@ -471,7 +472,7 @@ screenBuffer dd SCREEN_SIZE dup(?)
|
||||||
ALIGN 4
|
ALIGN 4
|
||||||
zBuffer dd SCREEN_W dup(?)
|
zBuffer dd SCREEN_W dup(?)
|
||||||
ALIGN 4
|
ALIGN 4
|
||||||
texturesBuffer dd (104 * 128 * 128) dup(?)
|
texturesBuffer dd (185 * 128 * 128) dup(?)
|
||||||
|
|
||||||
hudNumBuffer db 32 dup(?)
|
hudNumBuffer db 32 dup(?)
|
||||||
|
|
||||||
|
|
@ -3249,6 +3250,25 @@ dice_start_roll:
|
||||||
invoke RandomRange3D, 6
|
invoke RandomRange3D, 6
|
||||||
inc eax
|
inc eax
|
||||||
mov dice3d_val2, eax
|
mov dice3d_val2, eax
|
||||||
|
call BackroomsLuck3D
|
||||||
|
cmp eax,-1
|
||||||
|
je br_dice_fixed
|
||||||
|
xor eax,1
|
||||||
|
mov ecx,dice3d_choice
|
||||||
|
dec ecx
|
||||||
|
xor eax,ecx
|
||||||
|
mov edx,dice3d_val1
|
||||||
|
add edx,dice3d_val2
|
||||||
|
and edx,1
|
||||||
|
cmp eax,edx
|
||||||
|
je br_dice_fixed
|
||||||
|
xor edx,edx
|
||||||
|
mov eax,dice3d_val2
|
||||||
|
mov ecx,6
|
||||||
|
div ecx
|
||||||
|
inc edx
|
||||||
|
mov dice3d_val2,edx
|
||||||
|
br_dice_fixed:
|
||||||
invoke PlayCasinoSound3D, OFFSET soundDiceRoll, 0, 1
|
invoke PlayCasinoSound3D, OFFSET soundDiceRoll, 0, 1
|
||||||
call SaveProgress3D
|
call SaveProgress3D
|
||||||
ret
|
ret
|
||||||
|
|
@ -3485,6 +3505,21 @@ InitSkullsGame ENDP
|
||||||
FinalizeSkullsGuess PROC uses ebx
|
FinalizeSkullsGuess PROC uses ebx
|
||||||
cmp skulls3d_state,3
|
cmp skulls3d_state,3
|
||||||
jne skulls_guess_done
|
jne skulls_guess_done
|
||||||
|
cmp brSkullsLuck3D,-1
|
||||||
|
je br_skulls_fixed
|
||||||
|
mov eax,skulls3d_choice
|
||||||
|
cmp brSkullsLuck3D,1
|
||||||
|
je @F
|
||||||
|
inc eax
|
||||||
|
xor edx,edx
|
||||||
|
mov ecx,3
|
||||||
|
div ecx
|
||||||
|
mov eax,edx
|
||||||
|
@@:
|
||||||
|
mov skulls3d_ballPos,eax
|
||||||
|
; Reality distortion explicitly covers relocation before the reveal.
|
||||||
|
mov skulls3d_timer,0
|
||||||
|
br_skulls_fixed:
|
||||||
mov eax, skulls3d_choice
|
mov eax, skulls3d_choice
|
||||||
cmp eax, skulls3d_ballPos
|
cmp eax, skulls3d_ballPos
|
||||||
jne skulls_guess_wrong
|
jne skulls_guess_wrong
|
||||||
|
|
@ -3568,6 +3603,8 @@ skulls_bet_down:
|
||||||
ret
|
ret
|
||||||
|
|
||||||
skulls_start_game:
|
skulls_start_game:
|
||||||
|
call BackroomsLuck3D
|
||||||
|
mov brSkullsLuck3D,eax
|
||||||
mov eax, skulls3d_bet
|
mov eax, skulls3d_bet
|
||||||
cmp eax, bankroll
|
cmp eax, bankroll
|
||||||
jle @F
|
jle @F
|
||||||
|
|
@ -3716,6 +3753,16 @@ RenderSkullsGame PROC uses ebx esi edi
|
||||||
jne @F
|
jne @F
|
||||||
invoke DrawString8x8, 28, 62, OFFSET textSkullsPhase3, 00FFFF00h
|
invoke DrawString8x8, 28, 62, OFFSET textSkullsPhase3, 00FFFF00h
|
||||||
jmp skulls_draw_idle_cups
|
jmp skulls_draw_idle_cups
|
||||||
|
@@:
|
||||||
|
; Short artifact glitch, then reveal the actual ball and matching payout.
|
||||||
|
cmp brSkullsLuck3D,-1
|
||||||
|
je @F
|
||||||
|
cmp skulls3d_timer,12
|
||||||
|
jae @F
|
||||||
|
inc skulls3d_timer
|
||||||
|
invoke DrawBox,8,76,304,122,00130F20h
|
||||||
|
invoke DrawString8x8,108,128,OFFSET brRealityGlitch3D,00FF88CCh
|
||||||
|
jmp skulls_render_controls
|
||||||
@@:
|
@@:
|
||||||
; Phase 4: Reveal outcome
|
; Phase 4: Reveal outcome
|
||||||
mov eax, skulls3d_win
|
mov eax, skulls3d_win
|
||||||
|
|
@ -4633,6 +4680,8 @@ check_total_movement:
|
||||||
mov playerY, eax
|
mov playerY, eax
|
||||||
|
|
||||||
input_action:
|
input_action:
|
||||||
|
cmp brActive3D,0
|
||||||
|
jne player_input_complete
|
||||||
cmp engineMode,MODE_STAIRS
|
cmp engineMode,MODE_STAIRS
|
||||||
je player_input_complete
|
je player_input_complete
|
||||||
invoke Pressed3D, 45h
|
invoke Pressed3D, 45h
|
||||||
|
|
@ -4706,9 +4755,12 @@ CheckInteractions ENDP
|
||||||
; (Legacy console arcade bezel bridge removed)
|
; (Legacy console arcade bezel bridge removed)
|
||||||
|
|
||||||
Trigger3DInteraction PROC
|
Trigger3DInteraction PROC
|
||||||
|
cmp brActive3D,0
|
||||||
|
jne trigger_backrooms_station
|
||||||
call TriggerHallInteraction3D
|
call TriggerHallInteraction3D
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jnz trigger_done
|
jnz trigger_done
|
||||||
|
trigger_backrooms_station:
|
||||||
mov eax, interactTargetId
|
mov eax, interactTargetId
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz trigger_done
|
jz trigger_done
|
||||||
|
|
@ -5201,6 +5253,7 @@ include src_graphics\charms.inc
|
||||||
include src_graphics\observer.inc
|
include src_graphics\observer.inc
|
||||||
include src_graphics\darts.inc
|
include src_graphics\darts.inc
|
||||||
include src_graphics\jackbox.inc
|
include src_graphics\jackbox.inc
|
||||||
|
include src_graphics\backrooms.inc
|
||||||
|
|
||||||
; --- Main Loop of the 3D Casino Engine ---
|
; --- Main Loop of the 3D Casino Engine ---
|
||||||
StartHellTower3D PROC uses ebx esi edi
|
StartHellTower3D PROC uses ebx esi edi
|
||||||
|
|
@ -5279,6 +5332,9 @@ engine_observer_skip:
|
||||||
cmp engineMode, MODE_WALK
|
cmp engineMode, MODE_WALK
|
||||||
jne leave_table
|
jne leave_table
|
||||||
pause_interior_walk:
|
pause_interior_walk:
|
||||||
|
cmp brCutscene3D,0
|
||||||
|
jne engine_tick
|
||||||
|
mov brEntryHold3D,0
|
||||||
xor paused3D, 1
|
xor paused3D, 1
|
||||||
jmp engine_tick
|
jmp engine_tick
|
||||||
leave_table:
|
leave_table:
|
||||||
|
|
@ -5343,10 +5399,15 @@ check_arrival_mode:
|
||||||
check_walk_mode:
|
check_walk_mode:
|
||||||
cmp engineMode, MODE_WALK
|
cmp engineMode, MODE_WALK
|
||||||
jne check_slots_mode
|
jne check_slots_mode
|
||||||
|
cmp brActive3D,0
|
||||||
|
jne engine_backrooms
|
||||||
call UpdateHall3D
|
call UpdateHall3D
|
||||||
call UpdateCamera3D
|
call UpdateCamera3D
|
||||||
call CheckInteractions
|
call CheckInteractions
|
||||||
call HandlePlayerInput
|
call HandlePlayerInput
|
||||||
|
call BackroomsEntry3D
|
||||||
|
cmp brActive3D,0
|
||||||
|
jne engine_backrooms
|
||||||
call HandleJukeboxKeys3D
|
call HandleJukeboxKeys3D
|
||||||
call UpdateInteriorTravel3D
|
call UpdateInteriorTravel3D
|
||||||
call UpdateInteriorEye3D
|
call UpdateInteriorEye3D
|
||||||
|
|
@ -5365,6 +5426,14 @@ walk_world_ready:
|
||||||
call RenderHUD
|
call RenderHUD
|
||||||
call RenderMinimap
|
call RenderMinimap
|
||||||
jmp present_frame
|
jmp present_frame
|
||||||
|
engine_backrooms:
|
||||||
|
call HandleBackrooms3D
|
||||||
|
cmp brActive3D,0
|
||||||
|
je check_walk_mode
|
||||||
|
cmp engineMode,MODE_WALK
|
||||||
|
jne check_slots_mode
|
||||||
|
call RenderBackrooms3D
|
||||||
|
jmp present_frame
|
||||||
check_slots_mode:
|
check_slots_mode:
|
||||||
cmp engineMode,MODE_JACKBOX
|
cmp engineMode,MODE_JACKBOX
|
||||||
jne check_jackbox_done
|
jne check_jackbox_done
|
||||||
|
|
@ -5531,6 +5600,7 @@ check_russian_mode:
|
||||||
call RenderRussianGame3D
|
call RenderRussianGame3D
|
||||||
jmp present_frame
|
jmp present_frame
|
||||||
draw_pause:
|
draw_pause:
|
||||||
|
mov brEntryHold3D,0
|
||||||
invoke DrawBoxBorder, 28, 36, 264, 168, 00151C21h, 00D8BC6Ah, 2
|
invoke DrawBoxBorder, 28, 36, 264, 168, 00151C21h, 00D8BC6Ah, 2
|
||||||
invoke DrawString8x8, 44, 48, OFFSET textPause3D, 00FFFFFFh
|
invoke DrawString8x8, 44, 48, OFFSET textPause3D, 00FFFFFFh
|
||||||
cmp displayFill3D, 0
|
cmp displayFill3D, 0
|
||||||
|
|
@ -5559,7 +5629,10 @@ pause_draw_quality_value:
|
||||||
invoke DrawString8x8, 44, 130, OFFSET textSoundLevel3D, 00BBBBBBh
|
invoke DrawString8x8, 44, 130, OFFSET textSoundLevel3D, 00BBBBBBh
|
||||||
invoke FormatNumber, settingsVolume, OFFSET hudNumBuffer
|
invoke FormatNumber, settingsVolume, OFFSET hudNumBuffer
|
||||||
invoke DrawString8x8, 124, 130, OFFSET hudNumBuffer, 00FFFFFFh
|
invoke DrawString8x8, 124, 130, OFFSET hudNumBuffer, 00FFFFFFh
|
||||||
|
cmp brOwned3D,0
|
||||||
|
jne @F
|
||||||
invoke DrawString8x8, 44, 150, OFFSET textFullscreenKey3D, 00A0A0A0h
|
invoke DrawString8x8, 44, 150, OFFSET textFullscreenKey3D, 00A0A0A0h
|
||||||
|
@@:
|
||||||
invoke DrawString8x8, 44, 170, OFFSET textResume3D, 00D8BC6Ah
|
invoke DrawString8x8, 44, 170, OFFSET textResume3D, 00D8BC6Ah
|
||||||
invoke DrawString8x8, 44, 188, OFFSET textQuit3D, 00BBBBBBh
|
invoke DrawString8x8, 44, 188, OFFSET textQuit3D, 00BBBBBBh
|
||||||
invoke Pressed3D, 31h
|
invoke Pressed3D, 31h
|
||||||
|
|
@ -5597,12 +5670,37 @@ pause_low_spec_saved:
|
||||||
call ApplySoundVolume
|
call ApplySoundVolume
|
||||||
call SaveProgress3D
|
call SaveProgress3D
|
||||||
@@:
|
@@:
|
||||||
|
cmp brOwned3D,0
|
||||||
|
je br_pause_inventory_done
|
||||||
|
invoke DrawString8x8,44,150,OFFSET brToggle3D,00D8BC6Ah
|
||||||
|
invoke DrawString8x8,36,214,OFFSET brInventory3D,00D8BC6Ah
|
||||||
|
mov edx,OFFSET brDisabledText3D
|
||||||
|
cmp brEnabled3D,0
|
||||||
|
je @F
|
||||||
|
mov edx,OFFSET brEnabledText3D
|
||||||
|
@@:
|
||||||
|
invoke DrawString8x8,248,150,edx,00FFFFFFh
|
||||||
|
invoke Pressed3D,52h
|
||||||
|
test eax,eax
|
||||||
|
jz br_pause_inventory_done
|
||||||
|
xor brEnabled3D,1
|
||||||
|
call SaveProgress3D
|
||||||
|
br_pause_inventory_done:
|
||||||
invoke Pressed3D, 51h
|
invoke Pressed3D, 51h
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz @F
|
jz @F
|
||||||
call SaveProgress3D
|
call SaveProgress3D
|
||||||
jmp engine_shutdown
|
jmp engine_shutdown
|
||||||
present_frame:
|
present_frame:
|
||||||
|
cmp brActive3D,0
|
||||||
|
je br_record_clock_done
|
||||||
|
cmp engineMode,MODE_WALK
|
||||||
|
je br_record_clock_done
|
||||||
|
cmp paused3D,0
|
||||||
|
jne br_record_clock_done
|
||||||
|
mov eax,deltaTime3D
|
||||||
|
add brClock3D,eax
|
||||||
|
br_record_clock_done:
|
||||||
call UpdateJukeboxAudio3D
|
call UpdateJukeboxAudio3D
|
||||||
call RenderTowerInGameBadge
|
call RenderTowerInGameBadge
|
||||||
call RenderJukeboxVolumeHUD
|
call RenderJukeboxVolumeHUD
|
||||||
|
|
@ -5638,6 +5736,7 @@ present_frame:
|
||||||
invoke Sleep, ecx
|
invoke Sleep, ecx
|
||||||
jmp engine_loop
|
jmp engine_loop
|
||||||
engine_idle:
|
engine_idle:
|
||||||
|
mov brEntryHold3D,0
|
||||||
call UnlockMouse3D
|
call UnlockMouse3D
|
||||||
invoke Sleep, 50
|
invoke Sleep, 50
|
||||||
jmp engine_loop
|
jmp engine_loop
|
||||||
|
|
@ -5659,6 +5758,7 @@ engine_shutdown:
|
||||||
@@:
|
@@:
|
||||||
call SaveProgress3D
|
call SaveProgress3D
|
||||||
invoke PlayCasinoSound3D, 0, 0, 0
|
invoke PlayCasinoSound3D, 0, 0, 0
|
||||||
|
invoke FreeAnimPack3D,OFFSET brMaterials3D
|
||||||
call FreeRussianAssets3D
|
call FreeRussianAssets3D
|
||||||
call FreeDarts3D
|
call FreeDarts3D
|
||||||
call FreeStartupAssets3D
|
call FreeStartupAssets3D
|
||||||
|
|
|
||||||
BIN
dist/Assembler Casino.exe
vendored
BIN
dist/Assembler Casino.exe
vendored
Binary file not shown.
24
poker.asm
24
poker.asm
|
|
@ -820,7 +820,14 @@ save_stats_played_loop:
|
||||||
mov DWORD PTR [saveBuffer+296],eax
|
mov DWORD PTR [saveBuffer+296],eax
|
||||||
mov eax,charmEnabledMask3D
|
mov eax,charmEnabledMask3D
|
||||||
mov DWORD PTR [saveBuffer+300],eax
|
mov DWORD PTR [saveBuffer+300],eax
|
||||||
mov DWORD PTR [saveBuffer+304],2
|
mov eax,brOwned3D
|
||||||
|
shl eax,16
|
||||||
|
mov ecx,brEnabled3D
|
||||||
|
and ecx,brOwned3D
|
||||||
|
shl ecx,17
|
||||||
|
or eax,ecx
|
||||||
|
or eax,2
|
||||||
|
mov DWORD PTR [saveBuffer+304],eax
|
||||||
invoke ArtifactSaveSignature3D,OFFSET saveBuffer
|
invoke ArtifactSaveSignature3D,OFFSET saveBuffer
|
||||||
mov DWORD PTR [saveBuffer+308],eax
|
mov DWORD PTR [saveBuffer+308],eax
|
||||||
call BuildSaveFullPath
|
call BuildSaveFullPath
|
||||||
|
|
@ -887,6 +894,14 @@ load_file_opened:
|
||||||
mov charmDevilUses,eax
|
mov charmDevilUses,eax
|
||||||
mov eax,DWORD PTR [saveBuffer+300]
|
mov eax,DWORD PTR [saveBuffer+300]
|
||||||
mov charmEnabledMask3D,eax
|
mov charmEnabledMask3D,eax
|
||||||
|
mov eax,DWORD PTR [saveBuffer+304]
|
||||||
|
shr eax,16
|
||||||
|
and eax,1
|
||||||
|
mov brOwned3D,eax
|
||||||
|
mov eax,DWORD PTR [saveBuffer+304]
|
||||||
|
shr eax,17
|
||||||
|
and eax,1
|
||||||
|
mov brEnabled3D,eax
|
||||||
load_signature_ok:
|
load_signature_ok:
|
||||||
mov eax, DWORD PTR [saveBuffer+4]
|
mov eax, DWORD PTR [saveBuffer+4]
|
||||||
mov bankroll, eax
|
mov bankroll, eax
|
||||||
|
|
@ -2043,7 +2058,14 @@ test_error_exit_engine:
|
||||||
RunHellTowerTest3D ENDP
|
RunHellTowerTest3D ENDP
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
|
IFDEF BACKROOMS_TEST
|
||||||
|
include tools/tests/backrooms_test.inc
|
||||||
|
ENDIF
|
||||||
main PROC
|
main PROC
|
||||||
|
IFDEF BACKROOMS_TEST
|
||||||
|
call RunBackroomsTest3D
|
||||||
|
invoke ExitProcess,eax
|
||||||
|
ENDIF
|
||||||
IFDEF HELL_TOWER_TEST
|
IFDEF HELL_TOWER_TEST
|
||||||
call RunHellTowerTest3D
|
call RunHellTowerTest3D
|
||||||
invoke ExitProcess,eax
|
invoke ExitProcess,eax
|
||||||
|
|
|
||||||
BIN
poker.exe
BIN
poker.exe
Binary file not shown.
BIN
poker.obj
BIN
poker.obj
Binary file not shown.
|
|
@ -1,4 +1,7 @@
|
||||||
HandleArtifactShop3D PROC uses ebx
|
HandleArtifactShop3D PROC uses ebx
|
||||||
|
call HandleBackroomsInventory3D
|
||||||
|
test eax,eax
|
||||||
|
jnz artifact_shop_done
|
||||||
invoke Pressed3D,09h
|
invoke Pressed3D,09h
|
||||||
test eax,eax
|
test eax,eax
|
||||||
jz @F
|
jz @F
|
||||||
|
|
@ -95,6 +98,11 @@ HandleArtifactShop3D ENDP
|
||||||
|
|
||||||
RenderArtifactShop3D PROC uses ebx esi edi
|
RenderArtifactShop3D PROC uses ebx esi edi
|
||||||
local y:DWORD,x:DWORD,ink:DWORD
|
local y:DWORD,x:DWORD,ink:DWORD
|
||||||
|
cmp brInventoryOpen3D,0
|
||||||
|
je @F
|
||||||
|
call RenderBackroomsInventory3D
|
||||||
|
ret
|
||||||
|
@@:
|
||||||
invoke DrawBox,0,0,320,240,0015191Bh
|
invoke DrawBox,0,0,320,240,0015191Bh
|
||||||
invoke DrawBox,0,0,320,24,002B302Ah
|
invoke DrawBox,0,0,320,24,002B302Ah
|
||||||
invoke DrawString8x8,8,7,OFFSET artifactShopTitle3D,00EED5A0h
|
invoke DrawString8x8,8,7,OFFSET artifactShopTitle3D,00EED5A0h
|
||||||
|
|
@ -140,7 +148,13 @@ artifact_shop_card:
|
||||||
invoke DrawString8x8,120,77,charmDescs3D[ebx*4],00FFFFFFh
|
invoke DrawString8x8,120,77,charmDescs3D[ebx*4],00FFFFFFh
|
||||||
; Detail descriptions use full width below cards to avoid clipped text.
|
; Detail descriptions use full width below cards to avoid clipped text.
|
||||||
invoke DrawString8x8,8,216,artifactRules3D[ebx*4],00DDCDAAh
|
invoke DrawString8x8,8,216,artifactRules3D[ebx*4],00DDCDAAh
|
||||||
|
cmp brOwned3D,0
|
||||||
|
je @F
|
||||||
|
invoke DrawString8x8,8,228,OFFSET brInventoryHelp3D,00D8BC6Ah
|
||||||
|
jmp br_shop_help_done
|
||||||
|
@@:
|
||||||
invoke DrawString8x8,8,228,OFFSET artifactHelp3D,0099AAA5h
|
invoke DrawString8x8,8,228,OFFSET artifactHelp3D,0099AAA5h
|
||||||
|
br_shop_help_done:
|
||||||
invoke DrawString8x8,120,96,OFFSET artifactPack3D,0099AAA5h
|
invoke DrawString8x8,120,96,OFFSET artifactPack3D,0099AAA5h
|
||||||
invoke FormatNumber,charmUsesPack3D[ebx*4],OFFSET artifactNum3D
|
invoke FormatNumber,charmUsesPack3D[ebx*4],OFFSET artifactNum3D
|
||||||
invoke DrawString8x8,280,96,OFFSET artifactNum3D,00FFFFFFh
|
invoke DrawString8x8,280,96,OFFSET artifactNum3D,00FFFFFFh
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,15 @@ ValidateArtifactSave3D PROC uses esi edi source:DWORD
|
||||||
mov esi,source
|
mov esi,source
|
||||||
cmp DWORD PTR [esi+280],32465241h
|
cmp DWORD PTR [esi+280],32465241h
|
||||||
jne artifact_save_invalid
|
jne artifact_save_invalid
|
||||||
cmp DWORD PTR [esi+304],2
|
mov eax,[esi+304]
|
||||||
|
and eax,0FFFCFFFFh
|
||||||
|
cmp eax,2
|
||||||
jne artifact_save_invalid
|
jne artifact_save_invalid
|
||||||
|
test DWORD PTR [esi+304],20000h
|
||||||
|
jz @F
|
||||||
|
test DWORD PTR [esi+304],10000h
|
||||||
|
jz artifact_save_invalid
|
||||||
|
@@:
|
||||||
invoke ArtifactSaveSignature3D,esi
|
invoke ArtifactSaveSignature3D,esi
|
||||||
cmp eax,[esi+308]
|
cmp eax,[esi+308]
|
||||||
jne artifact_save_invalid
|
jne artifact_save_invalid
|
||||||
|
|
@ -65,6 +72,8 @@ ArtifactCredit3D PROC amount:DWORD
|
||||||
ArtifactCredit3D ENDP
|
ArtifactCredit3D ENDP
|
||||||
|
|
||||||
ResetArtifacts3D PROC
|
ResetArtifacts3D PROC
|
||||||
|
mov brOwned3D,0
|
||||||
|
mov brEnabled3D,1
|
||||||
mov charmCloverUses,0
|
mov charmCloverUses,0
|
||||||
mov charmHorseshoeUses,0
|
mov charmHorseshoeUses,0
|
||||||
mov charmSkullUses,0
|
mov charmSkullUses,0
|
||||||
|
|
|
||||||
1068
src_graphics/backrooms.inc
Normal file
1068
src_graphics/backrooms.inc
Normal file
File diff suppressed because it is too large
Load diff
86
src_graphics/backrooms_data.inc
Normal file
86
src_graphics/backrooms_data.inc
Normal file
|
|
@ -0,0 +1,86 @@
|
||||||
|
; Dedicated world/session. All coordinates are 16.16, all time is active ms.
|
||||||
|
HALL_BACKROOMS equ 6
|
||||||
|
BR_WALL equ 180
|
||||||
|
BR_FLOOR equ 181
|
||||||
|
BR_CEILING equ 182
|
||||||
|
BR_LAMP equ 183
|
||||||
|
BR_EXIT equ 184
|
||||||
|
BackroomsEntry3D PROTO
|
||||||
|
BeginBackrooms3D PROTO
|
||||||
|
GenerateBackrooms3D PROTO
|
||||||
|
HandleBackrooms3D PROTO
|
||||||
|
RenderBackrooms3D PROTO
|
||||||
|
LeaveBackrooms3D PROTO :DWORD
|
||||||
|
BackroomsLuck3D PROTO
|
||||||
|
BackroomsWheelLuck3D PROTO :DWORD
|
||||||
|
BackroomsDeck3D PROTO :DWORD,:DWORD,:DWORD
|
||||||
|
BackroomsBlackjackDeck3D PROTO
|
||||||
|
BackroomsPokerDeck3D PROTO
|
||||||
|
BackroomsDurakDeck3D PROTO
|
||||||
|
BackroomsBuckshotLuck3D PROTO
|
||||||
|
BackroomsRussianLuck3D PROTO
|
||||||
|
BackroomsRussianCylinder3D PROTO
|
||||||
|
LoadBackroomsAssets3D PROTO
|
||||||
|
HandleBackroomsInventory3D PROTO
|
||||||
|
RenderBackroomsInventory3D PROTO
|
||||||
|
.data
|
||||||
|
brActive3D dd 0
|
||||||
|
brEntryHold3D dd 0
|
||||||
|
brEntryAngle3D dd 0
|
||||||
|
brCutscene3D dd 0
|
||||||
|
brClock3D dd 0
|
||||||
|
brSkullsLuck3D dd -1
|
||||||
|
brSlotLuck3D dd -1
|
||||||
|
brRussianLuck3D dd -1
|
||||||
|
brBuckshotLuck3D dd -1
|
||||||
|
brDeckTargets3D dd 16 dup(0)
|
||||||
|
brDialogue3D dd 0
|
||||||
|
brOwned3D dd 0
|
||||||
|
brEnabled3D dd 1
|
||||||
|
brVhs3D dd 1
|
||||||
|
brExitCell3D dd 0
|
||||||
|
brTarget3D dd -1
|
||||||
|
brInventoryOpen3D dd 0
|
||||||
|
brMap3D db 1024 dup(BR_WALL)
|
||||||
|
brDistance3D dd 1024 dup(-1)
|
||||||
|
brStack3D dd 1024 dup(0)
|
||||||
|
brCandidates3D dd 4 dup(0)
|
||||||
|
brSteps3D dd -64,2,64,-2
|
||||||
|
brGames3D dd INTERACT_COIN,INTERACT_DICE,INTERACT_SLOTS_777,INTERACT_BLACKJACK,INTERACT_ROULETTE,INTERACT_SLOTS_CLOVER
|
||||||
|
brGameCells3D dd 6 dup(0)
|
||||||
|
brGamePacks3D dd OFFSET hallCardFurniture3D,OFFSET hallCardFurniture3D,OFFSET hallSlotFurniture3D,OFFSET hallCardFurniture3D,OFFSET hallWheelFurniture3D,OFFSET hallSlotFurniture3D
|
||||||
|
brGameFrames3D dd 0,0,0,0,0,1
|
||||||
|
brGamePrompts3D dd OFFSET brCoinPrompt3D,OFFSET brDicePrompt3D,OFFSET brSlotPrompt3D,OFFSET brCardPrompt3D,OFFSET brWheelPrompt3D,OFFSET brCloverPrompt3D
|
||||||
|
brCoinPrompt3D db 'E: COIN',0
|
||||||
|
brDicePrompt3D db 'E: DICE',0
|
||||||
|
brSlotPrompt3D db 'E: 777',0
|
||||||
|
brCardPrompt3D db 'E: BLACKJACK',0
|
||||||
|
brWheelPrompt3D db 'E: ROULETTE',0
|
||||||
|
brCloverPrompt3D db 'E: CLOVERPIT',0
|
||||||
|
brProp3D CityProp3D <0,0,FP_1*3/5,FP_1*4/5,0,OFFSET hallCardFurniture3D>
|
||||||
|
brMaterials3D AnimPack3D <0>
|
||||||
|
brMaterialPath3D db "assets\sprites\backrooms\materials.bin",0
|
||||||
|
brRec3D db 'REC',0
|
||||||
|
brTime3D db '00:00:00',0
|
||||||
|
brExitPrompt3D db 'E: EXIT',0
|
||||||
|
brHelp3D db 'V: VHS ESC: PAUSE',0
|
||||||
|
brInventory3D db 'REALITY ERROR: 90% / INFINITE',0
|
||||||
|
brToggle3D db 'R: TOGGLE REALITY ERROR',0
|
||||||
|
brEnabledText3D db 'ON',0
|
||||||
|
brDisabledText3D db 'OFF',0
|
||||||
|
brRealityGlitch3D db 'REALITY ERROR',0
|
||||||
|
brAward3D db 'REALITY ERROR / INFINITE / 90%',0
|
||||||
|
brInventoryHelp3D db 'R: REALITY ERROR / E: TOGGLE',0
|
||||||
|
brInventoryReturn3D db 'R / TAB: BACK',0
|
||||||
|
brInventoryRules1 db '90% FAVORABLE RANDOM OUTCOME',0
|
||||||
|
brInventoryRules2 db 'NO CHARGES / NO DUPLICATES',0
|
||||||
|
brInventoryRules3 db 'NORMAL CASINO ONLY',0
|
||||||
|
brInventoryRules4 db 'OFF IN TOWER / BACKROOMS',0
|
||||||
|
brInventoryRules5 db 'SKILL / CARD RULES STILL APPLY',0
|
||||||
|
brInventoryRules6 db 'BILLIARDS/BOWLING/DARTS UNCHANGED',0
|
||||||
|
brGlyph3D db 0,0
|
||||||
|
; Exact CP1251 dialogue, wrapped only at spaces by the renderer.
|
||||||
|
brText3D db 221,242,238,32,237,229,32,242,243,242,44,32,242,251,32,237,229,32
|
||||||
|
db 228,238,235,230,229,237,32,225,251,242,252,32,231,228,229,241,252,44,32
|
||||||
|
db 241,250,229,225,232,32,239,238,32,225,240,224,242,241,234,232,32,239,230,0
|
||||||
|
.code
|
||||||
|
|
@ -97,6 +97,7 @@ bs_reload_next:
|
||||||
inc bs3d_blankCount
|
inc bs3d_blankCount
|
||||||
dec bs3d_liveCount
|
dec bs3d_liveCount
|
||||||
@@:
|
@@:
|
||||||
|
call BackroomsBuckshotLuck3D
|
||||||
; The loading motion loops once per actual cartridge, then racks the pump.
|
; The loading motion loops once per actual cartridge, then racks the pump.
|
||||||
mov eax, bs3d_shellCount
|
mov eax, bs3d_shellCount
|
||||||
imul eax, 330
|
imul eax, 330
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,19 @@ cityRayY3D dd SCREEN_W dup(?)
|
||||||
; Exterior-only materials do not consume or overwrite the hall's texture slots.
|
; Exterior-only materials do not consume or overwrite the hall's texture slots.
|
||||||
ResolveCitySurface3D PROC material:DWORD
|
ResolveCitySurface3D PROC material:DWORD
|
||||||
mov eax,material
|
mov eax,material
|
||||||
|
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
|
cmp eax,BW_MATERIAL
|
||||||
jb @F
|
jb @F
|
||||||
cmp eax,BW_LAST_MATERIAL
|
cmp eax,BW_LAST_MATERIAL
|
||||||
|
|
@ -290,6 +303,27 @@ city_vertical_along:
|
||||||
dec edx
|
dec edx
|
||||||
and eax, 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 sourceX, eax
|
||||||
mov eax, viewEye3D
|
mov eax, viewEye3D
|
||||||
sub eax, zHigh
|
sub eax, zHigh
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,12 @@ hall_plane_row:
|
||||||
mov eax, viewCeiling3D
|
mov eax, viewCeiling3D
|
||||||
sub eax, viewEye3D
|
sub eax, viewEye3D
|
||||||
mov material, 101
|
mov material, 101
|
||||||
|
cmp brActive3D,0
|
||||||
|
je @F
|
||||||
|
cmp hallLevel3D,HALL_BACKROOMS
|
||||||
|
jne @F
|
||||||
|
mov material,BR_CEILING
|
||||||
|
@@:
|
||||||
cmp hallLevel3D,2
|
cmp hallLevel3D,2
|
||||||
jne @F
|
jne @F
|
||||||
mov material,125
|
mov material,125
|
||||||
|
|
@ -131,6 +137,26 @@ hall_plane_crossroad:
|
||||||
hall_plane_sidewalk:
|
hall_plane_sidewalk:
|
||||||
mov ebx, 72
|
mov ebx, 72
|
||||||
hall_plane_sample:
|
hall_plane_sample:
|
||||||
|
cmp brActive3D,0
|
||||||
|
je br_plane_sample_done
|
||||||
|
cmp hallLevel3D,HALL_BACKROOMS
|
||||||
|
jne br_plane_sample_done
|
||||||
|
mov eax,row
|
||||||
|
cmp eax,viewHorizon3D
|
||||||
|
jae br_plane_sample_done
|
||||||
|
mov ebx,BR_CEILING
|
||||||
|
mov eax,wx
|
||||||
|
shr eax,16
|
||||||
|
and eax,3
|
||||||
|
cmp eax,1
|
||||||
|
jne br_plane_sample_done
|
||||||
|
mov eax,wy
|
||||||
|
shr eax,16
|
||||||
|
and eax,3
|
||||||
|
cmp eax,1
|
||||||
|
jne br_plane_sample_done
|
||||||
|
mov ebx,BR_LAMP
|
||||||
|
br_plane_sample_done:
|
||||||
cmp outdoorRender3D, 0
|
cmp outdoorRender3D, 0
|
||||||
jne hall_plane_low_sample
|
jne hall_plane_low_sample
|
||||||
mov eax, row
|
mov eax, row
|
||||||
|
|
|
||||||
|
|
@ -120,6 +120,7 @@ StartNativeBlackjack3D PROC
|
||||||
mov cbDealerCount3D, 2
|
mov cbDealerCount3D, 2
|
||||||
mov cbCursor3D, 4
|
mov cbCursor3D, 4
|
||||||
invoke ShuffleCards3D, OFFSET cbDeck3D
|
invoke ShuffleCards3D, OFFSET cbDeck3D
|
||||||
|
call BackroomsBlackjackDeck3D
|
||||||
mov eax, cbDeck3D[0]
|
mov eax, cbDeck3D[0]
|
||||||
mov cbPlayer3D[0], eax
|
mov cbPlayer3D[0], eax
|
||||||
mov eax, cbDeck3D[4]
|
mov eax, cbDeck3D[4]
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,41 @@ clp_start_rows:
|
||||||
inc esi
|
inc esi
|
||||||
cmp esi,5
|
cmp esi,5
|
||||||
jb clp_start_column
|
jb clp_start_column
|
||||||
|
call BackroomsLuck3D
|
||||||
|
cmp eax,-1
|
||||||
|
je br_clover_fixed
|
||||||
|
mov ebx,eax
|
||||||
|
xor esi,esi
|
||||||
|
br_clover_row:
|
||||||
|
xor edi,edi
|
||||||
|
br_clover_column:
|
||||||
|
mov eax,esi
|
||||||
|
imul eax,2
|
||||||
|
add eax,edi
|
||||||
|
xor edx,edx
|
||||||
|
mov ecx,7
|
||||||
|
div ecx
|
||||||
|
cmp ebx,1
|
||||||
|
jne @F
|
||||||
|
mov edx,1
|
||||||
|
@@:
|
||||||
|
mov eax,esi
|
||||||
|
imul eax,5
|
||||||
|
add eax,edi
|
||||||
|
mov clpGrid3D[eax*4],edx
|
||||||
|
mov eax,clpSteps3D[edi*4]
|
||||||
|
add eax,esi
|
||||||
|
mov ecx,edi
|
||||||
|
shl ecx,8
|
||||||
|
lea ecx,clpTape3D[ecx]
|
||||||
|
mov [ecx+eax*4],edx
|
||||||
|
inc edi
|
||||||
|
cmp edi,5
|
||||||
|
jb br_clover_column
|
||||||
|
inc esi
|
||||||
|
cmp esi,3
|
||||||
|
jb br_clover_row
|
||||||
|
br_clover_fixed:
|
||||||
call SaveProgress3D
|
call SaveProgress3D
|
||||||
invoke PlayCasinoSound3D,OFFSET soundSlotSpin,0,1
|
invoke PlayCasinoSound3D,OFFSET soundSlotSpin,0,1
|
||||||
clp_start_done:
|
clp_start_done:
|
||||||
|
|
|
||||||
|
|
@ -308,6 +308,16 @@ coin_native_start:
|
||||||
invoke RandomRange3D,2
|
invoke RandomRange3D,2
|
||||||
inc eax
|
inc eax
|
||||||
mov coin3d_result,eax
|
mov coin3d_result,eax
|
||||||
|
call BackroomsLuck3D
|
||||||
|
cmp eax,-1
|
||||||
|
je br_coin_fixed
|
||||||
|
xor eax,1
|
||||||
|
mov ecx,coin3d_choice
|
||||||
|
dec ecx
|
||||||
|
xor eax,ecx
|
||||||
|
inc eax
|
||||||
|
mov coin3d_result,eax
|
||||||
|
br_coin_fixed:
|
||||||
call SaveProgress3D
|
call SaveProgress3D
|
||||||
invoke PlayCasinoSound3D,OFFSET soundCoin,0,1
|
invoke PlayCasinoSound3D,OFFSET soundCoin,0,1
|
||||||
call ClearKeys3D
|
call ClearKeys3D
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ dk_compact:
|
||||||
inc esi
|
inc esi
|
||||||
cmp esi, 52
|
cmp esi, 52
|
||||||
jb dk_compact
|
jb dk_compact
|
||||||
|
call BackroomsDurakDeck3D
|
||||||
mov eax, dkDeck3D[35*4]
|
mov eax, dkDeck3D[35*4]
|
||||||
mov durakTrumpCard, eax
|
mov durakTrumpCard, eax
|
||||||
invoke DurakCardSuit, eax
|
invoke DurakCardSuit, eax
|
||||||
|
|
|
||||||
|
|
@ -75,6 +75,7 @@ StartNativePoker3D PROC uses ebx esi
|
||||||
mov pkRaise3D, eax
|
mov pkRaise3D, eax
|
||||||
mov pkCurrent3D, eax
|
mov pkCurrent3D, eax
|
||||||
invoke ShuffleCards3D, OFFSET pkDeck3D
|
invoke ShuffleCards3D, OFFSET pkDeck3D
|
||||||
|
call BackroomsPokerDeck3D
|
||||||
mov esi, pkButton3D
|
mov esi, pkButton3D
|
||||||
xor esi, 1
|
xor esi, 1
|
||||||
shl esi, 3 ; first card goes to the non-button player
|
shl esi, 3 ; first card goes to the non-button player
|
||||||
|
|
|
||||||
|
|
@ -69,11 +69,22 @@ StartNativeSlots3D PROC uses ebx esi
|
||||||
mov slotLeaveAfter3D,0
|
mov slotLeaveAfter3D,0
|
||||||
mov slotError3D,0
|
mov slotError3D,0
|
||||||
mov slotEffects3D,0
|
mov slotEffects3D,0
|
||||||
|
call BackroomsLuck3D
|
||||||
|
mov brSlotLuck3D,eax
|
||||||
xor esi,esi
|
xor esi,esi
|
||||||
slot_start_reel:
|
slot_start_reel:
|
||||||
mov eax,slotStops3D[esi*4]
|
mov eax,slotStops3D[esi*4]
|
||||||
mov slotStartStops3D[esi*4],eax
|
mov slotStartStops3D[esi*4],eax
|
||||||
invoke RandomRange3D,20
|
invoke RandomRange3D,20
|
||||||
|
cmp brSlotLuck3D,-1
|
||||||
|
je br_slot_target
|
||||||
|
mov eax,0
|
||||||
|
cmp brSlotLuck3D,1
|
||||||
|
je br_slot_target
|
||||||
|
; Distinct symbols, with no refund pair, for the unlucky 10%.
|
||||||
|
mov eax,esi
|
||||||
|
inc eax
|
||||||
|
br_slot_target:
|
||||||
mov slotTargets3D[esi*4],eax
|
mov slotTargets3D[esi*4],eax
|
||||||
mov edx,slotStrip3D[eax*4]
|
mov edx,slotStrip3D[eax*4]
|
||||||
mov slotReel1[esi*4],edx
|
mov slotReel1[esi*4],edx
|
||||||
|
|
|
||||||
|
|
@ -352,6 +352,7 @@ wheel_regular_spin:
|
||||||
mov roulState, 1
|
mov roulState, 1
|
||||||
mov wheelTime3D, 0
|
mov wheelTime3D, 0
|
||||||
invoke RandomRange3D, 37
|
invoke RandomRange3D, 37
|
||||||
|
invoke BackroomsWheelLuck3D,eax
|
||||||
mov wheelResult3D, eax
|
mov wheelResult3D, eax
|
||||||
call SaveProgress3D
|
call SaveProgress3D
|
||||||
invoke PlayCasinoSound3D, OFFSET soundRoulette,0,1
|
invoke PlayCasinoSound3D, OFFSET soundRoulette,0,1
|
||||||
|
|
|
||||||
|
|
@ -137,6 +137,12 @@ event_key_up:
|
||||||
cmp ecx, 255
|
cmp ecx, 255
|
||||||
ja event_done
|
ja event_done
|
||||||
mov keys3D[ecx], 0
|
mov keys3D[ecx], 0
|
||||||
|
cmp ecx,57h
|
||||||
|
je event_entry_release
|
||||||
|
cmp ecx,26h
|
||||||
|
jne event_done
|
||||||
|
event_entry_release:
|
||||||
|
mov brEntryHold3D,0
|
||||||
jmp event_done
|
jmp event_done
|
||||||
event_fullscreen:
|
event_fullscreen:
|
||||||
test lp, 40000000h
|
test lp, 40000000h
|
||||||
|
|
@ -144,6 +150,7 @@ event_fullscreen:
|
||||||
call ToggleFullscreen3D
|
call ToggleFullscreen3D
|
||||||
jmp event_done
|
jmp event_done
|
||||||
event_focus_lost:
|
event_focus_lost:
|
||||||
|
mov brEntryHold3D,0
|
||||||
mov dtHolding3D,0
|
mov dtHolding3D,0
|
||||||
mov dtMouseReleased3D,0
|
mov dtMouseReleased3D,0
|
||||||
call ClearKeys3D
|
call ClearKeys3D
|
||||||
|
|
@ -505,9 +512,12 @@ UpdateCamera3D ENDP
|
||||||
|
|
||||||
; Four corners of a 0.3-tile-wide body; bounds checked before every map read.
|
; 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
|
CanWalk3D PROC uses ebx esi edi px:DWORD, py:DWORD
|
||||||
|
cmp brActive3D,0
|
||||||
|
jne br_generic_collision
|
||||||
invoke CanWalkHall3D, px, py
|
invoke CanWalkHall3D, px, py
|
||||||
test eax, eax
|
test eax, eax
|
||||||
jz walk_blocked
|
jz walk_blocked
|
||||||
|
br_generic_collision:
|
||||||
mov esi, -9830
|
mov esi, -9830
|
||||||
walk_corner_x:
|
walk_corner_x:
|
||||||
mov edi, -9830
|
mov edi, -9830
|
||||||
|
|
@ -550,6 +560,8 @@ LoadProgress3D PROC uses ebx
|
||||||
mov charmSkullUses, 0
|
mov charmSkullUses, 0
|
||||||
mov charmDevilUses, 0
|
mov charmDevilUses, 0
|
||||||
mov charmEnabledMask3D,7
|
mov charmEnabledMask3D,7
|
||||||
|
mov brOwned3D,0
|
||||||
|
mov brEnabled3D,1
|
||||||
invoke CreateFileA, OFFSET savePath3D, 80000000h, 1, 0, 3, 80h, 0
|
invoke CreateFileA, OFFSET savePath3D, 80000000h, 1, 0, 3, 80h, 0
|
||||||
cmp eax, -1
|
cmp eax, -1
|
||||||
je progress_loaded
|
je progress_loaded
|
||||||
|
|
@ -566,7 +578,23 @@ LoadProgress3D PROC uses ebx
|
||||||
cmp eax,saveData3D[36]
|
cmp eax,saveData3D[36]
|
||||||
jne progress_loaded
|
jne progress_loaded
|
||||||
mov eax,saveData3D[32]
|
mov eax,saveData3D[32]
|
||||||
mov charmEnabledMask3D,eax
|
test eax,0FFFCFFF0h
|
||||||
|
jnz progress_loaded
|
||||||
|
test eax,20000h
|
||||||
|
jz @F
|
||||||
|
test eax,10000h
|
||||||
|
jz progress_loaded
|
||||||
|
@@:
|
||||||
|
mov ecx,eax
|
||||||
|
and ecx,15
|
||||||
|
mov charmEnabledMask3D,ecx
|
||||||
|
shr eax,16
|
||||||
|
and eax,1
|
||||||
|
mov brOwned3D,eax
|
||||||
|
mov eax,saveData3D[32]
|
||||||
|
shr eax,17
|
||||||
|
and eax,1
|
||||||
|
mov brEnabled3D,eax
|
||||||
jmp progress_version_ok
|
jmp progress_version_ok
|
||||||
progress_legacy_version:
|
progress_legacy_version:
|
||||||
cmp saveData3D, 33443343h
|
cmp saveData3D, 33443343h
|
||||||
|
|
@ -653,7 +681,15 @@ SaveProgress3D PROC uses ebx
|
||||||
mov saveData3D[24], eax
|
mov saveData3D[24], eax
|
||||||
mov eax, charmDevilUses
|
mov eax, charmDevilUses
|
||||||
mov saveData3D[28], eax
|
mov saveData3D[28], eax
|
||||||
mov eax,charmEnabledMask3D
|
mov eax,brOwned3D
|
||||||
|
and eax,1
|
||||||
|
shl eax,16
|
||||||
|
mov ecx,brEnabled3D
|
||||||
|
and ecx,brOwned3D
|
||||||
|
and ecx,1
|
||||||
|
shl ecx,17
|
||||||
|
or eax,ecx
|
||||||
|
or eax,charmEnabledMask3D
|
||||||
mov saveData3D[32],eax
|
mov saveData3D[32],eax
|
||||||
invoke PreviewArtifactSignature3D,OFFSET saveData3D
|
invoke PreviewArtifactSignature3D,OFFSET saveData3D
|
||||||
mov saveData3D[36],eax
|
mov saveData3D[36],eax
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,10 @@ rr_party_cartridge:
|
||||||
jb rr_party_cartridge
|
jb rr_party_cartridge
|
||||||
invoke RandomRange3D,6
|
invoke RandomRange3D,6
|
||||||
mov rr3d_chamber,eax
|
mov rr3d_chamber,eax
|
||||||
|
cmp rrPartyReloads3D,0
|
||||||
|
je @F
|
||||||
|
call BackroomsRussianCylinder3D
|
||||||
|
@@:
|
||||||
inc rrPartyReloads3D
|
inc rrPartyReloads3D
|
||||||
ret
|
ret
|
||||||
RRLoadCylinder3D ENDP
|
RRLoadCylinder3D ENDP
|
||||||
|
|
|
||||||
|
|
@ -98,9 +98,11 @@ StartRussianRound3D PROC uses ebx esi
|
||||||
sub bankroll, eax
|
sub bankroll, eax
|
||||||
mov rr3d_payout, 0
|
mov rr3d_payout, 0
|
||||||
mov rr3d_error, 0
|
mov rr3d_error, 0
|
||||||
|
mov brRussianLuck3D,-1
|
||||||
call RRLoadCylinder3D
|
call RRLoadCylinder3D
|
||||||
invoke RandomRange3D, rrPartySize3D
|
invoke RandomRange3D, rrPartySize3D
|
||||||
mov rr3d_turn, eax
|
mov rr3d_turn, eax
|
||||||
|
call BackroomsRussianLuck3D
|
||||||
mov rr3d_state, RR_LOAD
|
mov rr3d_state, RR_LOAD
|
||||||
mov rr3d_timer, 0
|
mov rr3d_timer, 0
|
||||||
invoke PlayCasinoSound3D, OFFSET rrLoadSound3D, 0, 20003h
|
invoke PlayCasinoSound3D, OFFSET rrLoadSound3D, 0, 20003h
|
||||||
|
|
|
||||||
|
|
@ -246,6 +246,16 @@ BuyScratch3D PROC uses ebx esi edi
|
||||||
jmp scratch_buy_save
|
jmp scratch_buy_save
|
||||||
@@:
|
@@:
|
||||||
invoke RandomRange3D,1000
|
invoke RandomRange3D,1000
|
||||||
|
push eax
|
||||||
|
call BackroomsLuck3D
|
||||||
|
pop edx
|
||||||
|
cmp eax,-1
|
||||||
|
je br_scratch_original
|
||||||
|
imul eax,650
|
||||||
|
jmp br_scratch_fixed
|
||||||
|
br_scratch_original:
|
||||||
|
mov eax,edx
|
||||||
|
br_scratch_fixed:
|
||||||
cmp eax,600
|
cmp eax,600
|
||||||
jb scratch_losing_bag
|
jb scratch_losing_bag
|
||||||
xor esi,esi
|
xor esi,esi
|
||||||
|
|
|
||||||
|
|
@ -321,6 +321,16 @@ portrait_fill:
|
||||||
jb portrait_fill
|
jb portrait_fill
|
||||||
mov scrPortraitOutcome3D,0
|
mov scrPortraitOutcome3D,0
|
||||||
invoke RandomRange3D,1000
|
invoke RandomRange3D,1000
|
||||||
|
push eax
|
||||||
|
call BackroomsLuck3D
|
||||||
|
pop edx
|
||||||
|
cmp eax,-1
|
||||||
|
je br_portrait_original
|
||||||
|
imul eax,920
|
||||||
|
jmp br_portrait_fixed
|
||||||
|
br_portrait_original:
|
||||||
|
mov eax,edx
|
||||||
|
br_portrait_fixed:
|
||||||
cmp eax,600
|
cmp eax,600
|
||||||
jb portrait_build_payout
|
jb portrait_build_payout
|
||||||
mov ebx,eax
|
mov ebx,eax
|
||||||
|
|
|
||||||
32
tools/generators/make_backrooms_assets.py
Normal file
32
tools/generators/make_backrooms_assets.py
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
"""Offline-only texture packing; runtime generation/rendering stays MASM."""
|
||||||
|
from pathlib import Path
|
||||||
|
import struct
|
||||||
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
source = ROOT / 'assets/sprites/backrooms'
|
||||||
|
frames = []
|
||||||
|
for name in ('wall', 'floor', 'ceiling', 'ceiling_lamp'):
|
||||||
|
image = Image.open(source / f'Backrooms_{name}.jpg').convert('RGBA')
|
||||||
|
image = image.resize((128, 128), Image.Resampling.LANCZOS)
|
||||||
|
frames.append(image.tobytes('raw', 'BGRA'))
|
||||||
|
# Exit is an offline-generated material, not a second game implementation.
|
||||||
|
image = Image.new('RGBA', (128, 128), (36, 60, 38, 255))
|
||||||
|
draw = ImageDraw.Draw(image)
|
||||||
|
draw.rectangle((9, 4, 119, 127), fill=(61, 84, 55), outline=(143, 160, 98), width=5)
|
||||||
|
# Eye-level sign stays visible even when standing in the exit cell.
|
||||||
|
draw.rectangle((18, 45, 110, 73), fill=(32, 170, 77))
|
||||||
|
font = ImageFont.truetype('arialbd.ttf', 23)
|
||||||
|
draw.text((64, 59), 'EXIT', fill='white', font=font, anchor='mm')
|
||||||
|
draw.rectangle((94, 76, 99, 82), fill=(240, 211, 101))
|
||||||
|
frames.append(image.tobytes('raw', 'BGRA'))
|
||||||
|
out = source / 'materials.bin'
|
||||||
|
out.write_bytes(struct.pack('<5I', 0x314D4E41, 128, 128, len(frames), len(frames)*65536) + b''.join(frames))
|
||||||
|
print(f'Packed {len(frames)} Backrooms materials: {out.relative_to(ROOT)}')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
391
tools/tests/backrooms_extended_test.inc
Normal file
391
tools/tests/backrooms_extended_test.inc
Normal file
|
|
@ -0,0 +1,391 @@
|
||||||
|
; Additional native invariants. No player files or runtime writes.
|
||||||
|
RunBackroomsExtendedTest3D PROC uses ebx esi edi
|
||||||
|
local rounds:DWORD,wins:DWORD,kind:DWORD,party:DWORD,bullets:DWORD,steps:DWORD
|
||||||
|
mov brOwned3D,1
|
||||||
|
mov brEnabled3D,0
|
||||||
|
mov rngSeed3D,87654
|
||||||
|
call BackroomsLuck3D
|
||||||
|
cmp eax,-1
|
||||||
|
jne br_extended_fail
|
||||||
|
cmp rngSeed3D,87654
|
||||||
|
jne br_extended_fail
|
||||||
|
mov brEnabled3D,1
|
||||||
|
mov obsActive3D,1
|
||||||
|
call BackroomsLuck3D
|
||||||
|
cmp eax,-1
|
||||||
|
jne br_extended_fail
|
||||||
|
mov obsActive3D,0
|
||||||
|
mov brTestStage,111
|
||||||
|
; Actual blackjack party dealing, all guest counts.
|
||||||
|
mov party,0
|
||||||
|
br_ext_bj_party:
|
||||||
|
mov wins,0
|
||||||
|
mov rounds,1000
|
||||||
|
br_ext_bj_round:
|
||||||
|
mov bankroll,1000000
|
||||||
|
mov eax,party
|
||||||
|
mov cbBotCount3D,eax
|
||||||
|
mov cbState3D,CB_IDLE
|
||||||
|
call StartNativeBlackjack3D
|
||||||
|
cmp cbPlayerScore3D,21
|
||||||
|
jne @F
|
||||||
|
inc wins
|
||||||
|
cmp cbDealerScore3D,19
|
||||||
|
jne br_extended_fail
|
||||||
|
@@:
|
||||||
|
dec rounds
|
||||||
|
jnz br_ext_bj_round
|
||||||
|
cmp wins,860
|
||||||
|
jb br_extended_fail
|
||||||
|
cmp wins,940
|
||||||
|
ja br_extended_fail
|
||||||
|
inc party
|
||||||
|
cmp party,4
|
||||||
|
jb br_ext_bj_party
|
||||||
|
mov cbBotCount3D,0
|
||||||
|
; Every scratch design, generated by the actual purchase path.
|
||||||
|
mov scrReady3D,1
|
||||||
|
mov brTestStage,112
|
||||||
|
mov kind,0
|
||||||
|
br_ext_ticket_type:
|
||||||
|
mov eax,kind
|
||||||
|
add eax,120
|
||||||
|
mov brTestStage,eax
|
||||||
|
mov wins,0
|
||||||
|
mov rounds,1000
|
||||||
|
br_ext_ticket:
|
||||||
|
mov bankroll,1000000
|
||||||
|
mov scrState3D,0
|
||||||
|
mov scrPriceIndex3D,0
|
||||||
|
mov eax,kind
|
||||||
|
mov scrType3D,eax
|
||||||
|
call BuyScratch3D
|
||||||
|
mov eax,scrGross3D
|
||||||
|
test eax,eax
|
||||||
|
jz @F
|
||||||
|
inc wins
|
||||||
|
@@:
|
||||||
|
cmp kind,4
|
||||||
|
jb @F
|
||||||
|
call ScratchPortraitPayout3D
|
||||||
|
cmp eax,scrGross3D
|
||||||
|
jne br_extended_fail
|
||||||
|
@@:
|
||||||
|
dec rounds
|
||||||
|
jnz br_ext_ticket
|
||||||
|
cmp wins,860
|
||||||
|
jb br_extended_fail
|
||||||
|
cmp wins,940
|
||||||
|
ja br_extended_fail
|
||||||
|
inc kind
|
||||||
|
cmp kind,7
|
||||||
|
jb br_ext_ticket_type
|
||||||
|
; Roulette: a real straight-up bet, including actual multiplier matching.
|
||||||
|
lea edi,wheelBets3D
|
||||||
|
mov brTestStage,113
|
||||||
|
xor eax,eax
|
||||||
|
mov ecx,49
|
||||||
|
rep stosd
|
||||||
|
mov wheelBets3D[7*4],100
|
||||||
|
mov wheelStake3D,100
|
||||||
|
mov wins,0
|
||||||
|
mov rounds,1000
|
||||||
|
br_ext_wheel:
|
||||||
|
invoke BackroomsWheelLuck3D,0
|
||||||
|
cmp eax,36
|
||||||
|
ja br_extended_fail
|
||||||
|
invoke WheelBetMultiplier3D,7,eax
|
||||||
|
test eax,eax
|
||||||
|
jz @F
|
||||||
|
inc wins
|
||||||
|
@@:
|
||||||
|
dec rounds
|
||||||
|
jnz br_ext_wheel
|
||||||
|
cmp wins,860
|
||||||
|
jb br_extended_fail
|
||||||
|
cmp wins,940
|
||||||
|
ja br_extended_fail
|
||||||
|
; Durak: 36 distinct legal cards, correctly exposed trump on favorable deals.
|
||||||
|
mov rounds,1000
|
||||||
|
br_ext_durak:
|
||||||
|
mov brTestStage,114
|
||||||
|
mov bankroll,1000000
|
||||||
|
mov dkState3D,DK_IDLE
|
||||||
|
call StartNativeDurak3D
|
||||||
|
xor esi,esi
|
||||||
|
br_ext_durak_card:
|
||||||
|
mov eax,dkDeck3D[esi*4]
|
||||||
|
cmp eax,52
|
||||||
|
jae br_extended_fail
|
||||||
|
invoke DurakCardRank,eax
|
||||||
|
cmp eax,4
|
||||||
|
jb br_extended_fail
|
||||||
|
lea edi,[esi+1]
|
||||||
|
br_ext_durak_unique:
|
||||||
|
cmp edi,36
|
||||||
|
jae br_ext_durak_next
|
||||||
|
mov eax,dkDeck3D[edi*4]
|
||||||
|
cmp eax,dkDeck3D[esi*4]
|
||||||
|
je br_extended_fail
|
||||||
|
inc edi
|
||||||
|
jmp br_ext_durak_unique
|
||||||
|
br_ext_durak_next:
|
||||||
|
inc esi
|
||||||
|
cmp esi,36
|
||||||
|
jb br_ext_durak_card
|
||||||
|
cmp dkDeck3D,33
|
||||||
|
jne @F
|
||||||
|
cmp durakTrumpSuit,2
|
||||||
|
jne br_extended_fail
|
||||||
|
@@:
|
||||||
|
dec rounds
|
||||||
|
jnz br_ext_durak
|
||||||
|
; Russian roulette: real party elimination/reload rules, all 1..3 guests/bullets.
|
||||||
|
mov party,1
|
||||||
|
mov brTestStage,115
|
||||||
|
br_ext_rr_party:
|
||||||
|
mov bullets,1
|
||||||
|
br_ext_rr_bullets:
|
||||||
|
mov rounds,300
|
||||||
|
mov wins,0
|
||||||
|
br_ext_rr_round:
|
||||||
|
mov brTestStage,151
|
||||||
|
mov eax,party
|
||||||
|
mov rrPartyCount3D,eax
|
||||||
|
call RRPartyReset3D
|
||||||
|
mov eax,bullets
|
||||||
|
mov rr3d_bullets,eax
|
||||||
|
mov rrPartySettled3D,0
|
||||||
|
mov rrPartyStake3D,50
|
||||||
|
mov rr3d_bet,50
|
||||||
|
mov rr3d_turn,0
|
||||||
|
call BackroomsRussianLuck3D
|
||||||
|
mov rrPartyReloads3D,1
|
||||||
|
mov steps,0
|
||||||
|
br_ext_rr_shot:
|
||||||
|
mov eax,rr3d_mask
|
||||||
|
mov ecx,rr3d_chamber
|
||||||
|
bt eax,ecx
|
||||||
|
jnc br_ext_rr_advance
|
||||||
|
call RRPartyHit3D
|
||||||
|
cmp rrPartySettled3D,0
|
||||||
|
jne br_ext_rr_outcome
|
||||||
|
br_ext_rr_advance:
|
||||||
|
call RRPartyNext3D
|
||||||
|
inc steps
|
||||||
|
cmp steps,100
|
||||||
|
jae br_extended_fail
|
||||||
|
jmp br_ext_rr_shot
|
||||||
|
br_ext_rr_outcome:
|
||||||
|
mov brTestStage,152
|
||||||
|
cmp rr3d_state,RR_WIN
|
||||||
|
jne @F
|
||||||
|
inc wins
|
||||||
|
cmp brRussianLuck3D,1
|
||||||
|
jne br_extended_fail
|
||||||
|
@@:
|
||||||
|
cmp brRussianLuck3D,1
|
||||||
|
jne @F
|
||||||
|
mov eax,party
|
||||||
|
imul eax,10
|
||||||
|
add eax,bullets
|
||||||
|
add eax,200
|
||||||
|
mov brTestStage,eax
|
||||||
|
cmp rr3d_state,RR_WIN
|
||||||
|
jne br_extended_fail
|
||||||
|
@@:
|
||||||
|
dec rounds
|
||||||
|
jnz br_ext_rr_round
|
||||||
|
mov brTestStage,154
|
||||||
|
cmp wins,240
|
||||||
|
jb br_extended_fail
|
||||||
|
cmp wins,295
|
||||||
|
ja br_extended_fail
|
||||||
|
inc bullets
|
||||||
|
cmp bullets,4
|
||||||
|
jb br_ext_rr_bullets
|
||||||
|
inc party
|
||||||
|
cmp party,4
|
||||||
|
jb br_ext_rr_party
|
||||||
|
; Buckshot permutations retain cartridge counts and valid binary identities.
|
||||||
|
mov rounds,1000
|
||||||
|
br_ext_bs:
|
||||||
|
mov brTestStage,116
|
||||||
|
call BuckshotReload3D
|
||||||
|
xor edi,edi
|
||||||
|
xor esi,esi
|
||||||
|
br_ext_bs_shell:
|
||||||
|
mov eax,bs3d_shells[esi*4]
|
||||||
|
cmp eax,1
|
||||||
|
ja br_extended_fail
|
||||||
|
add edi,eax
|
||||||
|
inc esi
|
||||||
|
cmp esi,bs3d_shellCount
|
||||||
|
jb br_ext_bs_shell
|
||||||
|
cmp edi,bs3d_liveCount
|
||||||
|
jne br_extended_fail
|
||||||
|
add edi,bs3d_blankCount
|
||||||
|
cmp edi,bs3d_shellCount
|
||||||
|
jne br_extended_fail
|
||||||
|
dec rounds
|
||||||
|
jnz br_ext_bs
|
||||||
|
xor eax,eax
|
||||||
|
ret
|
||||||
|
br_extended_fail:
|
||||||
|
mov eax,brTestStage
|
||||||
|
ret
|
||||||
|
RunBackroomsExtendedTest3D ENDP
|
||||||
|
|
||||||
|
RunBackroomsSaveTest3D PROC uses ebx esi edi
|
||||||
|
; Signed but impossible enabled-without-owned flag must be rejected.
|
||||||
|
mov DWORD PTR saveBuffer[304],20002h
|
||||||
|
invoke ArtifactSaveSignature3D,OFFSET saveBuffer
|
||||||
|
mov DWORD PTR saveBuffer[308],eax
|
||||||
|
invoke ValidateArtifactSave3D,OFFSET saveBuffer
|
||||||
|
test eax,eax
|
||||||
|
jnz br_save_fail
|
||||||
|
; Native preview keeps its 40-byte, signed backward-compatible layout.
|
||||||
|
invoke CopyCString,OFFSET savePath3D,OFFSET brTestPreviewPath
|
||||||
|
mov nativeProfileActive3D,0
|
||||||
|
mov arrivalConfirmed3D,1
|
||||||
|
mov brOwned3D,1
|
||||||
|
mov brEnabled3D,1
|
||||||
|
call SaveProgress3D
|
||||||
|
mov brOwned3D,0
|
||||||
|
mov brEnabled3D,0
|
||||||
|
call LoadProgress3D
|
||||||
|
cmp brOwned3D,1
|
||||||
|
jne br_save_fail
|
||||||
|
cmp brEnabled3D,1
|
||||||
|
jne br_save_fail
|
||||||
|
mov brActive3D,1
|
||||||
|
mov brEnabled3D,0
|
||||||
|
invoke LeaveBackrooms3D,1
|
||||||
|
cmp brOwned3D,1
|
||||||
|
jne br_save_fail
|
||||||
|
cmp brEnabled3D,0
|
||||||
|
jne br_save_fail
|
||||||
|
call LoadProgress3D
|
||||||
|
cmp brEnabled3D,0
|
||||||
|
jne br_save_fail
|
||||||
|
xor eax,eax
|
||||||
|
ret
|
||||||
|
br_save_fail:
|
||||||
|
mov eax,102
|
||||||
|
ret
|
||||||
|
RunBackroomsSaveTest3D ENDP
|
||||||
|
|
||||||
|
.data
|
||||||
|
brContextModes dd MODE_COIN,MODE_DICE,MODE_SLOTS,MODE_BLACKJACK,MODE_ROULETTE,MODE_CLOVER
|
||||||
|
brContextMap db 1024 dup(0)
|
||||||
|
.code
|
||||||
|
RunBackroomsContextTest3D PROC uses ebx esi edi
|
||||||
|
local index:DWORD,x:DWORD,y:DWORD
|
||||||
|
call GenerateBackrooms3D
|
||||||
|
mov brActive3D,1
|
||||||
|
mov brCutscene3D,0
|
||||||
|
mov hallLevel3D,HALL_BACKROOMS
|
||||||
|
mov worldMap3D,OFFSET brMap3D
|
||||||
|
lea esi,brMap3D
|
||||||
|
lea edi,brContextMap
|
||||||
|
mov ecx,256
|
||||||
|
rep movsd
|
||||||
|
mov index,0
|
||||||
|
br_context_game:
|
||||||
|
mov esi,index
|
||||||
|
mov ebx,brGameCells3D[esi*4]
|
||||||
|
mov eax,ebx
|
||||||
|
and eax,31
|
||||||
|
shl eax,16
|
||||||
|
add eax,FP_HALF
|
||||||
|
mov x,eax
|
||||||
|
mov playerX,eax
|
||||||
|
mov eax,ebx
|
||||||
|
shr eax,5
|
||||||
|
shl eax,16
|
||||||
|
add eax,FP_HALF
|
||||||
|
mov y,eax
|
||||||
|
mov playerY,eax
|
||||||
|
mov playerAngle,77
|
||||||
|
mov engineMode,MODE_WALK
|
||||||
|
mov mouseLocked3D,0
|
||||||
|
mov deltaTime3D,16
|
||||||
|
call ClearKeys3D
|
||||||
|
mov pressedKeys3D[45h],1
|
||||||
|
call HandleBackrooms3D
|
||||||
|
mov esi,index
|
||||||
|
mov eax,brContextModes[esi*4]
|
||||||
|
cmp eax,engineMode
|
||||||
|
jne br_context_fail
|
||||||
|
cmp eax,MODE_DICE
|
||||||
|
jne @F
|
||||||
|
call DiceEscape3D
|
||||||
|
jmp br_context_returned
|
||||||
|
@@:
|
||||||
|
call CardTableEscape3D
|
||||||
|
br_context_returned:
|
||||||
|
cmp engineMode,MODE_WALK
|
||||||
|
jne br_context_fail
|
||||||
|
mov eax,x
|
||||||
|
cmp playerX,eax
|
||||||
|
jne br_context_fail
|
||||||
|
mov eax,y
|
||||||
|
cmp playerY,eax
|
||||||
|
jne br_context_fail
|
||||||
|
cmp playerAngle,77
|
||||||
|
jne br_context_fail
|
||||||
|
cmp worldMap3D,OFFSET brMap3D
|
||||||
|
jne br_context_fail
|
||||||
|
cmp hallLevel3D,HALL_BACKROOMS
|
||||||
|
jne br_context_fail
|
||||||
|
lea esi,brMap3D
|
||||||
|
lea edi,brContextMap
|
||||||
|
mov ecx,1024
|
||||||
|
repe cmpsb
|
||||||
|
jne br_context_fail
|
||||||
|
inc index
|
||||||
|
cmp index,6
|
||||||
|
jb br_context_game
|
||||||
|
mov brActive3D,0
|
||||||
|
mov hallLevel3D,0
|
||||||
|
mov worldMap3D,OFFSET casinoMap
|
||||||
|
xor eax,eax
|
||||||
|
ret
|
||||||
|
br_context_fail:
|
||||||
|
mov eax,103
|
||||||
|
ret
|
||||||
|
RunBackroomsContextTest3D ENDP
|
||||||
|
|
||||||
|
RunBackroomsWallTest3D PROC uses esi
|
||||||
|
mov brActive3D,0
|
||||||
|
mov engineMode,MODE_WALK
|
||||||
|
mov mouseLocked3D,0
|
||||||
|
mov playerX,16*FP_1+FP_HALF
|
||||||
|
mov playerY,27*FP_1+FP_HALF
|
||||||
|
mov playerAngle,128
|
||||||
|
mov deltaTime3D,16
|
||||||
|
mov brEntryHold3D,0
|
||||||
|
call ClearKeys3D
|
||||||
|
mov keys3D[57h],1
|
||||||
|
mov esi,500
|
||||||
|
br_wall_walk:
|
||||||
|
call HandlePlayerInput
|
||||||
|
call BackroomsEntry3D
|
||||||
|
cmp brActive3D,1
|
||||||
|
je br_wall_entered
|
||||||
|
dec esi
|
||||||
|
jnz br_wall_walk
|
||||||
|
mov eax,104
|
||||||
|
ret
|
||||||
|
br_wall_entered:
|
||||||
|
cmp playerY,30*FP_1
|
||||||
|
jae br_wall_fail
|
||||||
|
cmp playerY,30*FP_1-15000
|
||||||
|
jb br_wall_fail
|
||||||
|
call ClearKeys3D
|
||||||
|
xor eax,eax
|
||||||
|
ret
|
||||||
|
br_wall_fail:
|
||||||
|
mov eax,105
|
||||||
|
ret
|
||||||
|
RunBackroomsWallTest3D ENDP
|
||||||
288
tools/tests/backrooms_test.inc
Normal file
288
tools/tests/backrooms_test.inc
Normal file
|
|
@ -0,0 +1,288 @@
|
||||||
|
.data
|
||||||
|
brTestPath db 'build\scratch\backrooms-native.bin',0
|
||||||
|
brTestFrame db 'build\scratch\backrooms-frame.bin',0
|
||||||
|
brTestExitFrame db 'build\scratch\backrooms-exit.bin',0
|
||||||
|
brTestIo dd 0
|
||||||
|
brTestSeeds dd 256
|
||||||
|
brTestStage dd 91
|
||||||
|
brTestRows dd 0
|
||||||
|
brTestLuckPath db 'build\scratch\backrooms-luck.bin',0
|
||||||
|
brTestProfileDir db 'build\scratch',0
|
||||||
|
brTestProfileName db 'backrooms-profile.dat',0
|
||||||
|
brTestProfilePath db 'build\scratch\backrooms-profile.dat',0
|
||||||
|
brTestPreviewPath db 'build\scratch\br-preview.dat',0
|
||||||
|
brTestFacesPath db 'build\scratch\backrooms-exit-faces.bin',0
|
||||||
|
brTestFaceNeighbors dd -32,32,-1,1
|
||||||
|
brTestFaceAngles dd 384,128,256,0
|
||||||
|
.code
|
||||||
|
include tools/tests/backrooms_extended_test.inc
|
||||||
|
RunBackroomsTest3D PROC uses ebx esi edi
|
||||||
|
invoke CreateFileA,OFFSET brTestPath,40000000h,0,0,2,80h,0
|
||||||
|
mov ebx,eax
|
||||||
|
cmp eax,-1
|
||||||
|
je br_test_fail
|
||||||
|
mov rngSeed3D,12345
|
||||||
|
br_test_seed:
|
||||||
|
call GenerateBackrooms3D
|
||||||
|
invoke WriteFile,ebx,OFFSET brMap3D,1024,OFFSET brTestIo,0
|
||||||
|
invoke WriteFile,ebx,OFFSET brExitCell3D,4,OFFSET brTestIo,0
|
||||||
|
invoke WriteFile,ebx,OFFSET brGameCells3D,24,OFFSET brTestIo,0
|
||||||
|
dec brTestSeeds
|
||||||
|
jnz br_test_seed
|
||||||
|
invoke CloseHandle,ebx
|
||||||
|
mov brTestStage,92
|
||||||
|
mov obsActive3D,0
|
||||||
|
mov tournamentMode,0
|
||||||
|
mov brActive3D,0
|
||||||
|
mov engineMode,MODE_WALK
|
||||||
|
mov hallLevel3D,0
|
||||||
|
mov playerX,16*FP_1+FP_HALF
|
||||||
|
mov playerY,30*FP_1-11000
|
||||||
|
mov playerAngle,128
|
||||||
|
mov keys3D[57h],1
|
||||||
|
mov deltaTime3D,50
|
||||||
|
mov esi,39
|
||||||
|
br_test_entry:
|
||||||
|
call BackroomsEntry3D
|
||||||
|
cmp brActive3D,0
|
||||||
|
jne br_test_fail
|
||||||
|
dec esi
|
||||||
|
jnz br_test_entry
|
||||||
|
cmp brEntryHold3D,1950
|
||||||
|
jne br_test_fail
|
||||||
|
mov brTestStage,93
|
||||||
|
mov playerAngle,129
|
||||||
|
call BackroomsEntry3D
|
||||||
|
cmp brEntryHold3D,0
|
||||||
|
jne br_test_fail
|
||||||
|
mov playerAngle,128
|
||||||
|
call BackroomsEntry3D
|
||||||
|
cmp brEntryHold3D,50
|
||||||
|
jne br_test_fail
|
||||||
|
mov keys3D[57h],0
|
||||||
|
call BackroomsEntry3D
|
||||||
|
cmp brEntryHold3D,0
|
||||||
|
jne br_test_fail
|
||||||
|
mov brTestStage,94
|
||||||
|
mov keys3D[57h],1
|
||||||
|
mov brEntryHold3D,1950
|
||||||
|
mov brEntryAngle3D,128
|
||||||
|
call BackroomsEntry3D
|
||||||
|
cmp brActive3D,1
|
||||||
|
jne br_test_fail
|
||||||
|
cmp brCutscene3D,1
|
||||||
|
jne br_test_fail
|
||||||
|
mov brClock3D,900
|
||||||
|
call HandleBackrooms3D
|
||||||
|
mov brTestStage,95
|
||||||
|
invoke CanWalk3D,FP_1+FP_HALF,FP_1+FP_HALF
|
||||||
|
cmp eax,1
|
||||||
|
jne br_test_fail
|
||||||
|
invoke CanWalk3D,FP_HALF,FP_HALF
|
||||||
|
test eax,eax
|
||||||
|
jnz br_test_fail
|
||||||
|
mov brTestStage,96
|
||||||
|
; Set up standard projection LUT through the real hall initializer first.
|
||||||
|
call InitHall3D
|
||||||
|
call RunBackroomsWallTest3D
|
||||||
|
test eax,eax
|
||||||
|
jnz br_test_return
|
||||||
|
mov brActive3D,1
|
||||||
|
mov hallLevel3D,HALL_BACKROOMS
|
||||||
|
mov worldMap3D,OFFSET brMap3D
|
||||||
|
mov floorTexture3D,BR_FLOOR
|
||||||
|
mov viewHorizon3D,HALF_H
|
||||||
|
mov brClock3D,8100
|
||||||
|
mov brDialogue3D,2500
|
||||||
|
mov brCutscene3D,0
|
||||||
|
mov playerX,FP_1+FP_HALF
|
||||||
|
mov playerY,FP_1+FP_HALF
|
||||||
|
mov playerAngle,64
|
||||||
|
call RenderBackrooms3D
|
||||||
|
invoke CreateFileA,OFFSET brTestFrame,40000000h,0,0,2,80h,0
|
||||||
|
mov ebx,eax
|
||||||
|
invoke WriteFile,ebx,OFFSET screenBuffer,SCREEN_SIZE*4,OFFSET brTestIo,0
|
||||||
|
invoke CloseHandle,ebx
|
||||||
|
; Door capture from its reachable exit cell, facing a neighboring wall.
|
||||||
|
mov ebx,brExitCell3D
|
||||||
|
mov eax,ebx
|
||||||
|
and eax,31
|
||||||
|
shl eax,16
|
||||||
|
add eax,FP_HALF
|
||||||
|
mov playerX,eax
|
||||||
|
mov eax,ebx
|
||||||
|
shr eax,5
|
||||||
|
shl eax,16
|
||||||
|
add eax,FP_HALF
|
||||||
|
mov playerY,eax
|
||||||
|
mov playerAngle,384
|
||||||
|
cmp brMap3D[ebx-32],0
|
||||||
|
jne br_test_exit_camera
|
||||||
|
mov playerAngle,128
|
||||||
|
cmp brMap3D[ebx+32],0
|
||||||
|
jne br_test_exit_camera
|
||||||
|
mov playerAngle,256
|
||||||
|
cmp brMap3D[ebx-1],0
|
||||||
|
jne br_test_exit_camera
|
||||||
|
mov playerAngle,0
|
||||||
|
br_test_exit_camera:
|
||||||
|
mov brDialogue3D,10000
|
||||||
|
call RenderBackrooms3D
|
||||||
|
invoke CreateFileA,OFFSET brTestExitFrame,40000000h,0,0,2,80h,0
|
||||||
|
mov ebx,eax
|
||||||
|
invoke WriteFile,ebx,OFFSET screenBuffer,SCREEN_SIZE*4,OFFSET brTestIo,0
|
||||||
|
invoke CloseHandle,ebx
|
||||||
|
mov arrivalConfirmed3D,0
|
||||||
|
call RunBackroomsDoorFrames3D
|
||||||
|
invoke LeaveBackrooms3D,1
|
||||||
|
cmp brOwned3D,1
|
||||||
|
jne br_test_fail
|
||||||
|
cmp brActive3D,0
|
||||||
|
jne br_test_fail
|
||||||
|
cmp hallLevel3D,0
|
||||||
|
jne br_test_fail
|
||||||
|
mov brTestStage,97
|
||||||
|
call RunBackroomsContextTest3D
|
||||||
|
test eax,eax
|
||||||
|
jnz br_test_return
|
||||||
|
mov brActive3D,1
|
||||||
|
call BackroomsLuck3D
|
||||||
|
cmp eax,-1
|
||||||
|
jne br_test_fail
|
||||||
|
mov brActive3D,0
|
||||||
|
mov tournamentMode,1
|
||||||
|
call BackroomsLuck3D
|
||||||
|
cmp eax,-1
|
||||||
|
jne br_test_fail
|
||||||
|
mov tournamentMode,0
|
||||||
|
xor edi,edi
|
||||||
|
mov esi,100000
|
||||||
|
br_test_luck:
|
||||||
|
call BackroomsLuck3D
|
||||||
|
add edi,eax
|
||||||
|
dec esi
|
||||||
|
jnz br_test_luck
|
||||||
|
cmp edi,89000
|
||||||
|
jb br_test_fail
|
||||||
|
cmp edi,91000
|
||||||
|
ja br_test_fail
|
||||||
|
call RunBackroomsExtendedTest3D
|
||||||
|
test eax,eax
|
||||||
|
jnz br_test_return
|
||||||
|
mov brTestStage,98
|
||||||
|
call LoadNativeCoinArt3D
|
||||||
|
call InitNativeSlots3D
|
||||||
|
call InitNativeClover3D
|
||||||
|
call InitNativeBlackjack3D
|
||||||
|
call InitNativePoker3D
|
||||||
|
invoke CreateFileA,OFFSET brTestLuckPath,40000000h,0,0,2,80h,0
|
||||||
|
mov ebx,eax
|
||||||
|
mov brTestRows,1000
|
||||||
|
br_test_rounds:
|
||||||
|
mov bankroll,1000000
|
||||||
|
mov coin3d_choice,1
|
||||||
|
mov coin3d_state,COIN_IDLE
|
||||||
|
mov pressedKeys3D[20h],1
|
||||||
|
call HandleNativeCoin3D
|
||||||
|
invoke WriteFile,ebx,OFFSET coin3d_result,4,OFFSET brTestIo,0
|
||||||
|
mov dice3d_state,0
|
||||||
|
mov dice3d_choice,1
|
||||||
|
mov pressedKeys3D[20h],1
|
||||||
|
call HandleDiceRules3D
|
||||||
|
invoke WriteFile,ebx,OFFSET dice3d_val1,8,OFFSET brTestIo,0
|
||||||
|
mov slotSpinState,SLOT_READY
|
||||||
|
call StartNativeSlots3D
|
||||||
|
invoke WriteFile,ebx,OFFSET slotReel1,12,OFFSET brTestIo,0
|
||||||
|
mov clpState3D,SLOT_READY
|
||||||
|
call StartNativeClover3D
|
||||||
|
call CloverEvaluate3D
|
||||||
|
invoke WriteFile,ebx,OFFSET clpTotal3D,4,OFFSET brTestIo,0
|
||||||
|
mov cbBotCount3D,0
|
||||||
|
mov cbState3D,CB_IDLE
|
||||||
|
call StartNativeBlackjack3D
|
||||||
|
invoke WriteFile,ebx,OFFSET cbPlayerScore3D,4,OFFSET brTestIo,0
|
||||||
|
invoke WriteFile,ebx,OFFSET cbDeck3D,208,OFFSET brTestIo,0
|
||||||
|
mov pkState3D,PK_IDLE
|
||||||
|
call StartNativePoker3D
|
||||||
|
invoke WriteFile,ebx,OFFSET pkDeck3D,208,OFFSET brTestIo,0
|
||||||
|
invoke WriteFile,ebx,OFFSET pkButton3D,4,OFFSET brTestIo,0
|
||||||
|
dec brTestRows
|
||||||
|
jnz br_test_rounds
|
||||||
|
invoke CloseHandle,ebx
|
||||||
|
mov brTestStage,99
|
||||||
|
mov nativeProfilesDirPtr3D,OFFSET brTestProfileDir
|
||||||
|
invoke CopyCString,OFFSET saveFileName,OFFSET brTestProfileName
|
||||||
|
mov nativeProfileActive3D,1
|
||||||
|
mov brOwned3D,1
|
||||||
|
mov brEnabled3D,0
|
||||||
|
call SaveGame
|
||||||
|
mov brOwned3D,0
|
||||||
|
mov brEnabled3D,1
|
||||||
|
call LoadSave
|
||||||
|
cmp brOwned3D,1
|
||||||
|
jne br_test_fail
|
||||||
|
cmp brEnabled3D,0
|
||||||
|
jne br_test_fail
|
||||||
|
invoke ValidateGraphicProfile3D,OFFSET brTestProfilePath
|
||||||
|
cmp eax,1
|
||||||
|
jne br_test_fail
|
||||||
|
call RunBackroomsSaveTest3D
|
||||||
|
test eax,eax
|
||||||
|
jnz br_test_return
|
||||||
|
xor eax,eax
|
||||||
|
ret
|
||||||
|
br_test_fail:
|
||||||
|
mov eax,brTestStage
|
||||||
|
br_test_return:
|
||||||
|
ret
|
||||||
|
RunBackroomsTest3D ENDP
|
||||||
|
|
||||||
|
; Identical door/camera distance on every face, VHS off/on pairs.
|
||||||
|
RunBackroomsDoorFrames3D PROC uses ebx esi edi
|
||||||
|
local face:DWORD,effect:DWORD
|
||||||
|
invoke CreateFileA,OFFSET brTestFacesPath,40000000h,0,0,2,80h,0
|
||||||
|
mov ebx,eax
|
||||||
|
mov face,0
|
||||||
|
br_test_door_face:
|
||||||
|
lea edi,brMap3D
|
||||||
|
xor eax,eax
|
||||||
|
mov ecx,256
|
||||||
|
rep stosd
|
||||||
|
; Keep all rays inside the fixture map, including peripheral FOV rays.
|
||||||
|
xor esi,esi
|
||||||
|
br_test_door_border:
|
||||||
|
mov brMap3D[esi],BR_WALL
|
||||||
|
mov brMap3D[esi+31*32],BR_WALL
|
||||||
|
mov eax,esi
|
||||||
|
shl eax,5
|
||||||
|
mov brMap3D[eax],BR_WALL
|
||||||
|
mov brMap3D[eax+31],BR_WALL
|
||||||
|
inc esi
|
||||||
|
cmp esi,32
|
||||||
|
jb br_test_door_border
|
||||||
|
mov brExitCell3D,16*32+16
|
||||||
|
mov esi,face
|
||||||
|
mov eax,brTestFaceNeighbors[esi*4]
|
||||||
|
mov brMap3D[eax+16*32+16],BR_WALL
|
||||||
|
mov playerX,16*FP_1+FP_HALF
|
||||||
|
mov playerY,16*FP_1+FP_HALF
|
||||||
|
mov eax,brTestFaceAngles[esi*4]
|
||||||
|
mov playerAngle,eax
|
||||||
|
mov viewEye3D,HALL_STANDING_EYE
|
||||||
|
mov viewHorizon3D,HALF_H
|
||||||
|
mov brDialogue3D,10000
|
||||||
|
mov effect,0
|
||||||
|
br_test_door_effect:
|
||||||
|
mov eax,effect
|
||||||
|
mov brVhs3D,eax
|
||||||
|
call RenderBackrooms3D
|
||||||
|
invoke WriteFile,ebx,OFFSET screenBuffer,SCREEN_SIZE*4,OFFSET brTestIo,0
|
||||||
|
inc effect
|
||||||
|
cmp effect,2
|
||||||
|
jb br_test_door_effect
|
||||||
|
inc face
|
||||||
|
cmp face,4
|
||||||
|
jb br_test_door_face
|
||||||
|
invoke CloseHandle,ebx
|
||||||
|
ret
|
||||||
|
RunBackroomsDoorFrames3D ENDP
|
||||||
128
tools/tests/check_backrooms.py
Normal file
128
tools/tests/check_backrooms.py
Normal file
|
|
@ -0,0 +1,128 @@
|
||||||
|
"""Execute shipping MASM maze/entry/collision/render, inspect native output."""
|
||||||
|
from collections import deque
|
||||||
|
from pathlib import Path
|
||||||
|
import struct
|
||||||
|
import subprocess
|
||||||
|
from PIL import Image
|
||||||
|
from check_artifacts import toolchain
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
OUT = ROOT / 'build/scratch'
|
||||||
|
|
||||||
|
|
||||||
|
def check_exit_faces():
|
||||||
|
raw = (OUT/'backrooms-exit-faces.bin').read_bytes()
|
||||||
|
assert len(raw) == 8*640*480*4
|
||||||
|
frames = [Image.frombytes('RGBA', (640, 480), raw[i:i+640*480*4],
|
||||||
|
'raw', 'BGRA').convert('RGB')
|
||||||
|
for i in range(0, len(raw), 640*480*4)]
|
||||||
|
# Source glyph at runtime's exact nearest-neighbor UV scale. Compare both
|
||||||
|
# orientations rather than merely counting green pixels (mirrors pass that).
|
||||||
|
pack = (ROOT/'assets/sprites/backrooms/materials.bin').read_bytes()
|
||||||
|
art = Image.frombytes('RGBA', (128, 128), pack[20+4*65536:], 'raw', 'BGRA')
|
||||||
|
glyph = [(x, y) for y in range(48, 70) for x in range(27, 101)
|
||||||
|
if min(art.getpixel((x, y))[:3]) > 240]
|
||||||
|
for face, name in enumerate(('north', 'south', 'west', 'east')):
|
||||||
|
clean, vhs = frames[2*face:2*face+2]
|
||||||
|
clean.save(OUT/f'backrooms-exit-{name}.png')
|
||||||
|
vhs.save(OUT/f'backrooms-exit-{name}-vhs.png')
|
||||||
|
white = [(x, y) for y in range(0, 300) for x in range(60, 580)
|
||||||
|
if min(clean.getpixel((x, y))) > 240]
|
||||||
|
assert white, f'{name}: EXIT missing'
|
||||||
|
x0, x1 = min(x for x, y in white), max(x for x, y in white)
|
||||||
|
y0, y1 = min(y for x, y in white), max(y for x, y in white)
|
||||||
|
gx0, gx1 = min(x for x, y in glyph), max(x for x, y in glyph)
|
||||||
|
gy0, gy1 = min(y for x, y in glyph), max(y for x, y in glyph)
|
||||||
|
def score(mirror):
|
||||||
|
hits = 0
|
||||||
|
for x, y in glyph:
|
||||||
|
u = (x-gx0)/(gx1-gx0)
|
||||||
|
if mirror:
|
||||||
|
u = 1-u
|
||||||
|
px = round(x0+u*(x1-x0))
|
||||||
|
py = round(y0+(y-gy0)/(gy1-gy0)*(y1-y0))
|
||||||
|
hits += min(clean.getpixel((px, py))) > 240
|
||||||
|
return hits/len(glyph)
|
||||||
|
normal, mirrored = score(False), score(True)
|
||||||
|
assert normal > .85 and normal > mirrored+.12, (name, normal, mirrored)
|
||||||
|
# White glyphs may darken on scanlines, never wrap into black/color noise.
|
||||||
|
corrupt = sum(min(vhs.getpixel(p)) < 180 or
|
||||||
|
max(vhs.getpixel(p))-min(vhs.getpixel(p)) > 12 for p in white)
|
||||||
|
assert corrupt == 0, (name, 'VHS corrupt white pixels', corrupt, len(white))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
OUT.mkdir(parents=True, exist_ok=True)
|
||||||
|
ml, link = toolchain()
|
||||||
|
sdk = Path('C:/Program Files (x86)/Windows Kits/10/Lib')
|
||||||
|
lib = next(p/'um/x86' for p in sorted(sdk.iterdir(), reverse=True)
|
||||||
|
if (p/'um/x86/kernel32.lib').exists())
|
||||||
|
for args in ([ml, '/c', '/coff', '/Cp', '/nologo', '/I.', '/DBACKROOMS_TEST=1',
|
||||||
|
'/Fobuild/scratch/backrooms.obj', 'poker.asm'],
|
||||||
|
[link, '/nologo', '/SUBSYSTEM:CONSOLE', '/LIBPATH:'+str(lib),
|
||||||
|
'/OUT:build/scratch/backrooms-test.exe', 'build/scratch/backrooms.obj',
|
||||||
|
'kernel32.lib', 'winmm.lib', 'user32.lib', 'ws2_32.lib', 'gdi32.lib']):
|
||||||
|
subprocess.run(list(map(str, args)), cwd=ROOT, check=True, timeout=120)
|
||||||
|
subprocess.run([str(OUT/'backrooms-test.exe')], cwd=ROOT, check=True, timeout=90)
|
||||||
|
raw = (OUT/'backrooms-native.bin').read_bytes()
|
||||||
|
assert len(raw) == 256 * 1052
|
||||||
|
fingerprints = set()
|
||||||
|
minimum = 10000
|
||||||
|
for offset in range(0, len(raw), 1052):
|
||||||
|
grid = raw[offset:offset+1024]
|
||||||
|
exit_cell, *games = struct.unpack_from('<7I', raw, offset+1024)
|
||||||
|
assert all(grid[x] for x in range(32))
|
||||||
|
assert all(grid[31*32+x] for x in range(32))
|
||||||
|
assert all(grid[y*32] and grid[y*32+31] for y in range(32))
|
||||||
|
distance, queue = {33: 0}, deque([33])
|
||||||
|
while queue:
|
||||||
|
cell = queue.popleft()
|
||||||
|
for neighbor in (cell-32, cell+1, cell+32, cell-1):
|
||||||
|
if grid[neighbor] == 0 and neighbor not in distance:
|
||||||
|
distance[neighbor] = distance[cell]+1
|
||||||
|
queue.append(neighbor)
|
||||||
|
assert len(distance) == grid.count(0), 'Disconnected open component'
|
||||||
|
assert distance[exit_cell] == max(distance.values())
|
||||||
|
assert len(set(games)) == 6 and exit_cell not in games and 33 not in games
|
||||||
|
assert all(cell in distance for cell in games)
|
||||||
|
minimum = min(minimum, distance[exit_cell])
|
||||||
|
fingerprints.add(grid)
|
||||||
|
assert len(fingerprints) == 256
|
||||||
|
assert minimum >= 40, minimum
|
||||||
|
luck = (OUT/'backrooms-luck.bin').read_bytes()
|
||||||
|
assert len(luck) == 1000*452
|
||||||
|
wins = dict.fromkeys(('coin', 'dice', '777', 'clover', 'blackjack', 'poker'), 0)
|
||||||
|
for row in struct.iter_unpack('<113I', luck):
|
||||||
|
coin, d1, d2, s1, s2, s3, clover, bj = row[:8]
|
||||||
|
assert coin in (1, 2) and 1 <= d1 <= 6 and 1 <= d2 <= 6
|
||||||
|
wins['coin'] += coin == 1
|
||||||
|
wins['dice'] += (d1+d2) % 2 == 0
|
||||||
|
assert (s1, s2, s3) in ((1, 1, 1), (2, 5, 3))
|
||||||
|
wins['777'] += s1 == s2 == s3
|
||||||
|
assert clover in (0, 78)
|
||||||
|
wins['clover'] += clover > 0
|
||||||
|
deck, poker, button = row[8:60], row[60:112], row[112]
|
||||||
|
assert sorted(deck) == sorted(poker) == list(range(52)), 'Duplicate/missing card'
|
||||||
|
assert bj in (19, 21)
|
||||||
|
assert bj == (21 if deck[0] == 12 else 19)
|
||||||
|
wins['blackjack'] += bj == 21
|
||||||
|
# Actual non-button-first deal order, plus actual burn/flop/turn/river offsets.
|
||||||
|
seat = button ^ 1
|
||||||
|
hand = [poker[seat], poker[seat+2], *(poker[i] for i in (5, 6, 7, 9, 11))]
|
||||||
|
wins['poker'] += set(range(8, 13)).issubset(hand)
|
||||||
|
assert all(860 <= n <= 940 for n in wins.values()), wins
|
||||||
|
image = Image.frombytes('RGBA', (640, 480), (OUT/'backrooms-frame.bin').read_bytes(), 'raw', 'BGRA').convert('RGB')
|
||||||
|
image.save(OUT/'backrooms-frame.png')
|
||||||
|
assert len(image.getcolors(640*480)) > 100
|
||||||
|
image = Image.frombytes('RGBA', (640, 480), (OUT/'backrooms-exit.bin').read_bytes(), 'raw', 'BGRA').convert('RGB')
|
||||||
|
image.save(OUT/'backrooms-exit.png')
|
||||||
|
assert sum(g > 1.4*r and g > 1.2*b for r, g, b in image.get_flattened_data()) > 100, 'Exit not visibly green'
|
||||||
|
check_exit_faces()
|
||||||
|
print('PASS: readable non-mirrored EXIT on all four wall faces; VHS preserves white glyphs')
|
||||||
|
print(f'PASS: 256 native seeds; sealed connected mazes; farthest exit >= {minimum} steps; unique reachable games; entry hold/reset; collision; isolation; profile roundtrip; render')
|
||||||
|
print(f'PASS: 1000 production rounds per game, valid unique decks, wins: {wins}')
|
||||||
|
print('PASS: all blackjack party sizes; 7 scratch designs; roulette; Durak conservation/trump; 9 Russian party/bullet setups; Buckshot counts; preview saves; repeat reward')
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
Loading…
Add table
Reference in a new issue