I had proposed to add Dendy support to the NES 2.0 format in 2016, here. Unfortunately, there was no active discussion. But now, in 2018, two important things happened. NSFe format now has Dendy support (in the regn chunk), and there is an another effort to add Dendy support to the NES 2.0 format, here. I have already participated in the latter topic, but now I go further and propose to extend all the NES-related formats in the same way. It is still possible to do, because all the formats are still have a very similar byte for this purpose. That's why I have created a new topic. I'm sorry that it is literally the third topic where I had written about the subject, but it is the first (and the last) dedicated one.
Overview of current situation.
iNES
original specification states:
UNIF
original specification states:
NES 2.0
The byte was moved and extended a bit, original specification states:
NSF
The header has this byte:
NSFe
The mandatory INFO chunk has this byte:
But it has a very flexible and unambiguous extension, the regn chunk:
Time to action
It is time to remove the ambiguity and to add feature parity to all the NES formats. All the above formats can be extended the same way, with preserving compatibility where it wasn't ambiguous before:
There is a list of supported systems by a ROM, and a preferred system selected in the ROM. A user of an emulator can choose a preferred system in the settings of the emulator: Auto, NTSC, PAL, Dendy, Force NTSC, Force PAL, Force Dendy. If Auto is specified, emulator will always use the preferred system specified in the ROM itself. If the user chooses NTSC/PAL/Dendy as preferred, the emulator checks if the preferred by user system is supported by the ROM, and if it is, it should use the preferred by user system. Otherwise, it should use preferred by ROM system. And if the user chooses to force NTSC/PAL/Dendy, the emulator just ignores the byte in the header and always uses the forced system.
Overview of current situation.
iNES
original specification states:
Code:
Byte Contents
---------------------------------------------------------------------------
9 bit 0 1 for PAL cartridges, otherwise assume NTSC.
bit 1-7 Reserved, must be zeroes!
---------------------------------------------------------------------------
---------------------------------------------------------------------------
9 bit 0 1 for PAL cartridges, otherwise assume NTSC.
bit 1-7 Reserved, must be zeroes!
---------------------------------------------------------------------------
UNIF
original specification states:
Code:
ID: [TVCI]
Length: BYTE
Revision: 6
Description: Television Standards Compatability Information set to:
0- Originally NTSC cartridge
1- Originally PAL cartridge
2- Does not matter
NOTE: ALL North American carts that are dumps of the North American
Version are NTSC. All licensed famicom games are NTSC.
It is important to mention that unlike iNES, it treats this byte not as a bitfield, but as an enum. First two values effectively are the same as the bit 0 from the byte 9 of the iNES header, but the third value effectively means that "both systems are supported".Length: BYTE
Revision: 6
Description: Television Standards Compatability Information set to:
0- Originally NTSC cartridge
1- Originally PAL cartridge
2- Does not matter
NOTE: ALL North American carts that are dumps of the North American
Version are NTSC. All licensed famicom games are NTSC.
NES 2.0
The byte was moved and extended a bit, original specification states:
Code:
Byte 12:
7 0
---------
xxxx xxBP
P: This is a PAL ROM. when set, indicates PAL mode.
B: When set, indicates this ROM works on both PAL and NTSC machines
(some of the Codemasters games actually will adjust the game depending
on if it detects you running on a PAL or NTSC machine. It adjusts the
timing of the game, and fixes the music).
Not many games would have this B flag set.
x: These bits are not used yet. They shall be maintained clear.
So, it is a mixture of what we have seen in the iNES and UNIF. This byte is a bitfield, and the spec clearly states that bit 0 set means "indicates PAL mode" (like in iNES), and bit 1 set means "it supports both NTSC and PAL". Unfortunately, description of these bits is ambiguous (it is not described how to treat the new bit 1 in combination with the old bit 0). That's why it is treated in different ways by different emulators. FCEUX: 00 - NTSC, 01 - PAL, 10 - NTSC, 11 - NTSC. Mesen: 00 - NTSC, 01 - PAL, 10 - NTSC, 11 - PAL. Nintendulator: 00 - NTSC, 01 - PAL, 10 - leave as is, 11 - leave as is. IMHO, Mesen has the most logical behavior, just because it does not contradict to the clear statement about meaning of the bit 0 which was borrowed from the iNES.7 0
---------
xxxx xxBP
P: This is a PAL ROM. when set, indicates PAL mode.
B: When set, indicates this ROM works on both PAL and NTSC machines
(some of the Codemasters games actually will adjust the game depending
on if it detects you running on a PAL or NTSC machine. It adjusts the
timing of the game, and fixes the music).
Not many games would have this B flag set.
x: These bits are not used yet. They shall be maintained clear.
NSF
The header has this byte:
Code:
offset # of bytes Function
----------------------------
$07A 1 BYTE PAL/NTSC bits
bit 0: if clear, this is an NTSC tune
bit 0: if set, this is a PAL tune
bit 1: if set, this is a dual PAL/NTSC tune
bits 2-7: not used. they *must* be 0
Similar to NES 2.0. Ambiguous.----------------------------
$07A 1 BYTE PAL/NTSC bits
bit 0: if clear, this is an NTSC tune
bit 0: if set, this is a PAL tune
bit 1: if set, this is a dual PAL/NTSC tune
bits 2-7: not used. they *must* be 0
NSFe
The mandatory INFO chunk has this byte:
Code:
offset # of bytes Function
----------------------------
$0006 1 BYTE PAL/NTSC bits
bit 0: if clear, this is an NTSC tune
bit 0: if set, this is a PAL tune
bit 1: if set, this is a dual PAL/NTSC tune
bits 2-7: not used. they *must* be 0
Similar to NES 2.0. Ambiguous.----------------------------
$0006 1 BYTE PAL/NTSC bits
bit 0: if clear, this is an NTSC tune
bit 0: if set, this is a PAL tune
bit 1: if set, this is a dual PAL/NTSC tune
bits 2-7: not used. they *must* be 0
But it has a very flexible and unambiguous extension, the regn chunk:
Code:
offset # of bytes Function
----------------------------
$0000 1 BYTE Bitfield of supported regions.
bit 0: NTSC
bit 1: PAL
bit 2: Dendy
bit 3-7: Reserved (always clear)
$0001 1 BYTE Specifies preferred region if multiple regions are supported. (Optional)
0 - NTSC
1 - PAL
2 - Dendy
This chunk adds support for the Dendy region, and the ability to specify which region is preferred (for players that can support multiple regions). This chunk should appear after the INFO chunk, and overrides its region data (byte 6).
So, it overrides byte 6 if is present. It is aware of existence of Dendy systems. Also it specifies both list of supported systems and a preferred system, so an emulator have enough information about how this ROM can be executed properly.----------------------------
$0000 1 BYTE Bitfield of supported regions.
bit 0: NTSC
bit 1: PAL
bit 2: Dendy
bit 3-7: Reserved (always clear)
$0001 1 BYTE Specifies preferred region if multiple regions are supported. (Optional)
0 - NTSC
1 - PAL
2 - Dendy
This chunk adds support for the Dendy region, and the ability to specify which region is preferred (for players that can support multiple regions). This chunk should appear after the INFO chunk, and overrides its region data (byte 6).
Time to action
It is time to remove the ambiguity and to add feature parity to all the NES formats. All the above formats can be extended the same way, with preserving compatibility where it wasn't ambiguous before:
Code:
Byte 9 in iNES, or Byte 12 in NES 2.0, or TVCI byte in UNIF, or byte $7A in NSF:
7 0
---------
xdpn xxBP
The byte consists of two nibbles. The higher nibble describes which systems are supported, the lower nibble describes which system is preferred.
If higher nibble is 0, use legacy interpretation:
0000 0000 - NTSC only
0000 0001 - PAL only
0000 0010 - Supports NTSC and PAL, but NTSC is preferred
0000 0011 - Supports NTSC and PAL, but PAL is preferred
Otherwise, higher nibble describes supported systems:
d - Dendy
p - PAL
n - NTSC
Lower nibble (bits BP) describes preferred system:
00 - NTSC (a legacy emulator will use NTSC)
01 - PAL (a legacy emulator will use PAL)
10 - Dendy with fallback to NTSC (a legacy emulator will use NTSC)
11 - Dendy with fallback to PAL (a legacy emulator will use PAL)
If the lower nibble chooses the system which is not marked as a supported system in the higher nibble, fallback to the legacy behavior. Bits 2,3 and 7 should be ignored by emulators, and should be 0 in ROMs.
It describes both how to treat original format with two bits unambiguously, and how to treat extended format. It will be possible to use exactly the same code for extracting information from this byte for all the NES formats.7 0
---------
xdpn xxBP
The byte consists of two nibbles. The higher nibble describes which systems are supported, the lower nibble describes which system is preferred.
If higher nibble is 0, use legacy interpretation:
0000 0000 - NTSC only
0000 0001 - PAL only
0000 0010 - Supports NTSC and PAL, but NTSC is preferred
0000 0011 - Supports NTSC and PAL, but PAL is preferred
Otherwise, higher nibble describes supported systems:
d - Dendy
p - PAL
n - NTSC
Lower nibble (bits BP) describes preferred system:
00 - NTSC (a legacy emulator will use NTSC)
01 - PAL (a legacy emulator will use PAL)
10 - Dendy with fallback to NTSC (a legacy emulator will use NTSC)
11 - Dendy with fallback to PAL (a legacy emulator will use PAL)
If the lower nibble chooses the system which is not marked as a supported system in the higher nibble, fallback to the legacy behavior. Bits 2,3 and 7 should be ignored by emulators, and should be 0 in ROMs.
There is a list of supported systems by a ROM, and a preferred system selected in the ROM. A user of an emulator can choose a preferred system in the settings of the emulator: Auto, NTSC, PAL, Dendy, Force NTSC, Force PAL, Force Dendy. If Auto is specified, emulator will always use the preferred system specified in the ROM itself. If the user chooses NTSC/PAL/Dendy as preferred, the emulator checks if the preferred by user system is supported by the ROM, and if it is, it should use the preferred by user system. Otherwise, it should use preferred by ROM system. And if the user chooses to force NTSC/PAL/Dendy, the emulator just ignores the byte in the header and always uses the forced system.