Classic Computer Magazine Archive COMPUTE! ISSUE 37 / JUNE 1983 / PAGE 219

Automatic
Atari DATA Statements
Richard Dorfner

Use these handy routines to merge machine language programs with BASIC. Never again will you need to manually convert machine language to DATA statements. Your Atari, using the auto-return mode, will do it for you.

Writing programs in BASIC is fine if you don't need great speed. But if you must have a subroutine-that operates very quickly, then BASIC is not the answer. One solution is to whip out your assembler and write a machine language subroutine to get the job done. If you want to incorporate it into BASIC, you then need to transform all of these hexadecimal digits into a more useful form, namely DATA statements made up of decimal digits. This can be tedious. After once staying up into the wee hours of the morning, I decided there had to be a better way. Fortunately, there is.

Storage Technique
Before getting to the solution, we should first look at the storage technique used by the Editor Assembler cartridge. When the ASM saves the object code onto the disk, it first writes six bytes onto the beginning of the file. The first two are simply used to delimit the beginning of the header. The next two bytes determine the starting address. The last two bytes determine the ending address.
    The difference between these two numbers represents the number of bytes to be POKEd into place - which presents a problem. What if there are several "chunks" of machine code to be POKEd into place? ASM handles this by writing another set of starting and ending addresses. This takes up four bytes. With this information, we can now begin the construction of a program which writes DATA statements using the object code file.
    Actually, the program to create the DATA statements is rather simple. It fills an array with ten numbers at a time, getting the numbers directly from the object code file. The fun part is when it turns this information into a DATA statment.
    To do this, we format a line of code on the screen in a manner that will be accepted by the BASIC interpreter. The next step is to write CONT on a line below the DATA statement.
    Why? Well, for one thing, we're going to stop the program and send all the information that we wrote on the screen under program control to the BASIC interpreter, so we must somehow start it up again.
    To accomplish this minor miracle, we first, under program control, position the cursor above the items on the screen and then type POKE 842,13:STOP. What happens next is that the operating system begins to send what's on the screen to the BASIC interpreter automatically. As soon as the line with DATA on it is reached, the BASIC interpreter takes it in and shoves it into its proper place in the listing. The next thing to be sent to the interpreter is the CONTinue statement. When BASIC sees this, it executes the command because there is no line number in front of it. It's an immediate mode command.
    After the CONTinue statement is hit, the program starts executing on the next line of the BASIC program from where it stopped. In Program 1, this is line 280, which shuts off the automatic input feature.
    This program will continue running until it runs out of data in the object code file. When this happens, the program dumps out all of the numbers held by DAT(1-10). This is done to avoid losing data, which might occur due to an End Of File error.
    After all of the data has been READ in and LISTed to either the disk or cassette, the computer very kindly announces the file name under which the DATA statements were listed. This name will always be "D or C:DATASTAT.LST". It also includes an initial DATA statement which tells POKEIT how many bytes are to be POKEd into place.

POKEIT
Program 2, POKEIT, must be loaded from wherever you have it saved. To use it, you also have to ENTER"Device.DATASTAT.LST" which was saved by the other program. After you type RUN, POKEIT begins to read the first item of information. This number that it gets is the number of bytes to be POKEd into place altogether.
    It then reads the next six bytes. The first two of these are thrown away. The third and fourth bytes are used to calculate the starting memory location to POKE to. The fifth and sixth bytes are used to calculate the ending address to be POKEd.
    The program starts to read and POKE until it runs out of memory locations to POKE to. And then compares the number of bytes it has POKEd to the total number of bytes it is required to POKE. If it has not yet completed its job, it's because there is another "chunk" of code to be placed in a starting and stopping set of addresses and cycles through the program once more. It will continue to do this until it has run out of data, at which point it will automatically jump to the machine language subroutine.

Program Description
Here's a play-by-play report on what Programs 1 and 2 are doing.

Program 1.
Line no.
60
Gets the device and the file name that it will be working with.
70
Opens that file.
80-100
Initialize the array DAT to 0.
110-150
Are a WHILE loop which gets values for X and puts them in the array DAT(I).
170
Clears the screen.
180
Increments the line counter which will be used to give the DATA statement a line number.
190-250
Format the screen to look like a line of BASIC.
260
Positions the cursor above what was just written on the screen.
270
Turns on the automatic line-entering feature and stops the program so that it can take effect.
280
Turns it off. This is the line which BASIC will return to once it gets the CONTinue statement.
290
Checks to see if the trap flag was set. The only way it can get set is if the machine gets an End Of File error. If TR has been set, then it goes to line 325; otherwise, it goes to line 80.
310
Sets TR to 1 whenever it is reached.
325-370
Put the number of bytes read from the file into the first DATA statement and automatically enters it into the basic program.
380
Changes the file name to DATASTAT.LST.
390
LISTs the DATA statements to the device named in FILE$.
400
Tells the user by what file name the DATA statements were saved.

