Skip to content

6502 Indexed Indirect Addressing Guide

This article examines indexed indirect addressing within 6502 assembly, an uncommon but powerful addressing mode that proves useful when creating coordinated sprite movement patterns. While most tutorials mention this mode only briefly, practical applications exist that justify understanding its operation thoroughly.

The Challenge

When working with sprite MSB (Most Significant Bit) values inside NMI handlers, keeping CPU cycle usage low becomes critical. The VIC-II chip’s MSB register at $D010 controls the ninth bit of horizontal position for all eight hardware sprites, and modifying it mid-frame requires precise timing. The objective is updating MSB states without conditional branching within the interrupt routines, as branches introduce variable cycle counts that can destabilize raster timing.

The Approach

Instead of evaluating conditions inside NMI handlers, all logic runs beforehand during the main loop when timing is less constrained. The computed results get written directly as ORA or AND instructions along with the correct bitmasks, effectively pre-calculating which bits need modification.

  • Clearing the MSB uses: AND #%10111111 — this mask preserves all bits except bit 6
  • Setting the MSB uses: ORA #%01000000 — this sets bit 6 while preserving other bits

The specific bit position depends on which sprite is being manipulated; the examples above target sprite 6.

How It Works

Raster interrupt handlers modify code within NMI handlers through indexed indirect addressing. This method writes to RAM addresses that vary based on the current loop iteration, enabling a single code path to update multiple targets. Such scenarios represent the perfect application for this addressing mode, which was likely designed with exactly this kind of table-driven operation in mind.

The indexed indirect mode uses zero page locations as pointers, with the X register providing an offset into a table of pointers. This double indirection enables powerful abstractions at the cost of some setup complexity.

Considerations

  • Consumes 12 zero page locations for storing address vectors, representing significant zero page real estate in memory-constrained applications
  • Requires setup code to populate addresses in low/high byte order, adding initialization overhead
  • Delivers better cycle efficiency than alternative methods despite setup overhead, particularly when the same addresses are written repeatedly across multiple frames
  • Self-modifying code alternatives exist but introduce cache-related complications on some accelerator hardware

This addressing mode works best for rapid loops writing to absolute addresses that change each iteration. Such requirements appear rarely in most programming scenarios, which explains why tutorials often gloss over indexed indirect addressing. However, when the situation calls for it, no other approach matches its elegance and efficiency.

See also: ORA bit-testing techniques · undocumented opcodes · assembly interrupt setup · C64 development tools overview