[comp.sys.atari.8bit] BASIC USR FUNC IN ACTION!

curzon@kaoa01.dec.com (Richard Curzon KAO4-3/7A DTN 621-2196) (06/29/87)

    One downer for programmers upgrading to Action! from from BASIC, is
that machine code subroutines they may have been using in BASIC can't
usually be called from Action!  That is because they pass parameters
differently.  Basic pushes parameters of the USR call onto the stack, so
that machine lang routines must pull them off as they need them.  Action
passes parameters in the 6502 registers, and in memory locations in page
0. 

    Since there are a couple of good BASIC subroutine packages I
know of, I figured out a generic way to call them from Action. 
Results were very good so I am passing them on here for Action users.

    Below are a couple of Action demos, one calling MWINDOWS, a
utility for opening successive "windows" in a graphics 0 screen; and
one calling GUP, the Graphic Utilities Package with lots of graphics
goodies.  Both can be found in most User Group libraries, if you
don't have them.  

    For use with Action, you have to ensure that the machine code
routine is in memory when you compile and run the "caller".  As with
BASIC, you could call them AUTORUN.SYS with Atari DOS.  If using
SpartaDos or DOS XL, you just invoke them before going to the Action
cartridge.

    Unlike BASIC's USR function, the CALL routine needs the number of 
parameters specified.  However, this can be hidden in DEFINE statements
as in these examples. Then the CALL from Action looks virtually
identical to the USR function in the BASIC examples in the original
magazine articles.  It might be useful to have the magazine article to
refer to.  The value (if any) returned by the Basic USR function can
be found in "CARD usrval = $D4" as shown below.

    Aside from saving you a lot of Action! programming, using these
utilities in object code form saves you from symbol name conflicts, and
saves space in your Action! symbol table. 

    I included the Mac/65 assembly listing only so software aficionados
can quickly see the simple logic.  You don't need it for anything.


;---------------- CUT HERE ------------------
;MWINDOWS DEMO IN ACTION


CARD i 
BYTE ch = 764, crsinh = 752

MODULE;MWindows setup for Call procedure

DEFINE OpenW="7459,5"
DEFINE CloseW="7826,0"
BYTE fill_char=7625

;Generic Call Procedure

CARD usrval = $D4  ; any value return by
  ; the USR function will be found here

PROC Call=*(CARD code, BYTE pnum,
   CARD p1,p2,p3,p4,p5,p6)
 [$85$E0$8A$85$E1$98$0A$AA$E8$E8$CA
  $CA$CA$30$09$B5$A2$48$E8$B5$A2$48
  $90$F2$98$48$6C$E0$00 ]
RETURN

;Using MWindows

PROC Test()
  BYTE x,y,wid,ht,border
; even though CALL defines its parameters
; as CARD, it will accept BYTE parameters
  crsinh = 1
  ch = 255
  DO
    fill_char = 128  ;display char set
    Call(OpenW,09,6,22,5,1)
    Position(11,7)
    Print("mwindows & Action!") ;all in
    ;            atari inverse graphics
    Position(11,9)
    Print(" ...hit any key.. ") ;inverse
    Position(0,0)
    DO UNTIL ch # 255 OD ch=255
    FOR I = 1 TO 4 DO
      x = Rand(36)  y = Rand(20)
      wid = Rand(37-x)+3
      ht = Rand(21-y)+3
      border = Rand(3)*100
      fill_char = 144+i
      Call (OpenW,x,y,wid,ht,border)
      DO UNTIL ch # 255 OD ch=255
    OD 
    FOR I = 1 TO 4 DO
      Call (CloseW)
      DO UNTIL ch # 255 OD ch=255
    OD
    Call(CloseW)
    DO UNTIL ch # 255 OD ch=255
  OD
RETURN

;--------------- CUT HERE ------------------

;GRAPHICS UTILITIES PACKAGE DEMO IN ACTION

CARD i 
BYTE ch = 764

