10 REM ... UTIL.ECB 15 DIM A$(4),B$(5),C$(5),D$(256) 20 REM* UTILITY PROGRAM FOR TAPE-DISK-TAPE OPERATIONS 30 REM* WRITTEN BY: TOM DIGATE 40 REM* Copyright (C) 1979 By TAD Enterprises 50 GOSUB 870: GOSUB 1220 60 PRINT "&K": PRINT TAB(10);"CP/M Utility Program" 70 PRINT TAB(10);"Copyright (C) 1979 TAD Enterprises" 80 PRINT 90 PRINT "Commands are:";TAB(20);"EXIT";TAB(27);"Return to Basic" 100 PRINT TAB(20);"CRED";TAB(27);"Enable block reads from tape" 110 PRINT TAB(20);"CWRT";TAB(27);"Enable block saves to tape" 120 PRINT TAB(20);"TRED";TAB(27);"Transfer byte file from tape to disk" 130 PRINT TAB(20);"TWRT";TAB(27);"Transfer byte file from disk to tape" 140 PRINT TAB(20);"TRCE";TAB(27);"Print address of Trace byte" 150 PRINT TAB(20);"INIT";TAB(27);"^C CP/M for New Diskettes in Drives" 160 PRINT TAB(20);"TYPE";TAB(27);"Display or Change CP/M filetype" 170 PRINT TAB(20);"SNGL";TAB(27);"Set all Disk I/O to Drive A" 180 PRINT TAB(20);"SBMT";TAB(27);"Generate CP/M Submit File $$$.SUB" 190 PRINT 200 INPUT (4,0)"Enter command >",A$ 210 IF A$="" THEN LET A$="EXIT" 220 IF A$="EXIT" THEN PRINT "Utility Program Off!": END 230 IF A$="INIT" THEN GOTO 480 240 IF A$="CRED" THEN GOTO 550 250 IF A$="CWRT" THEN GOTO 640 260 IF A$="TRED" THEN LET F=0: GOTO 700 270 IF A$="TWRT" THEN LET F=1: GOTO 700 280 IF A$="TRCE" THEN GOTO 390 290 IF A$="TYPE" THEN GOTO 330 300 IF A$="SNGL" THEN GOTO 1340 310 IF A$="SBMT" THEN GOTO 1600 320 PRINT "Invalid command...": PAUSE 30: GOTO 20 330 GOSUB 420: LET A=A+25: PRINT "&K": PRINT : PRINT 340 PRINT "Current filetype is ";CHR(PEEK(A));CHR(PEEK(A+1));CHR(PEEK(A+2)) 350 PRINT : INPUT (3,0)"Enter new filetype or hit return to exit >",A$ 360 IF A$="" THEN GOTO 20 370 POKE A,ASC(A$(1,1)): POKE A+1,ASC(A$(2,2)): POKE A+2,ASC(A$(3,3)) 380 PAUSE 10: GOTO 20 390 GOSUB 420: GOTO 430 400 REM. The following statement calculates the address of 410 REM. where the CP/M interface software is located in memory 420 LET A=PEEK(1249)*256+PEEK(1248)-4: RETURN 430 PRINT "&K": PRINT "Address of Trace enable byte is ";A 440 PRINT "To enable trace mode, poke a 1 into this address" 450 PRINT "To disable trace mode, poke a 0 into this address" 460 PRINT : PRINT : INPUT (1,0)"Hit return when ready....>",A$ 470 GOTO 20 480 GOSUB 420 490 PRINT "&K": PRINT "This command will allow you to exchange diskettes" 500 PRINT "without having to return to CP/M and during a warm boot." 510 PRINT : PRINT : INPUT (1,0)"Swap disks and hit return when ready...>",A$ 520 REM. The following CALL can be used in your programs to 530 REM. to perform the INIT function. 540 LET A=CALL(A+1): GOTO 20 550 POKE 2692,19: POKE 2693,PEEK(9816) 560 PRINT "&K": PRINT "Cassette block read mode is now enabled." 570 PRINT "All programs will be read from tape into memory with" 580 PRINT "the GET command. TEXT files will still come from disk." 590 PRINT "The APPEND command will read files from disk. The XEQ " 600 PRINT "command will read file from tape unless specified as " 610 PRINT "a text file." 620 PRINT : PRINT : INPUT (1,0)"Hit return when ready...>",A$ 630 GOTO 20 640 POKE 2492,22: POKE 2493,PEEK(9816) 650 PRINT "&K": PRINT "Cassette block write mode is now enabled." 660 PRINT "All programs will be written to tape when the SAVE" 670 PRINT "command is given. TEXT files will still be written" 680 PRINT "to disk." 690 GOTO 620 700 PRINT "&K" 710 ERRSET 1290 720 IF F=0 THEN PRINT TAB(10);"Tape to Disk"; ELSE PRINT TAB(10);"Disk to Tape"; 730 PRINT " Utility Program" 740 PRINT TAB(10);"For byte or text files only!" 750 PRINT : PRINT 760 IF F=0 THEN PRINT "Note---Files are read from tape unit #2 and saved on" 770 IF F=1 THEN PRINT "Note---Files are saved on tape unit #2 and read from" 780 PRINT " Disk drive 'A'. Make sure that everything is" 790 PRINT " ready before proceeding beyond this point.": PRINT 800 PRINT : INPUT (1,0)"When desired disk is in Drive A, hit return...",A$ 810 IF F=0 THEN INPUT "Enter filename of tape file desired in unit #2....>",B$: GOTO 830 820 IF F=1 THEN INPUT "Enter filename of disk file to be saved on tape....>",B$ 830 IF B$="" THEN GOTO 1210 840 SEARCH "/",B$,A 850 IF A<>0 THEN PRINT "Invalid filename": GOTO 750 860 GOSUB 420: LET A=CALL(A+1): GOTO 910 870 GOSUB 420: LET B=PEEK(9816) 880 LET O1=5309: LET O2=5560 890 LET C1=5262: LET C2=5477: LET C3=55 900 LET W1=5368: LET W2=5389: LET R=5431: RETURN 910 GOSUB 870 920 IF F=0 THEN FILE #1;B$,2 ELSE FILE #1;B$,1 930 PRINT "&K": PRINT "Basic is now in a modified state. Do not" 940 PRINT "press MODE select during the transfer operation" 950 PRINT "or else BASIC will not be in a healthy condition." 960 PRINT "If you do hit MODE by accident, Basic can be" 970 PRINT "restored to a healthy condition by RUNning this program" 980 PRINT "from the start. Otherwise, a BYE command should be given." 990 PRINT : PRINT 1000 POKE O1+1,B: POKE O1,7: POKE O2+1,B: POKE O2,7 1010 POKE 5642,84: POKE 5643,65: POKE 5644,80: POKE 5645,69 1020 POKE 5494,48 1030 IF F=0 THEN FILE #2;B$+"/2",1 ELSE FILE #2;B$+"/2",2 1040 IF F=0 THEN POKE R+1,B: POKE R,13 1050 IF F=1 THEN POKE W1+1,B: POKE W2+1,B: POKE W1,16: POKE W2,16 1060 PRINT "&K": PRINT : PRINT : PRINT : PRINT "File Transfer in progress......": PRINT 1070 LET D$="" 1080 IF F=1 THEN 1110 1090 READ #2;D$: GOTO 1140 1100 GOTO 1120 1110 READ #1;D$: GOTO 1140 1120 IF F=0 THEN PRINT #1;D$: GOTO 1070 1130 IF F=1 THEN PRINT #2;D$: GOTO 1070 1140 CLOSE #1 1150 POKE C1+1,B: POKE C2+1,B: POKE C3+1,B: POKE C1,10: POKE C2,10: POKE C3,10 1160 CLOSE #2 1170 PRINT "&K" 1180 PRINT : IF F=0 THEN PRINT "Tape to Disk"; ELSE PRINT "Disk to Tape"; 1190 PRINT " File Transfer is Complete." 1200 PAUSE 30: GOTO 20 1210 GOSUB 1220: LET A$="": GOTO 210 1220 GOSUB 420: LET A1=PEEK(1249) 1230 POKE O1+1,A1: POKE O2+1,A1: POKE C1+1,A1: POKE C2+1,A1: POKE C3+1,A1: POKE W1+1,A1: POKE W2+1,A1: POKE R+1,A1 1240 LET A2=PEEK(1248)-4 1250 POKE O1,A2+7: POKE O2,A2+7: POKE C1,A2+10: POKE C2,A2+10 1260 POKE C3,A2+10: POKE R,A2+13: POKE W1,A2+16: POKE W2,A2+16 1270 POKE 5494,64: POKE 5642,68: POKE 5643,73: POKE 5644,83: POKE 5645,75 1280 PRINT : RETURN 1290 PRINT "&K": PRINT "An error has occurred while reading/writing. A reboot" 1300 PRINT "to CP/M is necessary. Do not attempt to run this program" 1310 PRINT "again since BASIC was modified and can no longer be used." 1320 PRINT 1330 BYE 1340 PRINT "&K": PRINT "This command will cause all I/O that normally" 1350 PRINT "would go to UNIT 2 (Drive B) to go to UNIT 1 (Drive A)" 1360 PRINT "Thus, a single drive system can have two files open" 1370 PRINT "at the same time on the same disk.": PRINT 1380 REM. calculate address of byte to poke for single 1390 GOSUB 420 1400 REM. The following pokes change all disk I/O to a specified 1410 REM. drive. It is currently set to change it to drive A 1420 REM. but this can be any drive you want. For example, to get 1430 REM. drive C, poke a 3 into A+29 instead of 1. 1440 REM. (Drive A=1,B=2,C=3,D=4) 1450 REM. One possible use of this function is to read data from 1460 REM. drive A and save it on drive C. This can be accomplished 1470 REM. by pokeing the drive number before executing the FILE 1480 REM. command for that drive. An example program to do this 1490 REM. is given below; 1500 REM. POKE A+28,62:POKEA+29,1:POKEA+30,0 1510 REM. FILE #1;"AFILE/1",1 1520 REM. POKE A+29,3 1530 REM. FILE #2;"CFILE/2",2 1540 REM. READ#1;X:END 1550 REM. PRINT#2;X 1560 REM. END 1570 POKE A+28,62: POKE A+29,1: POKE A+30,0 1580 PRINT : PRINT : INPUT "Hit return when ready.....",A$ 1590 GOTO 20 1600 PRINT "&K": PRINT TAB(10);"CP/M Command File Generator for Auto Execution" 1610 PRINT TAB(10);"Copyright 1979 TAD Enterprises" 1620 PRINT : PRINT "This command generates a file that contains CP/M" 1630 PRINT "command lines as you would normally type while under CP/M." 1640 PRINT "This file is then executed the next time a warm boot to" 1650 PRINT "Drive A is given. There must not be a file called $$$.SUB" 1660 PRINT "on the disk before using this command or unwanted" 1670 PRINT "commands may be executed." 1680 DIM E$(128),F$(5) 1690 LET F$="$$$/1": LET G$=CHR(229): GOTO 1730 1700 PRINT : PRINT "Working ... ": LET H$="" 1710 FOR I=1 TO J*128-2: LET H$=H$+G$: NEXT 1720 RETURN 1730 PRINT : PRINT : INPUT "Enter total number of commands to be executed ... ",J 1740 LET M=J 1750 DIM H$(J*128-2) 1760 GOSUB 1700: PRINT 1770 PRINT "Enter CP/M command #";M+1-J; 1780 INPUT " ... ",E$ 1790 LET E$=CHR(LEN(E$))+E$+CHR(0)+"$" 1800 IF ASC(E$(1,1))=13 THEN LET E$(1,1)=CHR(14): LET E$=E$(1,14)+" "+CHR(0)+"$" 1810 FOR L=LEN(E$)+1 TO 128: LET E$=E$+G$: NEXT 1820 LET K=((J-1)*128)+1 1830 IF J=M THEN LET L=J*128-2 ELSE LET L=J*128 1840 IF J=M THEN LET H$(K,L)=E$(1,126) ELSE LET H$(K,L)=E$(1,128) 1850 LET J=J-1 1860 IF J<>0 THEN GOTO 1770 1870 GOTO 1890 1880 LET H$=H$(1,32)+H$(34,LEN(H$)) 1890 LET A=PEEK(1249)*256+PEEK(1248)-4 1900 POKE A+25,ASC("S"): POKE A+26,ASC("U"): POKE A+27,ASC("B") 1910 FILE #1;F$,2 1920 PRINT #1;H$ 1930 CLOSE #1 1940 PRINT : PRINT "The $$$.SUB file is now created." 1950 INPUT "Do you want to execute it? ",A$ 1960 IF A$(1,1)="Y" THEN BYE ELSE SCR 1970 END