fix(jackbox): realign UI strictly within CRT monitor sprite and clear wall painting

This commit is contained in:
Игорь Федосеев 2026-10-25 17:07:05 +03:00
parent 6bf2a2885c
commit 7c262a15ad
11 changed files with 434 additions and 315 deletions

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 223 KiB

After

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

After

Width:  |  Height:  |  Size: 38 KiB

BIN
poker.exe

Binary file not shown.

BIN
poker.obj

Binary file not shown.

View file

@ -1,67 +1,68 @@
; ============================================================================== ; ==============================================================================
; JACKBOX / JUKEBOX IMPLEMENTATION - MASM32 / CP1251 ; JACKBOX / JUKEBOX IMPLEMENTATION - MASM32 / CP1251
; ============================================================================== ; ==============================================================================
.code .code
LoadJackboxArt3D PROC LoadJackboxArt3D PROC
invoke LoadAnimPack3D, OFFSET jackboxWorldArt3D, OFFSET jackboxWorldPath3D invoke LoadAnimPack3D, OFFSET jackboxWorldArt3D, OFFSET jackboxWorldPath3D
invoke ValidateCityPack3D, OFFSET jackboxWorldArt3D, 256, 512, 3 invoke ValidateCityPack3D, OFFSET jackboxWorldArt3D, 256, 512, 3
invoke LoadAnimPack3D, OFFSET jackboxScreenArt3D, OFFSET jackboxScreenPath3D invoke LoadAnimPack3D, OFFSET jackboxScreenArt3D, OFFSET jackboxScreenPath3D
invoke ValidateCityPack3D, OFFSET jackboxScreenArt3D, 640, 480, 1 invoke ValidateCityPack3D, OFFSET jackboxScreenArt3D, 640, 480, 1
ret ret
LoadJackboxArt3D ENDP LoadJackboxArt3D ENDP
FreeJackboxArt3D PROC FreeJackboxArt3D PROC
invoke FreeAnimPack3D, OFFSET jackboxWorldArt3D invoke FreeAnimPack3D, OFFSET jackboxWorldArt3D
invoke FreeAnimPack3D, OFFSET jackboxScreenArt3D invoke FreeAnimPack3D, OFFSET jackboxScreenArt3D
ret ret
FreeJackboxArt3D ENDP FreeJackboxArt3D ENDP
ResolveJackboxSurface3D PROC material:DWORD ResolveJackboxSurface3D PROC material:DWORD
cmp jackboxWorldArt3D.pixels, 0 cmp jackboxWorldArt3D.pixels, 0
je jackbox_surface_missing je jackbox_surface_missing
mov eax, material mov eax, material
cmp eax, MATERIAL_JACKBOX_FRONT cmp eax, MATERIAL_JACKBOX_FRONT
je jackbox_surface_front je jackbox_surface_front
cmp eax, MATERIAL_JACKBOX_SIDE cmp eax, MATERIAL_JACKBOX_SIDE
je jackbox_surface_side je jackbox_surface_side
cmp eax, MATERIAL_JACKBOX_BACK cmp eax, MATERIAL_JACKBOX_BACK
jne jackbox_surface_missing jne jackbox_surface_missing
; Frame 2: rear panel (offset 256*512*4*2 = 1048576) ; Frame 2: rear panel (offset 256*512*4*2 = 1048576)
mov eax, jackboxWorldArt3D.pixels mov eax, jackboxWorldArt3D.pixels
add eax, 1048576 add eax, 1048576
mov ecx, 256 mov ecx, 256
mov edx, 512 mov edx, 512
ret ret
jackbox_surface_side: jackbox_surface_side:
; Frame 1: side profile (offset 256*512*4 = 524288) ; Frame 1: side profile (offset 256*512*4 = 524288)
mov eax, jackboxWorldArt3D.pixels mov eax, jackboxWorldArt3D.pixels
add eax, 524288 add eax, 524288
mov ecx, 256 mov ecx, 256
mov edx, 512 mov edx, 512
ret ret
jackbox_surface_front: jackbox_surface_front:
; Frame 0: front face ; Frame 0: front face
mov eax, jackboxWorldArt3D.pixels mov eax, jackboxWorldArt3D.pixels
mov ecx, 256 mov ecx, 256
mov edx, 512 mov edx, 512
ret ret
jackbox_surface_missing: jackbox_surface_missing:
xor eax, eax xor eax, eax
ret ret
ResolveJackboxSurface3D ENDP ResolveJackboxSurface3D ENDP
DrawJackboxCabinet3D PROC uses ebx esi edi wx:DWORD, wy:DWORD DrawJackboxCabinet3D PROC uses ebx esi edi wx:DWORD, wy:DWORD
local x0:DWORD, x1:DWORD, y0:DWORD, y1:DWORD local x0:DWORD, x1:DWORD, y0:DWORD, y1:DWORD
; Solid rectangular cabinet against East wall beside billiards: ; Solid rectangular cabinet against East wall beside billiards:
; Depth along X: 0.55m (x0 = 30.40m, x1 = 30.95m against wall at 31.0m) ; Depth along X: 0.55m (x0 = 30.40m, x1 = 30.95m against wall at 31.0m)
; Width along Y: 0.85m (y0 = 24.575m, y1 = 25.425m, centered at Y = 25.0m) ; Width along Y: 0.85m (y0 = 23.075m, y1 = 23.925m, centered at Y = 23.5m)
; Leaves painting 116 at Y = [25.0 .. 26.5] completely visible and unblocked!
; Height Z: 1.85m ; Height Z: 1.85m
mov x0, FP_1*304/10 mov x0, FP_1*304/10
mov x1, FP_1*3095/100 mov x1, FP_1*3095/100
mov y0, 25*FP_1 - FP_1*425/1000 mov y0, FP_1*235/10 - FP_1*425/1000
mov y1, 25*FP_1 + FP_1*425/1000 mov y1, FP_1*235/10 + FP_1*425/1000
; 1. Back Face (against East wall: X = x1) ; 1. Back Face (against East wall: X = x1)
invoke DrawCityVertical3D, 0, x1, y0, y1, 0, FP_1*37/20, MATERIAL_JACKBOX_BACK invoke DrawCityVertical3D, 0, x1, y0, y1, 0, FP_1*37/20, MATERIAL_JACKBOX_BACK
@ -88,7 +89,7 @@ JackboxCanWalk3D PROC px:DWORD, py:DWORD
cmp eax, 31*FP_1+9830 cmp eax, 31*FP_1+9830
ja jackbox_walk_clear ja jackbox_walk_clear
mov eax, py mov eax, py
sub eax, 25*FP_1 sub eax, FP_1*235/10
test eax, eax test eax, eax
jns @F jns @F
neg eax neg eax
@ -102,230 +103,309 @@ jackbox_walk_clear:
ret ret
JackboxCanWalk3D ENDP JackboxCanWalk3D ENDP
PlayJukeboxTrack3D PROC uses ebx trackIndex:DWORD PlayJukeboxTrack3D PROC uses ebx trackIndex:DWORD
invoke mciSendStringA, OFFSET jboxStopCmd, 0, 0, 0 invoke mciSendStringA, OFFSET jboxStopCmd, 0, 0, 0
invoke mciSendStringA, OFFSET jboxCloseCmd, 0, 0, 0 invoke mciSendStringA, OFFSET jboxCloseCmd, 0, 0, 0
mov jboxIsPlaying, 0 mov jboxIsPlaying, 0
mov ebx, trackIndex mov ebx, trackIndex
cmp ebx, 9 cmp ebx, 9
jae jbox_play_done jae jbox_play_done
cmp ebx, JACKBOX_TRACK_COUNT cmp ebx, JACKBOX_TRACK_COUNT
jae jbox_play_done jae jbox_play_done
mov eax, jboxOpenCommands[ebx*4] mov eax, jboxOpenCommands[ebx*4]
test eax, eax test eax, eax
jz jbox_play_done jz jbox_play_done
invoke mciSendStringA, eax, 0, 0, 0 invoke mciSendStringA, eax, 0, 0, 0
invoke mciSendStringA, OFFSET jboxPlayCmd, 0, 0, 0 invoke mciSendStringA, OFFSET jboxPlayCmd, 0, 0, 0
mov jboxCurrentTrack, ebx mov jboxCurrentTrack, ebx
mov jboxIsPlaying, 1 mov jboxIsPlaying, 1
jbox_play_done: jbox_play_done:
ret ret
PlayJukeboxTrack3D ENDP PlayJukeboxTrack3D ENDP
StopJukeboxTrack3D PROC StopJukeboxTrack3D PROC
invoke mciSendStringA, OFFSET jboxStopCmd, 0, 0, 0 invoke mciSendStringA, OFFSET jboxStopCmd, 0, 0, 0
invoke mciSendStringA, OFFSET jboxCloseCmd, 0, 0, 0 invoke mciSendStringA, OFFSET jboxCloseCmd, 0, 0, 0
mov jboxIsPlaying, 0 mov jboxIsPlaying, 0
mov jboxCurrentTrack, -1 mov jboxCurrentTrack, -1
ret ret
StopJukeboxTrack3D ENDP StopJukeboxTrack3D ENDP
BeginJackbox3D PROC BeginJackbox3D PROC
mov engineMode, MODE_JACKBOX mov engineMode, MODE_JACKBOX
call ClearKeys3D call ClearKeys3D
mov mouseClick3D, 0 mov mouseClick3D, 0
ret ret
BeginJackbox3D ENDP BeginJackbox3D ENDP
HandleJackbox3D PROC uses ebx esi HandleJackbox3D PROC uses ebx esi
; 1. Mouse interactions ; 1. Mouse interactions
cmp mouseClick3D, 0 cmp mouseClick3D, 0
je jbox_keys je jbox_keys
; Check Exit button in top right: x in [228..312], y in [8..26] ; Exit via Top-Right LCD slot: x in [232..284], y in [12..26]
cmp mouseY3D, 8 cmp mouseY3D, 12
jb @F jb @F
cmp mouseY3D, 26 cmp mouseY3D, 26
ja @F ja @F
cmp mouseX3D, 228 cmp mouseX3D, 232
jae jbox_exit jb @F
@@: cmp mouseX3D, 284
; Check track row click: y in [54..186] jbe jbox_exit
cmp mouseY3D, 54 @@:
jb jbox_keys ; Exit via Bottom Red CANCEL button: x in [224..256], y in [195..225]
cmp mouseY3D, 186 cmp mouseY3D, 195
ja jbox_keys jb @F
cmp mouseX3D, 16 cmp mouseY3D, 225
jb jbox_keys ja @F
cmp mouseX3D, 304 cmp mouseX3D, 224
ja jbox_keys jb @F
mov eax, mouseY3D cmp mouseX3D, 256
sub eax, 54 jbe jbox_exit
xor edx, edx @@:
mov ebx, 13 ; Bottom Green START button: x in [154..188], y in [195..225] -> Play selected
div ebx cmp mouseY3D, 195
cmp eax, JACKBOX_TRACK_COUNT jb @F
jae jbox_keys cmp mouseY3D, 225
mov jboxSelectedTrack, eax ja @F
invoke PlayJukeboxTrack3D, eax cmp mouseX3D, 154
jmp jbox_handled jb @F
cmp mouseX3D, 188
jbox_keys: jbe jbox_play_selected
; Exit keys: ESC (1Bh) or 'E' (45h) @@:
invoke Pressed3D, 1Bh ; Bottom Orange SELECT button: x in [190..222], y in [195..225] -> Next track & play
test eax, eax cmp mouseY3D, 195
jnz jbox_exit jb @F
invoke Pressed3D, 45h cmp mouseY3D, 225
test eax, eax ja @F
jnz jbox_exit cmp mouseX3D, 190
jb @F
; Navigation: UP (26h) / DOWN (28h) cmp mouseX3D, 222
invoke Pressed3D, 26h ja @F
test eax, eax inc jboxSelectedTrack
jz @F cmp jboxSelectedTrack, JACKBOX_TRACK_COUNT
dec jboxSelectedTrack jb jbox_play_selected
jns jbox_handled mov jboxSelectedTrack, 0
mov jboxSelectedTrack, JACKBOX_TRACK_COUNT - 1 jmp jbox_play_selected
jmp jbox_handled @@:
@@: ; Bottom Left Arrow: x in [256..274], y in [204..224] -> Prev track
invoke Pressed3D, 28h cmp mouseY3D, 204
test eax, eax jb @F
jz @F cmp mouseY3D, 224
inc jboxSelectedTrack ja @F
cmp jboxSelectedTrack, JACKBOX_TRACK_COUNT cmp mouseX3D, 256
jb jbox_handled jb @F
mov jboxSelectedTrack, 0 cmp mouseX3D, 274
jmp jbox_handled ja @F
@@: dec jboxSelectedTrack
; Play selection: ENTER (0Dh) or SPACE (20h) jns jbox_play_selected
invoke Pressed3D, 0Dh mov jboxSelectedTrack, JACKBOX_TRACK_COUNT - 1
test eax, eax jmp jbox_play_selected
jnz jbox_play_selected @@:
invoke Pressed3D, 20h ; Bottom Right Arrow: x in [276..294], y in [204..224] -> Next track
test eax, eax cmp mouseY3D, 204
jnz jbox_play_selected jb @F
cmp mouseY3D, 224
; Stop key: 'S' (53h) ja @F
invoke Pressed3D, 53h cmp mouseX3D, 276
test eax, eax jb @F
jz @F cmp mouseX3D, 294
call StopJukeboxTrack3D ja @F
jmp jbox_handled inc jboxSelectedTrack
@@: cmp jboxSelectedTrack, JACKBOX_TRACK_COUNT
; Random key: 'R' (52h) jb jbox_play_selected
invoke Pressed3D, 52h mov jboxSelectedTrack, 0
test eax, eax jmp jbox_play_selected
jz @F @@:
invoke RandomRange3D, 9 ; Check track row click inside CRT screen: x in [46..274], y in [65..165]
mov jboxSelectedTrack, eax cmp mouseY3D, 65
invoke PlayJukeboxTrack3D, eax jb jbox_keys
jmp jbox_handled cmp mouseY3D, 165
@@: ja jbox_keys
; Direct digit keys '1'..'9', '0' cmp mouseX3D, 46
mov ebx, 31h ; '1' jb jbox_keys
jbox_digit_loop: cmp mouseX3D, 274
invoke Pressed3D, ebx ja jbox_keys
test eax, eax mov eax, mouseY3D
jz jbox_digit_next sub eax, 65
mov eax, ebx xor edx, edx
sub eax, 31h mov ebx, 10
mov jboxSelectedTrack, eax div ebx
invoke PlayJukeboxTrack3D, eax cmp eax, JACKBOX_TRACK_COUNT
jmp jbox_handled jae jbox_keys
jbox_digit_next: mov jboxSelectedTrack, eax
inc ebx invoke PlayJukeboxTrack3D, eax
cmp ebx, 39h ; '9' jmp jbox_handled
jbe jbox_digit_loop
jbox_keys:
; '0' key for mute/stop ; Exit keys: ESC (1Bh) or 'E' (45h)
invoke Pressed3D, 30h invoke Pressed3D, 1Bh
test eax, eax test eax, eax
jz jbox_handled jnz jbox_exit
mov jboxSelectedTrack, 9 invoke Pressed3D, 45h
invoke PlayJukeboxTrack3D, 9 test eax, eax
jmp jbox_handled jnz jbox_exit
jbox_play_selected: ; Navigation: UP (26h) / DOWN (28h)
invoke PlayJukeboxTrack3D, jboxSelectedTrack invoke Pressed3D, 26h
jmp jbox_handled test eax, eax
jz @F
jbox_exit: dec jboxSelectedTrack
mov engineMode, MODE_WALK jns jbox_handled
call ClearKeys3D mov jboxSelectedTrack, JACKBOX_TRACK_COUNT - 1
jmp jbox_handled
jbox_handled: @@:
mov mouseClick3D, 0 invoke Pressed3D, 28h
ret test eax, eax
HandleJackbox3D ENDP jz @F
inc jboxSelectedTrack
RenderJackbox3D PROC uses ebx esi edi cmp jboxSelectedTrack, JACKBOX_TRACK_COUNT
local rowY:DWORD, color:DWORD jb jbox_handled
mov jboxSelectedTrack, 0
; 1. Draw base background jmp jbox_handled
invoke DrawBox, 0, 0, 320, 240, 000B1815h @@:
; Play selection: ENTER (0Dh) or SPACE (20h)
; 2. Overlay screen artwork if available invoke Pressed3D, 0Dh
cmp jackboxScreenArt3D.pixels, 0 test eax, eax
je @F jnz jbox_play_selected
invoke DrawAnimSprite3D, OFFSET jackboxScreenArt3D, 0, 0, 0, 640, 480 invoke Pressed3D, 20h
@@: test eax, eax
; 3. Title & Exit Button jnz jbox_play_selected
invoke DrawString8x8, 52, 12, OFFSET jboxTitle, 00E7C479h
invoke DrawBoxBorder, 228, 8, 84, 16, 001A2522h, 00C8AD75h, 1 ; Stop key: 'S' (53h)
invoke DrawString8x8, 234, 12, OFFSET jboxClose, 00F2E6C6h invoke Pressed3D, 53h
test eax, eax
; 4. Now Playing Status Banner jz @F
cmp jboxIsPlaying, 1 call StopJukeboxTrack3D
jne jbox_render_stopped jmp jbox_handled
cmp jboxCurrentTrack, -1 @@:
je jbox_render_stopped ; Random key: 'R' (52h)
cmp jboxCurrentTrack, 9 invoke Pressed3D, 52h
jae jbox_render_stopped test eax, eax
jz @F
invoke DrawString8x8, 20, 34, OFFSET jboxStatusPlaying, 008CD8AFh invoke RandomRange3D, 9
mov eax, jboxCurrentTrack mov jboxSelectedTrack, eax
mov edx, jboxTrackNames[eax*4] invoke PlayJukeboxTrack3D, eax
invoke DrawString8x8, 140, 34, edx, 00F0E6C3h jmp jbox_handled
jmp jbox_render_divider @@:
; Direct digit keys '1'..'9'
jbox_render_stopped: mov ebx, 31h ; '1'
invoke DrawString8x8, 20, 34, OFFSET jboxStatusStopped, 0090B19Fh jbox_digit_loop:
invoke Pressed3D, ebx
jbox_render_divider: test eax, eax
invoke DrawBox, 20, 47, 280, 1, 00495B4Ah jz jbox_digit_next
mov eax, ebx
; 5. Track Selection List (10 rows, step Y = 13) sub eax, 31h
mov rowY, 55 mov jboxSelectedTrack, eax
xor esi, esi invoke PlayJukeboxTrack3D, eax
jbox_render_row: jmp jbox_handled
mov color, 0090B19Fh ; Default muted jbox_digit_next:
cmp esi, jboxSelectedTrack inc ebx
jne @F cmp ebx, 39h ; '9'
mov color, 00F2E6C6h ; Bright cream for selection jbe jbox_digit_loop
invoke DrawString8x8, 14, rowY, OFFSET jboxCursor, 00E7C479h
@@: ; '0' key for mute/stop
mov edx, jboxTrackNames[esi*4] invoke Pressed3D, 30h
invoke DrawString8x8, 28, rowY, edx, color test eax, eax
jz jbox_handled
; Mark playing track mov jboxSelectedTrack, 9
cmp esi, jboxCurrentTrack invoke PlayJukeboxTrack3D, 9
jne jbox_row_next jmp jbox_handled
cmp jboxIsPlaying, 1
jne jbox_row_next jbox_play_selected:
invoke DrawString8x8, 252, rowY, OFFSET jboxPlayingTag, 008CD8AFh invoke PlayJukeboxTrack3D, jboxSelectedTrack
jmp jbox_handled
jbox_row_next:
add rowY, 13 jbox_exit:
inc esi mov engineMode, MODE_WALK
cmp esi, JACKBOX_TRACK_COUNT call ClearKeys3D
jb jbox_render_row
jbox_handled:
; 6. Footer Controls Help mov mouseClick3D, 0
invoke DrawBox, 20, 192, 280, 1, 00314538h ret
invoke DrawString8x8, 20, 200, OFFSET jboxHelp1, 00C1A982h HandleJackbox3D ENDP
invoke DrawString8x8, 20, 214, OFFSET jboxHelp2, 0090B19Fh
RenderJackbox3D PROC uses ebx esi edi
ret local rowY:DWORD, color:DWORD
RenderJackbox3D ENDP
; 1. Draw base background
invoke DrawBox, 0, 0, 320, 240, 000B1815h
; 2. Overlay screen artwork (640x480 physical buffer)
cmp jackboxScreenArt3D.pixels, 0
je @F
invoke DrawAnimSprite3D, OFFSET jackboxScreenArt3D, 0, 0, 0, 640, 480
@@:
; 3. Top Digital LCD Slots
; Left slot: status text
cmp jboxIsPlaying, 1
jne jbox_top_lcd_stopped
cmp jboxCurrentTrack, -1
je jbox_top_lcd_stopped
cmp jboxCurrentTrack, 9
jae jbox_top_lcd_stopped
invoke DrawString8x8, 42, 17, OFFSET jboxLcdPlay, 0050FF90h ; Green "ÈÃÐÀÅÒ"
jmp jbox_top_lcd_exit
jbox_top_lcd_stopped:
invoke DrawString8x8, 45, 17, OFFSET jboxLcdStop, 008CB8A5h ; Dim green "ÑÒÎÏ"
jbox_top_lcd_exit:
; Right slot: exit button text
invoke DrawString8x8, 241, 17, OFFSET jboxLcdExit, 00F2A648h ; Amber "ÂÛÕÎÄ"
; 4. CRT Monitor Header: Now Playing Status
cmp jboxIsPlaying, 1
jne jbox_render_stopped
cmp jboxCurrentTrack, -1
je jbox_render_stopped
cmp jboxCurrentTrack, 9
jae jbox_render_stopped
invoke DrawString8x8, 48, 52, OFFSET jboxHdrNow, 0050FF90h ; Green "ÑÅÉ×ÀÑ:"
mov eax, jboxCurrentTrack
mov edx, jboxTrackNames[eax*4]
invoke DrawString8x8, 108, 52, edx, 00F0E6C3h
jmp jbox_render_divider
jbox_render_stopped:
invoke DrawString8x8, 48, 52, OFFSET jboxHdrStop, 008CB8A5h ; Dim green "ÑÒÀÒÓÑ: ÎÑÒÀÍÎÂËÅÍ"
jbox_render_divider:
invoke DrawBox, 46, 62, 228, 1, 001C3828h
; 5. Track Selection List (10 rows, step Y = 10, from Y = 66)
mov rowY, 66
xor esi, esi
jbox_render_row:
mov color, 008CB8A5h ; Default CRT phosphor pale cyan
cmp esi, jboxSelectedTrack
jne @F
; Selected row: highlight box, golden cursor, bright white text
invoke DrawBox, 46, rowY, 228, 9, 00143526h
invoke DrawString8x8, 48, rowY, OFFSET jboxCursor, 00FFD700h
mov color, 00FFFFFFh
@@:
mov edx, jboxTrackNames[esi*4]
invoke DrawString8x8, 58, rowY, edx, color
; Mark playing track with [>] tag
cmp esi, jboxCurrentTrack
jne jbox_row_next
cmp jboxIsPlaying, 1
jne jbox_row_next
invoke DrawString8x8, 238, rowY, OFFSET jboxTagPlay, 0050FF90h
jbox_row_next:
add rowY, 10
inc esi
cmp esi, JACKBOX_TRACK_COUNT
jb jbox_render_row
; 6. Footer Controls Help (strictly inside CRT)
invoke DrawBox, 46, 166, 228, 1, 001C3828h
invoke DrawString8x8, 56, 170, OFFSET jboxFooterHelp, 0070AA90h
ret
RenderJackbox3D ENDP

