Alternative assembler recommendations?

Discussion of hardware and software development for Super NES and Super Famicom. See the SNESdev wiki for more information.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
niconii
Posts: 219
Joined: Sun Mar 27, 2016 7:56 pm

Re: Alternative assembler recommendations?

Post by niconii »

Optiroc wrote:According to the manual ".addr" is an alias for ".word", so if true using it should yield the same overflow error.
Only for 6502, it says.
Optiroc
Posts: 129
Joined: Thu Feb 07, 2013 1:15 am
Location: Sweden

Re: Alternative assembler recommendations?

Post by Optiroc »

Nicole wrote:
Optiroc wrote:According to the manual ".addr" is an alias for ".word", so if true using it should yield the same overflow error.
Only for 6502, it says.
:oops: I should be more careful about posting two minutes after being forced out of bed...
Oziphantom
Posts: 1565
Joined: Tue Feb 07, 2017 2:03 am

Re: Alternative assembler recommendations?

Post by Oziphantom »

- 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.
64TASS
It has full 65816 support ( + 6502, 65C02, R65C02,W65C02,65CE02, 64dtv02, 65el02,6510, 4510 - I've asked about Hu6280 which sadly has 4 char opcodes making it harder to support at the moment ). All opcodes are supported, it will determine and work out from.databank and .dpage settings which is the correct addressing mode. It also has manual sizing and auto sizing. I have requested the ability to make auto collapsing REP/SEP statements, especially for macros. With these the assemblers build in optimiser will be able to determine if a REP/SEP is not needed and remove it automatically, so you can set them in Macros and not worry about them wasting space/clocks, Soci(the developer) has agreed and wants it, but it a little down the list at the moment. I have also added a request for special warnings that let me check that the size of a,index in code to catch such errors.

.include <- bring in a file whole
.binclude <- put everything in a file in a block basically lets you pack a file into a namespace
.binary <- brings in binary data, which you can skip bytes and only take a certian number of ie. .binary "myFile.bin",2,100 skips first 2 and brings in 100 bytes
worth noting, you can union a binary file with structures to get you labels for things in the file if you wish

.section can be added to from anywhere, and then instantiated in a location eg.

Code: Select all

*=$00
.dsection zp
then elsewhere you can do 

myFun
.section zp
localVar .byte ?
localWord .word ?
.send zo
this will make variables in the myFun name space but they will be collected and declared in the ZeroPage area. Upon assembly it will show the size of each segment e.g.

Code: Select all

Memory range:      $0801-$13b3   $0bb3
Section:           $0002-$0064   $0063   zp
Section:           $0866-$09a4   $013f   sBitmapDepack
Memory range:      $0866-$09a4   $013f
Section:           $09a5-$13b3   $0a0f   sDuckBitmapData
Memory range:      $09a5-$13b3   $0a0f
Macros, Functions and Segments are all well accounted for. You can call eitther of them with a '.' or '#' prefix, personally I force upon my self . for function and # for macro/segment. As to what is the difference, this is a function

Code: Select all

fCalcBitmapAddrChar .function base,x,y 
.endf base+(y*320)+(x*8)
which makes data at assemble time and returns the address/param to be assembled. Macros have their own namespace so any sub label defined in the macro is safe, it won't be duplicated if you put 2 in the same namespace. But it won't be able to nativly handle other labels in the instigators namespace, segments put everything in the instigators namespace.

No build in SNES header support, so it would need a macro built, the assembler has basically python levels of slicing built in, so a simple data structure could be made which a macro then spits out and converts to data in a human readable format.
With Logical, Base, Full bank support and blocks, sections it would be easy to build a full SNES ROM with it. I've used it to build a full D64 image, SNES should easily be doable. As the assembler supports atari xex and Apple][ formats, if enough of us want a SNES header, soci would probably put it in ;)

64Tass has a variety of warnings, the best one for me is the "Did you forget to add a # for this LDA $40?", it also has page boundary crossing warnings/errors. The Optimiser ( not sure how 65816 compat it is though ) will detect other silly things, like no need to clc here, this jump can be a BNE etc. It also has build in "alias" that will chose the minimal jump you need for a sitation for 65816 the GRA opcode will translate to BRA if within range auto changing to JMP XXXX if needed or JMP XXXXXX if needed. there are GNE,GEQ,GCC... it also covers the standards, code wrap at end of 64K, multi byte char, float compare, sign mismatch on .byte, .word etc

Sadly giant monolith help doc, hyper linked though http://tass64.sourceforge.net/

if one makes each bank a section then it will show the amount used, one could use a .warn "bank " + ^* + " has " + $FFFF-* + " bytes free" to get free though.

The ability to generate a symbol file for debugging purposes.
It has 2 output formats, its own and VICE format. These are basically label name,address, it will append all sub children, local variables, members of structs, blocks, sections etc

Also worth noting it is N pass, currently I use 7 passes in my code, but it scales as needed.

It is very actively maintained and is open source, and is so pure C it will even compile for 68K on an A500.
It is also has full backwards compatibility with TASS/TASM, not that is should be an issue around here ;)
Optiroc
Posts: 129
Joined: Thu Feb 07, 2013 1:15 am
Location: Sweden

