313 lines
7.6 KiB
Text
313 lines
7.6 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_render
|
|
// Render the menu screen with current settings
|
|
// ============================================================================
|
|
FUNC menu_render
|
|
WORD screen_pos @ $f0
|
|
WORD str_ptr @ $f2
|
|
BYTE draw_indicator
|
|
BYTE found_to_tab_indicator
|
|
|
|
// 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)
|
|
screen_pos = 2*40+$0400+8
|
|
POINTER str_ptr -> str_title
|
|
menu_print_string(screen_pos, str_ptr)
|
|
|
|
// Draw mode option (row 6)
|
|
screen_pos = 6*40+$0400+4
|
|
POINTER str_ptr -> str_draw_mode
|
|
menu_print_string(screen_pos, str_ptr)
|
|
|
|
// Draw mode value
|
|
screen_pos = 6*40+$0400+24
|
|
IF game_draw_mode == 1
|
|
POKE screen_pos[0] , 49 // '1'
|
|
ELSE
|
|
POKE screen_pos[0] , 51 // '3'
|
|
ENDIF
|
|
|
|
// Draw mode indicator
|
|
IF game_draw_mode == 1
|
|
draw_indicator = 91 // '['
|
|
screen_pos = 6*40+$0400+23
|
|
POKE screen_pos[0] , draw_indicator
|
|
screen_pos = 6*40+$0400+25
|
|
POKE screen_pos[0] , 93 // ']'
|
|
ELSE
|
|
draw_indicator = 91 // '['
|
|
screen_pos = 6*40+$0400+26
|
|
POKE screen_pos[0] , draw_indicator
|
|
screen_pos = 6*40+$0400+28
|
|
POKE screen_pos[0] , 93 // ']'
|
|
ENDIF
|
|
|
|
// Foundation to Tableau option (row 9)
|
|
screen_pos = 9*40+$0400+4
|
|
POINTER str_ptr -> str_found_to_tab
|
|
menu_print_string(screen_pos, str_ptr)
|
|
|
|
// 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)
|
|
|
|
// Instructions for resume/restart (row 14+)
|
|
screen_pos = 14*40+$0400+4
|
|
POINTER str_ptr -> str_inst_f7
|
|
menu_print_string(screen_pos, str_ptr)
|
|
|
|
screen_pos = 15*40+$0400+4
|
|
POINTER str_ptr -> str_inst_f8
|
|
menu_print_string(screen_pos, str_ptr)
|
|
|
|
// 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})
|
|
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
|
|
|
|
// 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()
|
|
|
|
// 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_render()
|
|
|
|
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_render()
|
|
|
|
CASE KEY_F7
|
|
// Resume game
|
|
action = MENU_ACTION_RESUME
|
|
BREAK
|
|
|
|
CASE KEY_F8
|
|
// Restart game (SHIFT+F7)
|
|
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
|
|
|
|
// 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)
|
|
|
|
// Restore border color
|
|
POKE $d020 , 1 // White
|
|
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_f8
|
|
ASM
|
|
!scr "F8: Restart game", 0
|
|
ENDASM
|
|
|
|
|
|
LABEL __skip_lib_gamemenu
|
|
|
|
#IFEND
|