View file

@ -6,11 +6,11 @@ MODE_JACKBOX equ 28
INTERACT_JACKBOX equ 48 INTERACT_JACKBOX equ 48
JACKBOX_X equ FP_1*306/10 JACKBOX_X equ FP_1*306/10
JACKBOX_Y equ 25*FP_1 JACKBOX_Y equ FP_1*235/10
JACKBOX_TRACK_COUNT equ 10 JACKBOX_TRACK_COUNT equ 10
MATERIAL_JACKBOX_FRONT equ 161 MATERIAL_JACKBOX_FRONT equ 161
MATERIAL_JACKBOX_SIDE equ 162 MATERIAL_JACKBOX_SIDE equ 162
MATERIAL_JACKBOX_BACK equ 163 MATERIAL_JACKBOX_BACK equ 163
LoadJackboxArt3D PROTO LoadJackboxArt3D PROTO
@ -30,7 +30,8 @@ jackboxScreenArt3D AnimPack3D <>
jackboxWorldPath3D db "assets\animations\hall\jackbox-v1.bin",0 jackboxWorldPath3D db "assets\animations\hall\jackbox-v1.bin",0
jackboxScreenPath3D db "assets\animations\hall\jackbox-ui-v1.bin",0 jackboxScreenPath3D db "assets\animations\hall\jackbox-ui-v1.bin",0
jackboxPrompt3D db "E: ÄÆÓÊÁÎÊÑ",0 ; Prompt: "E: Âêëþ÷èòü àâòîìàò"
jackboxPrompt3D db 69,58,32,194,234,235,254,247,232,242,252,32,224,226,242,238,236,224,242,0
jboxCurrentTrack dd -1 jboxCurrentTrack dd -1
jboxSelectedTrack dd 0 jboxSelectedTrack dd 0
@ -54,26 +55,31 @@ jboxOpenCommands dd OFFSET jboxOpen0, OFFSET jboxOpen1, OFFSET jboxOpen2, OFFSET
dd OFFSET jboxOpen4, OFFSET jboxOpen5, OFFSET jboxOpen6, OFFSET jboxOpen7 dd OFFSET jboxOpen4, OFFSET jboxOpen5, OFFSET jboxOpen6, OFFSET jboxOpen7
dd OFFSET jboxOpen8, 0 dd OFFSET jboxOpen8, 0
jboxName0 db "1. Keygen Church - Tenebre Rosso Sangue",0 jboxName0 db "1. Keygen - Tenebre",0
jboxName1 db "2. Keygen Church - Hareklavit",0 jboxName1 db "2. Keygen - Hareklavit",0
jboxName2 db "3. Keygen Church - Ladikerfos",0 jboxName2 db "3. Keygen - Ladikerfos",0
jboxName3 db "4. Keygen Church - Tilaskarot",0 jboxName3 db "4. Keygen - Tilaskarot",0
jboxName4 db "5. Mick Gordon - BFG Division (DOOM)",0 jboxName4 db "5. Mick Gordon - BFG",0
jboxName5 db "6. Mick Gordon - Rip & Tear (DOOM)",0 jboxName5 db "6. Mick Gordon - Rip",0
jboxName6 db "7. Mick Gordon - The Only Thing They Fear",0 jboxName6 db "7. Mick Gordon - Doom",0
jboxName7 db "8. Hakari Dance (Jackpot Theme)",0 jboxName7 db "8. Hakari Dance (Ost)",0
jboxName8 db "9. Team Fortress 2 - Victory Theme",0 jboxName8 db "9. TF2 - Victory",0
jboxName9 db "0. [ ÂÛÊËÞ×ÈÒÜ ÌÓÇÛÊÓ / ÒÈØÈÍÀ ]",0 ; "0. [Âûêëþ÷èòü çâóê]"
jboxName9 db 48,46,32,91,194,251,234,235,254,247,232,242,252,32,231,226,243,234,93,0
jboxTrackNames dd OFFSET jboxName0, OFFSET jboxName1, OFFSET jboxName2, OFFSET jboxName3 jboxTrackNames dd OFFSET jboxName0, OFFSET jboxName1, OFFSET jboxName2, OFFSET jboxName3
dd OFFSET jboxName4, OFFSET jboxName5, OFFSET jboxName6, OFFSET jboxName7 dd OFFSET jboxName4, OFFSET jboxName5, OFFSET jboxName6, OFFSET jboxName7
dd OFFSET jboxName8, OFFSET jboxName9 dd OFFSET jboxName8, OFFSET jboxName9
jboxTitle db "ÌÓÇÛÊÀËÜÍÛÉ ÀÂÒÎÌÀÒ",0 ; Top Digital LCD Display Slots
jboxClose db "ÂÛÕÎÄ [ESC]",0 jboxLcdPlay db 200,195,208,192,197,210,0 ; "ÈÃÐÀÅÒ"
jboxStatusPlaying db "ÑÅÉ×ÀÑ ÈÃÐÀÅÒ:",0 jboxLcdStop db 209,210,206,207,0 ; "ÑÒÎÏ"
jboxStatusStopped db "ÌÓÇÛÊÀ ÂÛÊËÞ×ÅÍÀ",0 jboxLcdExit db 194,219,213,206,196,0 ; "ÂÛÕÎÄ"
jboxCursor db "> ",0
jboxPlayingTag db " [ÈÃÐÀÅÒ]",0 ; CRT Monitor Screen Text
jboxHelp1 db "ÑÒÐÅËÊÈ / 0-9: Âûáîð ENTER: Âêëþ÷èòü",0 jboxHdrNow db 209,197,201,215,192,209,58,0 ; "ÑÅÉ×ÀÑ:"
jboxHelp2 db "S: Ñòîï R: Ñëó÷àéíûé ESC:  çàë",0 jboxHdrStop db 209,210,192,210,211,209,58,32,206,209,210,192,205,206,194,203,197,205,0 ; "ÑÒÀÒÓÑ: ÎÑÒÀÍÎÂËÅÍ"
jboxCursor db ">",0
jboxTagPlay db "[>]",0
; "ENTER:Ïóñê S:Ñòîï R:Ìèêñ"
jboxFooterHelp db 69,78,84,69,82,58,207,243,241,234,32,32,83,58,209,242,238,239,32,32,82,58,204,232,234,241,0

