Compile Rust code to GBZ80 (Work in Progress)
My first language is not English. It is always welcome to point out the awkward parts of this README.
^ filltest
example of GBDK-2020, ported to Rust.
- The Rust compiler can generate LLVM-IR for the ATMega328 processor. (which powers Arduino)
- LLVM-IR can be converted to C code using llvm-cbe.
- The C code can then be compiled to Z80 Assembly using sdcc.
- Z80 Assembly can be assembled into GBZ80 object code with sdasgb.
- The GBZ80 object code can be linked with GBDK libraries and built into a Game Boy ROM using lcc.
I referred to z80-babel for steps 1–3, and used gbdk-2020 for steps 4–5.
- Rust provides higher-level and better grammer than C.
- Rust's memory stability and strict types help you avoid to write incorrect code (even on a small device).
- Putting everything aside, it's fun!
My goal is to develop a Game Boy Development Kit that enables the creation of Game Boy games using Rust.
Thanks to GBDK, Z80 Assembly generated from Rust can call GBDK's low-level library functions (such as delay
, waitpad
, etc.).
My task is to wrap these functions in high-level Rust abstractions.
- rust
- avr-gcc
- avr-libc
- llvm
- llvm-cbe
- sdcc
This project is still a work in progress, and I haven't tested it outside of my development environment.
Dependencies may change as the project evolves.
I do not recommend that you build this project now. because this is WIP and I'm still testing many things.
But if you want to do it, Here is the description below.
- Install all dependencies in your linux (Use WSL for Windows)
- Build llvm-cbe in
./ext
directory. follow llvm-cbe's instruction to build it.
the path is./ext/llvm-project/llvm/build/bin/llvm-cbe
- Execute
cargo build --release
in./ext/rust-deps
- Now,
cargo build-rom
will build your GB ROM to./out/main.gb
# build GB ROM from Rust code
cargo build-rom
# build GB ROM from LLVM-IR
cargo llvm-rom
# ... from C code
cargo c-rom
# ... from ASM code
cargo asm-romm
- Call inline GB ASM functions in Rust
- Call the GBDK library in Rust
- Use
core
oralloc
libraries of Rust
- Some Rust functions use fast calling convention which not supported in
LLVM-CBE
. (alloc::Vec
orassert_eq!
etc. I'm finding a solution for it. - External crates are likely not supported.
Rust codes in ./source
bundled in one .rs file by rust-bundler-cp
Bundled Rust code is compiled to target avr-unknown-gnu-atmega328
.
This will provide 8-bit compatibility for z80.
Currently, nigtly Rust's LLVM version is 19. and LLVM-CBE's LLVM version is 17.
Keep compatibility through the replacement of new function or polyfill.
LLVM-CBE compile LLVM-IR to C code.
Unfortunetly, LLVM-CBE do not support some calling convention generated by Rust.
So, Some features from rust (like alloc::Vec
) can not be used.
Also, I'm considering If it can be replaced with llvm-gbz80
The generated C code is for GCC. Therefore, it goes through post-processing before it is entered into SDCC.
It's a simple string replacement right now, but it can be more complicated.
SDCC compile C code for GBZ80 (sm83
)
I used GBDK's build chain for this. GBDK's lcc
link ASM with GBDK libraries and build a complete Gameboy ROM file.