Program 2.
Line no.

80
Gets the number of bytes to be read and the first two useless bytes saved from the file.
100-120
Calculate the starting and ending address which will be POKEd to.
140-170
Do the actual POKEing of the information held by the DATA statements.
180
 Tests if all the information has been read. If it hasn't, then it goes back to line 100 and starts the process all over again.
190
Forces the machine to take the machine language plunge.
300-320
Get the starting address of the machine language subroutine for when the machine decides to go there.

Program 1: DATA Statements From Machine Code
10 REM DATA STATEMENTS FROM MACHINE
   CODE FILES
40 DIM DAT(10),FILE$(14)
50 POKE 710,0:POKE 709,14:REM make m
   y B$W T.V. look: nice
60 ? CHR$(125):? :? "INPUT DEVICE:Fl
   LENAME ";:INPUT FILE$:J=():LINE=10
   000
70 OPEN #6,12,0,FILE$
80 FOR I=1 TO 10
90 DAT(I)=0:REM Initialize DAT to 0
100 NEXT I
110 I=0
120 I=I+1:J=J+1:TRAP 310:REM Begin t
    he while loop
130 GET #6,X:REM Get a byte
140 DAT(I)=X:REM Put it in DAT(I)
150 IF I=10 THEN GOTO 170:REM Done t
    en yet? If so GOTO 170
160 GOTO 120:REM Otherwise go get th
    e next byte
170 ? CHR$(125):REM Clear the screen
180 LINE=LINE+10:REM Increment the l
    ine counter
190 POSITION 2,4
200 ? LINE;"DATA";:REM Print the lin
    e number and then DATA
210 FOR 1=1 TO 9
220 ? DAT(I);",";:REM Follow DATA wi
    th the various data items separa
    ted with commas
230 NEXT I
240 ? DAT(10):REM Finish the DATA st
    atement with a data item but don
    't put in a comma
250 ? :? "CONT":REM Skip a few lines
     then print CONT
260 POSITION 2,0:REM Position the cu
    rsor above it all
270 POKE 842,13:STOP :REM Then turn
    on the auto-entry feature and st
    op the program
280 POKE 842,12:REM When it has ente
    red the data statement, come bac
    k here and turn the feature off
290 IF TR=1 THEN GOTO 325:REM If the
     trap has occured, goto 325
300 GOTO SO:REM Otherwise goto 80
310 TR=I:REM Set the trap flag to 1
320 GOTO 170
325 CLOSE #6:REM close the file sinc
    e we're all done with it
330 ? CHR$(125):REM then clear the s
    creen
340 POSITION 2.4
350 ? 10005;"DATA";J-1:? :? :? "CONT
    ":REM Print a data statement tel
    ling how many bytes were read
360 POSITION 2,0:POKE 842,13:STOP :R
    EM Now enter it as a line of BAS
    IC
370 POKE 842,12:REM and turn the aut
    o-entry feature off
380 FILE$(3,14)="DATASTAT.LST":REM c
    hange the filename to DATASTA.LS
    T
390 LIST FILE$,10005,LINE:REM Then 1
    ist it to the device under the n
    ame of DATASTAT.LST
400 PRINT "FILE LISTED UNDER":PRINT
    FILE$:REM and let the user know
    what to call it

Program 2: POKEIT
10 REM POKE IT IN PLACE
40 DIM FILE$(15)
50 POKE 709,14:POKE 710,0:REM MAKES
   MY B&W T.V. LOOK NICE
80 READ NUMBEROFBYTES,JUNKI,JUNK2
90 TRAP 190
100 READ STARTLO,STARTHI,LASTLO.LAST
    HI
110 START=STARTLO+256*STARTHI:REM CA
    LCULATE THE STARTING ADDRESS
120 LAST=LASTLO+256*LASTHI:REM CALCU
    LATE THE LAST ADDRESS
130 GOSUB 300:REM IS THIS THE FIRST
    ADDRESS TO BE CALCULATED?
140 FOR I=START TO LAST
150 READ X
160 POKE I,X
170 NEXT I
180 IF (LAST-START)<>NUMBEROFBYTES T
    HEN GOTO 100:REM GOT ALL OF THE
    DATA YET? IF NOT GO GET THE NEXT
     "CHUNK"
190 X=USR(BEGINNING)
200 END
300 IF FLAG<>l THEN BEGINNING=START:
    REM HAVE WE FOUND A BEGINNING AD
    DRESS ALREADY? IF NOT THIS IS IT
310 FLAG=I:REM SET FLAG TO 1 TO INDI
    CATE WE HAVE ALREADY SET THE ENT
    RY POINT OF THE MACHINE CODE SUB
    ROUTINE
320 RETURN