Point Of Sale Cash Register

This file is part of and TS-2068 Computer Programs. Download the collection to get this file.
Developer(s): Imre Auersbacher
Date: 1985
Type: Program
Platform(s): TS 2068
Tags: Business

This program implements a full point-of-sale cash register system, managing an inventory stored in a 1,200-entry string array where each record is 25 characters wide (6-digit code, 12-character name, 7-character price with optional taxable flag). It uses a binary search subroutine at line 1 for fast item lookup and a Shell sort subroutine at lines 490–580 to keep inventory in alphabetical order after additions or deletions. Prices are formatted to two decimal places using the custom functions defined at lines 15 and 16, including zero-padding for trailing zeros. The program drives a printer via LPRINT for receipts and stock listings, saves/loads inventory data to tape, and uses two custom UDG characters (A and B) for menu highlighting.


Program Analysis

Program Structure

The program is organized into a main menu dispatcher and a set of subroutines, each handling a distinct function. Initialization occurs at line 9000 (cold start) and line 1000 (warm start / after tape load). The main menu loop runs at lines 40–65, dispatching via a computed GO SUB at line 60.

LinesFunction
1–12Binary search subroutine
15–16DEF FN: numeric formatting helpers
20–65Initialization, date entry, main menu loop
75–390Cash register / transaction processing
490–580Shell sort subroutine
585–720Add new item
725–810Delete item
815–850Print stock listing
860–870Save to tape
875–935Exit / daily totals report
1000–1010UDG setup and program entry point
2000UDG DATA for characters A and B
9000Cold start: initialize array, go to 1000
9999SAVE with auto-run

Data Storage

All inventory is held in a single string array Z$ dimensioned at line 9000 as DIM Z$(1200,25), giving up to 1,200 records of exactly 25 characters each. The record layout is fixed-width:

  • Characters 1–6: item code (zero-padded)
  • Characters 7–18: item name (space-padded to 12 characters)
  • Characters 19–25: price field (7 characters, space-padded); a trailing T in position 25 flags a taxable item

The variable M is used as the next-free-slot pointer; the valid record count is M-1. The array is kept sorted by code after every add or delete operation.

Binary Search (Lines 1–12)

The subroutine at line 1 accepts a search key in Q$ and searches Z$(1) through Z$(M-1) for a matching code in columns 1–6. It returns the found index in S, or 0 if not found. The algorithm uses standard midpoint halving with Y (low), Z (high), and C (mid). A boundary pre-check at line 1 short-circuits the search if Q$ falls outside the range of stored codes, avoiding unnecessary iterations on an empty or out-of-range query.

Line 9 handles the case where the binary search narrows to a single candidate without an exact match: S is set to the current low bound and then validated at line 10, which clears S to 0 if the code does not match exactly.

Shell Sort (Lines 490–580)

The sort subroutine implements a classic Shell sort (diminishing-increment sort). The gap sequence starts at INT(N/2) and is halved at each pass (line 500). Comparisons and swaps operate on entire 25-character strings in Z$(), so the code field naturally controls sort order. Deletion is handled by overwriting the target record’s code with ZZZZZZ (line 795) before sorting, which causes it to bubble to the end; M is then decremented at line 805 to effectively drop it.

Computed GO SUB Dispatch (Line 60)

Line 60 uses an arithmetic expression to compute the target line number:

GO SUB 75*(X=1)+585*(X=2)+725*(X=3)+815*(X=4)+860*(X=5)+875*(X=6)

In Sinclair BASIC, boolean expressions evaluate to 1 (true) or 0 (false), so exactly one term is non-zero for any valid menu choice. This is a compact single-line dispatcher avoiding a chain of IF/GO SUB statements.

Numeric Formatting Functions (Lines 15–16)

