Files
jasper/developer-handbook.md
Gary Talent d84c4980b2 Squashed 'deps/nostalgia/' changes from 63d0abaa..53aea973
53aea973 [ox] Cleanup
0e028ff6 [ox] Cleanup
07688a2c [ox] Remove oxExpect macro
9ce4d3f8 [keel,nostalgia/gfx] Minor cleanup of tests
4aa8255c [ox] Update formatting in recently edited files
bfdfc104 [nostalgia/gfx] Update panic
cdd574d8 [ox] Change panic and assert to use std::source_location
bc05bd12 [ox/model] Rename and fix isBString helpers
b754c66c [ox] Remove enable_if
6a423032 [ox/std] Slight optimization
7477ede2 [ox/std] Cleanup some enable_ifs
65e3153d [ox/std] Add Union_c concept
53a224cf [ox/std] Cleanup
592e641b [ox/std] Fix writeItoa to work with max length 64 bit ints
689da4a0 [ox] Update docs
bdf7755e [nostalgia/developer-handbook] Update developer handbook
63f62737 [ox/std] Remove excess char from intToStr return
ff9002ad [nostalgia/developer-handbook] Update error handling section
4d0da022 [ox] Update error handling docs
02332d99 [ox] Fix issues in String Types section of docs
a566ed2a [ox/std] Fix writeItoa to work with negatives
815c3d19 [ox/std] Make StringLiteral constructors non-explicit
522bb14f [ox/std] Fix intToStr to have room for negatives
f40d5515 [ox] Add strings section to docs
941d1d90 [ox/std] Add Vector::reserveResize
3e880dcd [nostalgia/gfx/studio] Remove unused EBO management
03328ac1 [turbine/glfw] Fix to handle null click handler

git-subtree-dir: deps/nostalgia
git-subtree-split: 53aea9731dc2bdf891f8c59bbbbb67a8f8801e82
2026-01-25 23:53:51 -06:00

6.6 KiB

Olympic Developer Handbook

About

The purpose of the Developer Handbook is similar to that of the README. The README should be viewed as a prerequisite to the Developer Handbook. The README should provide information needed to build the project, which might be used by an advanced user or a person trying to build and package the project. The Developer Handbook should focus on information needed by a developer working on the project.

Project Structure

Overview

All components have a platform indicator next to them:

(PG) - PC, GBA
(-G) - GBA
(P-) - PC
  • Nostalgia
    • modules
      • core - graphics system for Nostalgia (PG)
        • gba - GBA implementation (PG)
        • opengl - OpenGL implementation (P-)
        • studio - studio plugin for core (P-)
        • keel - keel plugin for core (PG)
      • sound - sound system for Nostalgia (PG)
        • studio - studio plugin for sound (P-)
        • keel - keel plugin for sound (PG)
    • player - plays the games (PG)
    • studio - makes the games (P-)
    • tools - command line tools (P-)
      • pack - packs a studio project directory into an OxFS file (P-)
  • Olympic
    • Applib - Library for creating apps as libraries that injects Keel and Studio modules
    • Keel - asset management system (PG)
    • Studio - where most of the studio code lives as library (P-)
      • applib - used for per project studio executables
      • modlib - used for studio modules to interact with studio
    • Turbine - platform abstraction and user I/O (PG)
      • gba - GBA implementation (PG)
      • glfw - GLFW implementation (P-)
  • deps - project dependencies
    • Ox - Library of things useful for portable bare metal and userland code. Not really that external... (PG)
    • GlUtils - OpenGL helpers (P-)
    • teagba - GBA assembly startup code (mostly pulled from devkitPro under MPL 2.0), and custom GBA hardware interop code (-G)

Most GBA code is built on PC because it is small and helps to work on both projects with the same CMake build dir, but GBA code is never linked with any executables on PC.

Platform Notes

GBA

The GBA has two major resources for learning about its hardware:

  • Tonc - This is basically a short book on the GBA and low level development.
  • GBATEK - This is a more concise resource that mostly tells about memory ranges and registers.

Graphics

  • Background Palette: 256 colors
  • Sprite Palette: 256 colors

Code Base Conventions

Formatting

  • Indentation is done with tabs.
  • Alignment is done with spaces.
  • Opening brackets go on the same line as the thing they are opening for (if, while, for, try, catch, function, etc.)
  • No space between function parentheses and arguments.
  • Spaces between arithmetic/bitwise/logical/assignment operands and operators.
  • Pointer and reference designators should be bound to the identifier name and not the type, unless there is not identifier name, in which case it should be bound to the type.
  • East const

Write C++, Not C

On the surface, it seems like C++ changes the way we do things from C for no reason, but there are reasons for many of these duplications of functionality. The C++ language designers aren't stupid. Question them, but don't ignore them.

Casting

Do not use C-style casts. C++ casts are more readable, and more explicit about the type of cast being used. Do not use dynamic_cast in code building for the GBA, as RTTI is disabled in GBA builds.

Library Usage

C++ libraries should generally be preferred to C libraries. C libraries are allowed, but pay extra attention.

This example from nostalgia::core demonstrates the type of problems that can arise from idiomatically mixed code.

uint8_t *loadRom(const char *path) {
	auto file = fopen(path, "r");
	if (file) {
		fseek(file, 0, SEEK_END);
		const auto size = ftell(file);
		rewind(file);
		// new can technically throw, though this project considers out-of-memory
		// to be unrecoverable
		auto buff = new uint8_t[size];
		fread(buff, size, 1, file);
		fclose(file);
		return buff;
	} else {
		return nullptr;
	}
}

In practice, that particular example is not something we really care about here, but it does demonstrate that problems can arise when mixing what might be perceived as cool old-school C-style code with lame seemingly over-complicated C++-style code.

Here is another more concrete example observed in another project:

int main() {
	// using malloc does not call the constructor
	std::vector<int> *list = (std::vector<int>*) malloc(sizeof(std::vector<int>));
	doStuff(list);
	// free does not call the destructor, which causes memory leak for array
	// inside list
	free(list);
	return 0;
}

The code base where this was observed actually got away with this for the most part, as the std::vector implementation used evidently waited until the internal array was needed before initializing and the memory was zeroed out because the allocation occurred early in the program's execution. While the std::vector implementation in question worked with this code and the memory leak is not noticeable because the std::vector was meant to exist for the entire life of the process, other classes likely will not get away with it due to more substantial constructors and more frequent instantiations of the classes in question.

Project Systems

Olympic builds on Ox as its standard-ish library. Please read the Ox documentation. The Ox way of doing things is the Olympic way of doing things.

Error Handling

Instead of throwing exceptions, generally try to use ox::Error for error reporting. Exceptions may be used where errors-as-values will not work, but catch them and convert them to ox::Error as soon as possible.

Exceptions should generally just use ox::Exception, which is basically an exception form of ox::Error.

File I/O

All engine file I/O should go through Keel, which should go through ox::FileSystem. Similarly, all studio file I/O should go thorough nostalgia::studio::Project, which should go through ox::FileSystem.

ox::FileSystem abstracts away differences between conventional storage devices and ROM.

Olympic files are generally just Claw objects.

Keel

Keel, as its name implies, is a foundational component of Olympic. Keel is the asset management system.

Keel provides for the following needs:

  • Type conversion
  • Asset bundling
  • Asset loading (including flyweighting on PC and preloading to ROM on the GBA)