Alternative assembler recommendations?
Moderator: Moderators
Forum rules
- For making cartridges of your Super NES games, see Reproduction.
Alternative assembler recommendations?
Currently my SNES framework is using WLA-DX as its assembler. Technically there isn't anything wrong with this assembler that is straight up preventing me from finishing the framework, but it feels messy and I've had to deal with several workarounds to bugs in its functionality:
- Macros are fragile and inflexible ("invalid use of modulo" bug - I have to make separate versions of the same macro for immediate values and absolute addressing as the arguments).
- Potentially useful functions like RAMSECTIONs don't work due to bugs.
- Seriously, what the hell is a "slot"? This concept is not adequately explained.
- I don't trust it to generate code that won't hit a BRK and thus crash the game.
Since this is a framework I'd like others to be able to use, I'd prefer to have a cleaner codebase than I have now. I would like to know if there are any other assemblers that would fit my needs better. I would also prefer to be able to port my project over to the new assembler relatively easily. Alternatively, this topic can serve to better educate me on anything I might be doing wrong with my existing assembler.
Here's what I'm looking for:
- Fully featured 65816 assembler, generates correct code (duh)
- Ability to include source or binary files inline. I'd like to have human-readable definition files for some of my data.
- Ability to define RAM variables in separate files but not have to manage their starting addresses myself across these files.
- More reliable and readable macros. Additionally, syntax that would make it clear that something is a macro and not a subroutine.
- Handles ROM headers correctly. I don't know what the best practices are.
- Supports a FastROM + HiROM configuration.
- Ability to detect certain programmer mistakes at assemble time would be very nice - specifically calling a subroutine that assumes 16-bit registers when they're currently 8-bit.
- Documentation that isn't a single mile-long text file would be nice.
- Ability to see free space remaining in banks (like WLA already does) would be nice.
Suggestions very much appreciated!
- Macros are fragile and inflexible ("invalid use of modulo" bug - I have to make separate versions of the same macro for immediate values and absolute addressing as the arguments).
- Potentially useful functions like RAMSECTIONs don't work due to bugs.
- Seriously, what the hell is a "slot"? This concept is not adequately explained.
- I don't trust it to generate code that won't hit a BRK and thus crash the game.
Since this is a framework I'd like others to be able to use, I'd prefer to have a cleaner codebase than I have now. I would like to know if there are any other assemblers that would fit my needs better. I would also prefer to be able to port my project over to the new assembler relatively easily. Alternatively, this topic can serve to better educate me on anything I might be doing wrong with my existing assembler.
Here's what I'm looking for:
- Fully featured 65816 assembler, generates correct code (duh)
- Ability to include source or binary files inline. I'd like to have human-readable definition files for some of my data.
- Ability to define RAM variables in separate files but not have to manage their starting addresses myself across these files.
- More reliable and readable macros. Additionally, syntax that would make it clear that something is a macro and not a subroutine.
- Handles ROM headers correctly. I don't know what the best practices are.
- Supports a FastROM + HiROM configuration.
- Ability to detect certain programmer mistakes at assemble time would be very nice - specifically calling a subroutine that assumes 16-bit registers when they're currently 8-bit.
- Documentation that isn't a single mile-long text file would be nice.
- Ability to see free space remaining in banks (like WLA already does) would be nice.
Suggestions very much appreciated!
SNES NTSC 2/1/3 1CHIP | serial number UN318588627
- Drew Sebastino
- Formerly Espozo
- Posts: 3496
- Joined: Mon Sep 15, 2014 4:35 pm
- Location: Richmond, Virginia
Re: Alternative assembler recommendations?
I think ca65 fits most, if not all, of the criteria. Would you mind posting your source code?
- rainwarrior
- Posts: 8734
- Joined: Sun Jan 22, 2012 12:03 pm
- Location: Canada
- Contact:
Re: Alternative assembler recommendations?
Those points vs ca65:
- .include and .incbin
- .res and linker .segment will lay out your RAM variables, .import / .export / .global will let you share them between files
- the macro system is pretty good, I think, though not quite as good as C preprocessor macros
- you can make a header segment easily, though I think you'll need to generate a checksum with another tool
- the linker is very configurable, so you can lay out the ROM in any arrangement fairly easily
- i think you could create assert macros for this?
- its documentation is HTML, with a hyperlinked table of contents: http://cc65.github.io/doc/ca65.html
- the linker can generate "map" files that give you information like that
- AFAIK it generates correct code but it's also actively maintained, so bugs can get fixed if you find anyHihiDanni wrote:- Fully featured 65816 assembler, generates correct code (duh)
- Ability to include source or binary files inline. I'd like to have human-readable definition files for some of my data.
- Ability to define RAM variables in separate files but not have to manage their starting addresses myself across these files.
- More reliable and readable macros. Additionally, syntax that would make it clear that something is a macro and not a subroutine.
- Handles ROM headers correctly. I don't know what the best practices are.
- Supports a FastROM + HiROM configuration.
- Ability to detect certain programmer mistakes at assemble time would be very nice - specifically calling a subroutine that assumes 16-bit registers when they're currently 8-bit.
- Documentation that isn't a single mile-long text file would be nice.
- Ability to see free space remaining in banks (like WLA already does) would be nice.
- .include and .incbin
- .res and linker .segment will lay out your RAM variables, .import / .export / .global will let you share them between files
- the macro system is pretty good, I think, though not quite as good as C preprocessor macros
- you can make a header segment easily, though I think you'll need to generate a checksum with another tool
- the linker is very configurable, so you can lay out the ROM in any arrangement fairly easily
- i think you could create assert macros for this?
- its documentation is HTML, with a hyperlinked table of contents: http://cc65.github.io/doc/ca65.html
- the linker can generate "map" files that give you information like that
Re: Alternative assembler recommendations?
I might as well at least mention my assembler asm16. I'd actually recommend you go ca65 since it would be easier to port WLA code to it but this is a good time for me to see what people want that asm16 may lack.
- .include and .incbin.
- unfortunately you have to use enums due to lack of a linker phase.
- macros are basically set up like in WLA, except you can pass a modulo just fine. You can also "emulate" an assembler directive by adding a period before macro calls if you really want to.
- not sure what this means. Checksum calculation? Not currently. On my mental to do list.
- yep.
- interesting feature. You can make an .if statement that leads to an .error, but subroutines would have to be called inside a macro.
- it's short and sweet.
- unfortunately not currently.
- yes.- Fully featured 65816 assembler, generates correct code (duh)
- Ability to include source or binary files inline. I'd like to have human-readable definition files for some of my data.
- Ability to define RAM variables in separate files but not have to manage their starting addresses myself across these files.
- More reliable and readable macros. Additionally, syntax that would make it clear that something is a macro and not a subroutine.
- Handles ROM headers correctly. I don't know what the best practices are.
- Supports a FastROM + HiROM configuration.
- Ability to detect certain programmer mistakes at assemble time would be very nice - specifically calling a subroutine that assumes 16-bit registers when they're currently 8-bit.
- Documentation that isn't a single mile-long text file would be nice.
- Ability to see free space remaining in banks (like WLA already does) would be nice.
- .include and .incbin.
- unfortunately you have to use enums due to lack of a linker phase.
- macros are basically set up like in WLA, except you can pass a modulo just fine. You can also "emulate" an assembler directive by adding a period before macro calls if you really want to.
- not sure what this means. Checksum calculation? Not currently. On my mental to do list.
- yep.
- interesting feature. You can make an .if statement that leads to an .error, but subroutines would have to be called inside a macro.
- it's short and sweet.
- unfortunately not currently.
Re: Alternative assembler recommendations?
I'll take a look at both assemblers tomorrow. It's a bit frustrating that the ca65 template assumes a LoROM configuration so I might need to play around with it some.
One more useful feature that I forgot to mention: The ability to generate a symbol file for debugging purposes.
One more useful feature that I forgot to mention: The ability to generate a symbol file for debugging purposes.
SNES NTSC 2/1/3 1CHIP | serial number UN318588627
- Hamtaro126
- Posts: 818
- Joined: Thu Jan 19, 2006 5:08 pm
Re: Alternative assembler recommendations?
There was some (of mostly my) planning for a standard assembler for things like this,
My planned feature set was similar to yours, a 6502/65c02/Hu6280/65816/SPC700 multi-assembler with clean 3-part build process similar to ASM6, but unlike ASM6, it was to add Thingy "Table File" support for text,
Thingy was first used as a rom hacking tool for script and text editing, Byuu decided to add it in BASS (a.k.a. XKAS 14) for text support, Any other assembler did not implement this (besides ASAR from SMW Central, But that's for SMW patches!)
My planned feature set was similar to yours, a 6502/65c02/Hu6280/65816/SPC700 multi-assembler with clean 3-part build process similar to ASM6, but unlike ASM6, it was to add Thingy "Table File" support for text,
Thingy was first used as a rom hacking tool for script and text editing, Byuu decided to add it in BASS (a.k.a. XKAS 14) for text support, Any other assembler did not implement this (besides ASAR from SMW Central, But that's for SMW patches!)
AKA SmilyMZX/AtariHacker.
Re: Alternative assembler recommendations?
ca65's linker (ld65) can output a pretty nice symbol file with the `-Ln` option. While trying to get various mapping types correct I've also found use for the `-m` and `-vm` options (export map/verbose map file).HihiDanni wrote:One more useful feature that I forgot to mention: The ability to generate a symbol file for debugging purposes.
I was sure that some of the templates I've seen around had a Mode 21/HiROM version, but it seems both blargg's and tepples' templates use Mode 20 exclusively.HihiDanni wrote:I'll take a look at both assemblers tomorrow. It's a bit frustrating that the ca65 template assumes a LoROM configuration so I might need to play around with it some.
It's easy enough to edit the linker configuration for HiROM, though. Here's an example. It's really only the ROM locations in the memory map and the header/vector segments you need to change compared to a LoROM config.
Re: Alternative assembler recommendations?
You'd need to make some other slight changes to the code of my lorom-template project to get it to run in HiROM, such as not assuming that MMIO ports associated with the B Bus ($2100-$2183) and memory controller ($4200-$437F) are within the current data bank.
EDIT: clarified which "the code"
EDIT: clarified which "the code"
Re: Alternative assembler recommendations?
The game already runs at HiROM, unless you're talking about assembler differences here.
Anyway, I am already seeing two ca65 techniques that I could really use that I hadn't even touched on previously: ability to define stack size within the memory map definition, and the ability to export symbols to other files (which I'm 95% sure WLA can do, but as I said earlier, the readme is kind of a mess to look through).
Currently I'm designing my WRAM layout using an ODS spreadsheet for planning and .enums in code to define them in the program. Obviously I think this approach really sucks and is probably the biggest thing I'd like to improve.
Anyway, I am already seeing two ca65 techniques that I could really use that I hadn't even touched on previously: ability to define stack size within the memory map definition, and the ability to export symbols to other files (which I'm 95% sure WLA can do, but as I said earlier, the readme is kind of a mess to look through).
Currently I'm designing my WRAM layout using an ODS spreadsheet for planning and .enums in code to define them in the program. Obviously I think this approach really sucks and is probably the biggest thing I'd like to improve.
SNES NTSC 2/1/3 1CHIP | serial number UN318588627
Re: Alternative assembler recommendations?
I tried modifying the basic LoROM template on the wiki to be HiROM like the linked example, but I get a range error where the vectors are defined. Specifically, it seems to take issue to the reset symbol:
I'm guessing reset is being written as a 24-bit address because ROM0 is technically at $c00000 in the configuration? Some assistance getting a proper linker memory configuration would be appreciated. I want to have code run in LoROM banks (so $008000 at reset, then $808000 when FastROM is engaged), but data be in HiROM banks. How would I achieve this in ld65? I tried modifying the configuration somewhat to have an additional region named "LOROM" starting at $8000. If I do this, the linker "succeeds". however it seems like any code that is inserted pushes the header downward (and also expands the file).
Here is my current ld65 config, which is probably wrong in more ways than one:
Code: Select all
.word $ff, $ff, 0, 0, 0, 0, 0, 0
.word $ff, $ff, 0, 0, 0, 0, reset, 0
Here is my current ld65 config, which is probably wrong in more ways than one:
Code: Select all
# ca65 linker config for 256K HiROM
# Based on configurations by blargg and David Lindecrantz
SYMBOLS {
__STACKSIZE__: type = weak, value = $100;
}
# Physical areas of memory
# Names need not match, but it makes it easier to remember if they do.
MEMORY {
ZEROPAGE: start = 0, size = $100;
LORAM: start = $000100, size = $1f00 - __STACKSIZE__, define = yes;
STACK: start = $002000 - __STACKSIZE__, size = __STACKSIZE__, define = yes;
HIRAM: start = $7e2000, size = $e000, define = yes;
EXRAM: start = $7f0000, size = $10000, define = yes;
LOROM: start = $8000, size = $8000;
ROM0: start = $c00000, size = $ffb0, fill = yes, fillval = $00;
ROMHEADER: start = $c0ffb0, size = $50, fill = yes, fillval = $00;
ROM1: start = $c10000, size = $10000, fill = yes, fillval = $00;
ROM2: start = $c20000, size = $10000, fill = yes, fillval = $00;
ROM3: start = $c30000, size = $10000, fill = yes, fillval = $00;
}
# Logical areas code/data can be put into.
SEGMENTS {
ZEROPAGE: load = ZEROPAGE, type = zp, optional = yes;
BSS: load = LORAM, type = bss, optional = yes;
LORAM: load = LORAM, type = bss, optional = yes;
HIRAM: load = HIRAM, type = bss, optional = yes;
EXRAM: load = EXRAM, type = bss, optional = yes;
CODE: load = LOROM, type = ro, optional = yes;
RODATA: load = ROM0, type = ro;
HEADER: load = ROMHEADER, type = ro, start = $c0ffb0;
ROM1: load = ROM1, type = ro, optional = yes;
ROM2: load = ROM2, type = ro, optional = yes;
ROM3: load = ROM3, type = ro, optional = yes;
}
SNES NTSC 2/1/3 1CHIP | serial number UN318588627
Re: Alternative assembler recommendations?
..., reset - $C00000, ...
Re: Alternative assembler recommendations?
I haven't used ca65 for SNES development, but I think you want to use .addr, not .word.HihiDanni wrote:I tried modifying the basic LoROM template on the wiki to be HiROM like the linked example, but I get a range error where the vectors are defined. Specifically, it seems to take issue to the reset symbol:
Code: Select all
.word $ff, $ff, 0, 0, 0, 0, 0, 0 .word $ff, $ff, 0, 0, 0, 0, reset, 0
First of all, all RAM regions in the MEMORY section need to have file = "" or else they'll get output to the ROM file (and push everything else out of place). Second, regions that you do want in the ROM file need to be listed in the order you want them written to the ROM, not necessarily the order that they appear in the CPU address space. And everything that gets written to the ROM needs fill = yes so that banks stay aligned.Here is my current ld65 config, which is probably wrong in more ways than one:
Code: Select all
# ca65 linker config for 256K HiROM # Based on configurations by blargg and David Lindecrantz SYMBOLS { __STACKSIZE__: type = weak, value = $100; } # Physical areas of memory # Names need not match, but it makes it easier to remember if they do. MEMORY { ZEROPAGE: start = 0, size = $100; LORAM: start = $000100, size = $1f00 - __STACKSIZE__, define = yes; STACK: start = $002000 - __STACKSIZE__, size = __STACKSIZE__, define = yes; HIRAM: start = $7e2000, size = $e000, define = yes; EXRAM: start = $7f0000, size = $10000, define = yes; LOROM: start = $8000, size = $8000; ROM0: start = $c00000, size = $ffb0, fill = yes, fillval = $00; ROMHEADER: start = $c0ffb0, size = $50, fill = yes, fillval = $00; ROM1: start = $c10000, size = $10000, fill = yes, fillval = $00; ROM2: start = $c20000, size = $10000, fill = yes, fillval = $00; ROM3: start = $c30000, size = $10000, fill = yes, fillval = $00; } # Logical areas code/data can be put into. SEGMENTS { ZEROPAGE: load = ZEROPAGE, type = zp, optional = yes; BSS: load = LORAM, type = bss, optional = yes; LORAM: load = LORAM, type = bss, optional = yes; HIRAM: load = HIRAM, type = bss, optional = yes; EXRAM: load = EXRAM, type = bss, optional = yes; CODE: load = LOROM, type = ro, optional = yes; RODATA: load = ROM0, type = ro; HEADER: load = ROMHEADER, type = ro, start = $c0ffb0; ROM1: load = ROM1, type = ro, optional = yes; ROM2: load = ROM2, type = ro, optional = yes; ROM3: load = ROM3, type = ro, optional = yes; }
If you want data in the lower half of each 64K bank and code in the upper half (like Super Robot Wars 4) you need something like this:
Code: Select all
DATA0: start = $c00000, size = $8000, fill = yes, fillval = $00;
CODE0: start = $808000, size = $7fb0, fill = yes, fillval = $00;
ROMHEADER: start = $80ffb0, size = $50, fill = yes, fillval = $00;
# repeat for however many code+data banks you need:
DATA1: start = $c10000, size = $8000, fill = yes, fillval = $00;
CODE1: start = $818000, size = $8000, fill = yes, fillval = $00;
DATA2: start = $c20000, size = $8000, fill = yes, fillval = $00;
CODE2: start = $828000, size = $8000, fill = yes, fillval = $00;
# finally, for HiROM I think data-only banks can all go in one big region,
# since they're contiguous both in ROM and in CPU address space
# not 100% sure about this though (ld65 might not allow regions larger than 64K)
BIGDATA: start = $cX0000, size = $XXXXX, fill = yes, fillval = $00;
Re: Alternative assembler recommendations?
It's an interrupt vector, they must specifically be word-sized, unless you know of a way to force it to use just the lower 16 bits. Otherwise I might use tepples' suggestion despite looking kind of hackish.AWJ wrote:I haven't used ca65 for SNES development, but I think you want to use .addr, not .word.
SNES NTSC 2/1/3 1CHIP | serial number UN318588627
Re: Alternative assembler recommendations?
.addr does force the output to be word-sized. For a 24-bit pointer you use .faraddr.HihiDanni wrote:It's an interrupt vector, they must specifically be word-sized, unless you know of a way to force it to use just the lower 16 bits. Otherwise I might use tepples' suggestion despite looking kind of hackish.AWJ wrote:I haven't used ca65 for SNES development, but I think you want to use .addr, not .word.