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,1353 @@
|
|
|
1
|
+
# 6502 Illegal Opcodes Reference
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
The MOS 6502 (and its 6510 cousin in the C64) has a one-byte opcode space:
|
|
6
|
+
256 possible instruction bytes. The official MOS data sheet documents only
|
|
7
|
+
151 of them. The remaining 105 are unassigned in the original
|
|
8
|
+
specification — yet on real silicon they do *not* trap, do *not* NOP
|
|
9
|
+
silently, and do *not* always do the same thing. They execute. They have
|
|
10
|
+
side effects. They are the **illegal opcodes** (also called *undocumented*,
|
|
11
|
+
*unintended*, *unofficial*, or *anomalous* opcodes).
|
|
12
|
+
|
|
13
|
+
These instructions arise from the way the 6502's micro-instruction matrix
|
|
14
|
+
is decoded. Each opcode byte selects a column in an addressing-mode table
|
|
15
|
+
and a row in an operation table. Most cells in that grid are filled with
|
|
16
|
+
useful combinations. The "illegal" cells are simply the unfilled ones —
|
|
17
|
+
where the chip nevertheless ANDs together two operation strobes that the
|
|
18
|
+
designers never intended to activate simultaneously. The result is usually
|
|
19
|
+
predictable: an instruction that does the work of two legal instructions
|
|
20
|
+
back-to-back, with one operand fetch shared between them.
|
|
21
|
+
|
|
22
|
+
A small number of illegal opcodes are *unstable* — they involve internal
|
|
23
|
+
buses whose floating-bit values depend on chip revision, temperature, die
|
|
24
|
+
process, and even the value of the previous instruction's operand. These
|
|
25
|
+
are interesting curiosities but rarely safe to use in shipping code.
|
|
26
|
+
|
|
27
|
+
A handful are *fatal*: they hang the CPU until reset (the so-called
|
|
28
|
+
**KIL/JAM** opcodes — see [KIL/JAM](#kiljam)).
|
|
29
|
+
|
|
30
|
+
The illegal opcodes have been the subject of intense reverse-engineering
|
|
31
|
+
work since the late 1970s. The C64 demoscene in particular treats them as
|
|
32
|
+
first-class instructions: a saved cycle here, a saved byte there, and a
|
|
33
|
+
50-frame-per-second multiplexer suddenly fits in the badline budget.
|
|
34
|
+
Modern cycle-exact emulators (VICE, x64sc, Kowalski) implement them
|
|
35
|
+
faithfully, and modern assemblers accept their mnemonics once told the CPU
|
|
36
|
+
is NMOS (acme `!cpu 6510`, ca65 `.setcpu "6502X"`; KickAssembler needs
|
|
37
|
+
nothing; dasm not measured here).
|
|
38
|
+
|
|
39
|
+
This document covers all 105 undocumented opcodes (20 mnemonics),
|
|
40
|
+
distilled from the canonical Oxyron table, Masswerk's reference, and the
|
|
41
|
+
NESdev wiki. Per-revision differences are called out where they matter.
|
|
42
|
+
|
|
43
|
+
### What "illegal" actually means
|
|
44
|
+
|
|
45
|
+
The term is historical. Inside the chip there is nothing illegal about
|
|
46
|
+
these instructions — the decoder happily executes them. "Illegal" simply
|
|
47
|
+
means **MOS Technology never documented them**, never guaranteed their
|
|
48
|
+
behavior, and never promised that future revisions of the silicon would
|
|
49
|
+
keep behaving the same way. In practice:
|
|
50
|
+
|
|
51
|
+
- On every NMOS 6502/6510 ever produced, the *safe* illegal opcodes behave
|
|
52
|
+
identically. They are reliable across all C64 models that ship a 6510 or
|
|
53
|
+
8500 CPU.
|
|
54
|
+
- On the **65C02** (the CMOS revision used in the Apple //c, Apple //e
|
|
55
|
+
enhanced, BBC Master, and some later embedded systems) the illegal
|
|
56
|
+
opcodes were **removed**. Most slots are filled with explicit NOPs of
|
|
57
|
+
varying byte/cycle counts. Code that relies on illegal opcodes will *not*
|
|
58
|
+
run on a 65C02.
|
|
59
|
+
- The **65816** (Apple IIGS, SNES) does not preserve any illegal-opcode
|
|
60
|
+
behavior either. The same warning applies.
|
|
61
|
+
- The C64's 6510 and 8500 and the C128's 8502 are NMOS parts and *do*
|
|
62
|
+
support the illegal opcodes. The SuperCPU accelerator uses a 65816 and
|
|
63
|
+
*does not*.
|
|
64
|
+
|
|
65
|
+
In short: on a stock C64, illegal opcodes are safe. Outside the C64
|
|
66
|
+
NMOS family, they are not portable.
|
|
67
|
+
|
|
68
|
+
### Safe vs. unstable
|
|
69
|
+
|
|
70
|
+
The illegal opcodes fall into three reliability tiers:
|
|
71
|
+
|
|
72
|
+
| Tier | Examples | Use in production? |
|
|
73
|
+
|------|----------|--------------------|
|
|
74
|
+
| Safe (stable) | LAX, SAX, ANC, ARR, ALR, RLA, RRA, SLO, SRE, ISC, DCP, AXS, LAS (see note), NOPs | Yes — universal across NMOS 6502/6510 |
|
|
75
|
+
| Unstable | XAA, LAX #imm, AHX, TAS, SHX, SHY | Risky — output depends on chip and surrounding state |
|
|
76
|
+
| Fatal | KIL/JAM (12 opcodes) | Never — hangs the CPU |
|
|
77
|
+
|
|
78
|
+
LAS ($BB) was in the unstable tier in an earlier version of this page. None
|
|
79
|
+
of the sources this page cites marks it unstable — Oxyron and Masswerk
|
|
80
|
+
footnote exactly XAA, LAX #imm, AHX, SHX, SHY and TAS — and Oxyron records
|
|
81
|
+
only that one source called it "probably unreliable". Its stability cannot
|
|
82
|
+
be measured in VICE, which implements one behaviour; the classification
|
|
83
|
+
follows the cited tables. It still overwrites S, so it is deterministic,
|
|
84
|
+
not harmless.
|
|
85
|
+
|
|
86
|
+
The safe tier is what almost every demoscene production uses. The unstable
|
|
87
|
+
tier shows up in a small number of effects where the instability itself is
|
|
88
|
+
the point (random-number generation), but most demos avoid them. KIL/JAM
|
|
89
|
+
opcodes are used as crash-out markers and occasionally as fuses in
|
|
90
|
+
copy-protection routines.
|
|
91
|
+
|
|
92
|
+
### Per-revision availability
|
|
93
|
+
|
|
94
|
+
Tested behavior of the safe illegal opcodes is **identical** on:
|
|
95
|
+
|
|
96
|
+
- 6502 (Apple I, Apple II, Atari 2600/400/800, NES, BBC Micro early)
|
|
97
|
+
- 6510 (Commodore 64)
|
|
98
|
+
- 8500 (Commodore 64C, late breadbins — an earlier revision of this page
|
|
99
|
+
also listed the C128 here; the C128 has no 8500)
|
|
100
|
+
- 8502 (Commodore 128 — its only 65xx CPU, in C128 mode and C64 mode
|
|
101
|
+
alike; same logic as the 8500, 2 MHz capable. The C128 part name is as
|
|
102
|
+
VICE x128 reports it, not measured on hardware)
|
|
103
|
+
- 2A03 (NES — a 6502 with disabled BCD)
|
|
104
|
+
|
|
105
|
+
Tested behavior of the unstable illegal opcodes **varies** between these
|
|
106
|
+
parts and sometimes within the same part (different production runs of the
|
|
107
|
+
6502 differ on XAA, for example). Real-hardware regression testing is the
|
|
108
|
+
only reliable answer.
|
|
109
|
+
|
|
110
|
+
## Quick reference
|
|
111
|
+
|
|
112
|
+
All 105 undocumented opcodes are listed below — 20 mnemonics, of which 27
|
|
113
|
+
opcodes are NOPs and 12 are KIL/JAM. (An earlier revision omitted eight
|
|
114
|
+
SRE/RRA/RLA addressing modes and the $EB SBC alias.) Each has a full H3
|
|
115
|
+
entry later with cycles, flags, and behavioral notes.
|
|
116
|
+
|
|
117
|
+
| Opcode | Mnemonic | Mode | Operation | Cycles | Stable? |
|
|
118
|
+
|--------|------------|---------|-----------------------------------|--------|---------|
|
|
119
|
+
| $0B | ANC #imm | imm | A &= imm; C = N | 2 | yes |
|
|
120
|
+
| $2B | ANC #imm | imm | A &= imm; C = N (alias of $0B) | 2 | yes |
|
|
121
|
+
| $4B | ALR #imm | imm | A = (A & imm) >> 1 | 2 | yes |
|
|
122
|
+
| $6B | ARR #imm | imm | A = ((A & imm) >> 1) + ROR carry | 2 | yes |
|
|
123
|
+
| $8B | XAA #imm | imm | A = (A \| magic) & X & imm | 2 | NO |
|
|
124
|
+
| $AB | LAX #imm | imm | A = X = (A \| magic) & imm | 2 | NO |
|
|
125
|
+
| $CB | AXS #imm | imm | X = (A & X) - imm; sets C as CMP | 2 | yes |
|
|
126
|
+
| $EB | SBC #imm | imm | A = A - imm - !C (alias of $E9) | 2 | yes |
|
|
127
|
+
| $A3 | LAX (zp,X) | (zp,X) | A = X = M | 6 | yes |
|
|
128
|
+
| $A7 | LAX zp | zp | A = X = M | 3 | yes |
|
|
129
|
+
| $AF | LAX abs | abs | A = X = M | 4 | yes |
|
|
130
|
+
| $B3 | LAX (zp),Y | (zp),Y | A = X = M (+1 on page cross) | 5 | yes |
|
|
131
|
+
| $B7 | LAX zp,Y | zp,Y | A = X = M | 4 | yes |
|
|
132
|
+
| $BF | LAX abs,Y | abs,Y | A = X = M (+1 on page cross) | 4 | yes |
|
|
133
|
+
| $83 | SAX (zp,X) | (zp,X) | M = A & X | 6 | yes |
|
|
134
|
+
| $87 | SAX zp | zp | M = A & X | 3 | yes |
|
|
135
|
+
| $8F | SAX abs | abs | M = A & X | 4 | yes |
|
|
136
|
+
| $97 | SAX zp,Y | zp,Y | M = A & X | 4 | yes |
|
|
137
|
+
| $C3 | DCP (zp,X) | (zp,X) | M-- ; CMP A,M | 8 | yes |
|
|
138
|
+
| $C7 | DCP zp | zp | M-- ; CMP A,M | 5 | yes |
|
|
139
|
+
| $CF | DCP abs | abs | M-- ; CMP A,M | 6 | yes |
|
|
140
|
+
| $D3 | DCP (zp),Y | (zp),Y | M-- ; CMP A,M | 8 | yes |
|
|
141
|
+
| $D7 | DCP zp,X | zp,X | M-- ; CMP A,M | 6 | yes |
|
|
142
|
+
| $DB | DCP abs,Y | abs,Y | M-- ; CMP A,M | 7 | yes |
|
|
143
|
+
| $DF | DCP abs,X | abs,X | M-- ; CMP A,M | 7 | yes |
|
|
144
|
+
| $E3 | ISC (zp,X) | (zp,X) | M++ ; SBC M | 8 | yes |
|
|
145
|
+
| $E7 | ISC zp | zp | M++ ; SBC M | 5 | yes |
|
|
146
|
+
| $EF | ISC abs | abs | M++ ; SBC M | 6 | yes |
|
|
147
|
+
| $F3 | ISC (zp),Y | (zp),Y | M++ ; SBC M | 8 | yes |
|
|
148
|
+
| $F7 | ISC zp,X | zp,X | M++ ; SBC M | 6 | yes |
|
|
149
|
+
| $FB | ISC abs,Y | abs,Y | M++ ; SBC M | 7 | yes |
|
|
150
|
+
| $FF | ISC abs,X | abs,X | M++ ; SBC M | 7 | yes |
|
|
151
|
+
| $03 | SLO (zp,X) | (zp,X) | M <<= 1 ; A \|= M | 8 | yes |
|
|
152
|
+
| $07 | SLO zp | zp | M <<= 1 ; A \|= M | 5 | yes |
|
|
153
|
+
| $0F | SLO abs | abs | M <<= 1 ; A \|= M | 6 | yes |
|
|
154
|
+
| $13 | SLO (zp),Y | (zp),Y | M <<= 1 ; A \|= M | 8 | yes |
|
|
155
|
+
| $17 | SLO zp,X | zp,X | M <<= 1 ; A \|= M | 6 | yes |
|
|
156
|
+
| $1B | SLO abs,Y | abs,Y | M <<= 1 ; A \|= M | 7 | yes |
|
|
157
|
+
| $1F | SLO abs,X | abs,X | M <<= 1 ; A \|= M | 7 | yes |
|
|
158
|
+
| $23 | RLA (zp,X) | (zp,X) | M = ROL M ; A &= M | 8 | yes |
|
|
159
|
+
| $27 | RLA zp | zp | M = ROL M ; A &= M | 5 | yes |
|
|
160
|
+
| $2F | RLA abs | abs | M = ROL M ; A &= M | 6 | yes |
|
|
161
|
+
| $33 | RLA (zp),Y | (zp),Y | M = ROL M ; A &= M | 8 | yes |
|
|
162
|
+
| $37 | RLA zp,X | zp,X | M = ROL M ; A &= M | 6 | yes |
|
|
163
|
+
| $3B | RLA abs,Y | abs,Y | M = ROL M ; A &= M | 7 | yes |
|
|
164
|
+
| $3F | RLA abs,X | abs,X | M = ROL M ; A &= M | 7 | yes |
|
|
165
|
+
| $43 | SRE (zp,X) | (zp,X) | M >>= 1 ; A ^= M | 8 | yes |
|
|
166
|
+
| $47 | SRE zp | zp | M >>= 1 ; A ^= M | 5 | yes |
|
|
167
|
+
| $4F | SRE abs | abs | M >>= 1 ; A ^= M | 6 | yes |
|
|
168
|
+
| $53 | SRE (zp),Y | (zp),Y | M >>= 1 ; A ^= M | 8 | yes |
|
|
169
|
+
| $57 | SRE zp,X | zp,X | M >>= 1 ; A ^= M | 6 | yes |
|
|
170
|
+
| $5B | SRE abs,Y | abs,Y | M >>= 1 ; A ^= M | 7 | yes |
|
|
171
|
+
| $5F | SRE abs,X | abs,X | M >>= 1 ; A ^= M | 7 | yes |
|
|
172
|
+
| $63 | RRA (zp,X) | (zp,X) | M = ROR M ; ADC M | 8 | yes |
|
|
173
|
+
| $67 | RRA zp | zp | M = ROR M ; ADC M | 5 | yes |
|
|
174
|
+
| $6F | RRA abs | abs | M = ROR M ; ADC M | 6 | yes |
|
|
175
|
+
| $73 | RRA (zp),Y | (zp),Y | M = ROR M ; ADC M | 8 | yes |
|
|
176
|
+
| $77 | RRA zp,X | zp,X | M = ROR M ; ADC M | 6 | yes |
|
|
177
|
+
| $7B | RRA abs,Y | abs,Y | M = ROR M ; ADC M | 7 | yes |
|
|
178
|
+
| $7F | RRA abs,X | abs,X | M = ROR M ; ADC M | 7 | yes |
|
|
179
|
+
| $93 | AHX (zp),Y | (zp),Y | M = A & X & (H+1) | 6 | NO |
|
|
180
|
+
| $9F | AHX abs,Y | abs,Y | M = A & X & (H+1) | 5 | NO |
|
|
181
|
+
| $9B | TAS abs,Y | abs,Y | S=A&X ; M=A&X&(H+1) | 5 | NO |
|
|
182
|
+
| $BB | LAS abs,Y | abs,Y | A = X = S = M & S (+1 on page cross) | 4 | yes |
|
|
183
|
+
| $9E | SHX abs,Y | abs,Y | M = X & (H+1) | 5 | NO |
|
|
184
|
+
| $9C | SHY abs,X | abs,X | M = Y & (H+1) | 5 | NO |
|
|
185
|
+
| $02 | KIL/JAM | impl | halts CPU | — | fatal |
|
|
186
|
+
|
|
187
|
+
Additional undocumented NOPs (do nothing but consume bytes/cycles):
|
|
188
|
+
|
|
189
|
+
| Opcode | Mnemonic | Mode | Cycles | Notes |
|
|
190
|
+
|--------|----------|-------|--------|------------------------------|
|
|
191
|
+
| $1A | NOP | impl | 2 | undocumented 1-byte NOP |
|
|
192
|
+
| $3A | NOP | impl | 2 | undocumented 1-byte NOP |
|
|
193
|
+
| $5A | NOP | impl | 2 | undocumented 1-byte NOP |
|
|
194
|
+
| $7A | NOP | impl | 2 | undocumented 1-byte NOP |
|
|
195
|
+
| $DA | NOP | impl | 2 | undocumented 1-byte NOP |
|
|
196
|
+
| $FA | NOP | impl | 2 | undocumented 1-byte NOP |
|
|
197
|
+
| $80 | NOP #imm | imm | 2 | undocumented 2-byte NOP |
|
|
198
|
+
| $82 | NOP #imm | imm | 2 | undocumented 2-byte NOP |
|
|
199
|
+
| $89 | NOP #imm | imm | 2 | undocumented 2-byte NOP |
|
|
200
|
+
| $C2 | NOP #imm | imm | 2 | undocumented 2-byte NOP |
|
|
201
|
+
| $E2 | NOP #imm | imm | 2 | undocumented 2-byte NOP |
|
|
202
|
+
| $04 | NOP zp | zp | 3 | reads zp; flags unaffected |
|
|
203
|
+
| $44 | NOP zp | zp | 3 | reads zp; flags unaffected |
|
|
204
|
+
| $64 | NOP zp | zp | 3 | reads zp; flags unaffected |
|
|
205
|
+
| $14 | NOP zp,X | zp,X | 4 | reads zp,X |
|
|
206
|
+
| $34 | NOP zp,X | zp,X | 4 | reads zp,X |
|
|
207
|
+
| $54 | NOP zp,X | zp,X | 4 | reads zp,X |
|
|
208
|
+
| $74 | NOP zp,X | zp,X | 4 | reads zp,X |
|
|
209
|
+
| $D4 | NOP zp,X | zp,X | 4 | reads zp,X |
|
|
210
|
+
| $F4 | NOP zp,X | zp,X | 4 | reads zp,X |
|
|
211
|
+
| $0C | NOP abs | abs | 4 | reads abs (4-cycle TOP) |
|
|
212
|
+
| $1C | NOP abs,X | abs,X | 4 | +1 on page cross |
|
|
213
|
+
| $3C | NOP abs,X | abs,X | 4 | +1 on page cross |
|
|
214
|
+
| $5C | NOP abs,X | abs,X | 4 | +1 on page cross |
|
|
215
|
+
| $7C | NOP abs,X | abs,X | 4 | +1 on page cross |
|
|
216
|
+
| $DC | NOP abs,X | abs,X | 4 | +1 on page cross |
|
|
217
|
+
| $FC | NOP abs,X | abs,X | 4 | +1 on page cross |
|
|
218
|
+
|
|
219
|
+
KIL/JAM opcodes (CPU halt — these hang until reset):
|
|
220
|
+
|
|
221
|
+
| Opcode | Mnemonic | Notes |
|
|
222
|
+
|--------|----------|------------------------------------------|
|
|
223
|
+
| $02 | KIL | halts CPU |
|
|
224
|
+
| $12 | KIL | halts CPU |
|
|
225
|
+
| $22 | KIL | halts CPU |
|
|
226
|
+
| $32 | KIL | halts CPU |
|
|
227
|
+
| $42 | KIL | halts CPU |
|
|
228
|
+
| $52 | KIL | halts CPU |
|
|
229
|
+
| $62 | KIL | halts CPU |
|
|
230
|
+
| $72 | KIL | halts CPU |
|
|
231
|
+
| $92 | KIL | halts CPU |
|
|
232
|
+
| $B2 | KIL | halts CPU |
|
|
233
|
+
| $D2 | KIL | halts CPU |
|
|
234
|
+
| $F2 | KIL | halts CPU |
|
|
235
|
+
|
|
236
|
+
## Safe illegal opcodes
|
|
237
|
+
|
|
238
|
+
The instructions in this section are reliable across every 6502/6510/8500
|
|
239
|
+
ever shipped. They fall naturally into a few families based on what two
|
|
240
|
+
legal operations they combine.
|
|
241
|
+
|
|
242
|
+
### Combined load: LAX
|
|
243
|
+
|
|
244
|
+
**LAX** = LDA + LDX from the same memory operand. Stores the loaded byte
|
|
245
|
+
into both A and X in a single 3- or 4-cycle instruction instead of two
|
|
246
|
+
separate 3- or 4-cycle loads (6–8 cycles). Available in zp, zp,Y, abs,
|
|
247
|
+
abs,Y, (zp,X) and (zp),Y — and *not* zp,X or abs,X. That is not the set of
|
|
248
|
+
modes LDA and LDX have in common (only zp, abs, abs,Y and immediate are):
|
|
249
|
+
LAX takes LDA's modes with the zp,X and abs,X slots replaced by LDX's zp,Y
|
|
250
|
+
and abs,Y, and keeps (zp,X). An earlier version of this page called the six
|
|
251
|
+
"the modes LDA and LDX share" (KickAssembler 5.25: `lda $10,y` is silently
|
|
252
|
+
promoted to abs,Y $B9, and `ldx ($10),y`, `ldx ($10,x)`, `lax $10,x` are
|
|
253
|
+
refused).
|
|
254
|
+
|
|
255
|
+
The N and Z flags are set from the loaded byte. C, V, D, I are unchanged.
|
|
256
|
+
|
|
257
|
+
The immediate form `LAX #imm` ($AB) is **unstable** — see
|
|
258
|
+
[XAA/LAX immediate](#ab--lax-imm--load-a-and-x-immediate-unstable).
|
|
259
|
+
|
|
260
|
+
### Combined store: SAX (other references call it AXS or AAX — in this document, in KickAssembler and in ca65, AXS is the $CB subtract-into-X, and neither assembler accepts `axs` with an address operand or knows `aax`; see the Pitfalls note on mnemonics)
|
|
261
|
+
|
|
262
|
+
**SAX** = STA bitwise-ANDed with X. Stores the value `A & X` to memory.
|
|
263
|
+
No flags are affected. Useful when you have a precomputed mask in X and
|
|
264
|
+
want to store the masked accumulator value without disturbing A or doing
|
|
265
|
+
a separate AND. Two-in-one in 3-4 cycles.
|
|
266
|
+
|
|
267
|
+
Modes: zp, zp,Y, abs, (zp,X). No X-indexed variant (X is a source).
|
|
268
|
+
|
|
269
|
+
Frequently used in zeropage table generation: build the table once with
|
|
270
|
+
LAX from a source, transform with bit math, write back with SAX, all
|
|
271
|
+
without losing X.
|
|
272
|
+
|
|
273
|
+
### AND-then-set-carry: ANC
|
|
274
|
+
|
|
275
|
+
**ANC** = AND + copy-bit-7-to-carry. Performs A &= imm, sets N and Z from
|
|
276
|
+
the result, and copies bit 7 of the result into C, in one 2-cycle
|
|
277
|
+
instruction. The C it leaves is the one `AND #imm : CMP #$80` would leave,
|
|
278
|
+
but N and Z are not: CMP #$80 inverts N and sets Z only for a result of
|
|
279
|
+
$80 (measured in VICE x64sc: with A=$C5, `anc #$80` leaves A=$80, N=1 Z=0
|
|
280
|
+
C=1; `and #$80 : cmp #$80` leaves N=0 Z=1 C=1). An earlier version of this
|
|
281
|
+
page called the two sequences identical.
|
|
282
|
+
|
|
283
|
+
The 6502 silicon has two opcodes for this — $0B and $2B — that do
|
|
284
|
+
identical things. Most assemblers accept either.
|
|
285
|
+
|
|
286
|
+
Useful when the sign of a masked value has to end up in C — for a
|
|
287
|
+
following ROL/ROR/ADC/SBC, or so that a later instruction that rewrites N
|
|
288
|
+
still leaves the sign test in C. It saves nothing on a plain sign branch:
|
|
289
|
+
`and #$80 : bmi` needs no compare either, and takes the same branch as
|
|
290
|
+
`anc #$80 : bcs` for every value of A (measured in VICE x64sc, 0
|
|
291
|
+
mismatches over 256). An earlier version of this page gave "branch on the
|
|
292
|
+
sign without a separate compare" as the use; that compare was never
|
|
293
|
+
needed.
|
|
294
|
+
|
|
295
|
+
### AND-then-shift-right: ALR (a.k.a. ASR)
|
|
296
|
+
|
|
297
|
+
**ALR** = AND + LSR. Computes `A = (A & imm) >> 1`. The C flag receives
|
|
298
|
+
bit 0 of the AND result (i.e., the bit shifted out). Sets N (always 0,
|
|
299
|
+
since LSR clears bit 7) and Z from the shifted result. Two cycles.
|
|
300
|
+
|
|
301
|
+
Equivalent in effect to `AND #imm : LSR A` (4 cycles, 3 bytes — an
|
|
302
|
+
earlier version said 4 bytes) compressed into 2 cycles, 2 bytes.
|
|
303
|
+
|
|
304
|
+
### AND-then-rotate-right: ARR
|
|
305
|
+
|
|
306
|
+
**ARR** = AND + ROR with different flags. In binary mode the accumulator
|
|
307
|
+
is exactly what `AND #imm : ROR A` would leave (measured in VICE x64sc: 0
|
|
308
|
+
of 512 operand/carry-in cases differ); only C and V differ:
|
|
309
|
+
|
|
310
|
+
- `A = (A & imm) >> 1`, with C-in shifted into bit 7
|
|
311
|
+
- C = bit 6 of the result (NOT bit 0 — this is what makes it unusual)
|
|
312
|
+
- V = bit 6 XOR bit 5 of the result
|
|
313
|
+
- N, Z from the result
|
|
314
|
+
|
|
315
|
+
In decimal mode (D=1) ARR diverges further: the ROR result is BCD-adjusted
|
|
316
|
+
(+$06 if the low nibble of the AND result plus its bit 0 exceeds 5, +$60
|
|
317
|
+
if the high nibble plus its bit 4 exceeds $50), C is 1 exactly when the
|
|
318
|
+
+$60 fix-up fires rather than bit 6 of the result, and N is the carry-in
|
|
319
|
+
rather than bit 7 of the final A. So in decimal mode the accumulator
|
|
320
|
+
itself differs from AND + ROR (462 of 512 cases in VICE x64sc) and N no
|
|
321
|
+
longer reads the result's sign (352 of 512). An earlier version of this
|
|
322
|
+
page had the two modes the wrong way round. The C/V rule is genuinely
|
|
323
|
+
useful in shift-and-test sequences because C ends up holding what would
|
|
324
|
+
have been the carry-out of an add.
|
|
325
|
+
|
|
326
|
+
### Rotate-then-OR/AND/EOR/ADC families (RMW)
|
|
327
|
+
|
|
328
|
+
These four are the **most demoscene-friendly** of all illegal opcodes
|
|
329
|
+
because they save three to five cycles, depending on addressing mode,
|
|
330
|
+
every time you need to bit-shift a byte in memory and update the
|
|
331
|
+
accumulator with it:
|
|
332
|
+
|
|
333
|
+
| Mnemonic | Equivalent legal pair | Bytes saved | Cycles saved |
|
|
334
|
+
|----------|-----------------------|-------------|--------------|
|
|
335
|
+
| SLO | ASL mem : ORA mem | 2 (zp, zp,X, (zp,X), (zp),Y) / 3 (abs, abs,X, abs,Y) | 3 (zp), 4 (abs, zp,X), 4-5 (abs,X: the legal ORA pays the page-cross cycle, the RMW never does) |
|
|
336
|
+
| RLA | ROL mem : AND mem | 2 (zp, zp,X, (zp,X), (zp),Y) / 3 (abs, abs,X, abs,Y) | 3 (zp), 4 (abs, zp,X), 4-5 (abs,X) |
|
|
337
|
+
| SRE | LSR mem : EOR mem | 2 (zp, zp,X, (zp,X), (zp),Y) / 3 (abs, abs,X, abs,Y) | 3 (zp), 4 (abs, zp,X), 4-5 (abs,X) |
|
|
338
|
+
| RRA | ROR mem : ADC mem | 2 (zp, zp,X, (zp,X), (zp),Y) / 3 (abs, abs,X, abs,Y) | 3 (zp), 4 (abs, zp,X), 4-5 (abs,X) |
|
|
339
|
+
|
|
340
|
+
(An earlier version of this table said 2 bytes and 2-3 cycles for every
|
|
341
|
+
mode; a 2-cycle saving never occurs. Measured in VICE x64sc: zp 5 vs 8,
|
|
342
|
+
abs 6 vs 10, zp,X 6 vs 10, abs,X 7 vs 11 or 12.) The legal shifts have no
|
|
343
|
+
abs,Y, (zp,X) or (zp),Y form, so the "equivalent legal pair" column does
|
|
344
|
+
not apply to those three modes; there the saving is against a
|
|
345
|
+
load/shift/store/ORA sequence and is larger.
|
|
346
|
+
|
|
347
|
+
Available in every RMW addressing mode (zp, zp,X, abs, abs,X, abs,Y,
|
|
348
|
+
(zp,X), (zp),Y). Cycle counts match the equivalent legal RMW (5/6/7/8
|
|
349
|
+
cycles depending on mode). Flags: SLO/RLA/SRE set N, Z, C; RRA sets N, Z,
|
|
350
|
+
V, C (because it ends in ADC and inherits its V semantics).
|
|
351
|
+
|
|
352
|
+
Classic use: a multiplexer routine that needs to shift a sprite control
|
|
353
|
+
byte and OR it into a register-image table in one instruction. RLA is
|
|
354
|
+
similarly used for masking-in bits while rotating a flags byte.
|
|
355
|
+
|
|
356
|
+
### Decrement-then-compare: DCP
|
|
357
|
+
|
|
358
|
+
**DCP** = DEC mem + CMP. Decrements memory and then compares A against the
|
|
359
|
+
new value. Sets N, Z, C from the comparison. Useful in countdown loops
|
|
360
|
+
where you want to decrement a counter and branch on a specific reached
|
|
361
|
+
value without restoring A:
|
|
362
|
+
|
|
363
|
+
```asm
|
|
364
|
+
loop:
|
|
365
|
+
; ... do work using A ...
|
|
366
|
+
dcp counter ; counter-- ; CMP A,counter
|
|
367
|
+
bne loop
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
In legal-only code this needs `DEC counter : LDA #target : CMP counter`
|
|
371
|
+
(10 cycles with a zero-page counter, 12 absolute; an earlier version said
|
|
372
|
+
7+); DCP zp is 5 cycles flat. The shortest legal equivalent that, like
|
|
373
|
+
DCP, compares A against the decremented value is `dec counter : cmp
|
|
374
|
+
counter` (8 cycles zp, measured in VICE x64sc), so the saving DCP actually
|
|
375
|
+
buys is 3 cycles, not 5.
|
|
376
|
+
|
|
377
|
+
### Increment-then-subtract: ISC (a.k.a. ISB, INS)
|
|
378
|
+
|
|
379
|
+
**ISC** = INC mem + SBC. Increments memory, then subtracts the new value
|
|
380
|
+
from A with borrow. Sets N, Z, C, V from the subtraction. The compound is
|
|
381
|
+
useful for accumulating signed differences against an incrementing index.
|
|
382
|
+
|
|
383
|
+
### AND-then-subtract: AXS (a.k.a. SBX)
|
|
384
|
+
|
|
385
|
+
**AXS** = `X = (A & X) - imm`. Performs the AND of A and X, subtracts an
|
|
386
|
+
immediate, stores the result in X. The carry and N/Z flags reflect the
|
|
387
|
+
comparison the same way CMP would. **Decimal mode does not apply** — AXS
|
|
388
|
+
is always binary, even with D=1. This is the only 6502 instruction that
|
|
389
|
+
ignores decimal mode for subtraction.
|
|
390
|
+
|
|
391
|
+
Useful as a "test-then-decrement-X" combo when X holds a loop counter
|
|
392
|
+
masked against the accumulator.
|
|
393
|
+
|
|
394
|
+
### Load A, X and S: LAS (a.k.a. LAR)
|
|
395
|
+
|
|
396
|
+
**LAS** = `A = X = S = M & S`, abs,Y only ($BB). Reads memory, ANDs it
|
|
397
|
+
with the current stack pointer and writes the result into A, X and S at
|
|
398
|
+
once; N and Z from the result; 4 cycles, +1 on page cross. It writes S,
|
|
399
|
+
so restore the stack pointer before the next push or return. An earlier
|
|
400
|
+
version of this page listed it among the unstable opcodes — see the note
|
|
401
|
+
under the tier table and the $BB entry.
|
|
402
|
+
|
|
403
|
+
### Undocumented NOPs
|
|
404
|
+
|
|
405
|
+
The 6502 has ~27 undocumented NOPs scattered across the opcode map.
|
|
406
|
+
They consume 1, 2, or 3 bytes and 2 to 5 cycles depending on the
|
|
407
|
+
addressing mode the decoder *would* have applied if the opcode were
|
|
408
|
+
legal. The most common production uses:
|
|
409
|
+
|
|
410
|
+
- **Padding** for cycle-exact timing in raster code.
|
|
411
|
+
- **Branch-target alignment** to ensure a branch never crosses a page
|
|
412
|
+
boundary (and thus has a predictable cycle count).
|
|
413
|
+
- **Skip-next-instruction** tricks: a 2-byte NOP $80/$82/$89 will swallow
|
|
414
|
+
the byte that follows it, letting you jump into the middle of a
|
|
415
|
+
two-byte sequence and have it decode as one thing on entry and another
|
|
416
|
+
as a fall-through.
|
|
417
|
+
|
|
418
|
+
The 3-cycle and 4-cycle NOPs (`NOP zp`, `NOP abs`, `NOP abs,X`) perform a
|
|
419
|
+
read of the addressed location with no effect. The read *is* visible on
|
|
420
|
+
the address bus, which can have side effects on memory-mapped I/O — be
|
|
421
|
+
careful with `NOP $D019` for example, because reading $D019 has no side
|
|
422
|
+
effect but reading some other I/O addresses does.
|
|
423
|
+
|
|
424
|
+
## Unstable illegal opcodes
|
|
425
|
+
|
|
426
|
+
These instructions involve internal buses whose values are not fully
|
|
427
|
+
controlled by the rest of the chip. The result on real hardware depends
|
|
428
|
+
on chip revision, die batch, temperature, and sometimes the immediately
|
|
429
|
+
preceding instruction's data bus contents. **Do not use these in
|
|
430
|
+
production code** unless your goal is to exploit the instability itself
|
|
431
|
+
(rare RNG schemes).
|
|
432
|
+
|
|
433
|
+
### XAA (a.k.a. ANE)
|
|
434
|
+
|
|
435
|
+
`A = (A | magic) & X & imm`. The "magic" constant is the value the chip's
|
|
436
|
+
internal bus floats to during the operand fetch. Values reported for NMOS
|
|
437
|
+
parts include $EE, $EF, $FF and $00, and on one chip it can differ between
|
|
438
|
+
fetches depending on whether the VIC-II held RDY low (a badline or sprite
|
|
439
|
+
DMA) on that cycle. None of this is measured on silicon here. VICE (x64sc
|
|
440
|
+
and x64, 3.10 on this machine) uses $EF — measured: `lda #$00 : ldx #$ff :
|
|
441
|
+
xaa #$ff` leaves A=$EF — and substitutes $EE when the operand fetch fell on
|
|
442
|
+
a RDY cycle (from VICE's own release notes, not measured here). The result
|
|
443
|
+
equals `X & imm` only for the bits of `imm` that are set in `A | magic`;
|
|
444
|
+
with A=$FF preloaded it is `X & imm` for every magic value. An earlier
|
|
445
|
+
revision of this page said magic was $FF on most silicon; none of the
|
|
446
|
+
sources it cites says so and VICE does not model it.
|
|
447
|
+
|
|
448
|
+
### LAX #imm (a.k.a. LXA)
|
|
449
|
+
|
|
450
|
+
`A = X = (A | magic) & imm` — not `A = X = imm`. Same mechanism as XAA,
|
|
451
|
+
without the X term. VICE uses $EE (its NEWS: 3.5 set $EF, 3.6 "changed to
|
|
452
|
+
0xEE as required by wizball"), measured: `lda #$00 : lax #$ff` gives
|
|
453
|
+
A=X=$EE and `lda #$00 : lax #$55` gives $44. It loads `imm` only for the
|
|
454
|
+
bits set in `A | magic`; preload A=$FF if the instruction cannot be
|
|
455
|
+
avoided. Oxyron's table, this page's primary source, reports that on the
|
|
456
|
+
author's own C64-II the opcode "loses bits" (`ORA #? : AND #imm : TAX`),
|
|
457
|
+
so "works on most parts" was never what the source said; the
|
|
458
|
+
memory-addressed LAX forms are unaffected.
|
|
459
|
+
|
|
460
|
+
### AHX (a.k.a. SHA, AXA)
|
|
461
|
+
|
|
462
|
+
`M[addr] = A & X & (H+1)` where H is the high byte of the target
|
|
463
|
+
address. The `H+1` term comes from a half-cycle race between the
|
|
464
|
+
address-bus high byte and the data-output drivers. If the address
|
|
465
|
+
crosses a page boundary, the high byte feedback is corrupted and the
|
|
466
|
+
result is unpredictable.
|
|
467
|
+
|
|
468
|
+
### TAS (a.k.a. SHS, XAS)
|
|
469
|
+
|
|
470
|
+
`S = A & X ; M[addr] = A & X & (H+1)`. Has the same `(H+1)` instability
|
|
471
|
+
as AHX, plus it clobbers the stack pointer S, which makes it doubly
|
|
472
|
+
dangerous: even an emulator-stable form will trash the stack.
|
|
473
|
+
|
|
474
|
+
### SHX / SHY (a.k.a. SXA / SYA)
|
|
475
|
+
|
|
476
|
+
`M[addr] = X & (H+1)` and `M[addr] = Y & (H+1)`. Same `(H+1)` quirk as
|
|
477
|
+
AHX. The literal use case is "store an index masked against the
|
|
478
|
+
target's high byte" which is too niche for most code.
|
|
479
|
+
|
|
480
|
+
## KIL/JAM
|
|
481
|
+
|
|
482
|
+
Twelve opcodes ($02, $12, $22, $32, $42, $52, $62, $72, $92, $B2, $D2,
|
|
483
|
+
$F2) cause the CPU to enter a state where the instruction-cycle clock
|
|
484
|
+
keeps advancing but the PC, registers, and flags never change. The chip
|
|
485
|
+
is alive (its address bus continues to walk through the dead instruction
|
|
486
|
+
fetch) but the only way out is RESET. Even NMI and IRQ are ignored.
|
|
487
|
+
|
|
488
|
+
These are useful exactly as crash-out markers. In some copy-protection
|
|
489
|
+
schemes, a deliberately-placed KIL after a checksum failure ensures the
|
|
490
|
+
cracker has to manually patch the code rather than letting the program
|
|
491
|
+
fall through to a meaningful error path. In modern emulators, hitting a
|
|
492
|
+
KIL typically pops a debugger.
|
|
493
|
+
|
|
494
|
+
Mnemonics in the wild: `KIL`, `JAM`, `HLT`, `CIM`, `CRASH`. All point at
|
|
495
|
+
the same behavior.
|
|
496
|
+
|
|
497
|
+
## Detailed opcode list
|
|
498
|
+
|
|
499
|
+
### $0B — ANC #imm — AND immediate, copy bit 7 to carry (illegal)
|
|
500
|
+
|
|
501
|
+
**Cycles:** 2
|
|
502
|
+
**Flags:** N Z C
|
|
503
|
+
**Legal:** no
|
|
504
|
+
|
|
505
|
+
Performs `A &= imm` and copies bit 7 of the result into the C flag.
|
|
506
|
+
Leaves the same C as `AND #imm : CMP #$80`, but N and Z come from the AND
|
|
507
|
+
result, which CMP would not give — the two are not identical (an earlier
|
|
508
|
+
version said identical; N is inverted and Z differs, measured in VICE
|
|
509
|
+
x64sc; see the ANC section). The duplicate opcode $2B does the same
|
|
510
|
+
thing. Stable on all NMOS parts.
|
|
511
|
+
|
|
512
|
+
### $2B — ANC #imm — AND immediate, copy bit 7 to carry (illegal alias)
|
|
513
|
+
|
|
514
|
+
**Cycles:** 2
|
|
515
|
+
**Flags:** N Z C
|
|
516
|
+
**Legal:** no
|
|
517
|
+
|
|
518
|
+
Identical to $0B. The 6502 decode matrix maps both $0B and $2B to the
|
|
519
|
+
same micro-operation. Some assemblers emit $0B; others emit $2B; some
|
|
520
|
+
let you choose.
|
|
521
|
+
|
|
522
|
+
### $4B — ALR #imm — AND immediate then LSR (illegal)
|
|
523
|
+
|
|
524
|
+
**Cycles:** 2
|
|
525
|
+
**Flags:** N Z C
|
|
526
|
+
**Legal:** no
|
|
527
|
+
|
|
528
|
+
Computes `A = (A & imm) >> 1`. C receives bit 0 of `A & imm` (the bit
|
|
529
|
+
shifted out). N is always 0 after the LSR. Z reflects the final result.
|
|
530
|
+
Equivalent to `AND #imm : LSR A` but one instruction shorter and faster.
|
|
531
|
+
|
|
532
|
+
Also published as **ASR** in some references. The mnemonic ALR is from
|
|
533
|
+
the Oxyron table.
|
|
534
|
+
|
|
535
|
+
### $6B — ARR #imm — AND immediate then ROR with quirky flags (illegal)
|
|
536
|
+
|
|
537
|
+
**Cycles:** 2
|
|
538
|
+
**Flags:** N Z C V
|
|
539
|
+
**Legal:** no
|
|
540
|
+
|
|
541
|
+
Binary mode: `A = ROR(A & imm)` with C-in shifted into bit 7. The
|
|
542
|
+
output flags do *not* match a simple ROR:
|
|
543
|
+
|
|
544
|
+
- C = bit 6 of the final result
|
|
545
|
+
- V = bit 6 XOR bit 5 of the final result
|
|
546
|
+
|
|
547
|
+
In decimal mode (D=1) the result is BCD-adjusted (+$06 / +$60 fix-ups as
|
|
548
|
+
for ADC), C = 1 iff the high-nibble fix-up fired, N = carry-in, V = bit 6
|
|
549
|
+
XOR bit 5 of the un-adjusted ROR result. Example, measured in VICE x64sc:
|
|
550
|
+
SED CLC LDA #$FF ARR #$60 gives A=$90 C=1 where binary mode gives A=$30
|
|
551
|
+
C=0. (An earlier version of this entry said the decimal-mode C/V equal an
|
|
552
|
+
ADC's; the accumulator itself changes, not only the flags.)
|
|
553
|
+
|
|
554
|
+
Used in CRC and shift-and-detect-pattern routines.
|
|
555
|
+
|
|
556
|
+
### $8B — XAA #imm — Load A and X immediate (unstable)
|
|
557
|
+
|
|
558
|
+
**Cycles:** 2
|
|
559
|
+
**Flags:** N Z
|
|
560
|
+
**Legal:** no
|
|
561
|
+
|
|
562
|
+
`A = (A | magic) & X & imm`. The magic constant is the value the chip's
|
|
563
|
+
internal bus floats to during the operand fetch; values reported for NMOS
|
|
564
|
+
parts include $EE, $EF, $FF and $00, none measured on silicon here. VICE
|
|
565
|
+
(x64sc and x64, 3.10 on this machine) uses $EF, measured: `lda #$00 : ldx
|
|
566
|
+
#$ff : xaa #$ff` leaves A=$EF. The result equals `X & imm` only for the
|
|
567
|
+
bits of `imm` that are set in `A | magic`; with A=$FF preloaded it is
|
|
568
|
+
`X & imm` for every magic value. An earlier revision of this entry said
|
|
569
|
+
magic was $FF on most silicon; none of the cited sources says so and VICE
|
|
570
|
+
does not model it. **Unstable.** Do not use in production.
|
|
571
|
+
|
|
572
|
+
Also known as ANE.
|
|
573
|
+
|
|
574
|
+
### $AB — LAX #imm — Load A and X immediate (unstable)
|
|
575
|
+
|
|
576
|
+
**Cycles:** 2
|
|
577
|
+
**Flags:** N Z
|
|
578
|
+
**Legal:** no
|
|
579
|
+
|
|
580
|
+
Immediate-mode LAX. `A = X = (A | magic) & imm` — not `A = X = imm`. Same
|
|
581
|
+
floating-bus mechanism as XAA, without the X term. VICE uses $EE,
|
|
582
|
+
measured: `lda #$00 : lax #$ff` gives A=X=$EE and `lda #$00 : lax #$55`
|
|
583
|
+
gives $44; it loads `imm` only for the bits set in `A | magic`, so
|
|
584
|
+
preload A=$FF if the instruction cannot be avoided. An earlier revision of
|
|
585
|
+
this entry said it works on most parts; Oxyron's table reports that it
|
|
586
|
+
"loses bits" on the author's own C64-II. **Unstable.** The zero-page and
|
|
587
|
+
absolute LAX forms ($A3/$A7/$AF/$B3/$B7/$BF) are stable; only the
|
|
588
|
+
immediate form is risky.
|
|
589
|
+
|
|
590
|
+
### $CB — AXS #imm — AND A with X, subtract immediate into X (illegal)
|
|
591
|
+
|
|
592
|
+
**Cycles:** 2
|
|
593
|
+
**Flags:** N Z C
|
|
594
|
+
**Legal:** no
|
|
595
|
+
|
|
596
|
+
`X = (A & X) - imm`. The subtraction sets C the same way CMP does (C=1
|
|
597
|
+
if no borrow). Decimal mode is *ignored* — AXS always executes binary
|
|
598
|
+
subtraction. Useful as a fused "mask-and-decrement-X" in tight loops.
|
|
599
|
+
|
|
600
|
+
Also called SBX.
|
|
601
|
+
|
|
602
|
+
### $EB — SBC #imm — Subtract immediate (undocumented alias of $E9)
|
|
603
|
+
|
|
604
|
+
**Cycles:** 2
|
|
605
|
+
**Flags:** N Z C V
|
|
606
|
+
**Legal:** no
|
|
607
|
+
|
|
608
|
+
`A = A - imm - !C`. Identical arithmetic and flags to the official
|
|
609
|
+
`SBC #imm` ($E9), decimal mode included; 2 cycles, measured in VICE x64sc.
|
|
610
|
+
Assemblers never emit it for `sbc #`, so it only appears in hand-assembled
|
|
611
|
+
or obfuscated code. Stable.
|
|
612
|
+
|
|
613
|
+
### $A3 — LAX (zp,X) — Load A and X indirect-X (illegal)
|
|
614
|
+
|
|
615
|
+
**Cycles:** 6
|
|
616
|
+
**Flags:** N Z
|
|
617
|
+
**Legal:** no
|
|
618
|
+
|
|
619
|
+
`A = X = M[ind16(zp+X)]`. Loads through the X-indexed pointer in zero
|
|
620
|
+
page (the classic indirect-X mode). Stable.
|
|
621
|
+
|
|
622
|
+
### $A7 — LAX zp — Load A and X from zero page (illegal)
|
|
623
|
+
|
|
624
|
+
**Cycles:** 3
|
|
625
|
+
**Flags:** N Z
|
|
626
|
+
**Legal:** no
|
|
627
|
+
|
|
628
|
+
`A = X = M[zp]`. The fastest LAX form. Stable. Replaces a `LDA zp : LDX
|
|
629
|
+
zp` pair (6 cycles, 4 bytes) with 3 cycles, 2 bytes.
|
|
630
|
+
|
|
631
|
+
### $AF — LAX abs — Load A and X from absolute (illegal)
|
|
632
|
+
|
|
633
|
+
**Cycles:** 4
|
|
634
|
+
**Flags:** N Z
|
|
635
|
+
**Legal:** no
|
|
636
|
+
|
|
637
|
+
`A = X = M[abs]`. Absolute-addressed LAX. Stable.
|
|
638
|
+
|
|
639
|
+
### $B3 — LAX (zp),Y — Load A and X indirect-Y (illegal)
|
|
640
|
+
|
|
641
|
+
**Cycles:** 5
|
|
642
|
+
**Flags:** N Z
|
|
643
|
+
**Page-cross:** +1
|
|
644
|
+
**Legal:** no
|
|
645
|
+
|
|
646
|
+
`A = X = M[ind16(zp)+Y]`. Indirect-Y LAX. Adds one cycle when the
|
|
647
|
+
indexed read crosses a page boundary. Stable.
|
|
648
|
+
|
|
649
|
+
### $B7 — LAX zp,Y — Load A and X from zp,Y (illegal)
|
|
650
|
+
|
|
651
|
+
**Cycles:** 4
|
|
652
|
+
**Flags:** N Z
|
|
653
|
+
**Legal:** no
|
|
654
|
+
|
|
655
|
+
`A = X = M[zp+Y]`. Y-indexed zero-page LAX. Stable. The 6502 wraps
|
|
656
|
+
within the zero page (zp+Y stays in $00-$FF).
|
|
657
|
+
|
|
658
|
+
### $BF — LAX abs,Y — Load A and X from abs,Y (illegal)
|
|
659
|
+
|
|
660
|
+
**Cycles:** 4
|
|
661
|
+
**Flags:** N Z
|
|
662
|
+
**Page-cross:** +1
|
|
663
|
+
**Legal:** no
|
|
664
|
+
|
|
665
|
+
`A = X = M[abs+Y]`. Stable. +1 cycle on page cross.
|
|
666
|
+
|
|
667
|
+
### $83 — SAX (zp,X) — Store A AND X indirect-X (illegal)
|
|
668
|
+
|
|
669
|
+
**Cycles:** 6
|
|
670
|
+
**Flags:** —
|
|
671
|
+
**Legal:** no
|
|
672
|
+
|
|
673
|
+
`M[ind16(zp+X)] = A & X`. Stores the bitwise AND of A and X. No flags
|
|
674
|
+
affected. Stable.
|
|
675
|
+
|
|
676
|
+
### $87 — SAX zp — Store A AND X to zero page (illegal)
|
|
677
|
+
|
|
678
|
+
**Cycles:** 3
|
|
679
|
+
**Flags:** —
|
|
680
|
+
**Legal:** no
|
|
681
|
+
|
|
682
|
+
`M[zp] = A & X`. The shortest SAX. Stable. Replaces an `STX zp : AND
|
|
683
|
+
#mask : STA zp` sequence when you need a precomputed mask.
|
|
684
|
+
|
|
685
|
+
### $8F — SAX abs — Store A AND X to absolute (illegal)
|
|
686
|
+
|
|
687
|
+
**Cycles:** 4
|
|
688
|
+
**Flags:** —
|
|
689
|
+
**Legal:** no
|
|
690
|
+
|
|
691
|
+
`M[abs] = A & X`. Absolute SAX. Stable.
|
|
692
|
+
|
|
693
|
+
### $97 — SAX zp,Y — Store A AND X to zp,Y (illegal)
|
|
694
|
+
|
|
695
|
+
**Cycles:** 4
|
|
696
|
+
**Flags:** —
|
|
697
|
+
**Legal:** no
|
|
698
|
+
|
|
699
|
+
`M[zp+Y] = A & X`. Y-indexed zero-page SAX. Wraps in zero page. Stable.
|
|
700
|
+
|
|
701
|
+
### $C3 — DCP (zp,X) — Decrement then compare A indirect-X (illegal)
|
|
702
|
+
|
|
703
|
+
**Cycles:** 8
|
|
704
|
+
**Flags:** N Z C
|
|
705
|
+
**Legal:** no
|
|
706
|
+
|
|
707
|
+
`M-- ; sets N Z C from (A - M)`. Stable.
|
|
708
|
+
|
|
709
|
+
### $C7 — DCP zp — Decrement then compare A in zero page (illegal)
|
|
710
|
+
|
|
711
|
+
**Cycles:** 5
|
|
712
|
+
**Flags:** N Z C
|
|
713
|
+
**Legal:** no
|
|
714
|
+
|
|
715
|
+
`M[zp]-- ; sets N Z C from (A - M[zp])`. The most useful DCP form for
|
|
716
|
+
zero-page loop counters. Stable.
|
|
717
|
+
|
|
718
|
+
### $CF — DCP abs — Decrement then compare A absolute (illegal)
|
|
719
|
+
|
|
720
|
+
**Cycles:** 6
|
|
721
|
+
**Flags:** N Z C
|
|
722
|
+
**Legal:** no
|
|
723
|
+
|
|
724
|
+
`M[abs]-- ; sets N Z C from (A - M[abs])`. Stable.
|
|
725
|
+
|
|
726
|
+
### $D3 — DCP (zp),Y — Decrement then compare A indirect-Y (illegal)
|
|
727
|
+
|
|
728
|
+
**Cycles:** 8
|
|
729
|
+
**Flags:** N Z C
|
|
730
|
+
**Legal:** no
|
|
731
|
+
|
|
732
|
+
`M[ind16(zp)+Y]-- ; sets N Z C from (A - M)`. RMW form — page-cross
|
|
733
|
+
penalty is *already included* in the 8-cycle count (RMW always pays
|
|
734
|
+
for both reads). Stable.
|
|
735
|
+
|
|
736
|
+
### $D7 — DCP zp,X — Decrement then compare A zp,X (illegal)
|
|
737
|
+
|
|
738
|
+
**Cycles:** 6
|
|
739
|
+
**Flags:** N Z C
|
|
740
|
+
**Legal:** no
|
|
741
|
+
|
|
742
|
+
`M[zp+X]-- ; sets N Z C from (A - M[zp+X])`. Wraps in zero page. Stable.
|
|
743
|
+
|
|
744
|
+
### $DB — DCP abs,Y — Decrement then compare A abs,Y (illegal)
|
|
745
|
+
|
|
746
|
+
**Cycles:** 7
|
|
747
|
+
**Flags:** N Z C
|
|
748
|
+
**Legal:** no
|
|
749
|
+
|
|
750
|
+
`M[abs+Y]-- ; sets N Z C from (A - M[abs+Y])`. RMW form, no extra
|
|
751
|
+
page-cross penalty (the 7-cycle count is the worst case). Stable.
|
|
752
|
+
|
|
753
|
+
### $DF — DCP abs,X — Decrement then compare A abs,X (illegal)
|
|
754
|
+
|
|
755
|
+
**Cycles:** 7
|
|
756
|
+
**Flags:** N Z C
|
|
757
|
+
**Legal:** no
|
|
758
|
+
|
|
759
|
+
`M[abs+X]-- ; sets N Z C from (A - M[abs+X])`. RMW form. Stable.
|
|
760
|
+
|
|
761
|
+
### $E3 — ISC (zp,X) — Increment then SBC indirect-X (illegal)
|
|
762
|
+
|
|
763
|
+
**Cycles:** 8
|
|
764
|
+
**Flags:** N Z C V
|
|
765
|
+
**Legal:** no
|
|
766
|
+
|
|
767
|
+
`M++ ; A = A - M - (1 - C)`. Sets N, Z, V, C from the SBC. Stable.
|
|
768
|
+
|
|
769
|
+
Also written as ISB or INS in some references.
|
|
770
|
+
|
|
771
|
+
### $E7 — ISC zp — Increment then SBC zero page (illegal)
|
|
772
|
+
|
|
773
|
+
**Cycles:** 5
|
|
774
|
+
**Flags:** N Z C V
|
|
775
|
+
**Legal:** no
|
|
776
|
+
|
|
777
|
+
`M[zp]++ ; A = A - M[zp] - (1 - C)`. Stable.
|
|
778
|
+
|
|
779
|
+
### $EF — ISC abs — Increment then SBC absolute (illegal)
|
|
780
|
+
|
|
781
|
+
**Cycles:** 6
|
|
782
|
+
**Flags:** N Z C V
|
|
783
|
+
**Legal:** no
|
|
784
|
+
|
|
785
|
+
`M[abs]++ ; A = A - M[abs] - (1 - C)`. Stable.
|
|
786
|
+
|
|
787
|
+
### $F3 — ISC (zp),Y — Increment then SBC indirect-Y (illegal)
|
|
788
|
+
|
|
789
|
+
**Cycles:** 8
|
|
790
|
+
**Flags:** N Z C V
|
|
791
|
+
**Legal:** no
|
|
792
|
+
|
|
793
|
+
`M[ind16(zp)+Y]++ ; A = A - M - (1 - C)`. Stable.
|
|
794
|
+
|
|
795
|
+
### $F7 — ISC zp,X — Increment then SBC zp,X (illegal)
|
|
796
|
+
|
|
797
|
+
**Cycles:** 6
|
|
798
|
+
**Flags:** N Z C V
|
|
799
|
+
**Legal:** no
|
|
800
|
+
|
|
801
|
+
`M[zp+X]++ ; A = A - M[zp+X] - (1 - C)`. Wraps in zero page. Stable.
|
|
802
|
+
|
|
803
|
+
### $FB — ISC abs,Y — Increment then SBC abs,Y (illegal)
|
|
804
|
+
|
|
805
|
+
**Cycles:** 7
|
|
806
|
+
**Flags:** N Z C V
|
|
807
|
+
**Legal:** no
|
|
808
|
+
|
|
809
|
+
`M[abs+Y]++ ; A = A - M[abs+Y] - (1 - C)`. Stable.
|
|
810
|
+
|
|
811
|
+
### $FF — ISC abs,X — Increment then SBC abs,X (illegal)
|
|
812
|
+
|
|
813
|
+
**Cycles:** 7
|
|
814
|
+
**Flags:** N Z C V
|
|
815
|
+
**Legal:** no
|
|
816
|
+
|
|
817
|
+
`M[abs+X]++ ; A = A - M[abs+X] - (1 - C)`. Stable.
|
|
818
|
+
|
|
819
|
+
### $03 — SLO (zp,X) — ASL memory then ORA indirect-X (illegal)
|
|
820
|
+
|
|
821
|
+
**Cycles:** 8
|
|
822
|
+
**Flags:** N Z C
|
|
823
|
+
**Legal:** no
|
|
824
|
+
|
|
825
|
+
`M <<= 1 ; A |= M`. C receives the bit shifted out of memory. Stable.
|
|
826
|
+
|
|
827
|
+
### $07 — SLO zp — ASL zero page then ORA (illegal)
|
|
828
|
+
|
|
829
|
+
**Cycles:** 5
|
|
830
|
+
**Flags:** N Z C
|
|
831
|
+
**Legal:** no
|
|
832
|
+
|
|
833
|
+
`M[zp] <<= 1 ; A |= M[zp]`. The fastest SLO form. Common in
|
|
834
|
+
demoscene multiplexer code for shifting a sprite index byte and ORing
|
|
835
|
+
it into a register-image accumulator. Stable.
|
|
836
|
+
|
|
837
|
+
### $0F — SLO abs — ASL absolute then ORA (illegal)
|
|
838
|
+
|
|
839
|
+
**Cycles:** 6
|
|
840
|
+
**Flags:** N Z C
|
|
841
|
+
**Legal:** no
|
|
842
|
+
|
|
843
|
+
`M[abs] <<= 1 ; A |= M[abs]`. Stable.
|
|
844
|
+
|
|
845
|
+
### $13 — SLO (zp),Y — ASL memory then ORA indirect-Y (illegal)
|
|
846
|
+
|
|
847
|
+
**Cycles:** 8
|
|
848
|
+
**Flags:** N Z C
|
|
849
|
+
**Legal:** no
|
|
850
|
+
|
|
851
|
+
`M[ind16(zp)+Y] <<= 1 ; A |= M`. RMW form — page-cross cost already
|
|
852
|
+
included. Stable.
|
|
853
|
+
|
|
854
|
+
### $17 — SLO zp,X — ASL zp,X then ORA (illegal)
|
|
855
|
+
|
|
856
|
+
**Cycles:** 6
|
|
857
|
+
**Flags:** N Z C
|
|
858
|
+
**Legal:** no
|
|
859
|
+
|
|
860
|
+
`M[zp+X] <<= 1 ; A |= M[zp+X]`. Wraps in zero page. Stable.
|
|
861
|
+
|
|
862
|
+
### $1B — SLO abs,Y — ASL abs,Y then ORA (illegal)
|
|
863
|
+
|
|
864
|
+
**Cycles:** 7
|
|
865
|
+
**Flags:** N Z C
|
|
866
|
+
**Legal:** no
|
|
867
|
+
|
|
868
|
+
`M[abs+Y] <<= 1 ; A |= M[abs+Y]`. Stable.
|
|
869
|
+
|
|
870
|
+
### $1F — SLO abs,X — ASL abs,X then ORA (illegal)
|
|
871
|
+
|
|
872
|
+
**Cycles:** 7
|
|
873
|
+
**Flags:** N Z C
|
|
874
|
+
**Legal:** no
|
|
875
|
+
|
|
876
|
+
`M[abs+X] <<= 1 ; A |= M[abs+X]`. Stable.
|
|
877
|
+
|
|
878
|
+
### $23 — RLA (zp,X) — ROL memory then AND indirect-X (illegal)
|
|
879
|
+
|
|
880
|
+
**Cycles:** 8
|
|
881
|
+
**Flags:** N Z C
|
|
882
|
+
**Legal:** no
|
|
883
|
+
|
|
884
|
+
`M = ROL(M) ; A &= M`. Carry rotates through bit 0 of M. Stable.
|
|
885
|
+
|
|
886
|
+
### $27 — RLA zp — ROL zero page then AND (illegal)
|
|
887
|
+
|
|
888
|
+
**Cycles:** 5
|
|
889
|
+
**Flags:** N Z C
|
|
890
|
+
**Legal:** no
|
|
891
|
+
|
|
892
|
+
`M[zp] = ROL(M[zp]) ; A &= M[zp]`. The fast RLA form. Used in
|
|
893
|
+
multiplexer mask-rotation. Stable.
|
|
894
|
+
|
|
895
|
+
### $2F — RLA abs — ROL absolute then AND (illegal)
|
|
896
|
+
|
|
897
|
+
**Cycles:** 6
|
|
898
|
+
**Flags:** N Z C
|
|
899
|
+
**Legal:** no
|
|
900
|
+
|
|
901
|
+
`M[abs] = ROL(M[abs]) ; A &= M[abs]`. Stable.
|
|
902
|
+
|
|
903
|
+
### $33 — RLA (zp),Y — ROL memory then AND indirect-Y (illegal)
|
|
904
|
+
|
|
905
|
+
**Cycles:** 8
|
|
906
|
+
**Flags:** N Z C
|
|
907
|
+
**Legal:** no
|
|
908
|
+
|
|
909
|
+
`M[ind16(zp)+Y] = ROL(M) ; A &= M`. RMW form — page-cross cost already
|
|
910
|
+
included; cycles measured in VICE x64sc; no page-cross penalty (RMW).
|
|
911
|
+
Stable. (Omitted from an earlier revision of this page.)
|
|
912
|
+
|
|
913
|
+
### $37 — RLA zp,X — ROL zp,X then AND (illegal)
|
|
914
|
+
|
|
915
|
+
**Cycles:** 6
|
|
916
|
+
**Flags:** N Z C
|
|
917
|
+
**Legal:** no
|
|
918
|
+
|
|
919
|
+
`M[zp+X] = ROL(M[zp+X]) ; A &= M[zp+X]`. Wraps in zero page. Stable.
|
|
920
|
+
|
|
921
|
+
### $3B — RLA abs,Y — ROL abs,Y then AND (illegal)
|
|
922
|
+
|
|
923
|
+
**Cycles:** 7
|
|
924
|
+
**Flags:** N Z C
|
|
925
|
+
**Legal:** no
|
|
926
|
+
|
|
927
|
+
`M[abs+Y] = ROL(M[abs+Y]) ; A &= M[abs+Y]`. Stable.
|
|
928
|
+
|
|
929
|
+
### $3F — RLA abs,X — ROL abs,X then AND (illegal)
|
|
930
|
+
|
|
931
|
+
**Cycles:** 7
|
|
932
|
+
**Flags:** N Z C
|
|
933
|
+
**Legal:** no
|
|
934
|
+
|
|
935
|
+
`M[abs+X] = ROL(M[abs+X]) ; A &= M[abs+X]`. Stable.
|
|
936
|
+
|
|
937
|
+
### $43 — SRE (zp,X) — LSR memory then EOR indirect-X (illegal)
|
|
938
|
+
|
|
939
|
+
**Cycles:** 8
|
|
940
|
+
**Flags:** N Z C
|
|
941
|
+
**Legal:** no
|
|
942
|
+
|
|
943
|
+
`M >>= 1 ; A ^= M`. C receives bit 0 of M before the shift. Stable.
|
|
944
|
+
|
|
945
|
+
### $47 — SRE zp — LSR zero page then EOR (illegal)
|
|
946
|
+
|
|
947
|
+
**Cycles:** 5
|
|
948
|
+
**Flags:** N Z C
|
|
949
|
+
**Legal:** no
|
|
950
|
+
|
|
951
|
+
`M[zp] >>= 1 ; A ^= M[zp]`. Stable.
|
|
952
|
+
|
|
953
|
+
### $4F — SRE abs — LSR absolute then EOR (illegal)
|
|
954
|
+
|
|
955
|
+
**Cycles:** 6
|
|
956
|
+
**Flags:** N Z C
|
|
957
|
+
**Legal:** no
|
|
958
|
+
|
|
959
|
+
`M[abs] >>= 1 ; A ^= M[abs]`. Stable.
|
|
960
|
+
|
|
961
|
+
### $53 — SRE (zp),Y — LSR memory then EOR indirect-Y (illegal)
|
|
962
|
+
|
|
963
|
+
**Cycles:** 8
|
|
964
|
+
**Flags:** N Z C
|
|
965
|
+
**Legal:** no
|
|
966
|
+
|
|
967
|
+
`M[ind16(zp)+Y] >>= 1 ; A ^= M`. RMW form — page-cross cost already
|
|
968
|
+
included; cycles measured in VICE x64sc; no page-cross penalty (RMW).
|
|
969
|
+
Stable. (Omitted from an earlier revision of this page.)
|
|
970
|
+
|
|
971
|
+
### $57 — SRE zp,X — LSR zp,X then EOR (illegal)
|
|
972
|
+
|
|
973
|
+
**Cycles:** 6
|
|
974
|
+
**Flags:** N Z C
|
|
975
|
+
**Legal:** no
|
|
976
|
+
|
|
977
|
+
`M[zp+X] >>= 1 ; A ^= M[zp+X]`. Wraps in zero page. Cycles measured in
|
|
978
|
+
VICE x64sc; no page-cross penalty (RMW). Stable. (Omitted from an earlier
|
|
979
|
+
revision of this page.)
|
|
980
|
+
|
|
981
|
+
### $5B — SRE abs,Y — LSR abs,Y then EOR (illegal)
|
|
982
|
+
|
|
983
|
+
**Cycles:** 7
|
|
984
|
+
**Flags:** N Z C
|
|
985
|
+
**Legal:** no
|
|
986
|
+
|
|
987
|
+
`M[abs+Y] >>= 1 ; A ^= M[abs+Y]`. Cycles measured in VICE x64sc; no
|
|
988
|
+
page-cross penalty (RMW). Stable. (Omitted from an earlier revision of
|
|
989
|
+
this page.)
|
|
990
|
+
|
|
991
|
+
### $5F — SRE abs,X — LSR abs,X then EOR (illegal)
|
|
992
|
+
|
|
993
|
+
**Cycles:** 7
|
|
994
|
+
**Flags:** N Z C
|
|
995
|
+
**Legal:** no
|
|
996
|
+
|
|
997
|
+
`M[abs+X] >>= 1 ; A ^= M[abs+X]`. Stable.
|
|
998
|
+
|
|
999
|
+
### $63 — RRA (zp,X) — ROR memory then ADC indirect-X (illegal)
|
|
1000
|
+
|
|
1001
|
+
**Cycles:** 8
|
|
1002
|
+
**Flags:** N Z C V
|
|
1003
|
+
**Legal:** no
|
|
1004
|
+
|
|
1005
|
+
`M = ROR(M) ; A = A + M + C`. Sets V from the ADC. Stable.
|
|
1006
|
+
|
|
1007
|
+
### $67 — RRA zp — ROR zero page then ADC (illegal)
|
|
1008
|
+
|
|
1009
|
+
**Cycles:** 5
|
|
1010
|
+
**Flags:** N Z C V
|
|
1011
|
+
**Legal:** no
|
|
1012
|
+
|
|
1013
|
+
`M[zp] = ROR(M[zp]) ; A = A + M[zp] + C`. Stable.
|
|
1014
|
+
|
|
1015
|
+
### $6F — RRA abs — ROR absolute then ADC (illegal)
|
|
1016
|
+
|
|
1017
|
+
**Cycles:** 6
|
|
1018
|
+
**Flags:** N Z C V
|
|
1019
|
+
**Legal:** no
|
|
1020
|
+
|
|
1021
|
+
`M[abs] = ROR(M[abs]) ; A = A + M[abs] + C`. Stable.
|
|
1022
|
+
|
|
1023
|
+
### $73 — RRA (zp),Y — ROR memory then ADC indirect-Y (illegal)
|
|
1024
|
+
|
|
1025
|
+
**Cycles:** 8
|
|
1026
|
+
**Flags:** N Z C V
|
|
1027
|
+
**Legal:** no
|
|
1028
|
+
|
|
1029
|
+
`M[ind16(zp)+Y] = ROR(M) ; A = A + M + C`. RMW form — page-cross cost
|
|
1030
|
+
already included; cycles measured in VICE x64sc; no page-cross penalty
|
|
1031
|
+
(RMW). Stable. (Omitted from an earlier revision of this page.)
|
|
1032
|
+
|
|
1033
|
+
### $77 — RRA zp,X — ROR zp,X then ADC (illegal)
|
|
1034
|
+
|
|
1035
|
+
**Cycles:** 6
|
|
1036
|
+
**Flags:** N Z C V
|
|
1037
|
+
**Legal:** no
|
|
1038
|
+
|
|
1039
|
+
`M[zp+X] = ROR(M[zp+X]) ; A = A + M[zp+X] + C`. Wraps in zero page.
|
|
1040
|
+
Cycles measured in VICE x64sc; no page-cross penalty (RMW). Stable.
|
|
1041
|
+
(Omitted from an earlier revision of this page.)
|
|
1042
|
+
|
|
1043
|
+
### $7B — RRA abs,Y — ROR abs,Y then ADC (illegal)
|
|
1044
|
+
|
|
1045
|
+
**Cycles:** 7
|
|
1046
|
+
**Flags:** N Z C V
|
|
1047
|
+
**Legal:** no
|
|
1048
|
+
|
|
1049
|
+
`M[abs+Y] = ROR(M[abs+Y]) ; A = A + M[abs+Y] + C`. Cycles measured in
|
|
1050
|
+
VICE x64sc; no page-cross penalty (RMW). Stable. (Omitted from an earlier
|
|
1051
|
+
revision of this page.)
|
|
1052
|
+
|
|
1053
|
+
### $7F — RRA abs,X — ROR abs,X then ADC (illegal)
|
|
1054
|
+
|
|
1055
|
+
**Cycles:** 7
|
|
1056
|
+
**Flags:** N Z C V
|
|
1057
|
+
**Legal:** no
|
|
1058
|
+
|
|
1059
|
+
`M[abs+X] = ROR(M[abs+X]) ; A = A + M[abs+X] + C`. Cycles measured in
|
|
1060
|
+
VICE x64sc; no page-cross penalty (RMW). Stable. (Omitted from an earlier
|
|
1061
|
+
revision of this page.)
|
|
1062
|
+
|
|
1063
|
+
### $93 — AHX (zp),Y — Store A AND X AND (H+1) indirect-Y (unstable)
|
|
1064
|
+
|
|
1065
|
+
**Cycles:** 6
|
|
1066
|
+
**Flags:** —
|
|
1067
|
+
**Legal:** no
|
|
1068
|
+
|
|
1069
|
+
`M[ind16(zp)+Y] = A & X & (H+1)` where H is the high byte of the target
|
|
1070
|
+
address. **Unstable** — the `H+1` term comes from an internal half-cycle
|
|
1071
|
+
race, and on page-cross the high byte feedback corrupts the result.
|
|
1072
|
+
|
|
1073
|
+
Also called SHA or AXA.
|
|
1074
|
+
|
|
1075
|
+
### $9F — AHX abs,Y — Store A AND X AND (H+1) abs,Y (unstable)
|
|
1076
|
+
|
|
1077
|
+
**Cycles:** 5
|
|
1078
|
+
**Flags:** —
|
|
1079
|
+
**Legal:** no
|
|
1080
|
+
|
|
1081
|
+
`M[abs+Y] = A & X & (H+1)`. Same instability as $93. **Unstable.**
|
|
1082
|
+
|
|
1083
|
+
### $9B — TAS abs,Y — Transfer A AND X to S, store A AND X AND (H+1) (unstable)
|
|
1084
|
+
|
|
1085
|
+
**Cycles:** 5
|
|
1086
|
+
**Flags:** —
|
|
1087
|
+
**Legal:** no
|
|
1088
|
+
|
|
1089
|
+
`S = A & X ; M[abs+Y] = A & X & (H+1)`. Combines an AHX with a stack
|
|
1090
|
+
pointer overwrite. **Unstable** — same `H+1` race as AHX, plus the
|
|
1091
|
+
side effect of clobbering S.
|
|
1092
|
+
|
|
1093
|
+
Also called SHS or XAS.
|
|
1094
|
+
|
|
1095
|
+
### $BB — LAS abs,Y — Load A, X, and S from memory AND S
|
|
1096
|
+
|
|
1097
|
+
**Cycles:** 4
|
|
1098
|
+
**Flags:** N Z
|
|
1099
|
+
**Page-cross:** +1
|
|
1100
|
+
**Legal:** no
|
|
1101
|
+
|
|
1102
|
+
`A = X = S = M[abs+Y] & S`. Reads memory ANDed with the stack pointer
|
|
1103
|
+
and writes the result into A, X, and S simultaneously. Page-cross
|
|
1104
|
+
penalty applies. An earlier version of this page classed it unstable; the
|
|
1105
|
+
cited tables do not, and Oxyron notes only that one source called it
|
|
1106
|
+
"probably unreliable". Measured in VICE x64sc: S=$F0, M=$3F gives
|
|
1107
|
+
A=X=S=$30, N and Z from the result, 4 cycles, 5 on page cross. It writes
|
|
1108
|
+
S — restore the stack pointer before the next push or return.
|
|
1109
|
+
|
|
1110
|
+
Also called LAR.
|
|
1111
|
+
|
|
1112
|
+
### $9E — SHX abs,Y — Store X AND (H+1) abs,Y (unstable)
|
|
1113
|
+
|
|
1114
|
+
**Cycles:** 5
|
|
1115
|
+
**Flags:** —
|
|
1116
|
+
**Legal:** no
|
|
1117
|
+
|
|
1118
|
+
`M[abs+Y] = X & (H+1)` where H is the high byte of the target address.
|
|
1119
|
+
Same `H+1` race as AHX. **Unstable** on page cross.
|
|
1120
|
+
|
|
1121
|
+
Also called SXA or XAS.
|
|
1122
|
+
|
|
1123
|
+
### $9C — SHY abs,X — Store Y AND (H+1) abs,X (unstable)
|
|
1124
|
+
|
|
1125
|
+
**Cycles:** 5
|
|
1126
|
+
**Flags:** —
|
|
1127
|
+
**Legal:** no
|
|
1128
|
+
|
|
1129
|
+
`M[abs+X] = Y & (H+1)`. Same `H+1` race as AHX. **Unstable** on page
|
|
1130
|
+
cross.
|
|
1131
|
+
|
|
1132
|
+
Also called SYA.
|
|
1133
|
+
|
|
1134
|
+
### $02 — KIL — Halt CPU (illegal)
|
|
1135
|
+
|
|
1136
|
+
**Cycles:** —
|
|
1137
|
+
**Flags:** —
|
|
1138
|
+
**Legal:** no
|
|
1139
|
+
|
|
1140
|
+
Halts the CPU. The PC freezes. IRQ and NMI are ignored. The only way out
|
|
1141
|
+
is RESET. Eleven other opcodes ($12, $22, $32, $42, $52, $62, $72, $92,
|
|
1142
|
+
$B2, $D2, $F2) do the same thing. Also called JAM, HLT, CIM, or CRASH
|
|
1143
|
+
in different references.
|
|
1144
|
+
|
|
1145
|
+
## Demo-scene uses
|
|
1146
|
+
|
|
1147
|
+
The illegal opcodes earn their keep in cycle-tight C64 code. Some
|
|
1148
|
+
specific patterns that show up across decades of demos and games:
|
|
1149
|
+
|
|
1150
|
+
### LAX for table-driven loops
|
|
1151
|
+
|
|
1152
|
+
When a routine needs to read a byte from a table and use it as both a
|
|
1153
|
+
data value and a future index:
|
|
1154
|
+
|
|
1155
|
+
```asm
|
|
1156
|
+
lax sprite_y_table,x ; A = X = next sprite Y
|
|
1157
|
+
sta $D001 ; sprite 0 Y register
|
|
1158
|
+
; X is now the same value, ready for indexing into a control table
|
|
1159
|
+
ldy multiplex_table,x
|
|
1160
|
+
```
|
|
1161
|
+
|
|
1162
|
+
This saves the second LDX (or LDA) load and frees an instruction slot in
|
|
1163
|
+
a badline-adjacent raster sequence.
|
|
1164
|
+
|
|
1165
|
+
### SAX for masked stores
|
|
1166
|
+
|
|
1167
|
+
When you have a precomputed bitmask in X and need to write a masked
|
|
1168
|
+
version of A to memory without disturbing either register:
|
|
1169
|
+
|
|
1170
|
+
```asm
|
|
1171
|
+
.const cell = 40*12 + 20 // colour-RAM cell for row 12, column 20
|
|
1172
|
+
ldx #$0F // nibble mask
|
|
1173
|
+
lda color_byte
|
|
1174
|
+
sax $D800+cell // SAX abs ($8F, 3 bytes, 4 cycles): store color_byte & $0F
|
|
1175
|
+
```
|
|
1176
|
+
|
|
1177
|
+
Color RAM is nibble-wide on the C64, and SAX abs makes the masked store
|
|
1178
|
+
one 3-byte/4-cycle instruction against `AND #$0F : STA abs` at 5 bytes/6
|
|
1179
|
+
cycles. SAX has no abs,Y or abs,X form; the $9F slot that abs,Y would
|
|
1180
|
+
occupy is SHA/AHX, which stores A & X & (high byte + 1) — measured in
|
|
1181
|
+
VICE x64sc: $9F to $0300 with A=$FF, X=$0F stores $04, not $0F. If the
|
|
1182
|
+
cell has to be indexed, the index has to live in the address, not in Y:
|
|
1183
|
+
with X holding the mask, SAX can only be unindexed (abs/zp) or zp,Y, and
|
|
1184
|
+
zp,Y cannot reach $D800 at all. An earlier version of this page wrote
|
|
1185
|
+
`sax $D800,y`, which does not assemble (KickAssembler 5.25: "'sax'
|
|
1186
|
+
doesn't support ABSOLUTEY mode").
|
|
1187
|
+
|
|
1188
|
+
### SLO/RLA for sprite multiplexers
|
|
1189
|
+
|
|
1190
|
+
A multiplexer needs to shift a "which sprites are active this slot" byte
|
|
1191
|
+
and OR new sprite enables into a register-image table:
|
|
1192
|
+
|
|
1193
|
+
```asm
|
|
1194
|
+
; flag byte in $FB tracks sprites that just turned on
|
|
1195
|
+
slo $FB ; shift flag byte, OR shifted bit into A
|
|
1196
|
+
sta sprite_enable_image
|
|
1197
|
+
```
|
|
1198
|
+
|
|
1199
|
+
Equivalent to `asl $FB : lda $FB : ora ...` in 8+ cycles (an earlier
|
|
1200
|
+
version said 7+; ASL zp is 5 and LDA zp 3), but SLO fuses it to 5.
|
|
1201
|
+
|
|
1202
|
+
RLA is the AND-rotate version, used when rotating a sprite priority mask
|
|
1203
|
+
into a `$D01B`-bound register image.
|
|
1204
|
+
|
|
1205
|
+
### DCP for count-and-test loops
|
|
1206
|
+
|
|
1207
|
+
A scrolling routine running 8 cycles per character can decrement an
|
|
1208
|
+
on-screen counter and branch in one instruction:
|
|
1209
|
+
|
|
1210
|
+
```asm
|
|
1211
|
+
; A holds "what value triggers a wrap"
|
|
1212
|
+
loop:
|
|
1213
|
+
; ... raster-bar work ...
|
|
1214
|
+
dcp scroll_phase
|
|
1215
|
+
bne loop
|
|
1216
|
+
```
|
|
1217
|
+
|
|
1218
|
+
This is 8 cycles per iteration (`dcp` zp 5 + taken `bne` 3) vs. 13 for
|
|
1219
|
+
`dec scroll_phase : lda #wrap_value : cmp scroll_phase : bne loop` (an
|
|
1220
|
+
earlier version said 5 vs. ~7, which omitted the branch on one side and
|
|
1221
|
+
undercounted the other). All counts measured in VICE x64sc.
|
|
1222
|
+
|
|
1223
|
+
### NOPs for timing alignment
|
|
1224
|
+
|
|
1225
|
+
Cycle-exact raster code regularly needs padding of a few cycles to align
|
|
1226
|
+
register writes to the badline boundary. An earlier version of this page
|
|
1227
|
+
recommended the 1-byte $1A/$3A/$5A/$7A/$DA/$FA undocumented NOPs for this;
|
|
1228
|
+
that was wrong — they are exactly the shape of the legal `nop` ($EA,
|
|
1229
|
+
1 byte, 2 cycles; all seven measured 2 cycles in VICE x64sc) and buy
|
|
1230
|
+
nothing except a 65C02 incompatibility. No 6502 instruction takes fewer
|
|
1231
|
+
than 2 cycles, so a 1-cycle adjustment is made by swapping a 2-cycle
|
|
1232
|
+
instruction for a 3-cycle one, and that is where the illegal family earns
|
|
1233
|
+
its place: `nop zp` ($04, 2 bytes, 3 cycles) pads three cycles and leaves
|
|
1234
|
+
N, V and Z untouched (measured: P unchanged, where `bit zp` at the same
|
|
1235
|
+
point rewrote all three), and it is a byte shorter than `jmp *+3`.
|
|
1236
|
+
`nop #imm` ($80, 2 bytes, 2 cycles) is the no-side-effect 2-byte pad, and
|
|
1237
|
+
the one-byte skip. For 4 cycles two legal `nop`s (2 bytes) are already the
|
|
1238
|
+
smallest form; `nop abs` ($0C, 3 bytes, 4 cycles) is a 2-byte skip, not a
|
|
1239
|
+
pad. Prefer `bit $00` only when you can afford the flag change; it is
|
|
1240
|
+
3 cycles, 2 bytes, and legal.
|
|
1241
|
+
|
|
1242
|
+
### AXS for fused mask-and-loop
|
|
1243
|
+
|
|
1244
|
+
A bit-mask-then-counter pattern: `X = (A & X) - 1; if X != 0 goto loop`
|
|
1245
|
+
becomes a 5-cycle two-instruction loop body (2 for `axs #1` + 3 for the
|
|
1246
|
+
taken branch; an earlier version said 4 and 9):
|
|
1247
|
+
|
|
1248
|
+
```asm
|
|
1249
|
+
axs #1
|
|
1250
|
+
bne loop
|
|
1251
|
+
```
|
|
1252
|
+
|
|
1253
|
+
vs. `txa : and #mask : tax : dex : bne loop` (11 cycles, measured in VICE
|
|
1254
|
+
x64sc).
|
|
1255
|
+
|
|
1256
|
+
### ANC for sign-to-carry
|
|
1257
|
+
|
|
1258
|
+
When the sign of a masked value is needed in C for the code that follows,
|
|
1259
|
+
ANC folds the `CMP #$80` away:
|
|
1260
|
+
|
|
1261
|
+
```asm
|
|
1262
|
+
anc #$80 // A &= $80 ; C = N = bit 7 of the result
|
|
1263
|
+
ror // shifts the sign in: 4 cycles, where and/cmp/ror is 6
|
|
1264
|
+
```
|
|
1265
|
+
|
|
1266
|
+
For a plain branch on the sign, use the legal `and #$80 : bmi`:
|
|
1267
|
+
`anc #$80 : bcs` takes the same branch at the same cost and gives up CMOS
|
|
1268
|
+
compatibility for nothing. (The earlier example here, `anc #$80 : bcs
|
|
1269
|
+
negative`, was sold as saving a compare; AND sets N, so no compare was
|
|
1270
|
+
ever needed.)
|
|
1271
|
+
|
|
1272
|
+
## Pitfalls
|
|
1273
|
+
|
|
1274
|
+
- **Revision-dependence**: the unstable illegal opcodes (XAA $8B, LAX
|
|
1275
|
+
immediate $AB, AHX $93/$9F, TAS $9B, SHX $9E, SHY $9C) give different
|
|
1276
|
+
results across 6510 production runs and even between cold and warm
|
|
1277
|
+
silicon. Test on multiple real machines before relying on them — and
|
|
1278
|
+
ideally don't. Emulators often pick *one* behavior and call it "the"
|
|
1279
|
+
behavior, which masks the real-hardware variance.
|
|
1280
|
+
- **Not portable to 65C02**: the CMOS-revision 6502 (Apple //c, Apple
|
|
1281
|
+
//e Enhanced, BBC Master) implements
|
|
1282
|
+
almost every illegal opcode as a NOP of varying byte/cycle counts.
|
|
1283
|
+
Code that compiles for the C64 with illegal opcodes will not run on
|
|
1284
|
+
any 65C02-based machine. The same applies to the 65816 (Apple IIGS,
|
|
1285
|
+
SNES, SuperCPU).
|
|
1286
|
+
- **Assembler-dependent mnemonics**: different references use different
|
|
1287
|
+
mnemonics for the same opcode ($87-family store: SAX vs. AXS vs. AAX;
|
|
1288
|
+
$CB subtract: AXS vs. SBX; $AB: LAX #imm vs. LXA; AHX vs. SHA vs. AXA;
|
|
1289
|
+
KIL vs. JAM vs. HLT vs. CIM). Always
|
|
1290
|
+
consult your assembler's documentation, and prefer the Oxyron names
|
|
1291
|
+
for portability between code shared with other coders.
|
|
1292
|
+
- **3-cycle and 4-cycle NOPs perform a memory read**: `NOP zp`, `NOP
|
|
1293
|
+
abs`, `NOP abs,X` *do* drive an address-bus read of the operand.
|
|
1294
|
+
Harmless in RAM, but the read reaches memory-mapped I/O exactly as an
|
|
1295
|
+
`LDA` would. `NOP $D019` is harmless (a read of the VIC interrupt
|
|
1296
|
+
register acknowledges nothing; only a write does), but `NOP $DC0D` or
|
|
1297
|
+
`NOP $DD0D` clears the CIA's pending interrupt flags: after a Timer A
|
|
1298
|
+
underflow, `.byte $0C,$0D,$DC` left a following `LDA $DC0D` reading $00
|
|
1299
|
+
where the control read $01, and `NOP abs,X` ($1C) did the same
|
|
1300
|
+
(measured in VICE x64sc). `NOP $D41B` does not disturb the SID: voice
|
|
1301
|
+
3's OSC3 ramp advanced identically across sixteen `NOP $D41B` and
|
|
1302
|
+
sixteen `NOP` reads of RAM (measured in VICE x64sc reSID); its only
|
|
1303
|
+
visible effect is the one any read of $D419-$D41C has, refreshing the
|
|
1304
|
+
value the write-only SID registers read back (see
|
|
1305
|
+
c64-registers-reference). An earlier revision of this page said
|
|
1306
|
+
`NOP $D41B` "resets some internal state"; nothing in the SID does that
|
|
1307
|
+
on a read.
|
|
1308
|
+
- **KIL is one-way**: $02 and its siblings hang the CPU until reset.
|
|
1309
|
+
This is occasionally weaponized in copy protection, but in normal
|
|
1310
|
+
code, hitting a KIL means execution has gone wrong (corrupted PC,
|
|
1311
|
+
errant indirect jump, mistyped opcode). Most emulators will pop a
|
|
1312
|
+
debugger on KIL — VICE in particular shows a "JAM" dialog.
|
|
1313
|
+
- **ARR's flags never match ROR's, and in decimal mode neither does the
|
|
1314
|
+
result**: in binary mode `ARR #imm` leaves the same accumulator as
|
|
1315
|
+
`AND #imm : ROR A` but C is bit 6 of the result and V is bit 6 XOR
|
|
1316
|
+
bit 5; in decimal mode the accumulator is BCD-adjusted as well and N
|
|
1317
|
+
holds the carry-in. An earlier version said the flags matched in
|
|
1318
|
+
decimal mode — the reverse of what VICE x64sc measures.
|
|
1319
|
+
- **AXS ignores decimal mode**: AXS ($CB) is the *only* 6502 instruction
|
|
1320
|
+
with subtraction that does not honor the D flag. The result is always
|
|
1321
|
+
binary regardless of D=0 or D=1. Most other illegal opcodes that
|
|
1322
|
+
involve ADC/SBC (RRA, ISC) *do* honor decimal mode.
|
|
1323
|
+
- **RMW forms always pay the page-cross cost**: SLO/RLA/SRE/RRA/DCP/ISC
|
|
1324
|
+
in their abs,X / abs,Y / (zp),Y modes always take the worst-case
|
|
1325
|
+
cycle count (7 or 8) — there is no page-cross saving on RMW
|
|
1326
|
+
instructions, illegal or otherwise.
|
|
1327
|
+
- **Some assemblers reject illegal opcodes**: acme requires `!cpu 6510`
|
|
1328
|
+
(or `--cpu 6510`); ca65 requires `.setcpu "6502X"` or `--cpu 6502X` —
|
|
1329
|
+
an earlier version of this page said ca65 accepts them by default; it
|
|
1330
|
+
does not, and reports `':' expected` on every illegal mnemonic
|
|
1331
|
+
(measured with ca65 V2.18 as the binary reports it, Homebrew cc65
|
|
1332
|
+
2.19). KickAssembler accepts them with no directive (its default
|
|
1333
|
+
`.cpu _6502` includes them; measured with 5.25, which has no
|
|
1334
|
+
`kil`/`jam` mnemonic). dasm (`processor 6502`) and xa65
|
|
1335
|
+
(`--no-undefined-opcodes`) are not installed here and those two claims
|
|
1336
|
+
are not measured. Even with the CPU set, spellings differ: acme wants
|
|
1337
|
+
`asr` where Oxyron says ALR, and ca65 wants `axs` where some tables
|
|
1338
|
+
say SBX (both measured). Check your toolchain.
|
|
1339
|
+
- **VICE accuracy**: VICE's `x64sc` cycle-exact emulator implements all
|
|
1340
|
+
illegal opcodes; for the unstable ones it picks one fixed behaviour
|
|
1341
|
+
(XAA magic `$EF`, LAX #imm `$EE` — measured above), not a
|
|
1342
|
+
configurable model as an earlier version of this bullet said. Whether
|
|
1343
|
+
the faster `x64` differs from `x64sc` on them was not measured here.
|
|
1344
|
+
Use `x64sc` for any code that relies on illegal opcodes.
|
|
1345
|
+
|
|
1346
|
+
## Sources
|
|
1347
|
+
|
|
1348
|
+
- Oxyron (Graham), "6502/6510/8500/8502 Opcodes" — https://www.oxyron.de/html/opcodes02.html (page heading and credit as fetched 2026-09-22; an earlier version of this line called it "Frodo's 6502 opcode table")
|
|
1349
|
+
- Masswerk (Norbert Landsteiner), "6502 illegal opcodes" — https://www.masswerk.at/nowgobang/2021/6502-illegal-opcodes
|
|
1350
|
+
- NESdev wiki, "CPU unofficial opcodes" — https://www.nesdev.org/wiki/CPU_unofficial_opcodes
|
|
1351
|
+
- Pagetable / c64ref opcode reference — https://www.pagetable.com/c64ref/6502/
|
|
1352
|
+
|
|
1353
|
+
<!-- doc-type: hardware-reference -->
|