I thought I understood the MO5.

In reality, it was the MO5 testing me šŸ˜‰

Since I started developing my little game, I’ve run into quite a few issues, some predictable, others completely absurd, and most importantly several traps I fell into… even though I already knew the theory or had already experienced them before.

That’s probably the most frustrating part.

You know the trap exists, you’ve already read about it somewhere, but you still fall into it anyway.

And you lose your evening šŸ˜‰

I figured it was worth doing a small retrospective, just to help others avoid going through the same lonely moments.

The emulator that lies

First trap, and probably the trickiest one, trusting the emulator.

I was using DCMOTO to test my code, which makes sense at first, it’s convenient, fast, no need to take out the hardware.

Except…

DCMOTO does not always faithfully reproduce the behavior of a real MO5.

I had already been caught once with colors, which were not at all what was displayed on the real machine, I thought I had misunderstood the palette, I spent time checking my code, when the problem was simply coming from the emulator.

And of course… I made the same mistake again šŸ˜‰

This time, it was with sprite rendering.

I was working on rendering with a transparent background, everything seemed correct in the code, clean logic, background color handling, nothing unusual.

And yet, on screen, I consistently had a black background, a kind of “smearing” when the sprite was moving.

Impossible to understand why.

I spent quite some time questioning my code, my functions, my calculations, everything went through it.

Then I had a doubt… I tested on a real MO5… And then… Everything worked perfectly.

No black artifacts, perfect transparency, no smearing, exactly the expected behavior.

šŸ‘‰ the bug didn’t exist, it was the emulator! Damn the emulator… And yet, I had already been caught once with DCMOTO…

Since then, I avoid DCMOTO, and I rather use an online emulator (this one is quite good: https://scemino.github.io/yame_wp/mo5.html), or better, I test on the real machine whenever possible.

The innocent variable that breaks everything

Second trap, much more subtle, and honestly, this one made me lose several evenings.

With modern languages, we’ve developed good habits, declaring a variable when we need it, and often initializing it directly.

It’s clean, readable, recommended.

Except… CMOC does not play by those rules…

The compiler follows the C89 standard, which requires all variables to be declared at the beginning of the block.

And more importantly in my case, declaring a variable in the middle of the code, or worse, initializing it directly at declaration, can cause completely unpredictable behavior.

And the worst part?

  • it compiles perfectly
  • no error
  • no warning
  • nothing…

The program starts… and does not work… or crashes… or behaves randomly.

So naturally, you question your code.

  • you look at the logic
  • you suspect your functions
  • you think about a memory issue

When in fact… it was just the variable, not declared in the right place or initialized directly.

And since you never add a variable alone, but often along with surrounding code, you look everywhere except the right place.

Nice evenings ahead šŸ˜‰

The invisible stack limit

Third trap, even more insidious… the number of variables in a function

On the MO5, with CMOC, local variables are stored on the stack.

And the stack is very limited…

Very, very limited…

Extremely limited…

In my case, I noticed that a function could contain around 6 or 7 local variables, depending on their size.

And again, the behavior is very particular.

You add one variable. Just one.

And your program no longer works.

  • no error message
  • no warning
  • sometimes it doesn’t even start at all
  • it freezes before even entering your main loop

And you, you search… You analyze your code… You think you introduced a logical bug.

When in fact… it’s just the stack that overflowed

The kind of problem that simply does not exist anymore in modern environments, and that is extremely confusing when you encounter it again.

What I learned (sometimes the hard way)

After all these issues, I ended up gathering a few simple rules.

Not theoretical rules, but things I verified in practice, sometimes after several hours of debugging.

For example,

  • prefer unsigned char to int, because the 6809 is an 8-bit processor and 16-bit operations are much more expensive,
  • avoid multiplications and divisions, because they are very costly in cycles,
  • prefer pointer increments over array indexing, because it avoids unnecessary computations,
  • limit access to VRAM and group writes, because each access has a cost,
  • use bitwise operations instead of arithmetic ones when possible,
  • be careful with underflows on unsigned char,
  • declare all variables at the beginning of the function and initialize them afterwards,
  • and above all limit the number of local variables, moving some to static global variables when necessary.

These are fairly obvious things when you know the architecture well.

But when you come from the modern world, it requires a real mindset shift.

I have summarized all these rules in a .md file shared via my SDK.
I also injected them into my RAG server so they can be used by coding agents.

Conclusion

The MO5 is a simple machine… but not a forgiving one šŸ˜‰

  • it does not tolerate approximations
  • it does not always give clear errors
  • it forces you to understand what you are doing

But that’s also what makes the experience interesting.

Because every bug fixed, every constraint understood, really gives the feeling of progressing.

And even if some evenings are a bit long… it’s still very fun, well, not always šŸ˜‰