My recent experience with ca65, asm6, nesasm, and wla-dx

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

My recent experience with ca65, asm6, nesasm, and wla-dx

Post by blargg »

After porting some example code for an upcoming release to the four main NES assemblers, I have a good idea of how they compare for implementing the same small demo programs in a custom file format. Overall, asm6 and ca65 are the clear winners. asm6 is to C as ca65 is to C++; asm6 is good for small to medium programs, and ca65 is good for medium to large, or where you want lots of flexibility and plenty of room to grow. ca65 mainly has more indirection, sort of like how a web page with stylesheets can display in many different ways with the same content. Now if I could only get - and + label support supported by the official ca65, then porting between the two would be a lot easier...

ca65
+ Plenty of room to grow.
+ Powerful macro support.
- Heavyweight; inconvenient for small programs.
- Doesn't support - and + labels, the biggest porting headache.

asm6
+ Simple, elegant model for generating files with things at various addresses.
+ Easy to set up files with minimum of specification.
- Can't switch segments as in ca65, so order of things in file must match output (as far as I can tell).

nesasm
- Inflexible about output format if you're changing addresses (e.g. if you want code assembled for $6000, it must go at a file offset that's a multiple of $2000, + $10).
- Poor error reporting, often doesn't report errors even though you likely made one.
- Very picky about syntax. Uses different format for several things.

wla-dx
+ Supports multiple game console CPUs, allowing same assembler for all development.
- Bizarre set of directives, lack of coherency in object model, poor documentation.
- Way too many bugs, obscure behaviors.
- Silly things required like .w on many 16-bit addresses.
- Arithmetic done in floating-point, with unexpected results.
- Doesn't warn about things that are very likely errors.
- Macro parameters are numeric, rather than text, limiting things you can do.
User avatar
cartlemmy
Posts: 193
Joined: Fri Sep 24, 2010 4:41 pm
Location: California, USA
Contact:

Post by cartlemmy »

Awesome, this is the exact post I was looking for a few days ago. Thank you!
gilligan
Posts: 35
Joined: Tue Jan 04, 2005 7:31 am
Contact:

Post by gilligan »

Have you contacted Ulrich (main author of ca65) about anoymous +/- label support ? He's a nice guy, maybe its even a planned feature - who knows.
gilligan
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

It would duplicate the existing functionality of :+ and :-.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

I just haven't taken the time to draft up a proposal and post. I have many things to suggest for ca65. And yes, ca65 has the functionality already, just a different syntax.
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Post by Bregalad »

Well, I guess CC65 is the best one, I have to admit, although I don't use it. I use WLA, which while flawed, isn't as bas as you describe it.

There is awful bugs in the SPC700 version of WLA, but I didn't ever encounter any in the 6502 version. The error messages are usually informative enough. The segment system is somewhat convenient, and really flexible. For exmemple having a DPCM data that is aligned to $40 bytes and that is always located at $c000-$ffff is something you can pull off easily, without having to "cheat" and force it at $c000 like most assemblers would need you to do. A great feature is overwrite sections, I use it in my game to have non-CHR data in CHR-ROM easily (without the need to truncate my .chr file). I don't think any other assemblers support that. I also found a way to have the same piece of code in each bank (useful for mappers that do 32k switching), but it's a little tricky (you have to include multiple times the same file, and export labels, ask me if you're interested).
The documentation is just fine for me.

A big plus was that his author WAS active and open to bug report and sugettion, but isn't any longer the case, so this is now a handicap.

