💾 Archived View for mirrors.apple2.org.za › archive › apple.cabi.net › System › GSOS.P8.Anatomy › SY… captured on 2024-02-05 at 14:49:15.
View Raw
More Information
⬅️ Previous capture (2023-01-29)
-=-=-=-=-=-=-
Table 5-5 Continued
8E28: 00 C4 100 IHVECT4 DA $C400
0E2A: EE 9A 101 INVECT5 DA N0DEVERR
BE2C: 00 C6 102 INVECT6 DA $C600
BE2E: EE 9A 103 INVECT7 DA N0DEYERR
104
;(Assume mouse card)
;(Assume 5.25-inch drive)
105 ***********************************************
106 The BASIC.SYSTEM 1/0 links are stored here.
107 These are the addresses control will pass
108 to if the input or output is not handled
109 internally.
110 ***********************************************
8E30: 07 C3 111 VECT0UT DA C0UT80 ProDOS output link
BE32: 05 C3 112 VECTIN DA KEYIN80 ProDOS input link
113
114 Miscellaneous internal BASIC.SYSTEM parameters:
115
BE34: Fl 87 116 VD0SI0 DA D0S0UT ;Character out intercept
8E36: F4 87 117 DA D0SIN ;Character in intercept
118
8E38: 2F 9A 119 VSYSI0 DA SYS0UT Internal output subroutine
8E3A: 8A 9A 120 DA SYSIN ;Internal input subroutine
121
8E3C: 06 122 DEFSLT DF8 6 ;Default slot #
8E3D: 01 123 DEFDRV DF8 1 Default drive #
124
8E3E: 00 125 PREGA DF8 0 ;Temporary storage for A
8E3F: 00 126 PREGX DF8 0 Temporary storage for X
8E40: 00 127 PREGY DF8 0 ;Temporary storage for Y
128
8E41: 00 129 DTRACE DFB 0 ;bit 7=1 ==> Applesoft trace on
130
8E42: 00 131 STATE DF8 0 ;0=direct. ~0=in program
8E43: 00 132 EXACTV DF8 0 ;bit 7=1 ==> EXEC file open
8E44: 00 133 IFILACTV DF8 0 bit 7=1 ==> input file active
8E45: 00 134 0FILACTV DF8 0 ;bit 7=1 ==> output file active
8E46: 00 135 PFXACTV DF8 0
8E47: 00 136 DIRFLG DF8 0
8E48: 00 137 EDIRFLG DF8 0
8E49: 00 138 STRINGS DF8 0
8E4A: 00 139 T8UFPTR DF8 0
8E48: 00 140 INPTR DF8 0
8E4C: 00 141 CHRLAST DF8 0
8E4D: 00 142 0PENCNT DF8 0
8E4E: 00 143 EXFILE DF8 0
8E4F: 00 144 CATFLAG DF8 0
145
;bit 7=1 ==> prefix input active
;bit 7=1 ==> dir. file active
;bit 7=1 ==> end of directory
;Counter for free space calc.
Character count for WRITE
;Char. count for kbd input
Last character printed
;Number of open files (not EXEC)
;EXEC file close flag
Directory input flag
146 **************************~************************
147 The following three locations will be used if
148 you are adding user commands to 8ASIC.SYSTEM.
The BASIC. SYSTEM Global Page: $BEO~$BEFF 243
Table 5-5 Continued
BE50: 00 00 150 XTRNADDR DA 0 ;Address of user command handler
BE52: 00 151 XLEN DFB
BE53: 00 152 XCNUM DFB
153
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
8E54: 00 OO 184 PBITS DW 0
154
0 ;Length of user command - 1
0 ;Command number in use (O=user)
- Notes on PBITS and FBITS:
- Once BASIC.SYSTEM has identified a valid command,
- it stores a number in PBITS and PBITS*l that
- reflects the syntax of the command. It then calls
- the command parser, which updates FBITS and
- FBITS+l to reflect the parameters actually found.
- Meaning of bits in PBITS/FBITS:
- bit 7 fetch prefix if pathname not specified
- bit 6 slot number required/found
- bit 5 command NOT valid in direct mode
- bit 4 pathname is optional (no names+parms)
- bit 3 create file if it doesn't exist
- bit 2 file type optional (T parameter)/found
- bit 1 second pathname required (for RENAME)/found
- bit 0 filename allowed/found
- Meaning of bits in PBITS~l/FBITS+l:
- bit 7 A parameter allowed/found
- bit 6 8 parameter allowed/found
- bit 5 E parameter allowed/found
- bit 4 L parameter allowed/found
- bit 3 parameter allowed/found
- bit 2 S/D parameters allowed/found
- bit 1 F parameter allowed/found
- bit 0 R parameter allowed/found
0000 185 FBITS DW 0
186
;Permitted parameter bits BE56:
;Found parameter bits
188
189
190
191
192
8E58: 00 00 193
BE5A: 00 00 00 194
8E5D: 00 00 195
8E5F: 00 00 196
8E61: 00 197
187 *****************~**~*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- The following table is where command parameters
- are stored during a parsing operation. The
- entries for unspecified parameters are not
- changed.
APARM DA 0 A (address) parameter
BPARM DS 3 8 (byte #) parameter
EPARM DA 0 ;E (end addr) parameter
LPARM DW 0 ;L (length) parameter
SPARM DF8 0 5 (slot) parameter
244 System Programs
Table 5-5 Continued
BE62: DO 198 DPARM DFB 0
BE63: 00 00 199 FPARM DW 0
BE65: 00 00 200 RPARM DW 0
BE67: 00 201 VPARM DFB 0
BE68: DO 00 202 QPARM DW 0
BE6A: 00 203 TPARM DFB 0
BE6B: 00 204 SLPARM DFB 0
BE6C: BC BC 205 PATHl DA TXBUF-l
8E6E: 80 02 206 PATH2 DA TXBUF2
207
;D (drive) parameter
;F (field #) parameter
;R (record #) parameter
;V (volume #) parameter
(line #) parameter
;T (file type code) parameter
;slot (for IN#, PR#) parameter
;Pointer to first pathname
;Pointer to second pathname
208 *****************************************************
209 All BASIC.SYSTEM MLI calls are routed to GOSYSTEM
210 * with the command number in the accumulator.
211 Prior to calling GOSYSTEM. BASIC.SYSTEM
212 sets up the appropriate parameter table in the
213 global page as required by the call. GOSYSTEM
214 handles all MLI calls from $CO..$D3 inclusive. If
215 an error occurs. an Applesoft error code is
216 returned in A with the carry flag set.
217 **************~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BE70: 8D 85 BE 218 GOSYSTEM STA SYSCALL Save MLI command number
BE73: 8E A8 BC 219 STX CALLX Save X register
BE76: 29 IF 220 AND #$lF ;# mod 32
BE78: AA 221 TAX
BE79: BD 05 B8 222 LDA SYSCTBL.X ;Get address of parm table
BE7C: 8D 86 BE 223 STA SYSPARM (low) and save it
BE7F: AE A8 BC 224 LDX CALLX Restore X
BE82: 20 00 BF 225 JSR MLI ;Do the MLI call
BE85: 00 226 SYSCALL DFB 0 ;MLI command # stored here
BE86: 00 227 SYSPARM DFB 0 ;Address of parm table (low)
BE87: BE 228 DFB $BE High address always $BE
BE88: BO 01 229 BCS BADCALL ;Branch if error
BE8A: 60 230 RTS
231
232 *******~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
233 The BADCALL subroutine converts the MLI
234 error code to a corresponding Applesoft
235 error code.
236 *******~~*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BE8B: A2 12 237 BADCALL LDX #$12
BE8D: DD EE B9 238 MLIERRl CMP MLIERTBL,X ;Is it a "known" MLI error?
BE90: FO 05 239 BEQ MLIERR2 Yes. so branch
BE92: CA 240 DEX ;Check all 19 possibilities
BE93: 10 F8 241 BPL MLIERRl
BE95: A2 13 242 LDX #$13 ;Not known, so "1/0 error"
243
BE97: BD 01 BA 244 MLIERR2 LDA BIERRTBL,X ;Convert to Applesoft error code
BE9A: AE A8 BC 245
BE9D: 38 246
LDX CALLX ;Restore X
SEC ;==> error
The BASIC. SYSTEM Global Page: $BEO~$BEFF 245
Table 5-5 Continued
BE9F: 00 248 DFB $00 ;Unused byte
249
250 *************~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
251 The parameter tables for each of the MLI functions
252 supported by BASIC.SYSTEM follow. These tables
253 * must be filled in before calling GOSYSTEM.
254 ****************~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
255 Parm table for CREATE:
BEAD: 07 256 DFB $07
BEAl: BC BC 257 DA TXBUF-l
BEA3: C3 258 DFB $C3
BEA4: 00 259 DFB 0
BEA5: 00 00 260 DW $0000
BEA7: 00 261 DFB 0
BEA8: 00 00 262 DW 0
BEAA: 00 00 263 DW 0
264
265 Parm table for DESTROY
BEAC: 01 266 DFB $01
BEAD: BC BC 267 DA TXBUF-l
268
269 Parm table for RENAME:
BEAF: 02 270 DFB $02
BEB0: BC BC 271 DA TXBUF-1
BEB2: 80 02 272 DA TXBUF2
273
;Number of parameters
;Pathname pointer
Access code
;File type code
;Auxiliary type code
Storage type code (usually 1)
;Create date
;Create time
SET_PREFIX. GET_PREFIX:
;Number of parameters
;Pathname pointer
Number of parameters
Old pathname pointer
;New pathname pointer
274 Parm table for SET_FILE_INFO and GET_FILE_INFO:
BEB4: 00 275 DFB $00 ;=7 (SFI) or 10 (GFI)
BEB5: BC BC 276 0A TXBUF-lz ;Pathname pointer
BEB7: 00 277 DFB $00 ;Access code
BEB8: 00 278 DFB $00 ;File type code
BEB9: 00 00 279 OW $0000 ;Auxiliary type code
BEBB: 00 280 DFB $00 Storage type code (GFI only)
BEBC: 00 00 281 DW $0000 ;Blocks used (GFI only)
BEBE: 00 00 282 DW $0000 ;Modification date
BEC0: 00 00 283 DW $0000 Modification time
BEC2: 00 00 284 DW $0000 ;Create date (GFI only)
BEC4: 00 00 285 DW $0000 ;Create time (GFI only)
286
287 Parm table for ON_LINE, SET_MARK, GET_MARK.
288 SET_E0F,GET_E0F.SET_BUF,GET_BUF:
BEC6: 02 289 DFB $02 Number of parameters
BEC7: 00 290 DFB $00 ;Unit or reference number
BEC8: 00 291 DFB $00 ;2-byte pointer to data buffer
BEC9: 00 292 DFB $00 (BUF, ON_LINE), or 3-byte
BECA: 00 293 DF8 $00 position (MARK, E0F)
294
295 Parm table for OPEN:
246 System Programs
Table 5-5 Continued
BECB: 03 296 DFB $03
BECC: BC BC 297 DA TXBUF-l
BECE: OO 00 298 DA $0000
BEDO: DO 299 DFB O
300
301 Parm table for NEWLINE
BEDl: 03 302 DFB $03
BED2: DO 303 DFB 0
BED3: 7F 304 DFB $7F
BED4: OD 305 DFB $OD
306
Number of parameters
;Pathname pointer
;Buffer pointer (lK)
;Reference number
Number of parameters
;Reference number
;Ignore state of high bit
;Newline is $OD or $8D
307 Parm table for READ and WRITE:
BEDS: 04 308 DFB $04 Number of parameters
BED6: 00 309 DFB $00 Reference number
BED7: 00 00 310 DA $0000 ;Buffer pointer
BED9: 00 00 311 DW $0000 ;Number of bytes to read/write
BEDB: 00 00 312 DW $0000 Actual number read/written
313
314 * Parm table for CLOSE and FLUSH:
BEDD: 01 315 DFB $01 ;Number of parameters
BEDE: 00 316 DFB 0 ;Reference number
317
BEDF: 00 318 DFB 0 ;Unused byte
319
BEEO: C3 CF DD 320 ASC "COPYRIGHT APPLE, 1983"
BEE3: D9 D2 C9 C7 C8 D4 AD Cl
BEEB: DO DO CC C5 AC AD Bl B9
BEF3: B8 B3
321
322 *****************************************************
323 * Call GETBUFR to free up "A" pages above HIMEM. If
324 * the carry flag is set upon exit, there was not
325 enough memory to do so; otherwise, "A" will
326 * contain the number of the first page of the
327 buffer. Call FREEBUFR to remove the buffer, and
328 restore HIMEM to its bootup value (that value is
329 * stored at PAGETOP).
330 *****************************************************
BEF5: 4C B5 A2 331 GETBUFR JMP
BEF8: 4C 01 A3 332 FREEBUFR JMP
BEFB: 96 333 PAGET0P DFB
334
BEFC: 00 DO 00 335 DS
BEFF: 00
PAGEGET ;Reserve "A" pages above HIMEM
PAGEFREE ;Restore original HIMEM
$96 ;HIMEM page on boot
4 ;Unused bytes
The BASIC. SYSTEM Global Page: $BEO~$BEFF 247
Important; When using GOSYSTEM, be careful not to disturb the values of
parameter table entries that BASIC.SYSTEM sets up as constants. These parar
z The pathname pointers in all parameter lists
z The time and date entries at ~BEAA-$BEAB and ~BEA8-~BEA9 in
CREATE parameter list (they should both be zero)
z The "newline character" entry' at ~BED4 in the NEWLINE parameter
should always be $OD)
If you want to temporarily change any of these parameters, save their values first,
restore them after the GOSYSTEM call.
In the following section we discuss some of the other important areas of
BASIC.SYSTEM global page.
BASIC.SYSTEM ERROR HANDLING
If a call to GOSYSTEM results in a system error, G0SYSTEM branches to
CALL ($BE8B), a subroutine that converts the MLI error code in the
into a BASIC.SYSTEM (Applesoft) error code. Table 5-6 shows the -
between a given MLI code and a BASIC.SYSTEM code.
Note that only 19 MLI error codes are specifically dealt with by BADCALL
automatically converts all others to error code 8 ("1/0 Error"). Moreover, four B'
SYSTEM error codes do not correspond to any MLI error code at all; these
codes are generated by illegal conditions within BASIC.SYSTEM itself- such as -
attempt to load a program that is too large.
After BASIC.SYSTEM converts the MLI error code, it calls ERR0UT (~BE~
handle the error. This subroutine first stores the error code in ERRC0DE
and at $DE (the Applesoft interpreter expects to find an error code at $DE) and
checks if the Applesoft 0NERR G0T0 error-trapping feature is active. If it is,:
passes to the internal Applesoft error-handling subroutine. If it isn't, BASIC. _
calls PRINTERR ($BEOC) to print the error message corresponding to the error
(see Table 5-6).
If you are writing an assembly-language program that operates in an -
BASIC.SYSTEM environment, you can call ERB0UT or PRINTERR to handle
rors. But you must ensure that you call these subroutines with a BASIC.SYST:
(Applesoft) error code, rather than an M LI error code, in the accumulator. You
execute a JSR BADCALL instruction (with the error code in the accumulator)
perform the necessary error code conversion.
EXECUTING DISK COMMAND STRINGS FROM ASSEMBLY LANGUAGE
An assembly-language program can use the D0SCMD ($BE03) subroutine in
BASIC.SYSTEM global page to interpret and execute a standard BASIC.SYSTE~
248 System Programs
Table 5-6 BASIC.SYSTEM error codes and messages
BASIC. SYSTEM Error Code MLI Error Code
$00 $00
$02 $4D
$03 $28
$04 $2B
$05 $4C
$06 $45,$44
$07 $46
$08 [all others]
$09 $48
$0A $4E
$0B $53
$0C $56,$42,$41
$0D $4B
$0E
$0F
$10 $40
$11 $49
$12 $43
$13 $47
$14 $50
$15
$16
BASIC. SYSTEM Error Message
[no error occurred]
RANGE ERROR
NO DEVICE CONNECTED
WRITE PROTECTED
END OF DATA
PATH NOT FOUND
PATH NOT FOUND
1/0 ERROR
DISK FULL
FILE LOCKED
INVALID PARAMETER
NO BUFFERS AVAILABLE
FILE '1'YPE MISMATCH
PROGRAM TOO LARGE
NOT DIRECT COMMAND
SYNTAX ERROR
DIRECTORY FULL
FILE NOT OPEN
DUPLICATE FILE NAME
FILE BUSY
FILE(S) STILL OPEN
DIRECT COMMAND
disk command stored in the Apple input buffer at $200 as an ASCII string followed by
a carriage return code ($8D). DOSCMD is effective only when an Applesoft program
is actually running, so an Applesoft program must use the CALL command to access
the assembly-language program.
Executing Disk Command Strings from Assembly language 249
(Under DOS 3.3, assembly-language programs can execute disk
sending code $04 (Control-D) to the standard character output subro'itine,
($FDED), followed by the ASCII codes for the command and a carriage return
BASIC.SYSTEM does not support this technic~ue.)
DOSCMD can execute most, but not all, BASIC.SYSTEM disk
commands it does not handle properly are - (dash), RUN, LOAD, CHAIN,
WRITE, APPEND, and EXEC. When you call DOSCMD to execute a
can handle, it returns a BASIC.SYSTEM error code in the accumulator. If no
occurred, the code is 0, and the carry flag is clear. If an error did occur, the
is set. Handle an error condition by calling ERROUT ($BE09) or PRI.
($BE0C) (as described in the previous section) or by passing control to your
error-handling code.
Important: Just before a program using DOSCMD ends, it must clear the carry'
and execute a CLC instruction. If it ends with the carry flag set, the
program that called it may not work properly.
ADDING COMMANDS TO BASIC.SYSTEM
One of the best features of BASIC.SYSTEM is its support of user-defined
commands. To see how to extend BASIC.SYSTEM's standard command set, let's '-
look at exactly what happens when BASIC. SYSTEM encounters a string of charactert
may represent a valid command. Figure 5-2 shows a flowchart of this procedure.
The first thing BASIC.SYSTEM does is check if one of its 32 standard
has been specified (CATALOG, OPEN, WRITE, and so on). If one has been,
handles it internally.
But if the command can't be identified, BASIC.SYSTEM does not immediately,
an error code; rather, it calls a subroutine in its global page, EXTRNCMD ($BE06), to
if a user-installed external command handler will claim the command. (The
address is always stored at $BE07 and $BE08.) If no external command handler has
installed, EXTRNCMD simply jumps to a "do-nothing" RTS instruction at XRETU
($BE9E). If the external command handler does not claim the command, and if
command was issued from within a program, a BASIC.SYSTEM syntax error
occurs. If on the other hand, the command was entered in Applesofi command mode, it
passed on for consideration by the Applesofi interpreter. Only if the interpreter does
recognize it does an Applesofi syntax error occur.
Let's assume an external command handler has been installed so that a call
EXTRNCMD will pass control to it. Such a handler first executes a CLD instruction,
which Apple says it will use as an identification byte in future versions of BASIC.SYS-
TEM. The handler then determines whether its command has, in fact, been entered; it
can do this by checking if the first few characters in the command line match the
expected command string. (The command line is stored in the Apple's standard input
250 System Programs
Figure 5-2 A flowchart showing how BASIC. SYSTEM executes external commands
XLEN = $BE52
XCNUM = $BE53
PBI'T'S = $BE54
XTRNADDR = $BE5O/$BE51
JMP (x'T'RNADDR)
External
command syntax No
code ok?
~ call e::ternaI
command handler
Adding Commands to BASIC. SYSTEM 251
buffer beginning at $200 in ASCII form with the high bit of each code set to 1.) If
don't match, the subroutine must end with the carry flag set to indicate that it did
claim the command.
If the handler detects the correct command, the handler can do one of two
It can proceed to parse any expected parameters (such as a pathname, one of the
BASIC.SYSTEM letter parameters, or special parameters defined by the c~--
itself) from the command line and then actually execute the command. Alt:
all the possible parameters are capable of being recognized by BASIC.SYSTEM,
handler can ask BASIC.SYSTEM to do the parsing and syntax checking; the'
does this by setting certain bits in PBITS ($BE54) and PBITS + 1 ($BE55) to
the required command syntax. If BASIC.SYSTEM does the parsing and it detect::
error, BASIC.SYSTEM handles the error itself. Table 5-1 shows the command
parameters supported by BASIC.SYSTEM and the range of values that they can take -
With three exceptions, each bit in PBITS and PBITS + 1 is a flag indic
whether the particular parameter associated with that bit is required or allowed.
exceptions are bits that indicate particular characteristics of the command: 'v,'hotko
prefix must be fetched for it, whether it is valid in Applesoft command mode,
whether a file that is specified should be created if it doesn't already exist.
meaning of each bit is as follows:
PBITS ($8E54)
bit 7 Fetch the current prefix if a pathname is not
specified. The command line cannot contain a
pathname and a set of parameters unless bit 0 of
PBITS is also set to 1.
bit 6 A slot number is required (for example, IN#, PR,').
bit 5
bit 4
bit 3
bit 2
bit 1
bit 0
The slot number must be the first parameter after
the command name, and no pathnames can appear on
the command line (so bit 0 and bit 1 of PBITS must
both be 0).
The command is not valid in command mode.
A pathname is optional. Pathnames and parameters
cannot be specified on the same command line.
Create a file if the one specified does not exist.
The file type parameter is allowed (T parameter).
The T parameter can be a number or a three-
character file type mnemonic corresponding
to a file type code (see Table 2-4 in Chapter 2).
For example, ,TDIR selects the file type code
for a DIR file ($OF).
A second pathname is required (for example,
RENAME). Two pathnames must be specified, or
the first letter parameter will be incorrectly
interpreted as a pathname.
A pathname is allowed. Pathnames and parameters
can be specified on the same command line.
If the S and D bit (bit 2) of PBITS+1 is also
set to 1, a pathname is mandatory, and parameters
252 System Programs
alone cannot be specified without generating a
syntax error.
PBITS+1 ($BEss)
bit 7 The A parameter is allowed.
bit 6 The B parameter is allowed.
bit 5 The E parameter is allowed.
bit 4 The L parameter is allowed.
bit 3 The @ parameter is allowed.
bit 2 The S and D parameters are allowed. The S (slot)
and D (drive) parameters must correspond to an
existing disk drive if preceded by a filename; if
preceded by a slot number specification (see bit 6
of PBITS), they do not. If the S and D parameters
are allowed, but not specified. their values
default to those stored at DEFSLT ($BE3C) and
DEFDRV ($BE3D). If this bit is set, and no prefix
is active, the name of the volume directory on the
slot S, drive D drive is fetched and used to
create a full pathname whenever a filename or
partial pathname is specified. If a prefix is
active, it will be fetched like this only if an S
or D parameter is actually specified.
bit 1 The F parameter is allowed.
bit 0 The R parameter is allowed.
(One other parameter is always allowed and always parsed: the V (volume) parameter.
BASIC.SYSTEM commands tolerate this parameter but do not use it; it has been
included to maintain compatibility with DOS 3.3 commands that do use it.)
The descriptions for PBITS and PBITS + 1 apply when the corresponding bit is set
to 1. For example, if the command allows a pathname and A and E parameters, the
handler would set PBITS to $01 and PBITS + 1 to $A0. If a pathname is actually
mandatory, bit 2 of PBITS + 1 (the S and D bit) must be set to 1 as well. As indicated
above, this actually serves two purposes: First, it tells BASIC.SYSTEM to automati-
cally create a full pathname if one is not specified, and second, it tells BASIC. SYSTEM a pathname must be specified.
If BASIC.SYSTEM is not to do any parsing, PBITS must be set to 0. Whether or
not the command handler does its own parsing, if the command is found, the subrou-
tine must store the length of the command string minus 1 in XLEN ($BE52), store 0
(the code number for an external command) in XCNUM ($BE53), and then store at
XTRNADDR ($BE50-$BE51) the address control is to pass to after BASIC.SYSTEM
ultimately parses the command line. The latter step must be performed even if the
handler has indicated that no parsing need be performed. Lastly, the carry flag must
be cleared before executing the RTS to return control to BASIC.SYSTEM.
When control returns to BASIC.SYSTEM, the parameters in the command line are
parsed according to the instructions stored in PBITS and PBITS + 1 (if applicable).
The values of the parameters that are actually parsed from the line are stored in a
global page parameter table located from $BE58 to $BE6F (see Table 5-7); if a
Adding Commands to BASIC. SYSTEM 253
Table 5-7 BASIC. SYSTEM parameter table=
location Symbolic Name Meaning
$BE58-$BE59 APARM A (address) parameter
$BE5A-$BE5C BPARM B (byte #) parameter
$BE5D-$BE5E EPARM E (end addr) parameter
$BE5F-$BE60 LPARM L (length) parameter
$BE61 SPARM S (slot) parameter
$BE62 DPARM D (drive) parameter
$BE63-$BE64 FPARM F (field #) parameter
$BE65-$BE66 RPARM R (record #) parameter
$BE67 VPARM V (volume #) parameter
$BE68-$BE69 @PARM @ (line #) parameterb
$BE6A TPARM T (file type code) paramet~
$BE6B SLPARM slot (for IN#, PR#)
$BE6C-$BE6D PATH 1 Pointer to first pathname
$BE6E-$BE6F PATH2 Pointer to second pathname
N0TE5:
~e value associated with a parameter is stored in this table as it is parsed by BASIC.SYSTEM. If $
D parameters are allowed, but not specified, the default values stored at DEFSLT ($BE3C) and
DEFDRV ($BE3D) are transferred to this table.
hA bug in BASIC.SYSTEM (versions I.l and 1.2) causes the V parameter to be stored in @PARM
than VPARM (as shown). This means V and @ cannot be used together on the same command line
because the value of the first parameter specified will be overwritten by the value of the other.
particular parameter is not detected in the parsing operation, its entry in the
stays as it was before the external command was executed. The actual parameters
were successfully parsed are indicated by setting the appropriate bits in
($BE56) and FBITS + 1 ($BE57). (Table 5-7 describes a BASIC.SYSTEM version 1.
and 1.2 bug that hinders the proper parsing of a command line that uses both the
and @ parameters.)
Note that the first pathname parsed from a command line is stored in a
pointed to by VPATH1 ($BE6C) and the second is stored in a buffer pointed to by
VPATH2 ($BE6E). These are the same buffers pointed to by the pathname pointers In
254 System Programs
the MLI parameter tables used by BASIC.SYSTEM's GOSYSTEM ($BE70) subrou-
tine. This means an external command handler can use COSYSTEM to perform MLI
commands without first having to modify these pointers.
After a successful parse, BASIC.SYSTEM jumps to the subroutine whose address is
stored at XTRNADDR ($BE50-$BE51); this is the second half of the external com-
mand handler. This subroutine can actually execute the command (if this wasn't done
in the first half) and then return with a zero in the accumulator and the carry flag clear
if there was no error.
If an error is detected, it can be passed to BASIC.SYSTEM for handling by setting
the carry flag and placing the appropriate error code in the accumulator (the BASIC. SYSTEM error code, not the MLI error code). Alternatively, the command handler
can deal with the error itself if it does, the carry flag must be cleared and the
accumulator set to 0 before returning to BASIC.SYSTEM.
Note that if BASIC.SYSTEM does the parsing, the second part of the command
handler can examine FBITS to determine exactly what parameters were found and
then read their values from the table beginning at $BE58. If some parameters (marked
as optional in PBITS and PBITS + 1) must be specified, the second part of the
command handler can check the appropriate bits of FBITS and FBITS + 1 to ensure
that they are 1; if they're not, an error condition can be flagged by loading the
accumulator with the BASIC.SYSTEM error code (16 for "syntax error") and setting
the carry flag before returning.
The ONLINE Command
In this section, we see how to design and install the handler for a new BASIC. SYSTEM command called ONLINE. This command displays the names of any, or all,
of the disk volumes currently available to the system. ONLINE is useful if you
habitually forget the name of a disk microseconds after putting it into a disk drive.
The syntax of the ONLINE command is
ONLINE [,5,'] [,D#]
where the brackets mean the enclosed parameter (slot number or drive number) is
optional. If a specific slot or drive number is specified, only the name of the volume
for the corresponding disk device is displayed. But if both parameters are omitted, the
volume names for all disk devices are displayed. The ONLINE command can be
typed in while in Applesoft command mode, or it can be executed within a program
using a PRINT CHR$(4);"ONLINE" statement.
Table 5-8 shows the ONLINE installation program, which is executed with the
BRUN command. The first part of the program installs the image of the ONLINE
command handler code that begins at $2100. It first finds a safe spot above HIMEM
to store the image, patches it so that it will execute at this new position, and then
moves the code to its new home. It also links in the command handler by storing its
Adding Commands to BASIC. SYSTEM 255
Table 5-8 Adding the ONLINE command to BASIC.SYSTEM
4
5 * ONLINE [,Sn] [,Dn]
6
7 * Copyright 1985-1988 Gary B. Little
8
9 Last modified: August 26, 1988
10
11
12 SBLOCK EQU $3C Parameters for block move
13 EBLOCK EQU $3E
14 FBLOCK EQU $42
15 HIMEM EQU $73
16
17 IN EQU $200
18
19 EXTRNCMD EQU $BEO6
20 ERROUT EQU $BE09
21 XTRNADDR EQU $BE50
22 XLEN EQU $BE52
23 XCNUM EQU $BE53
24 PBITS EQU $BE54
25 FBITS EQU $BE56
26 VSLOT EQU $BE61
27 VDRIV EQU $BE62
28 GETBUFR EQU $BEF5
29
30 MLI EQU $BFOO
31
32 CROUT EQU $FD8E
33 COUT EQU $FDED
34 MOVE EQU $FE2C
35
36 ORG $2000
37
;Use this as ON_LINE buffer
;Command input buffer
External command JMP opcode
Error handler
Start of external cmd handler
;External cmd name length (-1)
;Command (0 for external)
;Command parameter bits
;Parameters found in parse
Slot parameter specified
;Drive parameter specified
;Get a free space
;Entry point to MLI
;Print a CR
Character output subroutine
Block move subroutine
38 Calculate # of pages that we need to reserve:
39
2000:38 40 SEC
2001: A9 22 41 LDA #>END
2003: E9 21 42 SBC #>CMDCODE
2005: 8D 74 20 43 STA PAGES
2008: EE 74 20 44 INC PAGES
45
20DB: AD 74 20 46 LDA PAGES ;Reserve the pages for the
200E: 20 F5 BE 47 JSR GETBUFR command handler
2011: 90 05 48 BCC INSTALL ;Carry clear if OK
49
2013: A9 DE 50 LDA #14 ;"PRDGRAM TOO LARGE" error
256 System Programs
Table 5-8 Continued
2015: 4C 09 BE
2018: 8D 75 20
201B: AD 07 BE
201E: 8D 26 21
2021: AD 08 BE
2024: 8D 27 21
2027: A9 00
2029: 8D 07 BE
202C: AD 75 20
2O2F: 8D 08 BE
2032: AD 75 20
2035: 8D OF 21
2038: 8D 1A 21
203B: 8D 32 21
2O3E: 8D 49 21
2041: 8D 4E 21
2044: 8D 55 21
2047: 8D 6F 21
204A: 8D 75 21
204D: 8D 8A 21
2050: 8D A4 21
2053: 8D D5 21
2056: A9 00
2058: 85 3C
205A: A9 21
205C: 85 3D
205E: A9 03
2060: 85 3E
2062: A9 22
2064: 85 3F
51 JMP ERROUT
52
53 INSTALL STA PGSTART Save starting page
54
55 * Install the new command handler:
56
57 LDA EXTRNCMD+1 Set up link to
58 STA NEXTCMD+1 existing external command
59 LDA EXTRNCMD+2
60 STA NEXTCMD+2
61
62 ****************************************
63 Install the external command handler
64 by storing its address after the
65 JMP at EXTRNCMD.
66 ****************************************
67
68 LDA #0
69 STA EXTRNCMD+1
70 LDA PGSTART
71 STA EXTRNCMD+2
72
73 * Relocate the code:
74
75 LDA PGSTART ;Get new page
76 STA CMDCODE+$OF
77 STA CMDCODE+$1A
78 STA CMDCODE+$32
79 STA CMDCODE+$49
80 STA CMDCODE+$4E
81 STA CMDCODE+$55
82 STA CMDCODE+$6F
83 STA CMDCODE+$75
84 STA CMDCODE+$8A
85 STA CMDCODE+$A4
86 STA CMDCODE+$D5
87
88 Set up parameters for block move to final location:
89
90 LDA #<CMDCODE
91 STA SBLOCK
92 LDA #>CMDCODE
93 STA SBLOCK+1
94
95 LDA #<END
96 STA EBLOCK
97 LDA #>END
98 STA EBLOCK+1
99
Adding Commands to BASIC. SYSTEM 257
Table 5-8 Continued
206A: AD 75 20 102 LDA PGSTART
206D: 85 43 103 STA FBL0CK+1
104
206F: AD O0 105 LDY #0
2071: 4C 2C FE 106 JMP MOVE Move it!
107
2074: 00 108 PAGES 05 1
2075:00 109 PG5TART 05 1
110
2076: 00 00 00 111 05 $2100~*
2079: 00 00 00 00 00 00 00 00
2081: 00 00 00 00 00 00 00 00
2089: 00 00 00 00 00 00 00 00
2091: 00 00 00 00 00 00 00 00
2099: 00 00 00 00 00 00 00 00
20A1: 00 00 00 00 00 00 00 00
20A9: 00 00 00 00 00 00 00 00
20B1: 00 00 00 00 00 00 00 00
20B9: 00 00 00 00 00 00 00 00
20C1: 00 00 00 00 00 00 00 00
20C9: 00 00 00 00 00 00 00 00
2001: 00 00 00 00 00 00 00 00
2009: 00 00 00 00 00 00 00 00
20E1: 00 00 00 00 00 00 00 00
20E9: 00 00 00 00 00 00 00 00
20F1: 00 00 00 00 00 00 00 00
20F9: 00 00 00 00 00 00 00
112
113 CMDC00E EQU
114
;Length of command handler
Starting page of cmd handler
(Must start on page boundary)
115 ******
- This is the command checker. It
- scans the input buffer to see
- if the command has been entered.
116
117
118
11 * *******
2100:08 120 CLD
2101: AD 00 121 L0Y #0
2103: A2 00 122 L0X #0
2105: BD 00 02 123 CHKCM0 LDA IN,X ;Get command character
2108: E8 124 INX
2109: C9 AD 125 CMP #$A0 Is it a blank?
21D~: F0 F8 126 BEQ CHKCM0 ;If it is, ignore it
2100: 09 EE 21 127 CMP CM0NAME,Y Same as our command?
2110: F0 0B 128 BEQ CHKCMD1 ;Yes, so branch
2112: C9 ED 129 CMP #$E0 Lowercase?
2114: 90 DE 130 BCC N0TF0UND No, so branch
2116: 29 OF 131 AND #$0F ;Convert to uppercase
258 Systein Programs
Table 5-8 Continued
2118: D9 EE 21 132 CMP
211B: DO 07 133 BNE
211D: C8 134 CHKCMD1 1NY
211E: CO 06 135 CPY
2120: DO E3 136 BNE
2122: F0 04 137 BED
138
2124: 38 13~ N0TF0UND SEC
2125: 4C 00 00 140 NEXTCMD JMP
141
2128: 88 142 SETRULES 0EY
2129: 8C 52 BE 143 STY
144
212C: Ag 51 145 LDA
212E: 8D 50 BE 146 STA
2131: A9 21 147 LDA
2133: 8D 51 BE 148 STA
149
2136: A9 00 150 L0A
2138: 80 53 BE 151 STA
152
CMDNAME,Y OK now?
N0TF0UND ;No, so branch
#CMDLEN-CMDNAME ;At end?
CHKCMD ;No, so branch
SETRULES Yes, so branch
Set carry to indicate failure
$0000 ;(Fill in when installed)
XLEN ;Store command length-I
#<EXECUTE Put address of command handler
XTRNADDR into XTRNADDR
#>EXECUTE
XTRNADDR+1
#0
XCNUM ;External cmd number = 0
153 Set up string parsing rules:
154
213B: A9 10 155 LOA #$10 ;Pathname is optional
2130: 8D 54 BE 156 STA PBITS
2140: A9 04 157 LDA #$04 Slot, drive allowed
2142: 80 55 BE 158 STA PBITS+1
159
2145: AS 73 160 LDA HIMEM ;Set ON_LINE buffer (at least
2147: 80 EC 21 161 STA BUFFER 256 bytes) to free area
214A: AS 74 162 LDA HIMEM+1 beginning at HIMEM
214C: 80 ED 21 163 STA BUFFER+1
164
214F: 18 165 CLC
2150:60 166 RTS
167
;Clear carry to indicate success
168 * BASIC.SYSTEM comes here after it has
169 successfully parsed the command line:
170
2151: A9 00 171 EXECUTE LDA #0
2153: 8D EB 21 172 STA UNITNUM (Assume all volumes)
2156: AD 57 BE 173 LDA FBITS+1 Examine result of parse
2159: 29 04 174 AND #$04 Slot, drive specified?
215B: FO 13 175 BEQ DOCALL ;No, so check everything
2150: AD 61 BE 176 LDA VSL0T Get slot # specified
2160:0A 177 ASL
2161:0A 178 ASL
2162:0A 179 ASL
2163: 0A 180 ASL Slot 16
Adding Comnjcinds to BASIC. SYSTEM 259
Table 5-8 Continued
2169: DO 02 183 BNE SAVEUN
216B: 09 80 184 0RA #$80
216D: 8D EB 21 185 SAVEUN STA UNITNUM
186
2170: 20 00 BF 187 D0CALL JSR MLI
2173: C5 188 DFB $C5
2174: EA 21 189 DA 0LPARM
190
2176: 20 8E FD 191 JSR CR0UT
2179: A0 00 192 LDY #0
217B: 98 193 SCAN TYA
217C: 48 194 PHA
217D: B1 73 195 LDA (HIMEM),Y
217F: F0 61 196 BEQ SCAN2
2181: 29 OF 197 AND #$0F
2183: F0 4E 198 BEQ NEXTNAME
2185:48 199 PHA
200
2186: A2 00 201 LDX #0
2188: BD F4 21 202 PRTMSG1 LDA SL0TMSG,X
218B: FO 06 203 BEQ PRTNUM1
218D: 20 ED FD 204 JSR C0UT
2190: E8 205 INX
2191: DO F5 206 BNE PRTMSG1
207
2193: B1 73 208 PRTNUM1 LDA (HIMEM),Y
2195: 29 70 209 AND #$70
2197:4A 210 LSR
2198:4A 211 LSR
2199:4A 212 LSR
219A: 4A 213 LSR
219B: 09 BO 214 ORA #$BO
219D: 20 ED FD 215 JSR COUT
216
21A0: A2 00 217 LDX #0
;Drive 2?
;No, so branch
Set "drive 2" bit
;Store slot, drive as unit num
ON_LINE call
;Address of parm table
;Get slot, drive + length
;If $00, then all done
Isolate length bits
;If 0, then must be error
;Print slot
;Get slot, drive + length
Isolate slot bits
;We now have slot
;Convert to ASCII digit
21A2: BD FA 21 218 PRTMSG2 LDA DRIVEMSG,X ;Print drive #
21A5: FO 06 219 BEQ PRTNUM2
21A7: 20 ED FD 220 JSR COUT
21AA: E8 221 INX
21AB: DO F5 222 BNE PRTMSG2
223
21AD: A2 B1 224 PRTNUM2 LDX #$B1 ;Assume drive 1
21AF: B1 73 225 LDA (HIMEM),Y
21B1: 10 02 226 BPL PSKIP Branch if drive 1
21B3: A2 B2 227 LDX #$B2 Must be drive 2
21BS: 8A 228 PSKIP TXA
21B6: 20 ED FD 229 JSR COUT
260 System I'i'ogranrs
Table 5-8 Continued
21B9: A9 BA 230 LDA #":
21BB: 20 ED FD 231 JSR C0UT
21BE: A9 A0 232 LDA #$A0
21C0: 20 ED FD 233 JSR C0UT
234
21C3: 68 235 PLA
21C4: AA 236 TAX
21C5: C8 237 PRTNAME INY
21C6: B1 73 238 LDA (HIMEM).Y Get next character in name
21C8: 09 80 239 0RA #$80 ;Set high bit
21CA: 20 ED FD 240 JSR C0UT and display it
21CD: CA 241 DEX
21CE: DO F5 242 BNE PRTNAME ;Branch until done
21D0: 20 8E FD 243 JSR CROUT
244
21D3: AD EB 21 245 NEXTNAME LDA UNITNUM Was only one volume specified?
21D6: DO 0A 246 BNE SCAN2 Yes, so branch
247
21D8: 68 248 PLA
21D9: 18 249 CLC
21DA: 69 10 250 ADC #16 ;Move to next name
21DC: A8 251 TAY
21DD: CO ED 252 CPY #224 At end of table?
21DF: DO 9A 253 BNE SCAN ;No, so branch
21E1: 48 254 PHA
255
21E2: 68 256 SCAN2 PLA
21E3: 20 8E FD 257 JSR CR0UT
21E6: 18 258 CLC ;CLC ==> no error
21E7: A9 00 259 LDA #0 ;Error code = 0
21E9: 60 260 RTS
261
21EA: 02 262 0LPARM DFB 2 ;Two parameters
21EB: 00 263 UNITNUM DFB 0 ;Unit number (05550000)
21EC: 00 00 264 BUFFER DA $0000 ;Device buffer
265
21EE: CF CE CC 266 CMDNAME ASC "ONLINE" External command name
21F1: C9 CE C5
267 CMDLEN EQU
268
21F4: 03 CC CF 269 SLOTMSG ASC "SLOT ".00
21F7: 04 AD DO
21FA: AC AD C4 270 DRIVEMSG ASC ", DRIVE ",00
21FD: 02 C9 D6 C5 AD 00
271
272 END EQU
Adding Commands to BASIC. SYSTEM 261
starting address at EXTRNCMD + 1 ($BE07) a"d EhTRNCMD + 2 ($
just in case another user con,n,and handler has already been installed, it
address previously stored in EhTRNCMD + 1 and E~TRNCMD + 2 and
the target address of a JMP instruction in the body of the ONLINE con,,i,aiid
This JMP is executed only if the ONLINE handler doesn't recognize the
passed to it. This nieans control always daisy-chains down to a previously
external coii,niai'd handler so that it will have a chance to clain, the con,tiiaiid.
The GETBUFR ($BEF5) subroutine is used to locate a "safe" buffer large
to store the command handler. It is called with the number of pages required
accumulator (1). If we run out of room, the carry flag will be set, and a "pr
large" error message will be printed by calling ERROUT ($BE09). Othei~ise,
memory page is, the block freed up will be returned in the accumulator. A>
earlier in the chapter, we can now use this block to store a prograni without
later being overwritten by file buffers or string variables.
Since the ONLINE command handler is not inherently relocatable, all
to internal absolute addresses must be altered to reflect the change in the
the code. The relocation procedure is relatively simple in our example bee
code fur the command handler was assembled on a page boundary, and it is
moved to another page boundary. This means only the high-order part
absolute address in the handler need be modified. Although it is possible to
complex subroutine to antomatically patch the code, we chose to "manuallv"
by inspecting the handler to identify addresses to be changed and then
new page number at these positions. If you change the handler in any way,
have to recalculate which addresses must be patched and make the necessarv
to the installation code.
The code is moved into place by using the system Monitor block move
MOVE ($FEC2). This subroutine moves the block of memory beginning at
address stored in $3C-$3D and ending at the address stored in $3E-$3F to the'
beginning at the address stored in $42-$43. MOVE must be called with the Y
set to zero.
The main part of the ONLINE command handler begins at CMDCODE. The
thing it does is check if the ASCII codes for the word "ONLINE" or "onlsne
the beginning of the input buffer at $200 (intervening spaces are ignored). If uot,
carry flag is set (indicating not handled), and the jutnp at NEXTCMD is
explained above, this gives a previously installed command handler a crack at
fying the command.
If the "ONLINE" command is detected, the length of the command (minus
stored at XLEN ($BE52); the external command number (0) is stored at XCN1
($BE53); and the address of the postparsing subroutine, EXECUTE, is stored
XTRNADDR ($BE50) and XTRNADDR + 1 ($BE51). Finally, the parsing rules
stored in PBITS ($BE54) and PBITS + 1 ($BE55): pathname optional, slot and
allowed. The pathname optional bit must be set because the ONLINE command
262 Systcin I'cogi'ains