KAZIK/src_graphics/jackbox.inc

411 lines
11 KiB
PHP
Raw Blame History

; ==============================================================================
; 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