; ============================================================================== ; 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, 2 jae jbox_play_stop_selected cmp ebx, JACKBOX_TRACK_COUNT jae jbox_play_stop_selected mov eax, jboxOpenCommands[ebx*4] test eax, eax jz jbox_play_stop_selected invoke mciSendStringA, eax, 0, 0, 0 invoke mciSendStringA, OFFSET jboxPlayCmd, 0, 0, 0 mov jboxCurrentTrack, ebx mov jboxIsPlaying, 1 mov jboxEffectiveVolume, -1 call UpdateJukeboxAudio3D ret jbox_play_stop_selected: mov jboxCurrentTrack, -1 call UpdateJukeboxAudio3D 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 call UpdateJukeboxAudio3D 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 @@: ; Track list click: x in [46..274], y in [66..108], step = 14 cmp mouseY3D, 66 jb jbox_keys cmp mouseY3D, 108 ja jbox_keys cmp mouseX3D, 46 jb jbox_keys cmp mouseX3D, 274 ja jbox_keys mov eax, mouseY3D sub eax, 66 xor edx, edx mov ebx, 14 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, 2 mov jboxSelectedTrack, eax invoke PlayJukeboxTrack3D, eax jmp jbox_handled @@: ; Direct digit keys '1'..'2' 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, 32h ; '2' jbe jbox_digit_loop ; '0' key for mute/stop invoke Pressed3D, 30h test eax, eax jz jbox_handled mov jboxSelectedTrack, 2 invoke PlayJukeboxTrack3D, 2 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, 2 jae jbox_top_lcd_stopped invoke DrawString8x8, 42, 17, OFFSET jboxLcdPlay, 0050FF90h jmp jbox_top_lcd_exit jbox_top_lcd_stopped: invoke DrawString8x8, 45, 17, OFFSET jboxLcdStop, 008CB8A5h jbox_top_lcd_exit: ; Right slot: exit button text invoke DrawString8x8, 241, 17, OFFSET jboxLcdExit, 00F2A648h ; 4. CRT Monitor Header: Now Playing Status cmp jboxIsPlaying, 1 jne jbox_render_stopped cmp jboxCurrentTrack, -1 je jbox_render_stopped cmp jboxCurrentTrack, 2 jae jbox_render_stopped invoke DrawString8x8, 48, 52, OFFSET jboxHdrNow, 0050FF90h 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 jbox_render_divider: invoke DrawBox, 46, 62, 228, 1, 001C3828h ; 5. Track Selection List (3 rows, step Y = 14, from Y = 70) mov rowY, 70 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, 10, 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, 14 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 ; ============================================================================== ; 3D SOUND PROPAGATION & MULTI-FLOOR ATTENUATION ; ============================================================================== CalculateJukeboxFalloff PROC uses ebx esi edi local dxDist:DWORD, dyDist:DWORD, distSq:DWORD, distVal:DWORD local factor:DWORD ; If music is not playing, factor = 0 cmp jboxIsPlaying, 1 jne falloff_silent cmp jboxCurrentTrack, -1 je falloff_silent cmp jboxCurrentTrack, 2 jae falloff_silent ; Check if on stairs (MODE_STAIRS) cmp engineMode, MODE_STAIRS je falloff_stairs ; Check floor level mov eax, hallLevel3D cmp eax, 0 je falloff_ground cmp eax, 1 je falloff_bunker cmp eax, 2 je falloff_upper cmp eax, 3 je falloff_fortune jmp falloff_silent falloff_ground: ; Level 0 (Ground Hall) - standard quadratic 2D distance falloff from Jackbox ; Jackbox: JACKBOX_X = 30.6m, JACKBOX_Y = 23.5m mov eax, playerX sub eax, JACKBOX_X test eax, eax jns @F neg eax @@: shr eax, 16 ; integer meters mov dxDist, eax mov eax, playerY sub eax, JACKBOX_Y test eax, eax jns @F neg eax @@: shr eax, 16 ; integer meters mov dyDist, eax ; distSq = dx*dx + dy*dy mov eax, dxDist imul eax, eax mov ebx, dyDist imul ebx, ebx add eax, ebx mov distSq, eax ; distVal = sqrt(distSq) fild distSq fsqrt fistp distVal ; Acoustic curve: ; dist <= 2m -> factor = 1000 ; dist >= 35m -> factor = 0 ; in between: rem = 35 - dist; factor = 1000 * rem * rem / 1089 mov eax, distVal cmp eax, 2 jbe falloff_full cmp eax, 35 jae falloff_silent mov ecx, 35 sub ecx, eax ; ecx = 35 - distVal (in 1..32) imul eax, ecx, 1000 imul eax, ecx ; eax = 1000 * rem * rem xor edx, edx mov ebx, 1089 ; 33 * 33 div ebx mov factor, eax jmp falloff_done falloff_full: mov factor, 1000 jmp falloff_done falloff_upper: ; Level 2 (Upper Lounge) - sound travels up the open stairs (stairwell at X=16, Y=21 on upper map) ; Base attenuation through floor + distance from stairwell opening mov eax, playerX sub eax, 16*FP_1 test eax, eax jns @F neg eax @@: shr eax, 16 mov dxDist, eax mov eax, playerY sub eax, 21*FP_1 test eax, eax jns @F neg eax @@: shr eax, 16 mov dyDist, eax mov eax, dxDist imul eax, eax mov ebx, dyDist imul ebx, ebx add eax, ebx mov distSq, eax fild distSq fsqrt fistp distVal ; At stair opening: factor = 420 (muffled from below) ; Drops by 18 per meter, min 90 mov eax, distVal imul eax, 18 mov ecx, 420 sub ecx, eax cmp ecx, 90 jge @F mov ecx, 90 @@: mov factor, ecx jmp falloff_done falloff_bunker: ; Level 1 (Bunker) - underground, heavily muffled concrete absorption (~160) mov factor, 160 jmp falloff_done falloff_fortune: ; Level 3 (Fortune Room) - secret room on opposite side of casino (~90) mov factor, 90 jmp falloff_done falloff_stairs: ; On stairs between floors mov eax, stairRoute3D cmp eax, 2 je falloff_stairs_upper cmp eax, 1 je falloff_stairs_bunker mov factor, 150 jmp falloff_done falloff_stairs_upper: ; Route 2 (Upper stairs) ; playerX goes from ~3 (bottom, beside jukebox) to ~16 (top, upper floor) ; At bottom: 850. At top: 420. mov eax, playerX shr eax, 16 ; integer X (3..16) cmp eax, 3 jge @F mov eax, 3 @@: cmp eax, 16 jle @F mov eax, 16 @@: ; Interpolate: factor = 850 - (eax - 3) * (850 - 420) / 13 sub eax, 3 imul eax, 430 xor edx, edx mov ebx, 13 div ebx mov ecx, 850 sub ecx, eax mov factor, ecx jmp falloff_done falloff_stairs_bunker: ; Route 1 (Basement stairs) ; Smooth blend between 350 (top) and 160 (bottom) mov factor, 250 jmp falloff_done falloff_silent: mov factor, 0 falloff_done: mov eax, factor ret CalculateJukeboxFalloff ENDP UpdateJukeboxAudio3D PROC uses ebx esi edi local falloff:DWORD, targetVol:DWORD ; Check if music is playing cmp jboxIsPlaying, 1 jne jbox_audio_mute ; If user volume is 0 -> mute mov eax, jboxUserVolume test eax, eax jz jbox_audio_mute ; Calculate 3D attenuation factor (0..1000) call CalculateJukeboxFalloff mov falloff, eax test eax, eax jz jbox_audio_mute ; targetVol = (jboxUserVolume * 100) * falloff / 1000 ; jboxUserVolume is 0..10 (0..1000 base) mov eax, jboxUserVolume imul eax, 100 imul eax, falloff xor edx, edx mov ebx, 1000 div ebx mov targetVol, eax jmp jbox_apply_vol jbox_audio_mute: mov targetVol, 0 jbox_apply_vol: ; If targetVol matches last applied volume, skip redundant MCI call mov eax, targetVol cmp eax, jboxEffectiveVolume je jbox_audio_done mov jboxEffectiveVolume, eax ; Format: "setaudio jboxmusic volume to " ; Copy prefix to jboxVolCmdBuf lea esi, jboxVolCmdPrefix lea edi, jboxVolCmdBuf jbox_vol_copy: lodsb stosb test al, al jnz jbox_vol_copy dec edi ; point at null terminator ; Append decimal number targetVol invoke FormatNumber, targetVol, edi ; Send to MCI invoke mciSendStringA, OFFSET jboxVolCmdBuf, 0, 0, 0 jbox_audio_done: ret UpdateJukeboxAudio3D ENDP ; ============================================================================== ; VOLUME CONTROL KEYS & POP-UP SLIDING HUD BAR ; ============================================================================== HandleJukeboxKeys3D PROC ; '+' key: VK_OEM_PLUS (0BBh) or VK_ADD (6Bh - numpad +) invoke Pressed3D, 0BBh test eax, eax jnz jbox_do_plus invoke Pressed3D, 6Bh test eax, eax jz jbox_check_minus jbox_do_plus: cmp jboxUserVolume, 10 jae @F inc jboxUserVolume @@: mov jboxHudTimer, 90 ; Show HUD for ~1.5s call UpdateJukeboxAudio3D ret jbox_check_minus: ; '-' key: VK_OEM_MINUS (0BDh) or VK_SUBTRACT (6Dh - numpad -) invoke Pressed3D, 0BDh test eax, eax jnz jbox_do_minus invoke Pressed3D, 6Dh test eax, eax jz jbox_keys_done jbox_do_minus: cmp jboxUserVolume, 0 jbe @F dec jboxUserVolume @@: mov jboxHudTimer, 90 ; Show HUD for ~1.5s call UpdateJukeboxAudio3D jbox_keys_done: ret HandleJukeboxKeys3D ENDP RenderJukeboxVolumeHUD PROC uses ebx esi edi local winX:DWORD, winY:DWORD, barX:DWORD, barY:DWORD, barW:DWORD, barH:DWORD local numBuf[16]:BYTE ; 1. Update Timer and Animation Position cmp jboxHudTimer, 0 je hud_sliding_down ; Active: decrement timer dec jboxHudTimer ; Slide UP towards target Y = 206 cmp jboxHudY, 206 jbe hud_at_target sub jboxHudY, 4 cmp jboxHudY, 206 jae hud_at_target mov jboxHudY, 206 hud_at_target: jmp hud_draw hud_sliding_down: ; Timer expired: slide DOWN towards 240 (offscreen) cmp jboxHudY, 240 jae hud_hidden add jboxHudY, 3 cmp jboxHudY, 240 jbe hud_draw mov jboxHudY, 240 hud_hidden: ret hud_draw: mov eax, jboxHudY mov winY, eax mov winX, 72 ; Centered in 320: width 176 ; 2. Background and Frame ; Outer dark shadow (178 x 30) mov eax, winX dec eax mov ecx, winY dec ecx invoke DrawBox, eax, ecx, 178, 30, 0008100Ch ; Outer bezel (176 x 28) invoke DrawBox, winX, winY, 176, 28, 001C2E24h ; Inner panel body (174 x 26) mov eax, winX inc eax mov ecx, winY inc ecx invoke DrawBox, eax, ecx, 174, 26, 00101A14h ; Brass top trim accent (174 x 1) mov eax, winX inc eax mov ecx, winY inc ecx invoke DrawBox, eax, ecx, 174, 1, 008A6B34h ; 3. Title text: "MUZ. AVTOMAT: " + percentage mov eax, winX add eax, 10 mov ecx, winY add ecx, 4 invoke DrawString8x8, eax, ecx, OFFSET jboxHudTitle, 0050FF90h ; Draw percentage or "VYKL" mov eax, winX add eax, 126 mov ecx, winY add ecx, 4 cmp jboxUserVolume, 0 jne hud_draw_pct_num invoke DrawString8x8, eax, ecx, OFFSET jboxHudMute, 008CB8A5h jmp hud_draw_trough hud_draw_pct_num: push eax push ecx mov edx, jboxUserVolume imul edx, 10 lea edi, numBuf invoke FormatNumber, edx, edi hud_find_term: cmp byte ptr [edi], 0 je hud_append_pct inc edi jmp hud_find_term hud_append_pct: mov byte ptr [edi], '%' mov byte ptr [edi+1], 0 pop ecx pop eax lea edx, numBuf invoke DrawString8x8, eax, ecx, edx, 00F0E6C3h hud_draw_trough: ; Progress trough at barX = winX + 24, barY = winY + 15, barW = 128, barH = 7 mov eax, winX add eax, 24 mov barX, eax mov ecx, winY add ecx, 15 mov barY, ecx mov barW, 128 mov barH, 7 ; Trough border mov eax, barX dec eax mov ecx, barY dec ecx invoke DrawBox, eax, ecx, 130, 9, 00223828h invoke DrawBox, barX, barY, 128, 7, 000C1610h ; Draw 10 blocks: i = 0..9 xor esi, esi hud_blocks_loop: mov eax, barX add eax, 4 mov edx, esi imul edx, 12 add eax, edx ; blockX = barX + 4 + i*12 mov ecx, barY inc ecx ; blockY = barY + 1 cmp esi, jboxUserVolume jae hud_block_empty ; Filled block color gradient cmp esi, 7 jb hud_col_green cmp esi, 9 jb hud_col_gold mov edx, 00465AFFh ; Red/orange accent for 100% jmp hud_draw_block_rect hud_col_green: mov edx, 0050FF90h ; Phosphor green jmp hud_draw_block_rect hud_col_gold: mov edx, 00FFD700h ; Golden amber jmp hud_draw_block_rect hud_block_empty: mov edx, 0018261Eh ; Dim background hud_draw_block_rect: invoke DrawBox, eax, ecx, 10, 5, edx inc esi cmp esi, 10 jb hud_blocks_loop ; Draw '-' and '+' labels mov eax, winX add eax, 8 mov ecx, winY add ecx, 15 invoke DrawString8x8, eax, ecx, OFFSET jboxHudMinus, 008CB8A5h mov eax, winX add eax, 158 mov ecx, winY add ecx, 15 invoke DrawString8x8, eax, ecx, OFFSET jboxHudPlus, 008CB8A5h ret RenderJukeboxVolumeHUD ENDP