Inventory

This file is part of Synchro-Sette December 1982 . Download the collection to get this file.
Date: December 1982
Type: Program
Platform(s): TS 1000
Tags: Business

This program implements a stock inventory management system storing up to 100 items in a two-dimensional string array, with each record occupying a fixed 32-character row divided into named fields: item name (columns 1–8), part number (10–15), unit cost (17–22), items per unit (24–27), and units in stock (29–32). The main menu uses inverse-video characters for labels and an animated prompt loop at line 180 that flickers between inverse and normal text to attract attention. Field formatting is handled by subroutines at lines 8000–8230 that pad strings with leading spaces or append missing decimal places to ensure fixed-width storage. Navigation uses computed GOTO destinations (e.g. `GOTO 1000*VAL B$` and `GOTO (VAL B$*200)+2100`) to dispatch menu choices, a common ZX81/TS1000 space-saving technique. The program saves its data array to tape using a user-supplied filename and uses `RUN` at line 4020 to perform a full data clear.


Program Analysis

Program Structure

The program is organised into several functional regions, each entered via computed GOTO from a menu:

Line RangeFunction
10–260Initialisation and main menu (options 1–4)
1000–1540Enter / add inventory items
2000–2820View data sub-menu and sub-functions (total view, change stock, view item)
2900–2999Edit item data sub-function
3000–3080Save data to tape
4000–4020Clear all data (via RUN)
8000–8960Shared formatting and editing subroutines
9000–9030Scroll 10 lines subroutine
9800–9830“Press ENTER to continue” pause subroutine
9998–9999Save program with auto-run flag

Data Storage Layout

All inventory data is stored in the array A$, dimensioned at line 10 as DIM A$(100,32). Each of the 100 rows holds exactly one item record with fields packed at fixed character positions:

ColumnsFieldWidth
1–8Item name / description8
10–15Part / stock number6
17–22Unit cost (£/$ value)6
24–27Items per unit4
29–32Units in stock4

Columns 9, 16, 23, and 28 serve as implicit spacers between fields, being left at their initialised space characters. This means a raw PRINT A$(N) produces a readable formatted line matching the column header "NAME PART NO. COST IT/UN IN/S".

The counter R1 (initialised to 0 at line 11) tracks the number of records entered. It is updated at line 1520 (LET R1=N-1) when item entry ends, and used as the loop bound whenever all records are iterated.

Menu Navigation and Computed GOTO

Both the main menu (line 260) and the data sub-menu (line 2260) use computed GOTO to dispatch on a single keypress. The main menu uses GOTO 1000*VAL B$, mapping keys 1–4 to lines 1000, 2000, 3000, and 4000. The data sub-menu uses GOTO (VAL B$*200)+2100, mapping keys 1–4 to lines 2300, 2500, 2700, and 2900. In both cases only keys with CODE values 29–32 (the digits 1–4 in ZX81 character encoding) are accepted, checked at lines 220 and 2220.

The edit sub-menu at line 2975 uses GOTO 8500+(100*VAL B$), dispatching to the four field-edit routines at 8600, 8700, 8800, and 8900.

Formatting Subroutines

Three subroutines handle string padding and decimal normalisation to keep field widths exact:

  • Line 8000 – Currency format fix: if the last character before the final digit is "." (one decimal place), appends "0"; if the last three characters contain no "." at position −2, appends ".00". This ensures cost strings always carry two decimal places.
  • Line 8100 – Left-pads B$ with spaces to a total width of 6 (for the cost field).
  • Line 8200 – Left-pads B$ with spaces to a total width of 4 (for items-per-unit and units-in-stock fields).

The separator line Z$ is pre-built at line 12 as a 64-character string of alternating inverse and normal hyphens and spaces, used as a visual rule under column headers.

Screen Layout Technique

The background fill at lines 40–60 (main menu) and 2030–2050 (data menu) prints alternating inverse-space and normal-space characters by looping PRINT "% % % % % % % % "; (using % as the zmakebas escape for inverse space) to produce a chequerboard pattern across the entire screen. This is done in FAST mode before switching to SLOW for interactive use.

The flicker prompt at line 180 (and 2180) prints the same screen position three times in succession: first inverse, then normal, then inverse again, creating a brief visual flash to draw attention to the prompt area without requiring a timing loop.

