solitaire-c64/winscreen.c65
2026-01-18 17:30:16 +01:00

139 lines
4 KiB
Text

#IFNDEF __lib_winscreen
#DEFINE __lib_winscreen 1
GOTO __skip_lib_winscreen
// ============================================================================
// WIN SCREEN
// Displays "YOU WIN!" celebration when game is won
// ============================================================================
BYTE CONST WIN_LOGO_CHAR = $50 // Hearts suit character
BYTE CONST WIN_CLEAR_CHAR = 0 // Solid block (shows color RAM color)
// Logo dimensions and position
// Logo is 26 chars wide x 5 chars tall, centered on 40x25 screen
BYTE CONST WIN_LOGO_WIDTH = 26
BYTE CONST WIN_LOGO_HEIGHT = 5
BYTE CONST WIN_LOGO_START_COL = 7 // (40-26)/2 = 7
BYTE CONST WIN_LOGO_START_ROW = 10 // (25-5)/2 = 10
// Clear area with 1 char padding on sides
BYTE CONST WIN_CLEAR_WIDTH = 28
BYTE CONST WIN_CLEAR_START_COL = 6
// Screen base
WORD CONST SCREEN_BASE = $0400
// ----------------------------------------------------------------------------
// Logo offset data
// Each byte is an offset from logo top-left where hearts char goes
// Arranged visually to show letter shapes in source
// ----------------------------------------------------------------------------
LABEL win_logo_offsets
ASM
; "YOU WIN!" - 5 rows x 26 cols
; Offsets where hearts char ($50) is placed
;
; Y O U W I N !
;
; Row 0:
; █ █ ███ █ █ █ █ █ █ █ █
!8 0,2, 4,5,6, 8,10, 13,17, 19, 21,23, 25
;
; Row 1:
; █ █ █ █ █ █ █ █ ███ █
!8 41, 44,46, 48,50, 53,57, 59, 61,62,63,65
;
; Row 2:
; █ █ █ █ █ █ █ █ █ █ █ █
!8 81, 84,86, 88,90, 93,95,97, 99, 101,103,105
;
; Row 3:
; █ █ █ █ █ █ █ █ █ █ █
!8 121, 124,126,128,130, 133,135,137,139,141,143
;
; Row 4:
; █ ███ ███ █ █ █ █ █ █
!8 161, 164,165,166,168,169,170,174,176,179,181,183,185
;
; Terminator
!8 255
ENDASM
// ============================================================================
// FUNC clear_win_area
// Clears a rectangular area in the center of screen for the logo
// Fills with WIN_CLEAR_CHAR (solid block showing white)
// ============================================================================
FUNC clear_win_area
WORD screen_ptr @ $a0
BYTE row
BYTE col
WORD row_start
// Calculate starting position: row 10, col 6
// Offset = 10 * 40 + 6 = 406
row_start = SCREEN_BASE + 406
FOR row = 0 TO WIN_LOGO_HEIGHT-1
POINTER screen_ptr -> row_start
FOR col = 0 TO WIN_CLEAR_WIDTH-1
POKE screen_ptr[col] , WIN_CLEAR_CHAR
NEXT
// Move to next row (add 40)
row_start = row_start + 40
NEXT
FEND
// ============================================================================
// FUNC draw_win_logo
// Draws "YOU WIN!" using hearts characters at the calculated offsets
// Must call clear_win_area first
// ============================================================================
FUNC draw_win_logo
WORD screen_ptr @ $a0
WORD offset_ptr @ $a2
WORD logo_base
BYTE offset
// Logo base position: row 10, col 7
// Offset = 10 * 40 + 7 = 407
logo_base = SCREEN_BASE + 407
POINTER offset_ptr -> win_logo_offsets
BYTE index
index = 0
// Loop through all offsets until terminator (255)
offset = PEEK offset_ptr[index]
WHILE offset != 255
// Calculate screen address: logo_base + offset
screen_ptr = logo_base + offset
// Poke hearts character
POKE screen_ptr[0] , WIN_LOGO_CHAR
// Next offset
index = index + 1
offset = PEEK offset_ptr[index]
WEND
FEND
// ============================================================================
// FUNC show_win_screen
// Main entry point - clears area and draws the win logo
// ============================================================================
FUNC show_win_screen
clear_win_area()
draw_win_logo()
FEND
LABEL __skip_lib_winscreen
#IFEND