Bun Runner Devlog -- 2024-12-22
I decided to work on the palette manager, and now I can fade between arbitrary palettes of colors:
The fading algorithm is a slightly tweaked implementation of Bresenham’s line algorithm. I know I built paletete fading code back in the AMOS days, very likely using a ratio approach like this:
m% "start color channel value" + "color channel delta" * ("current step" / "step count") %m
The issue is arbitrary multiplications and divisions on the 68000 processor are
expensive. Compare the roughly worst-case cycle time cost of MULU
and DIVU
to MOVE
, LSL
, and ADD
:
MULU
: 70 cyclesDIVU
: 140 cyclesMOVE.L
to/from memory: 8 cyclesLSL.L
: 8 cyclesADD.L
: 12 cycles
(Values from MC68000 Instructions Timing)
If you’re efficient, you can do a lot of stuff in the time it takes one division operation to take place!
The Bresenham implementation is all fixed point with no multiplications or divisions, and it’s pretty fast. This is also an algorithm I’m sure I’ll come back to a lot in retro development, so I wanted to get good with it:
The unit testing I alluded to in my last post helped out a lot with implementing this. Being able to write code like this to test out the results of the assembler-based algorithm made it way easier to find bugs and discover issues in my algorithm:
void T_buildColorTransition(CuTest *tc) {
uint16_t targetMemory[7] = { 0, 0, 0, 0, 0, 0, 0 };
struct ColorTransition ct = {
0x845,
0xAC0,
0,
6
};
int i;
buildColorTransition(
targetMemory,
&ct
);
CuAssertIntEquals(tc, 0x845, targetMemory[0]);
CuAssertIntEquals(tc, 0x864, targetMemory[1]);
CuAssertIntEquals(tc, 0x983, targetMemory[2]);
CuAssertIntEquals(tc, 0x992, targetMemory[3]);
CuAssertIntEquals(tc, 0xab1, targetMemory[4]);
CuAssertIntEquals(tc, 0xac0, targetMemory[5]);
CuAssertIntEquals(tc, 0, targetMemory[6]);
}
Additionally writing unit tests forced me to build an interface to the palette manager that was reusable. Lots of structures to manage incoming data, and well-defined inputs and outputs means that reusing this code in future programs, like the demo code above, was trivial.
I’ll be getting back to the head collision physics, and probably implementing more unit tests around that, since hand-testing the collision code requires a lot of setup and me jumping really precisely. Tests should speed up that feedback loop a lot.