Z-Mail

Z-Mail is a mailing-list manager from Zebra Systems for its FDD disk drive system on the Timex/Sinclair 2068 (loading screen: “copyright © 1985 Zebra Systems, Inc.”). A list holds up to 1,000 records of 128 characters, kept in a random-access disk file with a separate name and ZIP code index. You page through records with the arrow keys, and edit them in an on-screen editor with Modify, Insert, Delete, Append, Goto, Sort, Print and Quit commands. The list can be sorted by name or ZIP code, searched, and printed as mailing labels or as a summary through an AERCO, Tasman B, Tasman C or A&J printer interface, or the drive’s own RS232 port.

Z-Mail came on the Zebra Bonus Disk, side B, volume ZMAIL. The download has the disk image and every file as a TAP: the loader start, the BASIC program zmail.bas, its machine code zmail.obj (63000, 1300 bytes) and the files of a demo list. The demo list’s records, and a copy of an index and a record left in the program’s saved variables, have been blanked. The program uses TOS disk commands throughout, so it runs only with the drive, for example in FUSE with the FDD3000 interface (fdd3000e). It has not been tested.

Program Analysis

Files

A list called name uses four files: name.dat, the 128-byte records, opened with OPEN #*1;n$+".dat";r;128; name.ix1, saved from s$() (1,000 × 15: surname and ZIP for sorting and searching); name.ix2, saved from i$() (1,000 × 2: the physical record number of each entry as two bytes); and name.ptr, saved from p() (current, last and physical record counters). Records are read and written with INPUT *#1;r$;AT n and PRINT *#1;r$;AT n.

Structure

  • Lines 100–216: open an old list or create a new one, loading the three index files with LOAD *… DATA.
  • Lines 300–565: printer interface choice and the FDD-RS232 parameter settings.
  • Lines 1000–1744: record display and a character editor with cursor movement, insert and delete.
  • Lines 2000–2900: main loop and the record commands.
  • Lines 3000–3500: name extraction, sorting, and label and summary printing.

Notable Techniques

  • The physical record number is stored as two characters in i$(), so the index can be sorted without moving records in the data file.
  • Sorting and searching have both BASIC and machine code versions (RANDOMIZE USR 63004 and 63001).
  • Errors from the disk system are trapped by POKEing system variable 23729 and testing 23728 after each disk command.

Potential Issues

  • The routine at line 3002 that rebuilds the name index opens "mlist.dat" instead of the current list’s file.
  • Line 565 POKEs 23279, where the matching lines use 23729; this appears to be a typo.

Related Products

Four piece disk drive system designed for the TC 2068. Base system included disk controller, disk drive, system connector and twister board to convert the TS 2068 to the Spectrum bus.
Power supply, FDD controller and with two disk drives in a black metal case.

Related Articles

Unless you have been out of the country for the past year, I am sure that you have heard about...

Image Gallery