CARD usrval = $D4  ; any value return by
  ; the USR function will be found here

PROC Call=*(CARD code, BYTE pnum,
   CARD p1,p2,p3,p4,p5,p6)
 [$85$E0$8A$85$E1$98$0A$AA$E8$E8$CA
  $CA$CA$30$09$B5$A2$48$E8$B5$A2$48
  $90$F2$98$48$6C$E0$00 ]
RETURN

MODULE ;setup for GUP routine Calls

DEFINE Graphics="17467,1"
DEFINE Circle="17182,3"
DEFINE Text="17962,4"
DEFINE C128="17736,2"  ;scroll reg
DEFINE PSet="18216,4"
DEFINE Random="18231,0"
DEFINE Box="16679,4"
DEFINE DrawTo="16752,2";up to 6 parms
DEFINE Line="16780,4"  ;up to 6 parms
DEFINE Plot="18204,2"
BYTE CIRF=17432      ;circle fill flg
BYTE ARRAY Color(4)=16526
BYTE ARRAY SetColor(9)=18272
BYTE lowscr=208 ;allow use of low
                ;screen in gr 8
                ;set to 8 default 0

PROC Test()
  CIRF = 1
  Call(Graphics,15+16)
  Call(PSet,$55,$55,$FF,$FF)
  Call(Circle,080,080,50)
  Call(PSet,$A0,$A0,$F5,$F5)
  Call(Circle,055,055,50)
  Call(PSet,$55,$55,$AA,$AA)
  CIRF = 0
  Call(Circle,120,120,50)
  Call(Text,05,05,"DIGITAL HAS"+1,11)
; string needs +1 offset because
;  of Action string handling
  Call(Text,05,14,"IT NOW!"+1,07)
  Call(C128,200,6)
  Call(C128,200,4)
  Call(Graphics,08+48)
  Call(C128,200,2)  
  Call(Text,05,05,"DIGITAL HAS"+1,11)
  Call(Text,05,14,"IT NOW!"+1,07)
  Call(C128,200,2)
; just for starters!

RETURN

;--------------- CUT HERE ---------------

 CALL ROUTINE source code ... short and sweet

PAGE 1    
 

                1000 ;CALL -- 
                1005 ;ACTION INTERFACE TO MACHINE CODE
                1010 ;SUBROUTINES THAT HAVE BEEN
                1020 ;DESIGNED TO BE CALLED FROM BASIC
                1030 ;
    =00E0       1040 FR1 =   $E0
                1050 ;
                1060 ;*******
                1070 ;LETS GO
                1080 ;*******
0000 85E0       1090     STA FR1     ;ML LO
0002 8A         1100     TXA 
0003 85E1       1110     STA FR1+1   ;ML HI
0005 98         1120     TYA         ;NUM OF PARMS
0006 0A         1130     ASL A       ;2 BYTES/PARM
0007 AA         1140     TAX         ;OFFSET REG
0008 E8         1150     INX         ;READY FOR LOOP
0009 E8         1155     INX 
000A            1160 PUMP.PARMS
000A CA         1170     DEX 
000B CA         1175     DEX 
000C CA         1180     DEX 
000D 3009       1190     BMI NUM.PARMS
000F B5A2       1200     LDA $A2,X   ;GET LO
0011 48         1210     PHA 
0012 E8         1220     INX         ;NOW HI 
0013 B5A2       1230     LDA $A2,X   ;GET HI
0015 48         1240     PHA 
0016 90F2       1250     BCC PUMP.PARMS
0018            1260 NUM.PARMS
0018 98         1270     TYA         ;NUM OF PARMS
0019 48         1280     PHA 
001A 6CE000     1290     JMP (FR1)   ;GO TO SUBR.

curzon@kaoa01.dec.com (Richard Curzon KAO4-3/7A DTN 621-2196) (07/06/87)

    I tried submitting this before, but it never got through.... as far