View file

@ -64,7 +64,7 @@ def test_code_structure():
assert "MODE_JACKBOX equ 28" in data_inc assert "MODE_JACKBOX equ 28" in data_inc
assert "INTERACT_JACKBOX equ 48" in data_inc assert "INTERACT_JACKBOX equ 48" in data_inc
assert "JACKBOX_X equ FP_1*306/10" in data_inc assert "JACKBOX_X equ FP_1*306/10" in data_inc
assert "JACKBOX_Y equ 25*FP_1" in data_inc assert "JACKBOX_Y equ FP_1*235/10" in data_inc
assert "MATERIAL_JACKBOX_BACK equ 163" in data_inc assert "MATERIAL_JACKBOX_BACK equ 163" in data_inc
# Check procs # Check procs

View file

@ -251,14 +251,47 @@ def render_scene(cam_x, cam_y, cam_angle, out_path):
draw_pool_side(0, int(26.0*FP_1), int(24.0*FP_1), int(26.0*FP_1), 0, int(0.85*FP_1)) draw_pool_side(0, int(26.0*FP_1), int(24.0*FP_1), int(26.0*FP_1), 0, int(0.85*FP_1))
draw_pool_side(0, int(28.0*FP_1), int(24.0*FP_1), int(26.0*FP_1), 0, int(0.85*FP_1)) draw_pool_side(0, int(28.0*FP_1), int(24.0*FP_1), int(26.0*FP_1), 0, int(0.85*FP_1))
# 2. Solid Rectangular Jukebox Cabinet (at East wall, next to billiards table!) # 2. Wall Art / Painting 116 on East Wall: X = 30.98m, Y in [25.0m .. 26.5m], Z in [1.0m .. 2.0m]
def draw_painting(axis, coord, lo, hi, z0, z1, slot):
for col in range(SCREEN_W):
ray_dir = cityRayX[col] if axis == 0 else cityRayY[col]
if abs(ray_dir) < 256:
continue
orig = playerX if axis == 0 else playerY
num = (coord - orig)
depth = (num << 16) // ray_dir
if depth <= 4096 or depth >= zBuffer[col]:
continue
along = playerY + ((depth * cityRayY[col]) >> 16) if axis == 0 else playerX + ((depth * cityRayX[col]) >> 16)
if along < lo or along >= hi:
continue
top = (HALL_STANDING_EYE - z1) * SCREEN_H // depth + HALF_H
bottom = (HALL_STANDING_EYE - z0) * SCREEN_H // depth + HALF_H
span = bottom - top
if span <= 0:
continue
r_start = max(0, top)
r_end = min(SCREEN_H, bottom)
span_along = hi - lo
tx = int((along - lo) * 128 / span_along) % 128
shade = max(40, min(255, 255 - (depth >> 12)))
for row in range(r_start, r_end):
ty = int((row - top) * 128 / span) % 128
r, g, b, a = get_tex_pixel(slot, tx, ty)
if depth < depthBuffer[row * SCREEN_W + col]:
depthBuffer[row * SCREEN_W + col] = depth
screen_pixels[row * SCREEN_W + col] = ((r * shade) >> 8, (g * shade) >> 8, (b * shade) >> 8)
draw_painting(0, int(30.98 * FP_1), int(25.0 * FP_1), int(26.5 * FP_1), FP_1, 2 * FP_1, 116)
# 3. Solid Rectangular Jukebox Cabinet (at East wall, Y = 23.5m, clearing Painting 116!)
# Depth: X in [30.40m .. 30.95m] (back against East wall at 31.0m) # Depth: X in [30.40m .. 30.95m] (back against East wall at 31.0m)
# Width: Y in [24.575m .. 25.425m] (centered at Y = 25.0m) # Width: Y in [23.075m .. 23.925m] (centered at Y = 23.5m)
# Height: Z in [0 .. 1.85m] # Height: Z in [0 .. 1.85m]
x0 = int(30.40 * FP_1) x0 = int(30.40 * FP_1)
x1 = int(30.95 * FP_1) x1 = int(30.95 * FP_1)
y0 = int(24.575 * FP_1) y0 = int(23.075 * FP_1)
y1 = int(25.425 * FP_1) y1 = int(23.925 * FP_1)
zHigh = int(1.85 * FP_1) zHigh = int(1.85 * FP_1)
# Back Face (against wall: X = x1) - Frame 2 # Back Face (against wall: X = x1) - Frame 2
@ -277,11 +310,11 @@ def render_scene(cam_x, cam_y, cam_angle, out_path):
if __name__ == '__main__': if __name__ == '__main__':
# 1. Front View: Standing near billiards at (26.0, 25.0) looking East (angle=0) past table at Jukebox # 1. Front View: Standing near billiards at (26.0, 25.0) looking East (angle=0) past table at Jukebox
render_scene(26.0, 25.0, 0, DOCS_DIR / 'jukebox_3d_front.png') render_scene(26.0, 24.5, 0, DOCS_DIR / 'jukebox_3d_front.png')
# 2. Angle View: Standing at (27.5, 22.5) looking South-East (angle=480) at pool table and Jukebox # 2. Angle View: Standing at (27.5, 22.5) looking South-East (angle=480) at pool table and Jukebox
render_scene(27.5, 22.5, 480, DOCS_DIR / 'jukebox_3d_angle.png') render_scene(27.5, 21.0, 128, DOCS_DIR / 'jukebox_3d_angle.png')
# 3. Close-up View: Standing at (29.2, 25.0) looking East (angle=0) right at Jukebox # 3. Close-up View: Standing at (29.2, 25.0) looking East (angle=0) right at Jukebox
render_scene(29.2, 25.0, 0, DOCS_DIR / 'jukebox_3d_close.png') render_scene(29.2, 23.5, 0, DOCS_DIR / 'jukebox_3d_close.png')
# 4. Side View: Standing at (30.0, 27.5) looking North (angle=384) at South side of Jukebox # 4. Side View: Standing at (30.0, 27.5) looking North (angle=384) at South side of Jukebox
render_scene(30.0, 27.5, 384, DOCS_DIR / 'jukebox_3d_side.png') render_scene(30.6, 25.5, 768, DOCS_DIR / 'jukebox_3d_side.png')
print('All Jukebox 3D preview frames rendered to docs/previews_minigames/!') print('All Jukebox 3D preview frames rendered to docs/previews_minigames/!')