Source Code

    1 REM !VAL \~!CODE \ RETURN ( RETURN ( THEN '. THEN AND *U\>"PEEK #( IF RESTORE !LEN \N!@ RESTORE !VAL \~ NEW o>& THEN % THEN gSTR$ RESTORE !VAL \~ LLIST RETURN 8 RETURN "TAB \ LLIST RESTORE ~= OR RETURN a8paSTR$ X COPY OR  ao> THEN % THEN gSTR$ RESTORE !ATTR \~ LLIST RETURN (r CAT >2AT \ RESTORE ~W!ATTR \~ RETURN z({*TAB \ OR STR$ r#s+:AT \ RETURN (% RETURN  x RETURN  RESTORE !CODE \ THEN F LLIST OR  LPRINT PI GO SUB BSTR$ LPRINT PI GO SUB BSTR$ "TAB \ LLIST #:AT \=2AT \ POINT !CODE \ THEN F*TAB \(PI GO SUB BA..PI GO SUB B\ RETURN  #"TAB \ LLIST #>"PEEK >= DATA  :! THEN ? THEN THEN - THEN ? THEN THEN ,T]!ATTR \~ RETURN ( FLASH OR RESTORE ~ VERIFY *TAB \r#s+"TAB \ LLIST #STR$ *TAB \ RETURN PI GO SUB B"TAB \ LLIST #>"PEEK >=bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    2 DEF FN a()=PEEK 23635+256*PEEK 23636+5
    9 REM   Int Editor Parms  
   10 LET l=5: LET c=0: OVER 1
   11 LET rs=0
   12 LET f=6: REM flash period
   14 LET rm=31: REM right margin
   16 LET lm=0: REM left margin
   18 LET bm=8: REM bottom margin
   20 LET tm=4: REM top margin
   30 LET rd=10: REM repeat delay
   40 RETURN 
  100 REM        Start       
  101 FOR n=7 TO 20: PRINT AT n,0;"                                ": NEXT n
  102 INPUT "New or Old file (n or o)?";k$
  110 IF k$="o" THEN INPUT "Name of old data file?";n$
  111 IF k$="n" THEN INPUT "Name of new data file?";n$
  112 IF n$="" THEN GO TO 102
  113 IF k$="n" THEN GO TO 170
  114 PRINT AT 21,0; FLASH 1; PAPER 5;"data disk in drive'A' then ENTER"
  116 PAUSE 4e4
  117 PRINT AT 21,0; FLASH 1; PAPER 5;"          files loading         "
  118 LET erret=102: POKE 23729,255
  120 LOAD *n$+".ix1" DATA s$()
  121 IF PEEK 23728<>0 THEN GO TO 4000
  128 LOAD *n$+".ix2" DATA i$()
  129 IF PEEK 23728<>0 THEN GO TO 4000
  130 LOAD *n$+".ptr" DATA p()
  132 IF PEEK 23728<>0 THEN GO TO 4000
  133 LET CURrec=p(1): LET LSTrec=p(2): LET PHYrec=p(3)
  140 OPEN #*1;n$+".dat";r;128
  150 GO TO 2000
  170 REM   new file  
  172 PRINT AT 21,0; FLASH 1; PAPER 5;"data disk in drive'A' then ENTER": PAUSE 4e4: PRINT AT 21,0; PAPER 5;"                                "
  174 POKE 23728,9: POKE 23729,10: POKE 23723,2
  176 RANDOMIZE USR FN a()
  178 REM "please wait"
  180 PRINT AT 21,0; FLASH 1; PAPER 5;"    intilization in progress    "
  182 LET erret=102: POKE 23729,255: POKE 23728,0
  183 DIM s$(1000,15)
  184 IF PEEK 23728<>0 THEN GO TO 4000
  185 DIM i$(1000,2)
  186 IF PEEK 23728<>0 THEN GO TO 4000
  187 DIM p(3)
  188 IF PEEK 23728<>0 THEN GO TO 4000
  189 FOR n=1 TO 1000
  190 LET hi=INT (n/256)
  192 LET lo=n-(hi*256)
  194 LET i$(n,1)=CHR$ hi
  196 LET i$(n,2)=CHR$ lo
  198 NEXT n
  199 REM RANDOMIZE USR 63007: REM MC int-index
  200 DIM *n$+".dat"
  201 IF PEEK 23728<>0 THEN GO TO 4000
  202 SAVE *n$+".ix1" DATA s$()
  203 IF PEEK 23728<>0 THEN GO TO 4000
  204 SAVE *n$+".ix2" DATA i$()
  205 IF PEEK 23728<>0 THEN GO TO 4000
  206 LET CURrec=1
  208 LET LSTrec=1
  210 LET PHYrec=1
  211 LET sflg=0
  212 OPEN #*1;n$+".dat";r;128
  214 LET r$="                                                                                                                                "
  216 PRINT *#1;r$;AT 1
  220 GO TO 2000
  310 PRINT AT 8,0;"     Which printer interface","           do you use?"
  315 PRINT AT 12,0;"          1 = Aerco","          2 = Tasman-b","          3 = Tasman-c","          4 = A & J","          5 = FDD-RS232"
  320 PRINT AT 21,0; INVERSE 1;"       press no# to select      "
  330 LET k$=INKEY$: IF k$="" THEN GO TO 330
  335 IF k$<>"1" AND k$<>"2" AND k$<>"3" AND k$<>"4" AND k$<>"5" THEN GO TO 330
  340 LET If=CODE k$-48
  345 RETURN 
  500 REM  Cofiguration Mods  
  530 IF IF=1 THEN RANDOMIZE USR 63013
  540 IF IF=2 THEN RANDOMIZE USR 63016
  545 IF IF=3 THEN RANDOMIZE USR 63019
  560 IF IF=4 THEN RANDOMIZE USR 63022
  565 IF IF=5 THEN POKE 23729,255: CLOSE #*3: POKE 23279,0: CLS : PRINT AT 0,0; INVERSE 1;"  FDD-RS232 PARAMETER SETTINGS  ": FORMAT *":ch_a": OPEN #*3;":ch_a";o;1: RANDOMIZE USR 63025: CLS 
  570 RETURN 
 1000 REM   PRNT_REC  
 1002 PRINT AT 20,0;"Record #";CURrec;"  "
 1010 PRINT AT 5,0;r$(1 TO 32)
 1020 PRINT AT 6,0;r$(33 TO 64)
 1030 PRINT AT 7,0;r$(65 TO 96)
 1040 PRINT AT 8,0;r$(97 TO )
 1050 RETURN 
 1100 REM   DRW_WND  
 1110 PAPER 5: BORDER 5: CLS 
 1120 POKE 23728,0: POKE 23729,10
 1130 POKE 23723,3
 1140 RANDOMIZE USR FN a()
 1150 REM "Z-MAIL"
 1155 POKE 23728,0: POKE 23729,0: PAPER 7
 1160 PRINT AT 5,0;"                                                                                                                                ": GO SUB 1161: RETURN 
 1161 PRINT AT 11,0; PAPER 5;"_________ Control Keys _________"
 1162 PRINT AT 13,0; PAPER 5;"  Modify Insert Delete Append   "
 1164 PRINT AT 15,0; PAPER 5;"  Goto   Quit   Sort   Print    "        
 1166 PRINT AT 17,0; PAPER 5;"  ^up/dwn arrows to view records"
 1170 RETURN 
 1498 GO SUB 3200: REM  EDITOR   
 1499 LET is=0: LET flctr=f
 1502 LET flctr=flctr-1
 1504 IF flctr=0 THEN PRINT AT l,c;" ": LET is=(is=0): LET flctr=f
 1560 LET k=CODE INKEY$
 1562 IF k=0 THEN LET k=1
 1564 IF z(k)=1500 THEN GO TO 1500
 1566 IF is=0 THEN GO TO z(k)
 1568 PRINT AT l,c;" ": LET is=0
 1570 GO TO z(k)
 1595 BEEP .005,10
 1596 LET cnt=rd: IF INKEY$<>"" AND rs=1 THEN LET flctr=0: GO TO 1504
 1597 LET cnt=cnt-1: LET rs=1: IF cnt=0 THEN GO TO 1499
 1598 IF INKEY$<>"" THEN GO TO 1597
 1599 LET rs=0: LET flctr=0: GO TO 1504
 1600 REM   Print Char  
 1620 PRINT AT l,c; OVER 0;CHR$ k; OVER 1
 1622 LET r$(((l-5)*32)+c+1)=CHR$ k
 1632 GO SUB 1685
 1634 GO TO 1595
 1650 REM   Cmove  
 1660 GO SUB ((k-8)*5)+1680
 1670 GO TO 1595
 1680 REM   Left  
 1682 LET c=c-1
 1683 IF c=lm-1 THEN LET c=lm
 1684 RETURN 
 1685 REM  right 
 1686 LET c=c+1
 1687 IF c=rm+1 THEN LET c=rm
 1689 RETURN 
 1690 REM   Down  
 1691 LET l=l+1: IF l=bm+1 THEN LET l=bm
 1692 RETURN 
 1695 REM   Up   
 1696 LET l=l-1: IF l=tm-1 THEN LET l=tm
 1697 RETURN 
 1700 REM   Next Ln  
 1704 LET l=l+1: IF l>bm THEN LET l=bm
 1705 LET c=lm
 1706 GO TO 1595
 1740 REM   Delete  
 1742 GO SUB 1680
 1744 PRINT AT l,c; OVER 0;" "; OVER 1
 1746 LET r$(((l-5)*32)+c+1)=" "
 1748 GO TO 1595
 2000 REM       MAIN  LOOP      
 2013 GO SUB 1100: REM drw window
 2020 LET PHYrec=CODE I$(CURrec,1)*256+CODE I$(CURrec,2)
 2026 INPUT *#1;r$;AT PHYrec
 2030 REM   DIS_REC  
 2050 GO SUB 1000: REM prnt rec
 2060 REM   RD_KEY   
 2070 LET k=CODE INKEY$
 2072 IF k=71 THEN GO TO 2800
 2074 IF k=81 THEN GO TO 2700
 2076 IF k=83 THEN GO TO 3100
 2078 IF k=80 THEN GO TO 3300
 2080 IF k=10 THEN GO TO 2200
 2090 IF k=11 THEN GO TO 2300
 2100 IF k=68 THEN GO TO 2600
 2110 IF k=77 THEN GO TO 2400
 2120 IF k=73 THEN GO TO 2900
 2130 IF k=65 THEN GO TO 2500
 2140 GO TO 2060
 2200 REM   LST_REC   
 2210 IF CURrec=1 THEN BEEP .05,20: PRINT AT 21,0; PAPER 5; FLASH 1;"         bottom of file         ": PAUSE 100: PRINT AT 21,0; PAPER 5;"                                ": GO TO 2060
 2220 LET CURrec=CURrec-1
 2222 BEEP .01,0
 2240 GO TO 2020
 2300 REM   NXT_REC  
 2310 IF CURrec=LSTrec THEN BEEP .05,20: PRINT AT 21,0; PAPER 5; FLASH 1;"          end of file           ": PAUSE 100: PRINT AT 21,0; PAPER 5;"                                ": GO TO 2060
 2320 LET CURrec=CURrec+1
 2322 BEEP .01,0
 2350 GO TO 2020
 2400 REM   MOD_REC  
 2410 LET z(226)=2432
 2420 GO SUB 10: REM int edt parm
 2430 GO TO 1498: REM editor
 2432 OVER 0: GO SUB 1161
 2440 LET PHYrec=CODE I$(CURrec,1)*256+CODE I$(CURrec,2)
 2450 PRINT *#1;r$;AT PHYrec
 2452 GO SUB 3029: REM parse name
 2454 LET s$(CURrec)=r$(n+1 TO n+10)+r$(97 TO 102)
 2460 GO TO 2025
 2500 REM   ADD_REC  
 2510 IF CURrec=1000 THEN BEEP .05,20: PRINT AT 21,0; PAPER 5; FLASH 1;"           file full            ": PAUSE 100: PRINT AT 21,0; PAPER 5;"                                ": GO TO 2060
 2518 LET CURrec=LSTrec+1
 2520 LET LSTrec=LSTrec+1
 2521 IF CURrec=2 AND sflg=0 THEN LET CURrec=1: LET sflg=1: LET LSTrec=LSTrec-1
 2526 LET z(226)=2432
 2530 LET r$="                                                                                                                                "
 2550 GO SUB 1000: REM prnt rec
 2560 GO SUB 10: REM int edit prm
 2570 GO TO 1498: REM ret via 2432
 2600 REM   DEL_REC  
 2601 INPUT BRIGHT 1;"Delete record?(y or n)";k$
 2602 IF k$<>"y" THEN GO TO 2060
 2604 IF LSTrec=1 THEN GO TO 2020
 2610 LET t$=I$(CURrec)
 2621 IF CURrec=1 THEN BEEP .05,20: PRINT AT 21,0; PAPER 5; FLASH 1;"          last record           ": PAUSE 100: PRINT AT 21,0; PAPER 5;"                                ": GO TO 2060
 2630 IF CURrec=LSTrec THEN LET CURrec=CURrec-1: GO TO 2670
 2640 FOR n=CURrec+1 TO LSTrec
 2650 LET I$(n-1)=I$(n)
 2652 LET s$(n-1)=s$(n)
 2660 NEXT n
 2670 LET I$(LSTrec)=t$
 2680 LET LSTrec=LSTrec-1
 2690 GO TO 2020
 2700 REM   Quit    
 2701 INPUT BRIGHT 1;"Quit program?(y or n)";k$
 2702 IF k$<>"y" THEN GO TO 2060
 2710 PRINT AT 21,0; FLASH 1; PAPER 5;"data disk in drive'A' then ENTER": PAUSE 4e4: PRINT AT 21,0; PAPER 5;"                                "
 2711 CLOSE #*1: LET erret=2700: POKE 23729,255
 2712 SAVE *n$+".ix1" DATA s$()n
 2713 IF PEEK 23728<>0 THEN GO TO 4000
 2714 SAVE *n$+".ix2" DATA i$()n
 2715 IF PEEK 23728<>0 THEN GO TO 4000
 2716 LET p(1)=CURrec: LET p(2)=LSTrec: LET p(3)=PHYrec
 2717 SAVE *n$+".ptr" DATA p()n
 2718 IF PEEK 23728<>0 THEN GO TO 4000
 2720 CLS : NEW 
 2800 REM   Goto record  
 2810 INPUT BRIGHT 1;"Record to goto?";k$
 2811 IF k$="" THEN GO TO 2020
 2812 ON ERR GO TO 2850
 2814 LET k=INT (VAL k$)
 2816 ON ERR RESET 
 2821 IF k>LSTrec OR k<1 THEN BEEP .05,20: PRINT AT 21,0; PAPER 5; FLASH 1;"       record not in file       ": PAUSE 100: PRINT AT 21,0; PAPER 5;"                                ": GO TO 2810
 2830 LET CURrec=k
 2835 PRINT AT 21,0; PAPER 5;"                                "
 2840 GO TO 2020
 2850 ON ERR RESET : PRINT AT 21,0; FLASH 1; PAPER 5;"       search in progress       "
 2851 IF tog=1 THEN GO TO 2860
 2852 FOR k=1 TO LSTrec
 2854 IF s$(k,1 TO LEN k$)=k$ THEN GO TO 2830
 2856 NEXT k
 2857 LET k=CURrec
 2858 BEEP .05,20: PRINT AT 21,0; PAPER 5; FLASH 1;"        record not found        ": PAUSE 120: GO TO 2830
 2859 REM   mc version  
 2860 POKE 63029,INT ((LSTrec+1)/256)
 2861 LET buf=63035: POKE 63028,(LSTrec+1)-((INT ((LSTrec+1)/256))*256)
 2862 FOR n=1 TO LEN k$
 2863 POKE buf,CODE k$(n)
 2864 LET buf=buf+1
 2865 NEXT n
 2866 POKE buf,254
 2867 RANDOMIZE USR 63001: REM srch
 2870 LET n=PEEK 63033+256*PEEK 63034
 2880 IF n=0 THEN GO TO 2857
 2882 LET k=n: GO TO 2830
 2900 REM   INS_REC  
 2902 IF LSTrec=1 THEN GO TO 2025
 2910 LET t$=I$(LSTrec+1)
 2920 FOR n=LSTrec TO CURrec STEP -1
 2930 LET I$(n+1)=I$(n)
 2932 LET s$(n+1)=s$(n)
 2940 NEXT n
 2950 LET I$(CURrec)=t$
 2952 LET s$(CURrec)="               "
 2970 GO TO 2520
 3000 REM   Pull all LST names 
 3002 OPEN #*1;"mlist.dat";r;128
 3010 FOR m=1 TO LSTrec
 3021 LET PHYrec=CODE I$(m,1)*256+CODE I$(m,2)
 3022 INPUT *#1;r$;AT PHYrec
 3024 GO SUB 3030
 3026 GO TO 3080
 3029 REM   parse name  
 3030 LET x=0
 3031 FOR n=32 TO 1 STEP -1
 3040 IF r$(n)<>" " THEN LET x=1
 3050 IF r$(n)=" " AND x=1 THEN RETURN 
 3060 NEXT n
 3062 RETURN 
 3063 REM   end of rtn  
 3080 LET s$(m)=r$(n+1 TO )
 3090 NEXT m
 3092 RETURN 
 3100 REM   Sort alpha/num  
 3102 INPUT BRIGHT 1;"Sort name or zip?(n or z)";k$
 3103 IF k$="" THEN GO TO 2020
 3104 IF k$<>"n" AND k$<>"z" THEN GO TO 3102
 3106 PRINT AT 21,0; FLASH 1; PAPER 5;"        sort in progress        "
 3108 IF tog=1 THEN GO TO 3167
 3110 FOR m=1 TO LSTrec-1
 3120 FOR n=m+1 TO LSTrec
 3130 IF k$="n" AND s$(m, TO 10)<=s$(n, TO 10) THEN GO TO 3163
 3132 IF k$="z" AND s$(m,11 TO )<=s$(n,11 TO ) THEN GO TO 3163
 3140 LET t$=I$(n)+s$(n)
 3150 LET s$(n)=s$(m)
 3152 LET I$(n)=I$(m)
 3160 LET s$(m)=t$(3 TO )
 3162 LET I$(m)=t$(1 TO 2)
 3163 NEXT n
 3164 NEXT m
 3165 PRINT AT 21,0; PAPER 5;"                                "
 3166 GO TO 2020
 3167 REM   mc version   
 3168 IF k$="n" THEN POKE 63030,0
 3169 IF k$="z" THEN POKE 63030,1
 3170 POKE 63029,INT (LSTrec/256)
 3171 POKE 63028,LSTrec-((INT (LSTrec/256))*256)
 3174 RANDOMIZE USR 63004: REM sort
 3176 GO TO 3165
 3200 REM   edit contrl keys  
 3201 OVER 0
 3210 PRINT AT 11,0; PAPER 5;"______ Editor Control Keys ____"
 3220 PRINT AT 13,0; PAPER 5;"STOP=exit editor ENTER=next line"
 3230 PRINT AT 15,0; PAPER 5;"CS/0=delete char  ^=arrows move"
 3240 PRINT AT 17,0; PAPER 5;"                                "
 3245 OVER 1
 3250 RETURN 
 3299 REM   Print function  
 3300 GO TO 3600
 3301 LET str=1: LET fin=LSTrec
 3302 INPUT BRIGHT 1;"labels or summary?(l or s)";k$: IF k$="" THEN GO TO 3300
 3303 IF k$<>"l" AND k$<>"s" THEN GO TO 3302
 3304 IF k$="l" THEN GO SUB 3500
 3305 IF k$="s" THEN GO SUB 3402
 3306 IF k$="" THEN GO TO 2060
 3309 ON ERR GO TO 3310
 3310 INPUT BRIGHT 1;"Print from Rec#?(1)";k$
 3320 IF k$="" THEN GO TO 3340
 3330 LET str=VAL k$
 3340 ON ERR GO TO 3342
 3342 INPUT BRIGHT 1;"Print to Rec#?(LSTrec)";k$
 3350 IF k$="" THEN GO TO 3370
 3360 LET fin=VAL k$: IF fin>1000 THEN LET fin=1000
 3370 ON ERR RESET 
 3372 PRINT AT 21,0; INVERSE 1; PAPER 5;" press ENTER to abort printing  "
 3380 FOR n=str TO fin
 3385 LET PHYrec=CODE I$(n,1)*256+CODE I$(n,2)
 3390 INPUT *#1;r$;AT PHYrec
 3391 LET CURrec=n: GO SUB 1000
 3392 LPRINT t$;r$(1 TO 32);
 3393 LPRINT t$;r$(33 TO 64);
 3394 LPRINT t$;r$(65 TO 96);
 3396 LPRINT t$;r$(97 TO end);: IF pf=1 THEN LPRINT 
 3397 IF pf=0 THEN FOR m=1 TO space: LPRINT : NEXT m
 3398 PAUSE 60: IF INKEY$<>"" THEN GO TO 3400
 3399 NEXT N
 3400 PRINT AT 21,0; PAPER 5;"                                ": IF INKEY$<>"" THEN GO TO 3400
 3401 GO TO 2060
 3402 REM   print sumarry  
 3410 POKE 63000,128: RANDOMIZE USR 63010
 3420 POKE 23728,1: LPRINT CHR$ 15;: POKE 23728,0
 3425 LET pf=1: LET end=128
 3426 LET t$=CHR$ 17+CHR$ 5
 3430 RETURN 
 3432 ON ERR GO TO 3432: ON ERR RESET : RETURN 
 3500 REM   print labels  
 3510 POKE 63000,80: RANDOMIZE USR 63010
 3520 POKE 23728,1: LPRINT CHR$ 27;CHR$ 64;: POKE 23728,0
 3525 LET pf=0: LET end=103
 3526 LET t$=CHR$ 13
 3527 FOR n=1 TO lftmrg
 3528 LET t$=t$+" "
 3529 NEXT n
 3530 RETURN 
 3600 REM   IF customize  
 3610 INPUT BRIGHT 1;"Configure interface?(y or n)";k$
 3612 IF k$="" THEN GO TO 2060
 3620 IF k$<>"y" THEN GO TO 3301
 3630 CLS 
 3640 GO SUB 300: REM IF menu
 3642 GO SUB 500: REM do custom
 3650 GO SUB 1100: REM drw wnd
 3660 GO SUB 1000: REM prnt rec
 3680 GO TO 3301
 4000 REM  disk error 
 4010 CLS 
 4020 LET k=PEEK 23728
 4030 PRINT AT 10,8; FLASH 1;" disk error: ";k;" "
 4040 PRINT AT 13,4;"press ENTER to try again"
 4050 PAUSE 4e4
 4055 CLS 
 4060 GO TO erret
 9900 REM                    
 9901 OPEN #*1;"mlist.dat";I;128
 9910 INPUT *#1;a$
 9920 PRINT a$;
 9930 GO TO 9910
 9995 LPRINT "            Record Index        ": FOR n=1 TO LSTrec+900
 9996 LET PHYrec=CODE I$(n,1)*256+CODE I$(n,2)
 9997 LPRINT n;" ";s$(n);"/";" PHYrec=";PHYrec: IF n=LSTrec THEN LPRINT "-------------------------------"
 9998 NEXT n
 9999 LET m=PEEK 63002+256*PEEK 63003: FOR n=m TO 64000: PRINT n;"  ";CHR$ PEEK n: NEXT n

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.