In the 8-bit PC era, graphics hardware lacked modern features like texture mappers or blitters, forcing programmers to manually move every byte of a screen buffer to render a single frame. To make a side-scrolling game playable on a 6809 processor, a developer moved from a naive row-copy loop taking 157 cycles to a specialized stack-based hack that executed the same operation in just 56 cycles.

The Hardware Constraint

During the 1980s, PC graphics hardware provided almost no assistance in moving data. To display a side-scroller, a programmer had to copy 28x28 pixel tiles into a 320x240 screen buffer byte by byte. Because the screen buffer was wider than the tiles, each row copy required a specific memory offset calculation to advance the destination pointer.

Assembly code listing showing early graphics hardware logic
An early example of assembly code used to manage graphics hardware constraints.blog.moertel.com

This screenshot illustrates the manual memory management required in the 8-bit era.

“I had managed to harness every single available register on the machin”

— A Great Old-Timey Game-Programming Hack - Tom Moertel’s Blog

Iterative Assembly Optimizations

The first optimization involved unrolling the inner loop to eliminate the overhead of the 7-count loop used to copy a row's words. This reduced the cycle count from 157 to 120, a 30% speed-up.

Cycle Counts for Row Copying: Naive Loop 157 cycles; Optimized Loop 98 cycles; Stack Hack 56 cycles
Cycle Counts for Row Copyingblog.moertel.com

Chart drawn by HN Digest from figures reported by blog.moertel.com; values are shown as written in the source.

The next step involved replacing 3-cycle post-increment operations with 1-cycle exact offsets. By calculating the precise location of each word relative to the source and destination registers, the developer reduced the row-copy cost to 98 cycles, a 60% improvement over the original code.

Assembly code listing for performance optimization
Assembly code demonstrating the iterative optimizations used to reduce cycle counts.blog.moertel.com

The code listing shows the transition from naive loops to optimized assembly instructions.

The Stack and Direct Page Hack

The most extreme optimization leveraged the 6809's unique architecture. The processor featured PSHS and PULS instructions that could push or pull all registers onto the hardware stack in a very small number of cycles. By pointing the stack registers (S and U) at the background tile and the screen buffer, the developer could move data in large chunks.

To handle the fact that a 28-pixel row (14 bytes) is not evenly divisible by 6, the developer utilized the 6809's 'direct page' register. By designating a specific memory page as the 'direct page,' the DP register could act as an additional one-byte go-between, allowing the code to copy 7 bytes per pull-push pair. This final method reduced the row-copy operation to just 56 cycles.

Assembly code listing for stack and direct page hacks
Advanced assembly hacks utilizing the 6809's unique stack and direct page registers.blog.moertel.com

This listing demonstrates the 'crazy' hack that achieved the 56-cycle row copy.

Alternative Performance Strategies

While the 6809 hack focused on making the copy operation faster, other developers addressed the same performance bottleneck by changing what needed to be copied. Techniques like 'dirty rectangles' or adaptive tile refresh involve tracking changes in the game state and only redrawing the specific pixels or tiles that moved, rather than refreshing the entire screen every frame.