as I know!  If this is the second time you've seen this, somebody please
send me mail to stop the flood ;-)
----------------------------------------------------------------------- 

    One downer for programmers upgrading to Action! from from BASIC, is
that machine code subroutines they may have been using in BASIC can't
usually be called from Action!  That is because they pass parameters
differently.  Basic pushes parameters of the USR call onto the stack, so
that machine lang routines must pull them off as they need them.  Action
passes parameters in the 6502 registers, and in memory locations in page
0. 

    Since there are a couple of good BASIC subroutine packages I
know of, I figured out a generic way to call them from Action. 
Results were very good so I am passing them on here for Action users.

    Below are a couple of Action demos, one calling MWINDOWS, a
utility for opening successive "windows" in a graphics 0 screen; and
one calling GUP, the Graphic Utilities Package with lots of graphics
goodies.  Both can be found in most User Group libraries, if you
don't have them.  

    For use with Action, you have to ensure that the machine code
routine is in memory when you compile and run the "caller".  As with
BASIC, you could call them AUTORUN.SYS with Atari DOS.  If using
SpartaDos or DOS XL, you just invoke them before going to the Action
cartridge.

    Unlike BASIC's USR function, the CALL routine needs the number of 
parameters specified.  However, this can be hidden in DEFINE statements
as in these examples. Then the CALL from Action looks virtually
identical to the USR function in the BASIC examples in the original
magazine articles.  It might be useful to have the magazine article to
refer to.  The value (if any) returned by the Basic USR function can
be found in "CARD usrval = $D4" as shown below.

    Aside from saving you a lot of Action! programming, using these
utilities in object code form saves you from symbol name conflicts, and
saves space in your Action! symbol table. 

    I included the Mac/65 assembly listing only so software aficionados
can quickly see the simple logic.  You don't need it for anything.


;---------------- CUT HERE ------------------
;MWINDOWS DEMO IN ACTION


CARD i 
BYTE ch = 764, crsinh = 752

MODULE;MWindows setup for Call procedure

DEFINE OpenW="7459,5"
DEFINE CloseW="7826,0"
BYTE fill_char=7625

;Generic Call Procedure

CARD usrval = $D4  ; any value return by
  ; the USR function will be found here

PROC Call=*(CARD code, BYTE pnum,
   CARD p1,p2,p3,p4,p5,p6)
 [$85$E0$8A$85$E1$98$0A$AA$E8$E8$CA
  $CA$CA$30$09$B5$A2$48$E8$B5$A2$48
  $90$F2$98$48$6C$E0$00 ]
RETURN

;Using MWindows

PROC Test()
  BYTE x,y,wid,ht,border
; even though CALL defines its parameters
; as CARD, it will accept BYTE parameters
  crsinh = 1
  ch = 255
  DO
    fill_char = 128  ;display char set
    Call(OpenW,09,6,22,5,1)
    Position(11,7)
    Print("mwindows & Action!") ;all in
    ;            atari inverse graphics
    Position(11,9)
    Print(" ...hit any key.. ") ;inverse
    Position(0,0)
    DO UNTIL ch # 255 OD ch=255
    FOR I = 1 TO 4 DO
      x = Rand(36)  y = Rand(20)
      wid = Rand(37-x)+3
      ht = Rand(21-y)+3
      border = Rand(3)*100
      fill_char = 144+i
      Call (OpenW,x,y,wid,ht,border)
      DO UNTIL ch # 255 OD ch=255
    OD 
    FOR I = 1 TO 4 DO
      Call (CloseW)
      DO UNTIL ch # 255 OD ch=255
    OD
    Call(CloseW)
    DO UNTIL ch # 255 OD ch=255
  OD
RETURN

;--------------- CUT HERE ------------------

;GRAPHICS UTILITIES PACKAGE DEMO IN ACTION

CARD i 
BYTE ch = 764

CARD usrval = $D4  ; any value return by
  ; the USR function will be found here

