It is currently Tue Oct 17, 2017 3:28 pm

All times are UTC - 7 hours



Forum rules


Related:



Post new topic Reply to topic  [ 43 posts ]  Go to page 1, 2, 3  Next
Author Message
PostPosted: Fri May 19, 2017 5:24 pm 
Offline
User avatar

Joined: Tue Apr 05, 2016 5:25 pm
Posts: 121
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!

_________________
SNES NTSC 2/1/3 1CHIP | serial number UN318588627


Top
 Profile  
 
PostPosted: Fri May 19, 2017 5:33 pm 
Offline
User avatar

Joined: Mon Sep 15, 2014 4:35 pm
Posts: 3071
Location: Nacogdoches, Texas
I think ca65 fits most, if not all, of the criteria. Would you mind posting your source code?


Top
 Profile  
 
PostPosted: Fri May 19, 2017 5:48 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5710
Location: Canada
Those points vs ca65:
HihiDanni 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.

- AFAIK it generates correct code but it's also actively maintained, so bugs can get fixed if you find any
- .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


Top
 Profile  
 
PostPosted: Fri May 19, 2017 8:18 pm 
Offline
User avatar

Joined: Sat Jan 03, 2015 5:58 pm
Posts: 367
Location: ...
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.

Quote:
- 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.

- yes.
- .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.


Top
 Profile  
 
PostPosted: Fri May 19, 2017 8:27 pm 
Offline
User avatar

Joined: Tue Apr 05, 2016 5:25 pm
Posts: 121
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.

_________________
SNES NTSC 2/1/3 1CHIP | serial number UN318588627


Top
 Profile  
 
PostPosted: Fri May 19, 2017 11:04 pm 
Offline
User avatar

Joined: Thu Jan 19, 2006 5:08 pm
Posts: 744
Location: Shelton, Washington.
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!)

_________________
AKA SmilyMZX/AtariHacker.


Top
 Profile  
 
PostPosted: Fri May 19, 2017 11:52 pm 
Offline

Joined: Thu Feb 07, 2013 1:15 am
Posts: 94
Location: Sweden
HihiDanni wrote:
One more useful feature that I forgot to mention: The ability to generate a symbol file for debugging purposes.

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:
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.

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.

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.


Top
 Profile  
 
PostPosted: Sat May 20, 2017 6:18 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19091
Location: NE Indiana, USA (NTSC)
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"


Top
 Profile  
 
PostPosted: Sat May 20, 2017 6:44 am 
Offline
User avatar

Joined: Tue Apr 05, 2016 5:25 pm
Posts: 121
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.

_________________
SNES NTSC 2/1/3 1CHIP | serial number UN318588627


Top
 Profile  
 
PostPosted: Sat May 20, 2017 6:31 pm 
Offline
User avatar

Joined: Tue Apr 05, 2016 5:25 pm
Posts: 121
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:
    .word $ff, $ff, 0, 0, 0, 0, 0, 0
    .word $ff, $ff, 0, 0, 0, 0, reset, 0


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:
# 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


Top
 Profile  
 
PostPosted: Sat May 20, 2017 6:40 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19091
Location: NE Indiana, USA (NTSC)
..., reset - $C00000, ...


Top
 Profile  
 
PostPosted: Sat May 20, 2017 8:08 pm 
Offline

Joined: Mon Nov 10, 2008 3:09 pm
Posts: 429
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:
    .word $ff, $ff, 0, 0, 0, 0, 0, 0
    .word $ff, $ff, 0, 0, 0, 0, reset, 0


I haven't used ca65 for SNES development, but I think you want to use .addr, not .word.

Quote:
Here is my current ld65 config, which is probably wrong in more ways than one:

Code:
# 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;
}

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.

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:
    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;


Top
 Profile  
 
PostPosted: Sat May 20, 2017 8:18 pm 
Offline
User avatar

Joined: Tue Apr 05, 2016 5:25 pm
Posts: 121
AWJ wrote:
I haven't used ca65 for SNES development, but I think you want to use .addr, not .word.

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.

_________________
SNES NTSC 2/1/3 1CHIP | serial number UN318588627


Top
 Profile  
 
PostPosted: Sat May 20, 2017 8:20 pm 
Offline

Joined: Mon Nov 10, 2008 3:09 pm
Posts: 429
HihiDanni wrote:
AWJ wrote:
I haven't used ca65 for SNES development, but I think you want to use .addr, not .word.

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.


.addr does force the output to be word-sized. For a 24-bit pointer you use .faraddr.


Top
 Profile  
 
PostPosted: Sat May 20, 2017 10:21 pm 
Offline

Joined: Thu Feb 07, 2013 1:15 am
Posts: 94
Location: Sweden
I use the ".loword" directive to get the correct bytes into the vector tables, like so.

According to the manual ".addr" is an alias for ".word", so if true using it should yield the same overflow error.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 43 posts ]  Go to page 1, 2, 3  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: Yahoo [Bot] and 9 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group