Re: Alternative assembler recommendations?

Post by Optiroc »

Wow, I just skimmed through the documentation and have to say that there's certainly much to love about 64tass. I'll have to play around with it a bit for SNES use.

Really, the only thing I like about ca65 is that there's as of yet nothing I could think of that its macro language can't accomplish – but it's more through grunt and white knuckles than elegance you get things done with it a lot of the time. I do like the linker and memory configuration features, though.
User avatar
HihiDanni
Posts: 186
Joined: Tue Apr 05, 2016 5:25 pm

Re: Alternative assembler recommendations?

Post by HihiDanni »

Optiroc wrote:I use the ".loword" directive to get the correct bytes into the vector tables, like so.
Aha! .loword is used as function syntax. Thanks for the help with the linker configuration as well - it looks like I'm set to go ahead and start porting the actual code now!
SNES NTSC 2/1/3 1CHIP | serial number UN318588627
calima
Posts: 1745
Joined: Tue Oct 06, 2015 10:16 am

Re: Alternative assembler recommendations?

Post by calima »

Really, the only thing I like about ca65 is that there's as of yet nothing I could think of that its macro language can't accomplish
I have one (do chime in if I'm wrong): its C-like define cannot take more than one parameter, and the normal macro cannot be used for partial things (parameters to instructions), only full things with instructions.

That means I couldn't make a NTADR_A(x, y) macro, and instead had to make a "NTLINE_A(y) | x" workaround.
User avatar
nicklausw
Posts: 376
Joined: Sat Jan 03, 2015 5:58 pm
Location: ...
Contact:

Re: Alternative assembler recommendations?

Post by nicklausw »

calima wrote:
Really, the only thing I like about ca65 is that there's as of yet nothing I could think of that its macro language can't accomplish
I have one (do chime in if I'm wrong): its C-like define cannot take more than one parameter, and the normal macro cannot be used for partial things (parameters to instructions), only full things with instructions.

That means I couldn't make a NTADR_A(x, y) macro, and instead had to make a "NTLINE_A(y) | x" workaround.
There must have been some other bug going on, as other projects do multi-parameter defines (with the same purpose) just fine.
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Re: Alternative assembler recommendations?

Post by thefox »

Yeah, the ca65 .define macros support multiple arguments just fine, however you must make sure not to add extra parenthesis when you call them:

Code: Select all

.define foo(p1, p2) p2+p1
.byte foo 11, 22 ; ok
.byte foo(11, 22) ; not ok -- the first argument will be "(11", and then second one is "22)".
EDIT: Changed the macro expression to p2+p1 to better illustrate the point. Now it expands to "22)+(11".
Last edited by thefox on Mon May 22, 2017 1:12 pm, edited 2 times in total.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
calima
Posts: 1745
Joined: Tue Oct 06, 2015 10:16 am

Re: Alternative assembler recommendations?

Post by calima »

Are the docs wrong?

http://cc65.github.io/doc/ca65.html#ss12.7
Beware: Since the assembler cannot detect the end of one parameter, only the first token is used. If you don't like that, use classic macros instead:
I read that as saying .define only supports one parameter.
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Alternative assembler recommendations?

Post by rainwarrior »

calima wrote:Are the docs wrong?

http://cc65.github.io/doc/ca65.html#ss12.7
Beware: Since the assembler cannot detect the end of one parameter, only the first token is used. If you don't like that, use classic macros instead:
I read that as saying .define only supports one parameter.
They definitely support multiple parameters (e.g. I have PPU tile address macros that take X,Y parameters). I'm very confused as to what that statement is supposed to mean.
User avatar
nicklausw
Posts: 376
Joined: Sat Jan 03, 2015 5:58 pm
Location: ...
Contact:

Re: Alternative assembler recommendations?

Post by nicklausw »

thefox, your example confuses me because this also works without problem. (note to self: archive links)
User avatar
thefox
Posts: 3134
Joined: Mon Jan 03, 2005 10:36 am
Location: 🇫🇮
Contact:

Re: Alternative assembler recommendations?

Post by thefox »

calima wrote:Are the docs wrong?

http://cc65.github.io/doc/ca65.html#ss12.7
Beware: Since the assembler cannot detect the end of one parameter, only the first token is used. If you don't like that, use classic macros instead:
I read that as saying .define only supports one parameter.
I'm not sure what the docs are trying to say there, but the actual documentation for .define is clear cut: http://cc65.github.io/doc/ca65.html#.DEFINE
nicklausw wrote:thefox, your example confuses me because this also works without problem. (note to self: archive links)
It happens to work by coincidence. NTXY is defined as .define NTXY(xc,yc) ((xc)|((yc)<<5)). Then, NTXY(0, 23) expands to (((0)|((23))<<5)), which happens to have nicely balanced parenthesis.

But you're right, my example was bad, because the "not OK" case compiled even though it's ill-advised. I swapped the parameters around to better illustrate the point.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Alternative assembler recommendations?

Post by rainwarrior »

thefox wrote:
nicklausw wrote:thefox, your example confuses me because this also works without problem. (note to self: archive links)
It happens to work by coincidence. NTXY is defined as .define NTXY(xc,yc) ((xc)|((yc)<<5)). Then, NTXY(0, 23) expands to (((0)|((23))<<5)), which happens to have nicely balanced parenthesis.

But you're right, my example was bad, because the "not OK" case compiled even though it's ill-advised. I swapped the parameters around to better illustrate the point.
It happens to compile without error because of the balanced parentheses, but beyond that it happens to work because because "xc" is 0.

In general, parentheses + defines/macros in ca65 are a bit of a landmine, unfortunately. (See also: (indirect), Y addressing.)

I find it very strange/interesting that it obviously knows that '(' is not part of the name of the define, too, so that character has a special "new token" property to it.

Maybe we should propose some changes to the documentation just to point out how weird and error prone parentheses are when used with these features?
User avatar
pubby
Posts: 583
Joined: Thu Mar 31, 2016 11:15 am

Re: Alternative assembler recommendations?

Post by pubby »

The confusing thing is that parentheses are used when defining but not when invoking:

Code: Select all

.define foo(a, b, c) ; ...

; invoke
foo 0, 1, 2
AWJ
Posts: 433
Joined: Mon Nov 10, 2008 3:09 pm

Re: Alternative assembler recommendations?

Post by AWJ »

rainwarrior wrote:In general, parentheses + defines/macros in ca65 are a bit of a landmine, unfortunately. (See also: (indirect), Y addressing.)
The problem is that you aren't supposed to put parentheses around the argument list when invoking a macro (either a multiline .macro or a one-line .define). Assembler macros aren't C preprocessor macros. If you put parentheses around the argument list, the opening parenthesis gets interpreted as part of the first argument and the closing parenthesis as part of the last argument, which is almost certainly not what you want to happen.

If you want to pass an argument that contains a separator character like a comma, you put curly braces around that individual argument.

There's a clear example of this use of curly braces in the documentation (which, admittedly, is generally poorly written and unclear), under "Parametrized macros".
I find it very strange/interesting that it obviously knows that '(' is not part of the name of the define, too, so that character has a special "new token" property to it.
The definition of a one-line macro requires parentheses around the parameter list, so that the parser knows where the list of parameters ends and where the actual definition (what to expand the macro to) begins.

I have no idea either what the sentence "Since the assembler cannot detect the end of one parameter, only the first token is used" is supposed to mean.
Post Reply