This has probably been done before (as I say with every project I do), but I added INES directives to asm6.
https://github.com/nicklausw/asm6nThe 'n' can be for nicklausw, nintendo, nes, whatever. I dunno.
Anyway, here's an NROM example:
Code:
.inesprg 1 ; 1x 16KB bank of PRG code
.ineschr 1 ; 1x 8KB bank of CHR data
.inesmap 0 ; mapper 0 = NROM, no bank swapping
.inesmir 1 ; background mirroring (ignore for now)
.inesins ; put ines header in the file!
Yes, there has to be an insertion directive, because asm6 doesn't make NES support mandatory, and I'd rather keep it that way for now.
Also ANSI compatibility. Not sure why. Just wanted it.
This should work from what I've tested, tell me otherwise.
Is there any emulator that makes use of the 2.0 standard?
Nevermind, I see it on the wiki...
BizHawk as of r6313
FCEUX as of r3071
Nintendulator 0.975 Beta
MESS (per BBS post 62428)
no$nes v1.1
PowerMappers v23 for PowerPak
Glad to see I inspired some macro packs. Actually I forgot to add support for the upper nibble of the mapper number, so that's there now.
How is it suggested that iNES 2.0 be implemented in an assembler? I think Unofficial Magickit might handle this, so I'll take a look.
This is super cool -- thanks for it! Is there any reason this didn't get added to official asm6? loopy lingers and is contactable in many ways...
I think that's because asm6 wasn't specifically aimed towards the Famicom. I used it more on Apple ][ projects.
That doesn't mean it's not cool to have such extra features though.
No, asm6 was invented solely for NES/Famicom work, but obviously it's a generic enough assembler that you can use it for anything 6502-based. Quoting the original README:
Code:
--------------------------------------------------------------
ASM6 (v1.6)
A 6502 assembler by loopy (loopy at mm.st)
--------------------------------------------------------------
Yes, it's another 6502 assembler. I built it to do NES development, but you
can probably use it for just about anything. ...
Anyway, I'll point out that we now have at *least* 2 forks of asm6, which is why I keep asking the question why these features + patches aren't being sent in to loopy to incorporate into asm6 officially:
https://github.com/nicklausw/asm6nhttps://github.com/freem/asm6f
Frankly, if I was loopy, I wouldn't accept this patch. There's really no need for such directives when the assembler is flexible enough to generate the header with existing directives like .byte. Wrap it in a macro (like tepples did), and you get the same level of usability as well.
It's not too surprising that NESASM had to add those directives, because of the 8 KB bank size requirement.
thefox wrote:
There's really no need for such directives when the assembler is flexible enough to generate the header with existing directives like .byte. Wrap it in a macro (like tepples did), and you get the same level of usability as well.
While people clinging for dear life onto NESASM isn't a major problem as far as I can tell, asm6n does help with "NESASM doesn't NEED macros for that!"
Later on today I'll see about making a command line arg to have asm6n always put a blank header at the beginning for it to fill out later, meaning you don't need .inesins.
nicklausw wrote:
While people clinging for dear life onto NESASM isn't a major problem as far as I can tell, asm6n does help with "NESASM doesn't NEED macros for that!"
Just to be clear, I wasn't criticizing your work. I just think it's for the better if the mainline asm6 stays platform agnostic.
Yeah, I think asm6 should be clear of an intended platform.
At the same time, I'm interested in merging my changes with freem's; why choose between header directives and illegal opcodes with .nl support when you can have it all?
koitsu wrote:
Anyway, I'll point out that we now have at *least* 2 forks of asm6, which is why I keep asking the question why these features + patches aren't being sent in to loopy to incorporate into asm6 officially:
https://github.com/nicklausw/asm6nhttps://github.com/freem/asm6fIt should be noted that my fork is a "continuation" of sonder's fork (or more accurately, I stole his code for fceux *.nl generation).
nicklausw wrote:
At the same time, I'm interested in merging my changes with freem's; why choose between header directives and illegal opcodes with .nl support when you can have it all?
Even though I'm against the idea of the directives (for reasons mentioned in the thread), I don't see any harm in actually merging them, since you're not forced to use them; feel free to send a pull request to the asm6f repo and I'll look things over. (Personally though, I would hope support for NES 2.0 header fields would get added.)
The -i command line option now makes use of INESINS not needed! (Still there, though, of course).
So if you want to, you can just do:
Code:
.inesprg 1 ; 1x 16KB bank of PRG code
.ineschr 1 ; 1x 8KB bank of CHR data
.inesmap 0 ; mapper 0 = NROM, no bank swapping
.inesmir 1 ; background mirroring (ignore for now)
And assuming that's bla.asm, assemble with:
Code:
asm6n -i bla.asm bla.nes
And the header goes in. If you don't like the terminal args, then use the insertion directive, it's up to you.
(On a separate note, the code used to implement this is redundant and kind of hideous, but eh).
nicklausw, is there a particular need for this -i flag (or the equivalent .inesins pseudo-op)? It seems to me that inclusion of the 16-byte NES header would be based on any use of .ines{prg,chr,map,mir} directives. Rephrased: use of any of those should enable adding the header to the resulting binary. There should be defaults for each of the respective pseudo-ops as well (the default values should be documented), so that you could literally have a program that just says .inesprg 1 (with no other .inesXXX directives) and gets you a .NES ROM. There is no way to solve every "error condition/usage case", but to me the above is intuitive and how some other assemblers do it.
Just my two cents.
If the code only needs one pass, then the way asm6 works, either you'd have to do another pass for no reason to add the header bytes at the start of the file, or find a way to add bytes to the beginning of an existing file. Not possible, as far as I know (easily anyway).
The potential for NSF(2) and FDS headers could be interesting as well.
B00daW wrote:
The potential for NSF(2) and FDS headers could be interesting as well.
"FDS", 0x1A, a byte for disk sides and a bunch of zeroes to make it even? Sounds simple enough.
The NSF header is a lot more complicated, though; I think I'll do iNES 2 first.
koitsu wrote:
There should be defaults for each of the respective pseudo-ops as well (the default values should be documented), so that you could literally have a program that just says .inesprg 1 (with no other .inesXXX directives) and gets you a .NES ROM.
This is already true; the directives default to 0. The readme now says so.
The code does warn if INESINS is used before all 4 other iNES directives, though, to prevent confusion as to when to use the directive. Should I take out the warning?
If anything, the warning should depend on the value of inesmap. For mappers commonly used with CHR RAM, it should not warn for a missing ineschr except in verbose mode, in which case it may warn "assuming CHR RAM". And for mappers that control mirroring, it should not warn for a missing inesmir. My ca65 macro pack uses default values (horizontal mirroring, no WRAM, and no CHR ROM) if not specified, and it guesses CHR RAM size as 0 or 8K based on whether or not there's CHR ROM.
tepples wrote:
If anything, the warning should depend on the value of inesmap. For mappers commonly used with CHR RAM, it should not warn for a missing ineschr except in verbose mode, in which case it may warn "assuming CHR RAM". And for mappers that control mirroring, it should not warn for a missing inesmir. My ca65 macro pack uses default values (horizontal mirroring, no WRAM, and no CHR ROM) if not specified, and it guesses CHR RAM size as 0 or 8K based on whether or not there's CHR ROM.
I like the "Assuming CHR RAM" idea, but asm6 lacks a verbose mode, it just has a quiet mode. I dunno about having the program go:
Code:
pass 1..
pass 2..
assuming chr ram.
pineight.nes written (however many bytes).
I don't think it'll bother anyone (I usually have asm6 on quiet mode anyway, since it doesn't conform to the output of other tools in my makefile).
Can someone give an example of a game where a discrepancy requires the use of iNES 2? I need a good way to test and make sure I'm implementing it right.
Just throwing this out there, asm6n's functionality has been added to
freem's fork of asm6. The main difference is that it doesn't require INESINS or a flag to the command line. Turns out the assembler works differently than I initially thought a few months back.
asm6n isn't updated with this improved functionality simply because I want to encourage people to use the fork that already has plenty of NES-specific features, now including header directives.