POKE 16418,0 (lines 30 and 2020) sets the system variable FRAMES low byte, and POKE 16418,2 (lines 240 and 2240) restores it; this is used here to control display timing rather than machine code.

Stock Search Logic

Part-number searches (lines 2520–2540, 2730–2740, 2930–2940) use a partial-match technique: IF A$(N,10 TO 9+LEN B$)=B$. This compares only as many characters as the user typed, allowing prefix searches. The loop exits on the first match; if no match is found, the program falls through to an error message.

At line 2560 the search loop jumps to line 2560 on a match, but that line does not exist in the listing — the execution will fall through to line 2660 instead, which is the intended display-and-confirm block. This is the well-known technique of targeting a non-existent line to land on the next available line.

Stock Adjustment (Lines 8400–8540)

The change-inventory routine uses a variable named AT for both the menu choice (add=1, take=2) and subsequently for the quantity to add or subtract, reusing the same variable for two different purposes within the same routine. After the operation, the numeric result is converted back to a string via STR$, padded to 4 characters if necessary, and written directly back into A$(N,29 TO 32).

Notable Bugs and Anomalies

  • At line 8010, the decimal-format check IF B$(LEN B$-2)<>"." will cause a subscript error if B$ has fewer than three characters (e.g. a single-digit cost like "5"), because LEN B$-2 would be zero or negative. This could crash the program on very short cost strings.
  • Line 2560 does not exist; the search GOSUBs jump there but execution continues at line 2660. This is intentional (a non-existent target line trick) and works correctly.
  • At line 1145, after a part number is entered that is too long, the program GOTOs line 1135 (the SLOW statement before the INPUT), which is correct but relies on the SLOW/INPUT pair being adjacent.
  • The SAVE C$ at line 3050 saves only the program, not the A$ data array. To preserve inventory data across sessions, the user would need to rely on the auto-run save at line 9998 (SAVE "INVENTOR%Y") which also only saves the program; the array data would be lost on reload. There is no SAVE DATA or equivalent for the array.
  • The edit sub-menu at line 2965 only offers four options (name, stock no., cost, items/unit) — there is no option to edit units in stock via this path; that is only accessible through the change-inventory flow.

Content

Appears On

Cassette to accompany the December 1982 issue of Synchro-Sette.

Related Products

Related Articles

Related Content

Image Gallery

Inventory

Source Code

  10 DIM A$(100,32)
  11 LET R1=0
  12 LET Z$="%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-"
  20 FAST 
  25 CLS 
  30 POKE 16418,0
  40 FOR N=1 TO 96
  50 PRINT "% % % % % % % % ";
  60 NEXT N
  70 PRINT AT 2,6;" INVENTORY PROGRAM "
  80 PRINT AT 5,1;"%T%O% %E%N%T%E%R% %I%T%E%M%S";TAB 26;"%-% %1"
  90 PRINT AT 7,1;"%T%O% %S%E%E% %A%L%L% %D%A%T%A";TAB 26;"%-% %2"
 100 PRINT AT 9,1;"%T%O% %S%A%V%E% %D%A%T%A% %O%N% %T%A%P%E";TAB 26;"%-% %3"
 110 PRINT AT 11,1;"%T%O% %C%L%E%A%R% %A%L%L% %D%A%T%A";AT 11,26;"%-% %4"
 180 PRINT AT 22,4;"%E%N%T%E%R% %O%N%E% %O%F% %A%B%O%V%E% %:%:%:";AT 22,4;"ENTER ONE OF ABOVE :::";AT 22,4;"%E%N%T%E%R% %O%N%E% %O%F% %A%B%O%V%E% %:%:%:"
 190 SLOW 
 200 LET B$=INKEY$
 210 IF B$="" THEN GOTO 180
 220 IF CODE B$<29 OR CODE B$>32 THEN GOTO 180
 230 FAST 
 240 POKE 16418,2
 250 CLS 
 260 GOTO 1000*VAL B$
