c62d2810 |
1 | **************************************************************************** |
2 | UNIF file format specifications |
3 | (Universal NES Image) file format |
4 | |
5 | Created by Tennessee Carmel-Veilleux (veilleux@ameth.org) |
6 | REV 7b, November 28th, 2000 |
7 | |
8 | |
9 | ***********THIS IS AN OPEN STANDARD. IT IS OPEN TO SUGGESTIONS************** |
10 | |
11 | Overview |
12 | -------- |
13 | The UNIF format is a portable, flexible REPLACEMENT of the NES standard |
14 | (Designed by Marat Fayzullin). It is a chunked file format in the lines of |
15 | the Amiga IFF (LBM), Microsoft RIFF (WAV) and Autodesk 3D studio mesh |
16 | files (3DS). The goal of having a chunked definition is to provide |
17 | flexibility and ease of implementation, as data is described in blocks |
18 | with type IDs referring to them and header information to provide a |
19 | selective data reading. The format uses symetric data conversion for |
20 | numerical compatibility between the different platforms' byte ordering. |
21 | The ordering used is the 6502 Byte order (Intel), so that no more |
22 | bickering arrises from people who do not appreciate Network Byte Ordering |
23 | (Motorola). |
24 | |
25 | *** |
26 | The extension suggested for use with this format is .UNF (.UNIF under Operating |
27 | systems which support longer extensions). |
28 | *** |
29 | |
30 | Byte ordering |
31 | ------------- |
32 | Byte ordering used throughout the file for DWORDs and WORDs is 6502 Byte |
33 | order. The 6502 byte order is LSB, least significant byte first |
34 | (Little-endian): |
35 | |
36 | 3 2 1 0 <- Byte order for MSB (Network Byte order, m68k, PowerPC) |
37 | 0 1 2 3 <- Byte order for LSB (80x86, 6502, Z80) |
38 | |
39 | Care must be taken to convert the WORDs and DWORDs if you are using a |
40 | non-LSB platform (Mac, Amiga, some others). |
41 | |
42 | File format |
43 | ----------- |
44 | 00h-1Fh : Header |
45 | 20h-EOF : Chunks |
46 | |
47 | I can not think of an easier format to describe :) |
48 | |
49 | Header |
50 | ------ |
51 | The 4-byte header contains the string "UNIF" , NON null-terminated, case |
52 | as written. This is for identification purposes, a little like .NES' "NES^Z" |
53 | It is followed by Revision number and reserved bytes. |
54 | |
55 | Format: 00h-03h: "UNIF" tag identifier |
56 | 04h-07h: DWORD -> Revision number, currently 4 |
57 | 08h-1Fh: Reserved for future usage |
58 | |
59 | Sample structure: |
60 | |
61 | structure UNIF_header [ |
62 | char identification[4]; /* MUST be "UNIF" */ |
63 | dword revision; /* Revision number */ |
64 | byte expansion[24]; |
65 | ]; |
66 | |
67 | Chunks |
68 | ------ |
69 | Each chunks is composed of 3 distinct elements: |
70 | 00h-03h: Chunk ID string |
71 | 04h-07h: DWORD -> Block Length of Data |
72 | 08h-?? : Data |
73 | |
74 | All the chunks are written sequentially in the file. If you do not understand |
75 | a chunk by its ID, simply jump over it using the data length information. |
76 | *** ALL THE CHUNKS ARE OPTIONAL *** |
77 | That means that there are NO mandatory chunks, and you support only the |
78 | ONES YOU WISH, passing over the others while you are interpreting the |
79 | file. |
80 | |
81 | Sample structure: |
82 | |
83 | structure UNIF_chunk [ |
84 | char chunk_ID[4]; /* Chunk identification string. Can also be considered a |
85 | number. ASCII format */ |
86 | dword length; /* Data length, in little-endian format */ |
87 | ]; |
88 | |
89 | The different chunks: |
90 | --------------------- |
91 | ******************************************************************************* |
92 | How chunks are described: |
93 | ID field: Contains the 4-characters string identifier for the chunk |
94 | |
95 | Length: Length of the block. If it is "??", then the block may have |
96 | variable data size depending on the cartridge. |
97 | |
98 | Revision: First revision in which the chunk appeared. If your reader supports |
99 | a lower revision, you might be unable to read the chunk, simply pass |
100 | over it. The Revision used by the cart is written in the header. The |
101 | number represents the Revision Number of the most recent chunk |
102 | contained in the file. Example : If you have 5 chunks of revision 1 |
103 | and 2 chunks of revision 4 in the file, the Revision number in the |
104 | header will be 4. |
105 | |
106 | Description: Complete description of the contents and encoding of the chunk |
107 | ******************************************************************************* |
108 | |
109 | ID: [MAPR] |
110 | Length: ?? (Suggested max: 32 chars) |
111 | Revision: 1 |
112 | Description: This is supplemental information about the mapper. DO NOT USE |
113 | A MAPPER NUMBER HERE ! Rather use the BOARD NAME. There is |
114 | already a list in progress describing each NES cart and the |
115 | board it uses. The string is NULL-TERMINATED. |
116 | |
117 | examples: N,R,O,M,,0 -> This "No mapper" |
118 | U,N,R,O,M,0 -> This is (LS161+LS32) |
119 | |
120 | NOTA: This mapper organization suggests that emulators must be rewritten |
121 | to emulate the ACTUAL CARTRIDGE HARDWARE, and not solely a case of another |
122 | mapper number. That means you have to make for UNROM: |
123 | 1- Mapper handler (74LS161+74LS32) |
124 | 2- CHR-RAM Handler |
125 | |
126 | Those components can be reused, since many boards only have a slight |
127 | difference in them compared to similar ones. |
128 | |
129 | **IT SHOULD BE NOTED THAT**: A board name tells you EVERYTHING there is to |
130 | know about a board. You do not need other chunks to tell you how much RAM |
131 | there is, or if it is VRAM. It is all implied by the board name. A list |
132 | will soon be distributed containing board name information. |
133 | |
134 | Address of board table for North American Games and Board Names description: |
135 | http://www.parodius.com/~veilleux/boardtable.txt |
136 | http://www.parodius.com/~veilleux/boardnames |
137 | |
138 | ID: [READ] |
139 | Length: ?? |
140 | Revision: 1 |
141 | Description: Commentaries for the user of the ROM image. In the case of a |
142 | homebrew game, this can be very useful to store credit and maker |
143 | information. *** This could be "Incitation to littering". Please do not |
144 | put garbage in there. It is meant for either mapper information or |
145 | licensing information for homebrew games.*** |
146 | |
147 | |
148 | ID: [NAME] |
149 | Length: ?? |
150 | Revision: 1 |
151 | Description: NULL-terminated string containing the name of the game. If not |
152 | present, use the filename as the name. |
153 | |
154 | ID: [TVCI] |
155 | Length: BYTE |
156 | Revision: 6 |
157 | Description: Television Standards Compatability Information set to: |
158 | 0- Originally NTSC cartridge |
159 | 1- Originally PAL cartridge |
160 | 2- Does not matter |
161 | NOTE: ALL North American carts that are dumps of the North American |
162 | Version are NTSC. All licensed famicom games are NTSC. |
163 | |
164 | ID: [DINF] |
165 | Length: 204 |
166 | Revision: 2 |
167 | Description: Dumper information block: |
168 | structure dumper_info [ |
169 | |
170 | char dumper_name[100]; /* NULL-terminated string containing the name |
171 | of the person who dumped the cart. */ |
172 | byte day; /* Day of the month when cartridge was dumped */ |
173 | byte month; /* Month of the year when cartridge was dumped */ |
174 | word year; /* Year during which the cartridge was dumped */ |
175 | char dumper_agent[100]; /* NULL-terminated string containing the name of |
176 | the ROM-dumping means used */ |
177 | ] |
178 | |
179 | ID: [CTRL] |
180 | Length: BYTE |
181 | Revision: 7 |
182 | Description: Bitfield containing information about the controllers used by the |
183 | cartridge. |
184 | |
185 | Bit 0: Regular Joypad |
186 | Bit 1: Zapper |
187 | Bit 2: R.O.B |
188 | Bit 3: Arkanoid Controller |
189 | Bit 4: Power Pad |
190 | Bit 5: Four-Score adapter |
191 | Bit 6: Expansion (Do not touch) |
192 | Bit 7: Expansion (Do not touch) |
193 | |
194 | ID: [PCK0] through [PCKF] |
195 | Length: DWORD |
196 | Reivision: 5 |
197 | Description: This block contains a 32-bit CRC which can be used to make |
198 | sure that the ROM content matches a checksum when burning on EPROM. This |
199 | block provides a checksum for [PRG0] through [PRGF] inclusively |
200 | |
201 | ID: [CCK0] through [CCKF] |
202 | Length: DWORD |
203 | Reivision: 5 |
204 | Description: This block contains a 32-bit CRC which can be used to make |
205 | sure that the ROM content matches a checksum when burning on EPROM. This |
206 | block provides a checksum for [CHR0] through [CHRF] inclusively |
207 | |
208 | ID: [PRG0] through [PRGF] |
209 | Length: ?? |
210 | Revision: 4 |
211 | Description: Chunks containing the Binary data of the PRG ROM. If there |
212 | are more than 1 PRG chips on the PRG bus, use PRG1, PRG2, PRG4, etc. |
213 | The way PRGs are handled depends on the mapper and emulator. Most generaly |
214 | (99%), only use PRG0. (Some carts have been witnessed with 8 PRG ROMs). |
215 | |
216 | ID: [CHR0] through [CHRF] |
217 | Length: ?? |
218 | Revision: 4 |
219 | Description: Chunks containing the binary data of the CHR ROM. If there |
220 | are more than 1 CHR chips on the CHR bus, use CHR1, CHR2, CHR4, etc. The |
221 | way CHRs are handled depends on the mapper and emulator. Most generaly |
222 | (99%), only CHR0 is used. |
223 | |
224 | ID: [BATR] |
225 | Length: BYTE |
226 | Revision: 5 |
227 | Description: The presence of this block indicates that the board indeed |
228 | contains a battery. This is necessary because many boards have the |
229 | capability of a battery (the traces and holes are there), but they only |
230 | use RAM and don't add the battery at manufacturing time. Examples: |
231 | * SAROM: MMC1B, PRG ROM, CHR ROM, optional 8k of RAM (battery) |
232 | * SKROM: MMC1B, PRG ROM, CHR ROM, 8k optional RAM (battery) |
233 | |
234 | Both these boards (SAROM and SKROM) can have a battery, but usually they |
235 | don't have it. |
236 | |
237 | ID: [VROR] |
238 | Length: BYTE |
239 | Revision: 5 |
240 | Description: This is a VRAM Override. If this chunk is present, then the |
241 | CHR-ROM area will be considered as RAM even if ROM is present. This |
242 | overrides board identification. This is present so that homemade carts |
243 | which use NROM or others and replace the CHR-ROM with CHR-RAM can still be |
244 | interpreted (since NROM is always CHR-ROM in commercial games). |
245 | |
246 | ID: [MIRR] |
247 | Length: BYTE |
248 | Revision: 5 |
249 | Description: This chunk tells you how the hardwired mirroring is setup on |
250 | the board. The board name CANNOT tell you (in most cases) what the |
251 | mirroring is, since the all have solder pads to select the mirroring at |
252 | manufacturing time. The following values are legal: |
253 | |
254 | * $00 - Horizontal Mirroring (Hard Wired) |
255 | * $01 - Vertical Mirroring (Hard Wired) |
256 | * $02 - Mirror All Pages From $2000 (Hard Wired) |
257 | * $03 - Mirror All Pages From $2400 (Hard Wired) |
258 | * $04 - Four Screens of VRAM (Hard Wired) |
259 | * $05 - Mirroring Controlled By Mapper Hardware |
260 | |
261 | Conclusion |
262 | ---------- |
263 | This ends the specification for Revision 6 of UNIF. If you have ANY |
264 | suggestions to make regarding the UNIF file format, such as chunk ideas or |
265 | modifications, or would like to collaborate to the elaboration and design |
266 | process, e-mail me at veilleux@ameth.org. |
267 | |
268 | A multi-platform C Code Library for UNIF support was made by Evan Teran. It |
269 | is available at http://www.pretendo.org/~proxy/. |
270 | |
271 | [References] |
272 | {.NES file format specifications} by Marat Fayzullin (fms@cs.umd.edu) |
273 | {NESDEV mailing list} by Various authors |
274 | {NES technical documentation} by Jeremy Chadwick (yoshi@parodius.com) |
275 | |
276 | [Credits] |
277 | Neal Tew for his neat emulator and great contribution to the NESdev |
278 | community. |
279 | |
280 | Jeremy Chadwick (yoshi@parodius.com) for his contribution to the NESdev |
281 | community and great advice over the time. |
282 | |
283 | Mark Knibbs (mark_k@iname.com) for his excellent web site as well as his |
284 | more than honorable contribution to the NES world |
285 | |
286 | Matthew Conte (itsbroke@classicgaming.com) for his CajoNES and Nofrendo |
287 | programs |
288 | |
289 | Michael Iwaniec (mrbananmos@yahoo.com) for his interest in UNIF and |
290 | constructive criticism. |
291 | |
292 | Kevin Horton (khorton@iquest.net) for his proposals and support of |
293 | UNIF. He's also been a fantastic help to me in my learning curve of the |
294 | NES's hardware aspects. |
295 | |
296 | /Firebug/ (firebug@cfl.rr.com) for the ideas brought with NIFF |
297 | |
298 | T. Alex Reed {W1k} (rizen@netzero.net) for suggestions of additions |
299 | to UNIF. He also pointed out some mistakes in the original specifications. |
300 | |
301 | Evan Teran {PrOxY} (emt3734@rit.edu) for making suggestions as well as |
302 | writing a .NES->UNIF converter and the LIB_UNIF library. |