Ca65 "Constant expression expected"

Discussion of hardware and software development for Super NES and Super Famicom.

Moderator: Moderators

Forum rules
  • For making cartridges of your Super NES games, see Reproduction.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Ca65 "Constant expression expected"

Post by Drew Sebastino »

So, I have a struct for an object slot, and that's fine, but for whatever reason, ca65 doesn't like what I'm doing here:

Code: Select all

ObjectTable:		.res *-ObjectSlot*16
Doesn't "*-" mean the size of?
User avatar
koitsu
Posts: 4203
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Ca65 "Constant expression expected"

Post by koitsu »

I read *-ObjectSlot-16 to mean "{whatever the assembler thinks PC or the current 16-bit address is} minus {whatever ObjectSlot is} minus 16".
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: Ca65 "Constant expression expected"

Post by Drew Sebastino »

It's multiplied by 16.
User avatar
thefox
Posts: 3139
Joined: Mon Jan 03, 2005 10:36 am
Location: Tampere, Finland
Contact:

Re: Ca65 "Constant expression expected"

Post by thefox »

You can use .sizeof to get the size of a struct.
Download STREEMERZ for NES from fauxgame.com! — Some other stuff I've done: fo.aspekt.fi
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: Ca65 "Constant expression expected"

Post by Drew Sebastino »

When applying that to the code, it says "unexpected trailing garbage characters"

Code: Select all

ObjectTable:		.res.sizeof(ObjectSlot)x16
tepples
Posts: 22345
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Ca65 "Constant expression expected"

Post by tepples »

Try a space after .res and an asterisk instead of an x:

Code: Select all

ObjectTable:      .res .sizeof(ObjectSlot)*16
User avatar
rainwarrior
Posts: 8062
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Ca65 "Constant expression expected"

Post by rainwarrior »

1. No space between .res and .sizeof?
2. Are you expecting x16 to mean "times 16"? You might meant * 16?
(Edit: tepples made both those points already.)

What's ObjectSlot? Is it in the same segment?

It seems like ObjectTable - ObjectSlot might substitute for * - ObjectSlot in this case. The expression * is constant at link time, but not at assembly time. I'm not sure how smart the assembler is at deducing relative constants with it; it might fare better with labels in this respect? Possibly the problem is exacerbated because .res needs to evaluate constant immediately during the single pass assembly.
Nicole
Posts: 218
Joined: Sun Mar 27, 2016 7:56 pm

Re: Ca65 "Constant expression expected"

Post by Nicole »

It sounds like ObjectSlot is a struct, so they definitely don't want ObjectTable - ObjectSlot or * - ObjectSlot.
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: Ca65 "Constant expression expected"

Post by Drew Sebastino »

Yeah, thanks guys, this works. :)

Code: Select all

.res .sizeof(ObjectSlot)*16
User avatar
Drew Sebastino
Formerly Espozo
Posts: 3496
Joined: Mon Sep 15, 2014 4:35 pm
Location: Richmond, Virginia

Re: Ca65 "Constant expression expected"

Post by Drew Sebastino »

Not directly related to the problem earlier, but why start a new thread. I saw that I had something like:

Code: Select all

SpriteBuf1:	.res $200
SpriteBuf1Size=	*-SpriteBuf1
So I went and replaced every instance of SpriteBuf1Size with *-SpriteBuf1. I also had something that was SpriteBuf1Size+SpriteBuf2Size, that was just called "SpriteBufSize". It was being used at this "assert" that I noticed:

Code: Select all

.assert (SpriteBufSize < $10000), error, "SpriteBufs area too big for SNES DMA transfer"
So I changed it to this:

Code: Select all

.assert (*-SpriteBuf1+*-SpriteBuf2 < $10000), error, "SpriteBufs area too big for SNES DMA transfer"
However, for some reason unknown to me, it triggers the error. Is this not right? There's no way it could be too big:

Code: Select all

SpriteBuf1:		.res $200	;Sprite buffer for OAM DMA, 512 ($200) bytes
SpriteBuf2:    		.res $20	;Sprite buffer for OAM DMA, 32  ($20) bytes
Actually, wait, what? (referring to "*")
whatever the assembler thinks PC or the current 16-bit address is
How does this minus where something is equal the size of something?
User avatar
rainwarrior
Posts: 8062
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Ca65 "Constant expression expected"

Post by rainwarrior »

Espozo wrote:

Code: Select all

.assert (*-SpriteBuf1+*-SpriteBuf2 < $10000), error, "SpriteBufs area too big for SNES DMA transfer"
However, for some reason unknown to me, it triggers the error. Is this not right? There's no way it could be too big:

Code: Select all

SpriteBuf1:		.res $200	;Sprite buffer for OAM DMA, 512 ($200) bytes
SpriteBuf2:    		.res $20	;Sprite buffer for OAM DMA, 32  ($20) bytes
Actually, wait, what? (referring to "*")
whatever the assembler thinks PC or the current 16-bit address is
How does this minus where something is equal the size of something?
You don't seem to understand what * actually does, or what it is for.

If there was a label on the current line, * would be the address of that label. It has a different value on every line.

I don't know what you expect to be doing by measuring some current address (wherever that assert gets assembled) against both SpriteBuf1 and SpriteBuf2 at the same time. Both * in that statement must have the same value! * is just a single address value, it is not some sort of "sizeof" operator.
Espozo wrote:So I went and replaced every instance of SpriteBuf1Size with *-SpriteBuf1. I also had something that was SpriteBuf1Size+SpriteBuf2Size, that was just called "SpriteBufSize".
Have fun replacing them all again to fix the problems you've just created for yourself. :P

Here's a alternative:

Code: Select all

SpriteBuf1Size = $200
SpriteBuf1: .res SpriteBuf1Size
Nicole
Posts: 218
Joined: Sun Mar 27, 2016 7:56 pm

Re: Ca65 "Constant expression expected"

Post by Nicole »

Put another way, * is the current address wherever you happen to use it.

So, for this code:

Code: Select all

SpriteBuf1:   .res $200
SpriteBuf1Size=   *-SpriteBuf1
Let's say SpriteBuf1 is at the address $1000. Then, after reserving $200 bytes, the current address is now $1200. Therefore, * is $1200 at this point, so (* - SpriteBuf1) = ($1200 - $1000) = $200. This is why your old code worked.

However, you can't just replace everywhere you used SpriteBuf1Size with * - SpriteBuf1, because *'s value changes depending on where it's used.

If you later have a line like this at address $5000:

Code: Select all

lda *-SpriteBuf1
This won't have the desired effect, because the calculation will now be $5000 - $1000 = $4000.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Ca65 "Constant expression expected"

Post by tokumaru »

I don't know where you got that "* minus something is the size of something" thing from, but like Nicole showed, this is only true if you do this calculation immediately after "something" is defined. Do this anywhere else you'll not get the size of "something".
User avatar
koitsu
Posts: 4203
Joined: Sun Sep 19, 2004 9:28 pm
Location: A world gone mad

Re: Ca65 "Constant expression expected"

Post by koitsu »

tokumaru wrote:I don't know where you got that "* minus something is the size of something" thing from, but like Nicole showed, this is only true if you do this calculation immediately after "something" is defined. Do this anywhere else you'll not get the size of "something".
He got it from me, where I misread *16 as -16, which he promptly noticed, which just makes (his) misunderstanding even more confusing.
User avatar
tokumaru
Posts: 12106
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Ca65 "Constant expression expected"

Post by tokumaru »

I just figured I'd point out to Espozo that this is not wrong, it's a valid way to get the size of something that isn't a struct, but only if you do it right after the thing is defined. Just in case this wasn't clear in the place where he read about this.

Still, I wouldn't use this to get the size of a simple array... I would probably use a constant to hold the size, kinda like rainwarrior suggested. I use PC calculations for more complicated scenarios though, such as a bunch of variables I need 2 versions of (related to raster effects): the first block is declared normally, and then I get its size to reserve space for the second block. I also use the size as an index when I need to access the second block.
Post Reply