浏览代码

init

main
当前提交
b049d469e2
共有 22 个文件被更改,包括 1370 次插入0 次删除
  1. +18
    -0
      .ai/SKILLS.md
  2. +111
    -0
      .ai/skills/6510-assembly/SKILL.md
  3. +103
    -0
      .ai/skills/basic-v2-bridge/SKILL.md
  4. +96
    -0
      .ai/skills/c64-memory-map/SKILL.md
  5. +92
    -0
      .ai/skills/c64-programming-practices/SKILL.md
  6. +77
    -0
      .ai/skills/cia-io/SKILL.md
  7. +51
    -0
      .ai/skills/debugging-monitor/SKILL.md
  8. +70
    -0
      .ai/skills/interrupts-reset/SKILL.md
  9. +103
    -0
      .ai/skills/kernal-jump-table/SKILL.md
  10. +77
    -0
      .ai/skills/sid-sound/SKILL.md
  11. +84
    -0
      .ai/skills/vic-ii-graphics/SKILL.md
  12. +133
    -0
      AGENTS.md
  13. +22
    -0
      README.md
  14. +17
    -0
      examples/assembly/chrout-hello.asm
  15. +10
    -0
      examples/assembly/getin-echo.asm
  16. +46
    -0
      examples/assembly/irq-hook-skeleton.asm
  17. +10
    -0
      examples/assembly/safe-vic-bit-set.asm
  18. +7
    -0
      examples/basic/screen-and-color.bas
  19. +7
    -0
      examples/basic/sys-register-pass.bas
  20. +124
    -0
      references/c64-quick-reference.md
  21. +38
    -0
      templates/c64-task-brief.md
  22. +74
    -0
      tools/address-cheatsheet.json

+ 18
- 0
.ai/SKILLS.md 查看文件

@@ -0,0 +1,18 @@
# C64 / 6510 Skill Router

Load the smallest set of skills needed for the task.

| Task | Skill |
|---|---|
| Memory addresses, page zero, screen RAM, color RAM, ROM/RAM/I/O banking | `.ai/skills/c64-memory-map/SKILL.md` |
| BASIC V2, `SYS`, `USR`, `PEEK`, `POKE`, BASIC internals | `.ai/skills/basic-v2-bridge/SKILL.md` |
| KERNAL jump table, CHROUT, GETIN, LOAD/SAVE, device I/O | `.ai/skills/kernal-jump-table/SKILL.md` |
| 6510 assembly, addressing modes, registers, stack, subroutines | `.ai/skills/6510-assembly/SKILL.md` |
| VIC-II graphics, screen, bitmap, sprites, character sets, raster | `.ai/skills/vic-ii-graphics/SKILL.md` |
| SID sound, voices, ADSR, filters, paddles | `.ai/skills/sid-sound/SKILL.md` |
| CIA chips, timers, keyboard, joystick, serial bus, user port | `.ai/skills/cia-io/SKILL.md` |
| IRQ, NMI, reset vectors, vector patching, raster interrupts | `.ai/skills/interrupts-reset/SKILL.md` |
| Machine-language monitor, assembler, disassembler, emulator debugging | `.ai/skills/debugging-monitor/SKILL.md` |
| General C64 design practices and optimization | `.ai/skills/c64-programming-practices/SKILL.md` |

Always keep `references/c64-quick-reference.md` available for address lookup.

+ 111
- 0
.ai/skills/6510-assembly/SKILL.md 查看文件

@@ -0,0 +1,111 @@
# Skill: 6510 Assembly for the Commodore 64

## Use this skill when

The task involves 6510/6502 machine language, addressing modes, registers, stack, flags, subroutines, speed optimization, or assembly source.

## CPU model

The Commodore 64 uses the 6510, which is software-compatible with the 6502 instruction set and adds an on-chip I/O port at `$0000-$0001` used heavily for memory banking and cassette control.

## Registers

| Register | Purpose |
|---|---|
| A | Accumulator; arithmetic, logic, data movement |
| X | Index register; loops, offsets, counters |
| Y | Index register; loops, offsets, KERNAL/BASIC calling conventions |
| SP | Stack pointer, stack page `$0100-$01FF` |
| PC | Program counter |
| P | Processor status flags: N V - B D I Z C |

## Addressing modes to prefer

- Immediate: `lda #$01`
- Zero page: `lda $fb` faster/smaller than absolute.
- Zero page indexed: `lda $fb,x`
- Absolute: `lda $c000`
- Absolute indexed: `lda $0400,x`
- Indirect indexed: `lda ($fb),y` for pointer walking.
- Absolute indirect only works with `JMP (addr)`.

## Subroutine discipline

Called from BASIC with `SYS`:

```asm
* = $c000
start: ; work here
rts
```

If using registers for temporary work but caller expects preservation:

```asm
pha
txa: pha
tya: pha
; work
pla: tay
pla: tax
pla
rts
```

## Flags

- `C` carry: arithmetic carry/borrow; set before `SBC`, clear before `ADC` unless chaining multi-byte arithmetic.
- `Z` zero: many KERNAL calls and comparisons rely on it.
- `N` negative: mirrors bit 7 of result.
- `I` interrupt disable: `SEI` disables maskable IRQ; `CLI` enables.
- `D` decimal mode: normally keep clear on C64 unless using BCD intentionally.

## Multi-byte addition pattern

```asm
clc
lda lo1
adc lo2
sta resultlo
lda hi1
adc hi2
sta resulthi
```

## Pointer walking pattern

```asm
ptr = $fb

lda #<source
sta ptr
lda #>source
sta ptr+1
ldy #0
loop: lda (ptr),y
beq done
jsr $ffd2
iny
bne loop
inc ptr+1
bne loop
done: rts
```

## Avoid unless requested

- Undocumented opcodes.
- Self-modifying code without comments.
- Cycle-exact code without target PAL/NTSC note.
- Overwriting zero-page locations not reserved for your routine.

## Agent checklist

For assembly answers:

1. Identify assembler syntax.
2. Give load address.
3. Show how to run it.
4. Name KERNAL calls used.
5. Declare clobbered registers.
6. Explain zero-page usage.

+ 103
- 0
.ai/skills/basic-v2-bridge/SKILL.md 查看文件

@@ -0,0 +1,103 @@
# Skill: BASIC V2 Bridge — SYS, USR, PEEK, POKE, and BASIC Internals

## Use this skill when

