0010 ! UNPURGE - Unpurge a mass storage file, M.Markov 11/12/1987 0020 ! Required : HP-71 HP-IL module 0030 ! 0040 ! This is a quick and dirty routine that allows you to recover 0050 ! a file you just purged. If files have been added after the 0060 ! purge operation, you are risking Memory Lost - this program 0070 ! does not check the validity of the file. UNPURGE changes the 0080 ! filetype bytes in the mass storage directory from 0000 hex to 0090 ! the value you choose. The mass storage device must be on LOOP(1). 0100 ! 0110 ! If you are not sure that the unpurged file is still unchanged, 0120 ! back-up the contents of your calculator/ computer before copying the 0130 ! file into RAM. See program FINDFL71 (CHHU04 /CHHU05) for partial 0131 ! verification. 0140 ! 0150 ! Keep in mind that there may be more than one purged entries whose 0160 ! filename is identical. This frequently occurs in the development 0170 ! stage when the program keeps growing and the storage capacity 0180 ! reserved by existing purged entries is exceeded. UNPURGE therefore 0190 ! unpurges ALL the entries for the selected filename. This allows 0200 ! you to do a CAT to obtain additional information, 0210 ! such as file length / date stored to identify the copy you want to 0220 ! recover. Use RENAME or PURGE on duplicate entries that occur before 0230 ! the desired entry to get access to the copy you are interested in. 0240 ! 0250 ! This program handles all common HP-71 file types. You can add additional 0260 ! filetypes to suit your particular needs. See SWAP07 file LIFDATA if you 0270 ! want to add HP-41/HP-75 filetypes to the DATA statments, lines 500 & 510 0280 ! 0290 ! If you want to handle HP-41 filenames with leading blanks or lowercase 0300 ! charaters, comment lines 440 and 450. If you do, take extra care when 0310 ! when entering filenames. 0320 ! 0330 ! Now, let's write some code instead of blathering about it: 0340 CALL UNPURGE @ SUB UNPURGE 0350 STD @ DESTROY A,N,P,A$,B$,F$,T$ @ INTEGER A,N,P 0360 DIM A$,B$,F$,T$[5] 0370 RESTORE IO @ RESET HPIL @ A=DEVADDR(":TAPE(2)") @ IF A=-1 THEN 400 0380 INPUT "Drive #? ","1";A 0390 A=DEVADDR(":TAPE("&STR$(A)&")") @ IF A=-1 THEN 380 ELSE 410 0400 A=DEVADDR(":TAPE") @ IF A=-1 THEN BEEP @ DISP "No Mass Storage found" @ GOTO 630 0410 LC OFF @ INPUT "Filename to UNPURGE? ";F$ 0420 IF F$="" THEN BEEP @ GOTO 410 0430 ! Comment the following two lines if you want to unpurge HP-41 files 0440 IF F$[1,1]=" " THEN F$=F$[2] @ GOTO 420 0450 F$=UPRC$(F$) 0460 F$[11]=CHR$(0)&CHR$(0) @ B$=CHR$(255)&CHR$(255)&CHR$(255) @ B$=B$&B$&B$&B$ 0470 INPUT "Select file type ","BASIC";A$ @ A$=UPRC$(A$) @ IF A$="" THEN 630 0480 RESTORE @ N=0 @ ON ERROR GOTO 470 0490 READ C$,T$ @ IF C$#A$ THEN 490 ELSE 495 0491 INPUT "Filetype (Hex)? ","00 00";T$ 0492 IF T$="00 00" THEN 630 0495 OFF ERROR @ T$=CHR$(HTD(T$[1,2]))&CHR$(HTD(T$[4,5])) 0500 DATA DATA,E0 F0,BIN,E2 04,LEX,E2 08,KEY,E2 0C,BASIC,E2 14,FORTH,E2 18 0510 DATA ROM,E2 1C,TEXT,00 01,SDATA,E0 D0 0520 CLEAR :A 0530 SEND UNT UNL MTA LISTEN A DDL 4 DATA 0,2 UNL @ SEND MLA TALK A DDT 2 0540 ENTER :A USING "#,12A";A$ @ IF A$=B$ THEN 610 0550 IF A$#F$ THEN ENTER :A USING "#,20A";A$ @ GOTO 540 0560 ! Now, we have one of the target entries to be unpurged. So, we start by 0570 ! finding out where we are, then editing the file type as selected above. 0571 ! Note that MMLEXV04 allows decrementing two byte pointers with CHR2$ and 0572 ! NUMR, with C$[1,2]=CHR2$(NUMR(C$)-1). However, let's avoid non-mainframe 0573 ! keywords. 0580 SEND UNT MLA TALK A DDT 3 @ ENTER :A USING "#,3A";C$ @ P=NUM(C$[3]) 0581 N=N+1 @ C$[2,2]=CHR$(NUM(C$[2,2])-1) 0582 ! Actually, to insure proper operation at all times, we should decrement 0583 ! C$[1,2], not C$[2,2]. This means that we could have a serious error for 0584 ! directory sectors 100, 200,... (Hex). While this is unlikely to be a 0585 ! problem given present directory sizes, let's do the job correctly: 0586 IF NUM(C$[2])=255 THEN C$[1,1]=CHR$(NUM(C$)-1) 0587 ! Generally, after a seek sector (DDL 4) operation, you should wait 0588 ! for however long the drive remains "busy" before sending any further 0589 ! frames to the drive. However, here we know seek time will be negligible. 0590 SEND UNT UNL MTA LISTEN A DDL 4 DATA C$[1,2] DDL 6 DDL 3 DATA P-2 DDL 0 DATA T$ DDL 8 0591 ! You could also easily edit the filename to facilitate access. For 0592 ! example, you could change DDL 3 DATA P-2 DDL 0 DATA T$ to 0593 ! DDL 3 DATA P-11 DDL 0 DATA DTH$(N)&" "&T$ . The new filename consists 0594 ! of the first character of the original filename and a 5 character 0595 ! sequence in hex... This could result in duplicate filenames, which would 0596 ! require extra care to avoid future problems, specifically, purging all 0597 ! unwanted unpurged entries - something you should do anyway. 0598 ! 0599 ! We are now done editing, so, reset the drive and continue the search: 0600 SEND UNT UNL MTA LISTEN A DDL 4 DATA C$[1,2] UNL MLA TALK A DDT 2 @ GOTO 540 0610 SEND UNL UNT @ CLEAR :A @ IF NOT N THEN BEEP @ DISP F$;" not found" 0620 IF N THEN DISP N;" unpurged entries" 0630 END SUB 0640 ! If the file type you select is not recognized, that is, if it is 0650 ! misspelled or if it is not included in the DATA statment above, you will 0660 ! be re-promted until the filetype is recognized. You can exit the loop by 0670 ! pressing [f][-LINE] [ENDLINE], thus returning a null string. You will 0671 ! then be prompted for the filetype code in hex - thus taking care of 0672 ! non-standard file types. The default "00 00" applies to purged files, 0673 ! which requires no work, and therefore gives you a graceful exit from 0674 ! UNPURGE. 0680 ! 0690 ! CAUTION : Using UNPURGE to break private may lead to Memory Lost. 0700 ! Techniques have been developed that will protect the privacy of BASIC, 0710 ! BIN and LEX files from even skilled hackers. YOU HAVE BEEN WARNED! 0720 ! 0730 ! A historical note: various utilities have been writen in the past to 0740 ! unpurge mass storage files. See LBL UNP in XIO-UT, FIXDIR, EDDIRENT, 0750 ! WRTBYT, and others in various swapdisks and publications. 0760 ! 0770 ! The code for the editor routine (lines 580 to 590) can be easily adapted 0780 ! to edit any byte(s) on mass storage media, provided you keep in mind 0790 ! that the partial write (DDL 6) mode has an automatic wrap-around from 0800 ! end of sector (byte pointer=255) to start of the SAME sector (byte pt=0) 0810 ! This routine writes string T$ to the logical address defined by C$, 0820 ! where C$[1,2] is the sector address needed for the SEEK (DDL 4) data 0830 ! bytes and P is the byte pointer position where you want the first byte 0840 ! of T$ to go. The sector address is decremented by 1 because of the way 0850 ! the HP-71 buffers information from mass storage.