;                     _
;  ?__. .__ __ ____ _(_) __?
;  /  |/  / @ `/ $ `/ / __/
; /_/|_/_/\_,_/\_, /_/\__/
;             /___/

;    Magic-ARM Compiler

; erase screen with color/a1...

function clear.screen
 alias vga=a3, w=a2, c=a1
 . vga=VRAM, w=SCREEN.N
 .repeat w
   . (u16) *vga++=c
 .endr
endf

; address &vga[(y*(screen.w*2))+(x*2)]...

function vga.xy
 . a3=SCREEN.PITCH, a4=a2*a3
 . a4=a4+(a1<<1), a2=VRAM, a1=a2+a4
endf

; draw pixel: a1-a3=x/y/c...

function draw.pixel
 alias vga=a1, c=v1
 . c=a3
 vga.xy
 . (u16) *vga=c
endf

; draw horizontal line: a1-a4=x/y/w/c...

function draw.line.h
 alias vga=a1, c=v1, w=v2
 . c=a4, w=a3
 vga.xy
 .repeat w
   . (u16) *vga++=c
 .endr
endf       

; text.n(t) - get text length, # characters

function text.n
 alias t=a1, b=a2, c=v1
 . c=1, b=t
 .while c           ; until 0
   . (u8) c=*t++    ; read c
 .endw
 . t--, t-b         ; return current-start
endf

; text.copy(a, b) - standard copy with 0 after

function text.copy
 alias a=a1, b=a2, c=v1
 . c=1
 .while c
   . (u8) c=*b++    ; read
   . (u8) *a++=c    ; copy
 .endw
 . a--              ; return end
endf

; text.attach(a, b) - attach b to a

function text.attach
 alias a=a1,\
  b=a2, p=v1
 . p=b
 text.end
 . b=p
 text.copy
endf

; text.attach.c(t, c) - attach c to t

function text.attach.c
 alias t=a1, c=v2
 . c=a2
 text.end
 . (u8) *t++=c, (u8) *t=0
endf

; text.find(t, c) - search for character.
; return address or 0

function text.find
 alias t=a1,\
  c=v1, key=a2
 .forever           ; loop
   . (u8) c=*t      ; read c
   .if c=0          ; end?
     return 0       ; not found
   .end
   .if c=key        ; found?
     return t       ; t=address
   .end
   . t++            ; next
 .endfv
endf

; text.compare(a, b) - lexical comparison.
; return <0>

function text.compare
 alias a=a1, b=a2,\
  c=v1, d=v2
  . c=1, d=c
 .while c=d         ; while equal
   . (u8) c=*a++
   . (u8) d=*b++
   . c|d            ; and both nonzero
   .breakz          ; break if either=0
 .endw
 . a=c-d            ; return *a-*b
endf

; text.upper(t) - convert to uppercase

function text.upper
 alias t=a1, c=v1
 .forever
   . (u8) c=*t      ; get c
   .if c=0          ; end?
     return t
   .end
   .if c>=97        ; lowercase?
     .if c<=122
       . c-32
       . (u8) *t=c  ; copy c
     .end
   .end
   . t++            ; next c
 .endfv
endf

; convert unsigned 32BIT integer to text

 .while n           ; until 0
   . y=n            ; dividend
   . x=1999999Ah    ; ((2^32)/10)+1
   . n=n-(n>>>30)   ; n=n-(n>>>30)
   umull c, n, n, x ; divide: n*reciprocal
   . x=n<<1         ; multiply by 10
   . x=x+(x<<2)
   . x=y-x          ; remainder
   . c=x+30h        ; c=(n%10)+'0'
   . (u8) *t++=c    ; *t++=c
 .endw

; convert 32BIT binary number to text

 .while n            ; *t++=(n&1)+'0'
   . x=n&1, x+30h
   . (u8) *t++=x
   . n>>>1           ; n/2
 .endw
 . (u8) *t=0, a1=s

; convert bgr15 to rgb15

function convert.bgr15.rgb24
 alias r=a1, g=a2, b=a3, c=a4
 . c=a1, r=c&11111b, r<<3
 . g=c>>5, g&11111b, g<<3
 . b=c>>10, b&11111b, b<<3
 . c=r<<16, r=c|(g<<8), r|b
endf   

; return r/g/b in a1-a3 from bgr15

function get.rgb15
 alias r=a1, g=a2, b=a3, c=a4
 . c=a1, r=c&11111b, g=c>>5, g&11111b
 . b=c>>10, b&11111b
endf

; draw solid rectangle: a1-v1=x/y/w/h/c...

function draw.box
 alias vga=a1, c=v1,\
  sw=v2, w=v3, h=v4,\
  pitch=a2, wb=a3
 . w=a3, sw=w, h=a4    ; save w/h
 vga.xy
 . pitch=SCREEN.PITCH  ; screen+row
 . wb=w<<1             ; w in bytes
 .repeat h             ; h # times
   . w=sw              ; reset saved
   .repeat w           ; w # times
     . (u16) *vga++=c  ; copy color
   .endr
   . vga+pitch, vga-wb ; advance
 .endr
endf

; draw 15/16BPP bitmap. a1-a4=x/y/w/h.
; v1=pixels...   

 . pitch=SCREEN.PITCH   ; screen+image
 . iwb=w<<1             ; w in bytes
 vga.xy                 ; &vga(x,y)
 .repeat h              ; h # times
   . w=sw               ; get saved w
   .repeat w            ; w # times
     . (u16) \
      *vga++=*image++   ; copy pixel
   .endr
   . vga+pitch, vga-iwb ; advance
 .endr   

; draw 15/16BPP bitmap with transparency
; by upper left pixel color (0x0).
; a1-a4=x/y/w/h. v1=pixels...  

 . pitch=SCREEN.PITCH   ; screen+image
 . iwb=w<<1             ; w in bytes
 . (u16) key=*image     ; transparent color
 vga.xy                 ; &vga(x,y)
 .repeat h              ; h # times
   . w=sw
   .repeat w            ; w # times
     . (u16) c=*image++
     .if c<>key         ; opaque?
       . (u16) *vga++=c ; copy pixel
     .else
       . vga+2          ; next
     .end
   .endr
   . vga+pitch, vga-iwb ; advance
 .endr

; draw 15/16BPP scanline. a1-a3/v1=x/y/w/pixels...

function draw.scanline
 alias vga=a1,\        ; aliases
  p=v1, w=v2
 . w=a3, p=v1          ; save w/p
 vga.xy                ; &vga(x,y)
 .repeat w             ; w # times
   . (u16) *vga++=*p++ ; copy pixel
 .endr
endf

; draw bitmap text (FONT.INC)...

function draw.text
 alias t=v1,\             ; aliases
  x=v2, y=v3,\
  c=v5, fw=v6, ix=v7
 . t=a1, x=a2, y=a3       ; save these
 . ix=x
 . fw=FW                  ; font w
 . (u8) c=*t
 .while c                 ; while nonzero
   . (u8) c=*t++          ; get next c
   .if c=0Dh              ; return?
     . t++                ; skip 0Ah after
     . x=ix, x-fw, y+FH   ; reset x/y
   .end
   draw.c c, x, y         ; draw character
   . x+fw                 ; x+font.w
 .endw
endf