Yeah, my title pretty much says everything. Thanks!
The simplest way to make a header is to just use .db/.byte directives (depending of the assembler) to enter the bytes that forms the header at the start of the ROM.
Simple example of iNES header for NROM:
Code:
PRG_COUNT = $01 ;$01 = 16 kB ROM, $02 = 32 kB ROM
SCROLL = $01 ;$01 = Horizontal Nametable Arrangement, $00 = Vertical Nametable Arrangement, $08 = Four-Screen
TVSYSTEM = $00 ;$00 = NTSC, $01 = PAL
.db "NES", $1a ;identification of the iNES header
.db PRG_COUNT ;number of 16 kB PRG-ROM pages
.db $01 ;number of 8 kB CHR-ROM pages (0 = CHR-RAM)
.db $00|SCROLL ;mapper 0 and scroll setting
.db %00000000 ;mapper 0, iNES header, no arcade
.db $00 ;no PRG-RAM
.db TVSYSTEM ;NTSC or PAL
.dsb 6, $00 ;reserved bytes in the header
Using macros like Tepples' makes it easy to make any kind of header.
Ca65 doesn't have a .dsb directive. It does have .repeat and .res directives (either would do the same), but that's unnecessary. Just indicate fill = yes in the cfg definition of the header "segment", and it will pad up to the "size".
The size of the header needs to be exactly 16 bytes, and that is external to the PRG-ROM. It is metadata for the emulator, telling it how big the ROMs are and what map to use.
dougeff wrote:
Ca65 doesn't have a .dsb directive.
Ah yes sorry, I forgot to say my example is using Asm6 syntax.
Also Ca65 would use .byte instead of .db to define bytes. Nesasm uses .db, but it has special directives for defining the header. Manually defining the iNES header using .db in Nesasm might mess with its annoying banking system I guess.
So, if I were to have the iNES header in the text file, then have a hexdump file and write that to an EPROM to use it on a real NES, would it work? Even though I could probably use a simple JMP to get the the section that has all of the code. Also kind of unrelated but I find it funny how this websites spellcheck doesn't count NES as a real word as well as Nintendo.
DementedPurple wrote:
So, if I were to have the iNES header in the text file, then have a hexdump file and write that to an EPROM to use it on a real NES, would it work? Even though I could probably use a simple JMP to get the the section that has all of the code. Also kind of unrelated but I find it funny how this websites spellcheck doesn't count NES as a real word as well as Nintendo.
* To the (Somehow spellcheck didn't notice that)
Quote:
So, if I were to have the iNES header in the text file, then have a hexdump file and write that to an EPROM to use it on a real NES, would it work? Even though I could probably use a simple JMP to get the the section that has all of the code. Also kind of unrelated but I find it funny how this websites spellcheck doesn't count NES as a real word as well as Nintendo.
Let's break this down line by line...
Quote:
iNES header in the text file
The header, is the first 16 bytes of a .NES file. It is binary. You can assemble a header, from a text file, if that's what you mean.
Quote:
hexdump file
A dump is a term refferring to...when there is a fatal crash of a program, a dump is the contents of RAM at the time of crash, saved to a file, for debugging purposes. I think you mean some other term.
Quote:
EPROM to use it on a real NES
No. You will never write a header in any ROM. It is just for emulation purposes. You would strip the header off if you wanted to burn it to a file an play in on real hardware. (Unless you mean on a flash cartridge designed to play .NES files, then you would leave the original .NES file intact with the header).
Code:
JMP to get the the section
header has no code.
EDIT: The last 6 bytes of the PRG ROM, has address for important things, the middle 2 bytes of that is the location of the start of the program. It's called the 'reset vector', and needs to be at address $FFFC-$FFFD. It points to the start address. When you press power or reset, the NES gets its program counter from here.
Finally. I still don't know what you are attempting to do.
So, if I can assemble a header, then how would I assemble with a CHR bank? Would I just make a simple .BIN file with the two files merged and change the extension or is it more complicated than that?
dougeff wrote:
Quote:
Finally. I still don't know what you are attempting to do.
I'm attempting to make an NES ROM to test my game.
And also, buy hexdump I meant a file with my codes OpCodes, not actually the hex values typed out, but the hex values characters.
DementedPurple wrote:
And also, buy hexdump I meant a file with my codes OpCodes, not actually the hex values typed out, but the hex values characters.
This is not what hexdump means. If you say "an object file" (the .o extension) or "a binary file" (the general term), people will understand what you are referring to.
DementedPurple wrote:
this websites spellcheck doesn't count NES as a real word as well as Nintendo.
That's your browser's spell check.
DementedPurple wrote:
I'm attempting to make an NES ROM to test my game.
The cc65 toolchain is a bit more flexible than other toolchains, but this also makes it somewhat more complicated to set up. You need to make these:
- An iNES header
- Code and data to put in PRG ROM
- Tile data to put in CHR ROM (optional, required if not using CHR RAM)
- Linker script to tell ld65 in what order to put all the above
One thing you could try is getting
nrom-template to build. Then you can replace various pieces of it with your program.
Pokun wrote:
The simplest way to make a header is to just use .db/.byte directives (depending of the assembler) to enter the bytes that forms the header at the start of the ROM.
Simple example of iNES header for NROM:
Code:
PRG_COUNT = $01 ;$01 = 16 kB ROM, $02 = 32 kB ROM
SCROLL = $01 ;$01 = Horizontal Nametable Arrangement, $00 = Vertical Nametable Arrangement, $08 = Four-Screen
TVSYSTEM = $00 ;$00 = NTSC, $01 = PAL
.db "NES", $1a ;identification of the iNES header
.db PRG_COUNT ;number of 16 kB PRG-ROM pages
.db $01 ;number of 8 kB CHR-ROM pages (0 = CHR-RAM)
.db $00|SCROLL ;mapper 0 and scroll setting
.db %00000000 ;mapper 0, iNES header, no arcade
.db $00 ;no PRG-RAM
.db TVSYSTEM ;NTSC or PAL
.dsb 6, $00 ;reserved bytes in the header
Using macros like Tepples' makes it easy to make any kind of header.
So how would I tell it what TV System, would I just give the name, would I have to use some quotation marks, would I just give it the name with no quotation marks, or does a number stand for that.
What tutorial have you been following? I know that at least the Nerdy Nights tutorial covers this topic, and should help you understand what to do.
DementedPurple wrote:
So how would I tell it what TV System, would I just give the name, would I have to use some quotation marks, would I just give it the name with no quotation marks, or does a number stand for that.
In my example the header is set to NTSC. If you want to change to PAL you would just change the third line:
Code:
TVSYSTEM = $00 ;$00 = NTSC, $01 = PAL
into
Code:
TVSYSTEM = $01 ;$00 = NTSC, $01 = PAL
I set up the three constants PRG_COUNT, SCROLL and TVSYSTEM so that I can quickly change them if I want to without messing with the header.
Note that SCROLL is the same thing as what is popularily called "nametable mirroring" (but mirroring is backwards: H-Scroll is Vertical Mirroring and V-Scroll is Horizontal Mirroring).
The wiki explains
iNES and
NES 2.0 headers.
I haven't been following a tutorial, I've been reading a book from the eighties.
Would the ines header for the original NESASM assembler work with the newer NESASM3?
The problem with building an NES game based only on a 6502 book it that the language is just one little piece of the puzzle... It's kinda like saying "I want to write a book about astrophysics in French": sure, you'll have to learn French in order to actually write the information down, but you do have to master the astrophysics too.
If you have previous game programming knowledge from other projects on other platforms, great, because these concepts (maps, objects, physics, AI, etc.) are generally the same no matter the platform. If you don't, these are subjects you should be researching as well.
As for the hardware-specific stuff, such as video, audio and input, knowledge of other platforms helps a lot too, since being familiar with the general concept allows you to simply look at the documentation (wiki) to know the specifics. If you don't yet know how old computers work (memory mapping, memory-mapped IO, mirroring, interrupts, timing, tiled graphics, etc.), a tutorial might gradually introduce these topics.
So I've used every single 6502 assembler out there, And used an example iNES header for every one, and still, none of them work.
DementedPurple wrote:
So I've used every single 6502 assembler out there, And used an example iNES header for every one, and still, none of them work.
Having made multiple NES games, I can assure you they *do* in fact work, you're just doing something wrong. If you are seeking help, you need to say what you've already tried, and what errors or unexpected behavior you're seeing.
https://opensource.com/life/16/10/how-a ... -questions
The simplest possible way to build an iNES header is to use NESASM and its iNES directives. The second simplest way is to use ASM6 and build the header using .db statements (following the specification from the wiki) right before the
.org $8000 statement that starts the PRG-ROM. The third way is to use ca65 and create a segment for the header, that you can fill using .byte statements.
You can download any NES program with source code written for any of these assemblers to see how the iNES header can be generated.
Edit: my old
ASM6 templates demonstrate one way to get ASM6 to output correctly formed NES ROMs for a few different mappers, header included.
Quote:
none of them work.
Have you been able to assemble anything (even a broken output file)?
For example, using asm6, write a text file with the conetents....
LDA #01
And asm6 should assemble it into a 2 byte .bin file, when viewed in a hex editor should look like (A9 01).
Can you confirm this much. This is my definition of "works". Also, don't give up yet. I'm an idiot, and I made an NES game. It's doable.
Perhaps you should visit the IRC #nesdev channel and ask more questions there.
I get an accurate binary file, but the problem comes when I try to run it in an emulator. All I get is an error message saying "Corrupt file". The emulator I'm using is Nestopia.
That's the information I was looking for. The assemblers work, but you don't know how to assemble a functional NES ROM.
I suggest you start by taking some existing (working) example code, and assemble that. Nerdy Nights. Then modify it to learn / try things.
The most standard ROM (NROM256) is...
16 bytes header
32768 bytes program code
8192 bytes graphics.
40976 bytes exactly, total.
You need to write a header that says 2 banks PRG and 1 bank CHR and mapper 0, for that to work.
With a correct header and sized file, you will get a gray screen that does nothing, even if everything else is filled with zeroes.
So I split the CHR and PRG data from a Super Mario Bros. ROM and removed the original iNES header. Now is there a way I could turn the binary file to a text document that can be compiled?
Disassembling binary code back into assembly code is not a trivial thing to do (it may take months or even years to get something usable, depending on the complexity of the game), so this is not a very good approach.
If you want to experiment with existing sugar, use proper source code that's been officially released by the original author.
Try one of these...
viewtopic.php?f=22&t=12847The newest version (0.4), and the asm6 source code.
EDIT, note this is a NROM 128 example.
16 bytes header
16384 bytes program...defined as 1 bank in the header
8192 bytes graphics...defined as 1 bank in the header
24592 bytes total.
Okay, So I've compiled my iNES header, then copied the binary file and pasted it after the header in a HEX editor, then I created a .BIN with the CHR and PRG including the header, then tried running it in an emulator and it doesn't work. And yes, I've changed the file extension from .BIN to .NES.
I see you have perseverance. That is a good skill.
Communication skills, needs improvement.
Or perhaps you vastly overestimate our ability to understand your issue.
I don't know what your header looks like, nor what PRG ROM you are using, nor what CHR, nor which assembler, nor which emulator. It doesn't sound like you are using source code, but posting that would be useful, if you were.
And 'doesn't work', doesn't work in a forum. Error message? Blank screen? Screen full of gibberish tiles? What are isn't working?
Building a functional NES file takes a lot of technical knowledge. Working from a working source code is probably where you should start.
No need to paste anything in a hex editor, you assemble your source files into a complete binary .nes file, header and all. The iNES header is defined in the source of those example programs.
When NES homebrewing was in its infancy, it was somewhat common for programmers to create the header separately using an hex editor and join everything in the end. But we've come to realize that having the assembler spit out a complete NES file is more convenient, so nearly everyone does it like that now.
Seriously, if you want an example that "just works" for ASM6, get one of the templates I linked to in my previous post. Just provide the CHR file (if using a CHR-ROM template) and you should get a valid ROM after assembling. It won't do anything because there's no code, but the result will be a valid NES file emulators will accept. From there you can start writing the actual code so your program can do things.
This is what my iNES header looked like: (The game was Super Mario Bros.)
Code:
.db "NES",$1a
.db $02
.db $01
.db $00|$01
.db $00
.db $00
.db $00
.dsb 6,$00
And what did you do with it? How large was the resulting ROM file? What happened when you opened it in the emulator?
The resulting ROM file was 120 kilobytes, and when I load it in Nestopia, I get invalid file.
You need to be more precise with the file size, since every byte makes a difference. Please find the size in bytes (in Windows you can right click and ask for the file's properties to see the exact byte size).
120KB doesn't sound like a valid size for an NES ROM file though. The closest thing would be an UNROM program, with 16 + 131,072 = 131,088 bytes. UNROM has 8 16KB PRG-ROM banks and no CHR banks (it uses CHR-RAM).
tokumaru wrote:
You need to be more precise with the file size, since every byte makes a difference. Please find the size in bytes (in Windows you can right click and ask for the file's properties to see the exact byte size).
120KB doesn't sound like a valid size for an NES ROM file though. The closest thing would be an UNROM program, with 16 + 131,072 = 131,088 bytes. UNROM has 8 16KB PRG-ROM banks and no CHR banks (it uses CHR-RAM).
It's exactly 119,952 bytes.
DementedPurple wrote:
It's exactly 119,952 bytes.
That sounds to me like pasting ASCII instead of HEX, but that's just my random guess. Hard to know without more precise info.
Well, I've copied and pasted the text in the binary file.
What kind of ROM are you trying to make? NROM? If so, anything beyond 40,976 bytes is wrong for sure. NROM needs to be either 24,592 or 40,976 bytes, depending on the size of the PRG-ROM.
It seems you're expecting the hex editor to do something it just doesn't do. Hex editors don't convert anything, if you copied text, you can only paste the exact same text, unmodified. File extensions also don't mean anything, they're just text meant to indicate what program should be used to open each file. Changing extensions doesn't modify the files in any way.
But really, you don't need hex editors or anything fancy, you just need an assembler. Write the correct stuff in it and you can generate a proper NES ROM file in one step.
I know that when I try to cut from FCEUX's hex editor, and paste into another hex editor, it doesn't paste as binary, but rather as a string of ASCII values.
Example...original binary = 0x95 cut pasted, becomes...
0x39,0x35. (The ascii values of '9' and '5'). That is of course wrong.
EDIT. The only way I can cut and paste from FCEUX, is, I can paste into a source code file (asm6) with the directive .hex (example .hex 95). I wouldn't recommend this.
Hex editors usually have options to copy as ASCII or as "hex string" and so on. The .hex directive is usefull if you have a very large table and you want to type it in a more compact manner.
DementedPurple whatever you are trying now doesn't seem to be working, so why don't you do what people have adviced you to for a long time now? Namely, instead of copying headers from existing games, start with a working example and work from there. I'd recommend to start as small as possible, so Tokumaru's NROM
template is your best bet. It is already a minimal working ROM so just assemble it in asm6 and see if you can load it in an emulator without errors. Then you can enter some code to see if that works.
Here is some minimal working code that gives you feedback that it's working by making noise from the TV speakers:
Code:
;Basic init code:
sei
cld
ldx #$40
stx $4017
ldx #$FF
txs
inx
stx $2000
stx $2001
stx $4010
;Make some noise:
lda #%00001000
sta $4015 ;enable noise
lda #$3F
sta $400C ;volume F, disable internal length and volume
lda #$81
sta $400E ;make some noise
lda #$00
sta $400F ;set length
main:
jmp main
Paste this under the "Reset" label in Tokumaru's NROM template.
Code:
.dsb 8192, $00 ;no graphics
Paste this line in the CHR-ROM bank (replace ".incbin "tiles.chr" with this line).
If you uploaded some of your failed attempts to the forum as attachments, then we might be able to better-understand what's going wrong where.
I don't want to be an ass, but...
I feel proper forum etiquette requires a follow up post.
Something along the the lines of "I got it to work, thanks", or "I'm still having issues with X", or "I'm too busy to work on this now, but I'm making slow progress"
When you have multiple people trying to help you, and you leave it hanging like this, it tends to generate bitter feelings, and people will likely be less enthusiastic about helping you in the future.
Sorry, I haven't had time to test it out. I'll get to that right now.
One question though, how would I know how many PRG banks I'm using? Would I type the code in a different text file, then see how big the binary file is and change the number of PRG banks in the iNES header accordingly, or is there another way.
No you should be able to see how big the file is even if the header doesn't match the ROM size. But emulators won't be able to run the game properly if the header is wrong.
If you are using NROM you can have only one or two PRG banks. Each PRG bank is 16 kB so if your game is bigger than that (minus the 8 kB CHR-ROM) you need two banks. If your PRG-ROM is bigger than 32 kB you need to consider using another mapper.
Tokumaru's templates automatically calculates the PRG-ROM start address ($C000 or $8000 for NROM) depending on what you set the PRG_COUNT define to (1 or 2 for NROM).
https://wiki.nesdev.com/w/index.php/Programming_NROM
Well, banking is something you have to plan for, not something that happens automatically and you just change the header to match. An NES program needs to explicitly map the banks it needs to access, so a program can't just grow indefinitely without the programmer planning out *how* it's going to grow and how the interaction between all the different banks will happen.
You have to decide yourself how many and which banks will be dedicated to the main engine, the audio engine, level maps, graphics (in case of CHR-RAM), and so on, and design the code in a way that allows it to access all of this stuff. When you start a project, you need to know the mapper you're gonna use, since there are many different bank layouts across the different mappers, and estimate how much space you're gonna use. These things don't have to be set in stone, as it may be possible to switch to a similar mapper later on or increase the ROM size (as long as the mapper supports it), but more drastic changes may need a lot of refactoring.
Another important thing to note is that ROM sizes bust be powers of 2. you can't have 110KB of PRG-ROM, you have to round it up to the next multiple of 2, which is 128KB. For example, if you currently have 64KB of PRG-ROM that's completely full, and need to implement a new feature that only needs 1 extra byte, you have to double the ROM size to 128KB, even though you only need 1 extra byte, otherwise emulators won't know how to map you ROM file.
In ASM6 you can put the cointents of different banks in separate files, and include them all in a master file that will be assembled. Something like this:
Code:
;PRG-ROM bank 0
.base $8000
.include "bank0.asm"
.org $c000
;PRG-ROM bank 1
.base $8000
.include "bank1.asm"
.org $c000
;PRG-ROM bank 2
.base $8000
.include "bank2.asm"
.org $c000
;PRG-ROM bank 3
.base $c000
.include "bank3.asm"
.org $fffa
;interrupt vectors
.dw NMI
.dw Reset
.dw IRQ
This could be part of a master file for an UNROM program with 64KB of PRG-ROM (4 x 16KB).
Note. Number of banks should be a power of 2...
1, 2, 4, 8, 16
Don't worry about how many banks you need yet. Just stick to NROM128 (Donkey Kong, Pacman) or NROM256 (Super Mario Bros) sized right now.
If you have so much code that you overflow past FFFF, the assembler will give you an error. Until that happens, it's not a worry.