411 lines
11 KiB
PHP
411 lines
11 KiB
PHP
; ==============================================================================
|
||
; JACKBOX / JUKEBOX IMPLEMENTATION - MASM32 / CP1251
|
||
; ==============================================================================
|
||
|
||
.code
|
||
|
||
LoadJackboxArt3D PROC
|
||
invoke LoadAnimPack3D, OFFSET jackboxWorldArt3D, OFFSET jackboxWorldPath3D
|
||
invoke ValidateCityPack3D, OFFSET jackboxWorldArt3D, 256, 512, 3
|
||
invoke LoadAnimPack3D, OFFSET jackboxScreenArt3D, OFFSET jackboxScreenPath3D
|
||
invoke ValidateCityPack3D, OFFSET jackboxScreenArt3D, 640, 480, 1
|
||
ret
|
||
LoadJackboxArt3D ENDP
|
||
|
||
FreeJackboxArt3D PROC
|
||
invoke FreeAnimPack3D, OFFSET jackboxWorldArt3D
|
||
invoke FreeAnimPack3D, OFFSET jackboxScreenArt3D
|
||
ret
|
||
FreeJackboxArt3D ENDP
|
||
|
||
ResolveJackboxSurface3D PROC material:DWORD
|
||
cmp jackboxWorldArt3D.pixels, 0
|
||
je jackbox_surface_missing
|
||
mov eax, material
|
||
cmp eax, MATERIAL_JACKBOX_FRONT
|
||
je jackbox_surface_front
|
||
cmp eax, MATERIAL_JACKBOX_SIDE
|
||
je jackbox_surface_side
|
||
cmp eax, MATERIAL_JACKBOX_BACK
|
||
jne jackbox_surface_missing
|
||
; Frame 2: rear panel (offset 256*512*4*2 = 1048576)
|
||
mov eax, jackboxWorldArt3D.pixels
|
||
add eax, 1048576
|
||
mov ecx, 256
|
||
mov edx, 512
|
||
ret
|
||
jackbox_surface_side:
|
||
; Frame 1: side profile (offset 256*512*4 = 524288)
|
||
mov eax, jackboxWorldArt3D.pixels
|
||
add eax, 524288
|
||
mov ecx, 256
|
||
mov edx, 512
|
||
ret
|
||
jackbox_surface_front:
|
||
; Frame 0: front face
|
||
mov eax, jackboxWorldArt3D.pixels
|
||
mov ecx, 256
|
||
mov edx, 512
|
||
ret
|
||
jackbox_surface_missing:
|
||
xor eax, eax
|
||
ret
|
||
ResolveJackboxSurface3D ENDP
|
||
|
||
DrawJackboxCabinet3D PROC uses ebx esi edi wx:DWORD, wy:DWORD
|
||
local x0:DWORD, x1:DWORD, y0:DWORD, y1:DWORD
|
||
; Solid rectangular cabinet against East wall beside billiards:
|
||
; Depth along X: 0.55m (x0 = 30.40m, x1 = 30.95m against wall at 31.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
|
||
mov x0, FP_1*304/10
|
||
mov x1, FP_1*3095/100
|
||
mov y0, FP_1*235/10 - FP_1*425/1000
|
||
mov y1, FP_1*235/10 + FP_1*425/1000
|
||
|
||
; 1. Back Face (against East wall: X = x1)
|
||
invoke DrawCityVertical3D, 0, x1, y0, y1, 0, FP_1*37/20, MATERIAL_JACKBOX_BACK
|
||
; 2. North Side (Y = y0) - Authentic wooden terminal cabinet panel with brass trim
|
||
invoke DrawCityVertical3D, 1, y0, x0, x1, 0, FP_1*37/20, MATERIAL_JACKBOX_SIDE
|
||
; 3. South Side (Y = y1) - Authentic wooden terminal cabinet panel with brass trim
|
||
invoke DrawCityVertical3D, 1, y1, x0, x1, 0, FP_1*37/20, MATERIAL_JACKBOX_SIDE
|
||
; 4. Front Face (facing West towards billiards: X = x0)
|
||
invoke DrawCityVertical3D, 0, x0, y0, y1, 0, FP_1*37/20, MATERIAL_JACKBOX_FRONT
|
||
; 5. Top Lid (horizontal cap at z = 1.85m)
|
||
invoke DrawCityHorizontal3D, x0, x1, y0, y1, FP_1*37/20, 110
|
||
ret
|
||
DrawJackboxCabinet3D ENDP
|
||
|
||
RenderJackboxCabinet3D PROC
|
||
invoke DrawJackboxCabinet3D, JACKBOX_X, JACKBOX_Y
|
||
ret
|
||
RenderJackboxCabinet3D ENDP
|
||
|
||
JackboxCanWalk3D PROC px:DWORD, py:DWORD
|
||
mov eax, px
|
||
cmp eax, FP_1*303/10
|
||
jb jackbox_walk_clear
|
||
cmp eax, 31*FP_1+9830
|
||
ja jackbox_walk_clear
|
||
mov eax, py
|
||
sub eax, FP_1*235/10
|
||
test eax, eax
|
||
jns @F
|
||
neg eax
|
||
@@:
|
||
cmp eax, FP_1*55/100
|
||
ja jackbox_walk_clear
|
||
xor eax, eax
|
||
ret
|
||
jackbox_walk_clear:
|
||
mov eax, 1
|
||
ret
|
||
JackboxCanWalk3D ENDP
|
||
|
||
PlayJukeboxTrack3D PROC uses ebx trackIndex:DWORD
|
||
invoke mciSendStringA, OFFSET jboxStopCmd, 0, 0, 0
|
||
invoke mciSendStringA, OFFSET jboxCloseCmd, 0, 0, 0
|
||
mov jboxIsPlaying, 0
|
||
|
||
mov ebx, trackIndex
|
||
cmp ebx, 9
|
||
jae jbox_play_done
|
||
cmp ebx, JACKBOX_TRACK_COUNT
|
||
jae jbox_play_done
|
||
|
||
mov eax, jboxOpenCommands[ebx*4]
|
||
test eax, eax
|
||
jz jbox_play_done
|
||
invoke mciSendStringA, eax, 0, 0, 0
|
||
invoke mciSendStringA, OFFSET jboxPlayCmd, 0, 0, 0
|
||
mov jboxCurrentTrack, ebx
|
||
mov jboxIsPlaying, 1
|
||
jbox_play_done:
|
||
ret
|
||
PlayJukeboxTrack3D ENDP
|
||
|
||
StopJukeboxTrack3D PROC
|
||
invoke mciSendStringA, OFFSET jboxStopCmd, 0, 0, 0
|
||
invoke mciSendStringA, OFFSET jboxCloseCmd, 0, 0, 0
|
||
mov jboxIsPlaying, 0
|
||
mov jboxCurrentTrack, -1
|
||
ret
|
||
StopJukeboxTrack3D ENDP
|
||
|
||
BeginJackbox3D PROC
|
||
mov engineMode, MODE_JACKBOX
|
||
call ClearKeys3D
|
||
mov mouseClick3D, 0
|
||
ret
|
||
BeginJackbox3D ENDP
|
||
|
||
HandleJackbox3D PROC uses ebx esi
|
||
; 1. Mouse interactions
|
||
cmp mouseClick3D, 0
|
||
je jbox_keys
|
||
|
||
; Exit via Top-Right LCD slot: x in [232..284], y in [12..26]
|
||
cmp mouseY3D, 12
|
||
jb @F
|
||
cmp mouseY3D, 26
|
||
ja @F
|
||
cmp mouseX3D, 232
|
||
jb @F
|
||
cmp mouseX3D, 284
|
||
jbe jbox_exit
|
||
@@:
|
||
; Exit via Bottom Red CANCEL button: x in [224..256], y in [195..225]
|
||
cmp mouseY3D, 195
|
||
jb @F
|
||
cmp mouseY3D, 225
|
||
ja @F
|
||
cmp mouseX3D, 224
|
||
jb @F
|
||
cmp mouseX3D, 256
|
||
jbe jbox_exit
|
||
@@:
|
||
; Bottom Green START button: x in [154..188], y in [195..225] -> Play selected
|
||
cmp mouseY3D, 195
|
||
jb @F
|
||
cmp mouseY3D, 225
|
||
ja @F
|
||
cmp mouseX3D, 154
|
||
jb @F
|
||
cmp mouseX3D, 188
|
||
jbe jbox_play_selected
|
||
@@:
|
||
; Bottom Orange SELECT button: x in [190..222], y in [195..225] -> Next track & play
|
||
cmp mouseY3D, 195
|
||
jb @F
|
||
cmp mouseY3D, 225
|
||
ja @F
|
||
cmp mouseX3D, 190
|
||
jb @F
|
||
cmp mouseX3D, 222
|
||
ja @F
|
||
inc jboxSelectedTrack
|
||
cmp jboxSelectedTrack, JACKBOX_TRACK_COUNT
|
||
jb jbox_play_selected
|
||
mov jboxSelectedTrack, 0
|
||
jmp jbox_play_selected
|
||
@@:
|
||
; Bottom Left Arrow: x in [256..274], y in [204..224] -> Prev track
|
||
cmp mouseY3D, 204
|
||
jb @F
|
||
cmp mouseY3D, 224
|
||
ja @F
|
||
cmp mouseX3D, 256
|
||
jb @F
|
||
cmp mouseX3D, 274
|
||
ja @F
|
||
dec jboxSelectedTrack
|
||
jns jbox_play_selected
|
||
mov jboxSelectedTrack, JACKBOX_TRACK_COUNT - 1
|
||
jmp jbox_play_selected
|
||
@@:
|
||
; Bottom Right Arrow: x in [276..294], y in [204..224] -> Next track
|
||
cmp mouseY3D, 204
|
||
jb @F
|
||
cmp mouseY3D, 224
|
||
ja @F
|
||
cmp mouseX3D, 276
|
||
jb @F
|
||
cmp mouseX3D, 294
|
||
ja @F
|
||
inc jboxSelectedTrack
|
||
cmp jboxSelectedTrack, JACKBOX_TRACK_COUNT
|
||
jb jbox_play_selected
|
||
mov jboxSelectedTrack, 0
|
||
jmp jbox_play_selected
|
||
@@:
|
||
; Check track row click inside CRT screen: x in [46..274], y in [65..165]
|
||
cmp mouseY3D, 65
|
||
jb jbox_keys
|
||
cmp mouseY3D, 165
|
||
ja jbox_keys
|
||
cmp mouseX3D, 46
|
||
jb jbox_keys
|
||
cmp mouseX3D, 274
|
||
ja jbox_keys
|
||
mov eax, mouseY3D
|
||
sub eax, 65
|
||
xor edx, edx
|
||
mov ebx, 10
|
||
div ebx
|
||
cmp eax, JACKBOX_TRACK_COUNT
|
||
jae jbox_keys
|
||
mov jboxSelectedTrack, eax
|
||
invoke PlayJukeboxTrack3D, eax
|
||
jmp jbox_handled
|
||
|
||
jbox_keys:
|
||
; Exit keys: ESC (1Bh) or 'E' (45h)
|
||
invoke Pressed3D, 1Bh
|
||
test eax, eax
|
||
jnz jbox_exit
|
||
invoke Pressed3D, 45h
|
||
test eax, eax
|
||
jnz jbox_exit
|
||
|
||
; Navigation: UP (26h) / DOWN (28h)
|
||
invoke Pressed3D, 26h
|
||
test eax, eax
|
||
jz @F
|
||
dec jboxSelectedTrack
|
||
jns jbox_handled
|
||
mov jboxSelectedTrack, JACKBOX_TRACK_COUNT - 1
|
||
jmp jbox_handled
|
||
@@:
|
||
invoke Pressed3D, 28h
|
||
test eax, eax
|
||
jz @F
|
||
inc jboxSelectedTrack
|
||
cmp jboxSelectedTrack, JACKBOX_TRACK_COUNT
|
||
jb jbox_handled
|
||
mov jboxSelectedTrack, 0
|
||
jmp jbox_handled
|
||
@@:
|
||
; Play selection: ENTER (0Dh) or SPACE (20h)
|
||
invoke Pressed3D, 0Dh
|
||
test eax, eax
|
||
jnz jbox_play_selected
|
||
invoke Pressed3D, 20h
|
||
test eax, eax
|
||
jnz jbox_play_selected
|
||
|
||
; Stop key: 'S' (53h)
|
||
invoke Pressed3D, 53h
|
||
test eax, eax
|
||
jz @F
|
||
call StopJukeboxTrack3D
|
||
jmp jbox_handled
|
||
@@:
|
||
; Random key: 'R' (52h)
|
||
invoke Pressed3D, 52h
|
||
test eax, eax
|
||
jz @F
|
||
invoke RandomRange3D, 9
|
||
mov jboxSelectedTrack, eax
|
||
invoke PlayJukeboxTrack3D, eax
|
||
jmp jbox_handled
|
||
@@:
|
||
; Direct digit keys '1'..'9'
|
||
mov ebx, 31h ; '1'
|
||
jbox_digit_loop:
|
||
invoke Pressed3D, ebx
|
||
test eax, eax
|
||
jz jbox_digit_next
|
||
mov eax, ebx
|
||
sub eax, 31h
|
||
mov jboxSelectedTrack, eax
|
||
invoke PlayJukeboxTrack3D, eax
|
||
jmp jbox_handled
|
||
jbox_digit_next:
|
||
inc ebx
|
||
cmp ebx, 39h ; '9'
|
||
jbe jbox_digit_loop
|
||
|
||
; '0' key for mute/stop
|
||
invoke Pressed3D, 30h
|
||
test eax, eax
|
||
jz jbox_handled
|
||
mov jboxSelectedTrack, 9
|
||
invoke PlayJukeboxTrack3D, 9
|
||
jmp jbox_handled
|
||
|
||
jbox_play_selected:
|
||
invoke PlayJukeboxTrack3D, jboxSelectedTrack
|
||
jmp jbox_handled
|
||
|
||
jbox_exit:
|
||
mov engineMode, MODE_WALK
|
||
call ClearKeys3D
|
||
|
||
jbox_handled:
|
||
mov mouseClick3D, 0
|
||
ret
|
||
HandleJackbox3D ENDP
|
||
|
||
RenderJackbox3D PROC uses ebx esi edi
|
||
local rowY:DWORD, color:DWORD
|
||
|
||
; 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 "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||
jmp jbox_top_lcd_exit
|
||
jbox_top_lcd_stopped:
|
||
invoke DrawString8x8, 45, 17, OFFSET jboxLcdStop, 008CB8A5h ; Dim green "<EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||
jbox_top_lcd_exit:
|
||
; Right slot: exit button text
|
||
invoke DrawString8x8, 241, 17, OFFSET jboxLcdExit, 00F2A648h ; Amber "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||
|
||
; 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 "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>:"
|
||
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 "<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>"
|
||
|
||
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
|