solitaire-c64/gamemenu.c65

367 lines
9 KiB
Text

#IFNDEF __lib_gamemenu
#DEFINE __lib_gamemenu 1
#INCLUDE "pileconsts.c65"
#INCLUDE "keyboard.c65"
#INCLUDE "utils.c65"
GOTO __skip_lib_gamemenu
// ============================================================================
// GAME MENU SYSTEM
// ============================================================================
// Pause game and display menu for configuration and restart
//
// Usage:
// #INCLUDE "gamemenu.c65"
// BYTE action
// menu_show(action) // Returns MENU_ACTION_* constant
// ============================================================================
// Menu action constants
BYTE CONST MENU_ACTION_RESUME = 0
BYTE CONST MENU_ACTION_RESTART = 1
// Screen backup buffer (1000 bytes for screen, 1000 for color)
// Located at $C000-$C7CF (2000 bytes)
WORD CONST SCREEN_BACKUP = $C000
WORD CONST COLOR_BACKUP = $C3E8
// ============================================================================
// FUNC menu_save_screen
// Save current screen and color memory to backup buffer
// ============================================================================
FUNC menu_save_screen
mem_copy_range($0400, SCREEN_BACKUP, 1000)
mem_copy_range($D800, COLOR_BACKUP, 1000)
FEND
// ============================================================================
// FUNC menu_restore_screen
// Restore screen and color memory from backup buffer
// ============================================================================
FUNC menu_restore_screen
mem_copy_range(SCREEN_BACKUP, $0400, 1000)
mem_copy_range(COLOR_BACKUP, $D800, 1000)
FEND
// ============================================================================
// FUNC menu_switch_to_rom_charset
// Switch VIC-II to use ROM charset at $1800 (uppercase/lowercase)
// ============================================================================
FUNC menu_switch_to_rom_charset
set_vic_charmem(3) // $1800 / $0800 = 3
FEND
// ============================================================================
// FUNC menu_switch_to_card_charset
// Switch VIC-II back to custom card charset at $2000
// ============================================================================
FUNC menu_switch_to_card_charset
set_vic_charmem(4) // $2000 / $0800 = 4
FEND
// ============================================================================
// FUNC menu_print_string
// Print a string at a specific screen position
// ============================================================================
FUNC menu_print_string({WORD screen_pos @ $e0} {WORD str_ptr @ $e2})
BYTE char
BYTE str_offset
str_offset = 0
char = PEEK str_ptr[str_offset]
WHILE char != 0
POKE screen_pos[0] , char
screen_pos++
str_offset++
char = PEEK str_ptr[str_offset]
WEND
FEND
// ============================================================================
// FUNC menu_update_draw_mode
// Update only the draw mode display (row 6) - no screen clear
// ============================================================================
FUNC menu_update_draw_mode
WORD screen_pos @ $e0
// Clear the value area (cols 19-23)
screen_pos = 6*40+$0400+19
POKE screen_pos[0] , 32 // space
POKE screen_pos[1] , 32
POKE screen_pos[2] , 32
POKE screen_pos[3] , 32
POKE screen_pos[4] , 32
// Draw mode value - both values at same position (col 19)
// Show both [1] [3] with brackets around the selected one
screen_pos = 6*40+$0400+19
IF game_draw_mode == 1
POKE screen_pos[0] , 27 // '[' screen code
POKE screen_pos[1] , 49 // '1'
POKE screen_pos[2] , 29 // ']' screen code
POKE screen_pos[3] , 32 // space
POKE screen_pos[4] , 51 // '3'
ELSE
POKE screen_pos[0] , 49 // '1'
POKE screen_pos[1] , 32 // space
POKE screen_pos[2] , 27 // '[' screen code
POKE screen_pos[3] , 51 // '3'
POKE screen_pos[4] , 29 // ']' screen code
ENDIF
FEND
// ============================================================================
// FUNC menu_update_found_to_tab
// Update only the foundation to tableau display (row 9) - no screen clear
// ============================================================================
FUNC menu_update_found_to_tab
WORD screen_pos @ $e4
WORD str_ptr @ $e6
// Clear the value area (cols 28-30)
screen_pos = 9*40+$0400+28
POKE screen_pos[0] , 32 // space
POKE screen_pos[1] , 32
POKE screen_pos[2] , 32
// Foundation to Tableau value
screen_pos = 9*40+$0400+28
IF game_allow_found_to_tab == 0
POINTER str_ptr -> str_off
ELSE
POINTER str_ptr -> str_on
ENDIF
menu_print_string(screen_pos, str_ptr)
FEND
// ============================================================================
// FUNC menu_render
// Render the full menu screen with current settings
// ============================================================================
FUNC menu_render
// Clear screen
fill_mem($0400, $0400+999, 32) // 32 = space character
fill_mem($D800, $D800+999, 14) // Light blue text
// Title (centered at row 2)
menu_print_string(2*40+$0400+8, @str_title)
// Draw mode option (row 6)
menu_print_string(6*40+$0400+4, @str_draw_mode)
// Draw mode value and indicators
menu_update_draw_mode()
// Foundation to Tableau option (row 9)
menu_print_string(9*40+$0400+4, @str_found_to_tab)
// Foundation to Tableau value
menu_update_found_to_tab()
// Instructions for resume/restart (row 12+)
menu_print_string(12*40+$0400+4, @str_inst_f7)
menu_print_string(15*40+$0400+4, @str_inst_runstop)
// Controls info (row 20)
menu_print_string(20*40+$0400+2, @str_controls)
// License (row 23)
menu_print_string(23*40+$0400+1, @str_license)
// Set border color to menu color (purple)
POKE $d020 , 4
FEND
// ============================================================================
// FUNC menu_show
// Display menu and handle input, return action to take
// ============================================================================
FUNC menu_show(out:{BYTE action})
lib_c64scr_blank()
BYTE key
BYTE prev_key
action = MENU_ACTION_RESUME
prev_key = KEY_NONE
// Clear any card selection before entering menu
game_selected_pile = PILE_ID_NONE
game_selected_card_count = 0
// Hide menu hint sprite
menu_hint_hide()
// Save current screen state
menu_save_screen()
// Disable all sprites
POKE $D015 , 0 // Sprite enable register - disable all
// Switch to ROM charset and normal character mode
menu_switch_to_rom_charset()
clear_vic_ecm()
// Render menu
menu_render()
lib_c64scr_show()
// Wait for key release first (debounce)
key_scan(key)
WHILE key != KEY_NONE
key_scan(key)
WEND
// Menu loop
WHILE 1
key_scan(key)
// Only process on key press (transition from NONE to key)
IF key != KEY_NONE
IF prev_key == KEY_NONE
SWITCH key
CASE KEY_F1
// Toggle draw mode
IF game_draw_mode == 1
game_draw_mode = 3
ELSE
game_draw_mode = 1
ENDIF
menu_update_draw_mode()
CASE KEY_F3
// Toggle foundation to tableau
IF game_allow_found_to_tab == 0
game_allow_found_to_tab = 1
ELSE
game_allow_found_to_tab = 0
ENDIF
menu_update_found_to_tab()
CASE KEY_F7
// Resume game
action = MENU_ACTION_RESUME
BREAK
CASE KEY_RETURN
// Resume game
action = MENU_ACTION_RESUME
BREAK
CASE KEY_RUNSTOP
// Restart game
action = MENU_ACTION_RESTART
BREAK
ENDSWITCH
ENDIF
ENDIF
prev_key = key
WEND
// Wait for key release before returning
WHILE key != KEY_NONE
key_scan(key)
WEND
lib_c64scr_blank()
// Restore screen or clear for restart
IF action == MENU_ACTION_RESUME
menu_restore_screen()
ELSE
// Restarting - clear screen and reset colors
fill_mem($0400, $0400+999, 0)
fill_mem($d800, $d800+999, 1) // White color
ENDIF
// Switch back to card charset and ECM mode
menu_switch_to_card_charset()
set_vic_ecm()
// Re-enable pointer sprite (game loop will handle card display sprites)
pointer_enable(1)
// Show menu hint sprite again
menu_hint_show()
// Restore border color
POKE $d020 , 1 // White
lib_c64scr_show()
FEND
// Menu strings (null-terminated) - Using !scr for screen codes
LABEL str_title
ASM
!scr "Klondike Solitaire Menu", 0
ENDASM
LABEL str_draw_mode
ASM
!scr "F1: Draw mode:", 0
ENDASM
LABEL str_found_to_tab
ASM
!scr "F3: Foundation>Tableau:", 0
ENDASM
LABEL str_on
ASM
!scr "On", 0
ENDASM
LABEL str_off
ASM
!scr "Off", 0
ENDASM
LABEL str_inst_f1
ASM
!scr "F1: Toggle draw mode (1/3)", 0
ENDASM
LABEL str_inst_f3
ASM
!scr "F3: Toggle foundation moves", 0
ENDASM
LABEL str_inst_f7
ASM
!scr "F7: Resume game", 0
ENDASM
LABEL str_inst_runstop
ASM
!scr "Run/Stop: Restart game", 0
ENDASM
LABEL str_controls
ASM
!scr "1351 Mouse Port 1 / Joystick Port 2", 0
ENDASM
LABEL str_license
ASM
!scr "by Hackz0id/Siders 2026 (GNU GPL v2.0)", 0
ENDASM
LABEL __skip_lib_gamemenu
#IFEND