And surprisingly, you don't mention the biggest issue I have with WLA currently : NO SUPORT OF RELOCATABLE CODE. If you want to copy your code to RAM and execute it from here, it's going to be a headache in most assemblers, including WLA.
Also an issue is that the assembler assumes the target system is ROM. This is fine for (S)NESdev, but is really retarded for C64, FDS or SPC-700 development. In those systems you just load files in RAM and execute from here... Of course you reserve some maximum amount of RAM for the file, so all I did was make the file a "romsection" of the maximum reserved size... (I never did anything serious on those systems, but if I were to release them I'd just cut the size of the file manually after compilation... quite cheap but what else can you do ?)

I think CC65 fixed all the issues I mentioned (confirmation would be fine).
PS : How CC65 handles + and - is really a MAJOR problem. I use them all the time in my code, and I'd never find names for so many labels.
Useless, lumbering half-wits don't scare us.
tomaitheous
Posts: 592
Joined: Thu Aug 28, 2008 1:17 am
Contact:

Post by tomaitheous »

No comment on NESASM's macro support?
Drag
Posts: 1615
Joined: Mon Sep 27, 2004 2:57 pm
Contact:

Post by Drag »

A penny for your thoughts on DASM? I've been using it for years, and I'm not sure how it stacks up against these other programs.

The only major drawback with it that I can see is it doesn't support anonymous labels. Then again, I haven't died from not being able to use them, so it's nothing showstopping in my opinion. :P
User avatar
Memblers
Site Admin
Posts: 4044
Joined: Mon Sep 20, 2004 6:04 am
Location: Indianapolis
Contact:

Post by Memblers »

Yeah, the only notable complaint I've had with CA65/CC65 is the anonymous label syntax. I do remember there being a discussion about on the CC65 email list many years ago, not sure what the conclusion was, but maybe there's some insight there if it's available for searching.

They look really ugly, so I tend do just make up garbage names (if it's not a very short branch), which is all anonymous labels are supposed to be good for anyways. I often use local labels (preceded with @), so I can often use the same generic yet more descriptive names anyways.

I used DASM before, I left it then because it didn't have incbin (it does now though), it seemed good but I was a newb at the time and wasn't using macros or any kind of fancy stuff yet. If it's got good macro support (I don't remember), it should be just fine.

x816 seemed like a pretty good assembler, I can't use anymore though without using DOSBox. I mostly used it for my SNES 2A03 emulator, so it has to be assembled in DOSBox if I rebuild it anymore, heheh. Nerdtracker 2 used it originally (later I changed Bananmos' old code to assemble in CA65)

Bregalad wrote: I think CC65 fixed all the issues I mentioned (confirmation would be fine).
It's kind of funny, for relocatable code (that you want to move yourself) you actually use the .ORG command. And the end of it you use .reloc. So it's the rest of the stuff that's truly relocatable as far as the linker is concerned, heheh.
Last edited by Memblers on Thu Oct 07, 2010 5:07 pm, edited 2 times in total.
ReaperSMS
Posts: 174
Joined: Sun Sep 19, 2004 11:07 pm

Post by ReaperSMS »

The most annoying bit about :+ and :- is that it confuses the hell out of emacs' assembly autoindent. Well, aside from the fact that they were broken in a few versions. Unfortunately, automatically rewriting the file to go from +/- to : and :+/:- isn't entirely trivial, since cases like

Code: Select all

- cmp
  beq +
  bne ++
+bit
  bvc -
+rts
get a bit tricky to convert. You can't get away with converting every - or + in the first column to a :, and prepending a : to +'s and -'s after branches, because the ca65 version of that would be

Code: Select all

: cmp
  beq :+
  bne :++
:bit
  bvc :--
:rts
A 2-pass approach could probably do it though. Alternatively, someone could hack in support, though I recall the sourcebase for it being a bit messy.

The heavyweight bit can be mitigated somewhat with a decent premade makefile and linker script.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

Oh well, I guess we can get into discussing these unnamed labels. ca65's are workable, but no other assemblers use the convention, whereas the + and - convention is shared by many assemblers. The + and - convention also has the benefit of being fairly clear even without explanation, and somewhat consistent. There's a label named -, followed by a branch to -. Or a label named ++ and a branch before it to ++. Then you see multiple labels of the same name, and the first time you figure out which branch goes to which merely by proximity, and then see the way the + and - dictate direction.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Post by tepples »

