367 lines
9 KiB
Text
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
|