From 6ae8587fed4c1320dca8cdb5f03a68d52ff23c5f Mon Sep 17 00:00:00 2001 From: Mattias Hansson Date: Sun, 18 Jan 2026 17:30:16 +0100 Subject: [PATCH] Added win screen --- CLAUDE.md | 151 +++++++++++++++++++++++++++++++++++++++ cardgame.c65 | 1 + exomizer_compress_prg.sh | 2 +- gameloop.c65 | 12 ++-- gamestate.c65 | 3 + winscreen.c65 | 139 +++++++++++++++++++++++++++++++++++ 6 files changed, 302 insertions(+), 6 deletions(-) create mode 100644 CLAUDE.md create mode 100644 winscreen.c65 diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..1d5f49d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,151 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Development Workflow + +This is a collaborative pair programming effort. Claude runs in a Docker environment with access to the codebase but cannot build or run the project. The user handles all builds and testing. + +## Project Overview + +Solitaire C64 is a Klondike solitaire card game for the Commodore 64, written in c65gm (a high-level language that compiles to 6502 assembly). Language documentation is available in `language_docs/`. + +## Build Commands + +```bash +./cm.sh # Build the project (outputs main.prg) +./start_in_vice.sh # Launch in VICE emulator +./exomizer_compress_prg.sh # Compress binary with Exomizer +``` + +Build chain: C65 source → c65gm compiler → 6502 assembly → ACME assembler → main.prg + +Requirements: +- [c65gm compiler](https://git.techserio.com/mattiashz/c65gm) +- ACME 6502 assembler + +## Testing + +Enable test modes by uncommenting `#DEFINE TEST_GAMES 1` in `cardgame.c65`. Test functions in `cardtests.c65` and `joysticktests.c65` can be called from main() for debugging specific scenarios. + +## Architecture + +### Module Organization + +**Core Game Logic:** +- `cardgame.c65` - Main entry point, initialization, RNG seeding +- `gameloop.c65` - Main loop, input processing, coordinate-to-pile mapping +- `gamestate.c65` - Global state (draw mode, selected piles, interaction flags) +- `cardmoves.c65` - Move validation and execution +- `carddeck.c65` - Fisher-Yates shuffle, dealing +- `cardrender.c65` - Card and pile rendering + +**Input System:** +- `joystick.c65` - CIA Port 2 joystick driver +- `mouse.c65` - 1351 mouse driver with smoothing +- `keyboard.c65` - Non-interfering keyboard scan +- `pointer.c65` - VIC-II sprite cursor control + +**Data & Constants:** +- `piles.c65` - Pile data structures (13 piles: stock, waste, 4 foundations, 7 tableaus) +- `pileconsts.c65` - Pile ID constants +- `cardconsts.c65` - Card suits, ranks, flags + +### Game Data Model + +- 52 cards represented as values 0-51 (0-12 Hearts, 13-25 Diamonds, 26-38 Spades, 39-51 Clubs) +- Face-down cards have high bit set ($80) +- Each pile: 1 count byte + card slots (tableaus: 53 bytes, foundations: 14 bytes) +- PILE_END marker ($FF) indicates empty pile + +### Memory Layout + +- `$0400` - Screen memory +- `$2000` - Custom character set +- `$3000` - Code start +- `$C000` - Screen backup (menu) +- `$D000` - VIC-II registers +- `$DC00` - CIA ports (joystick/keyboard) + +### Custom Character Set (ECM Mode) + +The game uses a 64-character ECM (Extended Color Mode) font stored at `$2000`. This is NOT a standard ASCII font - it contains only card-specific graphics: + +- **Char 0**: Solid filled block (`$FF` bytes) +- **Chars 1-12**: Rank characters (2-10, J, Q, K) - note: Ace uses char 13 +- **Char 13**: Ace character +- **Chars 14-15**: Suit symbols (spades, clubs in one color set) +- **Chars 19 ($13)**: Empty/blank character (`$00` bytes) +- **Chars $15-$39**: Suit graphics (hearts, diamonds, spades, clubs as 3x3 grids) +- **Chars $50-$51**: Suit symbols (hearts, diamonds) +- **Various**: Card borders, corners, card back pattern pieces + +Character data is in `charpad_cards/`. The map PNG shows the visual layout. ECM mode uses 2 bits from color RAM to select between 4 color sets, effectively giving 64 unique characters × 4 color variations. + +Since there are no alphabet characters, any text display (like "YOU WIN!") must be constructed from available shapes (solid blocks, empty spaces, card graphics). + +## c65gm Language Notes + +See `language_docs/` for full reference. Key points: + +**Arithmetic expressions have two contexts:** + +*Compile-time* (no spaces) - evaluated by compiler, supports `+ - * /` and logic operators: +```c65 +value = 5+6*2 // Computed at compile time, supports * / +offset = 40*5+SCREEN // Fifth row (40 cols * 5 rows) + screen base address +// NOTE: SCREEN+40*5 would mean (SCREEN+40)*5 due to left-to-right eval! +``` + +*Runtime* (with spaces) - generates 6502 code, only `+ -` and logic operators: +```c65 +result = a + b // Runtime addition +result = count - 1 // Runtime subtraction +// No runtime multiplication - split complex expressions into multiple statements +``` + +**Critical: No operator precedence** in either context. Evaluation is strictly left to right: +```c65 +result = 2+3*4 // = 20, NOT 14 (evaluates as (2+3)*4) +``` + +**Types:** +- `BYTE` (8-bit), `WORD` (16-bit) +- `BYTE CONST` / `WORD CONST` for constants (preferred over `#DEFINE`) +- Memory-mapped: `BYTE borderColor @ $D020` + +**Control flow:** `IF`/`ENDIF`, `WHILE`/`WEND`, `FOR`/`NEXT`, `SWITCH`/`CASE`/`ENDSWITCH`, `BREAK` + +**Functions:** +```c65 +FUNC add(in:a, in:b, out:result) + result = a + b +FEND +``` +Parameter modifiers: `in:` (read-only, default), `out:` (write-only), `io:` (read-write, both in and out). +Call with `@