• Stars
    star
    227
  • Rank 175,900 (Top 4 %)
  • Language
    TypeScript
  • License
    MIT License
  • Created about 3 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

πŸ•Ή TypeScript Embedded GameBoy Macro Assembler

TEGA: TypeScript Embedded GameBoy Macro Assembler

TEGA is a TypeScript library (also usable in JS) for programming and creating GameBoy ROM images that can be played in an emulator or on real hardware via a flashcart.

It exposes a type safe API for all SM83 assembly instructions, defining inline bytes (in the form of TypedArrays), moving around in ROM space, and symbols, as well as definitions of the memory map layout, hardware registers and their important bitfield postitions (based on hardware.inc). It also provides facilities for creating type safe abstractions (macros) using all the regular language features of TS. This means that you can easily generate code using all of your favourite libraries like lodash and ramda.

A Game Example: Block Jump

A full game example can be found in ./src/block-jump. This game is based on the dinosaur jumping offline game in google chrome, and features, amongst other things:

  • multiple modules
  • use of the "standard library"
  • random number generator strategies
  • tile map compression
  • physics and collision
  • virtual address offsetting

There is a video that goes into some depth about TEGA and Block Jump on the Low Byte Productions YouTube channel.

The Juicy Details

TEGA generates the function definitions for all of the assembly operations automatically based on the dmgops.json file in izik1's gbops repo. This file is used to generate the excellent gbops website, which provides a highly detailed opcode table for the GameBoy, with tons of useful information like cycles take per op, memory operation breakdown per cycle, etc. In TEGA, the only name of the operation and its opcode are needed to generate overloaded, type safe function definitions for each assembly instruction. For example, 40 overloads are generated for the LD instruction. If you're curious about the exact transformation from JSON to TypeScript, check out the scripts/ops-generator.ts file this repo.

The SM83 CPU (which is a kind of a mix between a z80 and an 8080, but with some extra custom stuff thrown in the mix) has 256 opcodes, of which 11 are considered are undefined and will lock up the CPU. One of the opcodes - 0xCB - is a "prefix", which opens up another 256 opcodes - which mostly provide single bit operations for the 8 bit registers, as well as some extended rotations, shifts, and swaps.

Each operation returns a description of the operation, along with any dynamic (immediate) arguments it takes. At assembly time, the assembler maintains a buffer with an offset (starting at 0x150, the entry point located just after the cartridge header), and iterates through the operations, filling in opcodes and immediate values as it goes.

Of course, there are also symbolic values like labels, references, and size calculations. A label can be created with the label function, which returns a description of the label. When the assembler encounters a label definition, if it hasn't already been defined, it associates the label name with the current offset. When the assembler encounters an instruction that includes a symbol reference, it makes a note to revisit it after the operations have been processed - including the offset and symbol reference object - and moves the offset forward by the size required by the instruction.

The operations moveTo and inlineBytes move the assemblers internal offset and insert bytes directly into the ROM, respectively.

When all operations have been processed, the assembler revisits the symbol references found during iteration, and attempts to resolve them. If it is unable to resolve a symbol, it means it was never defined at all, and will throw an error. Otherwise, the correct 8 or 16 bit value is inserted into the ROM buffer.

Finally the header data is inserted and the checksum computed. Though configurable header information can be passed to TEGA, most of the fields relate to manufacturer codes and cartridge type. Cartridge type is currently limited to "32kb ROM Only", though this is a fairly straightforward restriction to remove. The header includes 2 separate checksum calculations: one on the header - which is checked for validity and will not boot on real hardware if incorrect - and one global checksum across all bytes, which is not checked at any point.

As a point of interest, Nintendo's original method for limiting unauthorised 3rd party developers was to force all games to include a copy of the Nintendo logo in the header of the ROM, which is checked against the console's built-in bootrom for validity. If the logo doesn't match, the GameBoy will lock up in the bootrom and the game will never launch. If an unauthorised developer includes the logo, they can be sued for trademark infringement! Though the GameBoy is more than 3 decades old at this point, there is still hesitancy in the emudev and homebrew communities towards including such legally murky byte sequences - though in an assembler it's an absolute requirement. And I have to admit I have continued this cycle of paranoia by not including the bytes directly in my own code, but rather a sequence of bytes that can be xor'd with another known value to produce the original sequence. I honestly think it's pure superstition at this point, but also kind of funny if nothing else.

Current support

  • 32kb ROMs only
  • All (documented) assembly instructions
  • Symbolic values
    • Labels and references to labels in instructions
    • Size calculations determined at assembly time
    • Current address / current instruction address
  • Interface for defining blocks - a group of instructions and/or data that generates and inserts symbols for the start/end and calculates and exposes the size. Can be used for macros, subroutines, interrupt handlers, etc
  • Generates a header with valid checksums

Future plans

  • Higher level macro abstractions
  • Larger ROM sizes / MBC possibilities
  • Facilities for automatically converting and loading images to tile data / tile maps

More Repositories

1

super-expressive

🦜 Super Expressive is a zero-dependency JavaScript library for building regular expressions in (almost) natural language
JavaScript
4,464
star
2

construct-js

πŸ› οΈA library for creating byte level data structures.
TypeScript
1,349
star
3

arcsecond

✨Zero Dependency Parser Combinator Library for JS Based on Haskell's Parsec
TypeScript
500
star
4

16bitjs

πŸ’» A 16-bit virtual machine, including assembly language with 37 instructions, binary assembler, and a step through debugger
JavaScript
470
star
5

githublog

I'm sick of complex blogging solutions, so markdown files in a git repo it is
338
star
6

hexnut

πŸ”© Hexnut is a middleware based, express/koa like framework for web sockets
JavaScript
208
star
7

