ranger@ecsvax.UUCP (05/07/87)
Apple II ProD TN #6: BASIC.SYSTEM External Commands Written: 1/85 Modified by: Pete McDonald 12/85 BASIC.SYSTEM has a facility that allows a user to attach his own commands to the existing commands that BASIC.SYSTEM implements. Once you attach a command, your command will be treated as if it was one of the BASIC.SYSTEM commands (with its own commands having preference). Therefore the command will execute in immediate and deferred modes as does the CATALOG command. In immediate mode all you must do to execute the command is type it in. In deferred mode (eg. from within a program), to access the command you must preface the command with a PRINT CHR$(4). Whenever BASIC.SYSTEM receives a command, it first checks its command list for a match. If the command is not recognized, BASIC.SYSTEM then sends the command out to the external command handlers (if any are connected). Finally, if no external command handler has recognized the command, BASIC.SYSTEM passes control to Applesoft which will return an error if the command is not recognized. If you find regular need for an additional command, you can write your own command handler and attach it to BASIC.SYSTEM through the EXTRNCMD jump vector. To do this, you must first save off the current EXTRNCMD vector (to JMP to if the command is not yours), and install the address of your routine in EXTRNCMD+1 and +2 (lo-byte first). There are essentially three functions that your routine must perform: (1) It must check for the presence of your command(s) by inpecting the GETLN input buffer. If it is not your command, you must set the carry (SEC) and JMP to the initial EXTRNCMD vector you saved off to continue the search. (2) If it is your command, you must let BASIC.SYSTEM know. You must zero XCNUM ($BE53) to indicate an external command and set XLEN ($BE52) equal to the length of your command string minus one. If there are no associated parameters (such as slot, drive, A$, etc.) to parse, you must set all 16 parameter bits in PBITS ($BE54,$BE55) to zero. And, if you're going to handle everything yourself before returning control to BASIC.SYSTEM you must point XTRNADDR ($BE50,$BE51) at an RTS instruction...XRETURN ($BE9E) is a good location. Now just "fall through" to your execution routines (3). If there are parameters to parse, it is easiest to let BASIC.SYSTEM parse them for you (unless you want to use some parameters that BASIC.SYSTEM doesn't use). By setting up the bits in PBITS ($BE54,$BE55), and setting XTRNADDR ($BE50,$BE51) equal to the location where execution of your command begins, you can return control to BASIC.SYSTEM, with an RTS, and let it parse and verify the parameters and return them to you in the global page. (3) It must execute the desired instructions expected of the command and should RTS with the carry cleared. NOTE: The facility to have BASIC.SYSTEM parse your external command parameters was initially intended for only its own use. It turns out that not all the parameters can be parsed separately. The low byte of 'PBITS' ($BE54) must have a non-zero value in it to have the BASIC.SYSTEM parse parameters. THIS MEANS THAT REGARDLESS OF WHAT PARAMETERS YOU NEED PARSED, YOU MUST ALSO ELECT TO OPTIONALLY PARSE SOME PARAMETER SPECIFIED BY THE LOW BYTE OF PBITS.(eg. Set PBITS to $10, filename optional, and this parameter need not be known by the user.) Attached are two example routines, BEEP and BEEPSLOT which can reside together as external commands. BEEP handles everything itself and BEEPSLOT will let you pass a slot & drive parameter (,S#,D#), where the drive is ignored. Suggestion: Save the EXTRNCMD address on entry in your routine AS IF there already was an external command attached. This will create a linked list of external commands in which the first command asking to be installed will be the last one asked to see if it's his command. Of course if you don't know the loading address of the other command's code, you may overwrite it. The problem of where external commands are stored in memory is left up to your own discretion (See Tech Note #9 for buffer allocation above HIMEM).