Page 1 of 2

SPC700 assemblers overview

Posted: Sun Jul 10, 2011 6:50 pm
by Shiru
If you ever need to write some code for SNES APU, you'll need one. Unfortunately, there is very few assemblers, and they aren't easy to find. I've spent a day searching available options, and here is the results, to save your time if you'd need this.

First, there are official tools, because the CPU core in SNES APU is just a part of a large MCU series (named SPC700). As an individual enthusiast, you can't have the tools, they probably cost a lot, but anyway, just as an interesting fact - there is Sony's assembler named WASM700II (virtually not mentioned in the internet), and Gaio Technology's toolset that includes an assembler, linker, C compiler, and IDE. You can find a lot of details on the MCU series and overview of the software in this PDF, and overview of Gaio's tools on their website.

For common people, less impressive options are available:

wladx-spc700 - unlike support of other processors, SPC700 support seems bad. There are reports from people who attempted to use it that it generates wrong code and has other bugs. There are sources, though, so maybe you will be able to fix the assembler (would be cool).

Telmark Cross Assembler (TASM) - is does not have native SPC700 support, but it is table-driven. You need to use this table created by GAU and revised by eKid. It was used to compile 5000+ lines of xmsnes, so it is tested well. There are downsides, though - this assembler is just old, and it is shareware. It costs $25, according to docs 'prolonged use without registration is unethical'.

spcas - very simple assembler specifically designed for SPC700, made by byuu, author of the bsnes. Reports are that it works well, but lacks many features, so may be not suitable for large projects.


If you are an hero, there are two extra options.

First, you can use an existing macro assembler and make macros for all the opcodes. If will work, and will give you nice set of features, but syntax will be unusual, because macro assemblers usually don't like spaces and special symbols in macro names, and error messages could be confusing.

Second, you can write your own assembler. It is a large project by itself, and in short time starting from scratch you can only make something comparable with spcas. However, if you already made an assembler, adapting it to SPC700 could take not that much time and effort.

Posted: Sun Jul 10, 2011 7:17 pm
by tepples
Or a way that doesn't require one to be suicidal: write a preprocessor in Perl or Python that outputs .byt statements, and have ca65 assemble that. This is like the macro way, but with the advantage of having more sophisticated syntax thanks to the regular expression facilities in such languages. It's also like the write-your-own-assembler way, but with the advantage that ca65 and ld65 handle all the label processing for you.

Posted: Sun Jul 10, 2011 7:33 pm
by Shiru
Agree, it could be a nice compromise between using macros and writing own assembler.

Posted: Sun Jul 10, 2011 8:15 pm
by Near
bass (successor to xkas) supports SPC700 syntax in Sony's format, and in an infinitely more logical 65xx style syntax. Your choice.

Has full define+macro+relocation support, among other things. Only thing it doesn't do is produce objects, but with a 16-bit processor and 64K RAM max, you really, really don't need that. Really.

Temporary link:
http://byuu.org/temp/bass_v00r06.tar.bz2

You'll have to compile it yourself (very easy, install TDM/GCC and run a batch file), or wait another day or two for v01 to be posted.

New syntax example:

Code: Select all

  sep
  jst 4
  set $55.2
  bbs $55.2,label
  eor $55
  eor $55aa
  eor (x)
  eor ($55+x)
  eor #$55
  eor $55,$aa
  and $55aa.0
  lsr $55
  lsr $55aa
  phx
  trb $55aa
  jsp $55
Again: old, ugly syntax is fully supported as well.

Posted: Sun Jul 10, 2011 8:31 pm
by Shiru
byuu, that's great. I almost decided to make my own assembler, and this will save me a lot of time.

Edit: Unfortunately it turned out that my bass build is broken to completely unusable state, including not working defines, macros, comments, etc. spcas also does not work for me, I haven't found anything like equ, and it does not report about problems, in simplest test it ends up in 7 bytes of generated code instead of expected 11 without any warning or errors. Together with lack of debuggers it makes work on code next to impossible.

Posted: Mon Jul 11, 2011 4:48 pm
by Near

Code: Select all

http://byuu.org/files/bass_v01.tar.bz2
Binaries and GPLv2 source included.

I can assure you that defines/macros work just fine, see example code under test/ :D

Posted: Mon Jul 11, 2011 6:34 pm
by Shiru
Tried this version. Defines seems working, but the same problem with macro:

Code: Select all

macro length()
  $000000
endmacro
Results in 'unknown command:macro length()'.

Other problem is that none of possible combinations of org and base allow to create a file assembled to, say, $0200, but without $200 zeroes in beginning of the file.

Posted: Mon Jul 11, 2011 7:36 pm
by Near
Sorry, namespace.asm wasn't updated yet.
Defines and macros were merged, ala test.asm. They work like this now:

Code: Select all

define base = $80
define add x = clc; adc.w #{base}+{x}
define sum x = {add {x}+0}; {add {x}+1}; {add {x}+2}; {add {x}+3}
define all x,multiplier
  {sum {x}+0*{multiplier}}; {sum {x}+1*{multiplier}}
  {sum {x}+2*{multiplier}}; {sum {x}+3*{multiplier}}
enddef

define hvbjoy = $4212

define loop
  wait{#}:
    lda {hvbjoy}
    bmi wait{#}
enddef

//this remaps strings for eg db "ABCD" -> db "abCD"
define 'A' = 0x61
define 'B' = 0x62

org $8000; base $7ec000
  {all $20, 4}; {all $30, 4}
Other problem is that none of possible combinations of org and base allow to create a file assembled to, say, $0200, but without $200 zeroes in beginning of the file.
Right, org is the location in the file, base is the location the code sees.

Use org 0; base $200 for what you want.

Posted: Mon Jul 11, 2011 7:42 pm
by Shiru
Ok, thanks. Now the last problem: comments with ; aren't work:

Code: Select all

rts ;test
Results in 'unknown command:test'. The same happens with any ;comment, does not matter if it is on a new line, with or without space after opcode.

Posted: Mon Jul 11, 2011 7:52 pm
by Near
Comments use //
Block separators use ;
It's like C++-style, but you don't need one for the last block on a line.

I know people like ; for comments, but ; is the most logical block separator.

Eg:
lda #$07; sta $2100 //set screen brightness to half intensity

If it bothers you that greatly, you can edit the source to change it, but please give it a chance =)

Posted: Mon Jul 11, 2011 8:02 pm
by Shiru
It bothers me because I use many different assemblers where a lot of things are different, and this is one extra thing. It is very uncomfortable to remember and relearn set of rules for every assembler.

Examples are # or $ for hex, @ or . or _ for local labels, : after labels in some assemblers, etc.

In many other assemblers block separator is : (and labels without : ). In 99% of assemblers ; is for comments.

I can change it in the source, of course, but what will do people who would like to use my code? Change source too, or replace ; with //? It is kinda unconvenient.

Posted: Mon Jul 11, 2011 9:01 pm
by Dwedit
Gnu Assembler uses @ for comments, and that's just wrong on so many levels. But that's what it uses.

Posted: Mon Jul 11, 2011 9:21 pm
by Shiru
Well, I think I can solve this problem seamlesly with a very simple preprocessor that will replace all the ; with // before compilation, and publish preprocessed files only. Still not very convinient, but as it is seemingly the best free SPC700 assembler available (and with active author, which is important), it is tolerable.

Posted: Mon Jul 11, 2011 9:51 pm
by Hamtaro126
Byuu's Macro technique is similar to TASM's Define/Macro technique,

That sounds like a decent thing.

Posted: Mon Jul 11, 2011 11:02 pm
by Shiru
I found it not so decent. Simplest thing from wla like

Code: Select all

.define ADDR=$f2
.define DATA=$f3

.define DSP_FLG=$6c

.macro dspn
	mov ADDR,\1
	mov DATA,\2
.endm

...

 dspn DSP_FLG,$00
turns into

Code: Select all

define ADDR=$f2
define DATA=$f3

define DSP_FLG=$6c

define dspn reg,val
	sti {ADDR},{reg}
	sti {DATA},{val}
enddef

..

 {dspn {DSP_FLG},$00}
In this case amount of additional symbols makes macros not helpful, because they are there to make code more readable, not more complex. Also, try to forget to use {} somewhere if you want to have a lot of fun searching what is wrong.

This system is probably works well for more complex uses, but not for this one.