The task involves BASIC V2, calling assembly from BASIC, calling BASIC ROM routines from assembly, `SYS`, `USR`, `PEEK`, `POKE`, `WAIT`, tokenization, variable storage, or BASIC program layout.

## Core concepts

- BASIC V2 is interpreted. Each statement is parsed and executed at runtime, which is why BASIC is slower than ML.
- BASIC program lines are tokenized and linked in memory.
- BASIC and ML can cooperate if memory ownership is clear.
- `SYS` calls an ML routine as a command.
- `USR(x)` calls an ML routine as a function-like expression.
- `PEEK` reads one byte; `POKE` writes one byte.

## Calling ML with SYS

BASIC:

```basic
10 SYS 49152
```

Assembly routine at `$C000` must normally end with:

```asm
rts
```

### Passing registers through SYS

Before `SYS`, BASIC can place values in these locations:

| Decimal | Hex | Register |
|---:|---:|---|
| 780 | `$030C` | Accumulator A |
| 781 | `$030D` | X register |
| 782 | `$030E` | Y register |
| 783 | `$030F` | Processor status |

Example:

```basic
10 POKE 780,65:REM A = PETSCII "A"
20 SYS 49152
30 PRINT PEEK(780)
```

## Calling ML with USR

`USR(x)` is best when an ML routine should behave like a function.

Use cases:

- Fast math helper.
- Custom string/numeric function.
- BASIC extension experiments.

Cautions:

- `USR` uses BASIC floating-point accumulator conventions.
- It is more complex than `SYS`; use `SYS` first unless function syntax is needed.

## BASIC pointers worth knowing

| Decimal | Hex | Meaning |
|---:|---:|---|
| 43-44 | `$002B-$002C` | Start of BASIC text |
| 45-46 | `$002D-$002E` | End of BASIC text |
| 47-48 | `$002F-$0030` | Start of variables |
| 49-50 | `$0031-$0032` | Start of arrays |
| 51-52 | `$0033-$0034` | End of arrays/start of strings |
| 55-56 | `$0037-$0038` | Top of BASIC memory |

## BASIC patterns

### Change border and background

```basic
10 POKE 53280,6:REM BORDER $D020
20 POKE 53281,0:REM BACKGROUND $D021
```

### Write to screen and color RAM

```basic
10 POKE 1024,1:REM SCREEN CODE A
20 POKE 55296,2:REM COLOR RED IN LOW NYBBLE
```

### Protect ML at $C000 with simple convention

For many C64 BASIC programs, `$C000` is outside normal BASIC RAM. Still, document the assumption and avoid loaders that extend into `$C000`.

## Agent checklist

When producing BASIC+ML examples:

1. Give a BASIC loader if the user needs type-in code.
2. Give the assembly source separately when possible.
3. Include exact `SYS` address.
4. Ensure ML routine ends in `RTS`.
5. Explain which locations are POKEd and why.

+ 96
- 0
.ai/skills/c64-memory-map/SKILL.md 查看文件

@@ -0,0 +1,96 @@
# Skill: C64 Memory Map and Address Discipline

## Use this skill when

The task involves memory addresses, `PEEK`, `POKE`, page zero, screen/color memory, ROM/RAM/I/O banking, vectors, or safe placement of machine-language code.

## Core concepts

- The 6510 can address 64K: `$0000-$FFFF` / `0-65535`.
- Most two-byte addresses are stored little-endian: low byte first, high byte second.
- Page zero `$0000-$00FF` is fast and heavily used by BASIC/KERNAL.
- Page one `$0100-$01FF` is the processor stack.
- Screen RAM normally starts at `$0400` / `1024`.
- Color RAM normally starts at `$D800` / `55296`; only the low nybble is meaningful.
- I/O registers normally occupy `$D000-$DFFF`; character ROM or RAM can be banked into the same range.
- BASIC ROM is normally at `$A000-$BFFF`; KERNAL ROM at `$E000-$FFFF`.
- RAM exists under ROM/I/O areas, but using it requires banking and interrupt care.

## Key addresses

| Decimal | Hex | Meaning |
|---:|---:|---|
| 0 | `$0000` | 6510 data-direction register |
| 1 | `$0001` | 6510 processor port; controls ROM/I/O banking and cassette lines |
| 43-44 | `$002B-$002C` | Start of BASIC program text pointer |
| 45-46 | `$002D-$002E` | End of BASIC program text pointer |
| 55-56 | `$0037-$0038` | Top of BASIC memory pointer |
| 198 | `$00C6` | Keyboard buffer length |
| 631-640 | `$0277-$0280` | Keyboard buffer |
| 646 | `$0286` | Current text color |
| 780-783 | `$030C-$030F` | `SYS` register save/pass area: A, X, Y, status |
| 788-789 | `$0314-$0315` | IRQ vector |
| 790-791 | `$0316-$0317` | BRK vector |
| 792-793 | `$0318-$0319` | NMI vector |
| 1024-2023 | `$0400-$07E7` | Default 40x25 screen RAM |
| 2040-2047 | `$07F8-$07FF` | Default sprite pointers |
| 49152 | `$C000` | Common safe ML area if protected from BASIC use |
| 53248 | `$D000` | VIC-II register base |
| 54272 | `$D400` | SID register base |
| 55296 | `$D800` | Color RAM base |
| 56320 | `$DC00` | CIA #1 base |
| 56576 | `$DD00` | CIA #2 base |

## Safe machine-language placement

Common choices:

- `$C000` / `49152`: often used for ML routines because BASIC normally has about 38911 bytes free and does not use this area directly.
- Above a lowered BASIC top: set top-of-memory pointer and issue `NEW` before loading BASIC program.
- In a cartridge/ROM area only when explicitly building cartridge code.
- Avoid `$033C-$03FB` unless you know which cassette buffer or workspace is being used.

## Banking rules

The 6510 processor port `$0001` controls what the CPU sees in ROM/I/O ranges. Use cautious read-modify-write:

```asm
lda $01
pha
; change bits only as needed
; ... do banked access quickly ...
pla
sta $01
```

When banking out I/O or banking in character ROM, interrupts that use I/O can fail. Disable IRQ briefly with `SEI`, restore `$01`, then `CLI`.

## BASIC bit manipulation patterns

Set a bit:

```basic
POKE A,PEEK(A) OR MASK
```

Clear a bit:

```basic
POKE A,PEEK(A) AND (255-MASK)
```

Toggle a bit:

```basic
POKE A,PEEK(A) XOR MASK
```

## Agent checklist

Before suggesting memory writes:

1. Identify whether the address is RAM, ROM, I/O, color RAM, vector, or register.
2. State decimal and hex.
3. Warn about global side effects.
4. Preserve existing bits unless replacing the whole register is intentional.
5. Explain how to restore the original value.

+ 92
- 0
.ai/skills/c64-programming-practices/SKILL.md 查看文件

@@ -0,0 +1,92 @@
# Skill: C64 Programming Practices, Patterns, Hints, and Optimization

## Use this skill when

The task asks for design advice, best practices, performance improvements, code organization, hybrid BASIC/ML strategy, or C64-specific programming patterns.

## Practices

### Use the right layer

- BASIC is excellent for quick control flow, menus, simple loaders, demos, and teaching.
- Assembly is best for speed, graphics effects, sound engines, raster work, custom I/O, compression, and tight loops.
- KERNAL calls are best for portability and standard I/O.
- Direct hardware access is best when KERNAL overhead or abstraction gets in the way.

### Keep ML small and callable

Build small routines with clear entry and exit conditions. Document:

- Entry address.
- Input registers/memory.
- Output registers/memory.
- Clobbered registers.
- Zero-page locations used.
- Whether interrupts must be enabled/disabled.

### Prefer tables

Tables are often faster and simpler than computation on a 1 MHz CPU:

- Screen row address tables.
- Sprite animation pointer tables.
- Sine/cosine movement tables.
- Frequency tables for notes.
- Bit masks.

### Preserve bits

Hardware registers often pack unrelated settings into one byte. Use `AND`/`OR` masks instead of blind `STA`/`POKE` unless replacing the whole register is intended.

### Respect PETSCII vs screen codes

- `CHROUT` expects PETSCII-style character output.
- Screen RAM expects screen codes.
- Key codes are different again.

### Optimize only where needed

First make the code correct and stable. Then optimize hot paths:

- Use zero-page addressing.
- Unroll small loops when timing matters.
- Avoid BASIC inside animation loops when ML is available.
- Avoid multiplication/division in raster-critical paths.
- Use precomputed tables.

### Keep recovery paths

- Use emulator snapshots.
- Keep STOP/RESTORE or reset strategy when possible.
- Include a routine to restore vectors and screen colors.
- Save original IRQ/NMI vectors before patching.

## Common patterns

### BASIC bootstrap + ML engine

BASIC loads/starts; ML handles fast loop.

### ML service routine called by BASIC

BASIC manages user interaction; ML performs fast operation.

### KERNAL I/O wrapper

ML uses KERNAL jump table for file/device operations.

### Raster IRQ effect

ML installs IRQ handler; handler changes VIC registers at specific raster lines.

### Double-buffered graphics data

Prepare screen/sprite/bitmap data off-screen, then switch pointers/registers.

## Agent checklist

1. Choose BASIC, assembly, or hybrid explicitly.
2. Avoid magic numbers; name addresses and masks.
3. Show restore/cleanup logic.
4. Explain cycle/timing assumptions for demos/games.
5. Favor reusable routines over one-off POKEs.

+ 77
- 0
.ai/skills/cia-io/SKILL.md 查看文件

@@ -0,0 +1,77 @@
# Skill: CIA I/O, Timers, Keyboard, Joystick, Serial Bus, and User Port

## Use this skill when

The task involves CIA chips, keyboard scanning, joysticks, timers, real-time clock, serial bus, disk/printer handshaking, RS-232, or user port I/O.

## CIA bases

| Chip | Decimal | Hex | Common role |
|---|---:|---:|---|
| CIA #1 | 56320 | `$DC00` | Keyboard matrix, joystick ports, timers, TOD, IRQ |
| CIA #2 | 56576 | `$DD00` | Serial bus, RS-232/user port, VIC bank select, NMI |

## CIA register layout

Each CIA exposes 16 registers mirrored across its 256-byte block.

| Offset | Purpose |
|---:|---|
| 0 | Port A data |
| 1 | Port B data |
| 2 | Port A data direction |
| 3 | Port B data direction |
| 4-5 | Timer A latch/counter low/high |
| 6-7 | Timer B latch/counter low/high |
| 8-11 | Time-of-day clock |
| 12 | Serial data register |
| 13 | Interrupt control/status |
| 14 | Control register A |
| 15 | Control register B |

## Joystick reading

Joystick values are active low.

- Port 2 commonly read at `$DC00` / `56320`.
- Port 1 commonly read at `$DC01` / `56321`.

Typical bits:

| Bit | Mask | Direction/button |
|---:|---:|---|
| 0 | 1 | Up |
| 1 | 2 | Down |
| 2 | 4 | Left |
| 3 | 8 | Right |
| 4 | 16 | Fire |

Pressed means bit is `0`.

BASIC example:

```basic
10 J=PEEK(56320)
20 IF (J AND 16)=0 THEN PRINT "FIRE"
```

## Serial bus concepts

- Device numbers distinguish serial devices.
- The C64 sends ATN, then TALK or LISTEN, plus optional secondary address.
- Data is transferred one byte at a time using handshaking.
- Prefer KERNAL routines (`SETLFS`, `SETNAM`, `OPEN`, `CHRIN`, `CHROUT`, `CLOSE`) unless bit-banging is the task.

## Timer principles

- CIA timers can count CPU cycles or external CNT pulses.
- Timer underflow can generate interrupts.
- For reliable timing, acknowledge CIA interrupt source and avoid leaving stale flags.

## Agent checklist

1. Identify CIA #1 vs CIA #2.
2. Preserve data direction registers unless intentionally changing port direction.
3. Remember joystick and keyboard are active-low.
4. For serial/disk/printer, prefer KERNAL I/O.
5. For timers, show latch, control, interrupt enable, and acknowledge steps.

+ 51
- 0
.ai/skills/debugging-monitor/SKILL.md 查看文件

@@ -0,0 +1,51 @@
# Skill: Debugging with Monitors, Assemblers, Disassemblers, and Emulators

## Use this skill when

The task involves entering ML, inspecting memory, using monitors, disassembling ROM/RAM, debugging crashes, emulator setup, or converting between BASIC loaders and assembly.

## Core tools

- Machine-language monitor: inspect/change memory and registers, run code, break, disassemble.
- Assembler: converts mnemonics to opcodes.
- Disassembler: converts opcodes back to mnemonics.
- Emulator monitor: VICE monitor is excellent for breakpoints/watchpoints.

## Common monitor activities

- Memory dump: inspect bytes at an address.
- Assemble line: write one instruction at an address.
- Disassemble range: inspect ML/ROM code.
- Fill memory: clear or initialize a range.
- Hunt/search: find byte patterns such as `20 D2 FF` for `JSR $FFD2`.
- Register view: inspect A/X/Y/SP/PC/flags.

## Debugging workflow

1. Confirm load address and `SYS` start address.
2. Verify first bytes in memory match assembled output.
3. Put `BRK` in suspected code path when using a monitor.
4. Single-step through register changes.
5. Check stack if `RTS` returns to nonsense.
6. Check zero-page pointers for little-endian order.
7. Check interrupt state and banking register `$01` after crashes.
8. Reset emulator snapshots frequently.

## Crash checklist

- Did the routine end with `RTS` when called by `SYS`?
- Did code overwrite BASIC text or variables?
- Did code corrupt `$01` and bank out KERNAL/BASIC unexpectedly?
- Did an IRQ vector point to invalid memory?
- Was a hardware interrupt acknowledged?
- Did the stack underflow/overflow?
- Was PETSCII/screen code confused with ASCII?

## Agent checklist

When helping debug:

1. Ask for start address, assembler, and emulator if not provided.
2. Request or infer memory map touched by the code.
3. Provide monitor commands conceptually, not tied to one monitor unless specified.
4. Use small reproducible examples.

+ 70
- 0
.ai/skills/interrupts-reset/SKILL.md 查看文件

@@ -0,0 +1,70 @@
# Skill: Interrupts, Reset, IRQ, NMI, BRK, and Vectors

## Use this skill when

The task involves IRQ/NMI handlers, raster interrupts, STOP+RESTORE, reset behavior, BRK, vector patching, or safe interrupt disabling.

## Core concepts

- RESET loads the CPU program counter from vector `$FFFC-$FFFD`.
- IRQ/BRK loads from `$FFFE-$FFFF` after pushing PC/status to stack.
- NMI loads from `$FFFA-$FFFB` and cannot be masked by the I flag.
- C64 RAM vectors allow patching system behavior without changing ROM.

## Important RAM vectors

| Decimal | Hex | Meaning |
|---:|---:|---|
| 788-789 | `$0314-$0315` | IRQ vector |
| 790-791 | `$0316-$0317` | BRK vector |
| 792-793 | `$0318-$0319` | NMI vector |
| 768-779 | `$0300-$030B` | BASIC vectors: error, main loop, tokenize, list, execute, evaluate |

## Safe IRQ hook pattern

1. `SEI`.
2. Save old vector.
3. Store new low/high bytes to `$0314/$0315`.
4. `CLI`.
5. Handler saves registers.
6. Handler acknowledges its interrupt source.
7. Handler restores registers.
8. Handler jumps to old IRQ or normal KERNAL IRQ path.

## Minimal handler skeleton

```asm
irq: pha
txa
pha
tya
pha

; acknowledge source here, e.g. VIC raster IRQ:
lda #$01
sta $d019

; do short, deterministic work

pla
tay
pla
tax
pla
jmp $ea31 ; normal KERNAL IRQ continuation on C64
```

## Warnings

- Do not leave IRQ disabled unless building a controlled loader/demo effect.
- NMI is used by RESTORE and CIA #2; avoid breaking STOP+RESTORE recovery unless intentional.
- Raster IRQ code must be short and cycle-aware.
- Always acknowledge the hardware source or the interrupt will immediately retrigger.

## Agent checklist

1. State interrupt source: VIC-II, CIA #1, CIA #2, BRK, RESTORE/NMI.
2. Show vector write low byte then high byte while IRQ disabled.
3. Save/restore A, X, Y unless deliberately not needed.
4. Acknowledge interrupt flags.
5. Chain to old handler or document full replacement.

+ 103
- 0
.ai/skills/kernal-jump-table/SKILL.md 查看文件

@@ -0,0 +1,103 @@
# Skill: KERNAL Jump Table and C64 Device I/O

## Use this skill when

The task involves screen/keyboard I/O, files, disk, printer, tape, RS-232, serial bus, `LOAD`, `SAVE`, `OPEN`, `CLOSE`, `GETIN`, `CHROUT`, or KERNAL calls from assembly.

## Core principle

Prefer KERNAL jump-table calls at the top of memory. They are stable public entry points and safer than jumping into undocumented ROM internals.

## Common KERNAL calls

| Address | Name | Purpose |
|---:|---|---|
| `$FF81` | `CINT` | Initialize screen editor |
| `$FF84` | `IOINIT` | Initialize I/O devices |
| `$FF87` | `RAMTAS` | Initialize RAM/test memory |
| `$FF8A` | `RESTOR` | Restore default vectors |
| `$FF8D` | `VECTOR` | Read/set RAM vectors |
| `$FF90` | `SETMSG` | Control system messages |
| `$FF93` | `SECOND` | Send secondary address after LISTEN |
| `$FF96` | `TKSA` | Send secondary address after TALK |
| `$FF99` | `MEMTOP` | Read/set top of memory |
| `$FF9C` | `MEMBOT` | Read/set bottom of memory |
| `$FF9F` | `SCNKEY` | Scan keyboard |
| `$FFA2` | `SETTMO` | Set serial timeout |
| `$FFA5` | `ACPTR` | Input byte from serial bus |
| `$FFA8` | `CIOUT` | Output byte to serial bus |
| `$FFAB` | `UNTLK` | Send UNTALK |
| `$FFAE` | `UNLSN` | Send UNLISTEN |
| `$FFB1` | `LISTEN` | Command device to listen |
| `$FFB4` | `TALK` | Command device to talk |
| `$FFB7` | `READST` | Read I/O status byte |
| `$FFBA` | `SETLFS` | Set logical file, device, secondary address |
| `$FFBD` | `SETNAM` | Set filename pointer and length |
| `$FFC0` | `OPEN` | Open logical file |
| `$FFC3` | `CLOSE` | Close logical file |
| `$FFC6` | `CHKIN` | Set input channel |
| `$FFC9` | `CHKOUT` | Set output channel |
| `$FFCC` | `CLRCHN` | Restore default I/O channels |
| `$FFCF` | `CHRIN` | Input character |
| `$FFD2` | `CHROUT` | Output character |
| `$FFD5` | `LOAD` | Load RAM from device |
| `$FFD8` | `SAVE` | Save RAM to device |
| `$FFDB` | `SETTIM` | Set system clock |
| `$FFDE` | `RDTIM` | Read system clock |
| `$FFE1` | `STOP` | Test STOP key |
| `$FFE4` | `GETIN` | Get character from keyboard/input buffer |
| `$FFE7` | `CLALL` | Close all channels/files |
| `$FFEA` | `UDTIM` | Update software clock |
| `$FFED` | `SCREEN` | Get screen size |
| `$FFF0` | `PLOT` | Read/set cursor position |
| `$FFF3` | `IOBASE` | Return I/O base address |

## CHROUT example

```asm
lda #'A' ; assembler may translate ASCII differently; PETSCII 65 works for A
jsr $ffd2 ; CHROUT
rts
```

## GETIN example

```asm
wait: jsr $ffe4 ; GETIN
beq wait ; zero means no key available
jsr $ffd2 ; echo key
rts
```

## Opening a device from ML

Typical sequence:

1. `SETLFS` with logical file, device number, secondary address.
2. `SETNAM` with filename length and pointer.
3. `OPEN`.
4. `CHKIN` or `CHKOUT`.
5. Use `CHRIN` / `CHROUT`.
6. `CLRCHN`.
7. `CLOSE`.

## Device numbers

| Device | Meaning |
|---:|---|
| 0 | Keyboard |
| 1 | Cassette |
| 2 | RS-232 |
| 3 | Screen |
| 4-5 | Printers, usually serial bus |
| 8-11 | Disk drives, commonly `8` for first 1541 |

## Agent checklist

When writing KERNAL-call assembly:

1. State required registers before call.
2. State affected registers/status after call if important.
3. Use jump table names in comments.
4. Restore channels with `CLRCHN` after redirected I/O.
5. Close files that were opened.

+ 77
- 0
.ai/skills/sid-sound/SKILL.md 查看文件

@@ -0,0 +1,77 @@
# Skill: SID 6581 Sound Programming

## Use this skill when

The task involves music, sound effects, SID registers, waveforms, ADSR envelopes, filters, volume, or paddles.

## SID base

SID base: `$D400` / `54272`.

Each of the three voices uses 7 registers:

| Voice | Base decimal | Base hex |
|---|---:|---:|
| Voice 1 | 54272 | `$D400` |
| Voice 2 | 54279 | `$D407` |
| Voice 3 | 54286 | `$D40E` |

Per voice:

| Offset | Purpose |
|---:|---|
| +0 | Frequency low |
| +1 | Frequency high |
| +2 | Pulse width low |
| +3 | Pulse width high nybble |
| +4 | Control: gate, sync, ring, test, waveform |
| +5 | Attack/decay |
| +6 | Sustain/release |

Global/filter registers:

| Decimal | Hex | Purpose |
|---:|---:|---|
| 54293 | `$D415` | Filter cutoff low bits |
| 54294 | `$D416` | Filter cutoff high bits |
| 54295 | `$D417` | Resonance/filter voice routing |
| 54296 | `$D418` | Filter mode and master volume |
| 54297 | `$D419` | Paddle X / ADC 1 |
| 54298 | `$D41A` | Paddle Y / ADC 2 |
| 54299 | `$D41B` | Voice 3 oscillator output |
| 54300 | `$D41C` | Voice 3 envelope output |

## Waveform bits in control register

| Bit/mask | Meaning |
|---:|---|
| `$01` | Gate |
| `$02` | Sync |
| `$04` | Ring modulation |
| `$08` | Test |
| `$10` | Triangle |
| `$20` | Sawtooth |
| `$40` | Pulse |
| `$80` | Noise |

## Simple BASIC tone

```basic
10 S=54272
20 POKE S+24,15:REM VOLUME
30 POKE S+5,9*16+0:REM ATTACK/DECAY
40 POKE S+6,15*16+8:REM SUSTAIN/RELEASE
50 POKE S,37:POKE S+1,17:REM FREQUENCY
60 POKE S+4,17:REM TRIANGLE + GATE
70 FOR T=1 TO 500:NEXT
80 POKE S+4,16:REM GATE OFF
```

## Agent checklist

1. Initialize volume at `$D418`.
2. Set frequency before opening gate.
3. Set ADSR before gate-on.
4. Clear gate for release.
5. Avoid leaving `TEST` bit set accidentally.
6. Mention SID 6581 vs 8580 sound differences when relevant.

+ 84
- 0
.ai/skills/vic-ii-graphics/SKILL.md 查看文件

@@ -0,0 +1,84 @@
# Skill: VIC-II Graphics, Screen, Characters, Sprites, and Raster

## Use this skill when

The task involves screen memory, colors, sprites, character sets, bitmap graphics, raster interrupts, scrolling, border/background, or VIC-II banking.

## Core registers

VIC-II base: `$D000` / `53248`.

| Decimal | Hex | Purpose |
|---:|---:|---|
| 53248-53263 | `$D000-$D00F` | Sprite X/Y coordinates |
| 53264 | `$D010` | High bits for sprite X positions |
| 53265 | `$D011` | Control register 1; vertical scroll, screen on, bitmap, raster bit 8 |
| 53266 | `$D012` | Raster line low byte |
| 53267 | `$D013` | Light pen X |
| 53268 | `$D014` | Light pen Y |
| 53269 | `$D015` | Sprite enable bits |
| 53270 | `$D016` | Control register 2; horizontal scroll, multicolor |
| 53271 | `$D017` | Sprite Y expansion |
| 53272 | `$D018` | Memory control: screen and character/bitmap pointers |
| 53273 | `$D019` | Interrupt flags |
| 53274 | `$D01A` | Interrupt enable |
| 53275 | `$D01B` | Sprite/background priority |
| 53276 | `$D01C` | Sprite multicolor enable |
| 53277 | `$D01D` | Sprite X expansion |
| 53278 | `$D01E` | Sprite-sprite collision |
| 53279 | `$D01F` | Sprite-background collision |
| 53280 | `$D020` | Border color |
| 53281 | `$D021` | Background color 0 |
| 53282-53284 | `$D022-$D024` | Extra background/multicolor registers |
| 53285-53286 | `$D025-$D026` | Sprite multicolor registers |
| 53287-53294 | `$D027-$D02E` | Sprite individual colors |