\n1000 FOR N=R1+1 TO 100
\n1010 GOSUB 9000
\n1020 PRINT "WHAT IS THE NAME OR DESCRIPTION"
\n1030 SCROLL 
\n1040 PRINT "OF ITEM NO. ";N;" (8 CHAR. MAX.)"
\n1050 SCROLL 
\n1055 SLOW 
\n1060 INPUT B$
\n1065 FAST 
\n1070 IF B$="" THEN GOTO 1500
\n1080 LET A$(N, TO 8)=B$
\n1090 PRINT A$(N)
\n1100 GOSUB 9000
\n1110 SCROLL 
\n1120 PRINT "WHAT IS THE PART NO. (6 CHAR MAX"
\n1130 SCROLL 
\n1135 SLOW 
\n1140 INPUT B$
\n1142 FAST 
\n1145 IF LEN B$>6 THEN GOTO 1135
\n1150 LET A$(N,10 TO 15)=B$
\n1160 PRINT A$(N)
\n1170 GOSUB 9000
\n1190 PRINT "COST PER UNIT?"
\n1200 SCROLL 
\n1205 SLOW 
\n1210 INPUT B$
\n1212 FAST 
\n1214 IF VAL B$>999.99 THEN GOTO 8300
\n1216 GOSUB 8000
\n1218 IF LEN B$<6 THEN GOSUB 8100
\n1220 SCROLL 
\n1230 LET A$(N,17 TO 22)=B$
\n1240 PRINT A$(N)
\n1250 GOSUB 9000
\n1260 PRINT "ITEMS PER UNIT?"
\n1270 SCROLL 
\n1275 SLOW 
\n1280 INPUT B$
\n1285 FAST 
\n1290 IF LEN B$>4 THEN GOTO 1275
\n1300 SCROLL 
\n1310 IF LEN B$<4 THEN GOSUB 8200
\n1320 LET A$(N,24 TO 27)=B$
\n1330 PRINT A$(N)
\n1340 GOSUB 9000
\n1350 PRINT "UNITS IN STOCK?"
\n1355 SLOW 
\n1360 INPUT B$
\n1365 FAST 
\n1370 IF LEN B$>4 THEN GOTO 1355
\n1374 IF LEN B$=4 THEN GOTO 1390
\n1376 FOR I=1 TO 4-LEN B$
\n1380 LET B$=" "+B$
\n1385 NEXT I
\n1390 SCROLL 
\n1400 LET A$(N,29 TO 32)=B$
\n1410 PRINT A$(N)
\n1420 NEXT N
\n1500 FAST 
\n1510 CLS 
\n1520 LET R1=N-1
\n1530 SLOW 
\n1540 GOTO 20
\n1999 STOP 
\n2000 FAST 
\n2010 CLS 
\n2020 POKE 16418,0
\n2030 FOR N=1 TO 192
\n2040 PRINT "% % % % ";
\n2050 NEXT N
\n2060 PRINT AT 2,7;" INVENTORY DATA "
\n2070 PRINT AT 5,1;"%T%O% %S%E%E% %T%O%T%A%L% %I%N%V%E%N%T%O%R%Y";TAB 28;"%-% %1"
\n2080 PRINT AT 7,1;"%T%O% %C%H%A%N%G%E% %I%N%V%E%N%T%O%R%Y";TAB 28;"%-% %2"
\n2090 PRINT AT 9,1;"%T%O% %S%E%E% %I%T%E%M% %D%A%T%A";TAB 28;"%-% %3"
\n2100 PRINT AT 11,1;"%T%O% %E%D%I%T% %D%A%T%A% %I%T%E%M%S";TAB 28;"%-% %4"
\n2180 PRINT AT 22,4;"%E%N%T%E%R% %O%N%E% %O%F% %A%B%O%V%E% %:%:%:";AT 22,4;"ENTER ONE OF ABOVE :::";AT 22,4;"%E%N%T%E%R% %O%N%E% %O%F% %A%B%O%V%E% %:%:%:"
\n2190 SLOW 
\n2200 LET B$=INKEY$
\n2210 IF B$="" THEN GOTO 2180
\n2220 IF CODE B$<29 OR CODE B$>32 THEN GOTO 2180
\n2230 FAST 
\n2240 POKE 16418,2
\n2250 CLS 
\n2260 GOTO (VAL B$*200)+2100
\n2300 SLOW 
\n2310 FOR N=1 TO R1
\n2320 SCROLL 
\n2340 SCROLL 
\n2350 PRINT "NAME    PART NO. COST IT/UN IN/S" 
\n2360 SCROLL 
\n2365 PRINT Z$
\n2370 SCROLL 
\n2380 PRINT A$(N)
\n2382 SCROLL 
\n2384 SCROLL 
\n2386 SCROLL 
\n2388 NEXT N
\n2390 PRINT "PRESS ENTER TO CONTINUE :::"
\n2392 INPUT B$
\n2395 GOTO 20
\n2500 PRINT AT 10,0;"WHAT IS THE STOCK NO. OF ITEM?"
\n2505 SLOW 
\n2510 INPUT B$
\n2515 FAST 
\n2520 FOR N=1 TO R1
\n2525 FAST 
\n2530 IF A$(N,10 TO 9+LEN B$)=B$ THEN GOTO 2560
\n2540 NEXT N
\n2542 CLS 
\n2544 GOSUB 9000
\n2546 PRINT "STOCK NO. NOT IN FILE :::"
\n2547 GOSUB 9000
\n2548 GOSUB 9800
\n2550 GOTO 20
\n2660 FAST 
\n2662 CLS 
\n2664 GOSUB 9000
\n2666 PRINT "NAME    PART NO. COST IT/UN IN/S" 
\n2668 SCROLL 
\n2670 PRINT Z$
\n2672 SCROLL 
\n2674 PRINT A$(N)
\n2676 GOSUB 9000
\n2678 PRINT AT 21,0;"IS THIS THE CORRECT STOCK NO.?"
\n2679 SLOW 
\n2680 INPUT Y$
\n2682 FAST 
\n2683 IF Y$(1)="N" THEN GOTO 2540
\n2684 SCROLL 
\n2685 SCROLL 
\n2686 PRINT "ADD TO (1) OR TAKE FROM (2)?"
\n2687 SLOW 
\n2688 INPUT AT
\n2689 FAST 
\n2690 IF AT>2 OR AT<1 THEN GOTO 2687
\n2695 GOTO 8400
\n2700 CLS 
\n2705 PRINT AT 10,1;"WHAT IS THE STOCK NO.?"
\n2710 SLOW 
\n2715 INPUT B$
\n2720 FAST 
\n2725 IF LEN B$>6 THEN GOTO 2710
\n2730 FOR N=1 TO R1
\n2735 IF A$(N,10 TO 9+LEN B$)=B$ THEN GOTO 2760
\n2740 NEXT N
\n2745 SCROLL 
\n2750 PRINT TAB 16-((LEN B$)/2);B$
\n2755 GOTO 2544
\n2760 CLS 
\n2765 PRINT ,,"STOCK NAME -";TAB 24;A$(N, TO 8)
\n2770 PRINT ,,"STOCK NO. -";TAB 26;A$(N,10 TO 15)
\n2775 PRINT ,,"UNIT COST -";TAB 26;A$(N,17 TO 22)
\n2780 PRINT ,,"ITEMS/UNIT -";TAB 28;A$(N,24 TO 27)
\n2785 PRINT ,,"UNITS IN STOCK -";TAB 28;A$(N,29 TO 32)
\n2790 PRINT ,,"COST OF TOTAL UNITS - $";
\n2795 LET B=(VAL A$(N,17 TO 22)*VAL A$(N,29 TO 32))
\n2800 LET B$=STR$ B
\n2805 GOSUB 8000
\n2810 PRINT B$
\n2815 GOSUB 9800
\n2820 GOTO 20
\n2900 CLS 
\n2905 PRINT AT 10,1;"WHAT IS THE STOCK NO.?"
\n2910 SLOW 
\n2915 INPUT B$
\n2920 FAST 
\n2925 IF LEN B$>6 THEN GOTO 2910
\n2930 FOR N=1 TO R1
\n2935 IF A$(N,10 TO 9+LEN B$)=B$ THEN GOTO 2950
\n2940 NEXT N
\n2945 GOTO 2745
\n2950 CLS 
\n2955 PRINT ,,"NAME    PART NO. COST IT/UN IN/S" 
\n2960 PRINT Z$;A$(N)
\n2965 PRINT ,,,,"<1> NAME","<3> COST","<2> STK. NO.","<4> ITEMS/UNIT",,,,"CHOOSE ONE?"
\n2967 SLOW 
\n2970 INPUT B$
\n2972 FAST 
\n2974 IF CODE B$<29 OR CODE B$>32 THEN GOTO 2967
\n2975 GOTO 8500+(100*VAL B$)
\n2999 GOTO 2999
\n3000 FAST 
\n3002 CLS 
\n3006 PRINT AT 10,10;"FILE NAME?"
\n3010 SLOW 
\n3020 INPUT C$
\n3030 PRINT AT 12,0;"PREPARE THE RECORDER AND THEN   PRESS ENTER :::"
\n3040 INPUT B$
\n3050 SAVE C$
\n3060 FAST 
\n3070 CLS 
\n3080 GOTO 20
\n4000 FAST 
\n4010 CLS 
\n4020 RUN 
\n8000 IF B$(LEN B$-1)="." THEN LET B$=B$+"0"
\n8010 IF B$(LEN B$-2)<>"." THEN LET B$=B$+".00"
\n8020 RETURN 
\n8100 FOR I=1 TO 6-LEN B$
\n8110 LET B$=" "+B$
\n8120 NEXT I
\n8130 RETURN 
\n8200 FOR I=1 TO 4-LEN B$
\n8210 LET B$=" "+B$
\n8220 NEXT I
\n8230 RETURN 
\n8300 SCROLL 
\n8310 SCROLL 
\n8320 PRINT "COST CANNOT EXCEED 999.00"
\n8340 SCROLL 
\n8350 GOTO 1170
\n8400 SCROLL 
\n8410 SCROLL 
\n8420 IF AT=1 THEN GOTO 8500
\n8430 PRINT "HOW MANY TO BE TAKEN AWAY?"
\n8435 SLOW 
\n8440 INPUT AT
\n8445 FAST 
\n8450 LET TA=VAL A$(N,29 TO 32)
\n8455 LET TA=TA-AT
\n8460 LET B$=STR$ TA
\n8470 IF LEN B$<4 THEN GOSUB 8200
\n8472 LET A$(N,29 TO 32)=B$
\n8475 SCROLL 
\n8480 SCROLL 
\n8481 PRINT "NAME    PART NO. COST IT/UN IN/S" 
\n8482 SCROLL 
\n8483 PRINT Z$
\n8484 SCROLL 
\n8485 PRINT A$(N)
\n8486 GOSUB 9000
\n8487 GOTO 2390
\n8500 PRINT "HOW MANY TO BE ADDED?"
\n8510 SLOW 
\n8520 INPUT AT
\n8525 FAST 
\n8530 LET TA=VAL A$(N,29 TO 32)
\n8535 LET TA=TA+AT
\n8540 GOTO 8460
\n8600 PRINT ,,"WHAT IS THE NEW NAME?"
\n8610 SLOW 
\n8620 INPUT B$
\n8630 FAST 
\n8640 IF LEN B$>8 THEN GOTO 8610
\n8650 LET A$(N, TO 8)=B$
\n8660 PRINT ,,"NAME    PART NO. COST IT/UN IN/S";Z$;A$(N) 
\n8670 GOSUB 9800
\n8680 GOTO 20
\n8700 PRINT ,,"WHAT IS THE NEW STOCK NO.?"
\n8710 SLOW 
\n8720 INPUT B$
\n8730 FAST 
\n8740 IF LEN B$>6 THEN GOTO 8710
\n8750 LET A$(N,10 TO 15)=B$
\n8760 GOTO 8660
\n8800 PRINT ,,"WHAT IS THE NEW COST?"
\n8810 SLOW 
\n8820 INPUT B$
\n8830 FAST 
\n8840 IF LEN B$>6 THEN GOTO 8810
\n8842 GOSUB 8000
\n8844 IF LEN B$<6 THEN GOSUB 8100
\n8850 LET A$(N,17 TO 22)=B$
\n8860 GOTO 8660
\n8900 PRINT ,,"WHAT IS THE NEW AMOUNT OF ITEMS PER UNIT?"
\n8910 SLOW 
\n8920 INPUT B$
\n8930 FAST 
\n8940 IF LEN B$>4 THEN GOTO 8910
\n8945 IF LEN B$<4 THEN GOSUB 8200
\n8950 LET A$(N,24 TO 27)=B$
\n8960 GOTO 8660
\n9000 FOR I=1 TO 10
\n9010 SCROLL 
\n9020 NEXT I
\n9030 RETURN 
\n9800 PRINT AT 21,0;"PRESS ENTER TO CONTINUE :::"
\n9810 INPUT B$
\n9820 CLS 
\n9830 RETURN 
\n9998 SAVE "INVENTOR%Y"
\n9999 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