Since we are talking about unnecessary code for pointers, I could talk about one of the result of my tests. One of my function that is processing intensive data requires to be done in asm. The parameters are for an entity that we put in a buffered list so it will be set later in the OAM when parsing is over. Instead of passing the parameters to the function or one my one with some with some ZP variables, what I do is I share a block of memory from the asm side and map it on the C side with a struct. This way all parameters, pointer included, are accessed with an indexer and cc65 doesn't use it's ptr1 thingy.
The c code would look that way when imported:
Code: Select all
someheader.h
typedef struct {
char x;
char y;
char foo;
const char* data;
} myParmeters_t;
extern myParameters_t addToBufferParams;
#pragma zpsym("adToBufferParams");
void __fastcall__ addToBuffer(void);
when used:
Code: Select all
mycode.c
// ---- begin addToBuffer -----
addToBufferParams.x = actor.x;
addToBufferParams.y = actor.y;
addToBufferParams.foo = actor.foo;
addToBufferParams.data = actor.currentFrame;
addToBuffer();
// ----- end addToBuffer ---------
Finally, the assembler would look something like this:
Code: Select all
.export _addToBuffer := subAddToBuffer
.exportzp _addToBufferParams := zpParams
.segment "ZEROPAGE"
zpPrams: .res 10 ; this is a shared buffer for parameters
.segment "BSS"
bufferedList .res 60 ; some list of entitites
.segment "CODE"
;->BEGIN----------------------------------------------------------------------
; add to entity buffer
;
; Note: uses shared parameters (etc etc)
;
.proc subAddToBuffer
;---------------- Parameters definitions ----------------
.scope local
posX = zpParams
posY = zpParams+1
foo = zpParams+2
data = zpParams+3
.endscope
;---------------------------------------------------------
; ... some code before
lda local::posY
; do some processing
sta bufferedList,x
; .... mode code here
rts
.endproc
;-<END------------------------------------------------------------------------
The code generated on the C side access the shared buffer with indexers (_addToBufferParams,x) for all parameters so it should be fast enough. But, it may be possible that different structs may generate different access code so more testing would be required.
One thing that may not be relevant to this conversation but found interesting is that cc65 doesn't use signed char by default: everything is unsigned unless you pass a parameter to the compiler. Which means, unless you want to write portable code (which is maybe not that possible with the nes), you don't have to write unsigned char since char is unsigned. My definition of variable were becoming long with all those const that I may decide to remove the unecessary unsigned for now. I'm just used to write it out of habit.
edit:
I confused it with some other tests, it was not with an indexer but like this:
Code: Select all
; addTobufferedListParams.data = hero.frame.current;
518 ;
519 .dbg line, "src/example1.c", 201
520 lda _hero+7+1
521 sta _addTobufferedListParams+3+1
522 lda _hero+7
523 sta _addTobufferedListParams+3
edit2:
Updated the asm code since it did something else. This code is written by end for example only.