Tightened up the code with better label and pointer handling. README improved.
This commit is contained in:
parent
f4bff18f29
commit
788c6ed60d
5 changed files with 20 additions and 58 deletions
21
README.md
21
README.md
|
|
@ -1,26 +1,17 @@
|
|||
# Solitaire C64
|
||||
|
||||
A classic Klondike solitaire card game for the Commodore 64, written in c65gm.
|
||||
A classic Klondike solitaire card game for the Commodore 64.
|
||||
|
||||
## Features
|
||||
|
||||
- **Full Klondike Solitaire**: Stock, waste, 7 tableaus, and 4 foundation piles
|
||||
- **Dual Input Support**: Play with joystick or 1351 mouse
|
||||
- **Draw Modes**: Toggle between draw-1 and draw-3 gameplay
|
||||
- **Custom Graphics**: Character-based card rendering using extended color mode
|
||||
- **Sprite Cursor**: Visual pointer for card selection and movement
|
||||
- **Smart Shuffling**: Hardware-seeded RNG for true randomness
|
||||
|
||||
## Technical Details
|
||||
|
||||
**Language**: c65gm (C-like language for 6502/C64)
|
||||
**Memory Layout**: Code at $3000, custom charset at $2000
|
||||
**Graphics**: Extended Color Mode (ECM) with custom character set
|
||||
**Input**: CIA joystick ports + 1351 proportional mouse support
|
||||
- Full Klondike with draw-1 and draw-3 modes
|
||||
- Joystick and 1351 mouse support
|
||||
- Extended color mode graphics with sprite cursor
|
||||
- Hardware-seeded RNG for shuffling
|
||||
|
||||
## Building
|
||||
|
||||
Requires the c65gm compiler and ACME assembler:
|
||||
Requires the [c65gm compiler](https://git.techserio.com/mattiashz/c65gm) and ACME assembler:
|
||||
|
||||
```bash
|
||||
./cm.sh
|
||||
|
|
|
|||
29
carddeck.c65
29
carddeck.c65
|
|
@ -95,28 +95,13 @@ FEND
|
|||
// Tab0=1, Tab1=2, Tab2=3, Tab3=4, Tab4=5, Tab5=6, Tab6=7 cards
|
||||
// Top card of each tableau is face up
|
||||
FUNC deal_tableaus
|
||||
WORD ptr
|
||||
|
||||
POINTER ptr -> pile_tab0
|
||||
deal_to_tableau(ptr, 1)
|
||||
|
||||
POINTER ptr -> pile_tab1
|
||||
deal_to_tableau(ptr, 2)
|
||||
|
||||
POINTER ptr -> pile_tab2
|
||||
deal_to_tableau(ptr, 3)
|
||||
|
||||
POINTER ptr -> pile_tab3
|
||||
deal_to_tableau(ptr, 4)
|
||||
|
||||
POINTER ptr -> pile_tab4
|
||||
deal_to_tableau(ptr, 5)
|
||||
|
||||
POINTER ptr -> pile_tab5
|
||||
deal_to_tableau(ptr, 6)
|
||||
|
||||
POINTER ptr -> pile_tab6
|
||||
deal_to_tableau(ptr, 7)
|
||||
deal_to_tableau(@pile_tab0, 1)
|
||||
deal_to_tableau(@pile_tab1, 2)
|
||||
deal_to_tableau(@pile_tab2, 3)
|
||||
deal_to_tableau(@pile_tab3, 4)
|
||||
deal_to_tableau(@pile_tab4, 5)
|
||||
deal_to_tableau(@pile_tab5, 6)
|
||||
deal_to_tableau(@pile_tab6, 7)
|
||||
FEND
|
||||
|
||||
// Clear the seen array
|
||||
|
|
|
|||
|
|
@ -84,13 +84,7 @@ FUNC main
|
|||
set_vic_charmem(4) // $2000
|
||||
set_vic_ecm()
|
||||
|
||||
|
||||
WORD charset_ptr
|
||||
WORD charset_end_ptr
|
||||
POINTER charset_ptr -> card_charset
|
||||
POINTER charset_end_ptr -> card_charset_end
|
||||
mem_copy(charset_ptr, charset_end_ptr, $2000)
|
||||
//mem_copy_range(charset_ptr, $2000, 512)
|
||||
mem_copy(@card_charset, @card_charset_end, $2000)
|
||||
|
||||
fill_mem($d800, $d800+999, color_white) // Fill color mem
|
||||
POKE $d020 , color_white //color_grey
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ FEND
|
|||
|
||||
// Waste to Tableau
|
||||
FUNC move_waste_to_tab({WORD tab_ptr} out:{BYTE success})
|
||||
WORD waste_ptr @ $8c
|
||||
WORD waste_ptr
|
||||
POINTER waste_ptr -> pile_waste
|
||||
BYTE card
|
||||
BYTE valid
|
||||
|
|
@ -249,7 +249,7 @@ FEND
|
|||
|
||||
// Waste to Foundation
|
||||
FUNC move_waste_to_found({WORD found_ptr} out:{BYTE success})
|
||||
WORD waste_ptr @ $aa
|
||||
WORD waste_ptr
|
||||
POINTER waste_ptr -> pile_waste
|
||||
BYTE card
|
||||
BYTE valid
|
||||
|
|
@ -273,7 +273,7 @@ FUNC move_waste_to_found({WORD found_ptr} out:{BYTE success})
|
|||
FEND
|
||||
|
||||
// Tableau to Foundation (top card only)
|
||||
FUNC move_tab_to_found({WORD tab_ptr @ $8e} {WORD found_ptr} out:{BYTE success})
|
||||
FUNC move_tab_to_found({WORD tab_ptr} {WORD found_ptr} out:{BYTE success})
|
||||
BYTE card
|
||||
BYTE valid
|
||||
BYTE is_facedown
|
||||
|
|
@ -358,7 +358,7 @@ FUNC move_tab_to_tab({WORD src_ptr @ $b0} {WORD dst_ptr} {BYTE card_count} out:{
|
|||
FEND
|
||||
|
||||
// Foundation to Tableau (optional rule - some variants allow this)
|
||||
FUNC move_found_to_tab({WORD found_ptr @ $84} {WORD tab_ptr} out:{BYTE success})
|
||||
FUNC move_found_to_tab({WORD found_ptr} {WORD tab_ptr} out:{BYTE success})
|
||||
BYTE card
|
||||
BYTE valid
|
||||
|
||||
|
|
|
|||
12
gameloop.c65
12
gameloop.c65
|
|
@ -871,22 +871,14 @@ FUNC game_loop
|
|||
BYTE button_state
|
||||
BYTE clicked
|
||||
BYTE is_won
|
||||
WORD src_ptr @ $8a
|
||||
WORD src_end_ptr
|
||||
WORD dst_ptr
|
||||
|
||||
// Copy sprite data to $2200 (sprite block 136)
|
||||
// $2000-$21FF reserved for charset
|
||||
POINTER src_ptr -> pointer_sprite_data
|
||||
POINTER src_end_ptr -> pointer_sprite_data_end
|
||||
POINTER dst_ptr -> $2200
|
||||
mem_copy(src_ptr, src_end_ptr, dst_ptr)
|
||||
mem_copy(@pointer_sprite_data, @pointer_sprite_data_end, $2200)
|
||||
|
||||
// Copy card sprite data to $2240 (sprite blocks 137+)
|
||||
// 26 sprites × 64 bytes = 1664 bytes (includes "RETURN FOR MENU" sprite)
|
||||
POINTER src_ptr -> sprite_rank_ace
|
||||
POINTER dst_ptr -> $2240
|
||||
mem_copy_range(src_ptr, dst_ptr, 64*26)
|
||||
mem_copy_range(@sprite_rank_ace, $2240, 64*26)
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue