This is an example project using llvm-mos targeting the MMC1 mapper. It's very much work-in-progress. There will be more to come.
Note: I've only tested this on Ubuntu 22.04 (bash) and Windows 11 (powershell). YMMV.
- llvm-mos SDK
- This needs to be findable by CMake. You can set CMAKE_PREFIX_PATH to
path/to/llvm-mosor you can addpath/to/llvm-mos/binto your PATH
- This needs to be findable by CMake. You can set CMAKE_PREFIX_PATH to
The rest of these should be available in your PATH:
- CMake
- Ninja
- Python 3
- Pillow (10.1.0 or higher) - for converting PNG to CHR
If you're familiar with CMake, have a quick glance at build.sh and decide whether you want to use it. Ninja and "Unix Makefiles" generators are known to work. Otherwise...
To build the project, simply run build.sh ('nix) or build.ps1 (Windows). This will configure CMake and compile the ROM to ./build/nes-starter-kit.nes.
The build script will pass arguments to ninja so you can do, e.g.:
./build.sh cleanYou can also set the build type like:
BUILD_TYPE=Release ./build.shThe default is RelWithDebInfo.
For maximum productivity you'll want to get familiar with the way CMake works. Here's a quick overview grafted a conversation in llvm-mos discord:
CMake lets you generate build-system scripts (visual studio projects, makefiles, Ninja build scripts, etc.) appropriate for whatever system you're developing on. Then you use those tools to actually do the build. This project uses Ninja by default.
CMakeLists.txt files are (mostly) declarative configuration for various targets (binaries, libraries, and such), their relationships, dependencies, and the way they get built. When you first run cmake, all of the results of processing CMakeLists.txt get baked into the build directory.
Running cmake again in this directory will only update anything that has changed since it originally ran (new source code files, changes made to CMakeLists.txt itself, etc). A lot of the core configuration (build type, SDK location, etc.) remains fixed. For example, passing a different CMAKE_BUILD_TYPE will have no effect. If you want to change the configuration, you need to remove the CMakeCache.txt and CMakeFiles dirs from inside build/ dir, remove the build/ dir itself, or make a new config-specific build dir.
The usual workflow is to make a build directory, cd into it, then do cmake [options] ... This uses the CMakeLists.txt of the parent directory to do the configuration, and the results of the configuration are saved to the current build dircetory. Then you can issue your normal build system commands from there (e.g. ninja run).
To configure for a different build type, you pass -DCMAKE_BUILD_TYPE=[something]. something can be one of Debug, Release, RelWithDebInfo, and MinSizeRel. This project's .gitignore filters out any directory that starts with build. So you can easily have several build directories each with a different configuration.
You can load the ROM manually from the build/ directory.
There is also a run target which you can use with ninja or the build script:
.\build.ps1 runBy default this will attempt to launch the ROM with your system's default app associated with .nes files. You can set the EMULATOR environment variable to use a specific program.
You can set the name of the project in CMakeLists.txt. Look for the line that starts project(nes-starter-kit...
Any new files you add to src/, including any subdirectories, will be compiled. The project is currently set to support C++ and Assembly, but you can customize this by changing the project declaration mentioned above.
PNG files added to chr/ will be automatically converted to .chr files during the build. See chr/make_chr.py for info on how to make compatible images. You will also need to add a new .incbin directive in chr/chr.s to incorporate them into the ROM.
llvm-mos includes a custom clangd server that knows how to handle llvm-mos-specific extensions, system include directories, etc. To set this up, rename .vscode/example_settings.json to .vscode/settings.json or follow the instructions on the llvm-mos wiki.
Note: the build scripts above already include -DCMAKE_EXPORT_COMPILE_COMMANDS=ON.
I'd like this project to demonstrate all the core aspects of NES development. Here's what I've currently got planned:
- Sprite animation
- Controller input
- CHR bank switching
- Scrolling
- Audio
- PRG bank switching
- Generate Visual Studio projects with cmake