Two DEF FN functions handle currency formatting:

  • FN D(X) at line 15 rounds to two decimal places using INT(100*X+0.5)/100.
  • FN Q$(X,Q$) at line 16 takes a number X and its string representation Q$, appending .00 if the number is an integer, or a trailing 0 if the string ends in a decimal point with only one digit. This ensures display values always show exactly two decimal places.

Taxable Item Handling

Items are flagged as taxable by a T in the last character (position 25) of the record, or position 7 of a manually entered price string. When reading the numeric value of a price (line 250), the code strips the trailing T using VAL Z$(S,19 TO 25-(Z$(S,25)="T")). Tax at rate TR (initialized to 6.5% at line 20) is applied only to taxable items, accumulated in TX per transaction and TTX as a daily running total.

UDG Characters

Lines 1000–1010 define two UDG characters, A and B, from DATA at line 2000, used in the menu highlight display at line 59 (CHR$ 144 and CHR$ 145). These two 8-byte patterns represent decorative cursor/marker glyphs flanking the selected menu option.

Input Validation and Padding

Throughout the program, input strings for codes, names, and prices are normalized to fixed widths by either left-padding with spaces/zeros or right-padding with spaces:

  • Item codes: left-padded with zeros to 6 characters (e.g., line 135, 620, 755)
  • Item names: right-padded with spaces to 12 characters (line 650)
  • Prices: left-padded with spaces to 7 characters (line 680)

Not-Found Item Entry (Lines 155–235)

If a scanned code is not in inventory during a transaction (line 150), the cashier is prompted to enter the item name and price directly. The entered price string is parsed with the same taxable-flag logic as stored records. This allows ad-hoc items to be sold without being in the database, printed with an NF (not found) prefix on the receipt.

Notable Anomalies

  • Line 110 is referenced from line 265 (GO TO 110) but does not exist in the listing. In practice this would cause a “Line does not exist” error; the apparent intent is to loop back to line 120 (the next item input prompt), suggesting line 110 is a missing or deleted line that was once equivalent to GO TO 120.
  • The SAVE at line 865 saves starting at LINE 1000, so on reload the program enters via the UDG setup routine rather than cold-starting at 9000, preserving the existing array contents if any are in memory.
  • Line 935 issues STOP : STOP — the second STOP is unreachable but harmless.

Content

Appears On

