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.