c64bridge 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/prompts/README.md +6 -0
- package/.github/prompts/assembly-routine-session.prompt.md +13 -0
- package/.github/prompts/basic-program-session.prompt.md +13 -0
- package/.github/prompts/drive-management-session.prompt.md +13 -0
- package/.github/prompts/petscii-art-session.prompt.md +13 -0
- package/.github/prompts/play-classic-game.prompt.md +13 -0
- package/.github/prompts/sid-music-session.prompt.md +13 -0
- package/AGENTS.md +173 -0
- package/LICENSE +339 -0
- package/README.md +582 -0
- package/data/README.md +16 -0
- package/data/api/basic-api-spec.md +154 -0
- package/data/api/kernal-api-spec.md +68 -0
- package/data/assembly/assembly-spec.md +196 -0
- package/data/assembly/examples/effects/sinewave.asm +5 -0
- package/data/assembly/examples/graphics/sprite/mover.asm +15 -0
- package/data/assembly/examples/sid-file-structure.md +8 -0
- package/data/assembly/examples/sid-overview.md +11 -0
- package/data/audio/examples/Biosphere.sid +0 -0
- package/data/audio/sid-file-structure.md +91 -0
- package/data/audio/sid-programming-best-practices.md +198 -0
- package/data/audio/sid-spec.md +166 -0
- package/data/audio/sidwave.md +131 -0
- package/data/audio/sidwave.schema.json +64 -0
- package/data/basic/basic-spec.md +230 -0
- package/data/basic/examples/audio/alle-meine-entchen-expressive.bas +41 -0
- package/data/basic/examples/audio/c-major-scale-pleasant.bas +29 -0
- package/data/basic/examples/io/joystick.bas +5 -0
- package/data/basic/examples/video/bounce.bas +8 -0
- package/data/basic/examples/video/entchen-petscii.bas +16 -0
- package/data/basic/examples/video/hello-world.bas +4 -0
- package/data/basic/examples/video/wave.bas +7 -0
- package/data/context/bootstrap.md +148 -0
- package/data/context/chat.md +36 -0
- package/data/drive/drive-spec.md +215 -0
- package/data/embeddings_asm.json +1 -0
- package/data/embeddings_basic.json +1 -0
- package/data/embeddings_hardware.json +1 -0
- package/data/embeddings_mixed.json +1 -0
- package/data/embeddings_other.json +1 -0
- package/data/io/cia-spec.md +115 -0
- package/data/io/io-spec.md +124 -0
- package/data/memory/kernal-memory-map.md +227 -0
- package/data/memory/low-memory-map.md +133 -0
- package/data/memory/memory-map.md +186 -0
- package/data/printer/printer-commodore-bitmap.md +31 -0
- package/data/printer/printer-commodore.md +28 -0
- package/data/printer/printer-epson-bitmap.md +29 -0
- package/data/printer/printer-epson.md +30 -0
- package/data/printer/printer-prompts.md +29 -0
- package/data/printer/printer-spec.md +180 -0
- package/data/video/character-set.csv +257 -0
- package/data/video/vic-spec.md +276 -0
- package/dist/assemblyConverter.js +1299 -0
- package/dist/audio/record_and_analyze_audio.js +292 -0
- package/dist/basicConverter.js +193 -0
- package/dist/bootstrap/stdio-logger.js +32 -0
- package/dist/c64Client.js +1052 -0
- package/dist/chargen.js +197 -0
- package/dist/config.js +142 -0
- package/dist/context.js +157 -0
- package/dist/device.js +413 -0
- package/dist/index.js +7 -0
- package/dist/knowledge.js +454 -0
- package/dist/logger.js +182 -0
- package/dist/loggingHttpClient.js +88 -0
- package/dist/mcp-server.js +426 -0
- package/dist/petscii.js +135 -0
- package/dist/petsciiArt.js +356 -0
- package/dist/platform.js +82 -0
- package/dist/prompts/registry.js +560 -0
- package/dist/rag/discover.config.json +41 -0
- package/dist/rag/discover.js +401 -0
- package/dist/rag/embeddings.js +60 -0
- package/dist/rag/externalFetcher.js +934 -0
- package/dist/rag/indexer.js +770 -0
- package/dist/rag/init.js +139 -0
- package/dist/rag/knowledgeIndex.js +361 -0
- package/dist/rag/loggingRetriever.js +46 -0
- package/dist/rag/rateLimiter.js +127 -0
- package/dist/rag/retriever.js +74 -0
- package/dist/rag/sources.csv +31 -0
- package/dist/rag/types.js +5 -0
- package/dist/rag/urlUtils.js +38 -0
- package/dist/sidplayRunner.js +240 -0
- package/dist/sidwave.js +101 -0
- package/dist/sidwaveCompiler.js +329 -0
- package/dist/tools/audio.js +944 -0
- package/dist/tools/developer.js +515 -0
- package/dist/tools/errors.js +59 -0
- package/dist/tools/graphics.js +469 -0
- package/dist/tools/machineControl.js +267 -0
- package/dist/tools/memory.js +224 -0
- package/dist/tools/printer.js +482 -0
- package/dist/tools/programRunners.js +315 -0
- package/dist/tools/rag.js +153 -0
- package/dist/tools/registry.js +58 -0
- package/dist/tools/responses.js +36 -0
- package/dist/tools/schema.js +304 -0
- package/dist/tools/storage.js +740 -0
- package/dist/tools/streaming.js +132 -0
- package/dist/tools/types.js +99 -0
- package/dist/viceRunner.js +239 -0
- package/doc/MCP_SETUP.md +153 -0
- package/doc/README.md +7 -0
- package/doc/developer.md +312 -0
- package/doc/img/logo.png +0 -0
- package/doc/img/prompts/duck_petscii.png +0 -0
- package/doc/img/prompts/duck_song.png +0 -0
- package/doc/img/vscode/vscode-copilot-c64-chat-mode.png +0 -0
- package/doc/img/vscode/vscode-copilot-hello-world.png +0 -0
- package/doc/prompts/README.md +96 -0
- package/doc/prompts/user-prompt-ideas.md +147 -0
- package/doc/rest/c64-openapi.yaml +979 -0
- package/doc/rest/c64-rest-api.md +106 -0
- package/doc/troubleshooting-mcp.md +177 -0
- package/generated/c64/index.js +857 -0
- package/mcp.json +106 -0
- package/package.json +79 -0
- package/scripts/c64-cli.mjs +142 -0
- package/scripts/c64-tool.sh +83 -0
- package/scripts/check-package.mjs +89 -0
- package/scripts/cli.js +61 -0
- package/scripts/fetch-external-sources.mjs +67 -0
- package/scripts/generate-changelog.mjs +131 -0
- package/scripts/postbuild.mjs +101 -0
- package/scripts/prepare-release.mjs +58 -0
- package/scripts/rag-rebuild.mjs +53 -0
- package/scripts/register-ts-node.mjs +6 -0
- package/scripts/run-mcp-check.sh +104 -0
- package/scripts/run-tests.mjs +195 -0
- package/scripts/sid2wav.sh +94 -0
- package/scripts/smoke-run.sh +65 -0
- package/scripts/start-mock-c64.mjs +51 -0
- package/scripts/start-mock.mjs +31 -0
- package/scripts/start.mjs +72 -0
- package/scripts/update-readme.ts +164 -0
- package/scripts/verify-package.mjs +147 -0
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# SID Programming Best Practices - Perfect Scale Generation
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This document captures the successful approach for creating pleasant, musical SID sounds on the Commodore 64, discovered through iterative testing with the MCP server and real hardware feedback.
|
|
6
|
+
|
|
7
|
+
## Sample Programs
|
|
8
|
+
|
|
9
|
+
### Play C Major Scale with Basic
|
|
10
|
+
|
|
11
|
+
```basic
|
|
12
|
+
10 POKE 54296,15:REM VOLUME
|
|
13
|
+
20 POKE 54277,17:POKE 54278,240:REM FAST ATTACK, SLOW RELEASE
|
|
14
|
+
30 REM LOWER C MAJOR SCALE WITH TRIANGLE WAVE
|
|
15
|
+
40 POKE 54273,30:POKE 54274,0:POKE 54276,17:FOR I=1 TO 3000:NEXT I:POKE 54276,16:FOR I=1 TO 500:NEXT I
|
|
16
|
+
50 POKE 54273,34:POKE 54274,0:POKE 54276,17:FOR I=1 TO 3000:NEXT I:POKE 54276,16:FOR I=1 TO 500:NEXT I
|
|
17
|
+
60 POKE 54273,38:POKE 54274,0:POKE 54276,17:FOR I=1 TO 3000:NEXT I:POKE 54276,16:FOR I=1 TO 500:NEXT I
|
|
18
|
+
70 POKE 54273,40:POKE 54274,0:POKE 54276,17:FOR I=1 TO 3000:NEXT I:POKE 54276,16:FOR I=1 TO 500:NEXT I
|
|
19
|
+
80 POKE 54273,45:POKE 54274,0:POKE 54276,17:FOR I=1 TO 3000:NEXT I:POKE 54276,16:FOR I=1 TO 500:NEXT I
|
|
20
|
+
90 POKE 54273,51:POKE 54274,0:POKE 54276,17:FOR I=1 TO 3000:NEXT I:POKE 54276,16:FOR I=1 TO 500:NEXT I
|
|
21
|
+
100 POKE 54273,57:POKE 54274,0:POKE 54276,17:FOR I=1 TO 3000:NEXT I:POKE 54276,16:FOR I=1 TO 500:NEXT I
|
|
22
|
+
110 POKE 54273,60:POKE 54274,0:POKE 54276,17:FOR I=1 TO 3000:NEXT I:POKE 54276,16
|
|
23
|
+
120 POKE 54276,0:PRINT "SMOOTH SCALE DONE"
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Key Success Factors
|
|
27
|
+
|
|
28
|
+
### 1. Ultra-Low Frequencies
|
|
29
|
+
|
|
30
|
+
- **Critical Discovery**: The standard frequency tables from documentation are too high for pleasant listening
|
|
31
|
+
- **Working Range**: Use frequencies around 30-60 for the low byte, 0 for high byte
|
|
32
|
+
- **Result**: Produces warm, bass-like tones instead of harsh, screechy sounds
|
|
33
|
+
|
|
34
|
+
### 2. Triangle Wave Instead of Pulse
|
|
35
|
+
|
|
36
|
+
- **Register 54276**: Use value `17` (triangle wave + GATE) instead of `33` (pulse wave + GATE)
|
|
37
|
+
- **Benefit**: Triangle waves are much smoother and more musical than pulse waves
|
|
38
|
+
- **Off State**: Use `16` (triangle wave, no GATE) to properly release notes
|
|
39
|
+
|
|
40
|
+
### 3. Proper ADSR Envelope
|
|
41
|
+
|
|
42
|
+
- **Attack/Decay (54277)**: `17` = fast attack (1), slow decay (7)
|
|
43
|
+
- **Sustain/Release (54278)**: `240` = high sustain (15), no release (0)
|
|
44
|
+
- **Effect**: Creates natural-sounding note onset and sustain
|
|
45
|
+
|
|
46
|
+
### 4. Timing is Everything
|
|
47
|
+
|
|
48
|
+
- **Note Duration**: 3000 cycles provides proper sustain (~1.5 seconds)
|
|
49
|
+
- **Pause Duration**: 500 cycles between notes for clear separation
|
|
50
|
+
- **GATE Control**: Keep GATE on during entire note, then turn off cleanly
|
|
51
|
+
|
|
52
|
+
### 5. Musical Expression and Phrasing
|
|
53
|
+
|
|
54
|
+
- **Varied Note Lengths**: Don't make all notes the same duration - create rhythm and emphasis
|
|
55
|
+
- **Phrase Breathing**: Use longer pauses between musical phrases (150-200 cycles)
|
|
56
|
+
- **Dynamic Emphasis**: Emphasize important notes (phrase beginnings/endings) with longer durations
|
|
57
|
+
- **Narrative Flow**: Each phrase should have its own character and emotional arc
|
|
58
|
+
- **Quick Passages**: Use shorter notes (140-180 cycles) for rapid, flowing sections
|
|
59
|
+
- **Sustained Endings**: Use longer notes (400-600 cycles) for phrase climaxes and endings
|
|
60
|
+
|
|
61
|
+
## Technical Analysis
|
|
62
|
+
|
|
63
|
+
### Frequency Values Used
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
Note | Low Byte | High Byte | Estimated Hz
|
|
67
|
+
-----|----------|-----------|-------------
|
|
68
|
+
C | 30 | 0 | ~50 Hz
|
|
69
|
+
D | 34 | 0 | ~57 Hz
|
|
70
|
+
E | 38 | 0 | ~63 Hz
|
|
71
|
+
F | 40 | 0 | ~67 Hz
|
|
72
|
+
G | 45 | 0 | ~75 Hz
|
|
73
|
+
A | 51 | 0 | ~85 Hz
|
|
74
|
+
B | 57 | 0 | ~95 Hz
|
|
75
|
+
C | 60 | 0 | ~100 Hz
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Register Settings
|
|
79
|
+
|
|
80
|
+
```text
|
|
81
|
+
54296 (Volume): 15 (maximum)
|
|
82
|
+
54277 (AD): 17 (attack=1, decay=7)
|
|
83
|
+
54278 (SR): 240 (sustain=15, release=0)
|
|
84
|
+
54273 (Freq Lo): Variable per note
|
|
85
|
+
54274 (Freq Hi): 0 (always)
|
|
86
|
+
54276 (Control): 17 (triangle+gate) / 16 (triangle only)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Common Pitfalls to Avoid
|
|
90
|
+
|
|
91
|
+
### 1. Using Documentation Frequencies Directly
|
|
92
|
+
|
|
93
|
+
- Standard frequency tables (C4=261Hz → 0x113E) produce harsh, unpleasant sounds
|
|
94
|
+
- These frequencies are mathematically correct but not musically pleasant for listening
|
|
95
|
+
|
|
96
|
+
### 2. Pulse Wave Without Proper Setup
|
|
97
|
+
|
|
98
|
+
- Pulse waves require careful pulse width settings
|
|
99
|
+
- Triangle waves are much more forgiving and musical
|
|
100
|
+
|
|
101
|
+
### 3. Inadequate ADSR Settings
|
|
102
|
+
|
|
103
|
+
- Without proper envelope, notes sound like short clicks
|
|
104
|
+
- Fast attack + slow decay + high sustain = musical notes
|
|
105
|
+
|
|
106
|
+
### 4. Poor GATE Timing
|
|
107
|
+
|
|
108
|
+
- GATE must stay on during the entire note duration
|
|
109
|
+
- Turning GATE off too early creates click-like sounds
|
|
110
|
+
|
|
111
|
+
## Testing Methodology
|
|
112
|
+
|
|
113
|
+
This solution was developed through:
|
|
114
|
+
|
|
115
|
+
1. **Real Hardware Testing**: Used actual C64 Ultimate with MCP server
|
|
116
|
+
2. **Iterative Refinement**: Multiple attempts with frequency adjustments
|
|
117
|
+
3. **Audio Feedback**: Human verification of pleasant vs. harsh sounds
|
|
118
|
+
4. **Systematic Debugging**: Isolated individual notes before building full scale
|
|
119
|
+
|
|
120
|
+
## MCP Server Integration
|
|
121
|
+
|
|
122
|
+
### Upload Command
|
|
123
|
+
|
|
124
|
+
> [!NOTE]
|
|
125
|
+
> These curl commands require the optional legacy HTTP bridge. Start it manually before using them; the day-to-day workflow runs over MCP stdio.
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
curl -X POST -H 'Content-Type: application/json' \
|
|
129
|
+
-d '{"program": "... BASIC program ..."}' \
|
|
130
|
+
http://localhost:8000/tools/upload_and_run_basic
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Future Audio Analysis
|
|
134
|
+
|
|
135
|
+
The working scale can now be used with the `analyze_audio` tool:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
curl -X POST -H 'Content-Type: application/json' \
|
|
139
|
+
-d '{"request": "verify the scale sounds correct"}' \
|
|
140
|
+
http://localhost:8000/tools/analyze_audio
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## Musical Expression Example: "Alle meine Entchen"
|
|
144
|
+
|
|
145
|
+
The following example demonstrates how to create a musically expressive children's song using varied timing and proper phrasing. This serves as a template for writing engaging melodies.
|
|
146
|
+
|
|
147
|
+
### Key Musical Programming Principles
|
|
148
|
+
|
|
149
|
+
1. **Opening Emphasis**: First note gets longer duration (250 cycles) to establish the song
|
|
150
|
+
2. **Flowing Middle**: Quick notes (180 cycles) for melodic flow
|
|
151
|
+
3. **Phrase Endings**: Extended notes (400-600 cycles) at the end of each phrase
|
|
152
|
+
4. **Breathing Space**: Longer pauses (150-200 cycles) between phrases
|
|
153
|
+
5. **Character Variation**: Each verse has its own timing character:
|
|
154
|
+
- "Swimming" = light, quick notes (160 cycles)
|
|
155
|
+
- "Diving" = very short, rapid notes (140 cycles)
|
|
156
|
+
- "Triumphant ending" = building emphasis
|
|
157
|
+
|
|
158
|
+
### Example Implementation
|
|
159
|
+
|
|
160
|
+
```basic
|
|
161
|
+
REM ALLE MEINE ENTCHEN - MUSICAL PHRASING
|
|
162
|
+
POKE 54296,15:POKE 54277,17:POKE 54278,240
|
|
163
|
+
|
|
164
|
+
REM OPENING PHRASE - emphasis on first note
|
|
165
|
+
POKE 54273,30:POKE 54274,0:POKE 54276,17:FOR I=1 TO 250:NEXT I:POKE 54276,16:FOR I=1 TO 40:NEXT I
|
|
166
|
+
POKE 54273,34:POKE 54274,0:POKE 54276,17:FOR I=1 TO 180:NEXT I:POKE 54276,16:FOR I=1 TO 40:NEXT I
|
|
167
|
+
REM ... continued with varied timing for musical expression
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Complete example**: See `data/basic/examples/audio/alle-meine-entchen-expressive.bas`
|
|
171
|
+
|
|
172
|
+
### Timing Patterns for Different Musical Effects
|
|
173
|
+
|
|
174
|
+
- **Emphasis/Importance**: 250-400+ cycles
|
|
175
|
+
- **Normal melody notes**: 180-200 cycles
|
|
176
|
+
- **Quick/flowing passages**: 140-160 cycles
|
|
177
|
+
- **Short pauses**: 25-40 cycles
|
|
178
|
+
- **Phrase breathing**: 120-200 cycles
|
|
179
|
+
- **Dramatic pauses**: 150-250 cycles
|
|
180
|
+
|
|
181
|
+
## Conclusion
|
|
182
|
+
|
|
183
|
+
The key insight is that **musical programming requires human feedback**, not just technical accuracy. The "correct" mathematical frequencies from documentation don't necessarily produce the most pleasant musical experience. This approach prioritizes:
|
|
184
|
+
|
|
185
|
+
1. **Listenability** over technical accuracy
|
|
186
|
+
2. **Smooth waveforms** (triangle) over complex ones (pulse)
|
|
187
|
+
3. **Proper envelopes** for musical note shaping
|
|
188
|
+
4. **Musical expression** through varied timing and phrasing
|
|
189
|
+
5. **Real hardware testing** to validate results
|
|
190
|
+
|
|
191
|
+
**For Children's Songs and Simple Melodies**: Use the expressive timing patterns demonstrated in "Alle meine Entchen" to create engaging, musical compositions that tell a story rather than just playing notes mechanically.
|
|
192
|
+
|
|
193
|
+
This methodology can be applied to create more complex musical compositions while maintaining the warm, pleasant character achieved in this scale progression.
|
|
194
|
+
|
|
195
|
+
---
|
|
196
|
+
|
|
197
|
+
*Document created: December 2024*
|
|
198
|
+
*Based on successful MCP server + C64 Ultimate testing session*
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Commodore 64 SID (MOS 6581 / 8580) — Concise Technical Overview
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
- **Voices:** 3 independent oscillators
|
|
6
|
+
Each has: 16-bit frequency, waveform select (triangle / saw / pulse / noise), pulse-width, ADSR envelope, optional SYNC and RING-MOD.
|
|
7
|
+
- **Global:** Analog multimode filter (LP / BP / HP), resonance, master volume, and read-back registers for OSC3 and ENV3.
|
|
8
|
+
- **Models:** 6581 (original, “warmer”, nonlinear filter) and 8580 (revised, linear filter, lower noise).
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## Register Map (base = $D400 / 54272)
|
|
13
|
+
|
|
14
|
+
**Per Voice (1 – 3):**
|
|
15
|
+
|
|
16
|
+
| Function | Voice 1 | Voice 2 | Voice 3 | Bits / Notes |
|
|
17
|
+
|-----------|----------|----------|----------|--------------|
|
|
18
|
+
| Frequency LO | $D400 | $D407 | $D40E | Low byte of 16-bit pitch increment |
|
|
19
|
+
| Frequency HI | $D401 | $D408 | $D40F | High byte |
|
|
20
|
+
| Pulse Width LO | $D402 | $D409 | $D410 | 12-bit value (0-4095) |
|
|
21
|
+
| Pulse Width HI | $D403 | $D40A | $D411 | Upper 4 bits used |
|
|
22
|
+
| Control | $D404 | $D40B | $D412 | **7..0 = NOISE PULSE SAW TRI TEST RING SYNC GATE** |
|
|
23
|
+
| AD | $D405 | $D40C | $D413 | Attack/Decay nibbles |
|
|
24
|
+
| SR | $D406 | $D40D | $D414 | Sustain/Release nibbles |
|
|
25
|
+
|
|
26
|
+
**Global:**
|
|
27
|
+
|
|
28
|
+
| Function | Address | Description |
|
|
29
|
+
|-----------|----------|-------------|
|
|
30
|
+
| Cutoff LO | $D415 | Lower 8 bits of filter cutoff |
|
|
31
|
+
| Cutoff HI | $D416 | Upper 3 bits of cutoff |
|
|
32
|
+
| Res/Routing | $D417 | 7..4 = resonance (0–15); 3..0 = route Ext,V3,V2,V1 into filter |
|
|
33
|
+
| Mode/Volume | $D418 | 0..3 = master vol (0–15); 4..6 = LP/BP/HP; 7 = CH3 off |
|
|
34
|
+
| Read-backs | $D419–$D41C | POTX, POTY, OSC3, ENV3 |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Note → SID Frequency
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
FREQ = round( note_hz * 2^24 / φ2 ) >> 8 ; 16-bit register value
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
- φ₂ = system clock
|
|
45
|
+
- PAL = 985 248 Hz
|
|
46
|
+
- NTSC = 1 022 727 Hz
|
|
47
|
+
- Store FREQ (low/high) into FREQLO/HI.
|
|
48
|
+
- Typical usage: lookup table per note/octave.
|
|
49
|
+
|
|
50
|
+
**Example (PAL):**
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
FREQ16 = round( (note_hz * 16777216) / 985248 ) >> 8
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Basic Play / Stop Sequence
|
|
59
|
+
|
|
60
|
+
1. Set FREQ, PW, AD/SR.
|
|
61
|
+
2. Write CTRL = waveform bits | GATE (=1) → start note.
|
|
62
|
+
3. Clear GATE bit to release note.
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## Waveforms & Pulse Width
|
|
67
|
+
|
|
68
|
+
- **Waveform bits:** Triangle = bit 4, Saw = 5, Pulse = 6, Noise = 7.
|
|
69
|
+
- **Pulse Width:** 12-bit ($000–$FFF); $0800 ≈ 50 % duty.
|
|
70
|
+
- Combining waveform bits produces nonlinear mixed timbres.
|
|
71
|
+
- PWM = vary pulse-width in real time.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Filter Block
|
|
76
|
+
|
|
77
|
+
- **Cutoff:** $D415 + $D416 (11 bits).
|
|
78
|
+
- **Resonance / Routing:** $D417.
|
|
79
|
+
- **Mode / Volume:** $D418 → LP/BP/HP bits + master volume.
|
|
80
|
+
- **Differences:** 6581 = nonlinear; 8580 = more accurate.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Famous Effects
|
|
85
|
+
|
|
86
|
+
**Arpeggio** – Cycle chord intervals (e.g. 0,+4,+7) each tick by rewriting FREQ.
|
|
87
|
+
**Vibrato** – Small sinusoidal offset of FREQ each tick (software LFO).
|
|
88
|
+
**PWM** – Periodic variation of pulse-width for animated tone.
|
|
89
|
+
**Filter Sweep** – Ramp cutoff ($D415/$D416) and/or resonance ($D417).
|
|
90
|
+
**Hard Restart** – Clear GATE early, optionally TEST=1 to reset osc; next tick set ADSR + GATE=1 for tight attack.
|
|
91
|
+
**Sync / Ring-Mod** – Enable SYNC or RING bits in CTRL to tie oscillators.
|
|
92
|
+
**Digi Playback** – Rapid writes to $D418 volume simulate 4-bit PCM DAC (~4–8 kHz).
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Reset Tips
|
|
97
|
+
|
|
98
|
+
Write $FF then $00 to all SID registers on init to clear stale state before loading new instrument settings.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Alternative Exact Frequency Formulas
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
PAL: x = f * (18 * 2^24) / 17734475
|
|
106
|
+
NTSC: x = f * (14 * 2^24) / 14318182
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Equivalent to `FREQ = f * 2^24 / φ2`, then take the upper 16 bits.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Frequency Table (C-Major, A4 = 440 Hz)
|
|
114
|
+
|
|
115
|
+
| Note | Freq (Hz) | FREQ PAL (hex) | FREQ NTSC (hex) |
|
|
116
|
+
|------|------------|----------------|-----------------|
|
|
117
|
+
| C4 (Do) | 261.63 | 0x113E (4414) | 0x1069 (4201) |
|
|
118
|
+
| D4 (Re) | 293.66 | 0x1325 (4901) | 0x123C (4668) |
|
|
119
|
+
| E4 (Mi) | 329.63 | 0x154E (5454) | 0x1459 (5209) |
|
|
120
|
+
| F4 (Fa) | 349.23 | 0x1667 (5735) | 0x156E (5486) |
|
|
121
|
+
| G4 (Sol)| 392.00 | 0x18EE (6382) | 0x1753 (5971) |
|
|
122
|
+
| A4 (La) | 440.00 | 0x1B9B (7067) | 0x19B5 (6581) |
|
|
123
|
+
| B4 (Ti) | 493.88 | 0x1F04 (7940) | 0x1BFD (7165) |
|
|
124
|
+
| C5 (Do) | 523.25 | 0x2102 (8450) | 0x1E08 (7688) |
|
|
125
|
+
|
|
126
|
+
*Multiply FREQ by 2ⁿ to move up n octaves.*
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## Primary References (for RAG)
|
|
131
|
+
|
|
132
|
+
- Oxyron SID Register Reference — bit map, frequency formulas, play sequence.
|
|
133
|
+
- Commodore 64 Programmer’s Reference (sound chapter, PDF).
|
|
134
|
+
- C64-Wiki — SID overview and filter behavior.
|
|
135
|
+
- Codebase64 — SID programming patterns (arpeggio, vibrato, PWM, players).
|
|
136
|
+
- $D418 Digi Playback articles — technique and bias requirements.
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Typical Usage Snippet (ASM)
|
|
141
|
+
|
|
142
|
+
```asm
|
|
143
|
+
; Initialize SID
|
|
144
|
+
lda #$0f ; volume = 15
|
|
145
|
+
sta $d418
|
|
146
|
+
|
|
147
|
+
; Play note (Voice 1 example)
|
|
148
|
+
lda freq_lo
|
|
149
|
+
sta $d400
|
|
150
|
+
lda freq_hi
|
|
151
|
+
sta $d401
|
|
152
|
+
lda #$00
|
|
153
|
+
sta $d402
|
|
154
|
+
lda #$08
|
|
155
|
+
sta $d403
|
|
156
|
+
lda #$11
|
|
157
|
+
sta $d405
|
|
158
|
+
lda #$f3
|
|
159
|
+
sta $d406
|
|
160
|
+
lda #%01000001 ; pulse + gate
|
|
161
|
+
sta $d404
|
|
162
|
+
|
|
163
|
+
; ... release ...
|
|
164
|
+
and #%11111110
|
|
165
|
+
sta $d404
|
|
166
|
+
```
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# SIDWAVE Format Specification
|
|
2
|
+
|
|
3
|
+
This document defines **SIDWAVE**, a declarative format for describing structured, modern C64 SID compositions.
|
|
4
|
+
SIDWAVE files are authored in YAML (optionally JSON) and compiled by an MCP server into `.SID` or `.PRG` binaries for playback on the Commodore 64 via the Ultimate64 REST API.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Purpose
|
|
9
|
+
|
|
10
|
+
SIDWAVE provides a human- and machine-readable way to describe complex, atmospheric, and modern electronic music for the MOS 6581/8580 SID chip.
|
|
11
|
+
It captures instruments, modulation, and structure symbolically, allowing large language models to generate music that the MCP expands into precise SID register sequences.
|
|
12
|
+
|
|
13
|
+
Pipeline:
|
|
14
|
+
|
|
15
|
+
LLM → SIDWAVE (YAML) → MCP Compiler → SID Binary (.sid/.prg) → Ultimate64 REST → C64 Playback
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## File and Schema Conventions
|
|
20
|
+
|
|
21
|
+
- **Format name:** SIDWAVE
|
|
22
|
+
- **File suffix:** `.sidwave.yaml` (or `.sid.yaml` for brevity)
|
|
23
|
+
- **Schema field:** `sidwave: 1.0`
|
|
24
|
+
- **Schema file:** `sidwave.schema.json`
|
|
25
|
+
- **Primary serialization:** YAML 1.2 (JSON also valid)
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Example SIDWAVE File
|
|
30
|
+
|
|
31
|
+
```yaml
|
|
32
|
+
# yaml-language-server: $schema=https://example.com/sidwave.schema.json
|
|
33
|
+
sidwave: 1.0
|
|
34
|
+
title: "Echoes of Tomorrow"
|
|
35
|
+
author: "Generated by MCP"
|
|
36
|
+
tempo: 92
|
|
37
|
+
mode: PAL
|
|
38
|
+
global_fx:
|
|
39
|
+
reverb_sim: { depth: 0.3, delay_frames: 3 }
|
|
40
|
+
filter_env: { cutoff_base: 1800, sweep: -800, speed: 12 }
|
|
41
|
+
|
|
42
|
+
voices:
|
|
43
|
+
- id: 1
|
|
44
|
+
name: LeadPad
|
|
45
|
+
waveform: sawtooth
|
|
46
|
+
adsr: [4, 2, 10, 3]
|
|
47
|
+
patterns:
|
|
48
|
+
A:
|
|
49
|
+
length: 16
|
|
50
|
+
motif: "Cmin9 pad motif"
|
|
51
|
+
transpositions: [0, 5, 7]
|
|
52
|
+
fx:
|
|
53
|
+
vibrato: { depth: 2, rate: 5 }
|
|
54
|
+
filter_mod: { sweep: +500 over 8 steps }
|
|
55
|
+
|
|
56
|
+
- id: 2
|
|
57
|
+
name: ArpLayer
|
|
58
|
+
waveform: pulse
|
|
59
|
+
pulse_width: 0.3
|
|
60
|
+
patterns:
|
|
61
|
+
B:
|
|
62
|
+
type: "arpeggio"
|
|
63
|
+
notes: [C3, Eb3, G3, Bb3]
|
|
64
|
+
frame_rate: 2
|
|
65
|
+
fx:
|
|
66
|
+
pwm_sweep: { speed: 6, depth: 8 }
|
|
67
|
+
|
|
68
|
+
- id: 3
|
|
69
|
+
name: Bass
|
|
70
|
+
waveform: triangle
|
|
71
|
+
patterns:
|
|
72
|
+
C:
|
|
73
|
+
groove: [C1, C1, C1, G0]
|
|
74
|
+
fx:
|
|
75
|
+
slide: { depth: 2, speed: 3 }
|
|
76
|
+
|
|
77
|
+
timeline:
|
|
78
|
+
- section: "Intro"
|
|
79
|
+
bars: 16
|
|
80
|
+
layers: { v1: A, v2: -, v3: C }
|
|
81
|
+
- section: "Build"
|
|
82
|
+
bars: 32
|
|
83
|
+
layers: { v1: A↑, v2: B, v3: C }
|
|
84
|
+
- section: "Drift"
|
|
85
|
+
bars: 48
|
|
86
|
+
layers: { v1: A↓, v2: B, v3: C }
|
|
87
|
+
- section: "Fade"
|
|
88
|
+
bars: 32
|
|
89
|
+
layers: { v1: A–, v2: -, v3: - }
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## MCP Responsibilities
|
|
95
|
+
|
|
96
|
+
1. Parse SIDWAVE YAML or JSON input.
|
|
97
|
+
2. Expand patterns, transpositions, and modulation into frame-accurate SID register writes.
|
|
98
|
+
3. Compile to valid `.SID` or `.PRG` binaries with proper init and play routines.
|
|
99
|
+
4. Send the binary to Ultimate64 via:
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
POST /v1/attachment:sid
|
|
103
|
+
Content-Type: application/octet-stream
|
|
104
|
+
Body = compiled binary
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Authoring and Validation
|
|
110
|
+
|
|
111
|
+
- SIDWAVE files are plain YAML and open cleanly in any standard editor.
|
|
112
|
+
- Validation uses JSON Schema:
|
|
113
|
+
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"yaml.schemas": {
|
|
117
|
+
"https://example.com/sidwave.schema.json": "*.sidwave.yaml"
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
This enables autocomplete, hover info, and validation in VS Code or similar IDEs.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## LLM Prompt Template
|
|
127
|
+
|
|
128
|
+
> Compose a 3–5 minute atmospheric, modern electronic SID composition using the **SIDWAVE** format.
|
|
129
|
+
> Use three voices with expressive modulation (PWM, filter sweeps, arpeggios, evolving pads).
|
|
130
|
+
> Output valid YAML conforming to `sidwave.schema.json`.
|
|
131
|
+
> Avoid direct note repetition; reuse and transpose patterns.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://example.com/schemas/sidwave.schema.json",
|
|
4
|
+
"title": "SIDWAVE Composition Schema",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["sidwave", "title", "tempo", "mode", "voices", "timeline"],
|
|
7
|
+
"properties": {
|
|
8
|
+
"sidwave": { "type": ["number", "string"], "enum": [1, "1.0", "1"] },
|
|
9
|
+
"title": { "type": "string" },
|
|
10
|
+
"author": { "type": "string" },
|
|
11
|
+
"tempo": { "type": "number", "minimum": 30, "maximum": 220 },
|
|
12
|
+
"mode": { "type": "string", "enum": ["PAL", "NTSC"] },
|
|
13
|
+
"global_fx": { "type": "object", "additionalProperties": true },
|
|
14
|
+
"voices": {
|
|
15
|
+
"type": "array",
|
|
16
|
+
"minItems": 1,
|
|
17
|
+
"items": {
|
|
18
|
+
"type": "object",
|
|
19
|
+
"required": ["id"],
|
|
20
|
+
"properties": {
|
|
21
|
+
"id": { "type": "number", "minimum": 1, "maximum": 3 },
|
|
22
|
+
"name": { "type": "string" },
|
|
23
|
+
"waveform": { "type": "string", "enum": ["pulse", "sawtooth", "triangle", "noise", "saw", "tri"] },
|
|
24
|
+
"pulse_width": { "type": "number", "minimum": 0 },
|
|
25
|
+
"adsr": { "type": "array", "items": { "type": "number", "minimum": 0, "maximum": 15 }, "minItems": 4, "maxItems": 4 },
|
|
26
|
+
"patterns": {
|
|
27
|
+
"type": "object",
|
|
28
|
+
"additionalProperties": {
|
|
29
|
+
"oneOf": [
|
|
30
|
+
{ "type": "object", "required": ["type", "notes"], "properties": {
|
|
31
|
+
"type": { "const": "arpeggio" },
|
|
32
|
+
"notes": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
|
|
33
|
+
"frame_rate": { "type": "number", "minimum": 1 },
|
|
34
|
+
"fx": { "type": "object", "additionalProperties": true }
|
|
35
|
+
}, "additionalProperties": false },
|
|
36
|
+
{ "type": "object", "properties": {
|
|
37
|
+
"length": { "type": "number", "minimum": 1 },
|
|
38
|
+
"motif": { "type": "string" },
|
|
39
|
+
"transpositions": { "type": "array", "items": { "type": "number" } },
|
|
40
|
+
"fx": { "type": "object", "additionalProperties": true }
|
|
41
|
+
}, "additionalProperties": false },
|
|
42
|
+
{ "type": "object", "required": ["groove"], "properties": {
|
|
43
|
+
"groove": { "type": "array", "items": { "type": "string" }, "minItems": 1 },
|
|
44
|
+
"fx": { "type": "object", "additionalProperties": true }
|
|
45
|
+
}, "additionalProperties": false }
|
|
46
|
+
]
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"additionalProperties": true
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
"timeline": {
|
|
54
|
+
"type": "array",
|
|
55
|
+
"minItems": 1,
|
|
56
|
+
"items": { "type": "object", "required": ["bars", "layers"], "properties": {
|
|
57
|
+
"section": { "type": "string" },
|
|
58
|
+
"bars": { "type": "number", "minimum": 1 },
|
|
59
|
+
"layers": { "type": "object", "additionalProperties": { "type": "string" } }
|
|
60
|
+
}, "additionalProperties": false }
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"additionalProperties": false
|
|
64
|
+
}
|