PROC Call=*(CARD code, BYTE pnum,
   CARD p1,p2,p3,p4,p5,p6)
 [$85$E0$8A$85$E1$98$0A$AA$E8$E8$CA
  $CA$CA$30$09$B5$A2$48$E8$B5$A2$48
  $90$F2$98$48$6C$E0$00 ]
RETURN

MODULE ;setup for GUP routine Calls

DEFINE Graphics="17467,1"
DEFINE Circle="17182,3"
DEFINE Text="17962,4"
DEFINE C128="17736,2"  ;scroll reg
DEFINE PSet="18216,4"
DEFINE Random="18231,0"
DEFINE Box="16679,4"
DEFINE DrawTo="16752,2";up to 6 parms
DEFINE Line="16780,4"  ;up to 6 parms
DEFINE Plot="18204,2"
BYTE CIRF=17432      ;circle fill flg
BYTE ARRAY Color(4)=16526
BYTE ARRAY SetColor(9)=18272
BYTE lowscr=208 ;allow use of low
                ;screen in gr 8
                ;set to 8 default 0

PROC Test()
  CIRF = 1
  Call(Graphics,15+16)
  Call(PSet,$55,$55,$FF,$FF)
  Call(Circle,080,080,50)
  Call(PSet,$A0,$A0,$F5,$F5)
  Call(Circle,055,055,50)
  Call(PSet,$55,$55,$AA,$AA)
  CIRF = 0
  Call(Circle,120,120,50)
  Call(Text,05,05,"DIGITAL HAS"+1,11)
; string needs +1 offset because
;  of Action string handling
  Call(Text,05,14,"IT NOW!"+1,07)
  Call(C128,200,6)
  Call(C128,200,4)
  Call(Graphics,08+48)
  Call(C128,200,2)  
  Call(Text,05,05,"DIGITAL HAS"+1,11)
  Call(Text,05,14,"IT NOW!"+1,07)
  Call(C128,200,2)
; just for starters!

RETURN

;--------------- CUT HERE ---------------

 CALL ROUTINE source code ... short and sweet
 

                1000 ;CALL -- 
                1005 ;ACTION INTERFACE TO MACHINE CODE
                1010 ;SUBROUTINES THAT HAVE BEEN
                1020 ;DESIGNED TO BE CALLED FROM BASIC
                1030 ;
    =00E0       1040 FR1 =   $E0
                1050 ;
                1060 ;*******
                1070 ;LETS GO
                1080 ;*******
0000 85E0       1090     STA FR1     ;ML LO
0002 8A         1100     TXA 
0003 85E1       1110     STA FR1+1   ;ML HI
0005 98         1120     TYA         ;NUM OF PARMS
0006 0A         1130     ASL A       ;2 BYTES/PARM
0007 AA         1140     TAX         ;OFFSET REG
0008 E8         1150     INX         ;READY FOR LOOP
0009 E8         1155     INX 
000A            1160 PUMP.PARMS
000A CA         1170     DEX 
000B CA         1175     DEX 
000C CA         1180     DEX 
000D 3009       1190     BMI NUM.PARMS
000F B5A2       1200     LDA $A2,X   ;GET LO
0011 48         1210     PHA 
0012 E8         1220     INX         ;NOW HI 
0013 B5A2       1230     LDA $A2,X   ;GET HI
0015 48         1240     PHA 
0016 90F2       1250     BCC PUMP.PARMS
0018            1260 NUM.PARMS
0018 98         1270     TYA         ;NUM OF PARMS
0019 48         1280     PHA 
001A 6CE000     1290     JMP (FR1)   ;GO TO SUBR.
                1300 ;*****
                1310 ;NO MO
                1320 ;*****


				Dick Curzon
				Digital Equipment of Canada
                                PO Box 13000
                                Kanata Ontario      K2K 2A6
                                Canada.

(DEC E-NET)	KAOA01::CURZON
(UUCP)		{decvax, ucbvax, allegra}!decwrl!kaoa01.dec.com!curzon
(ARPA)		curzon%kaoa01.DEC@decwrl.ARPA