Chapter 8
Pseudo:

I/O and Linked Files


All pseudo-ops except .BYTE (and in-line ones like #< or +) are handled by the Pseudo subprogram. Eight pseudo-ops are tested for at the start of Pseudo (50-300). They are: .FILE, .END, .D, .P, .N, .O, .S, and .H. These tests and the associated JMPs are identical to an ON-GOTO multiple branch structure in a BASIC program. The rest of the Pseudo subprogram is a collection of subroutines which service these various pseudo-ops.
     If an unrecognized pseudo-op appears within the source code, an error message is printed out (340-460). If something like .X or .MAP appears, the line number, the start address, and the source code line are printed (350-390). The variable TEMP is set to point to the SYNTAX ERROR message in the Tables subprogram, and that message is sent to screen, and possibly printer, via the PRNTMESS subroutine (440). A carriage return is printed (450), and we return to the Eval subprogram after pulling all the characters of the current source code line. The subroutine PULLINE does this (460).
     Assuming, however, that LADS came upon the legitimate pseudo-op .FILE during an assembly, lines 480-830 take the necessary action. .FILE appears at the end of a subprogram. It tells LADS that another subprogram is linked to the one just assembled and that the source code within this next subprogram is to be assembled next, as an extension of the current subprogram. The current source code file will need to be shut down, and the next linked file will need to be opened for business. The next linked file is the one called NAME, for example, in .FILE NAME.

Linking with FILE
The FILE subroutine starts off by looking for a blank character following the FILE pseudo-op word (480-510). Locating a blank, it can now store the name of the next file of source code. It pulls in the name, one character at a time, looking for an end-of-line 0 (540) or a byte with the seventh bit set (a tokenized keyword which needs to be stretched out into a full ASCII word). Then each character in NAME is stored in the main buffer (590) as it comes in from the source code.
     When an end-of-line 0 is encountered, the whole filename has been stored in LABEL, the input buffer. And-since Y was counting the number of characters and helping store them in the right place in the buffer-Y now holds the number of characters in the filename, its length. We store Y in the FNAMELEN variable which will be needed by the DOS (Disk Operating System) when the OPEN1 subroutine tries to open or load a program file on the disk.
     Now the filename is moved from the LABEL buffer to the FILEN buffer (630-680). Why not just store the name in the FILEN buffer in the first place? First, because the printout routines get their characters and words from LABEL, the main buffer. Second, because there might be a keyword, a tokenized, abbreviated BASIC command within a filename. The filename might be END or IFNOT. And KEYWORD, our detokenization subroutine, acts upon words in LABEL, the main buffer. So, rather than make a separate KEYWORD detokenization subroutine for each buffer, it's easier to bring words into the main buffer first, detokenizing them on the fly. Then move them.
      But why, then, not have the OPEN1 subroutine look to the main buffer for its filenames? That way, the names wouldn't need to be moved to FILEN, a separate buffer. True enough, but it helps me and, I suspect, many other programmers to keep things separated by function.
      It takes only 14 bytes in LADS to move the filename from the main buffer to the filename buffer. It adds only a few microseconds during assembly time since FILE is a relatively rare event. It won't happen more than a few times during an entire assembly. It's nowhere near the heavy action of the innermost loops of LADS where every event counts, where every improvement in logic results in a noticeable improvement in speed. So memory use or speed efficiency is not really worth bothering with here. If it's easier for you to visualize the actions of a program (and make sure there are no unwanted interactions), use as many buffers and variables as you want.

Printing Addresses
The next section of this FILE subroutine prints out to screen or printer (690-740). Pass 2 doesn't print the starting address of each linked file. That's one way to tell which pass is currently being assembled. Change the LDA PASS in line 690 to LDA #0 if you want the address printed on both passes. The PRNTSA subroutine (from Printops) prints the address in RAM memory where the first byte in the new file will be assembled. PRNTINPUT prints the filename from the main buffer. Then a carriage return prepares for the next screen (or printer) line (740). The whole thing looks like this on the screen:

470A NAME
49FF NEXTNAME


     If the .S and .P pseudo-ops are turned off, nothing will be printed to the screen during an assembly except for this list of linked files and their object code addresses. That's the fastest way to assemble any source code. Printing during assembly takes up a considerable amount of time.
     The OPEN1 closes the old source code file and opens the new one. OPEN1 is found in the subprogram of the same name. Next, the computer's input channel is switched to file #1, the input-from-disk channel, and two bytes are pulled off the newly opened source code program file. (These first two bytes are, in the Commodore DOS system, ignorable.) Then ENDPRO gets us in position to analyze the first line in this new source code file (800). Finally, the ENDFLAG is set down because there's obviously more code to assemble. We return to line 80 where the RTS (back to the Indisk subprogram) is pulled off the stack, and we JMP directly back into the Eval subprogram to pull in the first source code line of the newly opened file.

The .END Link

The .END pseudo-op is quite like the FILE pseudo-op. It serves to link the last file in a chain to the first file:

PROG1    (ends with .FILE PROG2)
PROG2    (ends with .FILE PROG3)
PROG3    (ends with .END PROG1, pointing back to the original file)

This way, the assembler can go through two passes.
     .END starts off by printing the word END (850-940). Then it borrows a good section of the FILE subroutine above the JSRing to line 520. Most of the events in FILE now take place: The name of the new program file is stored in the two buffers, the file is opened, ENDPRO puts us in the right spot to look for a new line, and so on. When we return to the END subroutine (970), .END's most important work is now performed: On pass 1, the ENDFLAG is left down (980). But on pass 2, the ENDFLAG is sent up, and that will quickly cause the Eval subprogram to shut the entire LADS engine down.
     But if this is pass 1, another very important thing happens: Pass 1 is changed into pass 2. The PASS flag itself is set up (1000).
     The original starting address is now retrieved from the TA variable and restored into SA, the main Program Counter variable. This starts us off on the second pass with the correct, original starting address for assembling the object code. The JSR to INDISK gets us pointed to the first true line of source code in that first program file (past the * = symbol), and we RTS back up to line 140 which exits us from this subprogram the same way that the FILE pseudo-op exits.

Assembly to Disk Object File
The .DISK pseudo-op is an important one: It makes it possible to store the object code, the results of an assembly, as a program on disk. In a way, it's the opposite of .FILE, .FILE pulls in source code from a program file already on the disk; DISK sends out object code to a new program file being actively created during the assembly process.
     On pass 1, nothing is stored to a disk object file, so we branch to PULLJ which is a springboard to PULLINE. PULLINE pulls in the rest of a logical line and prepares us to look at the next logical line.
    On pass 2, however, all object code is stored to a disk object file if the .D NAME pseudo-op has been invoked. This storage happens character by character, just the way that object code is sent to the screen or printer. But before these bytes can go into a disk object code file, the file must be opened for writing on disk.
     One character is pulled off the source code, moving us past the space character in .D NAME and pointing to the N in NAME. A little loop (1130-1210) stores the NAME of the object file into the main buffer (for printouts) and into the filename buffer, FILEN, simultaneously. Meanwhile, if any tokenized keywords are detected (seventh bit set), we're directed to translate them to ASCII characters via a JSR KEYWORD (1170). This accomplished, we add ",P,W" onto the end of the filename. That's Commodore-specific; it tells the DOS that this file is to be a Program/Write file.
     At this point, Y holds the length of the filename, and it's then stored in the proper zero page location (1350) for use by the DOS in opening this write file. Now the main input line, the filename, is printed out, and the DISKFLAG is set up (1380). That tells LADS to always send object code bytes to this object file on pass 2 when it has finished assembling each logical line.

An Abnormal Program
The routine OPEN2 in the Open1 subprogram will now open the write file on disk (1390), and the channel to that file is made the main output channel at this point (1400-1410). Whatever is PRINTed will now go to the disk write file. And the first two bytes of a program file tell the computer where in RAM memory to load a program file. Normally, for a BASIC program, this load address would be the start of RAM, the start of BASIC's storage area for programs. But this is an abnormal program. It's machine language; it could go anywhere in RAM. We therefore need to tell the computer what the starting address of this particular program is.
     At the very beginning of LADS, the start address is pulled from just beyond the source code's *= symbol. That symbol must be the first item in any source code. The start address is then put into several variables. SA, the Program Counter, gets it, but will keep raising it as each logical line is assembled. SA is a dynamic, changing variable. TA also gets the start address. TA is a "variable," but never changes. Its job is to remember the starting address all through the assembly process. Perhaps TA should be called a constant rather than a variable, but the term variable is generally used in computing to refer to both types of "remember this" storage places.

TA Remembers
In any event, TA will always know where we started assembling. So TA is sent to the disk object file as the first two bytes (1420-1450) and then normal I/O (input from disk source file, output to screen) is restored (1460-1470). Now a disk error is checked for, and we prepare to look at the next logical line via JSR ENDPRO (1500). The RTS is pulled off the stack (it would want to send us back to INDISK), we set the ENDFLAG down and JMP back to Eval to analyze the next line of source code (1550).
     The PRINTER subroutine responds to a .P pseudo-op. It is ignored on pass 1, but on pass 2 the file to the printer is opened (1590), and the PRINTFLAG is raised. Normal I/O is restored, and we "fall through" to PULLINE, the subroutine which keeps sucking bytes off the current logical line until the end of that line is reached. These bytes are ignored. That's why pseudo-ops should be the only thing on any physical line. Anything following a pseudo-op is sucked in and ignored.
     The PULLINE routine finishes when a colon or a 0 is detected. The exit back to STARTLINE in Eval is prepared for by the PLA PLA which throws away the RTS (caused by JSRing to Pseudo from within Indisk). The only difference between a 0 (end-of-physical-line) and a colon (end-of-logical-line) condition is that a 0 requires that we skip over some link bytes in the source code. 0 requires that we first clean off these link bytes by a JSR to ENDPRO (1700). ENDPRO is also necessary in the event that the end of a physical line is also the end of the source code file itself. ENDPRO would detect that.
     The .O pseudo-op notifies LADS that you want object code stored into RAM memory during assembly beginning at the start address *=. This is relatively simple: We just print out the .O (1770-1800) and set up the POKEFLAG. (Elsewhere in LADS, the POKEFLAG is queried to determine if object code should be sent to RAM.) Then we exit via PULLINE.

Turning Things Off
The .N pseudo-op turns things off. It can turn four things off: printer printout, RAM object code storage, screen printout, and hexadecimal printout. If .N is detected in the ON-GOTO section of Pseudo above (110-320), we are sent here for another ON-GOTO series of tests (1880-1960). Of course, none of these forms of output are triggered on pass 1, so they don't need to be turned off on pass 1 either. But on pass 2, we are sent to one of the four turn-it-off routines below.
     NIXPRINT (1980) first notifies us that the .NP pseudo-op has been detected in the source code by printing the .NP. Then the PRINTFLAG is lowered (2050), and a carriage return is sent to the printer. This is in case you should want the printer turned on again further along in the source code. (You would turn it on with the .P pseudo-op.) The first line of a reactivated printout must appear on a new line, not as an extension of the previous printout.
     Then the printer is turned off with JSR CLOSE (this closedown-a-file routine is in the Open1 subprogram), and we exit via PULLINE (2160).
     The next three turn-it-off pseudo-ops are simple, and virtually identical. NIXOP prints .NO and sets down the POKEFLAG. NIXHEX prints .NH and sets down the HXFLAG (causing decimal to become the number base for opcode printouts to printer and screen). NIXSCREEN prints .NS and sets down the SFLAG. Each routine exits via PULLINE described above.

Disk Error Trapping

DISERR (2510) checks for an error in disk operation. It could be JSRed to from any place in LADS where you suspect that things aren't likely to go well with the disk. Disk drives differ considerably in their reliability: An unabused Commodore 4040 drive is usually good for years of error-free performance; many of the Commodore 1541 single-drive units, especially the earlier ones, are perhaps best described as sensitive. In any case, how often you feel the need to JSR DISERR for a report on the disk's success in completing an operation will depend on how often your drive is the cause of problems during your other programming experience.
     For Commodore computers, a simple check of the ST (status) byte in zero page will reveal many kinds of disk errors. If one is detected, an error message is printed and LADS is shut down (2650) by jumping to FIN within Eval.
     The .S (screen printout on) and .H (hexadecimal number printout) pseudo-ops are the final items to assemble as part of the LADS source code program. The subprogram Table follows, but it's data, not programming.
     There's no particular reason why these two pseudo-ops should be the last thing in LADS. They just are.
     Also, they're very simple. They each print their names to announce themselves, .S or .H; set up their flags, SFLAG or HXFLAG; and exit through PULLINE. The only notable thing about .S is that it must not set its flag until pass 2.
     The .H is a default condition of this assembler. LADS assumes that you want hex output unless you use the .NH to turn off hex and turn decimal on. Of course, you can set up other default conditions which are more harmonic with your own programming needs.

Program 8-1. Pseudo

10 ; "PSEUDO" HANDLE ALL PSEUDOPS EXCEPT BYTE
15 ;
20 ; JMP HERE FROM INDISK
30 ;    (INDISK WAS JSR'ED TO FROM EVAL . / Y HOLDS POINTER TO LABEL
40 ; -------------------------
50 PSEUDO CMP #70; IS IT "F" FOR FILE
60 BNE PSE1
70 JSR FILE; F MEANS GO TO NEXT LINKED FILE -----------------
80 GOBACK PLA; RETURN TO EVAL TO GET NEXT LINE
90 PLA
100 JMP STARTLINE;------------------------
110 PSE1 CMP #128; IS IT END
120 BNE PSEE
130 JSR PEND; 128 IS TOKEN FOR END (END OF CHAIN PSEUDO)
140 JMP GOBACK; RETURN TO EVAL
150 PSEE CMP #68; IS IT "D" FOR DISK (CREATE OBJECT CODE FILE ON DISK)
160 BNE PSEE1
170 JMP PDISK; OPEN FILE ON DISK FOR OBJECT CODE STORAGE
180 PSEE1 CMP #80; IS IT "P" FOR P (PRINTER OUTPUT)
190 BNE PSEE2
200 JMP PRINNTER; TURN ON PRINTER LISTING
210 PSEE2 CMP #78; IS IT "N" FOR NH OR NS OR SOME OTHER "TURN IT OFF"
220 BNE PSEE3
230 JMP NIX; TURN SOMETHING OFF
240 PSEE3 CMP #79; IS IT "O" FOR OUTPUT (POKE OBJECT CODE INTO RAM)
250 BNE PSEE4
260 JMP OPON; START POKING OBJECT CODE (DEFAULT)
270 PSEE4 CMP #83; IS IT "S" FOR PRINT TO SCREEN
280 BNE PSEE5
290 JMP SCREEN; TURN ON SCREEN PRINTING
300 PSEE5 CMP #72; IS IT "H" FOR HEX NUMBERS DURING PRINTOUTS
310 BNE PSE9;
320 JMP HEXIT; TURN ON HEX PRINTING
330 ;------------------------- PRINT ERROR MESSAGE (NO SUCH PSEUDO-OP)
340 PSE9 STA LABEL,Y; STORE CHAR. FOR PRINTOUT
350 JSR PRNTLINE
360 JSR PRNTSPACE
370 JSR PRNTSA
380 JSR ERRING
390 JSR PRNTINPUT
400 LDA #<MERROR
410 STA TEMP
420 LDA #>MERROR
430 STA TEMP+1
440 JSR PRNTMESS
450 JSR PRNTCR
460 JMP PULLINE; PULL IN (& IGNORE) REST OF LINE, THEN BACK TO EVAL
470 ;------------------------- HANDLE FILE PSEUDO-OP ----------------
480 FILE JSR CHARIN
490 CMP #32; LOOK FOR END OF THE WORD FILE (TO LOCATE FILENAME)
500 BEQ FIO
510 JMP FILE; CONTINUE LOOKING FOR BLANK
520 FIO LDY #0
530 FI1 JSR CHARIN
540 CMP #0; END OF LINE
550 BEQ FI2
560 CMP #127; KEYWORD, SO STRETCH IT OUT
570 BCC FII1
580 JSR KEYWORD
590 FII1 STA LABEL,Y; STORE CHAR. OF FILENAME
600 INY
610 JMP FI1; CONTINUE STORING FILENAME IN MAIN BUFFER (LABEL)
620 FI2 STY FNAMELEN; STORE FILENAME LENGTH
630 LDY #0
640 FILO LDA LABEL,Y;------- PUT FILENAME INTO PROPER BUFFER (FILEN)
650 BEQ FIL01
660 STA FILEN,Y
670 INY
680 JMP FILO
690 FIL01 LDA PASS; ON PASS 2, DON'T PRINT OUT PC
700 BNE FI5
710 JSR PRNTSA; PRINT THE FILENAME
720 JSR PRNTSPACE
730 FI5 JSR PRNTINPUT
740 JSR PRNTCR; CARRIAGE RETURN
750 JSR OPEN1; OPEN NEXT LINKED FILE ON DISK (FOR CONTINUED READING OF SOURCE)
760 LDX #1
770 JSR CHKIN
780 JSR CHARIN; PULL IN NEXT TWO BYTES AND
790 JSR CHARIN
800 JSR ENDPRO; CHECK FOR END OF PROGRAM
810 LDX #0
820 STX ENDFLAG; SET END OF PROGRAM FLAG TO ZERO
830 RTS
840 ;------------------------- HANDLE END PSEUDO-OP ---------
850 PEND LDA #46; PRINT OUT END
860 JSR PRINT
870 LDA #69
880 JSR PRINT
890 LDA #78
900 JSR PRINT
910 LDA #68
920 JSR PRINT
930 LDA #32
940 JSR PRINT
950 JSR CHARIN
960 JSR FIO; GET FILENAME, ETC. JUST AS FILE PSEUDO-OP DOES
970 LDA PASS; ON PASS 1, DON'T SET THE ENDFLAG UP.
980 BEQ PEND1; BUT ON PASS 2, IT'S NECESSARY (TO END THE ENTIRE PROGRAM)
990 INC ENDFLAG
1000 PEND1 INC PASS; RAISE PASS FROM PASS 1 TO PASS 2
1010 LDA TA; PUT ORIGINAL START ADDRESS BACK INTO PC (SA) FOR RESTART OF
1020 STA SA; ASSEMBLY ON PASS 2.
1030 LDA TA+l
1040 STA SA+1
1050 JSR INDISK; SET UP NEXT LINE
1060 RTS
1070 ;------------------- HANDLE D FILENAME PSEUDO-OP (OBJECT CODE FILE)
1080 PDISK LDA PASS; ON PASS 1, DON'T STORE ANYTHING TO DISK
1090 BEQ PULLJ; PULL) IS A SPRINGBOARD (JUMPS TO PULLINE)
1100 JSR CHARIN; POINT TO FILENAME
1110 STA LABEL,Y
1120 LDY #0
1130 PDLOOP JSR CHARIN
1140 BEQ PD1; END OF LINE
1150 CMP #127; IT'S A KEYWORD (WITHIN THE FILENAME) IF >127
1160 BCC PDIX
1170 JSR KEYWORD
1180 PDIX STA LABEL,Y; KEEP STORING FILENAME INTO PRINTOUT BUFFER (LABEL)
1190 STA FILEN,Y; AS WELL AS OPEN1 BUFFER (FILEN)
1200 INY
1210 JMP PDLOOP; KEEP STORING FILENAME;------------------
1220 PULLJ JMP PULLINE;-------- SPRINGBOARD TO IGNORE FILENAME
1230 PD1 LDA #44; PUT P,W (PROGRAM, WRITE) SIGNALS ONTO FILENAME
1240 STA FILEN,Y
1250 INY
1260 LDA #80
1270 STA FILEN,Y
1280 INY; ADD--,P,W
1290 LDA #44
1300 STA FILEN,Y
1310 INY
1320 LDA #87
1330 STA FILEN,Y
1340 INY
1350 STY FNAMELEN; STORE FILENAME LENGTH
1360 JSR PRNTINPUT; PRINT OUT THE LINE
1370 JSR PRNTCR; CARRIAGE RETURN
1380 INC DISKFLAG; RAISE DISKFLAG TO SHOW THAT FUTURE POKES SHOULD GO TO DISK
1390 JSR OPEN2; OPEN A SECOND DISK FILE (THIS ONE FOR WRITING TO)
1400 LDX #2
1410 JSR CHKOUT
1420 LDA TA; PRINT OBJECT CODE'S STARTING ADDRESS TO DISK FILE
1430 JSR PRINT
1440 LDA TA+1
1450 JSR PRINT
1460 EDISK JSR CLRCHN
1470 LDX #1; RESTORE NORMAL I/O
1480 JSR CHKIN
1490 JSR DISERR; CHECK FOR DISK ERROR (FAILURE TO OPEN CORRECTLY)
1500 JSR ENDPRO; GET NEXT LINE NUMBER
1510 PLA; PULL RTS
1520 PLA
1530 LDX #0
1540 STX ENDFLAG; RESET END OF PROGRAM FLAG
1550 JMP STARTLINE; AND RETURN TO EVAL TO GET NEXT LINE
1560 ;-------------------------- HANDLE .P (PRINTER) PSEUDO-OP -------
1570 PPRINTER LDA PASS; ON PASS 1, DO NO PRINTER OUTPUT
1580 BEQ PULLINE; GET RID OF REST OF LINE AND GO ON.
1590 JSR OPEN4; PASS 2, SO OPEN PRINTER TO HEAR FROM COMPUTER
1600 INC PRINTFLAG; RAISE PRINTER OUTPUT FLAG (SO PRINT WILL SEND BYTES TO
1610 JSR CLRCHN;    THE PRINTER AS WELL AS THE SCREEN).
1620 LDX #1; RESTORE NORMAL I/O
1630 JSR CHKIN
1640 ;---------------------- SUCTION ROUTINE. GET RID OF REST OF A LINE
1650 PULLINE JSR CHARIN; IGNORE ALL BYTES, JUST LOCATE NEXT LINE
1660 BEQ ENDPULL; ZERO END OF LINE SHOULD GO TO ENDPRO FOR NEXT LINE #
1670 CMP #58; WHEREAS A COLON END OF LINE SKIPS THAT STEP
1680 BEQ ENDPULR; (COLON)
1690 JMP PULLINE; NEITHER COLON NOR ZERO (SO PULL IN MORE CHARACTERS)
1700 ENDPULL JSR ENDPRO
1710 ENDPULR PLA; PULL RTS OFF STACK
1720 PLA
1730 LDX #0
1740 STX ENDFLAG; SET ENDFLAG DOWN
1750 JMP STARTLINE; RETURN TO EVAL (TO GET NEXT LINE OF SOURCE CODE)
1760 ;-------------------------- HANDLE .O (POKE BYTES TO RAM) PSEUDO-OP
1770 OPON LDA #46; PRINT .O
1780 JSR PRINT
1790 LDA #79; "0"
1800 JSR PRINT
1810 JSR PRNTCR; CARRIAGE RETURN
1820 LDA #1
1830 STA POKEFLAG; RAISE POKE-TO-RAM FLAG
1840 JMP PULLINE; IGNORE REST OF LINE
1850 ;-------------------------- HANDLE .N(SOMETHING),TURN-IT-OFF PSEUDO-OPS
1860 NIX LDA PASS; ON PASS 1, DON'T BOTHER WITH ANY OF THIS
1870 BEQ PULLINE
1880 JSR CHARIN; ON PASS 2, SEE WHICH THING IS BEING TURNED OFF
1890 CMP #80; IS IT ".NP" TO "NOT PRINT TO PRINTER"
1900 BEQ NIXPRINT
1910 CMP #79; IS IT ".NO" TO "NOT POKE OBJECT BYTES TO RAM"
1920 BEQ NIXOP
1930 CMP #83; IS IT ".NS" TO "NOT PRINT TO SCREEN"
1940 BEQ NIXSCREEN
1950 CMP #72; IS IT ".NH" TO "NOT PRINTOUT HEX" (THUS SWITCH TO DECIMAL)
1960 BEQ NIXHEX
1970 ;-------------------------- TURN OFF PRINTER OUTPUT
1980 NIXPRINT LDA #46; PRINT ".NP" TO SCREEN
1990 JSR PRINT
2000 LDA #78; "N"
2010 JSR PRINT
2020 LDA #80; "P"
2030 JSR PRINT
2040 JSR PRNTCR; CARRIAGE RETURN
2050 DEC PRINTFLAG; LOWER PRINT-TO-SCREEN FLAG
2060 JSR CLRCHN; TURN OFF PRINTER
2070 LDX #4
2080 JSR CHKOUT
2090 LDA #13
2100 JSR PRINT
2110 LDA #4
2120 JSR CLOSE
2130 JSR CLRCHN
2140 LDX #1; RESTORE NORMAL I/O
2150 JSR CHKIN
2160 JMP PULLINE; IGNORE REST OF LINE (AND RETURN TO EVAL)
2170 ;-------------------------- STOP POKEING OBJECT BYTES TO RAM
2180 NIXOP LDA #46; PRINT ".NO"
2190 JSR PRINT
2200 LDA #78;    "N"
2210 JSR PRINT
2220 LDA #79;    "O"
2230 JSR PRINT
2240 JSR PRNTCR;CARRIAGE RETURN
2250 LDA #0
2260 STA POKEFLAG; TURN OFF POKE FLAG
2270 JMP PULLINE; IGNORE REST OF LINE (AND RETURN TO EVAL)
2280 ;-------------------------- STOP HEX PRINTOUTS (START DECIMAL)
2290 NIXHEX LDA #46; PRINT ".NH"
2300 JSR PRINT
2310 LDA #78;    "N"
2320 JSR PRINT
2330 LDA #72;    "H"
2340 JSR PRINT
2350 JSR PRNTCR; CARRIAGE RETURN
2360 LDA #0
2370 STA HXFLAG; PUT HEXFLAG DOWN
2380 JMP PULLINE; IGNORE REST OF LINE (AND RETURN TO EVAL)
2390 ;-------------------------- STOP SCREEN PRINTOUTS
2400 NIXSCREEN LDA #46, PRINT ".NS"
2410 JSR PRINT
2420 LDA #78;    "N"
2430 JSR PRINT
2440 LDA #83;    "S"
2450 JSR PRINT
2460 JSR PRNTCR;CARRIAGE RETURN
2470 LDA #0
2480 STA SFLAG; PUT DOWN SCREEN PRINTOUT FLAG
2490 JMP PULLINE; IGNORE REST OF LINE (AND RETURN TO EVAL)
2500 ;-------------------------- DISK ERROR DETECTION ROUTINE --------
2510 DISERR LDX ST; CHECK DISK STATUS VARIABLE (COMPUTER SPECIFIC)
2520 BNE MODIER; IF NOT ZERO, THERE IS SOME FAULT IN THE DISK I/O
2530 RTS;----------
2540 MODIER LDA #0; PRINT OUT ERROR MESSAGE
2550 JSR PRNTNUM
2560 JSR PRNTSPACE
2570 LDA #<MDISER
2580 STA TEMP; POINT TO DISK ERROR MESSAGE
2590 LDA #>MDISER
2600 STA TEMP+1
2610 JSR ERRING; RING BELL
2620 JSR PRNTMESS; PRINT ERROR MESSAGE
2630 PLA; PULL RTS OFF STACK
2640 PLA
2650 JMP FIN; SHUT DOWN ENTIRE LADS OPERATION
2660 ;--------------- HANDLE S PSEUDO-OP (TURN ON SCREEN PRINTOUT)
2670 SCREEN LDA #46, PRINT ".S"
2680 JSR PRINT
2690 LDA #83;    "S"
2700 JSR PRINT
2710 JSR PRNTCR; CARRIAGE RETURN
2720 LDA PASS; ON PASS 1, NO SCREEN PRINTOUT
2730 BEQ SCREX
2740 LDA #1; OTHERWISE, RAISE SCREEN PRINTOUT (LISTING) FLAG
2750 STA SFLAG
2760 SCREX JMP PULLINE; IGNORE REST OF LINE (AND RETURN TO EVAL)
2770 ;-------------- HANDLE H PSEUDO-OP (HEX NUMBERS DURING PRINTOUT)
2780 HEXIT LDA #46; PRINT ".H"
2790 JSR PRINT
2800 LDA #72;    "H"
2810 JSR PRINT
2820 JSR PRNTCR; CARRIAGE RETURN
2830 LDA #1
2840 STA HXFLAG; SET HEXFLAG UP
2850 JMP PULLINE; IGNORE REST OF LINE (AND RETURN TO EVAL)
2860 .FILE TABLES


Program 8-2. Pseudo, Apple Modifications

To create the Apple version of Pseudo, omit lines 1230-1340 and lines 2500-2650 from Program 8-1 and change the following lines:

110 PSE1 CMP #69; IS IT END
960 JSR FILE; GET FILENAME, ETC. JUST AS FILE PSEUDO-OP DOES
1002 SEC; SAVE LENGTH OF FILE
1003 LDA SA; FOR THIRD AND FOURTH
1004 SBC TA; BYTES OF BINARY FILE
1005 STA LENPTR; CREATED BY D
1006 LDA SA+1; PSEUDO-OP
1007 SBC TA+1
1008 STA LENPTR+1
1350 PD1 STY FNAMELEN
1455 LDA LENPTR; WRITE LENGTH OF
1456 JSR PRINT; BINARY FILE
1457 LDA LENPTR+1
1458 JSR PRINT
1490 ;


Program 8-3. Pseudo, Atari Modifications

To create the Atari version of Pseudo, omit lines 1230-1340 and lines 1400-1450 from Program 8-1 and change the following lines:

10 ;ATARI MODIFICATIONS--PSEUDO
110 PSE1 CMP #69
580 ;
675 CPY FNAMELEN
680 BNE FILO
780 ;
790 ;
800 ;
960 JSR FILE
1001 LDA SA
1002 STA LLSA
1003 LDA SA+1
1004 STA LLSA+1
2510 DISERR LDX $0363
2530 .FILE D:KERNAL.SRC


Return to Table of Contents | Previous Chapter | Next Chapter