Mini Data Base

This file is part of and Timex Sinclair Public Domain Library Tape 1006. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000
Tags: Database

This program implements a flat-file mini database for the ZX81/TS1000 that stores all records in a single string variable A$, using CHR$ 111 (“o”) as a record separator and CHR$ 67–70 as field delimiters within each record. It supports five operations: data entry (up to four fields per record), deletion, editing, keyword search, and saving the data string to cassette tape. The menu dispatches to subroutines using the idiom GOTO VAL Y$*1000, where the user’s key press (codes 29–34 representing digits 1–5 in ZX81 character set) selects the 1000-level line block. The search routine includes a COPY command triggered by pressing “Z” to produce a printer hard copy of found records.


Program Analysis

Program Structure

The program is organised into discrete 1000-line blocks, each corresponding to a menu option. The main menu occupies lines 100–260, and execution branches via GOTO VAL Y$*1000 at line 260, dispatching to one of five routines:

  1. Lines 1000–1430: Data entry
  2. Lines 2000–2320: Delete a data block
  3. Lines 3000–3720: Edit a data block
  4. Lines 4000–4799: Keyword search
  5. Lines 5000–5080: Save data to cassette

Lines 5060–5080 (CLEAR, SAVE "1025", RUN) appear after the SAVE routine’s GOTO 100 and are therefore unreachable during normal execution. They likely represent a vestigial attempt at saving the program itself.

Data Storage Model

All database records are stored in the single string variable A$, initialised at line 10 to CHR$ 111 (the letter “o”). Each record consists of four fields separated by specific delimiter characters:

CHR$ codeCharacterRole
111oRecord separator (start/end of record)
67CEnd of Subject field
68DEnd of Item 1 field
69EEnd of Item 2 field
70FEnd of Item 3 / Last Item field

This scheme is fragile: any user input containing the letters C, D, E, F, or lowercase “o” will corrupt the delimiter structure. This is a significant bug — the program does not sanitise or validate field input against these reserved characters.

Menu Dispatch Idiom

Line 230 gates valid input by checking CODE Y$<29 OR CODE Y$>34. On the ZX81, character codes 29–33 correspond to the digit characters 1–5. Line 260 uses GOTO VAL Y$*1000 to jump directly to the appropriate 1000-block, a compact and efficient dispatch mechanism that avoids a chain of IF statements.

Search and Navigation

The keyword search at line 4000 scans A$ with a FOR/NEXT loop comparing substrings of length LEN C$. When a match is found, the code walks backwards from position N to locate the preceding CHR$ 111 record boundary (variable A), then forwards to find the closing boundary (variable B), isolating the record into D$. The subroutine at line 4800 prints up to the next delimiter and then trims D$ in place using LET D$=D$(N TO LEN D$).

There is a bug at line 4360: the search for the second field delimiter uses CODE D$(N)=63 (character “?”) rather than the expected 68 (“D”). This means Item 1 will never be correctly located or printed during a search display.

Delete and Edit Logic

Deletion (line 2310) reconstructs A$ by concatenating the portion before the found record with the portion after it: LET A$=A$( TO A)+A$(B+1 TO LEN A$). This correctly excises the block including its trailing CHR$ 111 separator.

The edit routine at line 3710 uses a similar splice: LET A$=A$( TO A)+F$+A$(B TO LEN A$). Note that unlike the delete case, it preserves the trailing boundary by including A$(B TO ...) rather than A$(B+1 TO ...), which is correct since the rebuilt F$ does not include the closing CHR$ 111.

The edit flow contains dead code: after locating the record into D$ at line 3170, execution jumps to 3800 for confirmation, but a “not found” retry at line 3850 sends control to 3070 (the NEXT of the search loop), which may iterate incorrectly after the loop variable is exhausted. Line 3175 (GOTO 3800) causes lines 3180 onwards to be unreachable on the first pass; they are only reached from line 3840 (IF INKEY$="Y" THEN GOTO 3180), which is the intended confirmation path.

FAST/SLOW Usage

The program switches between FAST and SLOW modes frequently. SLOW is invoked before INPUT statements to enable the display (required for the user to see what they are typing on a ZX81), and FAST is restored for processing and printing loops. This is standard ZX81 practice to balance display visibility with execution speed.

Notable Techniques

  • The prompt at line 210 is printed twice: first as normal video text, then overprinted in inverse video using the % escape sequences, producing a highlighted instruction without needing separate PRINT AT coordinates.
  • PAUSE 40000 (lines 2290, 3830, 4705) is used as an indefinite wait for a keypress, exploiting the fact that on a ZX81 PAUSE 40000 is effectively infinite until interrupted.
  • The cassette SAVE at line 5040 saves only the A$ variable (the entire database), not the program itself, allowing the data to be reloaded independently.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10252 – 10293.

Related Products

Related Articles

Related Content

Image Gallery

Mini Data Base

