say you got a sprite struct { x,y,c,p,xlo,dx,ylo,dy } (first 4 members are for 9918 usage).
struct of arrays style: x[256], y[256], c[256],... addresses of all arrays must be 256 aligned:
C000 spr_x equ 0xC0 ; take care your definitions are right for LD H,label usage. C100 spr_y equ 0xC1 C200 spr_c ... C300 spr_p C400 spr_xlo C500 spr_dx C600 spr_ylo C700 spr_dy
comparison. move sprites by adding dx,dy. for a short example, code does only handle x, and only 8bit dx, like dx=255 means speed 0.999.
ld l,0 ;L = struct index = 0 ld b,spr_count loop: 8 ld h,spr_dx ;ld h: select random struct member 8 ld a,(hl) 8 ld h,spr_xlo ;ld h: select random struct member 8 add (hl) 8 ld (hl),a 8 ld h,spr_x ;ld h: select random struct member 8 ld a,(hl) 8 adc 0 8 ld (hl),a 5 inc l ;inc l: next struct -- 77 cycles total djnz loop
and now in classic 16bit comfort style, using IX, array of struct:
C000 spr C000 spr_x C001 spr_y C002 spr_c C003 spr_p C004 spr_xlo C005 spr_dx C006 spr_ylo C007 spr_dy ld ix,spr ld b,spr_count ld de,8 ;size of struct loop: 15 ld a,(ix + dx) 15 add (ix + xlo) 15 ld (ix + xlo),a 15 ld a,(ix + x) 8 adc 0 15 ld (ix + x),a 16 add ix,de ;next struct in 16 cyles AND waste DE for sizeof struct offset -- 99 cycles total djnz loop
slow, must optimize:
C000 spr C000 spr_x C001 spr_y C002 spr_c C003 spr_p C004 spr_xlo C005 spr_dx C006 spr_ylo C007 spr_dy ld b,spr_count ld hl,spr_x ld de,8 ;size of struct exx ld hl,spr_xlo ld de,8 ;size of struct exx loop: 8 ld a,(hl) ;xlo 8 inc hl 8 add (hl) ;dx 8 dec hl 8 ld (hl),a ;xlo 5 exx 8 ld a,(hl) 8 adc 0 8 ld (hl),a 11 add hl,de ;next struct 5 exx 11 add hl,de ;next struct -- 96 cycles total djnz loop
rewrite everything to use HL, and result is just a few cycles less?
sidenote: if you would move the x member more near to xlo,dx to get faster member addressing,
then you wrecked the 9918 header. you will then get slow code when sending the bytes to VDP
just to make this code look good, this would be kind of cheating.
sooner or later, members will be further away than just an INC HL.
-- summary: --
z80 was always called the nice 16bit comfort in comparison to 6502 and also 8080.
but if you want really fast code, z80 is the hardest cpu:
registerallocation including EXX is a lot of work with lots of special purpose registers,
8/16 bit multiparadigm, HL/IX multiparadigm.
but the 256 byte aligned array style (where applicable)
is fast and also easy to program once you wrapped your head around it.
game enemy structs are a very good candidate for this paradigm, what do you think?
it turns your z80 in a faster machine and more comfortable to program 
-- APPENDIX: limits, null pointer, pointer types etc --
limits: you can have max 255 objects of the same struct type.
max 255 sprites, max 255 charset BOBs, etc... I think 255 sprites is ok 
null pointer: one does prefere to start at index L = 0. though L = 0xFF is a good candidate for null pointer.
when you got between 0 and 255 objects, the number of objects fits in 8bit.
and the indexes of 255 objects go from L = 0 to L = 254. and L = 255 is the NULL pointer, nice match.
variable name style: to avoid confusion, make variablenames struct_member,
so you always are aware which array is meant to belong to which struct:
spr_x equ 0xC0 spr_y equ 0xC1 bob_x equ 0xC8 bob_y equ 0xC9
an index meant to be used for spr got no meaning in bob, the variable naming helps here too.
storing only 8bit indexes in most cases is as useful as full pointers in classic style.
with index in L, you need to know the type of the struct to get a full address:
nothing really new, in classic style you too need to know the struct type to make sane struct offsets.
index in L, know that it is a spr, full address: LD H,spr_x. I took the first member of the struct.
exception: a code capable of working on x,y members, no matter whether it is a spr or a bob.
in this case you need to pass the full pointers to the code in question.
setxy0: ;set members x and y to 0. full address in HL ld (hl),0 ;member x = 0 inc H ;to next member in 5 cycles: inc HI byte of address. ld (hl),0 ;member y = 0 ret
this kind of is a mixed mode paradigm: you work with full pointers.
but next byte of the struct is still 256 bytes further.



, then 6 accesses per 4 sprites=24)

