/BERGASMS/GBA/02

..

01/08/22: Part 2

Current Goal: I will write the bare minimum amount of code to display a red pixel onto the GBA screen using Zig

So the GBA has memory mapped i/o, which basically means you need to write bits and bytes into certain adresses to tell the hardware to do certain things. I know the device has different video modes, and I know that one of the video modes is basically 'memory from a certain location is treated as a giant bitmap that represents the screen'. So in order to achieve our first goal i need to know where to write bits to in order to tell the hardware i want the simple and boring video mode, and where to write to this video memory in order to set a red pixel on. The best resource for this seems to be GBATEK which has all the info. It's hosted by mGBA which is the emulator I am using so it should be fine.
So from a quick read, it turns out the IO mapping for the GBA is done at the memory addresses
04000000-040003FE
This is a good starting point, now i just need to find out what values to write into what spots to get the desired setup. Should be simple right?
OK turns out it kinda was simple. The very first address has the following information
4000000h  2    R/W  DISPCNT   LCD Control
Which from my inferred and possibly incorrect understanding means at 4000000 (no idea what the h is for, high bit maybe? something endian perhaps?), there are 2 bits, they can be Read or Written to, they're called DISPCNT and they control the LCD.
Wait, the Two means bytes. That makes more sense. Two bytes to control the LCD. Further reading (who knew that, you read more, you learn more) reveals that the first three bits set the BG Mode, which determines where/how you need to put your stuff to be rendered and how the device interprets it.
4000000h - DISPCNT - LCD Control (Read/Write)

  Bit   Expl.
  0-2   BG Mode                (0-5=Video Mode 0-5, 6-7=Prohibited)
  3     Reserved / CGB Mode    (0=GBA, 1=CGB; can be set only by BIOS opcodes)
  4     Display Frame Select   (0-1=Frame 0-1) (for BG Modes 4,5 only)
  5     H-Blank Interval Free  (1=Allow access to OAM during H-Blank)
  6     OBJ Character VRAM Mapping (0=Two dimensional, 1=One dimensional)
  7     Forced Blank           (1=Allow FAST access to VRAM,Palette,OAM)
  8     Screen Display BG0  (0=Off, 1=On)
  9     Screen Display BG1  (0=Off, 1=On)
  10    Screen Display BG2  (0=Off, 1=On)
  11    Screen Display BG3  (0=Off, 1=On)
  12    Screen Display OBJ  (0=Off, 1=On)
  13    Window 0 Display Flag   (0=Off, 1=On)
  14    Window 1 Display Flag   (0=Off, 1=On)
  15    OBJ Window Display Flag (0=Off, 1=On)
According to the book BG Modes 0-2 are Tile/Map-based. BG Modes 3-5 are Bitmap-based. It seems like what we want is one of the modes 3-5, so we have a nice chunky bitmap we can write to. Further on we find a description of Mode 3 which seems to fit it nicely.

BG Mode 3 (Bitmap based Mode for still images)

06000000-06013FFF  80 KBytes Frame 0 buffer (only 75K actually used)
06014000-06017FFF  16 KBytes OBJ Tiles
        
So now to write some Zig, i need to get a gba rom compiling that sets up Mode 3 video mode and doesn't crash on the emulator, that'll do for the moment.



Zig is super cool!


Me$ zig init-exe
info: Created build.zig
info: Created src/main.zig
info: Next, try `zig build --help` or `zig build run`
Me$ zig build run
info: All your codebase are belong to us.
        
So when i said i was gonna do it all myself I did lie just a little. There is actually some complicated linking and cross compilation steps involved to produce a valid ARM7 binary that the GBA can run. It would be a long slog for me to figure out this info and it would provide little in the way of benefit. I am super interested in writing code that runs on the GBA (either successfully or not) but less interested in the work of just getting the code in an understandable format in the first place.
A big part of Zig is the build file. This is where you tell it how to turn your source into an executable. It's also where you can tell it what type of executable you want. Zig is fricken awesome for cross compilation, it does a heck of a lot out of the box. All we need to do to get code that runs on the GBA is give Zig a bunch of target information, it will do most of the rest. (All the build code snippets are adapted or taken from the ZigGBA repo mentioned previously, BTW)

const gba_thumb_target = blk: {
    var target = CrossTarget{
        .cpu_arch = std.Target.Cpu.Arch.thumb,
        .cpu_model = .{ .explicit = &std.Target.arm.cpu.arm7tdmi },
        .os_tag = .freestanding,
    };
    target.cpu_features_add.addFeature(@enumToInt(std.Target.arm.Feature.thumb_mode));
    break :blk target;
};
The Zig build file comes out of the box with some nice steps set up for us to run the program and run tests and suchlike, however as we are targeting an emulator for now I am going to get rid of them. There is nothing Zig can test for us at this stage, we just want to make an 'executable' rom. We will also handle the running of the rom ourselves by opening it from within the emulator.
The gba.ld file has some symbols in it we need to export in order to get a working binary. So i'm gonna go through the ZigGBA source to figure out exactly what that entails, and then match it up with the supplied document to see why they are setting what they are setting.

.text :
    {
        KEEP(*(.gbaheader))
        KEEP(*(.gbamain))
        *(EXCLUDE_FILE (*.iwram*) .text*)
        . ALIGN(4);
    } >rom = 0xff
It appears we can export these things out from Zig, I found the following line that looks interesting.
export var gameHeader linksection(".gbaheader")
Lets have a look and see what the Zig documentation has to say about linksection.
The linksection keyword.
TODO add documentation for linksection
Ah.. Did i mention Zig is still in active development! Ok, for now, we will guess that it makes that keyword available for linking stuff in outside of our source code or something!
OK! Some further digging into ZigGBA has turned up the guts which does the real nitty gritty stuff to get the GBA going. This includes the asm to boot everything up, the Nintendo logo, and a whole heap of other bits and pieces. Tomorrows job will be to cut back this to the bare minimum to achieve our goal. Time now to play some Dwarf Fortress and chill.