This program implements a “Job Jar” task management system, allowing the user to initialise a job list, add job descriptions with time estimates, mark jobs as done (removing them from the list with an array shift), pick a random job matching available time, list all jobs, and save the program to tape. Job entries are stored in a dimensioned string array B$ with 28 characters per record: 24 characters for the description and 3 characters (positions 26–28) for a numeric time estimate. The PICK function (line 4000) implements a rudimentary time-matching and randomised selection algorithm that decrements the requested time by one each pass until a matching job is found, using RND to introduce non-determinism. The save routine at line 9550 renders a pixel-accurate bitmap of the text “JOB” by reading character ROM data via PEEK from address 7680, printing inverse or normal space characters to reconstruct each glyph on screen.
Program Analysis
Program Structure
The program is organised as a menu-driven application with a central dispatcher at line 490–600 and several functional modules at higher line numbers. Shared subroutines at lines 10–70 handle common prompts (Y/N confirmation, “More?”, “Press C”, and printer copy). The main modules are:
- Lines 490–600: Main menu and dispatcher
- Lines 1000–1050: Initialise — dimension the job array
- Lines 2000–2170: Add a job entry
- Lines 3000–3160: Mark a job done and remove it
- Lines 4000–4260: Pick a random job by available time
- Lines 5000–5050: List all jobs
- Lines 9550–9680: Save program and display logo splash screen
Data Storage
Jobs are stored in a two-dimensional string array B$ dimensioned at line 1030 as DIM B$(N1,28). Each record uses a fixed 28-character layout:
| Positions | Content |
|---|---|
| 1–24 | Job description (free text) |
| 25 | Unused / padding |
| 26–28 | Time estimate (numeric string, right-padded with spaces) |
A scratch buffer X$ of 28 characters is dimensioned at line 2020 for each add operation, then copied wholesale into B$(N) at line 2140.
Input Validation
Both the ADD and PICK routines validate their numeric inputs by iterating character-by-character over the time-estimate field. The condition at lines 2070 and 4050, IF X$(K)<"A" AND X$(K)>".", attempts to accept only digits (which lie between "." and "A" in the ZX81 character set). Spaces are accepted as padding after the first character (lines 2064, 4044). This validation is applied in a FOR loop but uses GOTO to skip the first character check, which skips validation for position 26 entirely — a minor anomaly that could allow a non-digit leading character.
Job Deletion by Array Compaction
When a job is marked done (line 3000 module), the array is compacted by shifting all subsequent entries down one position (lines 3070–3090), then decrementing the job counter N at line 3100. This is a classic in-place list deletion without pointer arithmetic, achieved purely in BASIC.
Random Job Picker Algorithm
The PICK routine (lines 4085–4260) is a two-phase search. It scans all N jobs for one whose time estimate string matches X$(1 TO 3). If none is found and the search has not already been expanded (X=1 at line 4130), it decrements the requested time by 1 and retries — effectively widening the search downward. Once a matching job is found (line 4110), it is selected only with probability 1/3 using IF INT(RND*3+1)<>1 at line 4200, providing randomisation across multiple matches. The variable X is set to 1 at line 4090 on the assumption that the loop sets it, but there is a bug: X is only reset to 0 at line 4090 at the top of each retry pass, never explicitly set to 1 in the no-match path; line 4130 checks X=1 which will never be true, so the decrement loop runs indefinitely if no match is ever found.
Additionally, line 4160 contains IF T=0 THEN LET T1=T1+1, which increments T1 when the counter reaches zero, but this value is never used thereafter — this appears to be dead or vestigial code.
Character ROM Logo Renderer
The save splash screen (lines 9565–9645) renders the letters “JOB” pixel-by-pixel by reading the character ROM. For each letter in A$="JOB", it retrieves the ASCII code with CODE A$(NN) and reads 8 bytes from address 7680 + C*8 + H via PEEK. Each byte is decomposed bit-by-bit by repeatedly testing against a bitmask V (starting at 128 and halved each iteration). Set bits are printed as inverse space characters ("% ") and clear bits as a block graphic ("\@@" = two @ characters rendered as a light block). The three letters are spaced 7 columns apart starting at column 5, and rendered starting at row 3, producing a large pixelated title.
Subroutine Conventions and GOSUB Usage
Three shared subroutines are invoked repeatedly:
GOSUB 10— “CHANGE Y OR N?” prompt; sets flagF=1for Y,F=0for NGOSUB 30— “MORE Y OR N?” prompt; falls through to line 14 of subroutine 10GOSUB 40— “PRESS C TO CONTINUE” promptGOSUB 60— “COPY Y OR N?” prompt with optionalCOPYto printer
Subroutine 30 at line 34 jumps directly into the body of subroutine 10 at line 14, sharing its Y/N polling loop and RETURN — a deliberate code-reuse technique via fall-through.
Key BASIC Idioms
- Inverse-video text in messages (e.g.
"%B%A%D% %E%S%T%I%M%A%T%E") uses the ZX81 inverse character escape to highlight error notices. RAND 0at line 490 seeds the random number generator to a fixed value, ensuring reproducible picks each session start.SLOW/FASTmode switching is used around the display-intensive logo renderer and the main menu to balance display quality versus computation speed.- The copy subroutine at line 62 uses a double-poll pattern (
IF INKEY$<>"" THEN GOTO 62followed byIF INKEY$="" THEN GOTO 64) to wait for a key release then a new keypress, debouncing the input.
Content
Source Code
10 LET F=0
12 PRINT AT 21,0;"CHANGE Y OR N"
14 IF INKEY$="Y" THEN GOTO 20
16 IF INKEY$="N" THEN GOTO 22
18 GOTO 14
20 LET F=1
22 PRINT AT 21,0;" "
24 RETURN
30 LET F=0
32 PRINT AT 21,0;"MORE Y OR N"
34 GOTO 14
40 PRINT AT 21,0;"PRESS C TO CONTINUE"
42 IF INKEY$="C" THEN GOTO 22
44 GOTO 42
60 PRINT AT 21,0;"COPY Y OR N?"
62 IF INKEY$<>"" THEN GOTO 62
64 IF INKEY$="" THEN GOTO 64
66 IF INKEY$="N" THEN RETURN
68 IF INKEY$="Y" THEN COPY
70 GOTO 62
490 RAND 0
500 CLS
510 SLOW
520 PRINT "I=INITIAL, A=ADD, D=DONE"
530 PRINT "P=PICK, L=LIST, S=SAVE"
540 IF INKEY$="I" THEN GOTO 1000
550 IF INKEY$="A" THEN GOTO 2000
560 IF INKEY$="D" THEN GOTO 3000
570 IF INKEY$="P" THEN GOTO 4000
580 IF INKEY$="L" THEN GOTO 5000
590 IF INKEY$="S" THEN GOTO 9550
600 GOTO 540
1000 CLS
1010 PRINT "INPUT NUMBER OF JOBS"
1020 INPUT N1
1030 DIM B$(N1,28)
1040 LET N=0
1050 GOTO 500
2000 CLS
2002 IF N<>N1 THEN GOTO 2008
2004 PRINT "% NO MORE ROOM IN FILE% "
2006 PAUSE 100
2007 GOTO 500
2008 CLS
2009 PRINT " NUMBER OF JOBS=";N
2010 PRINT AT 1,0;" INPUT DESCRIPTION FOR JOB ";N+1
2020 DIM X$(28)
2030 INPUT X$(1 TO 24)
2035 PRINT AT 2,0;"*";X$(1 TO 24)
2040 PRINT AT 3,0;" HOURS FOR JOB ";N+1;"=";
2050 INPUT X$(26 TO 28)
2060 FOR K=26 TO 28
2062 IF K=26 THEN GOTO 2070
2064 IF X$(K)=" " THEN GOTO 2100
2070 IF X$(K)<"A" AND X$(K)>"." THEN GOTO 2100
2080 PRINT "%B%A%D% %E%S%T%I%M%A%T%E"
2090 GOTO 2040
2100 NEXT K
2105 PRINT X$(26 TO 28);" "
2110 GOSUB 10
2120 IF F=1 THEN GOTO 2008
2130 LET N=N+1
2140 LET B$(N)=X$
2150 GOSUB 30
2160 IF F=1 THEN GOTO 2000
2170 GOTO 500
3000 CLS
3010 PRINT "I HAVE COMPLETED NO. ";
3020 INPUT I
3030 IF I>N THEN GOTO 3000
3035 PRINT I
3040 PRINT B$(I)
3050 GOSUB 10
3060 IF F=1 THEN GOTO 3010
3070 FOR J=I TO N-1
3080 LET B$(J)=B$(J+1)
3090 NEXT J
3100 LET N=N-1
3110 GOSUB 30
3120 IF F=0 THEN GOTO 500
3130 IF N<>0 THEN GOTO 3000
3140 PRINT "%N%O% %M%O%R%E% %J%O%B%S"
3150 PAUSE 100
3160 GOTO 500
4000 CLS
4005 DIM X$(3)
4010 IF N=0 THEN GOTO 3140
4020 PRINT "INPUT AVAILABLE TIME"
4030 INPUT X$(1 TO 3)
4040 FOR K=1 TO 3
4042 IF K=1 THEN GOTO 4050
4044 IF X$(K)=" " THEN GOTO 4080
4050 IF X$(K)<"A" AND X$(K)>"." THEN GOTO 4080
4060 PRINT "%B%A%D% %I%N%P%U%T"
4065 PAUSE 100
4070 GOTO 4000
4080 NEXT K
4085 FAST
4090 LET X=0
4100 FOR K=1 TO N
4110 IF B$(K,26 TO 28)=X$(1 TO 3) THEN GOTO 4200
4120 NEXT K
4130 IF X=1 THEN GOTO 4090
4140 LET T=VAL X$(1 TO 3)
4145 LET T1=T
4150 LET T=T-1
4160 IF T=0 THEN LET T1=T1+1
4170 LET X$(1 TO 3)=STR$ T
4180 GOTO 4090
4200 IF INT (RND*3+1)<>1 THEN GOTO 4090
4210 CLS
4215 SLOW
4220 PRINT "%J%O%B% %I%S:"
4230 PRINT B$(K)
4240 PRINT
4250 GOSUB 40
4260 GOTO 500
5000 CLS
5010 FOR K=1 TO N
5020 PRINT K;TAB 4;B$(K)
5030 NEXT K
5040 GOSUB 60
5050 GOTO 500
9550 CLS
9551 SAVE "JO%B"
9555 LET A$="JOB"
9560 FAST
9565 LET NN=0
9570 FOR L=5 TO 19 STEP 7
9575 LET NN=NN+1
9580 LET C=CODE A$(NN)
9585 FOR H=0 TO 7
9590 LET P=PEEK (7680+C*8+H)
9595 LET V=128
9600 FOR G=0 TO 7
9605 IF P<V THEN GOTO 9625
9610 PRINT AT H+3,G+L;"% "
9615 LET P=P-V
9620 GOTO 9630
9625 PRINT AT H+3,G+L;"@@"
9630 LET V=V/2
9635 NEXT G
9640 NEXT H
9645 NEXT L
9650 PRINT " JOB JAR COPYRIGHT UAS"
9655 PRINT "BOX 612 HADDONFIELD, N.J. 08033"
9660 PAUSE 200
9670 CLS
9680 GOTO 490
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.


