Preliminary version: details are not finalized, and may change after discussion period.
A romless NES program is one which runs from RAM rather than ROM. Before being run, its data is loaded into the various RAM areas in the NES and cartridge. The program doesn't care how the data is loaded, allowing it to be stored in more than one format. The preferred format is a standard iNES file, allowing them to be run on anything. Most importantly, programs can be uploaded from a PC to a NES via a serial link cable, allowing quick development and testing on a low-cost cartridge.
For full details, see the specification.
PC upload isn't finished yet. It's working, but needs a few bugs fixed and documentation to be completed.
Normally, running programs on a NES requires a programmable cartridge of considerable cost, and removal of the cartridge each time the program is modified. The romless format was created to solve these problems.
Romless programs run from RAM in the NES and cartridge. To get them there, a small bootloader runs on the NES and receives data via a serial cable connected to the PC and writes it to RAM. The bootloader gives the PC full control over the NES.
Many cartridges are suitable for running romless programs. The only requirement is that they have a bootloader on their ROM:
Different cartridges have different RAM capacities and mapper chips. Romless programs can be written so that they only require a minimum of cartridge features, and thus work on multiple cartridge types. For example, a program can be made to run from the RAM inside the NES so that it works even if the cartridge doesn't have WRAM.
Romless programs are normally stored as standard iNES files. They include a built-in loader so that they work on any emulator or programmable NES cartridge, without any need to connect to a PC. In this way, they act like normal NES programs and don't require anything special to run.
NMI and IRQ interrupts can be used as long as the cartridge has interrupt handlers in ROM that forward them to the romless program's own vectors held in RAM. Special features of the cartridge can also be used, for example changing the mirroring mode on MMC1 and MMC3, or using the MMC3's scanline interrupt.
The romless format offers
Download examples and support files for the ca65, asm6, nesasm, and wla-dx assemblers: romless.zip
Before a romless program is run, its data is loaded into the various memory areas: RAM, WRAM, CHR RAM, nametables, and palette. Zero-page and most of the stack are cleared to 0, as well as the CPU, APU, and PPU registers. A second set of NMI, reset, and IRQ vectors is kept in RAM at $7FA-$7FF, and loaded as a part of loading RAM. The program is started with a JMP ($7FC) instruction.
A program's source code generally follows this template:
MAPPER = 1, 4, etc. or omit if no mapper needed V_MIRRORING = 0 or 1, or omit if it doesn't matter NO_INTERRUPTS = 1 if nmi and irq aren't defined .include "romless.inc" ; required reset: ; required ... nmi: ... irq: ... BEGIN_WRAM ; $2000 bytes ... BEGIN_CHARS ; $2000 bytes ... BEGIN_SCREENS ; $800 bytes (only $400 if also using BEGIN_SCREEN2) ... BEGIN_SCREEN2 ; $400 bytes ... BEGIN_PALETTE ; $20 bytes ... END_ROMLESS ; required
Most sections optional: Everything above is optional, except those marked as required. Don't put an empty section if it's not needed, because that will cause the program to require that hardware present when running.
Little else needed: The .include "romless.inc" sets almost everything up, including iNES header, reserved areas, loader code, main vectors and vectors in RAM.
Code can go in WRAM: To put code in WRAM at $6000, move it after BEGIN_WRAM.
Unused bytes cleared: Any unused bytes of a section are filled with 0, except palette, which is filled with $0F (black).
Assembler | Commands to assemble program |
---|---|
ca65 | ca65 program.s ld65 -C romless.cfg -o program.nes program.o |
asm6 | asm6 program.s |
nesasm | nesasm program.s |
wla | wla -o program.s program.o wlalink linkfile program.o |
Assembler | Specifics |
---|---|
ca65 |
|
asm6 |
|
nesasm |
|
wla-dx |
|
A romless program can run on different hardware configurations, depending on what sections it defines. For example, a program that has its code in WRAM requires a cartridge that has WRAM, and thus can't run on a UNROM cartridge. To make a program runnable on the widest possible range of cartridges people might have, a program can indicate that it doesn't need a particular feature. The following features can be indicated as not used:
Feature | To indicate non-use | Allows running on | Uses |
---|---|---|---|
CHR RAM | omit CHARS section | CHR ROM | sound-only program |
WRAM | omit WRAM section | cart without WRAM | small program, picture display |
H/V mirroring | don't define V_MIRRORING | mapper with fixed mirroring | graphics without scrolling |
Mapper | don't define MAPPER | UNROM, MMC1, MMC3 | fixed mirroring, no special features |
Interrupts | define NO_INTERRUPTS | cart without interrupt forwarding | simple demos, music |
Contact Shay Green