## Screen basics

Default screen RAM: `$0400` / `1024`.
Default color RAM: `$D800` / `55296`.
Screen is 40 columns x 25 rows = 1000 character cells.

Cell address:

```text
screen = 1024 + row * 40 + column
color = 55296 + row * 40 + column
```

## Sprite basics

- Each sprite is 24 x 21 pixels.
- Each sprite pattern uses 64 bytes.
- Default sprite pointers are `$07F8-$07FF` / `2040-2047`.
- Pointer value = sprite data address / 64, within the active VIC bank.
- Enable sprites with `$D015` bits.

Example enable sprite 0 in BASIC:

```basic
POKE 53269,PEEK(53269) OR 1
```

## VIC-II bank rule

The VIC-II sees one 16K bank at a time. CIA #2 port A controls the video bank. All active screen RAM, character data, bitmap data, and sprite data must be visible inside the selected VIC bank.

## Character ROM copy warning

To copy character ROM from CPU-visible `$D000-$DFFF`, you must bank character ROM in and I/O out. Since I/O disappears during that window, disable interrupts briefly and restore banking immediately.

## Raster interrupt principles

- Set raster line in `$D012`; bit 8 is in `$D011`.
- Enable raster IRQ in `$D01A` bit 0.
- Acknowledge VIC interrupt by writing the relevant bit back to `$D019`.
- Chain or jump to the normal KERNAL IRQ handler unless replacing the system IRQ completely.

## Agent checklist

1. Give addresses in decimal and hex.
2. Preserve unrelated VIC register bits.
3. Note PAL/NTSC timing differences for raster work.
4. Keep sprite data inside active VIC bank.
5. For character/bitmap changes, explain `$D018` layout.

+ 133
- 0
AGENTS.md 查看文件

@@ -0,0 +1,133 @@
# AGENTS.md — Commodore 64 / 6510 Expert Agent

## Purpose

Act as a panel of 150 expert Commodore 64 developers, 6510 assembly programmers, BASIC V2 power users, emulator/debugging specialists, and retro-computing systems programmers.

Your job is to help create, debug, document, optimize, and explain Commodore 64 programs using:

- Commodore BASIC V2
- 6510/6502-family assembly language
- KERNAL jump-table calls
- BASIC ROM routines when appropriate
- Direct memory access through `PEEK`, `POKE`, `SYS`, and `USR`
- VIC-II, SID, CIA #1, CIA #2, color RAM, screen RAM, joystick, keyboard, serial bus, tape, disk, and interrupt techniques

## Startup Instructions

Before working on any C64 task:

1. Read this file.
2. Read the skill router:

```text
./.ai/SKILLS.md
```

3. Load only the skill files relevant to the requested work.
4. Use `references/c64-quick-reference.md` when addresses, KERNAL vectors, or hardware registers are needed.
5. Prefer stable KERNAL jump-table calls over hard-coded internal ROM addresses unless the task specifically requires ROM internals.
6. Clearly state whether code is intended for:
- BASIC V2
- 6510 assembly
- monitor-entry hex
- cc65/ca65
- ACME/TMPx/KickAssembler-style assembly
- emulator-specific use

## Core Operating Principles

### 1. Preserve the machine

The C64 is small, powerful, and easy to crash. When generating code:

- Do not overwrite BASIC text, variables, stack, screen memory, color RAM, or KERNAL/BASIC vectors accidentally.
- Protect machine-language regions from BASIC by lowering the top of BASIC memory or placing code in a safe RAM area such as `$C000` when appropriate.
- End BASIC-called machine-language routines with `RTS` unless intentionally transferring control elsewhere.
- Save and restore registers when a caller expects them preserved.
- Disable interrupts only as long as necessary.
- Restore memory banking after switching ROMs/I/O/character ROM in or out.

### 2. Prefer official entry points

When calling operating-system routines, prefer the KERNAL jump table at `$FF81-$FFF3`. These addresses are intended as stable entry points across compatible Commodore systems.

Use internal BASIC or KERNAL routines only when:

- A documented jump-table routine cannot do the job.
- The program is explicitly C64 ROM-version-specific.
- The routine is wrapped in comments explaining entry conditions, clobbered registers, and risks.

### 3. Think in bytes, pages, and banks

C64 work is address work. Always consider:

- Decimal and hexadecimal address forms.
- Low-byte/high-byte order for vectors.
- Page zero efficiency and scarcity.
- Page 1 stack use.
- BASIC RAM boundaries.
- I/O/ROM/RAM banking controlled by processor port `$0001`.
- VIC-II 16K video banks selected through CIA #2 at `$DD00`.

### 4. BASIC and assembly should cooperate

For mixed BASIC + ML programs:

- Use BASIC loaders for short demos and bootstrapping.
- Use `SYS address` for command-style routines.
- Use `USR(x)` when the machine-language routine behaves like a function.
- Use locations `780-783` / `$030C-$030F` for BASIC `SYS` register passing when appropriate.
- Do not let BASIC garbage collection or variable storage overwrite machine-code bytes.

### 5. Make examples runnable

When producing code, include:

- Load/start address.
- How to run it from BASIC or a monitor.
- Required assembler syntax assumptions.
- What memory is touched.
- Expected output.
- Reset/recovery advice if it crashes.

## Skill Routing

Use `.ai/SKILLS.md` to choose the correct skill.

Common routes:

- Memory address, `PEEK`, `POKE`, banking → `c64-memory-map`
- `SYS`, `USR`, BASIC internals → `basic-v2-bridge`
- KERNAL calls, device I/O, files → `kernal-jump-table`
- Assembly language, registers, addressing modes → `6510-assembly`
- Sprites, screen, raster, bitmap, character sets → `vic-ii-graphics`
- Sound/music → `sid-sound`
- Keyboard, joystick, timers, serial bus, user port → `cia-io`
- IRQ/NMI/raster interrupts → `interrupts-reset`
- Debugging, monitors, emulators → `debugging-monitor`
- Style, structure, optimization → `c64-programming-practices`

## Response Rules for Agents

When answering C64 questions:

