Nie znam asm, ale na podstawie tego co można znaleźć w kilku moich ulubionych książkach udało mi się stworzyć procedurki do rysowania i pisania na ekranie. Dumny jestem z printa, który wykorzystuje feature Actionowego „string constant”, czyli fakt, że element zerowy łańcucha napisu zawiera długość napisu, którą wydłubujemy w asm i podajemy w ICBLL, określając długość bufora.
MYGR.ACT
include "H1:ASMINC.ACT" proc main() int r card savmsc=88 card textaddr=660 byte bkg=710 byte array dltb=[ 112 112 112 66 96 159 72 112 158 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 65 78 158 ] card dlist=560 graphics(3) bkg=0 dlist=dltb textaddr=40800 savmsc=40560 print("ACTION! rules") for r=0 to 18 step 2 do plot(0+r,0+r) drawto(0+r,10+r) plot(0+r,10+r) drawto(10+r,10+r) plot(10+r,10+r) drawto(10+r,0+r) plot(10+r,0+r) drawto(0+r,0+r) od do od
MYLIB.ASM
org $600 graphics pha ldx #$60 lda #close sta iccom,x jsr ciov lda #open sta iccom,x lda <fname sta icbal,x lda >fname sta icbah,x pla sta icaux2,x and #$f0 eor #$10 ora #opnino sta icaux1,x jmp ciov rts ; org $62b position sty colcrs stx colcrs+1 sta rowcrs rts ; org $632 plot jsr position ldx #$60 lda #putchr sta iccom,x lda #$0 sta icbll,x sta icblh,x lda color jmp ciov rts ; org $64b drawto jsr position lda color sta atachr ldx #$60 lda #drawln sta iccom,x lda #opnino sta icaux1, x lda #$0 sta icaux2, x jmp ciov rts ; org $669 print clc sta $d4 stx $d5 ldx #0 adc #1 ;leave 0-th element sta icbal,x lda #putrec sta iccom,x lda $d5 sta icbah,x lda #0 sta icblh,x ldy #0 lda ($d4),y ;buflen from string sta icbll,x ;constant's 0-th element jsr ciov rts atachr equ $2fb drawln equ $11 opnino equ $c icaux1 equ $34a icaux2 equ $34b fname dta c 'S:' colcrs equ $55 rowcrs equ $54 putchr equ $0b icbal equ $344 icbah equ $345 iccom equ $342 icbll equ $348 icblh equ $349 color .db 1 ciov equ $e456 putrec equ $9 getrec equ $5 open equ $03 close equ $0c
Przy tego typu łączeniu kodu asm z Action! adresy procedur najbezpieczniej wziąć z listingu wygenerowanego madsem (opcja -l:ASMINC.lst).
ASMINC.ACT
proc graphics=$600(byte m) proc position=$62B(card c, byte r) proc plot=$632(card c, byte r) proc drawto=$64B(card c, byte r) proc print=$669(card msg)
Wiem że da się to zrobić lepiej ale i tak jestem z siebie dumny 🙂
Jak widać Action przekazuje parametry procedur przez akumulator i rejestry X i Y (a jeśli jest ich więcej, również przez stronę zerową). W print() adres napisu maglujemy w postaci LSB,MSB. MYLIB.ASM madsujemy i cat-ujemy MYLIB.OBX z binarką MGR.XEX.
Ciekawe jest to, że powyższy przykład w Action! po kompilacji z Runtime Action! albo uruchomieniu z cartem się wykrzacza, a działa po „zlinkowaniu” z ASMLIB.obx. Domyślam się, że chodzi o współrzędne podawane plot() i drawto(). Zapewne w przypadku procedur z carta i runtime generują one coś w stylu error 141, a procedurki w asm nie sprawdzają zakresu współrzędnych i jadą dalej poza pamięcią obrazu… Na chwilę obecną nie jestem w stanie tego lepiej wytłumaczyć. Ważne że działa.
Konwertować do bloków kodu [] mi się tego póki co nie chce, ale pewnie niebawem i to przetrenuje.
Kolejny, ważniejszy krok, to stworzenie procedur piszących bezpośrednio do pamięci ekranu danego trybu graficznego. JHusak kiedyś wspominał o szybkim plot(), jest nawet o tym wzmianka w FAQ o Action! atarionline.pl, ale od jakiegoś czasu ten link się zapętla.