Bregalad wrote:There is awful bugs in the SPC700 version of WLA, but I didn't ever encounter any in the 6502 version. The error messages are usually informative enough. The segment system is somewhat convenient, and really flexible. For exmemple having a DPCM data that is aligned to $40 bytes and that is always located at $c000-$ffff is something you can pull off easily, without having to "cheat" and force it at $c000 like most assemblers would need you to do.
Under ca65 and ld65, I make a segment with alignment 64 bytes and in the $C000-$FFFF memory area. Then I put all samples in that segment and .align 64 before each .incbin.
A great feature is overwrite sections, I use it in my game to have non-CHR data in CHR-ROM easily (without the need to truncate my .chr file).
A .png to .chr converter that can handle sizes less than full banks allows this easily. If I want 512 bytes of ROM in a given 4 KiB CHR bank reserved for data, I make that bank's tile sheet 128x112 pixels instead of 128x128.
And surprisingly, you don't mention the biggest issue I have with WLA currently : NO SUPORT OF RELOCATABLE CODE. If you want to copy your code to RAM and execute it from here, it's going to be a headache in most assemblers, including WLA.
Something that ld65 handles easily with its load and run addresses. See nes.ini and ramcode.s of Forbidden Four.
I think CC65 fixed all the issues I mentioned (confirmation would be fine).
PS : How CC65 handles + and - is really a MAJOR problem. I use them all the time in my code, and I'd never find names for so many labels.
For the tightest of loops (such as waiting for vblank or sprite 0, or clearing memory), I occasionally use the : labels with :+ and :-. But my current coding style, as seen in Concentration Room, uses .proc heavily. This allows labels such as "charloop" or "xloop" to be reused from subroutine to subroutine, allowing the labels themselves to reinforce the meaning of the code comments. And before that, back when I was working on a project that I started in x816 and finished in ca65, I used @ labels, which are valid only between normal labels. I've seen C compilers for various target platforms generate arbitrarily named @ labels as well.
User avatar
Banshaku
Posts: 2417
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Post by Banshaku »

Regarding unnamed labels:

I may be biased since I never used them but to me it feel more like a mess than anything. For small code with maybe one "-" or maximum two "--" it could be acceptable but the more you add, the mode it becomes messy. I think locals labels are the way to go (with CC65) since you can re-use their name and it can make the code clearer if used properly.

If you read the comments from the author of CC65, this is what he said exactly, word for word:

Code: Select all

Unnamed labels may be accessed by using the colon plus several minus or plus characters as a label designator. Using the '-' characters will create a back reference (use the n'th label backwards), using '+' will create a forward reference (use the n'th label in forward direction). An example will help to understand this:

            :       lda     (ptr1),y        ; #1
                    cmp     (ptr2),y
                    bne     :+              ; -> #2
                    tax
                    beq     :+++            ; -> #4
                    iny
                    bne     :-              ; -> #1
                    inc     ptr1+1
                    inc     ptr2+1
                    bne     :-              ; -> #1

            :       bcs     :+              ; #2 -> #3
                    ldx     #$FF
                    rts

            :       ldx     #$01            ; #3
            :       rts                     ; #4

As you can see from the example, unnamed labels will make even short sections of code hard to understand, because you have to count labels to find branch targets (this is the reason why I for my part do prefer the "cheap" local labels). Nevertheless, unnamed labels are convenient in some situations, so it's your decision.

edit: fixed missing )
Last edited by Banshaku on Thu Oct 07, 2010 8:59 pm, edited 1 time in total.
User avatar
blargg
Posts: 3715
Joined: Mon Sep 27, 2004 8:33 am
Location: Central Texas, USA
Contact:

Post by blargg »

I very rarely use more than one + or -. That's where a named label becomes useful. But a single - is very common for short loops. I think if you've never used them you might imagine they would be hard to read, but that's because you're imagining complex situations where they wouldn't be the best solution. For a typical file of mine that's about 290 source lines, there were 29 total labels, 13 unnamed, with all but one used for a 2-5 instruction loop. Thus, there is no difficulty in following them. It's clear that it's a loop, and a comment describes its purpose better than a label could. By reserving labels for situations that aren't loops or simple branches over a few instructions (i.e. part of an if construct), the very fact that something has a label communicates information about its use. If named labels were used for everything, this extra expressiveness would be lost as well.
User avatar
Kasumi
Posts: 1293
Joined: Wed Apr 02, 2008 2:09 pm

Post by Kasumi »

I'm a nesasm guy who has never used nameless labels, but I totally see them as useful. One case that immediately come to mind is extended branches.
Post Reply