London Calling

Remember call, ret and rst? It's high time we give them some love and care!

Calling functions

The concept of calling a function is that at some point in the flow, the flow is interrupted, a separate piece of code is ran, and then the flow resumes, optionally using some of the function's calculations. On the GB, this is done using the call instruction.

The principle is, again, that the function "returns" to the main flow. To do that, it need to save where the "calling" flow was... My, my, didn't we just see that the stack was perfect for saving stuff? Well, that's exactly what happens!

    ; Let's say that `Function` is a label

    call Function

    ; equivalent to (again, these instructions are illustrative but **invalid**)

    push pc ; But PC equals the address after the following instruction
    jp Function
.return ; This is the address whose value gets pushed onto the stack

(If you're not sure how that works, read ret's description below; that should make it clearer.)

Oh, and also, just like jp and jr, call can be executed conditionally. call nz, AFunctionCalledOnlyIfZIsReset


Now, a function needs to tell the CPU when it's over, and when control need to be passed back to the calling code. This is done by the ret operation, which is basically pop pc. And this instruction can be used conditionally too! Here's an example:

    ld a, [de]
    ld [hli], a
    inc de
    dec bc
    ld a, b
    or c
    jr nz, Memcpy

If you remember from the Hello World chapter, this looks like the piece of code we used to copy data to VRAM. This is useful to avoid repeating blocks of code:

    ld de, FontTiles
    ld hl, $9000
    ld bc, FontTilesEnd - FontTiles
    call Memcpy

Note that the ret doesn't have to be at the end of the function!

    ld de, DefaultPlayerName
    ld hl, wPlayerName
    call Strcpy

    ; (...)

; Copy a string up to but not including the first NUL character
; @param de A pointer to the string to be copied
; @param hl A pointer to the beginning of the destination buffer
; @return de A pointer to the byte after the source string's terminating byte
; @return hl A pointer to the byte after the last copied byte
; @return a Zero
; @return flags C reset, Z set
    ld a, [de]
    inc de
    and a
    ret z
    ld [hli], a
    jr Strcpy

An announcement about documentation

You can see that I inserted a huge comment before the Strcpy function. This is to help document what it does, etc. I recommend using a format similar to this one, because it's clear and concise. I use @param to indicate which registers, flags and memory addresses the function uses as input, @return to document the effects that the function has that are consistent, and @destroy to document the effects it has which are either inconsistent or too complex to explain. I recommend taking the time to write and keep this kind of comment to date, to help you maintain your code.