A Programming Language For Building NES Games

Generally speaking, writing your own games for retro consoles starts with C code. You’ll need to feed that through a console-specific tool-chain, and there’s certainly going to be some hoops to jump through, but if everything goes as expected, you should end up with a ROM file that can be run in an emulator or played on real hardware if you’ve got the necessary gadgetry to load it.

But NESFab takes things in a slightly different direction. While the code might look like C, it’s actually a language specifically tailored for developing games on the Nintendo Entertainment System (NES). The documentation claims that this targeted language not only compiles into considerably faster 6502 assembly than plain C on GCC or LLVM, but is designed to work around the strengths (and weaknesses) of the NES hardware.

Looking deeper into the example programs and documentation, NESFab offers quite a few quality of life features that should make developing NES games easier. For one thing, there’s integrated asset loading which automatically converts your image files into something the console can understand. One just needs to drop the image file into the source directory, open it in the code with the file function, and the build system will take care of converting it on the fly as the ROM is built. The nuances of bank switching — the organization of code and assets so they fit onto the physical ROM chips on the NES cartridge — are similarly abstracted away.

The obvious downside of NESFab is that, as with something like GB Studio, you’re going to end up putting effort into learning a programming environment that works for just one system. So before you get started, you really need to decide what your goals are. If you’re a diehard NES fan that has no interest in working on other systems, learning a language and build environment specifically geared to that console might make a certain degree of sense. But if you’d like to see your masterpiece running on more than just one system, working in straight C is still going to be your best bet.

