In This Issue...
Bag of Tricks 2
You've been asking when Bag of Tricks, that very popular and useful disk utility package, will be updated for ProDOS. Well, you can relax now: it's here.
The new ZAP program in "Bag of Tricks 2" adds the ability to access ProDOS blocks, directories, and files; the 80-column display can show most of a block at one view. The new version of FIXCAT can reconstruct a blown ProDOS directory, as far as is possible. You do still need to follow up with ZAP to correct things like file size and load address, which completely disappear when a directory is damaged.
This new, non-copy-protected edition of an old friend costs $49.95, or $45 + shipping from S-C. Owners of the older Bag of Tricks can get an upgrade directly from Quality Software for only $20 by returning your original disk.
Correction to Day of Week Programs
On page 20 of the December 1985 AAL, change lines 130 and 140 to the following: 130 FOR I=0 TO 11 : READ MD(I) : NEXT 140 FOR I=0 TO 6 : READ D$(I) : NEXT
On page 24, same issue, change line 120 to: 120 FOR I=0 TO 6 : READ D$(I) : NEXT
That's what we get for typing a program into the Word Processor rather than printing a LISTing!
WildCAT is a series of patches to DOS 3.3 which modify the CATALOG command. The new features include:
Lee Reynold's FILEDUMP command has been re-packaged and re-presented as TYPE (see Call-A.P.P.L.E. 6/82 p47). More on this later. WildCAT, along with TYPE, is an attempt to teach new tricks to an old dog, as it were.
The normal DOS CATALOG command allows slot, drive, and volume parameters. I have added a filename parameter, but process it a little differently than the way file names are usually processed. To display the catalog entries for all files whose names contain a particular string, type any of the following:
CATALOG ^string [,Dn] [,Sn] [,Vn] DIR ^string [,Dn] [,Sn] [,Vn] CAT ^string [,Dn] [,Sn] [,Vn]
where "^string" begins with the "^" or caret symbol (shifted N on the ][+ or shifted 6 on the //e or //c); the string should contain no blanks, although it may "end" with them; the string would normally end with a carriage return or with a comma if a drive or slot number is specified. Only those files that contain the "string" somewhere in the filename will be listed. (Of course you already know that the D, S, and V parameters are shown in brackets above because they are optional; you do not type the brackets.)
For example, "CATALOG ^TEST" would list each file with 'TEST' as part of the filename; while "DIR ^PAY." would list those with 'PAY.' somewhere in the filename; and "CAT^.OBJ,D2" would list filenames on drive 2 that contain the partial string '.OBJ'. "CAT" and "DIR" are simply synonyms for "CATALOG".
I have also arranged things so you can list the catalog entries of a specified file-type. You simply type the file type code in the CATALOG command:
CATALOG t [,Dn] [,Sn] [,Vn] DIR t [,Dn] [,Sn] [,Vn] CAT t [,Dn] [,Sn] [,Vn]
where "t" is any of the unadorned, single-letter filetypes: A B I R S T. Only that type of file (if present) will be listed.
For example, "CATALOG T" would list all the text files; "DIR A,D2" would list all of the Applesoft files on drive 2; "CAT B,S5,D1" would list all the binary files on slot 5, drive 1. Yes, "DIRT" works just fine.
I added the TYPE command, which allows you to display the contents of text files. Both CATALOG and TYPE will optionally:
You can slow down TYPE's output via SPEED=xx or POKE 241,xx; or pause by pressing any key; then Ctrl-Q to abort. Also, TYPE pauses and waits for a keypress when it encounters a hex 00 imbedded in the file or at end of file; press Ctrl-Q to quit. You may TYPE random text files by holding down REPT-SPACE to get past the hex 00's at the end of each logical record.
The listing that follows is intended for information only: it is not BRUNable. My intention is that you prepare the EXEC shown below to actually install the patches. Any word processor that produces a straight, sequential text file may be used to prepare the EXEC. Of course you can also use the S-C Macro Assembler for this purpose. Then, type EXEC WILDCAT to apply the patches to DOS 3.3 in memory. After checking it out and running any other tests you like, put in a new diskette, enter a HELLO program, and type INIT HELLO to "permanently" install WildCAT in the DOS on tracks 0, 1, and 2.
When I wrote WildCAT, I had two main goals in mind: it should be a (mostly in-place) code replacement, and it should be compatible with the known means of using (abusing?) the existing CATALOG code at $AD98-AE69.
One major design consideration was a mechanism for entering the ^string/type parameter. This required merely changing the "keyword parameter table" so CATALOG could have a "filename".
Next, a distinction had to be made between a "wildcard" and a "filetype" parameter. It made sense to 'delimit' the wildcard string; then the single-character filetype would be just that: a single character, entered without a delimiter. But this "phony" name mechanism has it's own problems:
First, "What's in a Name?" (DOS Manual p. 16): a filename has to start with a letter...which automatically eliminates most special characters (eg, equal, pound, slash, colon, etc) as the delimiter. The command parsing routine doesn't really know what it's working on at the time. All it knows is: if a name may be present, it must be valid. The validity test is only that the first character be equal to or greater that $C0 or an @-sign. The @-sign could have been used, but it's a problem on some 80-column boards; the ^ or caret works nicely (and besides, it looks good).
Second, now that we have a name (however, phony) and since the CATALOG command lives in the File Manager (FM) portion of DOS, there will be a buffer allocated for it. Unfortunately, the Command Interpreter (CI) DOCAT routine, which calls the FM, already "knows" that there will not really be a name, so it does not include housekeeping code to deallocate a buffer. So merrily allocating files without closing them...after the third time: NO BUFFERS AVAILABLE. And naively adding CLOSE (even if there were room for it), would have one very undesirable side effect if a "regular" catalog were requested: CATALOG-CLOSE without FNAME will close all open files. WildCAT instead plays a little shell game with DOS: The new DOCAT routine saves the first character of FNAME and substitutes a zero. Thereafter, neither the File Manager nor the rest of DOS ever knows that a name has been entered, so FM never actually allocates a buffer.
Third, what really should happen if a phony name is not entered? A regular catalog, of course, but how would this be indicated to WildCAT? Well, the shell game has a sting. Early on when the CI PARSE routine discovers that a filename is a valid parameter, it first clears FNAME to all blanks, expecting to fill it in with whatever comes in next. If a comma or carriage return comes in next, then FNAME still contains the blank; and that's what WildCAT saves off (under the shell) before it substitutes the zero.
Thus, the "sting" is that the CI "tricks" itself into telling WildCAT what to do in the absence of a ^string/type specifier: WildCAT takes a blank to indicate "do a regular" catalog; just as positively as a "^" indicates "do a wildcard" catalog, and a single character indicates "do a filetype" catalog.
The blank indicator also helps satisfy the second goal above and solves the problem of compatibilty with the "known means" of using/abusing the existing CATALOG code. WildCAT simply has to put a blank under the shell at each of the points where the code could most reasonably be entered without going thru the Command Interpreter's new DOCAT routine. That's exactly what all the JSR's to the routine AllowENTry are doing.
Satisfying that second goal takes up a lot of space, however; and has somewhat undermined the first constraint: WildCAT certainly isn't "in-place" in one place! And I apologize for this rather bizarre, serpentine code; I do hope that now you understand why some things were done the way they were.
Although considerable effort was spent to maintain compatibilty with the existing DOS commands, there were some compromises:
1. While the DOS manual (page 22) states: "To specify drive 1, you use the notation D1 separated from the file name by a comma", you can in fact leave out the comma between CATALOG and D1. With WildCAT that comma is now required; otherwise, it would take the "D" as a filetype and try to find it ... which of course it wouldn't and there would be no files reported. This would also be a problem for Applesoft programs that do something like: PRINT D$"CATALOG D1" without the comma. Therefore, WildCAT issues a (late) "SYNTAX ERROR" message if it encounters an undelimited string of length 2 or more.
2. CATALOG is a favorite routine to execute directly, bypassing the DOS Command Interpreter. FID, for example, provides its CATALOG via the "external" entry to the File Manager, which means that the main entry at CATHNDLR must provide for a "regular" catalog. It is also possible from machine language, however, to bypass both the CI and the FM. This usually involves changing the exit JMP address at DONEXT2 (to return to the user's code) and then jumping directly into almost anywhere in the CATALOG code (see the Listing 1 labels that begin "at"). I believe most of these cases are covered, but you may find some programs, which provide an "internal" CATALOG, that just won't work with WildCAT.
3. In order to both gain some patch space and provide the DIR/CAT short-form command name, the DOS command POSITION was eliminated. You may have to look it up just to find out that it is, much less what it is. Its relative rarity may be due to its implementation: it, like APPEND, finds its way through the file one byte at a time...all day long. Any program that uses it will now get a syntax error. If POSITION is really needed, it can be readily simulated by programming a read-loop to discard N-1 fields before processing the desired Nth field.
The following is a brief commentary on the assembly listing. The paragraph numbers correspond to numbers in comment lines.
The page zero locations I used ($EB thru $EF) are free, i.e. not used by DOS, the Monitor, or the Basics.
(1) In CMDTBL, replace Integer CHAIN address with TYPE and DOCAT address with NewDOCAT.
(2) Rearrange some code (and change both references to it) to add a "print blank" capability. The Command Interpreter uses its own vector to a "COUT" routine via CSW at $36; however, the File Manager (previously) used the Monitor COUT and CROUT routines for printing the catalog. With WildCAT all of DOS now consistently uses the vector at $9FCA for output; plus it has a new BlankOUT routine, all within the original code space.
(3) Recode a very cumbersome form of the "indexed indirect jump" to use register Y and leave X (which is zero by a previous operation) so it can be used in NewDOCAT.
(4) Replace old DOCAT's 12 bytes of code with a JMP to NewDOCAT and use the remainder to space over to column 7 after the file length has been displayed.
(5) NewDOCAT saves the first character of FNAME and substitutes a zero to prevent buffer allocation. It then loads 13, the new Catalog Function Code, and proceeds to CMDHNDLR2. Function 13 enters the catalog code past the "allow for irregular, direct entry".
(6) In the keyword parameter table, change parms to allow a filename with CATALOG and a filename, drive, and slot with DIR. Set new Function 13 address (previously a "no-op" to NOERROR) to WildCAT and change the range check to 14 to allow for it.
(7) Replace the Integer CHAIN code; PrtLOCK displays an asterisk or blank if the file is locked or not.
(8) Shorten the "NO BUFFERS AVAILABLE" message to "NO BUFFER" and re-use the space to decide which Basic is active, then JMP to the appropriate decimal print routine; used to print the free sector value and catalog filesizes. The value to be printed has been previously loaded into A and X.
(9) First, eliminate the need for "NOT DIRECT COMMAND" error message and then re-use the space to check for a "regular" catalog (no filename) or for a catalog by filetype (undelimited, single character). If more than a single, non-blank character is detected (ie, 2nd byte of FNAME is not blank), then "SYNTAX ERROR" message is issued.
(10) At beginning of catalog code allow for most normal points where the code could be directly entered. The new "official" Function 13, WildCAT initializes the FM workarea (per normal) and branches to Read VTOC to "find" the first catalog sector.
(11) Freespace "prolog"; clear carry and branch around another likely "irregular" entry point. Read first/next catalog sector, then lookup and save the filetype. Setup Y with 30 for name length and branch to CkFNAME.
(12) AllowVTOC fakes a "regular" catalog and falls into a JSR to read the VTOC. The BCC to initialize linecount is always taken; only if there had been an I/O error would the carry be set, in which case, control would have passed to the error-message-print exit anyway.
(13) PrtCat displays a catalog line. Note that loc $24, CH, is "POKEd" with 7 for uniform spacing over to the filename. If your printer interface board or 80-column card do not support this convention, then the display will not be properly spaced. The DONEXT routine is unchanged. SKIPLN has been re-arranged to allow init linecount, put out a carriage return, and check for a keypress (Ctrl-Q to quit) after 22 lines. Note: This leaves the cursor in column 37; see below.
(14) CkFNAME "looks under the shell" to figure out what to do. A caret indicates to check for a wildcard string. After JSR to CkCAT, if the equal status is set, then branch to print the catalog line. DoWild checks for the occurence of the wildcard string within the filename. $B4C9,X indexes the name in the Catalog Sector; $AA75,Y indexes the wildcard string; CatNmLen counts from 30 to 0, to scan the whole name.
(15) FreeSpce counts the free sectors, as indicated by the VTOC, loads X and A with the count, and JMPs ToPrtDec.
(16) WaitCk79 provides the "wait" for TYPE; also checks and puts out a carriage return after 79 characters to avoid overprinting long lines on certain printers, such as the MX-80.
(17) TYPE displays the contents of a sequential or random text file. A keypress will pause the display, and Ctrl-Q quits.
(18) InvCOUT is used by both CATALOG and TYPE. It converts hi-bit off characters to proper inverse. It will optionally show control characters as inverse or allow them to "function" as-is; and it will optionally "shift" lower case letters to upper case, if you do not have a lower case adapter; see "...Options" above. Loc $EA, decimal 234, is the Applesoft Hi-Res collision counter; it should always be zero, unless you POKE it.
(19) WaitCQ waits for a keypress and sets the equal status, if Ctrl-Q was pressed.
(20) Replace the inverted phrase DISK VOLUME with FREE SPACE=.
(21) The DOSCMDS list is moved down 6 bytes. AllowENT re-uses these 6 bytes to force a blank in FName1 "under the shell" to ease "irregular" entries into the catalog code; and clears the carry in case the entry was 'atADC9' which also cleared the carry. In the command list, TYPE replaces CHAIN and DIR replaces POSITION; change $A8BF:43 41 D4 to replace with CAT.
(22) Change the two references to DOSCMDS to the new location. These two changes must be done last as the EXEC is changing the very code that is executing.
I would like to thank Lee Reynolds and Art Schumer for their helpful comments and suggestions.
1000 *SAVE S.WILDCAT 1010 *-------------------------------- 1020 CatLnCnt .EQ $EB Catalog Linecount 1030 FType .EQ $EC Hold looked-up filetype 1040 FName1 .EQ $EE Hold FNAME shell 1st char 1050 CatNmLen .EQ $ED CatName check-length=30 1060 CatPtLen .EQ $EF CatName print-length=30 1070 *-----(1)---- 1080 .PH $9D26 In CMDTBL, command addresses, 1090 .DA TYPE-1 change Integer CHAIN to TYPE 1100 .PH $9D3E In CMDTBL, change address to 1110 .DA NewDOCAT-1 new DOCAT in POSITION code 1120 *-----(2)---- 1130 .PH $9FA8 In ECHO, change old COUT ref 1140 .DA #$CA was JSR $9FC5 now JSR $9FCA 1150 .PH $9FC5 Cleanup CDI COUT and CROUT 1160 BlankOUT LDA #" " and add BLANK out routine 1170 .DA #$2C fake BIT-NOP on fall-thru 1180 CROUT LDA #$8D DOS vectored CROUT; same loc 1190 COUT JMP ($36) DOS vectored COUT; new loc 1200 .PH $A710 In PRTERROR, change old COUT 1210 .DA #$CA was JSR $9FC5 now JSR $9FCA 1220 *-----(3)---- 1230 .PH $A186 Cleanup DOCMD; X=0 in NewDOCAT 1240 LDY $AA5F CMDINDX 1250 LDA $9D1F,Y CMDTBL+1; use Y instead of X 1260 PHA 1270 LDA $9D1E,Y CMDTBL 1280 PHA 1290 RTS 1300 NOP 1310 *-----(4)---- 1320 .PH $A56E Replace old DOCAT code: 1330 OldDOCAT JMP NewDOCAT To allow for direct entry 1340 PrtTYPE LDA FType Print looked-up filetype 1350 JSR COUT and 1360 JMP BlankOUT a blank 1370 NOP 1380 *-----(5)---- 1390 .PH $A5DD Replace old POSITION code: 1400 NewDOCAT LDA $AA75 FNAME set by CATALOG command 1410 STA FName1 save first byte, then zero 1420 STX $AA75 to avoid buffer allocation 1430 LDA #13 FM WildCAT Function Code 1440 JMP $A2AA CMDHNDL2 routine, per usual 1450 NOP 1460 *-----(6)---- 1470 .PH $A921 DIR [string] [,Dn] [,Sn] 1480 .DA #$60,$70 ->First comma: is NOT optional 1490 .PH $A929 CATALOG [string] <[,Dn] [,Sn]> 1500 .DA #$60 ->Must be CATALOG,D1 or DIR,D2 1510 .PH $AAE3 In FM function table, "borrow" 1520 .DA WildCAT-1 otherwise useless address 1530 .PH $AB10 Change range check from 13 for 1540 CMP #14 above now USEFULL address 1550 *-----(7)---- 1560 .PH $A4F0 Replace Integer CHAIN code 1570 PrtLOCK LDA #" " blank=unlocked 1580 LDX $B4C8,Y Catalog Filetype entry 1590 BPL ToPrint 1600 LDA #"*" *=locked 1610 ToPrint JMP COUT Print " " or "*" indicator 1620 *-----(8)---- 1630 .PH $A9FD Shorten NO BUFFER[S AVAILABLE] 1640 .AS -"R" to free 11 bytes for ToPrtDec: 1650 ToPrtDec BIT $E006 Check which Basic... 1660 BMI ToInt Integer or 1670 JMP $ED24 Applesoft; use appropriate 1680 ToInt JMP $E51B print decimal routine 1690 *-----(9)---- 1700 .PH $A021 Replace JSR ISBASRUN to allow 1710 NOP ALL commands entered direct 1720 NOP then error msg is redundant so 1730 NOP ok to re-use msg space below 1740 .PH $AA2C Replace NOT DIRECT COMMAND msg 1750 CkCAT CMP #" " If blank, do regular catalog 1760 BEQ ToRTS 1770 LDY #" " Must be single-char filetype 1780 CPY $AA76 FNAME+1, ie blank afterwards 1790 BEQ CkType if catalog by filetype; else 1800 JMP $A6C4 CSYNTAX error 1810 CkType CMP FType Does filetype match? 1820 ToRTS RTS 1830 NOP 1840 NOP 1850 *----(10)---- 1860 .PH $AD98 1870 CATHNDLR JSR AllowENT Allow for non-CDI entry 1880 WildCAT JSR $ABDC Init File Manager Workarea 1890 BNE ToRWVTOC 1900 atADA0 JMP AlowVTOC Allow for non-CDI entry 1910 atADA3 NOP Allow for non-CDI entry and 1920 NOP alignment 1930 atADA5 JSR AllowENT Allow for non-CDI entry 1940 atADA8 JSR AllowENT Allow for non-CDI entry 1950 atADAB JSR InitCR Init Linecount; output C/R 1960 *----(11)---- 1970 JSR SKIPLN 1980 LDX #12 1990 PrtFreSP LDA FreeMsg-1,X 2000 JSR COUT Print " FREE SPACE=" 2010 DEX 2020 BNE PrtFreSP X=0 for PrtFreSP 2030 JSR FreeSpce Count & print free sectors 2040 JSR SKIPLN 2050 JSR SKIPLN 2060 CLC Setup for RDNXTDIR to read 2070 BCC RDNXTDIR first sector; always branch 2080 NOP alignment 2090 atADC9 JSR AllowENT Allow non-CDI, non-FM entry 2100 RDNXTDIR JSR $B011 RDDIRSEC 2110 BCS DONEXT2 2120 LDX #0 2130 GTRKNUM STX $B39C DIRINDX 2140 LDA $B4C6,X Track part of T/S list 2150 BEQ DONEXT2 If End of Catalog, then exit 2160 BMI DONEXT If Deleted File, then skip it 2170 LDA $B4C8,X Catalog Filetype 2180 ASL ;skip hi-bit LOCK/UNLOCK flag 2190 LDY #7 2200 FindTYPE ASL 2210 BCS GotTYPE 2220 DEY 2230 BNE FindTYPE 2240 GotTYPE LDA $B3A7,Y From filetype table, 2250 STA FType save looked-up filetype 2260 LDY #30 Check CatName length and 2270 STY CatPtLen Print CatName length 2280 BNE CkFNAME always BNE 2290 *----(12)---- 2300 AlowVTOC JSR AllowENT Allow for non-CDI entry 2310 ToRWVTOC JSR $AFF7 RWVTOC read VTOC 2320 BCC atADAB always; carry set=I/O ERROR 2330 *----(13)---- 2340 NOP ;alignment 2350 NOP 2360 PrtCAT LDY $B39C Restore Y from DIRINDX 2370 JSR PrtLOCK Print Lock indicator 2380 JSR PrtTYPE Print filetype and BlankOUT 2390 LDX $B4E7,Y Filesize 2400 LDA $B4E8,Y Filesize+1 2410 JSR ToPrtDec Print "true" filesize 2420 LDY #7 "Poke" CH with 7 to "tab" 2430 STY $24 over for filename spacing 2440 LDX $B39C Restore X from DIRINDX 2450 PrtFN LDA $B4C9,X Print Catalog Filename 2460 JSR InvCOUT with optional conversions 2470 INX 2480 DEC CatPtLen CatName print length 2490 BNE PrtFN 2500 JSR SKIPLN 2510 DONEXT JSR $B230 NXTDIREN...atAE25 2520 BCC GTRKNUM 2530 BCS RDNXTDIR 2540 DONEXT2 JMP $B37F NOERROR....atAE2C 2550 SKIPLN DEC CatLnCnt Linecount..atAE2F 2560 BNE ToCR If not zero, C/R & return 2570 JSR WaitCQ else wait for keypress 2580 BEQ DONEXT2 If Ctrl-Q, exit to NOERROR 2590 InitCR LDA #22-1 else setup for next 22 lines 2600 STA CatLnCnt in line count 2610 ToCR JMP CROUT DOS vectored C/R out 2620 *----(14)---- 2630 CkFNAME LDA FName1 Holds FNAME first character 2640 CMP #"^" Wildcard string? 2650 BEQ DoWild yes...maybe 2660 JSR CkCAT Regular or by filetype? 2670 BEQ PrtCAT yes...else 2680 BNE DONEXT none of the above 2690 DoWild STY CatNmLen CatName length=30, for NotEQ 2700 LDY #1 Decr'd to 0; indexes FNAME 2710 NotEQ DEC CatNmLen Checked all 30 chars? 2720 BMI DONEXT Yes; no match, do next CatName 2730 BackDown DEX Backdown to string match start 2740 DEY Backdown to 0, ie. FNAME start 2750 BNE BackDown 2760 YesEQ INY First Y=1, then on past "^" 2770 INX 2780 LDA $AA75,Y FNAME 2790 CMP #" " If blank then wildcard EOS and 2800 BEQ PrtCAT still =, so we have a match! 2810 CMP $B4C9,X FNAME = CatName? 2820 BEQ YesEQ 2830 INX No, setup X to backdown 1 past 2840 BNE NotEQ string match start; always BNE 2850 NOP 2860 *----(15)---- 2870 .PH $BA69 Catalog Free Space Patch 2880 FreeSpce STX $44 X=0 2890 STX $45 Init Free Sec Count var 2900 LDY #50*4 VTOC entries * entry length 2910 NxBitMap LDA $B3F2,Y BITMAP-1 in VTOC buffer 2920 CkFree ASL ;shift hi-order bit into CARRY 2930 BCC CkMore In use, so check if any more 2940 INC $44 Incr free sector count 2950 BNE CkFree Zero means > 255, so 2960 INC $45 incr "page" part of word 2970 CkMore BNE CkFree More bits in same byte? 2980 DEY decr index to next VTOC byte 2990 BNE NxBitMap All done? 3000 LDX $44 Yes, so setup count in X & A 3010 LDA $45 for decimal print via 3020 JMP ToPrtDec one of the BASICs 3030 *----(16)---- 3040 WaitCk79 JSR $FCA8 Monitor WAIT routine 3050 DEC $55 Decr char cnt 3060 BNE $BA10 Fortuitous RTS; else fall thru 3070 InitLine LDA #79 TYPE prolog/setup 3080 STA $55 Init printer 80-col char cnt 3090 JMP CROUT 3100 NOP 3110 *----(17)---- 3120 .PH $B6B3 3130 TYPE JSR $A2A3 DOS Open file 3140 DoInitLn JSR InitLine Init char cnt & CROUT 3150 ToRead JSR $A68C DOS Read char 3160 BEQ ToWaitCQ EOF maybe...Ctrl-Q quit? 3170 CMP #$8D Carriage return? 3180 BEQ DoInitLn Yes, handle immediately 3190 JSR InvCOUT Optional Ctrls & Hibit=0 INV 3200 LDA $F1 Applesoft SPEED=nn byte 3210 JSR WaitCk79 Wait SPEED; 79 chars yet? 3220 LDA $C000 Has a key been pressed? 3230 BPL ToRead No, read on 3240 STA $C010 Reset keyboard strobe 3250 ToWaitCQ JSR WaitCQ Wait keypress, check Ctrl-Q? 3260 BNE ToRead If not Ctrl-Q, read on 3270 JMP $A2FC DOS Close, Deallocate, Exit 3280 *----(18)---- 3290 InvCOUT TAY If < $80, then hibit off 3300 BPL SetINV so set inverse flag & convert 3310 CMP #$A0 Ctrl-char? 3320 BCS CkLoCase No 3330 BIT $EA Usually, loc 234 contains 0: 3340 BMI CkLoCase POKE 234,255 skips conversion 3350 SetINV LSR $32 Set Inverse by shifting 0 into 3360 LSR $32 INVFLG first 2 bits; set carry 3370 AND #$3F Turn off 1st 2 bits maps down 3380 ADC #$1F maps up into hibit-on part of 3390 EOR #$E0 upper-case screen-char range 3400 CkLoCase CMP #$E0 Lower-case? 3410 BCC ToCOUT No; but POKE -18700,223 or 3420 AND #$FF B6F4:DF shifts l.c. to U.C. 3430 ToCOUT JSR COUT DOS vectored COUT 3440 LDA #$FF 3450 STA $32 Set normal video; always 3460 RTS 3470 *----(19)---- 3480 .PH $B78D Wait keypress; check Ctrl-Q 3490 WaitCQ JSR $FD0C Monitor RDKEY 3500 CMP #$91 Was it Ctrl-Q? 3510 RTS 3520 *----(20)---- 3530 .PH $B3AF Replace: DISK VOLUME inverted 3540 FreeMsg .AS -"=ECAPS EERF " with FREE SPACE= 3550 *----(21)---- 3560 .PH $A884 Setup FName1 for "irregular" 3570 AllowENT LDA #" " entry into CATALOG code 3580 STA FName1 Force blank at CkFNAME above 3590 CLC For possible RDNXTDIR entry 3600 RTS 3610 DOSCMDS .AT 'INIT' Move down DOSCMDS table and 3620 .AT 'LOAD' re-use the freed space above 3630 .AT 'SAVE' 3640 .AT 'RUN' 3650 .AT 'TYPE' was CHAIN 3660 .AT 'DELETE' 3670 .AT 'LOCK' 3680 .AT 'UNLOCK' 3690 .AT 'CLOSE' 3700 .AT 'READ' 3710 .AT 'EXEC' 3720 .AT 'WRITE' 3730 atA8BF .AT 'DIR' was POSITION; for CAT:43 41 D4 3740 *----(22)---- 3750 .PH $9FFB In Command Interpreter PARSE 3760 LDA DOSCMDS,Y DOSCMDS table ref. was $A884 3770 .PH $9FED Only 2 references to DOSCMDS 3780 EOR DOSCMDS,Y DO THIS AFTER ABOVE CHANGES! 3790 *-------------------------------- |
MON I CALL -151 9D26:B2 B6 9D3E:DC A5 9FA8:CA 9FC5:A9 A0 2C A9 8D 6C 36 00 A710:CA A186:AC 5F AA B9 1F 9D 48 B9 :1E 9D 48 60 EA A56E:4C DD A5 A5 EC 20 CA 9F :4C C5 9F EA A5DD:AD 75 AA 85 EE 8E 75 AA :A9 0D 4C AA A2 EA A921:60 70 A929:60 AAE3:9A AD AB10:C9 0E A4F0:A9 A0 BE C8 B4 10 02 A9 :AA 4C CA 9F A9FD:D2 2C 06 E0 30 03 4C 24 :ED 4C 1B E5 A021:EA EA EA AA2C:C9 A0 F0 0C A0 A0 CC 76 :AA F0 03 4C C4 A6 C5 EC :60 EA EA AD98:20 84 A8 20 DC AB D0 57 :4C F4 AD EA EA 20 84 A8 :20 84 A8 20 38 AE ADAE:20 2F AE A2 0C BD AE B3 :20 CA 9F CA D0 F7 20 69 :BA 20 2F AE 20 2F AE ADC5:18 90 04 EA 20 84 A8 20 :11 B0 B0 5B A2 00 8E 9C :B3 BD C6 B4 F0 51 30 48 ADDD:BD C8 B4 0A A0 07 0A B0 :03 88 D0 FA ADE9:B9 A7 B3 85 EC A0 1E 84 :EF D0 4B ADF4:20 84 A8 20 F7 AF 90 AF ADFC:EA EA AC 9C B3 20 F0 A4 :20 71 A5 AE07:BE E7 B4 B9 E8 B4 20 FE :A9 A0 07 84 24 AE 9C B3 AE17:BD C9 B4 20 DA B6 E8 C6 :EF D0 F5 20 2F AE | AE25:20 30 B2 90 A9 B0 A0 4C :7F B3 AE2F:C6 EB D0 09 20 8D B7 F0 :F4 A9 15 85 EB 4C C8 9F AE3F:A5 EE C9 DE F0 07 20 2C :AA F0 B4 D0 D9 AE4C:84 ED A0 01 C6 ED 30 D1 :CA 88 D0 FC C8 E8 B9 75 :AA C9 A0 F0 9D DD C9 B4 :F0 F2 E8 D0 E7 EA BA69:86 44 86 45 A0 C8 B9 F2 :B3 0A 90 06 E6 44 D0 F9 :E6 45 D0 F5 88 D0 EF A6 :44 A5 45 4C FE A9 BA87:20 A8 FC C6 55 D0 82 A9 :4F 85 55 4C C8 9F EA B6B3:20 A3 A2 20 8E BA 20 8C :A6 F0 14 C9 8D F0 F4 20 :DA B6 A5 F1 20 87 BA AD :00 C0 10 EA 8D 10 C0 20 :8D B7 D0 E2 4C FC A2 B6DA:A8 10 08 C9 A0 B0 0E 24 :EA 30 0A 46 32 46 32 29 :3F 69 1F 49 E0 B6EF:C9 E0 90 02 29 FF 20 CA :9F A9 FF 85 32 60 B78D:20 0C FD C9 91 60 B3AF:BD C5 C3 C1 D0 D3 A0 C5 :C5 D2 C6 A0 A884:A9 A0 85 EE 18 60 A88A:49 4E 49 D4 4C 4F 41 C4 :53 41 56 C5 52 55 CE 54 :59 50 C5 A89D:44 45 4C 45 54 C5 4C 4F :43 CB 55 4E 4C 4F 43 CB A8AD:43 4C 4F 53 C5 52 45 41 :C4 45 58 45 C3 57 52 49 :54 C5 A8BF:44 49 D2 9FFB:B9 8A A8 9FED:59 8A A8 48:04 N 3D0G NOMON I |
I received information from several sources this week about an interesting new branch of the 6502 tree. Mitsubishi has published specs for eight varieties, all part of the "740 series". The chip is based on the 6502, adds some new addressing modes for some of the standard 6502 opcodes, and adds 13 new opcodes. (Unfortunately, the opcode enhancements are not compatible with any of the other enhanced 6502s.)
The chips in the 740 series are intended for use as microcontrollers. As such, most of them have on-chip RAM and ROM. They all have built-in I/O ports, timers, and other goodies. The most interesting (to Don Lancaster, Nigel Nathan, and me) is the M50734. This chip, said to cost only $12, has four A/D converters, UART, six timers, a serial I/O port, four 8-bit I/O ports, a pair of stepper-motor drivers, and more. It all lives in a 64-pin shrink-DIP package. The M50734 is the only one in the 740 series which has no internal ROM and RAM. It is CMOS. The clock runs at 8 MHz, which in effect runs the opcodes at 2 MHz (that is, two cycle instructions take one microsecond).
To control all these functions, the bytes in page zero from $DA through $FF are used as I/O, control, and status registers.
One of the trickiest enhancements allows direct access (without bank switching or bank registers) to a second 64K memory, for data only. Apparently one of the address modes changes the state of one of the output signals during data memory references; if you use that signal to enable another bank of memory. ALMOST like having direct-addressability of 128K.
The data bus is multiplexed with half of the address bus, so it's a little harder to interface. Naturally, to get all the functions I mentioned above with only 64 pins, there have to be shared pins. Depending on which functions you are using, some of the timers and some of the I/O pins have dedicated uses.
The 6502 has one unused status bit. The 740 series calls this the T-flag, and gives it a use. If T=1, a special address mode is enabled which allows memory-to-memory operations without using the A-register. As I understand it, when T=1, address modes which use X as an index register take on a new meaning: rather than moving data between the indexed address and the A-register, data is moved between the absolute address and the zero page location whose address is in the X-register. If I am correct, ADC $400,X (assume X contains $34) would add the contents of $400 to the contents of $34, and store the result in $34. If T=0, indexing works in the old-fashioned 6502 way.
Another powerful enhancement allows you call subroutines with a two-byte version of the JSR opcode. One variation uses vectors stored in page zero, and the other uses vectors stored $FF00 through $FFF3. JMP can also uses vectors stored in page zero, so you have a two-byte JMP indirect.
Four new opcodes give you the ability to set, clear, or test any bit in the A-register or in page zero. This uses up 64 opcodes, because the bit number and bit state are coded into the opcode byte. Rockwell's version of the 65C02 includes page-zero bit-addressing, but the opcodes are not the same.
There are other new instructions, including several about which I do not have accurate complete information.
RRF zp (I think it swaps nybbles in the byte) COM zp (Probably forms 2's complement at zp) LDM zp (Probably loads ABS(zp) into A-register) CLT clear T-bit in status SET set T-bit in status STP stop the clock until reset or interrupt WIT low power mode " " " " SLW (slow?) FST (fast?) INC increment A-reg DEC decrement A-reg BRA rel branch always.
Of all the extensions, only ONE (BRA) is compatible with the standard 65C02 and 65816 extensions from Western Design Center (the OFFICIAL source for 6502 designs). The others, even if they do the same thing, use a different opcode value. Why?
If you have worked up an appetite for more information on the 740 series, contact Mitsubishi. I don't have all their numbers, but you can get close by calling 1-800-421-1132.
When we get all the data, we will be writing a Cross Assembler so you can use your Apple to develop software for this chip.
In the April 1984 issue of AAL I showed how to compute a cyclic redundancy check code (CRC) for a buffer full of data. I also tried to explain a little of the theory, as much as I understood. In the June 1984 issue Bruce Love explained how to work backward from the computed CRC of a received buffer to correct a single bit error. Both of these programs were written in plain 6502 code.
In the February 1986 "Dr. Dobb's Journal" Terry Ritter writes about "The Great CRC Mystery". He also presents some Pascal programs and 8088 machine code programs for calculating the CRC in various ways. Terry describes very briefly a table driven method (the very fastest way) and a byte-oriented method (almost as fast as table-driven).
I translated Terry's machine-coded byte-oriented method from 8088 to 65802 code, but even after twiddling and tweaking for half a day I could not make it give the correct answers. I don't know if his method is correct or not, but of course it MUST be, since it is printed in Dr. Dobb's and since he claims it works and since he even tells how many milliseconds it takes.
Anyway, I decided to derive my own byte-oriented method. The CRC algorithm is basically a "long division" of the entire bit stream in the buffer as though it were one long binary word. The divisor is $11021 in the CCITT scheme. The check code we use is the remainder of the division. The normal algorithm does "long division" on a bit-by-bit basis. The byte-oriented algorithm does "long division" on a byte-by-byte basis.
I put long division in quotation marks above because it is not EXACTLY long division. The difference is that the subtraction steps are replaced with exclusive-or operations. The exclusive-or is performed whenever the leading bit of the new dividend is a 1-bit. Here is a fully worked out example, for a CRC-so-far = $E1F0, and the next byte = $CC:
"divide" $E1F0CC by $11021, "quotient bits" down the left edge. Next CRC is the "remainder" 1110 0001 1111 0000 1100 1100 (E1F0CC in binary) 1 eor 1000 1000 0001 0000 1 (11021 in binary) --------------------- 110 1001 1110 0000 01 1 eor 100 0100 0000 1000 01 --------------------- 10 1101 1110 1000 000 1 eor 10 0010 0000 0100 001 --------------------- 0 0 1111 1110 1100 0010 1111 1110 1100 0010 1 1 eor 1000 1000 0001 0000 1 --------------------- 111 0110 1101 0010 01 1 eor 100 0100 0000 1000 01 --------------------- 11 0010 1101 1010 000 1 eor 10 0010 0000 0100 001 --------------------- 1 0000 1101 1110 0010 1 eor 1 0001 0000 0010 0001 --------------------- 0001 1101 1100 0011 = $1DC3
Note that the "quotient" is $EF. This "quotient" can always be exactly computed by using just the first byte of the dividend (the high byte of the old CRC code): quotient = crchi .eor. crchi/16. If you carefully study the worked out example above, you should be able to see why this is true. Now, if we use the exclusive-or rather than addition to perform a multiplication of the quotient times $11021, it will look like this:
uuuu.vvvv (symbolic quotient in binary) x $11021 (multiplier in hexadecimal) -------- uuuu.vvvv u.uuuu.vvv0 uuuu.vvvv uuuu.vvvv ----------------------------- whatever........
There are several significant things to notice about the multiplication above. First, we only need to save the rightmost 16 bits of the "product". If we exclusive-or those bits with the rightmost 16 bits of the original dividend (which means the low byte of the old CRC followed by the new byte), we will get the next CRC. (This trick relies on the fact that exclusive-or is a reversible operation, so that "adding" and "subtracting" give the same result!)
Furthermore, we can organize those "partial products" in a more efficient way for computation. Now, let's write the original CRC symbolically as "aaaa.bbbb.cccc.dddd", and the next data byte as "eeee.ffff". The "quotient" after "dividing" by $11021 will be "aaaa.bbbb exclusive-or 0000.aaaa"; let's write that symbolically as "aaaa.gggg". Then we can compute the next CRC code by the following very simple steps:
cccc.dddd.eeee.ffff eor gggg.0000.aaaa.gggg eor 000a.aaag.ggg0.0000 ------------------- wwww.xxxx.yyyy.zzzz
Believe it or not!
The program that follows implements this algorithm, in lines 1550-1760. I used 65802 code, but it really could be done quite nicely in plain 6502 as well. I leave it as "an exercise for the reader" (as college textbooks are wont to say), should you wish to try the algorithm in a plain-vanilla 6502.
The SEND and RECV programs simulate sending and receiving a buffer-full of data. I chose to put my buffer at $4000, for 258 bytes. This is the same as in the April 1984 article.
The FIND.BAD.BIT program is simply a translation of Bruce Love's 1984 program into 65802 code. Thanks to 16-bit registers, it is significantly faster and shorter.
Speaking of speed, the code for computing the next CRC code for one new byte takes (if I counted correctly) 57 clock cycles. In a normal Apple that means about 56 microseconds. The time for 8088 machine code in Terry Ritter's article was 17 microseconds for the equivalent steps. He was running with a 7.16 MHz clock. If you ran the 65802 code in an Applied Engineering Transwarp card or a Titan Accelerator card with a 4-MHz 65802 (running at 3.58 MHz), the time would be only 15.9 microseconds in an Apple.
1000 *SAVE S.CRC.GENERATOR 1010 *-------------------------------- 1020 BUFFER .EQ $4000 1030 LIMIT .EQ $4102 1040 *-------------------------------- 1050 CRC .EQ $00,01 1060 PNTR .EQ $02,03 1070 TEMP .EQ $0A,0B 1080 *-------------------------------- 1090 PRNTAX .EQ $F941 1100 CROUT .EQ $FD8E 1110 *-------------------------------- 1120 * SIMULATE SENDING A BUFFER-FULL 1130 *-------------------------------- 1140 SEND 1150 LDA #0 CLEAR CRC BYTES IN BUFFER 1160 STA LIMIT-1 1170 STA LIMIT-2 1180 JSR NEW.CRC.BUFFER COMPUTE CRC OF 258 BYTES 1190 LDX CRC STORE CRC INTO LAST 2 BYTES 1200 LDA CRC+1 1210 STX LIMIT-1 1220 STA LIMIT-2 1230 JSR PRNTAX DISPLAY THE CRC 1240 JMP CROUT <RETURN> AND RETURN 1250 *-------------------------------- 1260 * SIMULATE RECEIVING A BUFFER-FULL 1270 *-------------------------------- 1280 RECV 1290 JSR NEW.CRC.BUFFER COMPUTE CRC OF 258 BYTES 1300 LDX CRC DISPLAY CRC IN HEX 1310 LDA CRC+1 1320 JSR PRNTAX 1330 JMP CROUT 1340 *-------------------------------- 1350 .OP 65802 1360 *-------------------------------- 1370 * CRCH CRCL DATA 1380 * aaaa.bbbb.cccc.dddd.eeee.ffff 1390 * +0000.aaaa 1400 * --------- 1410 * aaaa.gggg 1420 * +gggg.0000.aaaa.gggg 1430 * +000a.aaag.ggg0.0000 1440 * ------------------- 1450 * (crchi) (crclo) 1460 *-------------------------------- 1470 NEW.CRC.BUFFER 1480 CLC 1490 XCE 1500 REP #$30 M&X BOTH 16-BITS 1510 LDA ##$FFFF 1520 STA CRC INITIALIZE CRC FOR BUFFER 1530 LDX ##BUFFER POINT TO BUFFER 1540 *-------------------------------- 1550 .1 SEP #$20 CRC=aaaabbbbccccdddd, DATA=eeeeffff 1560 LDA CRC+1 aaaabbbb .eor. 0000aaaa = aaaagggg 1570 LSR 1580 LSR 1590 LSR 1600 LSR 0000aaaa 1610 EOR CRC+1 aaaabbbb 1620 XBA AGXX 1630 LDA #0 AG00 1640 REP #$20 1650 LSR 1660 LSR 1670 LSR 000a.aaag.ggg0.0000 1680 STA TEMP 1690 LSR 0000.aaaa.gggg.0000 1700 EOR CRC aaaa.bbbb.cccc.dddd = aaaa.gggg.kkkk.dddd 1710 XBA kkkk.dddd.aaaa.gggg 1720 EOR TEMP 000a.aaag.ggg0.0000 1730 SEP #$20 1740 EOR 0,X crchi.crclo 1750 REP #$20 1760 STA CRC 1770 *-------------------------------- 1780 INX 1790 CPX ##LIMIT 1800 BCC .1 1810 XCE 1820 RTS 1830 *-------------------------------- 1840 * FIND BAD BIT BY BRUCE LOVE'S METHOD 1850 *-------------------------------- 1860 DUMMY.CRC .EQ $10,11 1870 *-------------------------------- 1880 FIND.BAD.BIT 1890 JSR RECV RECEIVE, COMPUTING NEW CRC 1900 *-------------------------------- 1910 CLC 1920 XCE ENTER NATIVE MODE 1930 REP #$30 X,M 16 BITS 1940 LDX ##$80F X=BIT NUMBER 1950 LDA ##1 START DUMMY CRC IN A-REG 1960 .1 CMP CRC 1970 BEQ .2 ...FOUND BAD BIT! 1980 DEX DECREMENT BIT NUMBER 1990 BMI .2 ...WENT TOO FAR, COULDN'T FIND BAD BIT 2000 ASL SHIFT DUMY CRC 2010 BCC .1 2020 EOR ##$1021 2030 BCS .1 ...ALWAYS 2040 *-------------------------------- 2050 .2 TXA BIT NUMBER 2060 SEC 2070 XCE 2080 XBA 2090 JMP PRNTAX 2100 *-------------------------------- |
In the March 1984 AAL, Paul Shetler gave us a very fast garbage collector for Applesoft. Last week Keith Satterley called from Australia, and mentioned he thought there was a bug in the handling of strings over 128 characters long. I looked into it, and he is right.
The bug is in the loop in lines 3240-3320, on page 9 of that issue. The loop moves a string from one place in memory to another. The way we printed the code, a string longer than 128 characters would only have one byte moved! Here is the old code and the correct code, side-by-side:
-----old code------------ -----correct code-------- 3240 LDY STRING.LENGTH 3240 LDY STRING.LENGTH 3250 DEY 3250 .3 DEY 3260 .3 LDA (FRESPC),Y 3260 LDA (FRESPC),Y 3270 STA (LOWTR),Y 3270 STA (LOWTR),Y 3280 DEY 3280 TYA 3290 BPL .3 3290 BNE .3 3300 BMI .1 3300 BEQ .1
Can you see why the new code works and the old doesn't?
I operate a AE/CATFUR line using my Apple and a modem in Montreal, Quebec. I have found that protecting your DOS from illegal entry can be a tough job to say the least.
In searching for ways to protect my system, I came across an interesting address in DOS: at $A026 there is some code which is executed whenever you try to type in a DOS command. The code checks to see if the command you typed is allowed as a direct command, and if not gives you the NOT DIRECT COMMAND message (or ERROR 15 if you are using DiversiDOS).
I have written a little patch that will catch you when you type a DOS command, and re-RUN the Applesoft program. If a sneaky caller finds a way to get out of the executing Applesoft program, at least he/she will be prevented from doing DOS commands.
Now every lock should have a key. You do want to be able to use your own DOS in direct mode, so I have included a way to turn off the protection. If you type "PRINT USR (0)" the system will respond with "PW:". Then enter a two-character password and the protection patch will be removed. Then you can CATALOG, DELETE, or whatever you want to do.
Since I use Diversi-DOS, and in both the 48K and 64K configurations, I set up my patching program so that it will work with both. The code which checks which version is loaded is in lines 1220-1260 and lines 1390-1410. If the output hook at $36,37 points up to $BDxx or higher, the 64K version must be running. Normal 48K DOS points to $9EBD.
These patches worked on my system, but yours may be a little different depending on which version of DOS you use. Examine carefully all the addresses I use inside DOS to see if yours is the same as mine before you try to use these patches.
1000 *SAVE GENDRON DOS MODS 1010 *-------------------------------- 1020 * DOS PROTECTION FOR THE DIRECT COMMAND "ERROR 15" 1030 * WRITTEN BY RICHARD GENDRON FOR USE ON TRANSFERS ][ 1040 * (514) 738-1247 (AE/CAT-FUR) 1050 *-------------------------------- 1060 .OR $300 1070 *-------------------------------- 1080 INSTALL 1090 LDA #$4C BUILD "USR" VECTOR 1100 STA $0A "JMP" OPCODE 1110 LDA #USR 1120 STA $0B 1130 LDA /USR 1140 STA $0C 1150 *---MOVE DATA INTO DOS----------- 1160 LDX #P1-PATCHES POINT AT OUR PATCHES 1170 *** JMP PATCH.DOS 1180 *-------------------------------- 1190 PATCH.DOS 1200 LDA #$A026 1210 STA $00 1220 LDA $37 48K OR 64K DOS? 1230 CMP #$BD CARRY CLEAR IF 48K 1240 LDA /$A026 ...48K 1250 BCC .1 ...48K 1260 LDA /$E026 ...64K 1270 .1 STA $01 1280 LDY #4 MOVE 5 BYTES 1290 .2 LDA PATCHES,X 1300 STA ($00),Y 1310 DEX 1320 DEY 1330 BPL .2 1340 RTS 1350 *-------------------------------- 1360 REBOOT 1370 SEI TURN OFF ANNOYING INTERRUPTS 1380 JSR $03EA RESET THE I/O HOOKS 1390 LDA $37 LETS SEE WHICH DOS WE ARE USING 1400 CMP #$BD IS IT 64K DOS ? 1410 BMI .1 SNIFF, NO IT IS NOT 1420 BIT $C081 YES IT IS, SO TURN OFF THE LANGUAGE CARD 1430 BIT $C081 TWICE, EVERYONE KNOWS WHY ?. 1440 JSR $E316 DOS "CLOSE" ALL FILES 1450 JMP $D566 NOW LET'S JUMP TO THE APPLESOFT "RUN" 1460 .1 JSR $A316 DOS "CLOSE" ALL FILES (NO TROUBLE PLS) 1470 JMP $A4FC 48K INTERNAL "DOS RUN" 1480 *-------------------------------- 1490 USR 1500 LDY #0 START OF LOOP COUNTER 1510 .1 LDA PASSWORD,Y GET PASSWORD TEXT 1520 BEQ .2 ...END OF STRING 1530 JSR PRINT NO, SO PRINT IT 1540 INY INCREMENT THE LOOP 1550 BNE .1 FOREVER LOOP (NEVER CAN EXIT) 1560 *-------------------------------- 1570 .2 JSR INPUT ALL TEXT PRINTED SO LET'S GET A KEY 1580 CMP #"* WAS IT A "*" ? (OR WHATEVER YOU WANT) 1590 BNE .4 NO IT WAS NOT , SO BYE BYE 1600 JSR INPUT YES IT WAS, SO GET ANOTHER KEY 1610 CMP #". WAS IT A "." (OR WHATEVER YOU WANT) 1620 BNE .4 NO IT WAS NOT, SO BYE BYE 1630 *-------------------------------- 1640 LDX #P2-PATCHES 1650 JSR PATCH.DOS 1660 .4 RTS WE HAVE FINISHED 1670 *-------------------------------- 1680 * TEXT TO BE PRINTED WHEN A 1690 * "PRINT USE(0)" COMMAND IS DONE 1700 * IN APPLESOFT 1710 *-------------------------------- 1720 PASSWORD 1730 .AS -"PW:" 1740 .HS 00 1750 *-------------------------------- 1760 * INPUT AND PRINT SUBROUTINES 1770 *-------------------------------- 1780 PRINT JMP ($36) 1790 INPUT JMP ($38) 1800 *-------------------------------- 1810 PATCHES 1820 JMP REBOOT CALL OUR NEW CODE 1830 NOP NEEDED FOR DIVERSI-DOS 1840 P1 NOP 1850 *-------------------------------- 1860 .HS A9023909 ORIGINAL CODE 1870 P2 .HS A9 1880 *-------------------------------- 9999 .LIF |
Apple Assembly Line is published monthly by S-C SOFTWARE CORPORATION, P.O. Box 280300, Dallas, Texas 75228. Phone (214) 324-2050. Subscription rate is $18 per year in the USA, sent Bulk Mail; add $3 for First Class postage in USA, Canada, and Mexico; add $14 postage for other countries. Back issues are available for $1.80 each (other countries add $1 per back issue for postage).
All material herein is copyrighted by S-C SOFTWARE CORPORATION,
all rights reserved. (Apple is a registered trademark of Apple Computer, Inc.)