aka Programming the NES in C

This is a replacement NES library for CC65. I have removed bunch of “useless” stuff from the default nes.lib and replaced crt0.s with a new version.

It probably won’t work on the current “official” CC65 release, so use the snapshot version from

Check knes/knes.h for info about what’s included. Also an incomplete platformer sample game is included. It demonstrates scrolling, collision checking, audio, DPCM, sprite 0 hit etc.

In “tools” directory there’s a utility to convert binary files to C headers.

I’m open to any suggestions. If you have some, my e-mail address is here. You can also reach me from

Some tips for programming the NES in C:

  • Compile with the “-Cl” switch, this makes local variables static. Otherwise they’re allocated from the CC65 software emulated stack, which is understandably very slow. One drawback to this is that every single temporary variable will now take a byte in RAM, even if it’s used very rarely. It might be a good idea to have some generic temporary global variables for that purpose¬†instead.
  • Use #pragma bss-name and/or data-name to place variables on the zero page.
  • Avoid passing parameters to functions — use global variables. If you need parameters, use the __fastcall__ calling convention, which can pass the first (rightmost) parameter in A and X registers.
  • Use the optimizer (“-Oirs” switch) BUT be aware that it might in some cases produce broken code. One such case is when you read the controllers by strobing $4016, then reading it eight times. The first read is optimized away. Of course when you’re using this library you can simply use read_joy().
  • If you define constant data in C code, make sure to make it “const” so that it goes to the RODATA (read-only data) segment. Otherwise it goes to the DATA segment and gets copied to RAM on program startup, wasting valuable resources. Warning: For some unknown reason, CC65 always seems to put multidimensional arrays on the DATA segment [This has been fixed in the latest snapshot version].
    // This is fine, goes to the RODATA segment.
    const byte foo[] = { 1, 2, 3, 4 };
    // This is wrong, it goes to the DATA segment.
    byte bar[] = { 5, 6, 7, 8 };
    // This goes to the DATA segment as well. :=(
    const byte baz[][ 4 ] = { { 9, 10, 11, 12 } };
  • Don’t use structs or at least be very careful with them! Instead of stuff like
    struct Foo
      int a;
      char b;
    struct Foo foos[ NUM_FOOS ];

    try using

    struct Foo
      int a[ NUM_FOOS ];
      char b[ NUM_FOOS ];
    struct Foo foos;

    for performance. 6502 doesn’t like interleaved data.

Download (1.44 MB)

Subscribe to the Comments Feed.

15 Responses to KNES

  1. Pingback: KNES v0.1 released | Kalle's Kanister (FOS)

  2. Pingback: KNES v0.1.1 | Kalle's Kanister (FOS)

  3. Jim says:

    This is very cool, much less mentally damaging than pure ASM. Now that you’ve updated Pornotracker to export Famitone, a new version of the KNES demo.nes using the Famitone library and one of your pornotracker tunes would be pretty darn handy.

    • fo says:

      The problem with FamiTone export is that it doesn’t support the full feature set of Pornotracker. To remedy this, I’ve been working on a 6502 player of my own recently. It’s called MUSE and supports all features of Pornotracker except for autodelay, PCM samples, PCM pulse and PCM saw. DPCM works of course. It also supports sound effects.

      I have some plans to incorporate MUSE in to the KNES demo as well. Maybe a different demo for FamiTone also, but we’ll see.

      • Jim says:

        I look forward to it! (I’m learning alot from your knes code.)

        • fo says:

          I have updated KNES to work with the latest version of CC65 now, as well as including a demo of how to use MUSE from a C project (among other things).

  4. Darkhog says:

    Hello. As user of Linux I’d like to know if I can use it with linux version of cc65 and if how to install it properly.

  5. Jim says:

    I’m a little confused by the Struct warning.
    I could do something like this:
    struct Bullet {
    byte x;
    byte y;
    byte life;
    byte facing;

    struct Bullet player_bullets[3];
    as long as i pass them around/manipulate their values using pointers? like:
    struct Bullet *blt = player_bullets;
    blt->x +=1;

    • fo says:

      It’s OK to use structs as long as you’re aware of what kind of code they produce. For example, indexing an array of structs requires the compiler to multiply the index by the struct size. As you said, pointers can alleviate the problem, but then the compiler may not be able to do some optimizations it otherwise could (every access to the pointer becomes indirect).

      So take the warning (actually, all of them) with a grain of salt. :)

  6. Luiz Fernando says:

    please email me, i developing a IDE to work with your knes.h, but i have some problems with your new code, contact me please, so i can talk with you

  7. Wolfeman says:

    Greetings, I do not know anything about programming so I do not know if this is possible, but you said you were open to suggestions… I would like to be able to use the NES as a synthesizer sound source without havign to invest in “MIDINES”. I have the NES Piano keyboard. I also have a RetroZone PowerPak. It would be great to have a “game” running on the PowerPak, that would allow me to access the sounds of the NES and tweak them like a traditional synthesizer gui. it would also be cool if some sort of sequencer could be implemented to create simple loops. key and tempo change along with sequence and patch saving would also be a nice feature.

    • fo says:

      It’s certainly possible to do something like that, but it’s not really related to KNES and personally I don’t have any plans to do anything like that. You may want to check out Neil Baldwin’s projects like NTRQ, Pulsar and PR8 for something similar, although I don’t think they have support for any kind of MIDI controllers right now.

Leave a Reply

Your email address will not be published. Required fields are marked *