      MODULE  gratc
      IMPORTC open='IO'.'XFindOutput'
      IMPORTC close='IO'.'XCloseStream'
      IMPORTC write='IO'.'XSBlockWrite'
      EXPORTC cgrat,clg,cls,colour,draw,gcol,graorg,grawin,line,mode
      EXPORTC move,plot,rectan,tabs,trian,txtwin,vdu,vdu19,vdu23
      AREADEF DATA,[],DOUBLE
      AREADEF PROG,[PIC,READ,SHARED,CODE],DOUBLE
      DEFSB   DATA
      AREA    DATA
unit  DCD     -1
buf   ALLOCB  20
;
      AREA    PROG
cgrat;                  close graphics file
      MOVD    unit,R0
      CMPQD   -1,R0
      BEQ     cl1          ; not open
      MOVD    R0,TOS
      CXP     close        ; close file
      MOVQD   -1,unit      ; flag unit as closed
cl1   RXP     0            ; return
;
clg;                    clear graphics screen
      MOVB    =16,buf      ;VDU16
      BR      cs1
;
cls;                    clear text screen
      MOVB    =12,buf      ; VDU12
cs1   MOVQD   1,R0
      BR      wrt
;
colour;(col)            set text colour to col
      MOVB    =17,buf      ; VDU17,
      MOVQD   2,R0
      BR      me1
;
draw;(x,y)  draw line to (x,y)
      MOVQD   5,R7         ;directive 5
      BR      tn1
;
gcol;(a,b)                 ; set graphics colours
      MOVB    =18,buf      ; VDU18,
      MOVQD   3,R0
      BR      me1
;
graorg;(x,y)         set up graphics origin
      MOVB    =29,buf      ; VDU29,
      MOVW    8(SP),buf+1  ; x;
      MOVW    12(SP),buf+3 ; y;
      MOVQD   5,R0
      BR      wrt
;
grawin;(x1,y1,x2,y2)         set up graphics window
      MOVB    =24,buf      ; VDU24,
      MOVW    8(SP),buf+1  ; x1;
      MOVW    12(SP),buf+3 ; y1;
      MOVW    16(SP),buf+5 ; x2;
      MOVW    20(SP),buf+7 ; y2;
      ADDR    @9,R0
      BR      wrt
;
line;(x1,y1, x2,y2) draw line from (x1,y1) to (x2,y2)
      ADDR    @#X504,R7    ;directives 4,5
tn1   ADDR    8(SP),R1
tn2   MOVQD   0,R0
ltn   MOVB    =25,buf[R0:B]    ;VDU25,
      MOVB    R7,buf+1[R0:B]   ; n,
      MOVW    0(R1),buf+2[R0:B]; x;
      MOVW    4(R1),buf+4[R0:B]; y;
      ADDR    8(R1),R1     ;next pair of I/P words
      ADDQD   6,R0         ;count in O/P buffer
      LSHD    =-8,R7       ;next byte of directive
      CMPQD   0,R7
      BNE     ltn
;
wrt   ADDR    buf,TOS      ; write out R0 bytes from buf
      MOVD    R0,TOS
      CMPQW   -1,unit+2
      BEQ     ograt        ; file not open
wr2   MOVD    unit,TOS
      CXP     write
      RXP     0            ; return
;
ograt MOVZBD  name,TOS     ; length of file name
      ADDR    name+1,TOS   ; address of file name
      CXP     open
      MOVD    R0,unit      ; store unit number
      BR      wr2
name  DCS     "rawvdu:"
;
mode;(n)                set graphics mode
      MOVB    =22,buf      ; VDU22,
      MOVQD   2,R0
me1   ADDR    -1(R0),R1    ;count to insert
ml    MOVB    4(SP)[R1:D],buf[R1:B]
      ACBD    -1,R1,ml
      BR      wrt
;
move;(x,y)  move graphics cursor to (x,y)
      MOVQD   4,R7          ;directive 4
      BR      tn1
;
plot;(n,x,y) plotn,x,y   (BBC BASIC)
      MOVZBD  8(SP),R7     ;directive
      ADDR    12(SP),R1    ;start with second argument
      BR      tn2
;
rectan;(x1,y1, x2,y2) filled rectangle; opposite corners (x1,y1) & (x2,y2)
      MOVD    =#X6504,R7   ;directives 4,101 
      BR      tn1
;
tabs;(x,y)                   tab to x,y
      MOVB    =31,buf      ; VDU31,
      MOVQD   3,R0
      BR      me1
;
trian;(x1,y1, x2,y2, x3,y3) make filled triangle
      MOVD    =#X550404,R7 ;directives 4,4,85
      BR      tn1
;
txtwin;(xleft,ybottom,xright,ytop)  set up text window
      MOVB    =28,buf      ; VDU28,
      MOVQD   5,R0
      BR      me1
;
vdu;(n)  just one character
      MOVQD   1,R0
      MOVB    8(SP),buf
      BR      wrt
;
vdu19;(logical,physical)    set up colour palette
      MOVB    =19,buf      ; VDU19,
      MOVB    8(SP),buf+1  ; logical,
      MOVW    12(SP),buf+2 ; physical;
      MOVQW   0,buf+4      ; 0;
      MOVQD   6,R0
      BR      wrt
vdu23;(n1,n2...n9)   BASIC VDU23
      MOVB    =23,buf      ;VDU23,
      ADDR    @10,R0
      BR      me1
      END