Source Code

   5 REM "DBAS%E"
  10 LET A$=CHR$ 111
 100 FAST 
 110 CLS 
 120 PRINT AT 1,10;"MINI DATA BASE"
 130 PRINT AT 4,0;"TO ENTER DATA";TAB 30;1
 140 PRINT AT 6,0;"TO DELETE DATA";TAB 30;2
 150 PRINT AT 8,0;"TO EDIT DATA";TAB 30;3
 160 PRINT AT 10,0;"TO SEARCH FOR DATA";TAB 30;4
 170 PRINT AT  12,0;"TO SAVE DATA ON TAPE";TAB 30;5
 200 SLOW 
 210 PRINT AT 21,6;" ENTER ONE OF ABOVE";AT 21,6;"% %E%N%T%E%R% %O%N%E% %O%F% %A%B%O%V%E% "
 220 LET Y$=INKEY$
 230 IF CODE Y$<29 OR CODE Y$>34 THEN GOTO 210
 240 FAST 
 250 CLS 
 260 GOTO VAL Y$*1000
 1000 REM %D%A%T%A% %E%N%T%R%Y
 1010 CLS 
 1020 PRINT 
 1030 PRINT "SUBJECT?"
 1035 SLOW 
 1040 INPUT B$
 1045 PRINT ,,B$
 1050 IF B$="" THEN GOTO 100
 1060 LET A$=A$+B$+CHR$ 67
 1070 PRINT ,,"ITEM NO. 1?"
 1080 INPUT B$
 1085 PRINT ,,B$
 1090 LET A$=A$+B$+CHR$ 68
 1100 PRINT ,,"ITEM NO. 2?"
 1110 INPUT B$
 1115 PRINT ,,B$
 1120 LET A$=A$+B$+CHR$ 69
 1130 PRINT ,,"ITEM NO. 3?"
 1140 INPUT B$
 1145 PRINT ,,B$
 1150 LET A$=A$+B$+CHR$ 70
 1400 PRINT ,,"LAST ITEM?"
 1410 INPUT B$
 1415 PRINT ,,B$
 1416 PAUSE 100
 1420 LET A$=A$+B$+CHR$ 111
 1430 GOTO 1000
 2000 REM %D%E%L%E%T%E% %D%A%T%A% %B%L%O%C%K
 2010 PRINT AT 10,0;"ENTER KEYWORD OF DATA TO BE     DELETED :::"
 2020 SLOW 
 2030 INPUT C$
 2040 FAST 
 2050 FOR N=1 TO LEN A$-LEN C$+1
 2060 IF A$(N TO N+LEN C$-1)=C$ THEN GOTO 2200
 2070 NEXT N
 2080 CLS 
 2090 PRINT AT 10,0;"DATA NOT IN FILE :::"
 2100 PAUSE 500
 2120 GOTO 100
 2200 FOR A=N TO 1 STEP -1
 2210 IF CODE A$(A)=111 THEN GOTO 2230
 2220 NEXT A
 2230 FOR B=N TO LEN A$
 2240 IF CODE A$(B)=111 THEN GOTO 2260
 2250 NEXT B
 2260 CLS 
 2270 PRINT ,,A$(A+1 TO B-1)
 2280 PRINT ,,"IS THIS THE DATA BLOCK YOU WANT DELETED?"
 2290 PAUSE 40000
 2300 IF INKEY$="N" THEN GOTO 2070
 2310 LET A$=A$(  TO A)+A$(B+1 TO LEN A$)
 2320 GOTO 100
 3000 REM %E%D%I%T% %D%A%T%A: 
 3010 PRINT ,,"ENTER KEYWORD?"
 3020 SLOW 
 3030 INPUT C$
 3040 FAST 
 3050 FOR N=1 TO LEN A$-LEN C$+1
 3060 IF A$(N TO N+LEN C$-1)=C$ THEN GOTO 3100
 3070 NEXT N
 3080 GOTO 2080
 3100 FOR A=N TO 1 STEP -1
 3120 IF CODE A$(A)=111 THEN GOTO 3140
 3130 NEXT A
 3140 FOR B=N TO LEN A$
 3150 IF CODE A$(B)=111 THEN GOTO 3170
 3160 NEXT B
 3170 LET D$=A$(A+1 TO B-1)
 3175 GOTO 3800
 3180 FOR I=1 TO LEN D$
 3190 IF CODE D$(I)=67 THEN GOTO 3210
 3200 NEXT I
 3210 CLS 
 3220 PRINT ,,"SUBJECT IS ";D$( TO I-1)
 3230 PRINT ,,"ENTER NEW SUBJECT OR PRESS ENTERFOR NO CHANGE?"
 3240 SLOW 
 3250 INPUT E$
 3260 IF E$="" THEN LET E$=D$( TO I-1)
 3265 LET D$=E$+D$(I TO LEN D$)
 3270 FAST 
 3275 LET F$=E$+CHR$ 67
 3280 CLS 
 3290 LET C=I+1
 3300 FOR I=C TO LEN D$
 3310 IF CODE D$(I)=68 THEN GOTO 3330
 3320 NEXT I
 3330 PRINT ,,"ITEM 1 IS ";D$(C TO I-1)
 3340 PRINT ,,"ENTER NEW ITEM OR PRESS ENTER   FOR NO CHANGE?"
 3350 SLOW 
 3360 INPUT E$
 3370 IF E$="" THEN LET E$=D$(C TO I-1)
 3380 LET F$=F$+E$+CHR$ 68
 3390 FAST 
 3400 CLS 
 3410 LET C=I+1
 3420 FOR I=C TO LEN D$
 3430 IF CODE D$(I)=69 THEN GOTO 3450
 3440 NEXT I
 3450 PRINT ,,"ITEM 2 IS ";D$(C TO I-1)
 3460 PRINT ,,"ENTER NEW ITEM OR PRESS ENTER   FOR NO CHANGE?"
 3465 SLOW 
 3470 INPUT E$
 3480 IF E$="" THEN LET E$=D$(C TO I-1)
 3490 LET F$=F$+E$+CHR$ 69
 3500 FAST 
 3510 CLS 
 3520 LET C=I+1
 3530 FOR I=C TO LEN D$
 3540 IF CODE D$(I)=70 THEN GOTO 3560
 3550 NEXT I
 3560 PRINT ,,"ITEM 3 IS ";D$(C TO I-1)
 3575 SLOW 
 3580 INPUT E$
 3590 IF E$="" THEN LET E$=D$(C TO I-1)
 3600 LET F$=F$+E$+CHR$ 70
 3610 FAST 
 3620 CLS 
 3630 LET C=I+1
 3640 PRINT ,,"LAST ITEM IS ";D$(C TO LEN D$)
 3650 PRINT ,,"ENTER NEW ITEM OR PRESS ENTER   FOR NO CHANGE?"
 3655 SLOW 
 3660 INPUT E$
 3670 IF E$="" THEN LET E$=D$(C TO LEN D$)
 3680 LET F$=F$+E$
 3690 FAST 
 3700 CLS 
 3710 LET A$=A$( TO A)+F$+A$(B TO LEN A$)
 3720 GOTO 100
 3800 CLS 
 3810 PRINT ,,D$
 3820 PRINT ,,,,"IS THIS THE CORRECT DATA BLOCK?"
 3830 PAUSE 40000
 3840 IF INKEY$="Y" THEN GOTO 3180
 3850 GOTO 3070
 4000 REM %K%E%Y%W%O%R%D% %S%E%A%R%C%H% 
 4010 CLS 
 4020 PRINT AT 10,0;"ENTER KEYWORD OR PHRASE?"
 4030 SLOW 
 4040 INPUT C$
 4050 FAST 
 4060 CLS 
 4070 FOR N=1 TO LEN A$-LEN C$+1
 4080 IF A$(N TO N+LEN C$-1)=C$ THEN GOTO 4200
 4090 NEXT N
 4100 PRINT AT 10,0;"NOT IN FILE :::"
 4120 PAUSE 500
 4130 GOTO 100
 4200 LET NN=N
 4205 FOR A=N TO 1 STEP -1
 4210 IF A$(A)=CHR$ 111 THEN GOTO 4230
 4220 NEXT A
 4230 FOR B=N TO LEN A$
 4240 IF A$(B)=CHR$ 111 THEN GOTO 4300
 4250 NEXT B
 4300 LET D$=A$(A TO B)
 4310 FOR N=1 TO LEN D$
 4320 IF CODE D$(N)=67 THEN GOTO 4340
 4330 NEXT N
 4340 GOSUB 4800
 4350 FOR N=1 TO LEN D$
 4360 IF CODE D$(N)=63 THEN GOTO 4380
 4370 NEXT N
 4380 GOSUB 4800
 4390 FOR N=1 TO LEN D$
 4400 IF CODE D$(N)=69 THEN GOTO 4420
 4410 NEXT N
 4420 GOSUB 4800
 4430 FOR N=1 TO LEN D$
 4440 IF CODE D$(N)=70 THEN GOTO 4460
 4450 NEXT N
 4460 GOSUB 4800
 4700 PRINT D$(2 TO LEN D$)
 4705 PAUSE 40000
 4710 IF INKEY$="Z" THEN COPY 
 4720 CLS 
 4730 FOR N=NN+1 TO LEN A$-LEN C$+1
 4740 GOTO 100
 4799 STOP 
 4800 PRINT D$(2 TO N-1)
 4810 PRINT 
 4820 LET D$=D$(N TO LEN D$)
 4830 RETURN 
 5000 REM % %S%A%V%E% %D%A%T%A% %O%N% %C%A%S%S%E%T%T%E% 
 5010 PRINT ,,"ENTER FILE NAME, PREPARE","RECORDER AND PRESS ENTER:::"
 5020 SLOW 
 5030 INPUT Z$
 5040 SAVE Z$
 5050 GOTO 100
 5060 CLEAR 
 5070 SAVE "1025%3"
 5080 RUN 

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

People

No people associated with this content.

Scroll to Top