This time I’m exploring inline Assembly language within Action!. This is more or less the equivalent to Atari BASIC USR routines. It turns out to be pretty easy to do.
In this example I use inline Assembly to execute the following code:
JSR $000A
This breaks down into 3 bytes of code. The instruction JSR is $6C. The address breaks down into two bytes (LSB first) $0A and $00. To add the instructions as inline Assembly, they get wrapped in square brackets with each byte separated by a space like this:
[ $6C $0A $00 ]
This code simply does a jump to the DOS entry point vector (DOSVEC). The code is useful with compiled Action! programs running from SpartaDOS. A normal return results in a system hang so the special exit is required to return to DOS.
The sample program I created tests to see if SpartaDOS is loaded. It will report if SpartaDOS is present. If it is, the program will use the special exit routine through DOSVEC jump, other wise it will exit normally.
Source Code
INCLUDE "D4:SYS.ACT" MODULE ; Proc..: IsSparta() ; Return: bRet: 1=yes, 0=no BYTE FUNC IsSparta() BYTE bRet=[0],bPk=[0] ; Get value from loc 3889 bPk=Peek(3889) ; Sparta if 0,15,68,89 if bPk=0 OR bPk=15 OR bPk=68 OR bPk=89 then bRet=1 fi RETURN(bRet) ; Proc..: SDExit() ; Desc..: Exits to DOSVEC ($000A) via ; JSR using inline assembly PROC SDExit() [ $6C $0A $00 ] PROC Main() BYTE bSparta=[0] ; Setup screen Put($7D) PrintE("Checking for SpartaDOS.") ; Is it Sparta or not bSparta=IsSparta() Print("DOS : ") ; If Sparta if bSparta=1 then ; Say so PrintE("SpartaDOS") ; Exit via DOSVEC SDExit() ; Else, say so, normal exit else PrintE("Other") fi RETURN
Breakdown
This section brings in the Action! Runtime library so the compilation will build a stand-alone executable that does not require the Action! cartridge:
INCLUDE "D4:SYS.ACT" MODULE
This is a function which checks memory location 3889 for value 0, 15 ,68, or 89. Any of these values indicate SpartaDOS is loaded. The function returns a BYTE value of 1 if SpartaDOS is detected, and 0 if it is not.
; Func..: IsSparta() ; Return: bRet: 1=yes, 0=no BYTE FUNC IsSparta() BYTE bRet=[0],bPk=[0] ; Get value from loc 3889 bPk=Peek(3889) ; Sparta if 0,15,68,89 if bPk=0 OR bPk=15 OR bPk=68 OR bPk=89 then bRet=1 fi RETURN(bRet)
This procedure is the custom exit routine to be used if SpartaDOS is loaded. It uses inline Assembly to execute a JSR to the DOSVEC address.
; Proc..: SDExit() ; Desc..: Exits to DOSVEC ($000A) via ; JSR using inline assembly PROC SDExit() [ $6C $0A $00 ]
This is the main routine. In this section a BYTE is declared to hold a flag for the SpartDOS detection. It also clears the screen and displays the message “Checking for SpartaDOS.”:
PROC Main() BYTE bSparta=[0] ; Setup screen Put($7D) PrintE("Checking for SpartaDOS.")
This calls the function IsSparta to test if SpartaDOS is loaded and stores the result flag in bSparta. Then it prints “DOS : ” without an EOL:
; Is it Sparta or not bSparta=IsSparta() Print("DOS : ")
This section tests the Sparta flag bSparta. If it is 1, it prints “SpartaDOS” then calls the procedure SDExit to exit via the JSR to DOSVEC. If it is not 1, it prints “Other” then exits normally (RTS instruction):
; If Sparta if bSparta=1 then ; Say so PrintE("SpartaDOS") ; Exit via DOSVEC SDExit() ; Else, say so, normal exit else PrintE("Other") fi RETURN
Results
In the first example, the program is about to be run from the SpartaDOS command prompt:
As you can see, control is returned to SpartaDOS at conclusion:
In this second example, the program is about to be run from Atari DOS 2.0s:
As you can see, it ran correctly. I captured the screen as the DUP.SYS (the DOS menu) was being reloaded since the menu would wipe out the display: