Z80 Good Programming Practices
From WikiTI
Using IX
If you have objects represented by adjacent chunks of data in memory, you can use IX to easily manage them.
Without | With |
---|---|
ld b,10 ld hl,SpritesData DisplaySpritesLoop ld b,(hl) ; coordx inc hl ld c,(hl) ; coordy inc hl ld d,(hl) ; first part of address inc hl ld e,(hl) ; end of address inc hl call DisplaySprite djnz DisplaySpritesLoop |
COORDX equ. 0 COORDY equ. 1 ADDR1 equ. 2 ADDR2 equ. 3 ld b,10 ld ix,SpritesData DisplaySpritesLoop ld b,(ix+COORDX) ld c,(ix+COORDY) ld d,(ix+ADDR1) ld e,(ix+ADDR2) call DisplaySprite ld hl,4 add ix,hl djnz DisplaySpritesLoop |
Defining constants for the offsets of each field of your "objects" makes the code more understandable.
Lookup table
If you have a place in your code where a value is tested to choose between a lot of things, like subroutines or data, it can be a good idea to use lookup tables instead of a series of tests. It makes the code more readable, concise and extensible.
Without | With |
---|---|
ld a,(SpriteNumber) cp 1 jp z,ChooseSprite1 cp 2 jp z,ChooseSprite2 cp 3 jp z,ChooseSprite3 cp 4 jp z,ChooseSprite4 ... ChooseSprite1 ld hl,Sprite1 jp DisplaySprite ChooseSprite2 ld hl,Sprite2 jp DisplaySprite ChooseSprite3 ld hl,Sprite3 jp DisplaySprite ChooseSprite4 ld hl,Sprite4 jp DisplaySprite ... DisplaySprite ld bc,(coordinates) call SpriteRoutine |
ld a,(SpriteNumber) add a,a ; a*2 ld h,O ld l,a ld de,SpriteAddressLUT add hl,de ld bc,(coordinates) call SpriteRoutine ... SpriteAddressLUT .dw Sprite1 .dw Sprite2 .dw Sprite3 .dw Sprite4 |
And this one :
Without | With |
---|---|
ld a,(MenuChoice) cp 1 jp z,Choice1 cp 2 jp z,Choice2 cp 3 jp z,Choice3 cp 4 jp z,Choice4 ... |
ld a,(MenuChoice) add a,a ; a*2 ld h,O ld l,a ld de,CodeBranchLUT add hl,de bcall(_LdHLInd) jp (hl) ... CodeBranchLUT .dw Choice1 .dw Choice2 .dw Choice3 .dw Choice4 |