This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

Romless NES program format

Romless NES program format
by on (#68275)
I've finished a preliminary version of a new romless NES program format that loads everything into RAM before running it. Romless programs are stored in standard iNES format and include the loader code, so they can be run in a normal emulator or on the PowerPak. There is the 2K RAM + 8K WRAM to load code into, 8K CHR RAM for graphics, and the two nametables can also be preloaded. Interrupts can be used, as well as mappers like MMC1 or MMC3.

Romless NES program format intro, along with specification and example code for ca65, asm6, nesasm, and wla-dx.

The main benefit is that they can also be uploaded from PC to NES via a serial cable. In the NES can be a PowerPak, or any other cartridge running a bootloader. This allows a quick edit-debug cycle when testing code on hardware. Since the cartridge in the NES doesn't need a reprogrammable ROM, cheaper cartridges can be used, allowing more people to run programs on hardware.

There are other uses too, for example compilations of romless programs are easy because they don't care how they're loaded. So you could compress several into a ROM, and have a menu to select which to run. The programs themselves wouldn't need to be modified at all to support this. This would be great for a game compo.

One interesting use is previewing graphics on a NES. There is a small include file that makes displaying yy-chr data files really easy. This allows editing the image, then a quick send from PC to NES to display it.

All four major NES assemblers are supported: ca65, asm6, nesasm, and wla-dx. An include file handles most of the file setup, so programs are short and minimal. Here's one that displays a message on screen:

 .include ""

reset:  ; The loader has already done the following for us:
        ; * Load palette, CHR RAM, nametables
        ; * Clear PPU registers
        ; * Wait for VBL
        ; Enable background
        lda #$08
        sta $2001
        jmp forever

        .byte 0,0,0,0,0,0,0,0, $00,$00,$00,$00,$00,$00,$00,$00 ; ' '
        .byte 0,0,0,0,0,0,0,0, $C6,$C6,$C6,$FE,$C6,$C6,$C6,$00 ; 'H'
        .byte 0,0,0,0,0,0,0,0, $FE,$C0,$C0,$FC,$C0,$C0,$FE,$00 ; 'E'
        .byte 0,0,0,0,0,0,0,0, $60,$60,$60,$60,$60,$60,$7E,$00 ; 'L'
        .byte 0,0,0,0,0,0,0,0, $7C,$C6,$C6,$C6,$C6,$C6,$7C,$00 ; 'O'

        dsb 10*$20 + 14 ; center on screen
        .byte 1,2,3,3,4 ; "HELLO"

        .byte $0F,$30,$30,$30  ; Black backgroud, white foreground


The above code will work with all assemblers, with only wla-dx requiring a change (.define NO_INTERRUPTS 1, since it doesn't support =).

I'm still working some bugs out of the PC loading, and haven't finished the documentation. At this point, the file format isn't finalized. I'm posting to get more feedback on it. It's been through a couple of weeks of work, so it's pretty close to what it'll be.

by on (#68283)
Cool. What I had before that in the same vein, was having the first 2 bytes of the mini-program (or raw data, for that matter) be the address that it gets loaded into (3 bytes would have made more sense though, for banking). That was actually hard-coded into the XMODEM code and was used for all transfers. Having it able to pre-load CHR and use interrupts is a pretty nice enhancement.

It may be good to leave a door open to larger WRAMs (maybe no point in outright supporting it yet). The CPLD board I'll be making has 32kB. PowerPak could have 32kB I think, but unfortunately there seems to be no support (not for 16kB/MMC1, at least).

by on (#68286)
So does that mean we can use our game to edit itself?

by on (#68290)
You would still need some way to store the modified program. This is just the standardization of a convention to link programs that run in NES RAM but can also be loaded as a ROM, much like the "mb.gba" convention on Game Boy Advance.

by on (#68291)
Yeah, it could edit any part of itself while it's running, and store and load itself from a PC's disk drive or some flashrom.

by on (#68299)
The main point is that it can be distributed and run as a normal iNES file, yet still run on low-cost development hardware, and uploaded without having to remove the cartridge. This rules out any rewriting by the game, or accessing data on the ROM (hence the name). The point isn't to support new features usable by the program itself, just to make development using the format easier. For small programs, especially ones used to test some technique on hardware, the quick edit-debug cycle is very useful.

Perhaps extra WRAM could be handled by adding some extra banks. There's no way I could get any contiguous $2000 byte chunks in the current 32K format, due to assembler limitations. The extra banks would be aligned, so work with assemblers like nesasm.

I'm really aiming for something fairly moderate at first, though. The two goals are kind of at odds: being able to run on low-cost cartridges, and supporting quick edit-debug cycle. The latter is useful for any hardware that the PowerPak can handle, but that tends to complicate the format so that it can handle every obscure mapper. Maybe just having the code for the PC uploader would allow one to customize it for special situations, since one wouldn't care about distribution then, just quick edit-debug.

My thought is that it might be big enough for small games, and thus a useful platform for homebrew stuff, allowing all the benefits for developing on it (easy testing, runs on anything, can be put into a compilation, good limitations for competitions).

by on (#68358)
I was going to ask "huh, why isn't 4-screen mirroring supported" but then I went to bootgod's db and saw that there never were any games released with CHRRAM and 4-screen mirroring.