Yes, another Orgams dedicated thread!

It could be useful to share here some useful macros. It could save time for everyone.

I was tired to replace FILL x,0 by a DJNZ loop so I wrote this one:

MACRO nops n ; n must be >4
ld b,n-1 /4
djnz $
FILL n-1 MOD 4,0
ENDM

Then we can write nops(30) to wait 30 nops (b register and Z flag are affected).

Examples copied from the manual.

**ALIGN(n) **
Advance $ to the closest multiple of n.

If $ is already a multiple if n, it is unchanged.

NB: $$ is incremented by the same amount

MACRO ALIGN n
SKIP -$ MOD n
ENDM

Explanation:

We want to skip x bytes such that $+x = 0 [n] and 0 <= x < n

This amounts to x = -$ MOD n

**ASSERT(predicate)**

Raise an error if predicate isn't true.

There is no ASSERT directive. It can be simulated by:

MACRO ASSERT predicate
IF predicate:ELSE
!! ERROR !!
END
ENDM

Explanation:

The '!! ERROR !!' part is not seen at all if predicate is true,

otherwise it triggers an assembly error.

**ASSERT_NOT(predicate)**

MACRO ASSERT_NOT predicate
IF predicate
!! ERROR !!
END
ENDM
[...]
ASSERT_NOT (my_table AND &ff) ; Ensure my_table is xx00 aligned address.

While '=' operator is missing (

**if toto=4**), use

**CHECK_EQUALS**:

MACRO CHECK_EQUALS x,y
IF x-y
!!! Error values are not equal.
END
ENDM

Useful to make sure a variable hasn't moved or a routine is properly aligned:

CHECK_EQUALS(drive_id, &9060)
rvi0
[...]
CHECK_EQUALS($, &bc40)
[...]

Attente qui marche pour

**n >= 0**.

MACRO nops n ; n >= 0
if n-1 AND &ffc
ld b,n-1 /4
djnz $
FILL n-1 MOD 4,0
else
FILL n,0
end
ENDM

Ohoh! Well done.

In the same spirit, to wait l lines (l*64 nops):

MACRO lines l
ld bc,l*8 -1
nop
dec bc
ld a,b
or c
jr nz,$-4
nops(6)
ENDM

Modify A, B, and C registers.

This happens to work, yet it's more prudent and clearer to name your parameter **n** instead of **l**.

Oh yes, I don't think about the synonymy with L register!

Magic numbers are bad for a number of reasons. Especially when you have to read a source of yours after being captive in the Columbia forest for 4 months.

; What ??
ld a,128 ; Hu...
cubes# = 128 ; Power of two
[...]
ld a,cubes#

We can go one step further (I know, "Name of your sex tape"), by annotating via code why it must be a power of two. I'll assume that you need a cheap modulo:

MACRO IS_POWER_OF_2(n)
IF n AND [n-1]:
!!! Error must be power of 2
END
ENDM
[...]
IS_POWER_OF_2(cubes#)
inc a:and cubes# - 1 ; modulo

Hence the constraint is next to the code needing it. If the code is removed, also removing the constraint is a no-brainer.