27 thoughts on “A Programming Language For Building NES Games

  1. I love to see the effort folks are still putting into the older hardware, it really shows just how far you can get with pretty basic silicon and decent optimisations.

    The obvious downside of NESFab is that, as with something like GB Studio, you’re going to end up putting effort into learning a programming environment that works for just one system

    To me this doesn’t sound like anything very different to the usual ‘Straight C’ programming methods really – you learn all you need to know about the many library you are using* to provide all those functions you didn’t have to program yourself but that are not core. Not looked into this enough to spot any real differences to C in synatax etc, but if it looks like C odds are it is so C like in use you are not really wasting time – a very transferable skill.

    *At least one hopes you do, as it is perfectly possible to have no idea how the functions you are calling actually work or why it is a good/bad/secure/(etc) method for task at hand just copying the default examples, web search results or worse the ‘AI’s’ likely awful output…

    1. I was curious about this – these days we build everything on top of libraries and frameworks, so I would imagine that even modern projects on retro consoles would do something similar. Why write your own sprite loading function when there’s already a battle tested implementation you could just use? This extends beyond just functions to design patterns too, a framework might help you organize sprites into levels or lay out animations. Using a framework like this could make it easier to port to other platforms since you’d just have to reimplement some of the lower level portions.

      1. At least in regards to sprites, a generic library would give you very generic results if, say you had one for the SNES and Genesis. They both have different image formats, pixel depts and that don’t include the types of hardware collision.

        I mention the 16 but systems because it MAY be possible for a super generic “something on screen” library might be possible. But you go to years before that you are using quite a few hardware tricks to push the system itself.

        I do like the idea of a C lite language that can make porting a bit easier. Old 8-bit CPUs usually have bunches of oddies and features that just not taken advantage of in compilers.

    2. Yeah, I’d love to see engines that are super widely compatible and let you export to old consoles with just a button press.
      Especially with 3D engines it where it’s much simpler to do basic and automatic quality lowering to scaler performance.

    3. I love it too. I hope we see more game engines, especially 3D ones, that implement wide compatibility and scalability. It’d be so cool to see games that can run from ancient to modern with the main difference just being fidelity.

    1. The only thing relation to python I see is code block indents in place of curly brackets and no EOL markers. The syntax of logic and loops is closer to C with parenthesis removed (else if vs elif, && vs and, for init;condition;iteration vs for iterator, …)

      1. I’ve written code in about a dozen different languages, some incredibly esoteric. One language didn’t even have proper conditionals, yet I was able to write a HTML-stripper for UUEncoded files downloaded off usenet in it anyway. So yes, I do have an idea. I’ve simply come to prefer C-like syntax, and get quite annoyed when people call something C-like that isn’t C-like at all.

        1. Oh God, a dozen? A dozen would be nice!! I’m easily into the multiple dozens, and I’m not even exaggerating. I’ve written parsers which convert languages that are “close enough” to C from very C-like syntax into their native languages, which is exactly what’s going on here. Are we done comparing yet?

          It’s like a hybrid of C and Python. It’s close enough that if you know C syntax you can read it fine. You could write it in C syntax and transliterate it. It’s not like FORTRAN or COBOL or god, BASIC where entire syntax chains are different, or like the eye-watering terribleness of Ada where you have to remember “no no no equals does not mean assign”.

          Personally I would’ve made it closer to C, but I’m guessing he did it to make the parsing easier – the trick I would’ve done there is to use astyle to reformat C to a known standard, which regularizes the parsing and makes it easy. Plus since the C preprocessor is standalone, you can integrate the C preprocessor and suddenly it looks very C-like to people.

          But, like I said, a bit of preprocessing would trivially convert a very C-like syntax into this.

          “when people call something C-like that isn’t C-like at all.”

          Would you prefer it to be “an ALGOL-family language” or something? It’s clearly along the ALGOL chain rather than the FORTRAN/BASIC/etc. chain, and it definitely isn’t Lisp/Forth and isn’t syntactically close to Tcl either.

  2. “The obvious downside is that you’re going to end up putting effort into learning a programming environment that works for just one system.”

    Not if the environment is designed for multiple platforms! Japanese programmer Inufuto uses the homegrown “Cate” language to write the same game to a LOT of 8-bit retro machines at once. Source code for an example game has recently been released:

    https://github.com/inufuto/Cate_examples

  3. Several years back for my university final project I wrote a platformer game for the NES in 6502 Assembly. The choice was intentional as I’d never worked that close to the metal before, but at the time the only real alternative was compiling C down to ASM. The general feeling in the community at the time was that the compiled C code came out much too bulky for the NES. I’m interested to see how NESFab addresses that kind of problem.

    Incidentally, if you haven’t checked out the NES homebrew scene and have any kind of affinity for the NES I highly recommend having a look. It’s amazing what people have managed to squeeze out of the NES hardware.

  4. The problem with gb-studio isn’t that it’s targeting one piece of hardware. The problem is that it isn’t very good. Performance is awful compared to writing assembly. Part of that is due to how the libraries are made, and part of it is due to C and SDCC just not going a great job optimizing for the gameboy CPU.

    1. Because not all languages are equal. Assembly is powerful and you have lots of choices working with it, but it can be a real slog. The purpose of a language is not solely for portability between platforms, but also express different features, and convenience for the programmer.

    2. Writing in assembly language can work super well with a processor as simple as the 6502/c02/816; but I think very few people are familiar with how much can be done with a good macro assembler.

      My own productivity in, and enjoyment of, assembly language increased dramatically when I figured out that you can form nestable program-flow-control structure macros.  Gone are most of the labels and the normally visible branch and jump instructions.  I wrote and posted an article at http://wilsonminesco.com/StructureMacros/ which also has links to my macro source code.  In most cases, the macros produce exactly the same code you would do by hand, meaning there’s no memory or performance penalty; it’s just that now you don’t have to look at the ugly internal details every time.  They make the source code more readable and maintainable, make it more concise, make the programmer more productive, prevent bugs (because you can see what you’re doing better), and help you keep from losing control of the project.  There are other examples on my site, like at the bottom of my source-code page for bit-banging SPI with a 6522 VIA at http://wilsonminesco.com/6502primer/SPI.ASM .  You’ll find longer examples near the bottom of the page in my multitasking article at http://wilsonminesco.com/multitask/ .  My 6502 stacks treatise covers in greater detail how the assembler itself uses a stack in the formation and nesting of program structures, and near the bottom of the treatise’s page on forming nestable program structures with macros, at http://wilsonminesco.com/stacks/pgmstruc.html, there’s an example showing a CASE (called “switch” in C) structure, where you can mouse over the underlined source code parts to get the explanation of the assembler’s operation on the particular line.  “Stack” here refers to the assembler’s stack, not the 6502’s stack.

      I have a lot of experience with 65c02 and PIC16, which are very, very different, but I use the same macros for both, which makes it a lot less work to convert code from one assembly language to the other, meaning portability is improved.  (I also use other macros besides the structure macros discussed above.)

  5. “Generally speaking, writing your own games for retro consoles starts with C code”

    Actually it was done with assembly back then

    High level language was more 16 bit and for computers

  6. Interesting. This kind of reminds me of Action! for the Atari 8-bit… it didn’t come out for retrocomputing, it was actually available in the 1980s when the Atari 800 etc. were current. It was designed for witing games. to be much faster than BASIC, easier than assembly, built in support for ‘fancy’ graphics modes without having to hand-controll the graphics hardware (building your own display lists… if you want some entertainment read about the Atari graphics, you could change graphics modes every couple scan lines, including a new color pallette and everything.). And in some cases ‘faster than assembly’ if you were not hand optimizing your code as they did for various functionality the language provided.

  7. I really don’t see a downside to machine specific languages, I worked with niche architecture FORTH’s, C cross-compilers that are also specific to said niche microprocessors (especially dealing with the assembly ISA with FORTH and C on those microprocessors), and I don’t see a big deal working on machine specific interpreters, compilers, etc. Then again I grew up in the era of the microcomputer.

  8. Just write it in 6502 assembly. I’ve worked in it for a few games. Writing in assembly really isn’t as scary as people make it out to be. It’ll also make you a much better programmer in the long run.

Leave a Reply

Please be kind and respectful to help make the comments section excellent. (Comment Policy)

This site uses Akismet to reduce spam. Learn how your comment data is processed.