ld65 complains if I try to reuse zp addresses in different source files

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
rainwarrior
Posts: 8734
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: ld65 complains if I try to reuse zp addresses in different source files

Post by rainwarrior »

tokumaru wrote: Fri Feb 18, 2022 12:42 pmBut what about static memory allocation for call trees?
I've never found this terribly complicated or error prone?

For the most part, an occasional one-line clobber list comment seems to keep track of nearly everything I need to know about this.

In practice most of my call trees aren't very deep at all, or fairly well contained. I'm struggling to even think of a situation where the structure would need to change so often and so much that it would sound like the problem you seem to be describing.
tokumaru wrote: Fri Feb 18, 2022 12:42 pmYou may not yet have run into a case where this became a problem for you personally, but you can't confidently say that this approach is versatile enough to handle anything you throw at it.
I can confidently say that I haven't felt it was inadequate in my last 10 years of using cc65.

It also seems adequate for the extensive cc65 library codebase, which also operates using a global collection of static variables. (Incidentally, it uses org only once, and it's to place a labelled structure on a memory mapped register, which I think is an interesting application.)

.

Anyway, like I said, glad it works for you. I appreciate the perspective you've provided as to why you want to do it, and I will gladly recognize that it sounds productive and useful for you. ...but you haven't persuaded me that I should use it, or that I should recommend it to others. I still advise against using org in general with this toolset. (On more specific cases I'm sure there's a situation where I could be persuaded.)

Of course, I also wouldn't advise to remove/change it from a large codebase where it's working well either. If I were adopted into an existing project, I would continue doing things the way they were.

From my interpretation of OP's question, superficially it felt to me like they were probably using org unnecessarily. I can see how it looks naturally like your apparent paradigm for using it heavily, but for me it sticks out, especially the way OPs problem was described. I don't know if OP is starting out, or already in deep, or what, but it's my honest opinion that it's generally best not to work against the linker like this.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: ld65 complains if I try to reuse zp addresses in different source files

Post by tokumaru »

I'm actually surprised that call trees aren't a problem for people working on large programs... I don't have particularly complex call trees either, but I do often add new functionality that requires changes be made to different functions, and it's not terribly uncommon that I have to reorganize or add local variables every so often.

I often use clobber lists as well, but the thought that I might miss something and accidentally try to use the same memory for different purposes at the same time scares me to death! If I can make the assembler explicitly tell me when something goes wrong, I'll feel much safer.

You can still implement safer static allocation of locals without using the .org directive though... If you have a block of memory for locals reserved in a traditional manner (e.g. LocalBase), you can use a small set of straightforward macros to do something like this:

Code: Select all

StartLocal 4 ;skips 4 bytes used in nested calls
  DetectCollision NestedFunction1_LocalEnd ;makes sure we skipped all of NestedFunction1's locals
  DetectCollision NestedFunction2_LocalEnd ;makes sure we skipped all of NestedFunction2's locals
  DeclareLocal MyWordVariable, 2
  DeclareLocal AnotherVariable, 1
  DeclareLocal SmallArray, 5
EndLocal MyFunction_LocalEnd ;marks the end so other functions can detect collisions with this
Here are some possible implementations for these macros:

Code: Select all

.macro StartLocal  _Start
  _Offset .set _Start ;resets the offset
.endmacro

.macro DeclareLocal _Label, _Size
  _Label := LocalBase + _Offset ;creates alias
  _Offset .set _Offset + _Size ;updates offset
.endmacro

.macro EndLocal _Symbol
  .assert _Offset <= LOCAL_SIZE, error, "Local memory overflow"
  .ifnblank _Symbol
    _Symbol = _Offset ;remembers final offset
  .emdif
.endmacro

.macro DetectCollision _Symbol
  .assert _Offset >= _Symbol, error, "Possible collision of local variables"
.endmacro
Using something like this you can rest assured that you will be warned if one function invades the local space of another function, and you can just go to the exact place where the error happened and increase the start offset until the error is gone.

I'm under the impression that you might not be a fan of these little snippets of automation either, even if it's basically doing the same thing you would be when manually creating aliases, but automatically, which is significantly safer.

BTW, I'm not trying to convince you to do things differently or anything, I'm just saying that .org isn't really required in order to implement a more robust static allocation control system, even if not everyone needs something like this.
User avatar
Movax12
Posts: 541
Joined: Sun Jan 02, 2011 11:50 am

Re: ld65 complains if I try to reuse zp addresses in different source files

Post by Movax12 »

This thread seems to be going in this direction, so I guess I will post this here. This isn't as polished as I would like: the documentation is not complete, but there is a demo that should demonstrate what the documentation is missing.

Full functionality relies on thefox's NintendulatorDX. It could be used without NDX, but it would be very difficult to keep track of overlapping local variables.

https://gitlab.com/ca65/funcCall

Please see the README in the repository.
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: ld65 complains if I try to reuse zp addresses in different source files

Post by DRW »

tokumaru wrote: Thu Feb 17, 2022 10:40 pm If you don't mind me asking, what is your proposed solution for declaring overlapping variables (such as for local variables or for modules that never run at the same time) that doesn't use ORG and doesn't require the creation of a bazillion different segments?
tokumaru wrote: Fri Feb 18, 2022 1:27 am
Aliases also work fine for this.
But then you lose all the versatility of using .res for reserving space, and instead have to do it the error-prone way of adding a number to the previous variable (var2 = var+2). Want to reorganize variables? Then you need to change all the references to the preceding variables as well, not to mention that the number you add on each line is the size of the variable in the *previous* line (the last variable doesn't even have its size explicitly stated unless you add a dummy variable after it just for that). This is way messier and error-prone than a simple .org based solution, and I'm really surprised that you find that the cleaner alternative.
How about this pretty straightforward solution?

Code: Select all

.segment "ZEROPAGE"
Byte1: .res 1
Byte2: .res 1
Byte3: .res 1
Int1: .res 2
Int2: .res 2
Long1: .res 4

; In another file:

.import Byte1, Byte2, Byte3, Int1, Int2, Long1

Counter = Byte1
Energy = Int1
XPosition = Byte2
YPosition = Byte3
No messy manual calculation with numbers.
Referencing a variable that doesn't exist yet (Byte4) gives you a compiler error (unlike var + 3 which the compiler would simply accept).
And reorganizing is also pretty simple. Just make sure that you don't use the same variable name twice in the same function.
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: ld65 complains if I try to reuse zp addresses in different source files

Post by DRW »

About call trees, nesting functions etc.:

My general-purpose variables are lettered: Byte1A, Byte2A, Byte3A, Byte1B, Byte2B, Byte1C etc. Plus a bunch of non-lettered variables: CommonByte1, CommonByte2 etc.

Every function that doesn't ever call another function uses the common variables.
Every function that calls only functions who don't use variables themselves (or who just use the common variables) uses the A variables.
Functions that call A functions use the B variables.
Functions that call B (and A and common) functions use the C variables.
And so on.

To make sure that the usage of the variable blocks don't get confused, I write a postfix to each function: _vA if they use the A variables (or call a function that uses the A variables), _vB if they use the B variables and so on.

This way you only have to really reorganize anything if MyFunction_vA suddenly needs to call MyOtherFunction_vA. This means MyFunction_vA now has to become MyFunction_vB and the variable aliases have to be changed accordingly.

But in this case, the compiler helps you by finding all the instances of the name MyFunction_vA that is now invalid. And when you rename instanses of JSR MyFunction_vA to JSR MyFunction_vB, you can also immediately rename the outer function from _vB to _vC. Repeat until there are no more compiler errors.

In my current case, I have about 20-25 variables in A, B and C each. And only three in D. There wasn't a necessity yet to declare a block of E variables.

P.S.: The CommonByte variables are optional. You can simply start with the A variables. But I included the common variables, so that totally self-contained generic functions who are guaranteed to never use JSR, like CopyMemory, don't already need to occupy the _vA range, but can be treated like functions that don't use local variables at all. And this way, if your _vA function suddenly needs to call CopyMemory, you don't already need to turn it into a _vB function.
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
chains
Posts: 1
Joined: Thu Mar 24, 2022 5:03 pm

Re: ld65 complains if I try to reuse zp addresses in different source files

Post by chains »

spaceharrier wrote: Mon Feb 14, 2022 8:34 pm
tokumaru wrote: Mon Feb 14, 2022 8:20 pm "does not like this" is very vague. Can you tell us what the actual error message is?
An example of output error ld65 gives me is as follows:

Code: Select all

ld65: Warning: Address size mismatch for 'readjoy_safe': Exported from joy.o, source\joy.s:79 as 'zeropage', import in start.o, source/joy.inc:12 as 'absolute'
I'll leave this message here just in case anyone else stumbles across this message and is using C.

You must add a `pragma` to the exported `extern` variable indicating to the linker that your variable is on ZP:

Code: Select all

//file1
#pragma bss-name(push, "ZEROPAGE")
unsigned char temp1;

// file2
extern unsigned char temp1;
#pragma zpsym("temp1");
Post Reply