c64-kb 0.17.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/CHANGELOG.md +2082 -0
- package/LICENSE +29 -0
- package/README.md +559 -0
- package/VERSION +25 -0
- package/dist/cli/setup.js +66 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/cli-memorize-audit.js +97 -0
- package/dist/cli-memorize-audit.js.map +1 -0
- package/dist/cli.js +335 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.js +83 -0
- package/dist/config.js.map +1 -0
- package/dist/context.js +53 -0
- package/dist/context.js.map +1 -0
- package/dist/domain/budget-notes.js +104 -0
- package/dist/domain/budget-notes.js.map +1 -0
- package/dist/domain/budget.js +417 -0
- package/dist/domain/budget.js.map +1 -0
- package/dist/domain/game-design.js +77 -0
- package/dist/domain/game-design.js.map +1 -0
- package/dist/domain/timing.js +39 -0
- package/dist/domain/timing.js.map +1 -0
- package/dist/graph/apply.js +132 -0
- package/dist/graph/apply.js.map +1 -0
- package/dist/graph/claims.js +231 -0
- package/dist/graph/claims.js.map +1 -0
- package/dist/graph/extract/archetype.js +118 -0
- package/dist/graph/extract/archetype.js.map +1 -0
- package/dist/graph/extract/common.js +69 -0
- package/dist/graph/extract/common.js.map +1 -0
- package/dist/graph/extract/failure.js +37 -0
- package/dist/graph/extract/failure.js.map +1 -0
- package/dist/graph/extract/game-design.js +189 -0
- package/dist/graph/extract/game-design.js.map +1 -0
- package/dist/graph/extract/hardware.js +124 -0
- package/dist/graph/extract/hardware.js.map +1 -0
- package/dist/graph/extract/pitfall.js +62 -0
- package/dist/graph/extract/pitfall.js.map +1 -0
- package/dist/graph/extract/raster-band.js +56 -0
- package/dist/graph/extract/raster-band.js.map +1 -0
- package/dist/graph/extract/recipe.js +71 -0
- package/dist/graph/extract/recipe.js.map +1 -0
- package/dist/graph/extract/technique-entities.js +180 -0
- package/dist/graph/extract/technique-entities.js.map +1 -0
- package/dist/graph/extract/technique.js +179 -0
- package/dist/graph/extract/technique.js.map +1 -0
- package/dist/graph/extract/toolchain.js +67 -0
- package/dist/graph/extract/toolchain.js.map +1 -0
- package/dist/graph/extract/types.js +3 -0
- package/dist/graph/extract/types.js.map +1 -0
- package/dist/graph/extract/vocabulary.js +65 -0
- package/dist/graph/extract/vocabulary.js.map +1 -0
- package/dist/graph/extract.js +43 -0
- package/dist/graph/extract.js.map +1 -0
- package/dist/graph/kernal-clobbers.js +64 -0
- package/dist/graph/kernal-clobbers.js.map +1 -0
- package/dist/graph/machine-variants.js +208 -0
- package/dist/graph/machine-variants.js.map +1 -0
- package/dist/ingest/files.js +99 -0
- package/dist/ingest/files.js.map +1 -0
- package/dist/ingest/passes.js +104 -0
- package/dist/ingest/passes.js.map +1 -0
- package/dist/ingest/points.js +50 -0
- package/dist/ingest/points.js.map +1 -0
- package/dist/ingest/report.js +140 -0
- package/dist/ingest/report.js.map +1 -0
- package/dist/ingest/tally.js +81 -0
- package/dist/ingest/tally.js.map +1 -0
- package/dist/ingest/verified-on.js +43 -0
- package/dist/ingest/verified-on.js.map +1 -0
- package/dist/ingest.js +135 -0
- package/dist/ingest.js.map +1 -0
- package/dist/schemas/cost-basis.js +5 -0
- package/dist/schemas/cost-basis.js.map +1 -0
- package/dist/schemas/machine-variant.js +25 -0
- package/dist/schemas/machine-variant.js.map +1 -0
- package/dist/schemas/plan-budget.js +121 -0
- package/dist/schemas/plan-budget.js.map +1 -0
- package/dist/schemas/tool-outputs.js +526 -0
- package/dist/schemas/tool-outputs.js.map +1 -0
- package/dist/server/define-tool.js +52 -0
- package/dist/server/define-tool.js.map +1 -0
- package/dist/server/defined-only.js +9 -0
- package/dist/server/defined-only.js.map +1 -0
- package/dist/server/tools-briefings.js +70 -0
- package/dist/server/tools-briefings.js.map +1 -0
- package/dist/server/tools-lookup.js +180 -0
- package/dist/server/tools-lookup.js.map +1 -0
- package/dist/server/tools-maintenance.js +116 -0
- package/dist/server/tools-maintenance.js.map +1 -0
- package/dist/server/tools-pitfalls.js +89 -0
- package/dist/server/tools-pitfalls.js.map +1 -0
- package/dist/server/tools-recipes.js +296 -0
- package/dist/server/tools-recipes.js.map +1 -0
- package/dist/server/tools-runtime.js +48 -0
- package/dist/server/tools-runtime.js.map +1 -0
- package/dist/server/tools.js +43 -0
- package/dist/server/tools.js.map +1 -0
- package/dist/server.js +95 -0
- package/dist/server.js.map +1 -0
- package/dist/services/analytics/schema.js +78 -0
- package/dist/services/analytics/schema.js.map +1 -0
- package/dist/services/analytics/statements.js +99 -0
- package/dist/services/analytics/statements.js.map +1 -0
- package/dist/services/analytics.js +195 -0
- package/dist/services/analytics.js.map +1 -0
- package/dist/services/bm25.js +158 -0
- package/dist/services/bm25.js.map +1 -0
- package/dist/services/chunker.js +81 -0
- package/dist/services/chunker.js.map +1 -0
- package/dist/services/embeddings.js +58 -0
- package/dist/services/embeddings.js.map +1 -0
- package/dist/services/falkor/base.js +85 -0
- package/dist/services/falkor/base.js.map +1 -0
- package/dist/services/falkor/links.js +361 -0
- package/dist/services/falkor/links.js.map +1 -0
- package/dist/services/falkor/nodes.js +183 -0
- package/dist/services/falkor/nodes.js.map +1 -0
- package/dist/services/falkor/params.js +45 -0
- package/dist/services/falkor/params.js.map +1 -0
- package/dist/services/falkor/schema.js +77 -0
- package/dist/services/falkor/schema.js.map +1 -0
- package/dist/services/falkor.js +100 -0
- package/dist/services/falkor.js.map +1 -0
- package/dist/services/qdrant.js +238 -0
- package/dist/services/qdrant.js.map +1 -0
- package/dist/services/versions.js +73 -0
- package/dist/services/versions.js.map +1 -0
- package/dist/services/vice-bin.js +51 -0
- package/dist/services/vice-bin.js.map +1 -0
- package/dist/tools/briefings/archetype.js +174 -0
- package/dist/tools/briefings/archetype.js.map +1 -0
- package/dist/tools/briefings/budget.js +177 -0
- package/dist/tools/briefings/budget.js.map +1 -0
- package/dist/tools/briefings/build-order.js +135 -0
- package/dist/tools/briefings/build-order.js.map +1 -0
- package/dist/tools/briefings/build.js +185 -0
- package/dist/tools/briefings/build.js.map +1 -0
- package/dist/tools/briefings/discovery.js +290 -0
- package/dist/tools/briefings/discovery.js.map +1 -0
- package/dist/tools/briefings/plan-pitfalls.js +69 -0
- package/dist/tools/briefings/plan-pitfalls.js.map +1 -0
- package/dist/tools/briefings/render.js +151 -0
- package/dist/tools/briefings/render.js.map +1 -0
- package/dist/tools/briefings/rows.js +41 -0
- package/dist/tools/briefings/rows.js.map +1 -0
- package/dist/tools/briefings/toolchain.js +63 -0
- package/dist/tools/briefings/toolchain.js.map +1 -0
- package/dist/tools/briefings/why-proposed.js +69 -0
- package/dist/tools/briefings/why-proposed.js.map +1 -0
- package/dist/tools/briefings.js +44 -0
- package/dist/tools/briefings.js.map +1 -0
- package/dist/tools/feedback.js +97 -0
- package/dist/tools/feedback.js.map +1 -0
- package/dist/tools/hydrate.js +75 -0
- package/dist/tools/hydrate.js.map +1 -0
- package/dist/tools/intelligence.js +67 -0
- package/dist/tools/intelligence.js.map +1 -0
- package/dist/tools/lint/asm-decimal.js +86 -0
- package/dist/tools/lint/asm-decimal.js.map +1 -0
- package/dist/tools/lint/asm-rules.js +221 -0
- package/dist/tools/lint/asm-rules.js.map +1 -0
- package/dist/tools/lint/asm-shared.js +3 -0
- package/dist/tools/lint/asm-shared.js.map +1 -0
- package/dist/tools/lint/c-rules.js +215 -0
- package/dist/tools/lint/c-rules.js.map +1 -0
- package/dist/tools/lint/text.js +122 -0
- package/dist/tools/lint/text.js.map +1 -0
- package/dist/tools/lint/types.js +40 -0
- package/dist/tools/lint/types.js.map +1 -0
- package/dist/tools/lint.js +76 -0
- package/dist/tools/lint.js.map +1 -0
- package/dist/tools/memorization-mcp.js +111 -0
- package/dist/tools/memorization-mcp.js.map +1 -0
- package/dist/tools/pitfalls/bm25.js +53 -0
- package/dist/tools/pitfalls/bm25.js.map +1 -0
- package/dist/tools/pitfalls/format.js +58 -0
- package/dist/tools/pitfalls/format.js.map +1 -0
- package/dist/tools/pitfalls/graph.js +124 -0
- package/dist/tools/pitfalls/graph.js.map +1 -0
- package/dist/tools/pitfalls.js +134 -0
- package/dist/tools/pitfalls.js.map +1 -0
- package/dist/tools/prompts.js +81 -0
- package/dist/tools/prompts.js.map +1 -0
- package/dist/tools/query/compatibility/closure.js +62 -0
- package/dist/tools/query/compatibility/closure.js.map +1 -0
- package/dist/tools/query/compatibility/facts.js +28 -0
- package/dist/tools/query/compatibility/facts.js.map +1 -0
- package/dist/tools/query/compatibility/fetch.js +164 -0
- package/dist/tools/query/compatibility/fetch.js.map +1 -0
- package/dist/tools/query/compatibility/hard-rules.js +159 -0
- package/dist/tools/query/compatibility/hard-rules.js.map +1 -0
- package/dist/tools/query/compatibility/index.js +27 -0
- package/dist/tools/query/compatibility/index.js.map +1 -0
- package/dist/tools/query/compatibility/kernal-zp-rule.js +90 -0
- package/dist/tools/query/compatibility/kernal-zp-rule.js.map +1 -0
- package/dist/tools/query/compatibility/render.js +106 -0
- package/dist/tools/query/compatibility/render.js.map +1 -0
- package/dist/tools/query/compatibility/rules.js +337 -0
- package/dist/tools/query/compatibility/rules.js.map +1 -0
- package/dist/tools/query/compatibility/unit-rules.js +253 -0
- package/dist/tools/query/compatibility/unit-rules.js.map +1 -0
- package/dist/tools/query/game-design.js +83 -0
- package/dist/tools/query/game-design.js.map +1 -0
- package/dist/tools/query/lookups.js +220 -0
- package/dist/tools/query/lookups.js.map +1 -0
- package/dist/tools/query/plan-budget.js +266 -0
- package/dist/tools/query/plan-budget.js.map +1 -0
- package/dist/tools/query/recipes.js +214 -0
- package/dist/tools/query/recipes.js.map +1 -0
- package/dist/tools/query/retrieval.js +128 -0
- package/dist/tools/query/retrieval.js.map +1 -0
- package/dist/tools/query/shared.js +121 -0
- package/dist/tools/query/shared.js.map +1 -0
- package/dist/tools/query/techniques.js +331 -0
- package/dist/tools/query/techniques.js.map +1 -0
- package/dist/tools/query/timing.js +106 -0
- package/dist/tools/query/timing.js.map +1 -0
- package/dist/tools/query/types.js +11 -0
- package/dist/tools/query/types.js.map +1 -0
- package/dist/tools/query.js +21 -0
- package/dist/tools/query.js.map +1 -0
- package/dist/tools/resources.js +186 -0
- package/dist/tools/resources.js.map +1 -0
- package/dist/tools/run-game.js +249 -0
- package/dist/tools/run-game.js.map +1 -0
- package/dist/tools/selfimprovement.js +367 -0
- package/dist/tools/selfimprovement.js.map +1 -0
- package/docker-compose.yml +35 -0
- package/docs/ARCHITECTURE.md +164 -0
- package/docs/CONVENTIONS-archetypes.md +158 -0
- package/docs/CONVENTIONS-failures.md +46 -0
- package/docs/CONVENTIONS-game-designs.md +75 -0
- package/docs/CONVENTIONS-hardware-reference.md +184 -0
- package/docs/CONVENTIONS-pitfalls.md +91 -0
- package/docs/CONVENTIONS-recipes.md +106 -0
- package/docs/CONVENTIONS-techniques.md +309 -0
- package/docs/CONVENTIONS-toolchain-reference.md +89 -0
- package/docs/ONTOLOGY.md +655 -0
- package/docs/art/art-production-reference.md +157 -0
- package/docs/art/asset-pipelines.md +586 -0
- package/docs/c64-failure-patterns.md +693 -0
- package/docs/demo-design/demo-composition.md +349 -0
- package/docs/demo-design/demo-design-philosophy.md +320 -0
- package/docs/demo-design/intro-cracktro-patterns.md +435 -0
- package/docs/figures/ctm-spd-embed-probe.png +0 -0
- package/docs/figures/dot-flag-mid-5000000.png +0 -0
- package/docs/figures/dot-flag-no-erase-12000000.png +0 -0
- package/docs/figures/edges.json +1 -0
- package/docs/figures/fig6-architecture.png +0 -0
- package/docs/figures/fig7-ontology.png +0 -0
- package/docs/figures/screen-dissolve-mid-frame25.png +0 -0
- package/docs/figures/screen-dissolve-wipe-frame25.png +0 -0
- package/docs/figures/spindle-two-parts-part1.png +0 -0
- package/docs/figures/spindle-two-parts-part2.png +0 -0
- package/docs/figures/starters/action-puzzle.png +0 -0
- package/docs/figures/starters/adventure.png +0 -0
- package/docs/figures/starters/beat-em-up.png +0 -0
- package/docs/figures/starters/demo.png +0 -0
- package/docs/figures/starters/platformer.png +0 -0
- package/docs/figures/starters/shmup-vertical.png +0 -0
- package/docs/figures/tape-kernal-master-ntsc.png +0 -0
- package/docs/figures/tape-kernal-master-pal.png +0 -0
- package/docs/figures/tape-turbo-loader-ntsc.png +0 -0
- package/docs/figures/tape-turbo-loader-pal.png +0 -0
- package/docs/figures/tape-turbo-master-ntsc.png +0 -0
- package/docs/figures/tape-turbo-master-pal.png +0 -0
- package/docs/figures/tech-tech-pad2-12000000.png +0 -0
- package/docs/figures/tech-tech-pad4-12000000.png +0 -0
- package/docs/figures/tech-tech-seven-12000000.png +0 -0
- package/docs/figures/twister-mid-5000000.png +0 -0
- package/docs/figures/twister-straight-12000000.png +0 -0
- package/docs/figures/vector-balls-nosort-ntsc.png +0 -0
- package/docs/figures/vector-balls-nosort.png +0 -0
- package/docs/formats/c64-file-formats.md +1212 -0
- package/docs/formats/iec-disk-reference.md +754 -0
- package/docs/game-design/c64-game-archetypes.md +273 -0
- package/docs/game-design/designs/falling-blocks.md +54 -0
- package/docs/game-design/designs/platformer-scaffold.md +48 -0
- package/docs/game-design/designs/simple-shmup.md +27 -0
- package/docs/game-design/enemy-behaviour-and-difficulty.md +349 -0
- package/docs/game-design/game-design-patterns.md +1189 -0
- package/docs/game-design/game-structure.md +354 -0
- package/docs/game-design/production-planning.md +349 -0
- package/docs/game-design/reference-game-sources.md +90 -0
- package/docs/hardware/6502-illegal-opcodes.md +1353 -0
- package/docs/hardware/6510-cpu-reference.md +2112 -0
- package/docs/hardware/c64-memory-map.md +3184 -0
- package/docs/hardware/c64-registers-reference.md +996 -0
- package/docs/hardware/cia-reference.md +1281 -0
- package/docs/hardware/kernal-routines-reference.md +1836 -0
- package/docs/hardware/pal-ntsc-reference.md +813 -0
- package/docs/hardware/sid-reference.md +1137 -0
- package/docs/hardware/vic-ii-reference.md +1714 -0
- package/docs/music/music-production-reference.md +403 -0
- package/docs/pitfalls/banking.md +1067 -0
- package/docs/pitfalls/cia.md +1147 -0
- package/docs/pitfalls/cpu.md +874 -0
- package/docs/pitfalls/input.md +282 -0
- package/docs/pitfalls/kernal-and-io.md +1615 -0
- package/docs/pitfalls/loader.md +1191 -0
- package/docs/pitfalls/logic.md +94 -0
- package/docs/pitfalls/maths.md +187 -0
- package/docs/pitfalls/raster-and-badline.md +721 -0
- package/docs/pitfalls/region-timing.md +660 -0
- package/docs/pitfalls/scroll.md +207 -0
- package/docs/pitfalls/sid.md +738 -0
- package/docs/pitfalls/sprite.md +979 -0
- package/docs/pitfalls/text-mode-render.md +1172 -0
- package/docs/recipes/cc65/cartridge-8k.md +398 -0
- package/docs/recipes/cc65/hello-world-conio.md +76 -0
- package/docs/recipes/cc65/memory-layout.md +312 -0
- package/docs/recipes/cc65/screenshots/README.md +14 -0
- package/docs/recipes/cc65/screenshots/cartridge-8k-ntsc.png +0 -0
- package/docs/recipes/cc65/screenshots/cartridge-8k.png +0 -0
- package/docs/recipes/cc65/screenshots/hello-world-conio.png +0 -0
- package/docs/recipes/cc65/screenshots/memory-layout-ntsc.png +0 -0
- package/docs/recipes/cc65/screenshots/memory-layout.png +0 -0
- package/docs/recipes/kickassembler/basic-float-calls.md +578 -0
- package/docs/recipes/kickassembler/basic-wedge.md +398 -0
- package/docs/recipes/kickassembler/big-font-scroller.md +620 -0
- package/docs/recipes/kickassembler/charset-copy-rom-to-ram.md +623 -0
- package/docs/recipes/kickassembler/cia-revision-detect.md +366 -0
- package/docs/recipes/kickassembler/colour-cycling.md +343 -0
- package/docs/recipes/kickassembler/colour-fade.md +303 -0
- package/docs/recipes/kickassembler/compare-16bit-signed.md +1007 -0
- package/docs/recipes/kickassembler/cracktro-template.md +526 -0
- package/docs/recipes/kickassembler/crt-banked.md +276 -0
- package/docs/recipes/kickassembler/dos-error-codes.md +466 -0
- package/docs/recipes/kickassembler/dot-flag.md +576 -0
- package/docs/recipes/kickassembler/drive-job-queue.md +667 -0
- package/docs/recipes/kickassembler/drive-via-probe.md +690 -0
- package/docs/recipes/kickassembler/dycp-scroller.md +568 -0
- package/docs/recipes/kickassembler/dypp-sprite-scroller.md +681 -0
- package/docs/recipes/kickassembler/dysp.md +670 -0
- package/docs/recipes/kickassembler/easyflash-save.md +800 -0
- package/docs/recipes/kickassembler/eight-way-scroll.md +1484 -0
- package/docs/recipes/kickassembler/file-io-roundtrip.md +546 -0
- package/docs/recipes/kickassembler/fire-effect.md +420 -0
- package/docs/recipes/kickassembler/fld.md +414 -0
- package/docs/recipes/kickassembler/fli-image.md +336 -0
- package/docs/recipes/kickassembler/four-player-read.md +672 -0
- package/docs/recipes/kickassembler/headless-verify.md +228 -0
- package/docs/recipes/kickassembler/hello-world.md +98 -0
- package/docs/recipes/kickassembler/high-score-insert.md +660 -0
- package/docs/recipes/kickassembler/hires-plot-line.md +723 -0
- package/docs/recipes/kickassembler/irq-chain.md +316 -0
- package/docs/recipes/kickassembler/irq-owns-port.md +668 -0
- package/docs/recipes/kickassembler/isometric-room.md +1145 -0
- package/docs/recipes/kickassembler/light-pen-read.md +926 -0
- package/docs/recipes/kickassembler/logic-rate-decoupling.md +670 -0
- package/docs/recipes/kickassembler/mci-interlace.md +543 -0
- package/docs/recipes/kickassembler/memory-layout.md +277 -0
- package/docs/recipes/kickassembler/mouse-1351-read.md +801 -0
- package/docs/recipes/kickassembler/nmi-timer-tick.md +562 -0
- package/docs/recipes/kickassembler/own-keyscan.md +881 -0
- package/docs/recipes/kickassembler/paddle-read.md +751 -0
- package/docs/recipes/kickassembler/palette-cells.md +219 -0
- package/docs/recipes/kickassembler/pseudo-3d-road.md +930 -0
- package/docs/recipes/kickassembler/pwm-digi.md +463 -0
- package/docs/recipes/kickassembler/raster-bars.md +264 -0
- package/docs/recipes/kickassembler/reu-dma.md +1019 -0
- package/docs/recipes/kickassembler/runtime-relocation.md +743 -0
- package/docs/recipes/kickassembler/screen-dissolve.md +545 -0
- package/docs/recipes/kickassembler/screen-wipe.md +408 -0
- package/docs/recipes/kickassembler/screenshots/README.md +72 -0
- package/docs/recipes/kickassembler/screenshots/basic-float-calls-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/basic-float-calls.png +0 -0
- package/docs/recipes/kickassembler/screenshots/basic-wedge-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/basic-wedge.png +0 -0
- package/docs/recipes/kickassembler/screenshots/big-font-scroller-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/big-font-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/charset-copy-rom-to-ram-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/charset-copy-rom-to-ram.png +0 -0
- package/docs/recipes/kickassembler/screenshots/cia-revision-detect-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/cia-revision-detect.png +0 -0
- package/docs/recipes/kickassembler/screenshots/colour-cycling-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/colour-cycling.png +0 -0
- package/docs/recipes/kickassembler/screenshots/colour-fade-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/colour-fade.png +0 -0
- package/docs/recipes/kickassembler/screenshots/compare-16bit-signed-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/compare-16bit-signed.png +0 -0
- package/docs/recipes/kickassembler/screenshots/cracktro-template.png +0 -0
- package/docs/recipes/kickassembler/screenshots/crt-banked-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/crt-banked.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dos-error-codes-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dos-error-codes.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dot-flag-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dot-flag.png +0 -0
- package/docs/recipes/kickassembler/screenshots/drive-job-queue-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/drive-job-queue.png +0 -0
- package/docs/recipes/kickassembler/screenshots/drive-via-probe-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/drive-via-probe.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dycp-scroller-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dycp-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dypp-sprite-scroller-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dypp-sprite-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dysp-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/dysp.png +0 -0
- package/docs/recipes/kickassembler/screenshots/easyflash-save-ntsc-run2.png +0 -0
- package/docs/recipes/kickassembler/screenshots/easyflash-save-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/easyflash-save-run2.png +0 -0
- package/docs/recipes/kickassembler/screenshots/easyflash-save.png +0 -0
- package/docs/recipes/kickassembler/screenshots/eight-way-scroll-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/eight-way-scroll.png +0 -0
- package/docs/recipes/kickassembler/screenshots/file-io-roundtrip-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/file-io-roundtrip.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fire-effect-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fire-effect.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fld-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fld.png +0 -0
- package/docs/recipes/kickassembler/screenshots/fli-image.png +0 -0
- package/docs/recipes/kickassembler/screenshots/four-player-read-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/four-player-read.png +0 -0
- package/docs/recipes/kickassembler/screenshots/headless-verify-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/headless-verify.png +0 -0
- package/docs/recipes/kickassembler/screenshots/hello-world.png +0 -0
- package/docs/recipes/kickassembler/screenshots/high-score-insert-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/high-score-insert.png +0 -0
- package/docs/recipes/kickassembler/screenshots/hires-plot-line-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/hires-plot-line.png +0 -0
- package/docs/recipes/kickassembler/screenshots/irq-chain-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/irq-chain.png +0 -0
- package/docs/recipes/kickassembler/screenshots/irq-owns-port-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/irq-owns-port.png +0 -0
- package/docs/recipes/kickassembler/screenshots/isometric-room-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/isometric-room.png +0 -0
- package/docs/recipes/kickassembler/screenshots/light-pen-read-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/light-pen-read.png +0 -0
- package/docs/recipes/kickassembler/screenshots/logic-rate-decoupling-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/logic-rate-decoupling.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mci-interlace-average.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mci-interlace-frame-b.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mci-interlace-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mci-interlace.png +0 -0
- package/docs/recipes/kickassembler/screenshots/memory-layout-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/memory-layout.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mouse-1351-read-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/mouse-1351-read.png +0 -0
- package/docs/recipes/kickassembler/screenshots/nmi-timer-tick-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/nmi-timer-tick.png +0 -0
- package/docs/recipes/kickassembler/screenshots/own-keyscan-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/own-keyscan.png +0 -0
- package/docs/recipes/kickassembler/screenshots/paddle-read-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/paddle-read.png +0 -0
- package/docs/recipes/kickassembler/screenshots/palette-cells-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/palette-cells.png +0 -0
- package/docs/recipes/kickassembler/screenshots/pseudo-3d-road-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/pseudo-3d-road.png +0 -0
- package/docs/recipes/kickassembler/screenshots/pwm-digi-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/pwm-digi.png +0 -0
- package/docs/recipes/kickassembler/screenshots/raster-bars.png +0 -0
- package/docs/recipes/kickassembler/screenshots/reu-dma-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/reu-dma.png +0 -0
- package/docs/recipes/kickassembler/screenshots/runtime-relocation-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/runtime-relocation.png +0 -0
- package/docs/recipes/kickassembler/screenshots/screen-dissolve-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/screen-dissolve.png +0 -0
- package/docs/recipes/kickassembler/screenshots/screen-wipe-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/screen-wipe.png +0 -0
- package/docs/recipes/kickassembler/screenshots/scroll-panel-split-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/scroll-panel-split.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sfx-in-player-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sfx-in-player.png +0 -0
- package/docs/recipes/kickassembler/screenshots/shadebobs-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/shadebobs.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sideborder-open.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sine-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sine-table-runtime-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sine-table-runtime.png +0 -0
- package/docs/recipes/kickassembler/screenshots/software-sprite-preshifted-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/software-sprite-preshifted.png +0 -0
- package/docs/recipes/kickassembler/screenshots/speedcode-generator-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/speedcode-generator.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-border-scroller-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-border-scroller.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-cache-flip-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-cache-flip.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-multiplex-24.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-multiplex-game-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-multiplex-game.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-priority-classes-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-priority-classes.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-sine-chain-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-sine-chain.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-stretcher-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprite-stretcher.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprites-only-screen-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sprites-only-screen.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sqrt-atan2-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/sqrt-atan2.png +0 -0
- package/docs/recipes/kickassembler/screenshots/stable-raster-irq-control.png +0 -0
- package/docs/recipes/kickassembler/screenshots/stable-raster-irq.png +0 -0
- package/docs/recipes/kickassembler/screenshots/tech-tech-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/tech-tech.png +0 -0
- package/docs/recipes/kickassembler/screenshots/tod-alarm-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/tod-alarm.png +0 -0
- package/docs/recipes/kickassembler/screenshots/topbottom-border-open.png +0 -0
- package/docs/recipes/kickassembler/screenshots/twister-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/twister.png +0 -0
- package/docs/recipes/kickassembler/screenshots/unit-test-driver-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/unit-test-driver.png +0 -0
- package/docs/recipes/kickassembler/screenshots/vector-balls-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/vector-balls.png +0 -0
- package/docs/recipes/kickassembler/screenshots/wireframe-ships-ntsc.png +0 -0
- package/docs/recipes/kickassembler/screenshots/wireframe-ships.png +0 -0
- package/docs/recipes/kickassembler/scroll-panel-split.md +381 -0
- package/docs/recipes/kickassembler/sfx-in-player.md +907 -0
- package/docs/recipes/kickassembler/shadebobs.md +522 -0
- package/docs/recipes/kickassembler/sideborder-open.md +338 -0
- package/docs/recipes/kickassembler/sine-scroller.md +321 -0
- package/docs/recipes/kickassembler/sine-table-runtime.md +815 -0
- package/docs/recipes/kickassembler/software-sprite-preshifted.md +725 -0
- package/docs/recipes/kickassembler/speedcode-generator.md +606 -0
- package/docs/recipes/kickassembler/sprite-border-scroller.md +696 -0
- package/docs/recipes/kickassembler/sprite-cache-flip.md +1071 -0
- package/docs/recipes/kickassembler/sprite-multiplex-24.md +326 -0
- package/docs/recipes/kickassembler/sprite-multiplex-game.md +986 -0
- package/docs/recipes/kickassembler/sprite-priority-classes.md +463 -0
- package/docs/recipes/kickassembler/sprite-sine-chain.md +338 -0
- package/docs/recipes/kickassembler/sprite-stretcher.md +501 -0
- package/docs/recipes/kickassembler/sprites-only-screen.md +550 -0
- package/docs/recipes/kickassembler/sqrt-atan2.md +1014 -0
- package/docs/recipes/kickassembler/stable-raster-irq.md +360 -0
- package/docs/recipes/kickassembler/tape-turbo-loader.md +875 -0
- package/docs/recipes/kickassembler/tech-tech.md +679 -0
- package/docs/recipes/kickassembler/tod-alarm.md +754 -0
- package/docs/recipes/kickassembler/topbottom-border-open.md +407 -0
- package/docs/recipes/kickassembler/twister.md +518 -0
- package/docs/recipes/kickassembler/unit-test-driver.md +314 -0
- package/docs/recipes/kickassembler/vector-balls.md +545 -0
- package/docs/recipes/kickassembler/wireframe-ships.md +2324 -0
- package/docs/recipes/oscar64/actor-activation-window.md +807 -0
- package/docs/recipes/oscar64/adventure-engine.md +1094 -0
- package/docs/recipes/oscar64/attract-replay.md +465 -0
- package/docs/recipes/oscar64/beat-em-up-lanes.md +563 -0
- package/docs/recipes/oscar64/bfs-distance-map.md +723 -0
- package/docs/recipes/oscar64/bitmap-koala-viewer.md +355 -0
- package/docs/recipes/oscar64/car-contact.md +950 -0
- package/docs/recipes/oscar64/cave-scan.md +609 -0
- package/docs/recipes/oscar64/char-bullets.md +477 -0
- package/docs/recipes/oscar64/charset-animation.md +383 -0
- package/docs/recipes/oscar64/charset-parallax.md +401 -0
- package/docs/recipes/oscar64/destructible-terrain.md +1099 -0
- package/docs/recipes/oscar64/difficulty-tables.md +654 -0
- package/docs/recipes/oscar64/dig-and-guards.md +975 -0
- package/docs/recipes/oscar64/directory-reader.md +535 -0
- package/docs/recipes/oscar64/divide-check.md +581 -0
- package/docs/recipes/oscar64/double-buffer-nomirror.md +205 -0
- package/docs/recipes/oscar64/double-buffer.md +255 -0
- package/docs/recipes/oscar64/falling-blocks.md +874 -0
- package/docs/recipes/oscar64/fixed-point-jump-velocity.md +289 -0
- package/docs/recipes/oscar64/fixed-point-jump.md +210 -0
- package/docs/recipes/oscar64/flip-screen-rooms.md +793 -0
- package/docs/recipes/oscar64/frame-sync-loop-overrun.md +214 -0
- package/docs/recipes/oscar64/frame-sync-loop.md +254 -0
- package/docs/recipes/oscar64/game-tree-search.md +743 -0
- package/docs/recipes/oscar64/ghost-targeting.md +867 -0
- package/docs/recipes/oscar64/headless-verify.md +345 -0
- package/docs/recipes/oscar64/hello-world.md +83 -0
- package/docs/recipes/oscar64/high-score-persist.md +772 -0
- package/docs/recipes/oscar64/iffl-kernal-skip.md +421 -0
- package/docs/recipes/oscar64/joystick-input.md +358 -0
- package/docs/recipes/oscar64/lane-pursuit.md +1028 -0
- package/docs/recipes/oscar64/level-rle-decoder.md +620 -0
- package/docs/recipes/oscar64/lfsr-random-seed2.md +338 -0
- package/docs/recipes/oscar64/lfsr-random.md +403 -0
- package/docs/recipes/oscar64/load-asset-runtime.md +492 -0
- package/docs/recipes/oscar64/memory-layout.md +232 -0
- package/docs/recipes/oscar64/mixed-fighters.md +781 -0
- package/docs/recipes/oscar64/multi-sprite-object.md +533 -0
- package/docs/recipes/oscar64/nav-area-pathfinding.md +881 -0
- package/docs/recipes/oscar64/object-pool.md +572 -0
- package/docs/recipes/oscar64/pal-ntsc-detect.md +257 -0
- package/docs/recipes/oscar64/password-state.md +532 -0
- package/docs/recipes/oscar64/per-frame-hitbox.md +651 -0
- package/docs/recipes/oscar64/petscii-screen-codes.md +428 -0
- package/docs/recipes/oscar64/platformer-scaffold.md +1467 -0
- package/docs/recipes/oscar64/print-number.md +367 -0
- package/docs/recipes/oscar64/raster-bars.md +239 -0
- package/docs/recipes/oscar64/raster-profile-bars.md +404 -0
- package/docs/recipes/oscar64/rel-side-sectors.md +391 -0
- package/docs/recipes/oscar64/relative-file-records.md +378 -0
- package/docs/recipes/oscar64/save-load-seq-file.md +365 -0
- package/docs/recipes/oscar64/screenshots/README.md +99 -0
- package/docs/recipes/oscar64/screenshots/actor-activation-window-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/actor-activation-window.png +0 -0
- package/docs/recipes/oscar64/screenshots/adventure-engine-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/adventure-engine.png +0 -0
- package/docs/recipes/oscar64/screenshots/attract-replay-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/attract-replay.png +0 -0
- package/docs/recipes/oscar64/screenshots/beat-em-up-lanes-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/beat-em-up-lanes.png +0 -0
- package/docs/recipes/oscar64/screenshots/bfs-distance-map-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/bfs-distance-map.png +0 -0
- package/docs/recipes/oscar64/screenshots/bitmap-koala-viewer.png +0 -0
- package/docs/recipes/oscar64/screenshots/car-contact-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/car-contact.png +0 -0
- package/docs/recipes/oscar64/screenshots/cave-scan-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/cave-scan.png +0 -0
- package/docs/recipes/oscar64/screenshots/char-bullets-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/char-bullets.png +0 -0
- package/docs/recipes/oscar64/screenshots/charset-animation-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/charset-animation.png +0 -0
- package/docs/recipes/oscar64/screenshots/charset-parallax-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/charset-parallax.png +0 -0
- package/docs/recipes/oscar64/screenshots/destructible-terrain-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/destructible-terrain.png +0 -0
- package/docs/recipes/oscar64/screenshots/difficulty-tables-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/difficulty-tables.png +0 -0
- package/docs/recipes/oscar64/screenshots/dig-and-guards-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/dig-and-guards.png +0 -0
- package/docs/recipes/oscar64/screenshots/directory-reader-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/directory-reader.png +0 -0
- package/docs/recipes/oscar64/screenshots/divide-check-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/divide-check.png +0 -0
- package/docs/recipes/oscar64/screenshots/double-buffer-nomirror.png +0 -0
- package/docs/recipes/oscar64/screenshots/double-buffer-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/double-buffer.png +0 -0
- package/docs/recipes/oscar64/screenshots/falling-blocks-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/falling-blocks.png +0 -0
- package/docs/recipes/oscar64/screenshots/fixed-point-jump-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/fixed-point-jump-velocity-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/fixed-point-jump-velocity.png +0 -0
- package/docs/recipes/oscar64/screenshots/fixed-point-jump.png +0 -0
- package/docs/recipes/oscar64/screenshots/flip-screen-rooms-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/flip-screen-rooms.png +0 -0
- package/docs/recipes/oscar64/screenshots/frame-sync-loop-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/frame-sync-loop-overrun.png +0 -0
- package/docs/recipes/oscar64/screenshots/frame-sync-loop.png +0 -0
- package/docs/recipes/oscar64/screenshots/game-tree-search-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/game-tree-search.png +0 -0
- package/docs/recipes/oscar64/screenshots/ghost-targeting-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/ghost-targeting.png +0 -0
- package/docs/recipes/oscar64/screenshots/headless-verify-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/headless-verify.png +0 -0
- package/docs/recipes/oscar64/screenshots/hello-world.png +0 -0
- package/docs/recipes/oscar64/screenshots/high-score-persist-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/high-score-persist.png +0 -0
- package/docs/recipes/oscar64/screenshots/iffl-kernal-skip-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/iffl-kernal-skip.png +0 -0
- package/docs/recipes/oscar64/screenshots/joystick-input-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/joystick-input.png +0 -0
- package/docs/recipes/oscar64/screenshots/lane-pursuit-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/lane-pursuit.png +0 -0
- package/docs/recipes/oscar64/screenshots/level-rle-decoder-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/level-rle-decoder.png +0 -0
- package/docs/recipes/oscar64/screenshots/lfsr-random-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/lfsr-random-seed2.png +0 -0
- package/docs/recipes/oscar64/screenshots/lfsr-random.png +0 -0
- package/docs/recipes/oscar64/screenshots/load-asset-runtime-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/load-asset-runtime.png +0 -0
- package/docs/recipes/oscar64/screenshots/memory-layout-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/memory-layout.png +0 -0
- package/docs/recipes/oscar64/screenshots/mixed-fighters-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/mixed-fighters.png +0 -0
- package/docs/recipes/oscar64/screenshots/multi-sprite-object-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/multi-sprite-object.png +0 -0
- package/docs/recipes/oscar64/screenshots/nav-area-pathfinding-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/nav-area-pathfinding.png +0 -0
- package/docs/recipes/oscar64/screenshots/object-pool-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/object-pool.png +0 -0
- package/docs/recipes/oscar64/screenshots/pal-ntsc-detect-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/pal-ntsc-detect-oldntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/pal-ntsc-detect-pal.png +0 -0
- package/docs/recipes/oscar64/screenshots/password-state-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/password-state.png +0 -0
- package/docs/recipes/oscar64/screenshots/per-frame-hitbox-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/per-frame-hitbox.png +0 -0
- package/docs/recipes/oscar64/screenshots/petscii-screen-codes-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/petscii-screen-codes.png +0 -0
- package/docs/recipes/oscar64/screenshots/platformer-scaffold-d64-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/platformer-scaffold-d64.png +0 -0
- package/docs/recipes/oscar64/screenshots/platformer-scaffold-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/platformer-scaffold.png +0 -0
- package/docs/recipes/oscar64/screenshots/print-number-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/print-number.png +0 -0
- package/docs/recipes/oscar64/screenshots/raster-bars.png +0 -0
- package/docs/recipes/oscar64/screenshots/raster-profile-bars-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/raster-profile-bars.png +0 -0
- package/docs/recipes/oscar64/screenshots/rel-side-sectors-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/rel-side-sectors.png +0 -0
- package/docs/recipes/oscar64/screenshots/relative-file-records-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/relative-file-records.png +0 -0
- package/docs/recipes/oscar64/screenshots/save-load-seq-file-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/save-load-seq-file.png +0 -0
- package/docs/recipes/oscar64/screenshots/seeded-level-fill-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/seeded-level-fill.png +0 -0
- package/docs/recipes/oscar64/screenshots/sfx-engine-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/sfx-engine.png +0 -0
- package/docs/recipes/oscar64/screenshots/sid-music-player.png +0 -0
- package/docs/recipes/oscar64/screenshots/simple-shmup.png +0 -0
- package/docs/recipes/oscar64/screenshots/slope-collision-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/slope-collision.png +0 -0
- package/docs/recipes/oscar64/screenshots/soft-scroll-h.png +0 -0
- package/docs/recipes/oscar64/screenshots/sprite-animation-table-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/sprite-animation-table.png +0 -0
- package/docs/recipes/oscar64/screenshots/sprite-multiplex-8.png +0 -0
- package/docs/recipes/oscar64/screenshots/stable-raster-irq.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-input-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-input.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield-gameover.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield-notrail-control.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield-ungated-control.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-overlay-playfield.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-window-menu-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/text-window-menu.png +0 -0
- package/docs/recipes/oscar64/screenshots/tile-grid-collision-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/tile-grid-collision.png +0 -0
- package/docs/recipes/oscar64/screenshots/tile-map-render-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/tile-map-render.png +0 -0
- package/docs/recipes/oscar64/screenshots/two-player-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/two-player.png +0 -0
- package/docs/recipes/oscar64/screenshots/two-word-parser-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/two-word-parser.png +0 -0
- package/docs/recipes/oscar64/screenshots/vehicle-control-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/vehicle-control.png +0 -0
- package/docs/recipes/oscar64/screenshots/wave-director-ntsc.png +0 -0
- package/docs/recipes/oscar64/screenshots/wave-director.png +0 -0
- package/docs/recipes/oscar64/seeded-level-fill.md +364 -0
- package/docs/recipes/oscar64/sfx-engine.md +514 -0
- package/docs/recipes/oscar64/sid-music-player.md +441 -0
- package/docs/recipes/oscar64/simple-shmup.md +1000 -0
- package/docs/recipes/oscar64/slope-collision.md +610 -0
- package/docs/recipes/oscar64/soft-scroll-h.md +261 -0
- package/docs/recipes/oscar64/sprite-animation-table.md +671 -0
- package/docs/recipes/oscar64/sprite-multiplex-8.md +314 -0
- package/docs/recipes/oscar64/stable-raster-irq.md +236 -0
- package/docs/recipes/oscar64/text-input.md +274 -0
- package/docs/recipes/oscar64/text-overlay-playfield.md +617 -0
- package/docs/recipes/oscar64/text-window-menu.md +551 -0
- package/docs/recipes/oscar64/tile-grid-collision.md +563 -0
- package/docs/recipes/oscar64/tile-map-render.md +395 -0
- package/docs/recipes/oscar64/two-player.md +528 -0
- package/docs/recipes/oscar64/two-word-parser.md +510 -0
- package/docs/recipes/oscar64/vehicle-control.md +771 -0
- package/docs/recipes/oscar64/wave-director.md +787 -0
- package/docs/recipes/runs.json +1606 -0
- package/docs/runtime/sim6502-reference.md +466 -0
- package/docs/runtime/vice-mcp-reference.md +351 -0
- package/docs/runtime/vice-reference.md +1393 -0
- package/docs/techniques/bitmap-modes.md +685 -0
- package/docs/techniques/cpu-cycle-tricks.md +1570 -0
- package/docs/techniques/effects-vector-3d.md +1431 -0
- package/docs/techniques/file-io.md +1427 -0
- package/docs/techniques/input.md +1072 -0
- package/docs/techniques/loaders-packers.md +768 -0
- package/docs/techniques/logic.md +3091 -0
- package/docs/techniques/maths.md +1524 -0
- package/docs/techniques/memory-banking.md +1686 -0
- package/docs/techniques/music-sid.md +1144 -0
- package/docs/techniques/raster.md +1543 -0
- package/docs/techniques/scroll.md +1292 -0
- package/docs/techniques/sprite.md +2566 -0
- package/docs/techniques/text-mode-render.md +717 -0
- package/docs/techniques/text.md +1095 -0
- package/docs/techniques/transitions.md +405 -0
- package/docs/toolchains/cartconv-reference.md +262 -0
- package/docs/toolchains/cc1541-reference.md +316 -0
- package/docs/toolchains/cc65-reference.md +667 -0
- package/docs/toolchains/error-sources/cc65/README.md +1 -0
- package/docs/toolchains/error-sources/cc65/missing-setcpu.s +4 -0
- package/docs/toolchains/error-sources/cc65/range-error.s +4 -0
- package/docs/toolchains/error-sources/cc65/segment-overflow.c +6 -0
- package/docs/toolchains/error-sources/cc65/unresolved-external.c +6 -0
- package/docs/toolchains/error-sources/kickassembler/README.md +1 -0
- package/docs/toolchains/error-sources/kickassembler/branch-out-of-range.asm +4 -0
- package/docs/toolchains/error-sources/kickassembler/failed-assert.asm +3 -0
- package/docs/toolchains/error-sources/kickassembler/flat-lib.asm +4 -0
- package/docs/toolchains/error-sources/kickassembler/import-source-no-namespace.asm +5 -0
- package/docs/toolchains/error-sources/kickassembler/macro-without-parentheses.asm +6 -0
- package/docs/toolchains/error-sources/kickassembler/memory-block-overlap.asm +4 -0
- package/docs/toolchains/error-sources/kickassembler/symbol-clash-lib.asm +5 -0
- package/docs/toolchains/error-sources/kickassembler/symbol-clash-main.asm +6 -0
- package/docs/toolchains/error-sources/kickassembler/unknown-symbol.asm +4 -0
- package/docs/toolchains/error-sources/oscar64/README.md +1 -0
- package/docs/toolchains/error-sources/oscar64/asm-addressing-mode.c +7 -0
- package/docs/toolchains/error-sources/oscar64/region-overflow.c +6 -0
- package/docs/toolchains/error-sources/oscar64/undefined-extern-var.c +5 -0
- package/docs/toolchains/error-sources/oscar64/undefined-extern.c +6 -0
- package/docs/toolchains/error-sources/oscar64/unknown-vic-field.c +6 -0
- package/docs/toolchains/error-sources/oscar64/void-main.c +3 -0
- package/docs/toolchains/kickassembler-reference.md +1020 -0
- package/docs/toolchains/memory-layout-planning.md +362 -0
- package/docs/toolchains/oscar64-headers-reference.md +583 -0
- package/docs/toolchains/oscar64-reference.md +892 -0
- package/docs/toolchains/petcat-reference.md +290 -0
- package/docs/toolchains/png2prg.md +188 -0
- package/docs/toolchains/release-disk.md +314 -0
- package/docs/toolchains/sidreloc.md +236 -0
- package/docs/toolchains/spindle-reference.md +487 -0
- package/docs/toolchains/tape-mastering.md +592 -0
- package/docs/toolchains/unit-testing-6502.md +281 -0
- package/docs/workflow/agent-harness.md +478 -0
- package/package.json +105 -0
- package/templates/_harness/CLAUDE.md.template +91 -0
- package/templates/_harness/PLAN.md.template +72 -0
- package/templates/_harness/check.py +442 -0
- package/templates/_harness/claude/settings.json +17 -0
- package/templates/_harness/gen-asm-header.py +96 -0
- package/templates/_harness/harness.mk +273 -0
- package/templates/_harness/hooks/plan-gate.py +185 -0
- package/templates/_harness/meter/frame_meter.asm +311 -0
- package/templates/_harness/meter/frame_meter.c +155 -0
- package/templates/_harness/meter/frame_meter.h +80 -0
- package/templates/_harness/zp-used.py +104 -0
- package/templates/action-puzzle/.claude/settings.json +17 -0
- package/templates/action-puzzle/.mcp.json +10 -0
- package/templates/action-puzzle/CLAUDE.md +120 -0
- package/templates/action-puzzle/Makefile +125 -0
- package/templates/action-puzzle/PLAN.md +388 -0
- package/templates/action-puzzle/README.md +240 -0
- package/templates/action-puzzle/expect.json +25 -0
- package/templates/action-puzzle/src/cave.c +280 -0
- package/templates/action-puzzle/src/cave.h +80 -0
- package/templates/action-puzzle/src/gen_autopilot.h +20 -0
- package/templates/action-puzzle/src/gen_caves.h +59 -0
- package/templates/action-puzzle/src/gen_notes.h +16 -0
- package/templates/action-puzzle/src/hiscore.c +152 -0
- package/templates/action-puzzle/src/hiscore.h +41 -0
- package/templates/action-puzzle/src/level.c +64 -0
- package/templates/action-puzzle/src/level.h +24 -0
- package/templates/action-puzzle/src/main.c +599 -0
- package/templates/action-puzzle/src/render.c +239 -0
- package/templates/action-puzzle/src/render.h +31 -0
- package/templates/action-puzzle/src/sound.c +158 -0
- package/templates/action-puzzle/src/sound.h +22 -0
- package/templates/action-puzzle/tools/disk_check.py +77 -0
- package/templates/action-puzzle/tools/drive.py +106 -0
- package/templates/action-puzzle/tools/gen.py +454 -0
- package/templates/action-puzzle/tools/model_check.py +49 -0
- package/templates/action-puzzle/tools/verdict_codes.py +24 -0
- package/templates/adventure/.claude/settings.json +17 -0
- package/templates/adventure/.mcp.json +10 -0
- package/templates/adventure/CLAUDE.md +118 -0
- package/templates/adventure/Makefile +113 -0
- package/templates/adventure/PLAN.md +396 -0
- package/templates/adventure/README.md +277 -0
- package/templates/adventure/expect.json +25 -0
- package/templates/adventure/src/engine.c +543 -0
- package/templates/adventure/src/engine.h +48 -0
- package/templates/adventure/src/gen_script.h +141 -0
- package/templates/adventure/src/gen_world.h +511 -0
- package/templates/adventure/src/main.c +439 -0
- package/templates/adventure/src/picture.c +83 -0
- package/templates/adventure/src/picture.h +16 -0
- package/templates/adventure/src/save.c +159 -0
- package/templates/adventure/src/save.h +25 -0
- package/templates/adventure/src/sound.c +71 -0
- package/templates/adventure/src/sound.h +16 -0
- package/templates/adventure/src/text.c +349 -0
- package/templates/adventure/src/text.h +40 -0
- package/templates/adventure/tools/disk_check.py +128 -0
- package/templates/adventure/tools/drive.py +119 -0
- package/templates/adventure/tools/gen.py +1033 -0
- package/templates/adventure/tools/world.py +356 -0
- package/templates/beat-em-up/.claude/settings.json +17 -0
- package/templates/beat-em-up/.mcp.json +10 -0
- package/templates/beat-em-up/CLAUDE.md +136 -0
- package/templates/beat-em-up/Makefile +96 -0
- package/templates/beat-em-up/PLAN.md +502 -0
- package/templates/beat-em-up/README.md +315 -0
- package/templates/beat-em-up/expect-gameover.json +8 -0
- package/templates/beat-em-up/expect.json +29 -0
- package/templates/beat-em-up/src/anim.c +70 -0
- package/templates/beat-em-up/src/art.c +344 -0
- package/templates/beat-em-up/src/autopilot.h +154 -0
- package/templates/beat-em-up/src/brute.c +273 -0
- package/templates/beat-em-up/src/enemy.c +281 -0
- package/templates/beat-em-up/src/engine.asm +512 -0
- package/templates/beat-em-up/src/fighter.c +384 -0
- package/templates/beat-em-up/src/game.h +269 -0
- package/templates/beat-em-up/src/hud.c +135 -0
- package/templates/beat-em-up/src/main.c +341 -0
- package/templates/beat-em-up/src/sound.c +44 -0
- package/templates/beat-em-up/src/street.c +93 -0
- package/templates/beat-em-up/src/verdict.h +523 -0
- package/templates/beat-em-up/src/view.c +362 -0
- package/templates/beat-em-up/tools/drive.py +105 -0
- package/templates/beat-em-up/tools/flickercheck.py +273 -0
- package/templates/demo/.claude/settings.json +17 -0
- package/templates/demo/.mcp.json +10 -0
- package/templates/demo/CLAUDE.md +129 -0
- package/templates/demo/Makefile +66 -0
- package/templates/demo/PLAN.md +401 -0
- package/templates/demo/README.md +322 -0
- package/templates/demo/expect.json +945 -0
- package/templates/demo/src/config.asm +80 -0
- package/templates/demo/src/framework.asm +390 -0
- package/templates/demo/src/main.asm +139 -0
- package/templates/demo/src/music.asm +197 -0
- package/templates/demo/src/part_main.asm +279 -0
- package/templates/demo/src/part_title.asm +79 -0
- package/templates/demo/src/parts.asm +43 -0
- package/templates/demo/src/tables.asm +73 -0
- package/templates/demo/src/verdict.asm +179 -0
- package/templates/demo/tools/audio.py +80 -0
- package/templates/demo/tools/gen_expect.py +167 -0
- package/templates/demo/tools/probe.py +95 -0
- package/templates/hello/.claude/settings.json +17 -0
- package/templates/hello/.mcp.json +10 -0
- package/templates/hello/CLAUDE.md +100 -0
- package/templates/hello/Makefile +38 -0
- package/templates/hello/PLAN.md +200 -0
- package/templates/hello/expect.json +20 -0
- package/templates/hello/src/main.c +161 -0
- package/templates/hello/src/sprite.asm +27 -0
- package/templates/hello-kick/.claude/settings.json +17 -0
- package/templates/hello-kick/.mcp.json +10 -0
- package/templates/hello-kick/CLAUDE.md +100 -0
- package/templates/hello-kick/Makefile +17 -0
- package/templates/hello-kick/PLAN.md +199 -0
- package/templates/hello-kick/expect.json +20 -0
- package/templates/hello-kick/src/main.asm +233 -0
- package/templates/platformer/.claude/settings.json +17 -0
- package/templates/platformer/.mcp.json +10 -0
- package/templates/platformer/CLAUDE.md +125 -0
- package/templates/platformer/Makefile +86 -0
- package/templates/platformer/PLAN.md +360 -0
- package/templates/platformer/README.md +277 -0
- package/templates/platformer/expect.json +32 -0
- package/templates/platformer/src/actors.c +289 -0
- package/templates/platformer/src/anim.c +51 -0
- package/templates/platformer/src/art.c +212 -0
- package/templates/platformer/src/autopilot.h +30 -0
- package/templates/platformer/src/engine.asm +253 -0
- package/templates/platformer/src/game.h +248 -0
- package/templates/platformer/src/hud.c +90 -0
- package/templates/platformer/src/level.c +184 -0
- package/templates/platformer/src/main.c +306 -0
- package/templates/platformer/src/player.c +268 -0
- package/templates/platformer/src/sound.c +42 -0
- package/templates/platformer/src/verdict.h +206 -0
- package/templates/platformer/src/view.c +331 -0
- package/templates/platformer/stage-expect.json +6 -0
- package/templates/platformer/tools/drive.py +112 -0
- package/templates/platformer/tools/tearcheck.py +229 -0
- package/templates/shmup-vertical/.claude/settings.json +17 -0
- package/templates/shmup-vertical/.mcp.json +10 -0
- package/templates/shmup-vertical/CLAUDE.md +137 -0
- package/templates/shmup-vertical/Makefile +131 -0
- package/templates/shmup-vertical/PLAN.md +569 -0
- package/templates/shmup-vertical/README.md +189 -0
- package/templates/shmup-vertical/expect.json +38 -0
- package/templates/shmup-vertical/src/bullets.c +158 -0
- package/templates/shmup-vertical/src/bullets.h +35 -0
- package/templates/shmup-vertical/src/display.c +239 -0
- package/templates/shmup-vertical/src/display.h +40 -0
- package/templates/shmup-vertical/src/game.h +85 -0
- package/templates/shmup-vertical/src/glyph.asm +358 -0
- package/templates/shmup-vertical/src/hiscore.c +141 -0
- package/templates/shmup-vertical/src/hiscore.h +16 -0
- package/templates/shmup-vertical/src/hit.asm +180 -0
- package/templates/shmup-vertical/src/hitbox.c +59 -0
- package/templates/shmup-vertical/src/hitbox.h +25 -0
- package/templates/shmup-vertical/src/kernel.asm +330 -0
- package/templates/shmup-vertical/src/level.c +174 -0
- package/templates/shmup-vertical/src/level.h +27 -0
- package/templates/shmup-vertical/src/main.c +824 -0
- package/templates/shmup-vertical/src/mux.asm +321 -0
- package/templates/shmup-vertical/src/sound.asm +255 -0
- package/templates/shmup-vertical/src/step.asm +169 -0
- package/templates/shmup-vertical/src/waves.c +195 -0
- package/templates/shmup-vertical/src/waves.h +33 -0
- package/templates/shmup-vertical/stage-expect.json +6 -0
- package/templates/shmup-vertical/tools/drive.py +152 -0
- package/templates/shmup-vertical/tools/joytest.py +159 -0
- package/templates/shmup-vertical/tools/meter.py +15 -0
- package/templates/shmup-vertical/tools/phases.py +73 -0
|
@@ -0,0 +1,892 @@
|
|
|
1
|
+
---
|
|
2
|
+
tool: oscar64
|
|
3
|
+
tool_kind: c-compiler
|
|
4
|
+
maintainer: drmortalwombat
|
|
5
|
+
license: GPL-3.0
|
|
6
|
+
home_url: https://github.com/drmortalwombat/oscar64
|
|
7
|
+
version_verified: "1.32.271"
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<!-- doc-type: toolchain-reference -->
|
|
11
|
+
|
|
12
|
+
# Oscar64 — C/C++ Cross-Compiler for 6502
|
|
13
|
+
|
|
14
|
+
## Tool
|
|
15
|
+
|
|
16
|
+
Oscar64 is an optimizing C/C++ cross-compiler that runs on a modern host (Windows, macOS, or Linux) and produces 6502 machine code targeting Commodore and other classic systems. It is the primary toolchain for c64-kb recipes. The compiler supports C99 with a large subset of C++ features including namespaces, templates, virtual functions, lambdas, and range-based for loops. Its headline achievement is native 6510 code that consistently outperforms code generated by cc65 in both speed and size, demonstrated by a Dhrystone score of 442 iterations per second on a stock C64 at -O3.
|
|
17
|
+
|
|
18
|
+
**Targets:** 6510
|
|
19
|
+
|
|
20
|
+
Oscar64 is designed around a full-program compilation model: the entire source tree is compiled in one pass, the linker is integrated, and only reachable code lands in the output. Library headers bring in their own implementations via `#pragma compile("lib.c")` directives, so there is no separate link step and no makefile required for most projects. The compiler includes a second data stack separate from the 6502 hardware stack, static call-graph analysis that converts the dynamic stack to a static layout wherever possible, zero-page register extension, and integer range analysis that narrows many 16-bit operations down to 8-bit operations. The result is code that is both compact and fast on an architecture that was originally considered a poor C target.
|
|
21
|
+
|
|
22
|
+
This knowledge base uses Oscar64 as its primary toolchain. Recipes and idioms are written for Oscar64 first. The cc65 patterns that LLM training data tends to suggest — POKE loops for sprites, manual IRQ vector swapping, raw $DC00 joystick reads — are antipatterns here. Reach for the Oscar64 header libraries instead.
|
|
23
|
+
|
|
24
|
+
## Quick reference
|
|
25
|
+
|
|
26
|
+
**Install (clone and build on Linux/macOS):**
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
git clone https://github.com/drmortalwombat/oscar64.git
|
|
30
|
+
cd oscar64
|
|
31
|
+
make -C make compiler # builds the oscar64 binary
|
|
32
|
+
sudo make -C make install # optional: installs to /usr/local/bin
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
A prebuilt Windows installer is available from the GitHub releases page. On Windows, the compiler is installed to `%programfiles(x86)%\oscar64\bin\oscar64`.
|
|
36
|
+
|
|
37
|
+
**Minimal invocation:**
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
oscar64 -n hello.c
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
This compiles `hello.c` to `hello.prg` with native code generation (the current default). The `-n` flag is shown explicitly here for clarity; it is equivalent to the default behavior as of recent releases.
|
|
44
|
+
|
|
45
|
+
**Common build command for a game or demo:**
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
oscar64 -n -O2 -tf=prg -o=game.prg main.c
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The output name is `-o=file`, flag and name joined by `=`. The space form `-o game.prg`, which an earlier version of this page showed, is rejected (`error 3004: Invalid command line argument '-o'`, then `game.prg` is opened as a source file; verified on build 2026-05-19).
|
|
52
|
+
|
|
53
|
+
**Expected outputs** for a typical build:
|
|
54
|
+
|
|
55
|
+
| File | When generated |
|
|
56
|
+
|------|---------------|
|
|
57
|
+
| `game.prg` | Always — the runnable C64 program |
|
|
58
|
+
| `game.map` | Always — memory layout report |
|
|
59
|
+
| `game.asm` | Always — assembler listing |
|
|
60
|
+
| `game.lbl` | Always — VICE monitor label commands |
|
|
61
|
+
| `game.int` | Always — intermediate-code listing |
|
|
62
|
+
| `game.dbj` | With `-g` — full JSON debug info |
|
|
63
|
+
| `game.csz` | With `-gp` — static profile data |
|
|
64
|
+
|
|
65
|
+
## Build pipeline
|
|
66
|
+
|
|
67
|
+
**Targets:** 6510
|
|
68
|
+
|
|
69
|
+
Oscar64 takes one or more `.c` or `.cpp` source files and produces a runnable artifact plus debug support files. The format is selected with `-tf=`.
|
|
70
|
+
|
|
71
|
+
### .PRG — Program file (executable)
|
|
72
|
+
|
|
73
|
+
**Produced by:** oscar64, kickassembler, cc65
|
|
74
|
+
|
|
75
|
+
The default output format. A `.prg` file starts with a two-byte load address header followed by the program body. For the `c64` target the load address is `$0801`, where the BASIC stub lives. The BASIC stub contains a single SYS line that jumps to the compiled entry point. In the default native build the `startup` region is `$0801`–`$0880` and `main` is `$0880`–`$A000` (Compiler.cpp region table; the compiler sets native code generation by default and only `-bc` clears it). The `$0801`–`$0900` startup, `$0900`–`$0A00` bytecode and `$0A00`–`$A000` main layout quoted by the upstream manual — and by an earlier version of this sentence — is what `-bc` produces. When checking a `.map`, its `regions` line prints `main` as `0880 - 9000` because the linker has already carved the 4 KB `stack` section (`$9000`–`$A000`) off the top of the declared region; the sections list shows `stack 9000 - a000`. Loading the file in VICE and typing `RUN` (or using autostart) launches the program.
|
|
76
|
+
|
|
77
|
+
**Consumed by:** vice, c1541
|
|
78
|
+
|
|
79
|
+
### .CRT — Cartridge image
|
|
80
|
+
|
|
81
|
+
**Produced by:** oscar64
|
|
82
|
+
|
|
83
|
+
Cartridge images are selected with `-tf=crt` (EasyFlash), `-tf=crt8` (generic 8 KB), or `-tf=crt16` (generic 16 KB). The EasyFlash format places the first 16 KB bank into RAM at startup and leaves remaining banks accessible for banked data. The 8 KB and 16 KB generic formats write code and data into the `rom` region at `$8000`–`$A000` or `$8000`–`$C000` with an autostart header. BSS, stack, and heap go into the `main` region from `$0800` to `$8000`.
|
|
84
|
+
|
|
85
|
+
**Consumed by:** vice
|
|
86
|
+
|
|
87
|
+
### .MAP — Linker map file
|
|
88
|
+
|
|
89
|
+
**Produced by:** oscar64
|
|
90
|
+
|
|
91
|
+
A text report of all memory regions, sections, and objects placed by the linker, sorted first by address and then by size. Essential for diagnosing programs that are too large: the "objects by size" section shows which functions and globals consume the most space. Generated unconditionally alongside every build.
|
|
92
|
+
|
|
93
|
+
### .ASM — Assembler listing
|
|
94
|
+
|
|
95
|
+
**Produced by:** oscar64
|
|
96
|
+
|
|
97
|
+
A human-readable listing of the generated bytecode and native 6502 assembly instructions. When `-g` is active, source file and line number annotations are interspersed. Use this to cross-reference when stopped at an address in the VICE machine code monitor.
|
|
98
|
+
|
|
99
|
+
### .LBL — VICE label file
|
|
100
|
+
|
|
101
|
+
**Produced by:** oscar64
|
|
102
|
+
|
|
103
|
+
Contains `al <addr> .<name>` monitor commands for every static symbol. Load into VICE with:
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
(monitor) ll game.lbl
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
or pass on the VICE command line as `-moncommands game.lbl`. After loading, the monitor, disassembly, and watch windows show symbolic names instead of raw addresses.
|
|
110
|
+
|
|
111
|
+
**Consumed by:** vice
|
|
112
|
+
|
|
113
|
+
### .DBJ — JSON debug info
|
|
114
|
+
|
|
115
|
+
**Produced by:** oscar64
|
|
116
|
+
|
|
117
|
+
Generated only when `-g` is passed. A structured JSON file with four top-level sections: `memory` (complete label map), `variables` (global/static variables with types and addresses), `functions` (per-function local variables, line numbers, and address ranges), and `types` (all declared types). Used by the Modern VICE PDB Monitor project for source-level debugging. The `-n -g -O0` combination produces the most debuggable output.
|
|
118
|
+
|
|
119
|
+
### .D64 — Commodore 1541 disk image
|
|
120
|
+
|
|
121
|
+
**Produced by:** oscar64
|
|
122
|
+
|
|
123
|
+
Created with the `-d64=output.d64` flag. The compiled `.prg` is placed as the first file in the directory. Additional resource files are added with `-f=file.bin` (raw) or `-fz=file.bin` (LZO-compressed). Disk overlays (code split across multiple `.prg` files in the image) are supported via the linker `#pragma overlay` mechanism.
|
|
124
|
+
|
|
125
|
+
**Consumed by:** vice, c1541
|
|
126
|
+
|
|
127
|
+
## CLI flags
|
|
128
|
+
|
|
129
|
+
The full invocation syntax is:
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
oscar64 {-i=path} [-o=output] [-rt=runtime.c] [-tf=format] [-tm=machine] [-e] [-n] [-dSYM[=val]] {source.c}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
| Flag | Description |
|
|
136
|
+
|------|-------------|
|
|
137
|
+
| `-v` / `-v2` | Verbose / very verbose diagnostic output |
|
|
138
|
+
| `-i=path` | Add an include search path |
|
|
139
|
+
| `-ii=path` | Set the default include path |
|
|
140
|
+
| `-o=file` | Output file name (defaults to source basename) |
|
|
141
|
+
| `-rt=file` | Alternative runtime library, replaces `crt.c`; use empty for no runtime |
|
|
142
|
+
| `-e` | Execute the result in the integrated emulator |
|
|
143
|
+
| `-ep` | Execute and profile in the integrated emulator |
|
|
144
|
+
| `-bc` | Compile all functions to bytecode |
|
|
145
|
+
| `-n` | Compile all functions to native 6502 code (current default) |
|
|
146
|
+
| `-dSYM[=val]` | Define a preprocessor symbol (no `=` between `-d` and the name: `-dNOFLOAT`, `-dNUM_IRQS=4`; `-d=SYM`, which an earlier version of this row showed, silently defines nothing useful) |
|
|
147
|
+
| `-D NAME=VALUE` | GCC-compatible symbol define |
|
|
148
|
+
| `-O0` | Disable optimizations |
|
|
149
|
+
| `-O1` / `-O` | Default optimizations |
|
|
150
|
+
| `-O2` | Aggressive speed optimizations including auto-inline of small functions |
|
|
151
|
+
| `-O3` | Maximum speed optimization |
|
|
152
|
+
| `-Os` | Optimize for size |
|
|
153
|
+
| `-Oi` | Auto-inline small functions (subset of -O2/-O3) |
|
|
154
|
+
| `-Oa` | Optimize inline assembler (subset of -O2/-O3) |
|
|
155
|
+
| `-Oz` | Auto-place global variables in zero page (subset of -O3) |
|
|
156
|
+
| `-Op` | Fold constant parameters into called functions |
|
|
157
|
+
| `-Oo` | Outliner: extract repeated code sequences into shared functions |
|
|
158
|
+
| `-Ox` | Optimize pointer arithmetic to prevent array page crossing |
|
|
159
|
+
| `-g` | Generate source-level debug info; annotate `.asm` with source lines |
|
|
160
|
+
| `-gp` | Like `-g` plus static profile data in `.csz` file |
|
|
161
|
+
| `-tf=format` | Target format: `prg` (default), `crt`, `crt8`, `crt16`, `bin` |
|
|
162
|
+
| `-tm=machine` | Target machine (see Target machines section) |
|
|
163
|
+
| `-d64=file.d64` | Create a D64 disk image |
|
|
164
|
+
| `-f=file` | Add a raw file to the D64 image |
|
|
165
|
+
| `-fz=file` | Add an LZO-compressed file to the D64 image |
|
|
166
|
+
| `-fi=n` | Sector skip for data files in the D64 image |
|
|
167
|
+
| `-xz` | Extended zero page usage; no return-to-BASIC |
|
|
168
|
+
| `-cid=n` | Cartridge type ID for VICE |
|
|
169
|
+
| `-csub=n` | Cartridge sub-type |
|
|
170
|
+
| `-cname=str` | Cartridge name |
|
|
171
|
+
| `-pp` | Compile in C++ mode |
|
|
172
|
+
| `-strict` | Strict ANSI C parsing (no C++ extensions) |
|
|
173
|
+
| `-psci` | PETSCII encoding for all strings without explicit prefix |
|
|
174
|
+
| `-rmp` | Generate `.error.map` and `.error.asm` when the linker fails |
|
|
175
|
+
|
|
176
|
+
**Runtime library defines** (passed with `-d`):
|
|
177
|
+
|
|
178
|
+
| Define | Effect |
|
|
179
|
+
|--------|--------|
|
|
180
|
+
| `NOLONG` | Exclude `long` support from `printf` |
|
|
181
|
+
| `NOFLOAT` | Exclude `float` support from `printf` |
|
|
182
|
+
| `HEAPCHECK` | Validate heap alloc/free; jam on error |
|
|
183
|
+
| `NOBSSCLEAR` | Skip clearing the BSS segment at startup |
|
|
184
|
+
| `NOZPCLEAR` | Skip clearing the zero-page BSS at startup |
|
|
185
|
+
|
|
186
|
+
These are the spellings `crt.c` tests (`#ifndef NOBSSCLEAR`, line 238; `#ifndef NOZPCLEAR`, line 262). An earlier version of this table gave `NOBSSCLR` and `NOZPCLR`; those compile cleanly and change nothing.
|
|
187
|
+
|
|
188
|
+
## Target machines
|
|
189
|
+
|
|
190
|
+
The `-tm=` flag selects the target. The default is `c64`.
|
|
191
|
+
|
|
192
|
+
| Machine | Memory range | Notes |
|
|
193
|
+
|---------|-------------|-------|
|
|
194
|
+
| `c64` | `$0800`–`$A000` | Stock Commodore 64, default target |
|
|
195
|
+
| `c128` | `$1C00`–`$FC00` | Commodore C128 full range |
|
|
196
|
+
| `c128b` | `$1C00`–`$4000` | C128 first 16 KB only |
|
|
197
|
+
| `c128e` | `$1C00`–`$C000` | C128 first 48 KB only |
|
|
198
|
+
| `plus4` | `$1000`–`$FC00` | Commodore PLUS/4 |
|
|
199
|
+
| `vic20` | `$1000`–`$1E00` | VIC-20, no expansion |
|
|
200
|
+
| `vic20+3` | `$0400`–`$1E00` | VIC-20, 3 KB expansion |
|
|
201
|
+
| `vic20+8` | `$1200`–`$4000` | VIC-20, 8 KB expansion |
|
|
202
|
+
| `vic20+16` | `$1200`–`$6000` | VIC-20, 16 KB expansion |
|
|
203
|
+
| `vic20+24` | `$1200`–`$8000` | VIC-20, 24 KB expansion |
|
|
204
|
+
| `pet` | `$0400`–`$2000` | PET 8 KB |
|
|
205
|
+
| `pet16` | `$0400`–`$4000` | PET 16 KB |
|
|
206
|
+
| `pet32` | `$0400`–`$8000` | PET 32 KB |
|
|
207
|
+
| `nes` | — | NES NROM 32 KB, no mirror |
|
|
208
|
+
| `nes_nrom_h` | — | NES NROM horizontal mirror |
|
|
209
|
+
| `nes_nrom_v` | — | NES NROM vertical mirror |
|
|
210
|
+
| `nes_mmc1` | — | NES MMC1 256 KB PRG, 128 KB CHR |
|
|
211
|
+
| `nes_mmc3` | — | NES MMC3 512 KB PRG, 256 KB CHR |
|
|
212
|
+
| `atari` | `$2000`–`$BC00` | Atari 8-bit |
|
|
213
|
+
| `x16` | `$0800`–`$9F00` | Commander X16 |
|
|
214
|
+
| `mega65` | `$2000`–`$C000` | Mega 65 |
|
|
215
|
+
|
|
216
|
+
**c64-kb scope note:** c64-kb covers stock C64 PAL and NTSC only. Recipes and idioms in this KB target `c64` exclusively. The other targets are listed here for completeness; they are out of scope for KB content.
|
|
217
|
+
|
|
218
|
+
## C extensions and language features
|
|
219
|
+
|
|
220
|
+
Oscar64 extends standard C/C++ with several features that are particularly useful for 6502 development.
|
|
221
|
+
|
|
222
|
+
### Pragmas
|
|
223
|
+
|
|
224
|
+
`#pragma warning(disable: 2000,2001)` suppresses specific warning codes. `#pragma message("text")` prints a message at compile time. `#pragma native(FuncName)` marks a function for native code generation even in bytecode mode. `#pragma optimize(option,...)` sets per-function optimizer options; valid options include `push`, `pop`, `asm`, `noasm`, `size`, `speed`, `noinline`, `inline`, `autoinline`, `maxinline`, `constparams`, `noconstparams`, `outline`, `nooutline`, and integer levels `0`–`3`.
|
|
225
|
+
|
|
226
|
+
Loop unrolling is controlled with `#pragma unroll(n)` or `#pragma unroll(full)` applied to the immediately following loop. A special `#pragma unroll(page)` mode reorganizes loop iterations into page-aligned chunks, which allows the 8-bit index registers to cover 256-byte strips efficiently — useful for filling the 1000-byte screen RAM without 16-bit indexing.
|
|
227
|
+
|
|
228
|
+
Placement pragmas control the linker: `#pragma region(name, start, end, flags, bank, {sections})` defines a physical memory region; `#pragma section(name, 0)` creates a logical section; `#pragma data(section)`, `#pragma code(section)`, and `#pragma bss(section)` redirect subsequent globals/functions into non-default sections. `#pragma align(symbol, power_of_two)` aligns a variable or function to a boundary. `#pragma stacksize(n)` and `#pragma heapsize(n)` set the reserved sizes for those sections.
|
|
229
|
+
|
|
230
|
+
### `__assume(cond)`
|
|
231
|
+
|
|
232
|
+
Provides the optimizer with facts it cannot deduce from the source. Common uses:
|
|
233
|
+
|
|
234
|
+
- `__assume(false)` in a switch default marks it as unreachable.
|
|
235
|
+
- `__assume(y < 25)` before a screen-index expression lets the compiler use 8-bit arithmetic for the `40 * y` multiply.
|
|
236
|
+
- `__assume(p != nullptr)` allows the compiler to omit null checks.
|
|
237
|
+
|
|
238
|
+
From `samples/games/lander.c`, which uses `__assume(y < 25)` before every screen access to prevent unnecessary 16-bit promotion.
|
|
239
|
+
|
|
240
|
+
### `__striped`
|
|
241
|
+
|
|
242
|
+
The 6502 has no multiply instruction and no indirect-plus-offset addressing mode. Accessing element `i` of a `struct S array[N]` requires multiplying `i` by `sizeof(S)`, which is expensive. The `__striped` storage qualifier reorders the array so all bytes of field `x` are contiguous, followed by all bytes of field `y`, and so on. The resulting layout — called structure of arrays (SoA) — allows direct index-register access:
|
|
243
|
+
|
|
244
|
+
```c
|
|
245
|
+
__striped struct Particle { int px, py; char color; } particles[64];
|
|
246
|
+
// particles[0].px, particles[1].px, ..., particles[63].px are contiguous
|
|
247
|
+
// compiler uses absolute+Y indexing, no multiply needed
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
The `auto` keyword from C++ enables typed pointers into striped arrays: `auto p = particles + i;` followed by `p->px` generates correct striped addressing. This feature is most effective when the array has no more than 256 elements.
|
|
251
|
+
|
|
252
|
+
### `__zeropage`
|
|
253
|
+
|
|
254
|
+
```c
|
|
255
|
+
__zeropage int counter;
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
Places a global variable into the zero-page BSS region. On the `c64` target that region is by default only `$F7`–`$FF` (nine bytes; measured in the `.map` of build 2026-05-19, and set in Compiler.cpp's region table), so a handful of `__zeropage` variables exhausts it. `-xz` widens it to `$80`–`$FF` at the cost of no return to BASIC. The upstream manual's phrase "usually 0x80 to 0xff" — which an earlier version of this sentence repeated — describes the `-xz` layout, not the default. Zero-page addressing saves one byte per instruction and runs slightly faster on the 6502. The default region sits in the KERNAL's RS-232 pointers (`$F7`–`$FA`) and the four free bytes `$FB`–`$FE`, so it is safe with the ROMs mapped; widening the region into BASIC's (`$03`–`$8F`) or the KERNAL's (`$90`–`$F6`) workspace is what collides. Zero-page globals are zero-cleared by the startup code (crt.c, `ZeroStart`..`ZeroEnd`) just like the ordinary BSS, unless built with `-dNOZPCLEAR`; an earlier version of this sentence said they were not initialised. An initializer on a `__zeropage` global is not honoured in memory: the storage is emitted as zero bytes and cleared at startup (the optimiser may constant-fold reads of a never-written initialised variable, which can mask this), so assign non-zero values in code.
|
|
259
|
+
|
|
260
|
+
### `__native` and `__noinline`
|
|
261
|
+
|
|
262
|
+
`__native void func(...)` forces native code generation for a single function regardless of whether `-bc` is active globally. `__noinline` prevents the optimizer from inlining the function even at `-O2`/`-O3`. `__forceinline` does the opposite: forces inlining even without the `inline` keyword.
|
|
263
|
+
|
|
264
|
+
### `__interrupt` and `__hwinterrupt`
|
|
265
|
+
|
|
266
|
+
```c
|
|
267
|
+
__hwinterrupt void raster_irq(void) {
|
|
268
|
+
vic.color_border++;
|
|
269
|
+
vic.intr_ctrl <<= 1;
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
`__interrupt` saves and restores all zero-page registers used by the function on entry and exit. `__hwinterrupt` additionally saves and restores A, X and Y (the generated prologue is `PHA / TXA / PHA / TYA / PHA`, the epilogue `PLA / TAY / PLA / TAX / PLA`) and exits with `RTI` instead of `RTS`; the processor status is not saved by generated code — the 6510 pushes it on interrupt entry and `RTI` restores it (an earlier version of this sentence listed it among the saved registers). Use `__hwinterrupt` for the top-level interrupt handler installed at `$FFFE`/`$FFFF`. Never read volatile hardware registers in a function called from both interrupt and non-interrupt context without `__interrupt` protection — the optimizer may cache the register value across the IRQ boundary.
|
|
274
|
+
|
|
275
|
+
### `#embed`
|
|
276
|
+
|
|
277
|
+
Imports binary file content directly into an array initializer:
|
|
278
|
+
|
|
279
|
+
```c
|
|
280
|
+
byte spritedata[] = {
|
|
281
|
+
#embed "../resources/sprites.bin"
|
|
282
|
+
};
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
`#embed` is a preprocessor directive and consumes the rest of its source line, so it must stand alone on its own line inside the initializer braces and the closing `};` must go on the following line; the one-line form `= { #embed "file" };`, which an earlier version of this page used in every example, loses the closing brace and fails with error 3006 / 3008 (verified with Oscar64 build 2026-05-19).
|
|
286
|
+
|
|
287
|
+
An optional limit and offset select a slice: `#embed 4096 128 "data.bin"` imports 4096 bytes starting at offset 128. In-line compression is available:
|
|
288
|
+
|
|
289
|
+
```c
|
|
290
|
+
char charset[] = {
|
|
291
|
+
#embed 2048 0 lzo "../resources/charset.bin"
|
|
292
|
+
};
|
|
293
|
+
// runtime: oscar_expand_lzo(CharsetDest, charset);
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Supported compression methods: `lzo` (LZ-based) and `rle` (run-length). The `word` specifier imports 16-bit words instead of bytes.
|
|
297
|
+
|
|
298
|
+
`#embed` also understands structured asset formats. `#embed ctm_chars "tiles.ctm"` extracts character data from a CharPad `.ctm` version 8 file; `#embed spd_sprites "sprites.spd"` extracts sprite data from a SpritePad `.spd` version 5 file. Tile variants (`ctm_tiles8`, `ctm_tiles16`, `ctm_map8`, `ctm_map16`) and attribute channels (`ctm_attr1`, `ctm_attr2`) are also supported.
|
|
299
|
+
|
|
300
|
+
### Console I/O and PETSCII
|
|
301
|
+
|
|
302
|
+
The C64 uses PETSCII rather than ASCII, and `CR` (13) as the line terminator instead of `LF` (10). Oscar64 handles translation via `iocharmap(IOCHM_PETSCII_2)` (switch to lowercase font and translate all subsequent I/O) or PETSCII string literals with the `p` prefix (`printf(p"Hello\n")`). Screen-code literals use the `s` or `S` prefix. The `-psci` compiler flag makes PETSCII the default encoding for all unadorned string literals. Per-character mapping can be customized with `#pragma charmap(index, code [, count])` — both are integer character codes (a `'a'` literal is refused with error 3031); `count` maps a run.
|
|
303
|
+
|
|
304
|
+
### Preprocessor extensions
|
|
305
|
+
|
|
306
|
+
Oscar64 adds three preprocessor directives beyond standard C:
|
|
307
|
+
|
|
308
|
+
```c
|
|
309
|
+
#assign ry 0 // assign a numeric value to a macro
|
|
310
|
+
#repeat // begin a preprocessor loop
|
|
311
|
+
...
|
|
312
|
+
#assign ry ry + 1
|
|
313
|
+
#until ry == 25 // end loop when condition is true
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
A shorthand for single-line expansion: `#for(i, COUNT) text_with_i` replicates `text_with_i` `COUNT` times with `i` substituted. These are useful for generating unrolled or table-driven code at compile time without adding runtime overhead.
|
|
317
|
+
|
|
318
|
+
## Memory layout and banking
|
|
319
|
+
|
|
320
|
+
The whole-program view (the constraints, one worked layout in all three toolchains, and confirming it from the map file) is `memory-layout-planning.md`, with the recipe `../recipes/oscar64/memory-layout.md`.
|
|
321
|
+
|
|
322
|
+
Oscar64's linker works with three levels: regions (physical memory areas), sections (logical groupings), and objects (functions and data items). The default layout for `c64`/`-tf=prg` on build 2026-05-19 with the default native code generation is:
|
|
323
|
+
|
|
324
|
+
```
|
|
325
|
+
$0801–$0880 startup — BASIC stub and crt entry
|
|
326
|
+
$0880–$A000 main — code, data, bss, heap, stack (the 4 KB stack is carved from the top, so the .map prints the region as 0880 - 9000 with stack at 9000 - A000)
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
There is no bytecode region and code begins at `$0880`. The vendor manual's `$0801–$0900 startup / $0900–$0A00 bytecode / $0A00–$A000 main` figures, which an earlier version of this table repeated, describe the layout selected when the bytecode interpreter is in use (`-bc`, or any non-native function); building the same file with `-bc` reproduces them exactly. The `#pragma region( main, 0x0a00, ... )` examples below still work in a native build, but starting at `0x0a00` leaves `$0880`–`$0A00` unused; use `0x0880` as the lower bound if you want it back. Verify against your own `.map`, since the split depends on the codegen mode.
|
|
330
|
+
|
|
331
|
+
To use memory up to `$D000` (displacing BASIC ROM but keeping I/O and KERNAL), include `<c64/memmap.h>` and add:
|
|
332
|
+
|
|
333
|
+
```c
|
|
334
|
+
#pragma region( main, 0x0a00, 0xd000, , , {code, data, bss, heap, stack} )
|
|
335
|
+
int main(void) { mmap_set(MMAP_NO_BASIC); ... }
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
To place a character set at a fixed address while splitting code around it:
|
|
339
|
+
|
|
340
|
+
```c
|
|
341
|
+
#pragma region( lower, 0x0a00, 0x2000, , , {code, data} )
|
|
342
|
+
#pragma section( charset, 0 )
|
|
343
|
+
#pragma region( charset, 0x2000, 0x2800, , , {charset} )
|
|
344
|
+
#pragma region( upper, 0x2800, 0xa000, , , {code, data, bss, heap, stack} )
|
|
345
|
+
|
|
346
|
+
#pragma data(charset)
|
|
347
|
+
char MyCharset[2048] = {
|
|
348
|
+
#embed "../resources/charset.bin"
|
|
349
|
+
};
|
|
350
|
+
#pragma data(data)
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
On the C64 target the stack defaults to 4 KB and the heap to a 1 KB minimum; the linker then grows the heap to fill all free space between the end of bss and the start of the stack (an earlier version of this sentence gave heap 4 KB, stack 1 KB; the `.map` shows `stack 9000 - a000` and the heap filling everything below it). `#pragma stacksize(n)` sets the stack reservation exactly; `#pragma heapsize(n)` sets the heap's minimum, and the linker reports "Cannot place heap section" if that minimum does not fit. Other targets use smaller defaults (512/512 on VIC-20 and 8 KB PET, 1 KB/1 KB on X16 and 16 KB+ VIC-20/PET, 256/256 on NES). Override with:
|
|
354
|
+
|
|
355
|
+
```c
|
|
356
|
+
#pragma stacksize(4096)
|
|
357
|
+
#pragma heapsize(8192)
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
Setting `heapsize` to zero eliminates the heap section entirely for programs that do not use `malloc`.
|
|
361
|
+
|
|
362
|
+
**Cartridge banking** uses up to 64 banks. Each bank gets its own section and region:
|
|
363
|
+
|
|
364
|
+
```c
|
|
365
|
+
#pragma section( bcode1, 0 )
|
|
366
|
+
#pragma region( bank1, 0x8000, 0xc000, , 1, { bcode1 } )
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
The `__bankof(symbol)` operator returns the bank ID of any function or constant placed in ROM. `__bankof(0)` returns the current bank. The `easyflash.h` header provides the `EFlashCall<fn>` template wrapper that switches banks before and after a call, and the `EF_CALL(fn)` macro that wraps it cleanly.
|
|
370
|
+
|
|
371
|
+
**Overlays** on D64 images work by associating a linker bank with a named overlay file:
|
|
372
|
+
|
|
373
|
+
```c
|
|
374
|
+
#pragma overlay( ovl1, 1 )
|
|
375
|
+
// at runtime:
|
|
376
|
+
krnio_setnam(P"OVL1");
|
|
377
|
+
krnio_load(1, 8, 1);
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
The overlay file is stored as a `.prg` entry in the D64 directory. Use `oscar_expand_lzo` from `oscar.h` to decompress inlays at runtime.
|
|
381
|
+
|
|
382
|
+
## Multi-file projects
|
|
383
|
+
|
|
384
|
+
There are no object files and no separate link step. Every source file is
|
|
385
|
+
compiled in one run and the linker inside the compiler keeps only what is
|
|
386
|
+
reachable from `main`. The manual (`oscar64.md`, "Using libraries") says it
|
|
387
|
+
in one sentence: "Source files are added to the build with the help of a
|
|
388
|
+
pragma: `#pragma compile("stdio.c")`". A second unit reaches the build in
|
|
389
|
+
one of two ways, measured on build 2026-05-19 with the three files below;
|
|
390
|
+
both ways produced a byte-identical 140-byte `out.prg`, which turned the
|
|
391
|
+
border and screen green in VICE x64sc 3.10.
|
|
392
|
+
|
|
393
|
+
**The header pulls in its own `.c`.** This is how every shipped library
|
|
394
|
+
works: `include/c64/vic.h` ends with `#pragma compile("vic.c")`,
|
|
395
|
+
`include/c64/sprites.h` with `#pragma compile("sprites.c")`, and the file
|
|
396
|
+
named is found next to the header, not in the current directory (with `-v`
|
|
397
|
+
the build prints `Compiling ".../include/c64/vic.c"` from any working
|
|
398
|
+
directory). Do the same for your own module:
|
|
399
|
+
|
|
400
|
+
```text
|
|
401
|
+
/* border.h */
|
|
402
|
+
#ifndef BORDER_H
|
|
403
|
+
#define BORDER_H
|
|
404
|
+
extern char border_calls;
|
|
405
|
+
void border_set(char colour);
|
|
406
|
+
#pragma compile("border.c")
|
|
407
|
+
#endif
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
```text
|
|
411
|
+
/* border.c */
|
|
412
|
+
#include "border.h"
|
|
413
|
+
#include <c64/vic.h>
|
|
414
|
+
char border_calls;
|
|
415
|
+
void border_set(char colour)
|
|
416
|
+
{
|
|
417
|
+
vic.color_border = colour;
|
|
418
|
+
vic.color_back = colour;
|
|
419
|
+
border_calls++;
|
|
420
|
+
}
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
```text
|
|
424
|
+
/* main.c */
|
|
425
|
+
#include "border.h"
|
|
426
|
+
int main(void)
|
|
427
|
+
{
|
|
428
|
+
border_set(5);
|
|
429
|
+
for (;;) ;
|
|
430
|
+
return border_calls;
|
|
431
|
+
}
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
```
|
|
435
|
+
oscar64 -tm=c64 -O2 -o=out.prg main.c
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
**Or name every unit on the command line.** The manual's "A list of source
|
|
439
|
+
files can be provided" is literal: `oscar64 -tm=c64 -O2 -o=out.prg main.c
|
|
440
|
+
border.c` builds the same program with the pragma line deleted from
|
|
441
|
+
`border.h`. Use this when a module must not know it is a module (a file
|
|
442
|
+
shared with another compiler), or to swap implementations per build. The
|
|
443
|
+
header form is the one to prefer, because a unit that is only reachable
|
|
444
|
+
through the command line is silently missing from any build that forgets
|
|
445
|
+
it, which is the failing form:
|
|
446
|
+
|
|
447
|
+
```text
|
|
448
|
+
border.h(5, 6) : error 3022: Calling undefined function 'border_set(u8)->void'
|
|
449
|
+
border.h(5, 6) : error 3022: Calling undefined function 'border_set(u8)->void'
|
|
450
|
+
main.c(5, 5) : info 1003: Called from here
|
|
451
|
+
border.h(5, 6) : error 3022: Calling undefined function 'border_set(u8)->void'
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
That is `oscar64 -tm=c64 -O2 -o=out.prg main.c` with the files exactly as
|
|
455
|
+
shown above, the `#pragma compile` line deleted from the header and
|
|
456
|
+
`border.c` not on the command line. The positions are the declaration on
|
|
457
|
+
line 5 of `border.h` and the call on line 5 of `main.c`. The compiler exits
|
|
458
|
+
20 and writes no PRG.
|
|
459
|
+
|
|
460
|
+
**`extern` across units** works as in any C: declare in the header, define
|
|
461
|
+
once in the `.c`; `border_calls` above is defined in `border.c`, written
|
|
462
|
+
there and readable from `main.c`. Two things differ from a linker you know. A `#define` in
|
|
463
|
+
one unit does not reach another, so a library table size such as `NUM_IRQS`
|
|
464
|
+
has to be passed as `-dNUM_IRQS=17` on the command line (see Pitfalls). And
|
|
465
|
+
an `extern` variable that is never defined anywhere is not an error: the
|
|
466
|
+
build exits 0 and the linker allocates it in `bss` (measured;
|
|
467
|
+
`error-sources/oscar64/undefined-extern-var.c` builds, and its `.map` shows
|
|
468
|
+
`088b - 088c : missing_var, DATA:bss`). Only an undefined function is
|
|
469
|
+
refused.
|
|
470
|
+
|
|
471
|
+
**What the build reports.** `-n` selects native code and is already the
|
|
472
|
+
default (see CLI flags), so it shows nothing new. `-v` is the flag that
|
|
473
|
+
shows the units: it prints one `Compiling "..."` line per source file and one
|
|
474
|
+
`Including "..."` line per header, in the order the pragmas and includes
|
|
475
|
+
pulled them in, so a missing unit is visible as a missing line. The `.map`
|
|
476
|
+
written next to the PRG lists sections, regions and objects. Objects are
|
|
477
|
+
functions and variables, not files: after this build its `objects` block has
|
|
478
|
+
`main` (`0880 - 088a : main, NATIVE_CODE:code`), the startup code and the
|
|
479
|
+
section markers, and neither `border_set` nor `border_calls`: at `-O2` the
|
|
480
|
+
call was inlined into `main`, and because nothing after the `for (;;)` can
|
|
481
|
+
read `border_calls`, the increment and the variable were removed with it
|
|
482
|
+
(`bss` is empty, `BSSStart` and `BSSEnd` both at `088b`). A variant of
|
|
483
|
+
`main.c` that spun on `while (border_calls) ;` kept it, at
|
|
484
|
+
`0899 - 089a : border_calls, DATA:bss`. A function or variable you expect
|
|
485
|
+
to see and do not is usually inlined, or unreferenced and dropped (see
|
|
486
|
+
Pitfalls, "Data nobody references is dropped"), not missing from the build.
|
|
487
|
+
|
|
488
|
+
## Header library overview
|
|
489
|
+
|
|
490
|
+
Oscar64 ships a suite of C64-specific headers in `include/c64/`. Including any of these headers automatically adds the corresponding `.c` implementation to the build via `#pragma compile`. No makefile or explicit library link step is needed.
|
|
491
|
+
|
|
492
|
+
Full per-header documentation: [oscar64-headers-reference.md](oscar64-headers-reference.md)
|
|
493
|
+
|
|
494
|
+
Headers in `include/c64/`:
|
|
495
|
+
|
|
496
|
+
- `types.h` — `byte`, `word`, `dword`, `sbyte` typedefs
|
|
497
|
+
- `vic.h` — VIC-II struct, color enum, bank/mode helpers, raster wait functions
|
|
498
|
+
- `sid.h` — SID struct, note macros, frequency scale constants
|
|
499
|
+
- `cia.h` — CIA1/CIA2 struct, `cia_init()` to disable timer interrupts
|
|
500
|
+
- `memmap.h` — `mmap_set()`, `mmap_trampoline()`, memory map constants
|
|
501
|
+
- `rasterirq.h` — Raster IRQ system: `rirq_init`, `rirq_build`, `rirq_set`, `rirq_sort`
|
|
502
|
+
- `sprites.h` — Hardware sprite control (`spr_*`) and 16-sprite multiplexer (`vspr_*`)
|
|
503
|
+
- `joystick.h` — `joy_poll()`, `joyx[]`, `joyy[]`, `joyb[]` poll results
|
|
504
|
+
- `keyboard.h` — `keyb_poll()`, scan-code enum, `key_pressed()`
|
|
505
|
+
- `charwin.h` — Character-mode windowed text rendering (`cwin_*`)
|
|
506
|
+
- `mouse.h` — `mouse_poll()`, `mouse_dx/dy`, `mouse_lb/rb`
|
|
507
|
+
- `kernalio.h` — KERNAL file I/O wrappers (`krnio_open`, `krnio_read`, `krnio_write`, etc.)
|
|
508
|
+
- `iecbus.h` — Low-level IEC serial bus access
|
|
509
|
+
- `easyflash.h` — EasyFlash bank register, `EFlashCall<>` template
|
|
510
|
+
- `reu.h` — RAM Expansion Unit struct and DMA helpers (`reu_store`, `reu_load`)
|
|
511
|
+
- `asm6502.h` — Runtime 6502 code emitter (generates machine instructions into a buffer)
|
|
512
|
+
|
|
513
|
+
## Debugging
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
Reaching the monitor prompt headless, the register line, breakpoints, watchpoints and measuring cycles between two points are in `../runtime/vice-reference.md`, "Text monitor for debugging".
|
|
517
|
+
Oscar64 produces two debug-support files on every build. The `.lbl` file contains `al` commands for the VICE monitor; loading it with `ll game.lbl` or `-moncommands game.lbl` makes the disassembler show symbolic names. The `.asm` file is the annotated assembler listing; with `-g`, each native instruction is preceded by the source file and line number that generated it.
|
|
518
|
+
|
|
519
|
+
For deeper source-level debugging, compile with `-n -g -O0`:
|
|
520
|
+
|
|
521
|
+
```bash
|
|
522
|
+
oscar64 -n -g -O0 -o=game.prg main.c
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
This produces a `.dbj` JSON file alongside the `.lbl`. The Modern VICE PDB Monitor (https://github.com/MihaMarkic/modern-vice-pdb-monitor) consumes `.dbj` for breakpoints, variable inspection, and step-through at the C source level.
|
|
526
|
+
|
|
527
|
+
The `-gp` variant adds a `.csz` file with every source line annotated with its byte count in the output — useful for finding where code size is going.
|
|
528
|
+
|
|
529
|
+
**vice-mcp integration:** The [vice-mcp](../runtime/vice-mcp-reference.md) bridge exposes VICE's binary monitor over MCP. After loading labels, an agent can read memory by symbol name, set breakpoints at C function boundaries, and capture raster screenshots. This is the runtime inspection complement to Oscar64's static outputs.
|
|
530
|
+
|
|
531
|
+
## Idioms — Oscar64 vs cc65
|
|
532
|
+
|
|
533
|
+
This section is the bias-enforcement core of this document. LLM training data is dominated by cc65 examples; Oscar64 idioms are underrepresented. For every pattern below, prefer the Oscar64 approach.
|
|
534
|
+
|
|
535
|
+
### Sprite setup: sprites.h vs POKE loops
|
|
536
|
+
|
|
537
|
+
**Oscar64 — correct:**
|
|
538
|
+
|
|
539
|
+
```c
|
|
540
|
+
#include <c64/sprites.h>
|
|
541
|
+
spr_init((char *)0x0400); // pass screen RAM address
|
|
542
|
+
spr_set(0, true, 160, 100, 1, VCOL_WHITE, false, false, false);
|
|
543
|
+
// sp=0, visible, x=160, y=100, image block=1, color, no multicolor, no expand
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
**cc65 antipattern — avoid:**
|
|
547
|
+
|
|
548
|
+
```c
|
|
549
|
+
// raw POKE to VIC registers -- fragile, verbose, no type safety
|
|
550
|
+
POKE(0xD015, PEEK(0xD015) | 0x01); // enable sprite 0
|
|
551
|
+
POKE(0xD000, 160); // x pos low
|
|
552
|
+
POKE(0xD001, 100); // y pos
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
The `sprites.h` functions handle the MSB of the X coordinate transparently, manage the enable bitmask, and work together with the `vspr_*` multiplexer. Direct VIC register POKEs scatter the logic across the codebase and break when the screen address changes.
|
|
556
|
+
|
|
557
|
+
### Raster IRQs: rasterirq.h vs hand IRQ swapping
|
|
558
|
+
|
|
559
|
+
**Oscar64 — correct:**
|
|
560
|
+
|
|
561
|
+
```c
|
|
562
|
+
#include <c64/vic.h> // vic and VCOL_* live here; rasterirq.h does not pull it in
|
|
563
|
+
#include <c64/rasterirq.h>
|
|
564
|
+
|
|
565
|
+
RIRQCode colorBar;
|
|
566
|
+
|
|
567
|
+
void setup(void) {
|
|
568
|
+
rirq_build(&colorBar, 1);
|
|
569
|
+
rirq_write(&colorBar, 0, &vic.color_back, VCOL_RED);
|
|
570
|
+
rirq_set(0, 80, &colorBar); // fires one line below raster 80
|
|
571
|
+
rirq_init(true); // use kernal IRQ vector
|
|
572
|
+
rirq_start();
|
|
573
|
+
}
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
**cc65 antipattern — avoid:**
|
|
577
|
+
|
|
578
|
+
```c
|
|
579
|
+
// Manual CIA disable + vector swap + SEI/CLI + RTI stub
|
|
580
|
+
*(unsigned char *)0xDC0D = 0x7F; // disable CIA timer
|
|
581
|
+
*(unsigned char *)0xD01A = 0x01; // enable raster IRQ
|
|
582
|
+
*(void **)0x0314 = my_irq; // kernal IRQ vector
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
The `rasterirq.h` system handles CIA disable, vector installation, slot sorting, and line-accurate entry in optimized assembly (every RIRQCode built by `rirq_build` begins with a `CMP $D012 / BCS` spin that lands the first write early in the target line, with up to six cycles of residual jitter — line-stable, not cycle-exact, which an earlier version of this sentence called "stable-IRQ timing"; for $D016/$D018 splits use the double-IRQ method in `recipes/kickassembler/stable-raster-irq.md`). The hand-rolled approach is error-prone on PAL vs NTSC and does not compose for multi-split effects.
|
|
586
|
+
|
|
587
|
+
### SID playback: sid.h helpers vs raw frequency writes
|
|
588
|
+
|
|
589
|
+
**Oscar64 — correct:**
|
|
590
|
+
|
|
591
|
+
```c
|
|
592
|
+
#include <c64/sid.h>
|
|
593
|
+
|
|
594
|
+
// Play middle A (440 Hz) on voice 0, square wave
|
|
595
|
+
sid.voices[0].freq = SID_FREQ_PAL(440);
|
|
596
|
+
sid.voices[0].pwm = 0x0800;
|
|
597
|
+
sid.voices[0].ctrl = SID_CTRL_RECT | SID_CTRL_GATE;
|
|
598
|
+
sid.voices[0].attdec = SID_ATK_2 | SID_DKY_6;
|
|
599
|
+
sid.voices[0].susrel = 0xF0;
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
**cc65 antipattern — avoid:**
|
|
603
|
+
|
|
604
|
+
```c
|
|
605
|
+
// Magic numbers with no semantic meaning
|
|
606
|
+
POKE(54272, 177); // voice 1 freq lo — what frequency is this?
|
|
607
|
+
POKE(54273, 28); // voice 1 freq hi
|
|
608
|
+
POKE(54276, 0x11); // gate + triangle
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
`SID_FREQ_PAL(hz)` and `SID_FREQ_NTSC(hz)` compute the correct 16-bit frequency register value for the given Hz. The named constants (`SID_ATK_*`, `SID_DKY_*`, `SID_CTRL_*`) make envelopes and waveforms self-documenting. The struct layout maps directly to the hardware registers at `$D400`; the compiler emits the same single-byte store that a POKE would, with no overhead.
|
|
612
|
+
|
|
613
|
+
### Joystick input: joystick.h vs direct $DC00 read
|
|
614
|
+
|
|
615
|
+
**Oscar64 — correct:**
|
|
616
|
+
|
|
617
|
+
```c
|
|
618
|
+
#include <c64/joystick.h>
|
|
619
|
+
|
|
620
|
+
joy_poll(0); // poll $DC00 = physical joystick port 2 (standard single-player port)
|
|
621
|
+
if (joyb[0]) { /* fire button */ }
|
|
622
|
+
if (joyy[0] < 0) { /* up */ }
|
|
623
|
+
if (joyx[0] > 0) { /* right */ }
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
Port mapping (verified against `include/c64/joystick.c`): `joy_poll(0)` reads `$DC00` = port 2, `joy_poll(1)` reads `$DC01` = port 1.
|
|
627
|
+
|
|
628
|
+
**cc65 antipattern — avoid:**
|
|
629
|
+
|
|
630
|
+
```c
|
|
631
|
+
// Direct CIA read with manual bit manipulation
|
|
632
|
+
char joy = ~PEEK(0xDC00);
|
|
633
|
+
if (joy & 0x10) { /* fire */ }
|
|
634
|
+
if (joy & 0x01) { /* up */ }
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
`joy_poll` reads the CIA port, inverts the active-low logic, and deposits signed delta values into `joyx[]`/`joyy[]` and a boolean into `joyb[]`. The signed-delta interface composes naturally with movement code. The CIA register approach requires knowing which port maps to which player and the active-low polarity.
|
|
638
|
+
|
|
639
|
+
**Pitfall:** `$DC00` is shared with the keyboard column drive. With the KERNAL IRQ scanning the keyboard 50/60 Hz, `joy_poll(0)` can read all-pressed phantom input if it samples mid-scan. Fix: `sei`/`cli` around the poll, or use keyboard input via `getchx()`/`keyb_poll()`. See `pitfalls/input.md`.
|
|
640
|
+
|
|
641
|
+
### Packed bitfields and structs: first-class in Oscar64
|
|
642
|
+
|
|
643
|
+
Oscar64 treats packed bitfield structs as native C. The compiler emits efficient read-modify-write sequences:
|
|
644
|
+
|
|
645
|
+
```c
|
|
646
|
+
struct VICFlags {
|
|
647
|
+
unsigned raster_msb : 1;
|
|
648
|
+
unsigned den : 1;
|
|
649
|
+
unsigned bmm : 1;
|
|
650
|
+
unsigned ecm : 1;
|
|
651
|
+
unsigned scroll_y : 3;
|
|
652
|
+
};
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
No need for explicit mask-and-shift macros. The optimizer recognizes that bit-field stores to volatile hardware registers must not be merged.
|
|
656
|
+
|
|
657
|
+
### printf is real
|
|
658
|
+
|
|
659
|
+
Oscar64 provides a working `printf` that calls `CHROUT` internally. It supports `%d`, `%u`, `%x`, `%s`, `%c`, and floating-point with `%f`/`%e`. Long and float support can be stripped with `-dNOLONG` and `-dNOFLOAT` to save code space. The PETSCII translation mode must be set for correct output on the C64 display:
|
|
660
|
+
|
|
661
|
+
```c
|
|
662
|
+
#include <stdio.h>
|
|
663
|
+
#include <conio.h> // iocharmap() and IOCHM_* live here, not in stdio.h
|
|
664
|
+
iocharmap(IOCHM_PETSCII_2);
|
|
665
|
+
printf("Score: %d\n", score);
|
|
666
|
+
```
|
|
667
|
+
|
|
668
|
+
There is no reason to write your own CHROUT loop.
|
|
669
|
+
|
|
670
|
+
### `__striped` arrays for tile maps and particle systems
|
|
671
|
+
|
|
672
|
+
When storing a tile map or particle array where each element has multiple byte fields, the `__striped` qualifier allows the compiler to use the 8-bit Y index register directly:
|
|
673
|
+
|
|
674
|
+
```c
|
|
675
|
+
__striped struct Tile {
|
|
676
|
+
char screen_code;
|
|
677
|
+
char color;
|
|
678
|
+
char flags;
|
|
679
|
+
} tilemap[256];
|
|
680
|
+
|
|
681
|
+
// tilemap[i].screen_code compiles to: LDA screen_code_base, Y
|
|
682
|
+
// tilemap[i].color compiles to: LDA color_base, Y
|
|
683
|
+
// No multiply, no 16-bit indexing
|
|
684
|
+
```
|
|
685
|
+
|
|
686
|
+
This pattern is the idiomatic way to handle per-sprite or per-tile parallel arrays in Oscar64. In cc65, programmers typically declare separate `sprite_x[]`, `sprite_y[]`, `sprite_color[]` arrays manually to achieve the same layout. In Oscar64, `__striped` formalizes that pattern in the type system.
|
|
687
|
+
|
|
688
|
+
### `#embed` for binary data
|
|
689
|
+
|
|
690
|
+
Avoid runtime file loading for assets that ship with the program. Use `#embed` to bake them into the `.prg` at compile time:
|
|
691
|
+
|
|
692
|
+
```c
|
|
693
|
+
const char charset_lzo[] = {
|
|
694
|
+
#embed lzo "../gfx/charset.bin"
|
|
695
|
+
};
|
|
696
|
+
// at startup:
|
|
697
|
+
oscar_expand_lzo((char *)0xD000, charset_lzo);
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
The cc65 idiom of `#incbin` in an assembler stub achieves the same result but requires a separate `.s` file and a `SEGMENTS` declaration in the config file. Oscar64's `#embed` works directly in C.
|
|
701
|
+
|
|
702
|
+
## Asm interop with KickAssembler
|
|
703
|
+
|
|
704
|
+
Oscar64 and KickAssembler address different needs. Use Oscar64 for game logic, asset handling, and most rendering. Reach for inline assembly or KickAssembler for cycle-critical routines where you need to count every cycle: stable-raster IRQ entry, sprite-multiplex sort loops, and hardware register sequences that must hit specific cycle offsets.
|
|
705
|
+
|
|
706
|
+
### Inline assembly
|
|
707
|
+
|
|
708
|
+
The `__asm { }` block embeds 6502 instructions directly inside any function:
|
|
709
|
+
|
|
710
|
+
```c
|
|
711
|
+
void fast_copy(const char * src, char * dst, char count) {
|
|
712
|
+
__asm {
|
|
713
|
+
ldx count
|
|
714
|
+
ldy #0 // the compiler emits no ldy; without it the copy starts at whatever Y holds
|
|
715
|
+
loop:
|
|
716
|
+
lda (src),y // src is a zero-page pointer pair
|
|
717
|
+
sta (dst),y
|
|
718
|
+
iny
|
|
719
|
+
dex
|
|
720
|
+
bne loop
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
```
|
|
724
|
+
|
|
725
|
+
Local variables and parameters are accessed by name inside `__asm` blocks; the compiler maps them to their zero-page register pairs automatically. Global variables use absolute addressing. Return values go into the `ACCU` zero-page location. Struct member offsets use the `Type::Member` syntax: `ldy #Point::y`. Labels are defined with a colon suffix; they are scoped to the function.
|
|
726
|
+
|
|
727
|
+
The assembler optimizer runs on inline assembly at `-O2` and above. To suppress it for timing-sensitive code: `__asm volatile { ... }` or `#pragma optimize(noasm)` around the block.
|
|
728
|
+
|
|
729
|
+
### Calling KickAssembler code from Oscar64
|
|
730
|
+
|
|
731
|
+
Oscar64 has no object linker and no external-symbol resolution (measured on build 2026-05-19): `extern "C"` is a parse error (`error 3006: Declaration starts with invalid token 'string literal'`), a call to a declared function with no body is `error 3022: Calling undefined function`, and a `.prg` given on the command line is accepted and silently ignored — the output is byte-identical to the build without it. An earlier version of this page described an extern/link workflow; it never worked. To use hand-written assembly either write it as an `__asm { }` block, or assemble it with KickAssembler at a fixed address (`* = $C000`), embed the bytes past the two-byte load address into a placed, exported array, and JSR to the address from inline assembly (a `const` function pointer to a literal address crashes the compiler, see Pitfalls):
|
|
732
|
+
|
|
733
|
+
```c
|
|
734
|
+
#pragma section( asmcode, 0 )
|
|
735
|
+
#pragma region( asmreg, 0xc000, 0xc100, , , { asmcode } )
|
|
736
|
+
#pragma data( asmcode )
|
|
737
|
+
__export const char scroller_code[] = {
|
|
738
|
+
#embed 256 2 "scroller.prg"
|
|
739
|
+
};
|
|
740
|
+
#pragma data( data )
|
|
741
|
+
// ...
|
|
742
|
+
__asm { jsr $c000 }
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
Put `#embed` on its own line: the directive consumes the rest of the line, so the one-line `{ #embed "f" };` form loses the closing brace and fails with `error 3006` on this build.
|
|
746
|
+
|
|
747
|
+
Any arguments must be passed through zero-page locations or globals the assembly side knows about; the Oscar64 parameter registers are not a stable interface. If the assembly does read the compiler's slots, it must observe the Oscar64 calling convention. For functions the compiler classifies as leaf calls, parameters are passed in the zero-page block from `$0D` upward (`P0` = `$0D/$0E`, `P2` = `$0F/$10`, `P4` = `$11/$12`, …; each parameter takes as many bytes as its type, so a `char` occupies one slot and a pointer two). `$02` is the compiler's Y-register spill byte, not an argument register — an earlier version of this page said the first argument lived at `$02`/`$03` (vendor manual, "Zero page usage" table; `BC_REG_FPARAMS = 0x0d` in the compiler source). Slot assignment is decided per function by the global analyzer — parameters that constant-fold away free their slots — and non-leaf or recursive functions receive arguments on the software stack instead, so always read the generated `.asm` listing for the exact slots of the function you are replacing. A concrete example: for `void unrolled_scroller(char *screen, char scroll_x)` the listing gives `screen` at `$0D/$0E` and `scroll_x` at `$0F`.
|
|
748
|
+
|
|
749
|
+
## Pitfalls
|
|
750
|
+
|
|
751
|
+
**Always set `-tf=`** when targeting anything other than `.prg`. Omitting `-tf=crt` when building for EasyFlash produces a `.prg` with the BASIC stub still present — it will crash when the cartridge reset vector fires.
|
|
752
|
+
|
|
753
|
+
**`__zeropage` lifetime.** `__zeropage` variables go to the linker's `zeropage` region, which on the `c64` target defaults to `$F7`–`$FE` (Compiler.cpp: `AddRegion(zeropage, 0x00f7, 0x00ff)`; read your `.map`). That is the KERNAL's RS-232 buffer pointers (`$F7`–`$FA`, only live if device 2 is opened) plus the four free bytes `$FB`–`$FE`, so with the ROMs mapped and no RS-232 in use they are safe by default. What causes crashes is widening the region — `-xz` moves it to `$80`–`$FE` (upstream: "no return to basic"), and `#pragma region(zeropage, ...)` into `$03`–`$8F` (BASIC's workspace) or `$90`–`$F6` (KERNAL's). They ARE zero-filled at startup by crt.c on every entry through the startup code, including a second `RUN` after `STOP`/`RESTORE`, unless you build with `-dNOZPCLEAR` (`-dNOBSSCLEAR` covers the main BSS; the spellings `NOBSSCLR`/`NOZPCLR` are not recognised and silently do nothing). "Not initialized" means only that an initializer such as `__zeropage char z = 0x55;` is silently ignored — the byte still starts at 0. An earlier version of this pitfall said the default region was `$02`–`$61`, that the variables were never cleared and that the flag was `NOBSSCLR`; all three were wrong.
|
|
754
|
+
|
|
755
|
+
**Banked-RAM context.** When accessing data in an EasyFlash bank, the `eflash.bank` write must not be reordered relative to subsequent reads from that bank. The `__memmap` qualifier on the bank register (already present in the `EasyFlash` struct definition) provides the necessary memory fence. Do not cast the bank register to plain `volatile byte *` — that loses the fence semantics.
|
|
756
|
+
|
|
757
|
+
**Register stomping in `__interrupt`.** An `__interrupt`/`__hwinterrupt` function saves and restores the zero-page registers used by itself *and* by every function it reaches through direct calls: the compiler walks the static call graph, adding each callee's zero-page set and a fixed ACCU/WORK set for each runtime routine (measured: a handler calling a plain function that multiplies saves that function's WORK `$03`–`$06` and ACCU `$1B`–`$1E`). An earlier version of this pitfall said callees were unprotected; they are not. Calls it cannot follow are rejected, not left unprotected — a call through a function pointer fails with error 3035 `No recursive functions in interrupt`, and `printf` or anything else needing a stack frame fails with error 3035 `Function to complex for interrupt`. The hole that does exist is the runtime scratch byte `__tmpy` at `$02`: runtime routines such as `mul16by8` use it, it is not in the saved set, and a handler that multiplies (directly or via a callee) corrupts a multiply the main code was in the middle of — measured 1,706 wrong products in 30,000 with a multiplying IRQ handler, 0 with a control handler whose multiply skips `$02`. Avoid multiplication, division and other runtime-routine arithmetic inside interrupt handlers, or save `$02` yourself around the call.
|
|
758
|
+
|
|
759
|
+
**Avoid recursion and function pointers.** The compiler's static call graph analysis — which eliminates the need for a runtime software stack — fails in the presence of recursion or indirect calls through function pointers. Recursive functions and indirect calls force the compiler to allocate stack frames dynamically, which is expensive on the 6502. Use switch statements instead of vtable-style function-pointer dispatch, and convert recursive algorithms to iterative form.
|
|
760
|
+
|
|
761
|
+
**Prefer `unsigned` and 8-bit types.** Signed arithmetic (signed shifts, signed compares, signed multiply) generates more code than unsigned equivalents. The compiler narrows 16-bit operations to 8-bit when it can prove the range fits, but it cannot do so through global variables or pointer-accessed values without help. Add `__assume(x < 256)` where you know the range, and declare loop counters as `char` or `byte` rather than `int`.
|
|
762
|
+
|
|
763
|
+
The next nine were found by compiling and running this knowledge base's own recipes with Oscar64 (build 2026-05-19, commit c1270bc) and VICE; see `scripts/check-listings.ts`.
|
|
764
|
+
|
|
765
|
+
**A call through a `const` function pointer initialised with a literal address crashes the compiler.** `static void (* const f)(void) = (void (*)(void))0x1003; f();` is a segmentation fault at every `-O` level, with no diagnostic. Casting the pointer without calling it is fine, so `rirq_call(&slot, 0, (void *)0x1003)` works; for a direct call use `__asm { jsr $1003 }`.
|
|
766
|
+
|
|
767
|
+
**Data nobody references is dropped, even in a placed section.** A `static const` array in a `#pragma data(section)` block that exists only to be at a fixed address — a SID stub at `$1000` that will be `JSR`ed by address — is removed by the linker because no C code names it, and the `JSR` then lands on zero bytes (`BRK`, so BASIC's warm start and a cleared screen). Declare it `__export` to keep it. The `.map` file shows the section's size as 0000 when this has happened.
|
|
768
|
+
|
|
769
|
+
**`NUM_IRQS` and the other library table sizes are per translation unit.** `rasterirq.c` is compiled as its own unit through the header's `#pragma compile`, so a `#define NUM_IRQS 17` in your main file changes what your file believes and not what the library allocates; slot 16 then overwrites something else, silently. Pass `-dNUM_IRQS=17` on the command line so every unit agrees, or stay within the default 16. `rirq_set` has no bounds check.
|
|
770
|
+
|
|
771
|
+
**A guarded index into an array shorter than 256 loses its guard.** Oscar64 1.32.271 at `-O1`, `-O2` and `-O3` compiles `char h = l == NONE ? NONE : lt[l];` (with `NONE` 255 and `char lt[64]`) to an unguarded `lda nextl,y / tax / cmp lt,x`: it infers `l < 64` from the size of `lt` and applies that to an access that only runs when `l != NONE`, so `l == 255` reads `lt[255]`, past the array. Measured in VICE x64sc: a 25-line test turns the border red at `-O1` to `-O3` and green at `-O0` and `-Os`, and green at `-O2` when `lt` has 256 entries. The same happens in the `nav-area-pathfinding` recipe's table check. Write the guard as a statement (`char h = NONE; if (l != NONE) h = lt[l];`), which compiles correctly. There is no diagnostic. Oscar64 HEAD 9a902f6 still emits the unguarded compare (tested here, #30).
|
|
772
|
+
|
|
773
|
+
**A function-like macro with an empty parameter list is refused.** `#define A() (x = 1)` followed by `A();` fails with `error 3006: ';' expected` on the line after the call, whatever the body (`(x = 1)`, `x = 1` or `do { x = 1; } while (0)`); `#define A(v) (x = (v))` with `A(1);` builds. Measured with Oscar64 1.32.271 at `-O2`. Give such a macro one parameter, or use a function. Fixed upstream: the same test builds and runs correctly on Oscar64 HEAD 9a902f6 (tested here, #30).
|
|
774
|
+
|
|
775
|
+
**A loop-invariant `array + signed char` is zero-extended.** Oscar64 1.32.271 compiles a loop storing `board[rowoff[y] + px + cx[i]]`, with `px` a global `signed char` equal to -2, by hoisting `board + px` out of the loop as a 16-bit pointer and adding `px` as unsigned (`CLC; LDA #<board; ADC px; ...; LDA #>board; ADC #$00`), so `px` = `$FE` lands the store 256 bytes above the intended cell. Measured in VICE x64sc with a 20-line test (border red; 2 written at `$0400` instead of 4) and in the `falling-blocks` recipe's draft, whose board check failed. It fails at every level (`-O0` to `-Os`), and still fails on Oscar64 HEAD 9a902f6 (tested here, #30). Compute the sum in a variable first (`char x = px + cx[i]; board[rowoff[y] + x] = 1;`), or keep the offset unsigned. There is no diagnostic.
|
|
776
|
+
|
|
777
|
+
**A read-modify-write after a store can lose its reload.** With `char i = ((height[c] + 1) << 3) + c; board[i] = side; height[c]++;` in a function that returns `i`, the 6502 back-end drops the reload of `height[c]` and emits `LDA side; STA board,y; ADC #$01; STA height,x`, storing `side + 1` into `height[c]`; the intermediate code is correct. Measured with a 24-line test in VICE x64sc at every level (`-O0`, `-O1`, `-O2`, `-O3`, `-Os`) on Oscar64 1.32.271 as built locally (commit c1270bc, see #25); the `game-tree-search` recipe's draft failed its check the same way. Read the old value into a variable first (`char h = height[c] + 1; height[c] = h;`). Oscar64 HEAD 9a902f6 compiles the pattern correctly at `-O1` to `-Os` but stops with an assertion in `GlobalRegisterYMap` at `-O0` (tested here, #30).
|
|
778
|
+
|
|
779
|
+
**Stores to a local `volatile` are deleted at `-O1` and `-O2`.** A `volatile char sink;` inside a function loses every store: a single `sink = 5;`, and a loop that only stores to it, compile to nothing, so a delay loop or a benchmark sink placed between a CIA timer start and stop leaves an empty timing window. C11 5.1.2.3 makes every access to a volatile object a side effect, so this is a miscompile. `-O0` keeps the stores; a global `volatile` is kept at `-O2`. Measured with Oscar64 1.32.271 (local build c1270bc) and Oscar64 HEAD 9a902f6 from the `-g` listings (tested here, #30). Use a global `volatile`, or write through a `volatile` pointer to a fixed address.
|
|
780
|
+
|
|
781
|
+
**Two byte tables read with one index can have the second load indexed by the first load's value.** In a loop that also calls a `__noinline` function, `cx[c] = (unsigned)sx[c] << 8; cy[c] = (unsigned)sy[c] << 8;` (with `sx`, `sy` `const char` tables and `cx`, `cy` `unsigned` arrays) compiles to `LDA sx,Y / STA cx+1,X / TAY / LDA sy,Y`: the value loaded from `sx` replaces the index before `sy` is read. Without the call in the loop the `TAY` is not emitted and the code is right. Measured with a 22-line test in VICE x64sc on Oscar64 1.32.271 (local build c1270bc): border red at `-O1`, `-O2`, `-O3` and `-Os`, green at `-O0`; found by the `car-contact` recipe's draft. Not tested on upstream HEAD (#30). Storing the values as 8.8 words, so no shift is needed, compiles correctly (the recipe's workaround). There is no diagnostic.
|
|
782
|
+
|
|
783
|
+
**Several fixed-address arrays cleared in one loop can have one array's stores sent to another's page.** `for (unsigned i = 0; i < 1024; i++) { A[i] = 32; B[i] = 32; C[i] = 32; D[i] = 32; }` with `A`..`D` at `$C000`, `$C400`, `$E800` and `$C800` compiles to one pointer shared by three of the arrays. Its high byte is set to `B`'s page before the inner loop and overwritten inside it for `D` and `C`, so from the second byte on, `B`'s stores land at `$E8xx`. Measured with a 12-line test in VICE x64sc on Oscar64 1.32.271 (local build c1270bc): border green at `-O0`, red at `-O1`, `-O2`, `-O3` and `-Os`. The #39 platformer's review saw the same on upstream HEAD 9a902f6. Found by the platformer starter, whose blank row showed `@` and `$FF` garbage. Clear each array in its own loop or with its own `memset`. There is no diagnostic (#30).
|
|
784
|
+
|
|
785
|
+
**GCC attribute syntax is not accepted.** `__attribute__((unused))` is a parse error; use `(void)x;` for a deliberately unused read. Oscar64's own qualifiers are keywords (`__interrupt`, `__zeropage`, `__striped`, `__export`, ...).
|
|
786
|
+
|
|
787
|
+
## Reading the errors
|
|
788
|
+
|
|
789
|
+
Every message below was provoked on build 2026-05-19 (`oscar64 -tm=c64 -O2`)
|
|
790
|
+
with the minimal source named in the second column; the sources are files in
|
|
791
|
+
`error-sources/oscar64/` and are shown after the table. The format is
|
|
792
|
+
`path(line, column) : error NNNN: text`, followed on some errors by an
|
|
793
|
+
`info` line with the call site or the sizes. A build with an error exits 20
|
|
794
|
+
and writes no PRG. Paths are printed absolute; they are shortened here.
|
|
795
|
+
|
|
796
|
+
| Message (verbatim) | Source | Cause | Fix |
|
|
797
|
+
|---|---|---|---|
|
|
798
|
+
| `error 3022: Calling undefined function 'missing()->void'` then `info 1003: Called from here` | `undefined-extern.c` | A function is declared and called but no unit in the build defines it. With a module of your own this means its `.c` was neither named by `#pragma compile` nor on the command line (see Multi-file projects). The error is printed against the declaration, twice before and once after the `info` line | Add `#pragma compile("file.c")` to the header, or the `.c` to the command line |
|
|
799
|
+
| (no error; exit 0) | `undefined-extern-var.c` | An `extern` variable with no definition is allocated by the linker in `bss`, silently | Define it once; check the `.map` if a value is unexpectedly zero |
|
|
800
|
+
| `error 3034: Could not place object 'big'` then `info 1004: Size 40000 Available 34672 in section 'bss'` | `region-overflow.c` | An object is larger than the free space in its section. The `info` line gives both numbers; 34,672 is the default `main` region (`$0880` to `$9000`, the 4 KB stack already carved off the top) less this program's own 16 bytes of code | Shrink the object, move it to its own region with `#pragma region` / `#pragma section` (see Memory layout and banking), or lower `#pragma stacksize` |
|
|
801
|
+
| `error 3006: ',y' expected` then `error 3006: End of line expected`, both at the same column | `asm-addressing-mode.c` | Inside `__asm`, an indirect operand in a form the 6502 lacks, here `lda ($fb),x`. `lda ($fb,x),y` gives only the `End of line expected` line; an unknown mnemonic gives `error 3006: ':' expected` then `error 3028: Invalid assembler token`, because the word is taken for a label | Use `($fb),y` or `($fb,x)` |
|
|
802
|
+
| (no error; exit 0) | `asm-addressing-mode.c`, second form | `sta #5`, `inc #5` and `jmp #$1000` are accepted. The `.asm` listing shows the opcode byte emitted as `ff` (`INV`), so the program executes an invalid opcode at run time. Only the indirect forms above are diagnosed | Read the `.asm` listing of any `__asm` block once; look for `INV` |
|
|
803
|
+
| `crt.c(30, 5) : error 3025: Function declaration differs 'main'` | `void-main.c` | `void main(void)`: the startup code in `include/crt.c` calls `main` as `int main(void)`, so the error is reported in crt.c, not in your file | Declare `int main(void)` and return a value |
|
|
804
|
+
| `error 3005: Struct member identifier not found 'border'` | `unknown-vic-field.c` | A field name `vic.h` does not have. The border colour register is `vic.color_border`, the background `vic.color_back` | Read the struct in `include/c64/vic.h`, or the [headers reference](oscar64-headers-reference.md) |
|
|
805
|
+
|
|
806
|
+
One thing seen while building this section is a crash, not an error. With
|
|
807
|
+
`while (border_calls) ;` as the idle loop in `main.c` (a global `char`,
|
|
808
|
+
nothing else in the loop), `-O0` and `-O1` aborted with `Assertion failed:
|
|
809
|
+
(size > 0), function Last, file Array.h, line 569.` (exit 134), and `-O2`
|
|
810
|
+
printed `Oops 29` repeatedly, after `warning 2007: Optimizer locked in
|
|
811
|
+
infinite loop 'main'`, and still wrote a PRG. How many times depends on the
|
|
812
|
+
surrounding source: eleven with the `main.c` shown above and `while
|
|
813
|
+
(border_calls) ;` in place of `for (;;) ;`, a different count with a shorter
|
|
814
|
+
file. `for (;;) ;` builds cleanly at every level. Not reduced further than
|
|
815
|
+
that.
|
|
816
|
+
|
|
817
|
+
Sources (each is meant to fail or misbehave, so none is in a buildable
|
|
818
|
+
fence):
|
|
819
|
+
|
|
820
|
+
`undefined-extern.c`
|
|
821
|
+
|
|
822
|
+
```text
|
|
823
|
+
extern void missing(void);
|
|
824
|
+
int main(void)
|
|
825
|
+
{
|
|
826
|
+
missing();
|
|
827
|
+
return 0;
|
|
828
|
+
}
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
`undefined-extern-var.c`
|
|
832
|
+
|
|
833
|
+
```text
|
|
834
|
+
extern char missing_var;
|
|
835
|
+
int main(void)
|
|
836
|
+
{
|
|
837
|
+
return missing_var;
|
|
838
|
+
}
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
`region-overflow.c`
|
|
842
|
+
|
|
843
|
+
```text
|
|
844
|
+
char big[40000];
|
|
845
|
+
int main(void)
|
|
846
|
+
{
|
|
847
|
+
big[0] = 1;
|
|
848
|
+
return big[39999];
|
|
849
|
+
}
|
|
850
|
+
```
|
|
851
|
+
|
|
852
|
+
`asm-addressing-mode.c` (the file holds the diagnosed form; the accepted
|
|
853
|
+
forms were tried one at a time in the same frame)
|
|
854
|
+
|
|
855
|
+
```text
|
|
856
|
+
int main(void)
|
|
857
|
+
{
|
|
858
|
+
__asm {
|
|
859
|
+
lda ($fb),x
|
|
860
|
+
}
|
|
861
|
+
return 0;
|
|
862
|
+
}
|
|
863
|
+
```
|
|
864
|
+
|
|
865
|
+
`void-main.c`
|
|
866
|
+
|
|
867
|
+
```text
|
|
868
|
+
void main(void)
|
|
869
|
+
{
|
|
870
|
+
}
|
|
871
|
+
```
|
|
872
|
+
|
|
873
|
+
`unknown-vic-field.c`
|
|
874
|
+
|
|
875
|
+
```text
|
|
876
|
+
#include <c64/vic.h>
|
|
877
|
+
int main(void)
|
|
878
|
+
{
|
|
879
|
+
vic.border = 5;
|
|
880
|
+
return 0;
|
|
881
|
+
}
|
|
882
|
+
```
|
|
883
|
+
|
|
884
|
+
## See also
|
|
885
|
+
|
|
886
|
+
- [oscar64-headers-reference.md](oscar64-headers-reference.md) — Full per-header API reference
|
|
887
|
+
- [recipes/oscar64/hello-world.md](../recipes/oscar64/hello-world.md) — First buildable example
|
|
888
|
+
- [formats/c64-file-formats.md](../formats/c64-file-formats.md) — PRG, CRT, D64 format details
|
|
889
|
+
- [hardware/vic-ii-reference.md](../hardware/vic-ii-reference.md) — VIC-II register reference
|
|
890
|
+
- [hardware/sid-reference.md](../hardware/sid-reference.md) — SID register reference
|
|
891
|
+
- [memory-layout-planning.md](memory-layout-planning.md) — whole-program layout: the constraints, one worked layout in all three toolchains, confirmed from the map file; recipe `../recipes/oscar64/memory-layout.md`
|
|
892
|
+
- [release-disk.md](release-disk.md) — putting the built PRG on a bootable D64 with c1541, proving it boots by autostarting the image headless, and a Makefile target that does both; measured with `../recipes/oscar64/platformer-scaffold.md`
|