React-Machinery

πŸ”₯ React Machinery provides a simple to use, component based approach to state machines in react.
JavaScript
105
star
8

vec-la

Tiny linear algebra library specifically for 2d
JavaScript
41
star
9

bewitched

πŸ§™πŸ» Command line hex editor
TypeScript
35
star
10

Lazy-Infinite-List

πŸ—’οΈ A Fantasy Land compliant Infinite List Data Structure
JavaScript
26
star
11

tiny-c-projects

A collection of small C projects - usually a minimal example of something interesting
C
25
star
12

vmfc

Stack-based VM Architecture in JavaScript. (Virtual Machine Fantasy Console)
JavaScript
23
star
13

vec-la-fp

↗️ A tiny (functional) 2d linear algebra library
JavaScript
22
star
14

arcsecond-binary

Binary parsers for arcsecond!
JavaScript
19
star
15

GMMK-Driver

An open source, reverse engineered control driver for the GMMK mechanical keyboard
TypeScript
19
star
16

AES-C

A (non-production) implementation of AES for educational purposes
C
14
star
17

teensy-nes

NES Emulator on a Teensy 4.1
C++
8
star
18

hexnut-client

JavaScript
8
star
19

trump-chain

JavaScript
8
star
20

kandinsky-js

🌈A tiny colour library
JavaScript
7
star
21

Classiest

🍸 Create classier classes with overloadable methods, getters, setters, and statics!
JavaScript
7
star
22

ebpf-usb

A tool for monitoring (specific) USB devices
Python
6
star
23

super-expressive-fp

SuperExpressive, but with a wrapped API for functional programming
JavaScript
6
star
24

Image-Glitcher

πŸ’’ Generates glitchy GIFs from JPEGs
JavaScript
5
star
25

rustack-machine

A simple stack machine in rust
Rust
5
star
26

bito

B.I.T.O - Programatic Beats Code Golfed In Your Browser
JavaScript
5
star
27

Steganography-C

Steganographic encoding implementation for hiding data in images
C
4
star
28

ATmega328P-Bare-Metal-Task-Switching

πŸŽ– A minimal implementation of a task-switching kernel in C for the ATmega328P chip
C
4
star
29

hexnut-sequence

Sequencing middleware for the HexNut framework
JavaScript
3
star
30

hexnut-handle

Simple hexnut middleware for dealing with connections and messages
JavaScript
3
star
31

algebraic-types

JavaScript
3
star
32

SpelBoy

A GameBoy (DMG) emulator written in TypeScript
TypeScript
3
star
33

modular-animation-synthesizer

https://francisrstokes.github.io/modular-animation-synthesizer/
JavaScript
3
star
34

frame-http

πŸ–ΌοΈLaughably minimal http framework combining the best parts of express and koa
JavaScript
3
star
35

ElessarOS

risc-v OS inspired by xv6
C
2
star
36

Brainfuck-Interpreter

Brainfuck interpreter using Jison
JavaScript
2
star
37

SNES-Controller-Arduino-Leonardo

Turn the SNES controller into a USB controller for use with an emulator
C++
2
star
38

zig-expressions

A regular expression engine written in Zig
Zig
2
star
39

lazy-do

Fantasy Land compliant do notation for lazy structures πŸ¦„
JavaScript
2
star
40

readme-cli

πŸ“– A CLI tool for rendering npm/github README files in the terminal
JavaScript
2
star
41

microcan

JavaScript
2
star
42

simple-transduce

A really simple transducer module to easily convert map-filter-reduce chains to single pass transducers.
JavaScript
2
star
43

creative-code-toolkit-fp

JavaScript
2
star
44

aoc-2023

Zig
1
star
45

WaveStrider

CMake
1
star
46

lambda-lang

JavaScript
1
star
47

hexnut-bodyparser

JavaScript
1
star
48

hexnut-restore-connection

HexNut middleware to restore a lost connection
JavaScript
1
star
49

app-and-bootloader

Simple app and bootloader implementation for STM32 using libopencm3
Makefile
1
star
50

salsa20-on-rp2040

My entry for LLJam0001: Salsa20 hardware encryption device using a Raspberry Pi Pico
C
1
star
51

microcan-fp

JavaScript
1
star
52

riscv-gateware-ts

A RISC-V processor with gateware-ts
TypeScript
1
star
53

bus-pirate

Bus Pirate integration for TS and JS
TypeScript
1
star
54

primer-js

πŸ•° A tiny (474 bytes minified + gzipped) library for creating normalised, unit independent timelines
JavaScript
1
star
55

zig-stm32-bare-metal

Minimal zig code to blink a LED for the STM32F401RE chip
Zig
1
star
56

Jazz-Chordr

Memorise common jazz chords https://francisrstokes.github.io/Jazz-Chordr/
JavaScript
1
star
57

Hindley-Milner-Parser

A Hindley-Milner type signature parser in haskell
Haskell
1
star
58

hexnut-with-observable

A Hexnut middleware for integrating with rxjs
JavaScript
1
star
59

Redux-State-Resolver

πŸ’‘Cleanly resolve a sequence of dependencies - write component logic that can assume the state has what it needs.
JavaScript
1
star
60

x86_64-Userspace-Emulator

C
1
star
61

hexnut-router

Routing middleware for HexNut
JavaScript
1
star
62

c-proj-init

A script to generate a skeleton C project, with a minimal Makefile and vscode debugging
JavaScript
1
star
63

autonotyper

An automatic typing engine tht can be plugged into anything
JavaScript
1
star
64

4FVM

Spiritual successor to 16bitJS
JavaScript
1
star
65

gibson-engine

A minimalist text game (interactive fiction) engine
JavaScript
1
star