It is currently Tue Oct 24, 2017 12:26 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 10 posts ] 
Author Message
PostPosted: Wed Apr 05, 2017 6:41 pm 
Offline
User avatar

Joined: Sat Jan 03, 2015 5:58 pm
Posts: 367
Location: ...
Code:
.define sprite(sprnum, sprattr) ($700+(sprnum*4)+sprattr)

The above does its job, but it seems ca65 doesn't expect it to be a function when used like this:
Code:
sta sprite(0, tile)

(tile is defined as 1). Unexpected trailing garbage characters.

The best workaround I've found is to add a "0+", as such.
Code:
sta 0+sprite(0, tile)

This isn't preferable, since it's kinda ugly. Are there any better ways around this?


Top
 Profile  
 
PostPosted: Wed Apr 05, 2017 6:44 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19122
Location: NE Indiana, USA (NTSC)
The macro appears to expand as follows:
Code:
sta ($700+(0*4)+tile)

But because the parentheses are outermost, ca65 thinks it's indirect addressing mode, which sta doesn't have.


Top
 Profile  
 
PostPosted: Wed Apr 05, 2017 6:50 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5736
Location: Canada
In my version of ca65 this gives "illegal addressing mode" which suggests to me that the problem is the parentheses () which suggest "STA (indirect)" which is an illegal addressing mode. Try your .define without the enclosing parentheses?

Edit: Hmm, didn't even get a ninja notification from tepples' post. ;)


Top
 Profile  
 
PostPosted: Wed Apr 05, 2017 7:08 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5736
Location: Canada
It's normal C macro practice to use the prophylactic () around your macro results, but it has this particular consequence in 6502 assembly where the meaning of () has this one contextual overload.

I've hit this particular problem myself a few times when using ca65 defines, making me wish there was some sort of "safe" expression enclosing operator that could wrap them up, like .expr() or something. Though, your 0+ solution is interesting; what if you put that directly in the .define instead of everywhere it's used?
Code:
.define sprite(sprnum, sprattr) 0+($700+(sprnum*4)+sprattr)


My actual practice is just to be very sparing with my use of .define in ca65, I think, preferring .macro in most cases (which has slightly fewer caveats). I find there's a lot of counter-intuitive things about its macro system if you're already used to C style macros, because it's not really a text substitution at all, but more like substituting a symbolic tokenized version.

Also, the command line -D define behaves differently from the .define control command, which is another thing to watch out for. (I forget exactly how at the moment. :S)


Top
 Profile  
 
PostPosted: Wed Apr 05, 2017 9:37 pm 
Offline

Joined: Fri Aug 21, 2009 3:16 pm
Posts: 37
I know DASM allows you to use square brackets as an equivalent to parentheses (e.g. [[blah+blah]*blah] ). Perhaps ca65 is similarly permissive.


Top
 Profile  
 
PostPosted: Thu Apr 06, 2017 7:57 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19122
Location: NE Indiana, USA (NTSC)
In ca65, square brackets mean indirect long, a 65816-exclusive addressing mode.

Putting the 0+ workaround in the macro could mess up operator precedence, as addition is fairly low in ca65's precedence chart.
Code:
; With a macro like this
.define sprite(sprnum, sprattr) 0+($700+(sprnum*4)+sprattr)
; Something like this
.word 0x8000 | sprite(0, tile)
; would expand to this
.word 0x8000 | 0+($700+(0*4)+tile)
; But because bitwise OR operator | binds more tightly than the
; addition operator +, it automatically parenthesizes thus
.word (0x8000 | 0)+($700+(0*4)+tile)

Instead, you can wrap with a unary prefix operator, as these tend to have the tightest precedence. One might try using +, the unary numeric no-op, but because + is also the numeric addition operator, it can hide syntax errors.
Code:
; With a macro like this
.define sprite(sprnum, sprattr) +($700+(sprnum*4)+sprattr)
; Something like this will unexpectedly assemble correctly
.word 0x8000 sprite(0, tile)
; because it expands to this
.word 0x8000 +($700+(0*4)+tile)

An invertible unary prefix operator that doesn't do double duty as an infix operator is ~, the ones' complement operator. Doubling it on an integer is a no-op unless there's something broken that I hadn't considered. So try this:
Code:
; With a macro like this
.define sprite(sprnum, sprattr) ~~($700+(sprnum*4)+sprattr)
; Your instruction
sta sprite(0, tile)
; expands to this
sta ~~($700+(0*4)+tile)


Top
 Profile  
 
PostPosted: Thu Apr 06, 2017 8:27 am 
Offline
User avatar

Joined: Sat Jan 03, 2015 5:58 pm
Posts: 367
Location: ...
Removing the parentheses fixed the problem, but I will consider ~~(using this) for other macros that may be mixed into formulas themselves.

Thanks all!


Top
 Profile  
 
PostPosted: Thu Apr 06, 2017 8:29 am 
Offline
User avatar

Joined: Mon Jan 03, 2005 10:36 am
Posts: 2963
Location: Tampere, Finland
As tepples suggested, I have been using ~~ to disambiguate these cases, although it's unfortunate that it's needed.

_________________
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: kkfos.aspekt.fi


Top
 Profile  
 
PostPosted: Thu Apr 06, 2017 9:04 am 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 19122
Location: NE Indiana, USA (NTSC)
Unfortunate but understandable. I guess MOS didn't anticipate that the equivalent of the C preprocessor would eventually be used on assembly language source code for its CPU. The first edition of The C Programming Language by K&R wouldn't even come out until 1978, three years after the 1975 introduction of the 6501 and 6502.


Top
 Profile  
 
PostPosted: Thu Apr 06, 2017 5:55 pm 
Offline
User avatar

Joined: Sun Jan 22, 2012 12:03 pm
Posts: 5736
Location: Canada
Apparently there is a .feature extension that selects [] for indirection instead of (). Maybe not useful on an existing project, but if you're starting from scratch (or perhaps switching from NESASM) you could just use square brackets for indirection instead and not have the conflict.
Code:
.feature bracket_as_indirect
jmp [$FFFC]


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 10 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: Bing [Bot] and 2 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