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