Predict eclipses across four millennia, track planetary positions through five centuries, calculate loan amortization schedules, or encode secret messages with modular arithmetic — Imre Auersbacher's collection brings scientific precision and practical utility to the TS 2068.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

    1 LET N=M-1: LET Y=1: LET Z=N+1: LET S=0: IF (Q$<Z$(1, TO 6))+(Q$>Z$(N, TO 6)) THEN GO TO 12
    2 IF Z<Y THEN GO TO 9
    3 LET C=INT ((Z+Y)/2): LET T$=Z$(C, TO 6)
    4 IF T$=Q$ THEN LET S=C: GO TO 10
    5 IF T$<Q$ THEN LET Y=C+1: GO TO 2
    6 LET Z=C-1: GO TO 2
    9 LET S=Z
   10 IF Q$<>Z$(S, TO 6) THEN LET S=0
   12 RETURN 
   15 DEF FN D(X)=INT (100*X+0.5)/100
   16 DEF FN Q$(X,Q$)=Q$+(".00" AND X=INT X)+("0" AND ("0"+Q$)(LEN Q$)=".")
   20 LET TR=0.065: LET B$=" ** YOUR BUSINESS NAME HERE **"
   26 PAPER 6: BORDER 3: POKE 23658,8: CLS : POKE 23609,10
   30 PRINT PAPER 5;"  POINT OF SALE CASH REGISTER   ";AT 1,0;"  \* 1985   BY: I. AUERSBACHER   ";AT 6,3;"ENTER TODAY'S DATE";AT 7,3;" (MM/DD/YYYY):"
   32 INPUT D$
   35 LET G=0: LET TTX=0
   40 PAPER 3: BORDER 5: CLS : PRINT PAPER 1; INK 7;"  POINT OF SALE CASH REGISTER   ":
   45 PRINT PAPER 7;AT 4,11;" MENU ";AT 7,6;"1- CASH REGISTER";AT 8,6;"2- ADD NEW ITEMS";AT 9,6;"3- DELETE ITEMS ";AT 10,6;"4- LPRINT STOCK ";AT 11,6;"5- SAVE TO TAPE ";AT 12,6;"6- EXIT PROGRAM ";AT 21,0;"OPTION NO?"
   50 LET Q$=INKEY$: IF Q$="" THEN GO TO 50
   55 IF CODE Q$<49 OR CODE Q$>54 THEN BEEP 0.3,-15: BEEP 0.3,-20: GO TO 50
   56 LET X=INT VAL Q$: IF M=1 AND X=1 THEN BEEP .4,-20: GO TO 50
   58 BEEP 0.06,25
   59 PRINT INK 0;AT 6+X,3;CHR$ 144; INK 6;CHR$ 145: PAUSE 100: PAPER 7: BEEP .1,20
   60 GO SUB 75*(X=1)+585*(X=2)+725*(X=3)+815*(X=4)+860*(X=5)+875*(X=6)
   65 GO TO 40
   75 CLS : PRINT B$: LPRINT : LPRINT : LPRINT B$
   80 PRINT "    DATE: ";D$: LPRINT "    DATE: ";D$
   85 PRINT : LPRINT 
   90 PRINT : LPRINT 
  100 LET TT=0: LET TX=0
  120 INPUT FLASH 1;"ENTER CODE: ";Q$
  125 IF Q$="" THEN GO TO 285
  130 IF LEN Q$>6 THEN GO TO 120
  135 IF LEN Q$<6 THEN LET Q$="00000"( TO 6-LEN Q$)+Q$
  150 GO SUB 1: IF S<>0 THEN BEEP .03,25: GO TO 245
  155 BEEP .4,-15: BEEP .5,-20: PRINT INK 2;" ";Q$;" NOT FOUND "
  160 PRINT INK 2;" ITEM NAME: ";
  165 INPUT A$: IF A$="" THEN PRINT FLASH 1;"CANCEL": GO TO 120
  170 IF LEN A$>12 THEN LET A$=A$( TO 12)
  175 PRINT INK 1;A$
  180 PRINT INK 2;" ITEM COST: ";
  185 INPUT Q$: IF Q$="" THEN BEEP 0.3,-20: GO TO 185
  190 PRINT INK 1;Q$
  205 LET X=LEN Q$: LET T=VAL Q$( TO X-(Q$(X)="T"))
  210 LET G=G+T: LET TT=TT+T
  220 IF X<7 THEN LET Q$="      "( TO 7-X)+Q$
  225 PRINT "   NF";TAB 8;A$;TAB 20+(Q$(7)="T");Q$: LPRINT "   NF";TAB 8;A$;TAB 20+(Q$(7)="T");Q$
  230 IF Q$(7)="T" THEN GO TO 270
  235 GO TO 120
  245 PRINT TAB 1;Z$(S, TO 6);" ";Z$(S,7 TO 18);TAB 20+(Z$(S,25)="T");Z$(S,19 TO )
  246 LPRINT TAB 1;Z$(S, TO 6);" ";Z$(S,7 TO 18);TAB 20+(Z$(S,25)="T");Z$(S,19 TO )
  250 LET T=VAL Z$(S ,19 TO 25-(Z$(S,25)="T"))
  265 LET TT=TT+T: LET G=G+T: IF Z$(S,25)<>"T" THEN GO TO 110
  270 LET T=FN D(T*TR)
  275 LET TX=TX+T: LET TTX=TTX+T
  280 GO TO 120
  285 CLS : LET C=FN D(TT): LET Q$=FN Q$(C,STR$ C): BEEP .1,25
  290 PRINT AT 4,7;"SUB TOT:";TAB 24-LEN Q$;Q$:
  295 LET TX=FN D(TX): LET Q$=FN Q$(TX,STR$ TX)
  300 PRINT TAB 7;"TAX DUE:";TAB 24-LEN Q$;Q$: LPRINT 
  305 LPRINT : LPRINT TAB 7;"TAX DUE:";TAB 24-LEN Q$;Q$
  310 LET TT=FN D(TT+TX): LET Q$=FN Q$(TT,STR$ TT): PRINT 
  315 PRINT TAB 7; FLASH 1;"TOTAL:"; FLASH 0;TAB 24-LEN Q$;Q$
  320 LPRINT TAB 7;"TOTAL:";TAB 24-LEN Q$;Q$
  325 PRINT : LPRINT 
  330 PRINT TAB 7;"CASH TEND:";
  340 INPUT Z
  345 LET C=Z-TT: IF C<-0.001 THEN BEEP 0.7,-20: GO TO 340
  350 LET Q$=FN Q$(Z,STR$ Z): PRINT TAB 24-LEN Q$;Q$: LPRINT TAB 7;"CASH TEND:";TAB 24-LEN Q$;Q$
  355 LET C=FN D(C): LET Q$=FN Q$(C,STR$ C): PRINT TAB 7;"CHNG DUE :";TAB 24-LEN Q$;Q$
  356 LPRINT TAB 7;"CHNG DUE :";TAB 24-LEN Q$;Q$
  370 LPRINT : LPRINT : LPRINT " THANK YOU * HAVE A NICE DAY!"
  375 FOR Z=1 TO 5: LPRINT 
  385 NEXT Z: PAUSE 10000
  390 RETURN 
  490 LET N=M-1: LET S=N
  500 LET S=INT (S/2)
  505 IF S=0 THEN GO TO 580
  510 LET W=N-S
  515 LET Y=1
  520 LET Z=Y
  525 LET C=Z+S
  535 IF Z$(Z)<=Z$(C) THEN GO TO 565
  540 LET Q$=Z$(Z)
  545 LET Z$(Z)=Z$(C)
  550 LET Z$(C)=Q$
  555 LET Z=Z-S
  560 IF Z>=1 THEN GO TO 525
  565 LET Y=Y+1
  570 IF Y<=W THEN GO TO 520
  575 GO TO 500
  580 RETURN 
  585 CLS : LET A$=""
  590 IF M>1200 THEN  PRINT FLASH 1;" FILE FULL ": BEEP 1.5,-22: PAUSE 240: PRINT : GO TO 715
  595 PRINT AT 2,8;"ADD DATA-->"
  600 PRINT AT 4,1;"CODE NO:   ";
  605 INPUT Q$
  610 IF Q$="" THEN GO TO 715
  615 IF LEN Q$>6 THEN GO TO 605
  620 IF LEN Q$<6 THEN LET Q$="00000"( TO 6-LEN Q$)+Q$
  630 PRINT Q$: LET A$=A$+Q$
  635 PRINT AT 5,1;"ITEM NAME: ";
  640 INPUT Q$: IF Q$="" THEN BEEP .4,-15: BEEP .5,-20: GO TO 640
  645 IF LEN Q$>12 THEN GO TO 640
  650 IF LEN Q$<12 THEN LET Q$=Q$+"           "( TO 12-LEN Q$)
  660 PRINT Q$: LET A$=A$+Q$
  665 PRINT AT 6,1;"ITEM COST: ";
  670 INPUT Q$: IF Q$="" THEN BEEP 1,-20: GO TO 670
  675 IF LEN Q$>7 THEN GO TO 670
  680 IF LEN Q$<7 THEN LET Q$="      "( TO 7-LEN Q$)+Q$
  685 PRINT Q$
  690 LET A$=A$+Q$: LET Z$(M)=A$
  700 LET M=M+1: PAUSE 50
  710 GO TO 585
  715 PRINT : PRINT : PRINT " "; FLASH 1;" SORTING ": GO SUB 490
  720 RETURN 
  725 CLS : IF M=1 THEN RETURN 
  730 PRINT AT 3,0;"DELETE-->"
  735 PRINT 
  740 PRINT "ENTER CODE NO. ";
  745 INPUT Q$: IF Q$="" THEN : BEEP 0.07,22: GO TO 810
  750 IF LEN Q$>6 THEN GO TO 745
  755 IF LEN Q$<6 THEN LET Q$="00000"( TO 6-LEN Q$)+Q$
  760 PRINT Q$: GO SUB 1
  775 IF S<>0 THEN GO TO 795
  780 PRINT Q$;" NOT FOUND"
  785 PAUSE 220: GO TO 810
  795 LET Z$(S, TO 6)="ZZZZZZ"
  800 PRINT : PRINT TAB 1; FLASH 1;" SORTING ": GO SUB 490
  805 LET M=M-1
  810 RETURN 
  815 CLS 
  820 PRINT "  CODE";TAB 10;"ITEM";TAB 23;"PRICE": LPRINT 
  822 LPRINT : LPRINT "  CODE";TAB 10;"ITEM";TAB 23;"PRICE"
  825 FOR Z=1 TO M-1
  830 LET X$=Z$(Z)
  835 PRINT " ";X$( TO 6);"  ";X$(7 TO 18);TAB 21+(X$(25)="T");X$(19 TO )
  836 LPRINT " ";X$( TO 6);"  ";X$(7 TO 18);TAB 21+(X$(25)="T");X$(19 TO )
  840 NEXT Z
  845 PRINT : LPRINT : LPRINT 
  850 PAUSE 20000: RETURN 
  860 CLS : PRINT AT 5,2;"NAME OF THIS FILE?": INPUT Q$: PRINT 
  862 IF LEN Q$>10 OR Q$="" THEN BEEP 1.5,-20: GO TO 860
  863 PRINT AT 7,2; PAPER 6;Q$
  865 SAVE Q$ LINE 1000
  867 PRINT FLASH 1;AT 9,2;" STOP RECORDER ": PAUSE 400
  870 RETURN 
  875 CLS 
  880 PRINT : LPRINT : LPRINT 
  885 LET G=FN D(G): LET X=FN D(TTX): LET Q$=FN Q$(G,STR$ G):
  890 LET A$=FN Q$(X,STR$ X)
  895 PRINT : PRINT " DATE: ";D$
  900 LPRINT " DATE: ";D$
  905 PRINT : PRINT " TOTAL SALES: $";TAB 23-LEN Q$;Q$
  906 LPRINT : LPRINT " TOTAL SALES: $";TAB 23-LEN Q$;Q$
  910 PRINT " TOTAL TAXES: $";TAB 23-LEN A$;A$
  912 LPRINT " TOTAL TAXES: $";TAB 23-LEN A$;A$
  915 PRINT : LET G=FN D(G+X): LET Q$=FN Q$(G,STR$ G)
  920 PRINT " GRAND TOTAL: $";TAB 23-LEN Q$;Q$
  925 LPRINT : LPRINT " GRAND TOTAL: $";TAB 23-LEN Q$;Q$
  930 PRINT : LPRINT : LPRINT 
  935 PRINT FLASH 1;AT 12,4;"PROGRAM TERMINATED": STOP : STOP 
 1000 BEEP 0.1,22: BEEP 0.1,20
 1010 RESTORE : FOR Z=0 TO 7: READ Y,C: POKE USR "A"+Z,Y: POKE USR "B"+Z,C: NEXT Z: GO TO 20
 2000 DATA 0,24,0,48,127,96,127,255,127,255,115,248,115,248,127,240
 9000 LET M=1: DIM Z$(1200,25): GO TO 1000
 9999 SAVE "cashreg" LINE 9000

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

Scroll to Top