- Give decimal and hex addresses together when useful: `53280 / $D020`.
- Identify whether an address is RAM, ROM, I/O, color RAM, vector, or register.
- For bit registers, show bit masks and safe `AND`/`OR` patterns.
- For KERNAL calls, list entry registers and return behavior.
- For assembly, mention clobbered registers.
- For BASIC, keep lines short enough to type when possible.
- Avoid undocumented opcodes unless explicitly requested.
- Warn before code that changes interrupt vectors, memory banking, disk state, or hardware registers globally.

## Definition of Done

A C64 answer is complete when it includes:

- Correct target environment.
- Safe memory placement.
- Clear run instructions.
- Address/register explanation.
- Practical testing/debugging steps.
- Notes for emulator and real hardware differences when relevant.

+ 22
- 0
README.md 查看文件

@@ -0,0 +1,22 @@
# Commodore 64 / 6510 AI Agent Pack

This pack turns the uploaded Commodore 64 reference texts into a practical AI-coding-agent workspace. It is designed for agents helping with C64 BASIC V2, 6510 assembly, KERNAL jump-table calls, memory-map work, VIC-II graphics, SID sound, CIA I/O, interrupts, and debugging.

## Layout

```text
AGENTS.md Root agent operating instructions
.ai/SKILLS.md Skill router and index
.ai/skills/*/SKILL.md Focused C64 skills loaded on demand
references/c64-quick-reference.md Memory, KERNAL, BASIC, and hardware tables
examples/basic/* BASIC examples
examples/assembly/* 6510 assembly examples
templates/c64-task-brief.md Prompt template for future C64 tasks
tools/address-cheatsheet.json Machine-readable address table
```

## How to use

Place this folder in the root of a Commodore 64 project. An AI coding agent should read `AGENTS.md` first, then follow `.ai/SKILLS.md` to load only the skill files relevant to the task.

The material is summarized and transformed into working rules, not a copy of the source books. Verify timing-sensitive raster, IRQ, banking, and device behavior on an emulator or real C64.

+ 17
- 0
examples/assembly/chrout-hello.asm 查看文件

@@ -0,0 +1,17 @@
; chrout-hello.asm
; Generic 6510 assembly. Load at $C000 and run with SYS 49152.
; Uses KERNAL CHROUT at $FFD2. Clobbers A/Y.

* = $c000

start: ldy #$00
loop: lda message,y
beq done
jsr $ffd2 ; KERNAL CHROUT
iny
bne loop
done: rts

message:
.byte 147 ; clear screen PETSCII
.byte "HELLO FROM $C000",13,0

+ 10
- 0
examples/assembly/getin-echo.asm 查看文件

@@ -0,0 +1,10 @@
; getin-echo.asm
; Load at $C000 and run with SYS 49152.
; Waits for a key using KERNAL GETIN, then echoes using CHROUT.

* = $c000

wait: jsr $ffe4 ; GETIN
beq wait ; no key yet
jsr $ffd2 ; CHROUT
rts

+ 46
- 0
examples/assembly/irq-hook-skeleton.asm 查看文件

@@ -0,0 +1,46 @@
; irq-hook-skeleton.asm
; C64 IRQ hook skeleton. Educational template only.
; Installs handler at $C100 and changes border color briefly.
; Assemble/load with install at $C000. Run SYS 49152.

* = $c000
oldirq: .word 0

install:
sei
lda $0314
sta oldirq
lda $0315
sta oldirq+1
lda #<irq
sta $0314
lda #>irq
sta $0315
cli
rts

restore:
sei
lda oldirq
sta $0314
lda oldirq+1
sta $0315
cli
rts

* = $c100
irq:
pha
txa
pha
tya
pha

inc $d020 ; visible heartbeat; keep handler short

pla
tay
pla
tax
pla
jmp (oldirq) ; chain to original IRQ handler

+ 10
- 0
examples/assembly/safe-vic-bit-set.asm 查看文件

@@ -0,0 +1,10 @@
; safe-vic-bit-set.asm
; Demonstrates read-modify-write for VIC-II registers.
; Enables sprite 0 without changing other sprite-enable bits.

* = $c000

start: lda $d015 ; VIC-II sprite enable
ora #$01 ; set bit 0
sta $d015
rts

+ 7
- 0
examples/basic/screen-and-color.bas 查看文件

@@ -0,0 +1,7 @@
10 REM SCREEN AND COLOR RAM DEMO
20 S=1024:C=55296
30 POKE 53280,6:POKE 53281,0
40 FOR I=0 TO 39
50 POKE S+I,1+I-INT(I/26)*26
60 POKE C+I,I AND 15
70 NEXT

+ 7
- 0
examples/basic/sys-register-pass.bas 查看文件

@@ -0,0 +1,7 @@
10 REM SYS REGISTER PASS EXAMPLE
20 REM A/X/Y VALUES GO THROUGH 780/781/782
30 POKE 780,65:REM PETSCII A
40 POKE 781,66:REM PETSCII B
50 POKE 782,67:REM PETSCII C
60 SYS 49152
70 PRINT:PRINT "RETURNED A,X,Y=";PEEK(780);PEEK(781);PEEK(782)

+ 124
- 0
references/c64-quick-reference.md 查看文件

@@ -0,0 +1,124 @@
# Commodore 64 Quick Reference

## Memory map overview

| Range | Meaning |
|---:|---|
| `$0000-$00FF` | Page zero: BASIC/KERNAL workspace, pointers, fast addressing |
| `$0100-$01FF` | Processor stack |
| `$0200-$03FF` | System workspace, buffers, vectors |
| `$0400-$07E7` | Default screen RAM |
| `$07F8-$07FF` | Default sprite pointers |
| `$0801` | Default BASIC program start |
| `$A000-$BFFF` | BASIC ROM, RAM underneath |
| `$C000-$CFFF` | Free RAM often used for ML routines |
| `$D000-$DFFF` | I/O, color RAM, character ROM, or RAM depending on banking |
| `$E000-$FFFF` | KERNAL ROM, RAM underneath |

## Common addresses

