====== ACME macro tutorial ====== Hi All! I just read in the Wish List someone wanted a small tutorial on how to use Macros in ACME. I've played with it a lot and found that it is pretty advanced stuff... ====== Basics ====== ===== define a Macro ===== !macro MacroName [Variable1 [,Variable2 [,Variable3 ]]] { ;some lines that make up your macro } ===== call a Macro ===== +MacroName [Variable1 [,Variable2 [,Variable3]]] Wow, now that was even less than you can read inside the AllPo.txt from the ACME documentation ... ===== simple Examples ===== I personally like Macros a lot, as they make Code much more readable. So I extended my by a few Macros like: !macro inc16 .t { inc .t bne .j; "*" syntax not used here because size of ".t" is unknown inc .t + 1 .j } ; far branch !macro bcc .t { bcs * + 5 jmp .t } !macro mv16im .wort, .mem { lda #<(.wort) sta .mem lda #>(.wort) sta .mem+1 } !macro mv16ab .wort, .mem { lda .wort sta .mem lda .wort+1 sta .mem+1 } With those you will be able to increment a 16bit value like this .my16bitValue !word 31336 by simply doing +inc16 .my16bitValue That would make .my16bitValue eleet ;-) Initialising the IRQ-vector could be done like this: +mv16im .irqroutine,$fffe ... .irqroutine asl $d019 ... rti Or if compiling the code reveals, that some branch is out of range, just prepend it with a "+" - as simple as that. I guess now you also start liking macros ;) ====== a little bit advanced Example ====== I like to code stuff that can be loaded and run directly. But I don't like BASIC-lines like 0 sys2063 When someone loads my crap and types "list" I'd like him or her to see a line like 2011 - the year when Neoplasia came back to life To have this neat little line in front of my code I wrote another library-routine which I use to !src instead of setting "* = 0801": ;============================================================================== ; ACME - Basicstart-Template ;-) by St0fF/Neoplasia ;============================================================================== !src <6502/std.a> !src * = $0801 !byte <.basend,>.basend,year,$9e !byte (.run/1000)+48,((.run/100)%10)+48,((.run/10)%10)+48,.run%10+48 !byte ":",$8f ;REM !fill 11,20 +der_text !byte 0 .basend !byte 0,0 .run ;YEAR SYS.run:REM~~~~~~~~~~~der_text So now you can start you code like this: ;my Routine, that starts with a nice BASIC line !macro der_text { !pet "the year when neoplasia came back to life" } year = 2011 !src You can clearly see that the "advancement" lays in this template using a very simple macro and a label defined before !src'ing it. ====== even more advanced examples ====== Codebase is great. I put some math code from here into a macro. The advancement is: the macro itself does not create any code, its sole purpose is precalculating a value I can use later on. Here we go with the "calculate square root at compile time" example: !macro wurzel Q,W { !set .M = Q !set .R = 0 !set .D = 128 !do while .D >= 1 { !set .T = .D * (2 * .R + .D) !if (.T <= .M) { !set .M = .M - .T !set .R = .R + .D } !set .D = .D / 2 } !set W = .R } Thanks a lot to Graham for the algorithm posting! Beware! Here we find some caveats in ACME's macro processing: each call of a macro seems to open up a subzone. So to use the "wurzel" macro, the "W" parameter needs to be a global label in the calling source. See this example of calculating lightsource data: ;Lightsource-Tabellen: ;LS/2 Tabellen über je eine Page, die die Lightsource-Farbe darstellen sollen ;============================================================================== !src "wurzel.ha" ;============================================================================== !for .y,LS/2 { !for .x,256 { !set .quadrat = (16-.y)^2 + (.x - 75 - LS/2)^2 +wurzel .quadrat,W !set .w = LS/2 - W -1 !if .w < 0 { !set .w = 0 } !by 15-.w } } ====== Use reference as macro params ====== When putting code into a macro that shall be manipulated from code outside (e.g. speedcode that is set up before being called) it is nice to have references as parameters for the macro-call. Just see the following example that does some nonsense as result: !macro my_code ~.pattern { .pattern lda #$00 sta $1000,x sta $1008,x sta $1010,x } lda #$55 sta pattern1+1 sta pattern2+1 eor #$ff sta pattern3+1 sta pattern4+1 ldx #$00 +my_code ~pattern1 inx +my_code ~pattern2 inx +my_code ~pattern3 inx +my_code ~pattern4 inx ... ---- I hope this small tutorial explains a few interesting aspects of macro-usage in ACME. If you have any questions, contact me somehow.