This month we'll conclude our exploration of the source code of the program to load a binary file starting with the GET routine presented last month.
Lines 600–619. GET is a special routine for two reasons. First, it assumes a buffer length of zero, thus forcing a single byte transfer into the A register (Atari I/O spec). Second, if the GET fails, it pops a level off the subroutine stack and goes directly to the end-of-file code at line 4000 (BA-SIC's line 400). This is a crude but effective simulation of the TRAP 400 code in the BASIC version.
For GET to be a general-purpose subroutine, it would have to simply return the status and let the caller do the error trapping.
The Main Section
This routine begins the real work. All object code is reasonably close to its BASIC parallel.
Lines 1200–1204, 1300–1304. Remember the calling requirements for the I/O routines? Channel in X, address in A and Y. Looks easy once you have built the subroutines.
Lines 1400–1407. Same as above. The only extra here is the need to specify a mode for OPEN. Here, we use mode 4 (just as in BASIC) to indicate we will only read the file.
Lines 2400–2405. Since we just stored the A register in HIGH, we test HIGH first by comparing A with 255. If HIGH is equal to 255, then A contains 255 and we can compare it to LOW. A tiny bit sneaky. Did you ever realize that BASIC has to implement THEN this way? By branching around the following code?
Lines 2600–2701. We used LOW and HIGH to get the START address, but we have already moved their contents to START. Now, they won't be used again until we are through with QUIT, so why not share memory between QUIT, LOW, and HIGH? Again, a little bit sneaky, but not inordinately so.
We could have saved more memory (and code) by doing GETs into the low and high bytes of START directly, but I wanted to keep the code as close as reasonable to the original BASIC.
Lines 3100–3106. See the comments above about START and ADDR.
The FOR Loop
Lines 3300–3302. Remember, if a zero page location points to a desired memory location, use an offset of zero in the Y register to store, load, add, etc., to or from that location.
Lines 3403–3408. Since we are STEPping by one, we need check only for equality.
Lines 3411–3417. If the FOR loop had used a STEP, we would have had to add it on here. Since the step is implied to be one, we can use this simple two-byte increment.
Line 4103. If this routine is called from DOS or from BASIC, the RTS is all that is needed, thanks to the POP in the GET routine.
As I said, one could write this routine in better ways. The most obvious thought that comes to mind is to replace the FOR loop with a block get of the requisite bytes. Since that would produce significantly faster runtime (for large files, at least), we will make these changes next month.
To do so, though, we will also change the BASIC program to enable it to make a call to do block I/O. So, even if you are not into machine language, watch next month for a method of doing fast memory reads and writes to and from disk.