bios

This module exposes the GBA system calls (aka. BIOS functions).

The function names are PascalCase as is the convention used by Tonc, GBATek and others, which also conveniently helps to avoid clashing with Nim’s reserved keywords such as div and mod.

Attention

These aren’t fully documented yet - please refer to GBATek in the meantime.

Types

type ResetFlag = enum
  • rsEwramClear 256K on-board RAM.
  • rsIwramClear 32K in-chip RAM, except for the last 0x200 bytes
  • rsPalettesClear palettes
  • rsVramClear VRAM
  • rsOamClear OAM (does not disable OBJs!)
  • rsSioReset serial registers (switches to general purpose mode)
  • rsSoundReset sound registers
  • rsRegistersReset all other registers
type ResetFlags = set[ResetFlag]

A bitset of flags to be passed to RegisterRamReset

type CpuSetMode = enum
  • csmCopyCopy data
  • csmFillFill data (source pointer remains fixed)
type CpuSetStride = enum
  • cssHalfwordsCopy/fill by 2 bytes at a time
  • cssWordsCopy/fill by 4 bytes at a time
type CpuSetOptions = distinct uint32
type CpuFastSetOptions = distinct uint32
type BitUnpackOptions = object

    Field    

    Type    

    Description    

srcLen uint16

Source length (bytes)

srcBpp uint8

Source bitdepth (1,2,4,8)

dstBpp uint8

Destination bitdepth (1,2,4,8,16,32)

dstOffset cuint

Value added to all non-zero elements.

incZeros bool

If true, dstOffset will also be added to zero elements.

type MultibootOptions = object

    Field    

    Type    

reserved1 array[5, uint32]
handshakeData uint8
padding uint8
handshakeTimeout uint16
probeCount uint8
clientData array[3, uint8]
paletteData uint8
responseBit uint8
clientBit uint8
reserved2 uint8
bootSrcp ptr uint8
bootEndp ptr uint8
masterp ptr uint8
reserved3 array[3, ptr uint8]
systemWork2 array[4, uint32]
sendflag uint8
probeTargetBit uint8
checkWait uint8
serverType uint8
type MultibootMode = enum
  • mbNormal
  • mbMulti
  • mbFast

Procedures

Resetting

proc SoftReset()
proc RegisterRamReset(flags: ResetFlags)

Performs a selective reset of memory and I/O registers.

Note

This also enables the “forced blank” bit of the display control register (dispcnt.blank), which will turn the screen white until you set it to false.

Halting

proc Halt()

Halts the CPU until any enabled interrupt occurs.

proc Stop()

Stops the CPU and turns off the LCD until an enabled keypad, cartridge or serial interrupt occurs.

proc IntrWait(clear: bool, irq: set[IrqIndex])

Wait until any one of the specified interrupts occurs.

Clear:

If true, pre-acknowledged interrupts will be disregarded and the routine will wait for them to be acknowledged again.

Irq:

Which interrupt(s) to wait for.

proc VBlankIntrWait()

Wait for the next VBlank period.

This is equivalent to IntrWait(true, {iiVBlank}).

If the VBlank interrupt is not enabled, then this will hang.

Example:

import natu/[irq, bios]

irq.enable(iiVBlank)

while true:
  VBlankIntrWait()

Arithmetic

proc Div(num, den: cint): cint

Basic integer division.

Num:

Numerator.

Den:

Denominator.

Returns num / den.

Note

Dividing by zero results in an infinite loop. Try DivSafe instead.

proc DivArm(den, num: cint): cint

Basic integer division, but with switched arguments.

Den:

Denominator.

Num:

Numerator.

Returns num / den.

Note

Dividing by 0 results in an infinite loop.

proc Sqrt(num: cuint): cuint

Integer Square root.

proc ArcTan(dydx: FixedT[int16,14]): int16

Arctangent of dy/dx.

Takes a 2.14 fixed-point value representing the steepness of the slope.

Returns an angle in the range -0x4000..0x4000 (representing -𝜋/2 to 𝜋/2).

Warning

This gives completely wrong results for inputs outside the range -0x2000..0x2000 (-1.0 to 1.0).

As such, it can only effectively return angles in the range -0x2000..0x2000 (-𝜋/4 to 𝜋/4).

Consider using ArcTan2 instead.

proc ArcTan2(x, y: int16): uint16

Full-circle arctangent of a coordinate pair.

          +Y
           │  . (x,y)
           │ /
           │/╮θ
-X ────────┼──────── +X
           │
           │
           │
          -Y

This calculates the angle between the positive X axis and the point (x, y).

The value returned is in the range 0x0000..0xffff (0 to 2𝜋).

Warning

In most mathematical libraries the parameters to atan2 are ordered as y, x, but here they’re x, y.

Memory copy / fill

proc CpuSet(src: pointer, dst: pointer, opts: CpuSetOptions)

