Hacker News new | past | comments | ask | show | jobs | submit login
A Great Old-Timey Game-Programming Hack (2013) (moertel.com)
140 points by graderjs on March 9, 2022 | hide | past | favorite | 23 comments



Man, the 6809 was an incredibly fun processor to write for.

I'll let you know you were in good company. At Williams (pinball/video game company, later became Midway) that exact same hack was used in almost every game that used the 6809. We definitely used it in all the dot-matrix pinball machines to blit large pieces of data in RAM.


Random, but have you seen the documentary Insert Coin on the heyday of Williams and Midway? I'd love to hear your stories from working there.


I contributed to Josh Tsui's Kickstarter. He did an excellent job on that, all the people in that video are exactly like I remember them.

There's another documentary called Tilt: The Battle to Save Pinball by Greg Maletec that describes what we were going through on the pinball side near the end. It's streamable on a few services.

The stories themselves? Way too many to relate. But it was certainly like the doc. A cutthroat company where anything could happen. But probably the most talented and creative group of engineers I've ever worked with.


Awesome, thanks for the documentary recommendation!


This dug up a vague memory of stack-based optimization tricks for copying memory on the Z80, from when I learned how to program that for my calculator. Searching for that revealed this Retro Computing Stack Exchange discussion[0] which lists a number of them. I guess this was a common trick among many architectures back in the day.

[0] https://retrocomputing.stackexchange.com/questions/4744/how-...


Mapping the stack to the graphics screen is also a staple for fast animation on the Apple IIgs.

On pretty much all the micros of that era, stack operations would be the fastest instruction due to the auto-decrement behavior. If one could leverage the stack for bitblts, it was usually a win.


Yup, and it goes back at least to the Atari 2600, with a 6502-equivalent CPU. For a homebrew game on that, I did the same thing of pointing the stack at the video registers, to get faster throughput with push instructions. The machine has no interrupts so you can always do whatever you want with the stack pointer register.

The 2600's video hardware is actually intentionally designed for such a trick. The register to enable the "missile" objects has its hot bit at bit 1. Why that, why not bit 0 or 7? Because bit 1 is the location of the zero flag in the 6502's flags register. You can enable/disable an object by doing a compare on its coordinate, then push the flags register. No conditionals or branching needed, and you even get a consistent cycle-invariant code path, a useful property on this machine. And there are registers for several such objects adjacent in addressing space, so you can handle them with consecutive push instructions without resetting the stack pointer.

As for inverting the storage to deal with the directionality, that trick was also known on the 2600. Store a sprite bottom-first in memory, so that your indexing counter decrements towards zero rather than incrementing upwards, so you can "branch if zero flag" to know when you're done rather than needing a compare instruction.


> Yup, and it goes back at least to the Atari 2600, with a 6502-equivalent CPU

For those wondering whether the 2600 even _had_ a stack: it had 128 bytes of RAM that appeared at both $80-$FF _and_ $180-$1FF (maybe also other places) in the address map.

The former means you can read and write it using zero page addressing (faster, shorter instructions), the latter that you’d have half of the 6502 hardware stack, which the CPU thought was at $100-$1FF. It was up to the programmer to ensure the stack didn’t accidentally ran into your variable storage.


The RAM appears at every page where lines 9 and 12 of the 16-bit address space are zero. Bit 9 means pages $00xx, $01xx, $04xx, $05xx, $08xx, $09xx, $0Cxx, $0Dxx. Furthermore, then all that is also mirrored for every even-numbered topmost hex digit ($20xx, $21xx, etc), because the 2600's motherboard just omits address lines 13 or higher so those bits don't do anything.

When bit 9 is 1 (pages $02xx, $03xx, $07xx, $08xx, etc), you're accessing the timer and console input registers instead. When bit 12 is 1, you're accessing ROM instead of anything onboard.

It's not really useful to mirror the RAM anywhere else besides page 1 for the stack, but the architecture just ended up that way for simplicity - no need to decode any other lines than 9 and 12. It would have been possible to use that address space for more ROM, but at the cost of more logic gates - as-is, address line 12 is simply directly wired to the ROM chip-enable line.



> Terry A Davis • 8 years ago • edited

> You'll love my 64-bit ring-0-only identity-mapped operating system.

RIP


It's a bit of a shame that Linux doesn't put the kernel at the low end of the address space and identity-map the kernel's address space. For one, calculating kernel address mappings would be slightly faster, and for two, it would allow putting 64-bit processes at the top of virtual memory, where pointers are NaN when bit-cast to pointers, so NaN-boxing language runtimes get a speed bump.

I wonder how much software assumes it's being mapped in the lower portion of the address space.


I caught that too. It put a smile on my face.

Might boot up TempleOS for a bit and play around with it later.

F


I remember reading this back in 2013 but didn't bookmark it so it's great to have the link again!


Happy to have helped you find your long lost favorite! :)


Dumb question, why not disable interrupts during each iteration of the inner loop (+6 cycles per iteration = +42 cycles total)? Was the audio device using NMI? Or maybe the 224 cycles of that loop was too long a delay to respond to the interrupt?


Those darn 28 pixels! ) I guess it was the only way of choosing the scale of game objects. But so many problems... It's crazy how even today some amateurs use non-power-of-2 sprites. Luckily, many CG tools disallow that. )


Thanks for the read! This is the kind of stuff you always used to hear about programmers doing, and every story like this brings a bit of delight at the ingenious conquering of obstacles.

That's how programming ought to feel.


I’m dreading the day when the kind of coding I grew up with is called “old timey”. Already the music I listened to is moving over to the oldies station (greatest hits of the 80s 90s and now!). They were playing nirvana…


I thought it was about hacking the original hack(6). But turned out interesting anyway!


Fun article, now I wish I could try the game out to see it all in action!


There's a blog about porting the arcade (Z80) code of Pac Man to the 6809 Color Computer. This link is about converting the Z80 to 6809 but elsewhere is discussion of blitting, ie drawing the sprites with the CPU to a bitmap, and I think he ended up using a similar technique IIRC https://nowhereman999.wordpress.com/2016/12/29/zilog-z80-to-...

You can definitely try that one.


Thought it was going to be about JS, and since it was 2013 the author had to go back and add "Old-Timey" to the title.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: