npm.io
0.1.6 • Published yesterdayCLI

chip8c

Licence
MIT
Version
0.1.6
Deps
0
Size
127 kB
Vulns
0
Weekly
0

chip8c

chip8c is a dependency-free CommonJS compiler for a small CHIP-8 language. It turns .ch8s source files into ROMs that can be loaded by a CHIP-8 emulator.

This first release is published as a beta. The compiler pipeline and encoded output are tested, but the language and backend are intentionally small.

Install

This release is a prerelease, so install the beta tag explicitly:

npm install --global chip8c@beta

Check the installation:

chip8c --version
chip8c --help

Compile a program

Compile a source file by providing an output path:

chip8c program.ch8s --output program.ch8

-o is the short form of --output:

chip8c program.ch8s -o program.ch8

The output is a raw CHIP-8 ROM. Load it at address 0x200 in your emulator.

Try the included example from a source checkout:

chip8c test.ch8s -o test.ch8

Draw the included sprite example:

chip8c examples/draw.ch8s -o draw.ch8

Load draw.ch8 at 0x200 in a CHIP-8 emulator. The language provides the clear() and draw(x, y, "hex bytes") builtins. Sprite strings contain one to fifteen two-digit hexadecimal bytes, stored in ROM data and loaded into I before the generated DXYN instruction runs.

Language guide

Declarations and values

Use let for mutable variables and const for values that cannot be assigned again. Values are unsigned 8-bit integers or booleans.

let counter = 3;
const limit = 10;
let enabled = true;

counter = counter + 1;
enabled = false;

Numeric literals may be decimal, hexadecimal, or binary:

let decimal = 42;
let hexadecimal = 0x2a;
let binary = 0b101010;
Arithmetic and comparisons

The operators +, -, *, /, and % are supported. Comparisons produce 0 or 1 and support ==, !=, <, <=, >, and >=.

let sum = 4 + 5;
let remainder = 10 % 3;

if (sum >= 9) {
        V0 = 1;
} else {
        V0 = 0;
}

Unary - and !, plus logical && and ||, are also supported.

Control flow

Use if/else and while statements. Braces are recommended for clarity.

let value = 0;

while (value < 10) {
        value += 1;
}
Functions

Functions can accept up to three parameters and return a value with return. Arguments are passed using the compiler's CHIP-8 calling convention.

function addOne(value) {
        return value + 1;
}

V0 = addOne(7);

V0 is the return register. Function arguments use V1, V2, and V3.

CHIP-8 registers and memory

Registers V0 through VF can be read and assigned. Global and local source variables are allocated in CHIP-8 memory automatically.

V0 = 10;
V1 = V0 + 2;

JavaScript API

The package also exposes the compiler from its CommonJS main entrypoint:

const { compileSource, compileFile } = require("chip8c");

const result = compileSource("V0 = 42;", "example.ch8s");
console.log(result.bytes);

compileFile("example.ch8s", "example.ch8");

The compiler pipeline is:

.ch8s -> lexer -> parser/AST -> semantic analysis -> IR -> CodeGenerator -> CHIP-8 encoder -> ROM

Limitations

  • CHIP-8 has no floating-point type. Numeric constants must be integer bytes from 0 through 255.
  • Arithmetic is 8-bit and wraps modulo 256 where applicable.
  • Functions support at most three parameters. Arguments use V1 through V3 and return values use V0.
  • Values outside one byte and addresses outside 0x000 through 0xFFF are compile errors.
  • Arrays, member expressions, timers, keyboard input, and display instructions other than clear() and draw() are not yet lowered by the backend.
  • Division and modulo by zero produce zero rather than trapping.

Development

Run the test suite with:

npm test

The tests cover exact encoded instruction bytes, comparison edge cases, and source-to-ROM compilation.

License

MIT. See LICENSE.

Keywords