Functions

So far, we have only written a single “flow” of code, but we can already spot some snippets that look redundant. Let’s use functions to “factor out” code!

For example, in three places, we are copying chunks of memory around. Let’s write a function below the jp Main, and let’s call it Memcpy, like the similar C function:

; Copy bytes from one area to another.
; @param de: Source
; @param hl: Destination
; @param bc: Length
Memcopy:
	ld a, [de]
	ld [hli], a
	inc de
	dec bc
	ld a, b
	or a, c
	jp nz, Memcopy
	ret

The new ret instruction should immediately catch our eye. It is, unsurprisingly, what makes execution return to where the function was called from. Importantly, many languages have a definite “end” to a function: in C or Rust, that’s the closing brace }; in Pascal or Lua, the keyword end, and so on; the function implicitly returns when execution reaches its end. However, this is not the case in assembly, so you must remember to add a ret instruction at the end of the function to return from it! Otherwise, the results are unpredictable.

Notice the comment above the function, explaining which registers it takes as input. This comment is important so that you know how to interface with the function; assembly has no formal parameters, so comments explaining them are even more important than with other languages. We’ll see more of those as we progress.

There are three places in the initialization code where we can use the Memcpy function. Find each of these copy loops and replace them with a call to Memcpy; for this, we use the call instruction. The registers serve as parameters to the function, so we’ll leave them as-is.

BeforeAfter
	; Copy the tile data
	ld de, Tiles
	ld hl, $9000
	ld bc, TilesEnd - Tiles
CopyTiles:
	ld a, [de]
	ld [hli], a
	inc de
	dec bc
	ld a, b
	or a, c
	jp nz, CopyTiles
	; Copy the tile data
	ld de, Tiles
	ld hl, $9000
	ld bc, TilesEnd - Tiles
	call Memcopy
	; Copy the tilemap
	ld de, Tilemap
	ld hl, $9800
	ld bc, TilemapEnd - Tilemap
CopyTilemap:
	ld a, [de]
	ld [hli], a
	inc de
	dec bc
	ld a, b
	or a, c
	jp nz, CopyTilemap
	; Copy the tilemap
	ld de, Tilemap
	ld hl, $9800
	ld bc, TilemapEnd - Tilemap
	call Memcopy
	; Copy the tile data
	ld de, Paddle
	ld hl, $8000
	ld bc, PaddleEnd - Paddle
CopyPaddle:
	ld a, [de]
	ld [hli], a
	inc de
	dec bc
	ld a, b
	or a, c
	jp nz, CopyPaddle
	; Copy the tile data
	ld de, Paddle
	ld hl, $8000
	ld bc, PaddleEnd - Paddle
	call Memcopy

In the next chapter, we’ll write another function, this time to read player input.