NESASM: common among beginners, due to it having been used in a popular tutorial series (Nerdy Nights). It's a very straightforward assembler, takes assembly code as input and outputs a binary ROM file. Uses non-standard syntax for some things, and has a few weird bugs/quirks that sometimes creates problems that are hard to debug.
ASM6: Just as straightforward as NESASM, also taking assembly code and spitting out a binary file. Has very few built-in functionalities, only covering the basics. Being a multi-pass assembler means it offers a lot of versatility when it comes to organizing banks and variables. Also has it's share of little bugs/quirks, but these are normally less problematic than the ones in NESASM.
ca65: The most "professional" one. After the assembly step, it needs to link the intermediary code in order to generate the final binary, which requires a memory configuration file, which is normally what you use to define the ROM/RAM layout. Has a very extensive set of built-in directives and an advanced macro system that combined allow the implementation of all sorts of custom functionalities. Some versatility is lost sure to the fact it's a single pass assembler.
I personally avoid NESASM, use ASM6 for small programs and quick tests, and ca65 for bigger projects, but I'm still not 100% satisfied with this combination. Ideally I'd like something between ASM6 and ca65, with a decent number of useful directives and functions, but not so strict about ROM/RAM organization.
It basically has a built in linker and it is N pass, so you can do some voodoo with it. http://tass64.sourceforge.net/
ca65 has an incbin directive that lets you include part of a binary file. Using segments to place them at the correct location, you can replace the middle of a binary file with a patch:
Code: Select all
.segment "BIN1" .incbin "bank.bin", 0, $9500 - $8000 .segment "PATCH" ; patch code goes here .segment "BIN2" .incbin "bank.bin", $A000 - $8000, $C000 - $A000
Code: Select all
.segment "HEADER" .ascii "PATCH" .segment "PATCH1_HEADER" PATCH1_POS = $9500 - $8000 .import __PATCH1_SIZE__ .byte PATCH1_POS >> 16 .byte >PATCH1_POS .byte <PATCH1_POS .byte >__PATCH1__SIZE__ .byte <__PATCH1__SIZE__ .segment "PATCH1" ; patch code goes here ; remember to use 'define = yes' in the segment definition .segment "FOOTER" .ascii "EOF"