| Dec | Hex | Name |
|---:|---:|---|
| 1 | `$0001` | 6510 memory banking port |
| 43 | `$002B` | BASIC start pointer low |
| 44 | `$002C` | BASIC start pointer high |
| 55 | `$0037` | BASIC top pointer low |
| 56 | `$0038` | BASIC top pointer high |
| 198 | `$00C6` | Keyboard buffer count |
| 646 | `$0286` | Current text color |
| 780 | `$030C` | SYS A register save/pass |
| 781 | `$030D` | SYS X register save/pass |
| 782 | `$030E` | SYS Y register save/pass |
| 783 | `$030F` | SYS status save/pass |
| 788 | `$0314` | IRQ vector low |
| 789 | `$0315` | IRQ vector high |
| 792 | `$0318` | NMI vector low |
| 793 | `$0319` | NMI vector high |
| 1024 | `$0400` | Screen RAM |
| 2040 | `$07F8` | Sprite pointer 0 |
| 49152 | `$C000` | Common ML start |
| 53248 | `$D000` | VIC-II base |
| 53280 | `$D020` | Border color |
| 53281 | `$D021` | Background color |
| 54272 | `$D400` | SID base |
| 55296 | `$D800` | Color RAM |
| 56320 | `$DC00` | CIA #1 base |
| 56576 | `$DD00` | CIA #2 base |

## KERNAL jump table

| Hex | Routine | Purpose |
|---:|---|---|
| `$FF81` | CINT | Initialize screen editor |
| `$FF84` | IOINIT | Initialize I/O |
| `$FF87` | RAMTAS | RAM test/init |
| `$FF8A` | RESTOR | Restore vectors |
| `$FF8D` | VECTOR | Read/set vectors |
| `$FF90` | SETMSG | Set system message flag |
| `$FF93` | SECOND | Send secondary address after LISTEN |
| `$FF96` | TKSA | Send secondary address after TALK |
| `$FF99` | MEMTOP | Read/set top of memory |
| `$FF9C` | MEMBOT | Read/set bottom of memory |
| `$FF9F` | SCNKEY | Scan keyboard |
| `$FFA2` | SETTMO | Set timeout |
| `$FFA5` | ACPTR | Read serial byte |
| `$FFA8` | CIOUT | Write serial byte |
| `$FFAB` | UNTLK | Untalk |
| `$FFAE` | UNLSN | Unlisten |
| `$FFB1` | LISTEN | Listen |
| `$FFB4` | TALK | Talk |
| `$FFB7` | READST | Read status |
| `$FFBA` | SETLFS | Set logical file/device/secondary address |
| `$FFBD` | SETNAM | Set filename |
| `$FFC0` | OPEN | Open file |
| `$FFC3` | CLOSE | Close file |
| `$FFC6` | CHKIN | Set input channel |
| `$FFC9` | CHKOUT | Set output channel |
| `$FFCC` | CLRCHN | Restore default I/O |
| `$FFCF` | CHRIN | Input character |
| `$FFD2` | CHROUT | Output character |
| `$FFD5` | LOAD | Load from device |
| `$FFD8` | SAVE | Save to device |
| `$FFDB` | SETTIM | Set clock |
| `$FFDE` | RDTIM | Read clock |
| `$FFE1` | STOP | Check STOP key |
| `$FFE4` | GETIN | Get input character |
| `$FFE7` | CLALL | Close all files |
| `$FFEA` | UDTIM | Update clock |
| `$FFED` | SCREEN | Get screen dimensions |
| `$FFF0` | PLOT | Read/set cursor position |
| `$FFF3` | IOBASE | Return I/O base |

## Color codes

| Code | Color |
|---:|---|
| 0 | Black |
| 1 | White |
| 2 | Red |
| 3 | Cyan |
| 4 | Purple |
| 5 | Green |
| 6 | Blue |
| 7 | Yellow |
| 8 | Orange |
| 9 | Brown |
| 10 | Light red |
| 11 | Dark gray |
| 12 | Gray |
| 13 | Light green |
| 14 | Light blue |
| 15 | Light gray |

## BASIC snippets

```basic
REM BORDER AND BACKGROUND
POKE 53280,6:POKE 53281,0

REM PUT "A" AT UPPER LEFT AND COLOR IT RED
POKE 1024,1:POKE 55296,2

REM CALL MACHINE LANGUAGE AT $C000
SYS 49152
```

+ 38
- 0
templates/c64-task-brief.md 查看文件

@@ -0,0 +1,38 @@
# C64 Task Brief Template

## Goal

Describe the desired program, bug fix, or explanation.

## Target

- Machine: C64 / VIC-20 / both
- Language: BASIC V2 / 6510 assembly / hybrid
- Assembler/emulator: VICE / ACME / ca65 / KickAssembler / monitor / other
- Load address:
- Run command:

## Constraints

- Must preserve BASIC? yes/no
- Safe ML area:
- Uses interrupts? yes/no
- Uses disk/tape/printer/serial? yes/no
- PAL/NTSC timing matters? yes/no

## Hardware areas touched

- VIC-II:
- SID:
- CIA #1:
- CIA #2:
- KERNAL calls:
- BASIC vectors/pointers:

## Expected result

What should the user see/hear/control?

## Testing

How should it be tested in emulator or real hardware?

+ 74
- 0
tools/address-cheatsheet.json 查看文件

@@ -0,0 +1,74 @@
{
"screen_ram": {
"dec": 1024,
"hex": "$0400"
},
"color_ram": {
"dec": 55296,
"hex": "$D800"
},
"vic_ii_base": {
"dec": 53248,
"hex": "$D000"
},
"sid_base": {
"dec": 54272,
"hex": "$D400"
},
"cia1_base": {
"dec": 56320,
"hex": "$DC00"
},
"cia2_base": {
"dec": 56576,
"hex": "$DD00"
},
"border_color": {
"dec": 53280,
"hex": "$D020"
},
"background_color": {
"dec": 53281,
"hex": "$D021"
},
"sys_a": {
"dec": 780,
"hex": "$030C"
},
"sys_x": {
"dec": 781,
"hex": "$030D"
},
"sys_y": {
"dec": 782,
"hex": "$030E"
},
"sys_status": {
"dec": 783,
"hex": "$030F"
},
"irq_vector": {
"dec": 788,
"hex": "$0314"
},
"nmi_vector": {
"dec": 792,
"hex": "$0318"
},
"ml_common_start": {
"dec": 49152,
"hex": "$C000"
},
"kernal": {
"CHROUT": "$FFD2",
"GETIN": "$FFE4",
"CHRIN": "$FFCF",
"SETLFS": "$FFBA",
"SETNAM": "$FFBD",
"OPEN": "$FFC0",
"CLOSE": "$FFC3",
"LOAD": "$FFD5",
"SAVE": "$FFD8",
"CLRCHN": "$FFCC"
}
}

正在加载...
取消
保存

Powered by TurnKey Linux.