Errata: Making 8-Bit Arcade Games in C

To future-proof the code examples from compiler updates, some code has been changed.

Some interrupt handers must start at a specific address, and the SDCC compiler currently does not have an easy way to force this. Therefore, the current approach is to put padding bytes between functions so that when lined up in memory, the interrupt handlers are at the right address.

We’ve modified the Galaxian-Scramble demo game to make this more predictable. We insert padding bytes at the end of the start() routine’s __asm block:

    .ds   0x66 - (. - _start)

The .ds directive means “insert N bytes here.” (. - _start) is the current program counter subtracted from the _start label. We do this to convert the program counter to an absolute constant (stuff specific to the SDCC assembler). Then we subtract that value from 0x66, which is where we want our next function to reside.

We also use the __naked function decorator so that the compiler doesn’t insert a RET instruction or stack frame instructions, modifying our code length.

The end result of this is that our next C function definition will reside at address 0x66, where we want it.

The bcd_add() function has also been changed, as the inline assembly made assumptions about the code that are not portable across compiler flags. It also now uses the __naked decorator.

In the VIC Dual sections, RAM is defined as starting at $8000, but the code defines it at the mirrored location $c000. Note that it is a 32 x 32 array (1024 bytes) but only 28 rows (896 bytes) are visible.

Chapter 6, p. 41: The line typedef unsigned char sbyte should define a signed char type, not unsigned char.

Chapter 8: The function definition for halve_score has a redundant LD IY,#_score instruction.

Chapter 18, p. 115: The field _unused is padding for the AttackingEnemy struct, but there is no such field in the example code.

Comments