Accessing C struct members from Assembly?

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

Post Reply
User avatar
gauauu
Posts: 779
Joined: Sat Jan 09, 2016 9:21 pm
Location: Central Illinois, USA
Contact:

Accessing C struct members from Assembly?

Post by gauauu »

I'm curious if cc65/ca65 has a method for accessing C struct members by name from assembly. I looked through the docs and didn't find anything.

Here's an example of what I mean:

Code: Select all

struct Foo {
  char x;
  char y;
  char z;
}

struct Foo myFoo;
Now later in assembly, I want to access myFoo.y without knowing the position of y in Foo. If I know that it's the 2nd member, it's easy to do:

Code: Select all

 lda _myFoo+1

But is there any notation for accessing it by name y? I know there are also structs in ca65, but I don't know any way to make a struct available to both C and assembly without building my own preprocessor to generate the code for one or the other.

(I know I can completely rework things, using structs of arrays instead of an array of structs, etc. I know there's many reasons not to do what I'm doing in 6502. I'm not asking about those here. I'm just curious if there's a way to let assembly know about the ordering of members so that if I add a member w in Foo, before x, my assembly code won't need to be updated.)
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: Accessing C struct members from Assembly?

Post by dougeff »

You could define some constants to make the code clearer.

x = 0
y = 1
z = 2

So
lda _myFoo+1
becomes
lda _myFoo+y

*x, y, z are not good variable names
Last edited by dougeff on Fri Nov 16, 2018 2:45 pm, edited 1 time in total.
nesdoug.com -- blog/tutorial on programming for the NES
User avatar
gauauu
Posts: 779
Joined: Sat Jan 09, 2016 9:21 pm
Location: Central Illinois, USA
Contact:

Re: Accessing C struct members from Assembly?

Post by gauauu »

dougeff wrote:You could define some constants to make the code clearer.

x = 0
y = 1
z = 2

So
lda _myFoo+1
becomes
lda _myFoo+y
Yeah, that's what I've done in the past. It still requires me modifying all the constants if I insert a member w. Worst comes to worst, I can write a pre-processor that generates all those constants for me, but I'd hate to do that if cc65 already provides a mechanism to do this.
*x, y, z are not be good variable names
Absolutely, they're just placeholders to illustrate the problem. Like Foo.
User avatar
Banshaku
Posts: 2417
Joined: Tue Jun 24, 2008 8:38 pm
Location: Japan
Contact:

Re: Accessing C struct members from Assembly?

Post by Banshaku »

There is no automated way, unfortunately (except for maybe the hack above but I don't know if there is any drawback to do so :lol:).

What I do is I have a file that contains the definition, again, for the asm side and I keep them in sync when updated. If you don't have many structure to share it may not be a big issue. An example of what I used:

C side:

Code: Select all

typedef struct {
	const unsigned char* frameCount;
	const unsigned char* const *frameList;
} animInfo_t; 

typedef struct {
	unsigned char index;           // index of the frame to be shown
	unsigned char count;           // current count for next frame
	unsigned char maxCount;        // how long is the frame
	const unsigned char* current;  // the current frame to be shown
} frameInfo_t;

// player's specific information
typedef struct {
	int x;						   // location inside stage. May need negative, not sure yet.
	int y; 						   // vertical location, now 16 bits for checking bound outside screen
	unsigned char direction;       // which direction facing, left or right
	unsigned char priority;		   // if shown priority is front or background
	unsigned char outOfBound;	   // if went out of bound in a direction (up/down/left/right) based on the limit of the map
	unsigned char state;	       // state of actor (for player, this means animState)
	unsigned char subState;        // state that modify current state (ex: using weapon while doing somethings)
	unsigned char previousState;   // previous states
	unsigned char health;		   // tentative: value for health
	unsigned char invicibleTimer;  // flag & counter for invincible state (> 0, in that state)
	unsigned char weapon; 		   // which weapon was selected
	frameInfo_t frame;
	animInfo_t anim;
} player_t;
Asm side (started to convert recently, maybe issue in it)

Code: Select all

;
; Info regarding animation for the currently selected anim
;
.struct FrameInfo
    index       .byte 
    count       .byte
    maxCount    .byte
    current     .word 
.endstruct

;
; animation info
;
.struct AnimInfo
    frameCount  .word
    frameList   .word
.endstruct

;
; Player information definition
;
.struct Player
    posX        .word
    posY        .word
    direction   .byte
    priority    .byte
    outOfBound  .byte
    state       .byte
    subState    .byte
    previousState .byte
    health      .byte
    invicibleTimer .byte
    weapon      .byte
    frame       .tag FrameInfo
    anim        .tag AnimInfo
.endstruct
Something like that.

Then in asm you just use the struct, like expected:

Code: Select all


lda _gplayer + Player::state

User avatar
gauauu
Posts: 779
Joined: Sat Jan 09, 2016 9:21 pm
Location: Central Illinois, USA
Contact:

Re: Accessing C struct members from Assembly?

Post by gauauu »

Yeah, the C has more type information than what would be in the assembly (signed vs unsigned, whether it's an int vs a pointer), so my intention was to go that direction.
User avatar
gauauu
Posts: 779
Joined: Sat Jan 09, 2016 9:21 pm
Location: Central Illinois, USA
Contact:

Re: Accessing C struct members from Assembly?

Post by gauauu »

Either way, thanks for the suggestions. I appreciate the input.
Post Reply