Transfer via CPU in word/halfword chunks.

The default mode is 16-bit copies.

When opts.mode == cmFill it will keep the source address constant, effectively performing fills instead of copies.

When opts.stride == csWords it will copy or fill in 32-bit steps instead.

Src:

Source address.

Dst:

Destination address.

Opts:

Number of transfers, mode and stride.

Note

This basically does a straightforward loop-copy, and is not particularly fast.

In fill-mode, the source is still an address, not a value.

proc CpuFastSet(src: pointer, dst: pointer, opts: CpuFastSetOptions)

A fast transfer via CPU in 32 byte chunks.

This uses ARM’s ldmia/stmia instructions to copy 8 words at a time, making it rival DMA transfers in speed.

When opts.mode == cmFill it will keep the source address constant, effectively performing fills instead of copies.

Src:

Source address. Must be word aligned.

Dst:

Destination address. Must be word aligned.

Opts:

Number of words to transfer, and mode.

Note

Both source and destination must be word aligned; the number of copies must be a multiple of 8.

In fill-mode, the source is still an address, not a value.

memcpy32/16 and memset32/16 basically do the same things, but safer. Use those instead.

Checksum

proc BiosCheckSum(): uint32

Calculate the checksum of the BIOS.

Returns:

  • 0xbaae187f for GBA / GBA SP / Game Boy Micro / Game Boy Player

  • 0xbaae1880 for DS / DS Lite / DSi / 3DS Family.

Rotation / scaling

These procedures are misnomers, because ObjAffineSet is merely a special case of BgAffineSet. Results from either can be used for both objs and bgs.

proc ObjAffineSet(src: ptr ObjAffineSource, dst: pointer, num: cint, offset: cint)

Sets up a simple scale-then-rotate affine transformation. Uses a single ObjAffineSource struct to set up an array of affine matrices (either BG or Object) with a certain transformation. The matrix created is:

┌───────────┬────────────┐
| sx·cos(α) | -sx·sin(α) |
├───────────┼────────────┤
| sy·sin(α) | sy·cos(α)  |
└───────────┴────────────┘
Src:

Array with scale and angle information.

Dst:

Array of affine matrices, starting at a pa element.

Num:

Number of matrices to set.

Offset:

Offset between affine elements. Use 2 for BG and 8 for object matrices.

Note

Each element in src needs to be word aligned.

proc BgAffineSet(src: ptr BgAffineSource, dst: ptr BgAffineDest, num: cint)

Sets up a simple scale-then-rotate affine transformation. See ObjAffineSet for more information.

Decompression

(see GBATek for format details)

proc BitUnPack(src: pointer, dst: pointer, bup: BitUnpackOptions)
proc LZ77UnCompWram(src: pointer, dst: pointer)
proc LZ77UnCompVram(src: pointer, dst: pointer)
proc HuffUnComp(src: pointer, dst: pointer)
proc RLUnCompWram(src: pointer, dst: pointer)
proc RLUnCompVram(src: pointer, dst: pointer)
proc Diff8bitUnFilterWram(src: pointer, dst: pointer)
proc Diff8bitUnFilterVram(src: pointer, dst: pointer)
proc Diff16bitUnFilter(src: pointer, dst: pointer)

Sound

proc SoundBias(bias: uint32)
proc SoundDriverInit(src: pointer)
proc SoundDriverMode(mode: uint32)
proc SoundDriverMain()
proc SoundDriverVSync()
proc SoundChannelClear()
proc MidiKey2Freq(wa: pointer, mk: uint8, fp: uint8): uint32
proc MultiBoot(mb: MultibootOptions, mode: MultibootMode): cint

Multiboot handshake

proc HardReset()

Reboots the GBA, including playing through the GBA boot intro.

proc SoundDriverVSyncOff()
proc SoundDriverVSyncOn()

Extras

Additional utilities from Tonc which are built atop the BIOS routines.

proc VBlankIntrDelay(count: cuint)

Wait for count frames.

proc DivSafe(num, den: cint): cint

Divide-by-zero safe division.

The standard Div hangs when den == 0. This version will return cint.high or cint.low, depending on the sign of num.

Num:

Numerator.

Den:

Denominator.

Returns num / den.

proc Mod(num, den: cint): cint

Modulo: num % den.

proc DivMod(num, den: cint): cint

Modulo: num % den.

proc DivAbs(num, den: cint): cuint

Absolute value of num / den.

proc DivArmMod(den, num: cint): cint

Modulo: num % den.

proc DivArmAbs(den, num: cint): cuint

Absolute value of num / den.

proc CpuFastFill(wd: uint32, dst: pointer, words: cuint)

A fast word fill.

While you can perform fills with CpuFastSet, the fact that swi 0x01 requires a source address makes it awkward to use. This function is more like the traditional memset formulation.

Wd:

Fill word.

Dst:

Destination address.

Words:

Number of words to transfer.