NES targets
The NES is a particularly challenging compiler target, due to the extremely large number of configurations supported by the various "mapper" ASICs on its cartridges.
The generic nes
target contains only functionality that is generically applicable across mapper chips. Individual mappers each have their own derived target:
Number | Name | Target |
---|---|---|
000 | NROM | nes-nrom
|
001 | MMC1 | nes-mmc1
|
003 | CNROM | nes-cnrom
|
004 | MMC3 | nes-mmc3
|
Sections
PRG-ROM
If PRG-ROM banking is disabled, then data can be placed in PRG-ROM using the regular .rodata
C sections. Otherwise, data can be placed into a specific PRG-ROM bank using section .prg_rom_<bankno>
or any section that begins with .prg_rom_<bankno>.
. The load addresses of PRG-ROM banks begin at 0x01000000
. This allows the bottom 24-bits to represent a logical PRG-ROM address space, while the high byte being 0x01
indicates that the address is PRG-ROM.
CHR-ROM
If CHR-ROM banking is disabled, then data can be placed in CHR-ROM using the .chr_rom
section or any section that begins with .chr_rom.
. Otherwise, data can be placed into a specific CHR-ROM bank using section .chr_rom_<bankno>
or any section that begins with .chr_rom_<bankno>.
. The logical addresses of CHR-ROM banks begins at 0x02000000
. This allows the bottom 24-bits to represent a logical CHR-ROM address space, while the highest byte being 0x02
indicates that the address is CHR-ROM.
PRG-RAM
If PRG-RAM banking is disabled, then data can be placed in PRG-RAM using the .prg_ram
section or any section that begins with .prg_ram.
. Otherwise, variables can be placed into a specific PRG-RAM bank using section .prg_ram_<bankno>
or any section that begins with .prg_rom_<bankno>.
. The PRG-RAM is not initialized at program start, so any initializers given in C or data provided in assembly are ignored.
Symbol Configuration
As far as is possible, mappers are configured by assigning symbol values. These control the contents of the iNES 2.0 header in the resulting binary, as well as the addresses assigned to program sections. Some of the following values have logical sizes less than the full 32-bits available for symbol values. In such cases, only the lowest order bits are considered. For example, __prg_nvram_size_raw
corresponds to the high nibble of header field 10. This means that the lowest nibble of __prg_nvram_size_raw
is mapped to the high nibble of header field 10.
Symbol | Description |
---|---|
__prg_rom_size
|
KiB of PRG-ROM |
__chr_rom_size
|
KiB of CHR-ROM |
__prg_ram_size
|
KiB of PRG-RAM |
__prg_nvram_size
|
KiB of PRG-NVRAM |
__chr_ram_size
|
KiB of CHR-RAM |
__chr_nvram_size
|
KiB of CHR-NVRAM |
__mirroring
|
Bit 0 of field 6 |
__battery
|
Bit 1 of field 6 |
__trainer
|
Bit 2 of field 6 |
__four_screen
|
Bit 3 of field 6 |
__mapper
|
Mapper number. |
__console_type
|
Low two bits of field 7 |
__timing
|
Low two bits of field 12 |
__ppu_type
|
Low nibble of byte 13 when Vs. System |
__hw_type
|
High nibble of byte 13 when Vs. System |
__extended_console_type
|
Low nibble of byte 13 when Extended Console Type |
__misc_roms
|
Low 2 bytes of byte 14 |
__default_expansion_device
|
Low 6 bytes of byte 15 |
__prg_rom_size_raw
|
The most significant nibble is the lower nibble of field 9, and the least significant byte is field 4. Overrides __prg_rom_size .
|
__chr_rom_size_raw
|
The most significant nibble is the upper nibble of field 9, and the least significant byte is field 5. Overrides __chr_rom_size .
|
__prg_ram_size_raw
|
Raw value of low 4 bits of header field 10. Overrides __prg_ram_size .
|
__prg_nvram_size_raw
|
Raw value of high 4 bits of header field 10. Overrides __prg_nvram_size .
|
__chr_ram_size_raw
|
Raw value of low 4 bits of header field 11. Overrides __chr_ram_size .
|
__chr_nvram_size_raw
|
Raw value of high 4 bits of header field 11. Overrides __chr_nvram_size .
|
INCLUDE Configuration
In some cases, the linker script semantics are insufficiently powerful to configure the linker alone. In this case, linker scripts can be composed by `INCLUDE`-ing script files to build up a custom linker script (rather than using the default). The following script files are common to all targets.
Name | Description |
---|---|
common.ld
|
Functionality common to all linker scripts for a given target. Must be included. Included in default linker script. |
c-in-ram.ld
|
Place the writable C sections into NES RAM. Exactly one c-in- script must be included. Included in default linker script.
|
NROM, CNROM
INCLUDE Configuration
Name | Description |
---|---|
c-in-prg-ram.ld
|
Place the writable C sections into PRG-RAM. |
MMC1
Different PRG-ROM sizes of the MMC1 require different numbers of reset stubs to be available, so the PRG-ROM size must be set by INCLUDE, not by symbol. The below INCLUDE files automatically set the __prg_rom_size
header field to the corresponding value. The 512KiB PRG-ROM mode and PRG-ROM bank modes other than 3 are not yet supported, since the C runtime model currently used by the compiler is only really practical if a fixed bank is present where e.g. libcalls can be placed.
INCLUDE Configuration
Name | Description |
---|---|
c-in-prg-ram-0.ld
|
Place the writable C sections into PRG-RAM bank 0. |
prg-ram-16.ld
|
16 KiB of PRG-ROM without banking. |
prg-ram-32.ld
|
32 KiB of PRG-ROM without banking. |
prg-ram-32-banked.ld
|
32 KiB of PRG-ROM with banking. Initializes to PRG-ROM bank mode 3, bank 0. |
prg-ram-64.ld
|
64 KiB of PRG-ROM with banking. Initializes to PRG-ROM bank mode 3. |
prg-ram-128.ld
|
128 KiB of PRG-ROM with banking. Initializes to PRG-ROM bank mode 3. |
prg-ram-256.ld
|
256 KiB of PRG-ROM with banking. Initializes to PRG-ROM bank mode 3. Included in default linker script. |
MMC3
By default, the mapper is configured such that 24KiB of PRG-ROM is fixed, while a 8KiB bank is available at 0x8000. This can be altered by INCLUDEing alternative linker scripts.
In banking mode 0, the even banks are available at 0x8000, and the odd banks are available at 0xa000. In banking mode 1, the even banks are available at 0xc000, and the odd banks at 0xa000. This assignment can be changed on a per-bank basis by defining the symbol __prg_rom_NN
, where NN
is the bank number.
INCLUDE Configuration
Name | Description |
---|---|
c-in-prg-ram.ld
|
Place the writable C sections into PRG-RAM. |
prg-ram-banked-8.ld
|
One 8KiB bank is visible at 0x8000, and the last 3 banks are fixed contiguously at 0xa000. |
prg-ram-banked-mode-0.ld
|
Two independent 8KiB banks at 0x8000 and 0xa000, and the last 2 banks fixed contiguously at 0xc000. |
prg-ram-banked-mode-1.ld
|
Two independent 8KiB banks at 0xc000 and 0xa000, the next-to-last bank fixed at 0x8000, and the last bank fixed at 0xe000. |
prg-ram-fixed.ld
|
Up to 32KiB of fixed PRG-ROM. |