thecodingidiot.com

c01-the-toolkit

The Toolkit

No Functions to Call

The Atari 2600 shipped with 128 bytes of RAM and a cartridge slot. No operating system. No standard library. No strlen, no memset, no malloc.

If a game needed to copy memory — to scroll the playfield, to move a sprite's data between buffers — it wrote the loop. If it needed to measure the length of something, it counted. The 2600 programmer had no functions to call. Every operation on data was written, by hand, in the game itself.

That was not unusual. It was the state of the industry for over a decade. The NES had 2 kilobytes of RAM and no standard library either.

Every game that displayed a score — every routine that converted an integer to tile indices, every scan of the sprite table to find an empty slot — was doing by hand what we will shortly put behind tci_strlen and tci_memset. The function did not exist. The programmer wrote what it does, inline, every place it was needed, because there was no other place to put it.

By the time the PlayStation arrived, C SDKs existed. The Psy-Q SDK — SN Systems[1] official PlayStation dev toolchain — included a C standard library.

Naughty Dog[2][3] used it — and found it too slow in the hot paths. The inner loops of Crash Bandicoot's[4][5] renderer and physics engine needed memory operations faster than what the SDK provided, so Andy Gavin[6] wrote his own.

They were building on Silicon Graphics[7] workstations — each one around $100,000 in the mid-1990s, the only machines that ran the PlayStation toolchain.[8] Not because any one function is hard to write. Because understanding each one is what lets you choose.

Crash Bandicoot PAL cover art
Andy Gavin

On constrained hardware you do not want the full standard library — you want the functions your project actually uses, and where a general-purpose version does more than you need, a leaner version written to your exact requirements costs less. You cannot make that trade-off for code you have not understood.

That is what libtci is. Not a replacement for the standard library, which is better optimised than anything we will write and which we will switch to when we start porting to console hardware. An exercise in understanding it. libtci reimplements libc — each function written clearly enough to see why it works. When the time comes to use strlen instead of tci_strlen, you will know what is happening inside it.

The implementation pages build libtci from the ground up, one group of functions at a time. Pointers first — the concept behind every function in the library — then memory operations, then strings, then characters, then the heap, then the static-library build. Every concept earns the next one. Start at Setup.

Implementation

Setup

Begin Implementation
  1. 0Setup
  2. 1Pointers
  3. 2Memory
  4. 3Strings
  5. 4Characters
  6. 5The Heap
  7. 6The Library
  8. 7Pointer Depth

Footnotes

  1. SN Systems - Wikipedia

  2. Naughty Dog - Wikipedia

  3. Naughty Dog

  4. Crash Bandicoot - Wikipedia

  5. Crash Bandicoot

  6. Andy Gavin - Wikipedia

  7. Silicon Graphics - Wikipedia

  8. Making Crash Bandicoot – part 3 | All Things Andy Gavin