This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download


by on (#217107)
To stop derailing the other thread I'm pealing this one off
From the other thread
Garth wrote:
Oziphantom wrote:
Macros are nice, but they are mermaids.. they sing a sweet song and send you to your doom if you are not careful. If you make the "safe" its mostly ok. But you have to really plan to properly and understand how they work etc. I did have a lot of macros but I found they tend to make the code less readable and maintainable after a while. ADCB_W, ADCBX_W, IFBLT, IFBLTE, BAGTE etc.

Take a different approach. Instead of using cryptic names, make it really clear what they're doing, and use the parameters to make like a sentence. If your ADCB_W means "Do a double-precision (16-bit) add-with-carry of B and W," you could change the macro name to something like _16bit_ADC, and make the line say for example,
        _16bit_ADC   B, _and, W    ; B=B+W

(Unfortunately the assembler requires separating parameters with a comma, which is why there's a comma after the _and.) The "_and" (with the underscore or other character to keep the assembler from confusing it with the mnemonic) is an equate that does not actually get used by the macro. It's only there to make things more readable to humans. The comment clarifies where the answer goes. So this would assemble the same as
        LDA   B
        ADC   W
        STA   B
        LDA   B+1
        ADC   W+1
        STA   B+1

The same macro can be used to add different variables which you specify in the parameters, rather than being confined to B and W. Conditional assembly in the macro definition can do optimizations if necessary. Some assemblers let you say in essence, "If there's a fourth parameter, do the following;" so you could use the same macro to add more than just two numbers, and you could invoke it something like this:
        _16bit_ADC   B, W, _and, offset3    ; B=B+W+offset3

If your IFBLT means "if: branch if less than," and only assembles a BMI, it's not really clarifying or shortening anything. How about something like this instead, where a portion is skipped if the N flag is set:
        IF_POSITIVE    ; Negative result above causes it to skip the following lines.

or to branch back to the beginning of a loop as long as the result is negative:
        BEGIN           ; (Or name it "DO" if you like)

Then you don't even need a label (although you can still use one if you want to).

The idea of using dummy strings to improve readability is a nice one. (note if you want to avoid the , issue you can switch to tass64. the .fucntion form of macros lets you do thing a,x,_and,b,y and it will work it out just fine ;) )
For me the issue with _16_ADC B, W, _and, offset3 is it puts me in to a C/C++ intrinsic function mindset to which point I start to forget about # although in the example you give you then need _16_ADC_Immed B,W or if the assembler lets you determine a parameter type _16_ADC B,#W but then getting it to be able to do #<#W might be tricky...
The Mermaid part comes from the _16 ADC_8_Immed case
lda B
adc #W
sta B
bcc +
inc B+1

say given
  ldx #7
- lda 2
  bit 4
  bpl +
  _16_ADC_8_Immed 8,40
  jmp _next
+ _16_ADC_8_Immed 8,20
  bpl -

spot the bug ;)
I would think that your DO/WHILE LOOP/UNTIL would have the same issue. Unless your assembler is that rare beast that lets you make unique labels? can you Loop in a Loop?

My point with
#ADCBW Add With Carry Byte to Word
#DXP Decrement X branch if Positive
was to make "instructions" and keep the Assembly look and flow.
BALT - Branch A Less Than
BALT immediate/address branch_target
IF A < value THEN branch
BALT .segment
   cmp \1
   bcc \2

ISALT - IS Address Less Than
ISALT address immediate/address branch_target
IF (address) < value THEN branch
ISALT .segment
   lda \1
   cmp \2
   bcc \3
this way I don't have to remember which way 6502 does the comparasing. Does it branch if A is < CMP or if CMP is less than A - ISALT Thing,cmp,dest - however as I said this was stupid ;)
As mentioned I have since abandoned this idea in favor of !!if Thing < Other then DEST and then !!Dest += #5, !!Dest &|= #$f0,#$02, !!Dest = Src + other - #40, loops and 16bit versions of the maths are the next big things to tackle though...