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