Payroll

Date: 198x
Type: Program
Platform(s): TS 1000
Tags: Business

This is a payroll management system that handles employee records, weekly hours input, pay stub generation, and year-to-date withholding tracking for up to 32 employees. Employee data is stored compactly in a two-dimensional string array N$(25,200), encoding numeric values such as hours, rates, and accumulated totals as raw character bytes using a three-byte binary packing scheme (lines 16–28 and 36–42) to work around the limited numeric storage of the platform. The program supports multiple withholding categories (federal tax, state tax, FICA, disability, unemployment, and other) with configurable percentage rates and a FICA dollar cap. Menu navigation uses INKEY$ scanning with CODE-based dispatch via a calculated GOTO at line 700.


Program Structure

The program is organised as a menu-driven application with a main dispatch loop at lines 500–700 and numbered sections at every 1000th line. The top of the file (lines 10–116) contains shared subroutines, and the menu entry point at line 500 prints a title before falling through to the menu at line 570.

Line rangePurpose
10–14Subroutine: “Press Enter to continue” pause
16–28Subroutine: pack integer X into 3-char string X$
36–42Subroutine: unpack 3-char string X$ into integer X
44–52Subroutine: input a value and store as CHR$ in N$
56–66Subroutine: display employee list (two columns)
70–94Subroutine: print data-entry screen labels
100–116Subroutine: format and print a monetary value P with decimal alignment
200–440Subroutine: calculate and display a pay stub for employee K, week Y
500–703Startup banner and main menu with INKEY$ dispatch
1000–1130Option 1: Add a new employee
1520–1690Per-field data-entry subroutines (called via calculated GOSUB)
2000–2410Option 2: Input weekly hours for all employees
3000–3140Option 3: Print individual pay stub
4000–4220Option 4: Print weekly payroll totals
5000–5160Option 5: Print year-to-date withholding totals
6000–6310Option 6: Change employee data
7000–7240Option 7: Initialise (clear) all data
8000–8020Option 8: SAVE program to tape
9000–9110Option 9: Update tax-rate constants
9100–9110Error handler: “INITIATE FIRST” guard

Data Storage: Binary Packing in a String Array

All employee records live in N$(25,200), a 25-row × 200-character string array. Numeric values that exceed a single byte range (e.g., hourly rates in cents, year-to-date totals) are stored as 2- or 3-byte sequences using CHR$ encoding. The pack subroutine at lines 16–28 decomposes an integer into base-65536, base-256, and remainder components, storing each as a character. The corresponding unpack subroutine (lines 36–42) reconstructs the value with CODE and multiplications. This avoids storing floating-point numbers (which consume 5 bytes each) and instead uses only as many characters as needed.

The layout of significant byte offsets within each employee row is as follows:

Column(s)Content
1–10Last name (padded)
11Initial
12–13Hourly rate × 100 (2 bytes)
14–18Withholding % rates (1 byte each: FWT, STAX, FICA-flag, DISA, VAC)
19–20Vacation/sick deduction × 100 (2 bytes)
W+20Hours for week W (packed: hours×4 + vac×32)
2W+70–2W+71Rate snapshot for week W (2 bytes)
177–179YTD gross pay × 100 (3 bytes)
180–198YTD withholdings by category (3 bytes each, 7 categories)

Menu Dispatch

The main menu (lines 680–700) reads a keypress with INKEY$ in a tight polling loop, validates that its CODE falls in the range 29–37 (keys 1–9), then executes GOTO 1000*(CODE B$-28). This maps key “1” → line 1000, “2” → 2000, …, “9” → 9000 in a single calculated jump, a classic Sinclair BASIC dispatch idiom.

Data-entry field subroutines during employee add/change are similarly dispatched with GOSUB K*20+1500 (lines 1090, 6270), stepping through fields at lines 1520, 1540, 1560, 1580/1600, 1620, 1640, 1660, 1680.

Monetary Formatting Subroutine (Lines 100–116)

The formatting routine at line 100 is a pure-BASIC fixed-point formatter for currency values stored as floating-point. It rounds to two decimal places, converts via STR$, then applies a cascade of string-length checks to ensure exactly two digits appear after the decimal point. If the value is six or more characters (i.e., ≥ 1000.00), a comma is inserted three places from the right. Output is right-aligned to column V+10 using TAB.

Pay Calculation (Lines 200–440)

The pay stub routine unpacks hours (dividing the stored byte by 4 to recover quarter-hours) and separates regular from overtime (anything above 40 hours). Base pay is R*H; premium overtime pay applies the employee’s overtime multiplier stored at offset 14. Withholding deductions (FWT, STAX, FICA, disability, unemployment, other) are each computed as a percentage of gross and accumulated into both weekly totals T() and year-to-date totals W(). The FICA deduction is capped by checking the running YTD total against the configured dollar limit T. The Z flag controls whether totals are accumulated (Z=0) or the stub is display-only (Z=1 or Z=2).

Notable Techniques and Idioms

  • The INKEY$ polling loop at lines 680–700 and 2210–2230 is used without PAUSE 0 pre-delay, relying on the loop itself for debounce.
  • RUN 7015 at line 7011 during initialisation clears all variables and restarts execution mid-program, a technique used to reliably reset all arrays and variables without a separate clear routine.
  • The H$() string array (8 rows × 4 chars) stores short category labels (“GRSS”, “FWT”, “STAX”, “FICA”, “DISA”, “UNEM”, “OTAX”, “OTHR”) for reuse throughout display and input prompts, avoiding repeated string literals.
  • DIM W(7) appears twice (lines 7015 and 7050) — the second DIM reinitialises the array to zero after the rate-input section, which effectively doubles as a year-to-date accumulator reset.
  • The block-graphic characters in lines 78, 80, 82, 84 (rendered as \ '/\. = ▝▖ = a “%” lookalike) are used decoratively as a percent-sign substitute within labels.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

Source Code

  10 PRINT AT 21,0;"%T%O% %C%O%N%T%I%N%U%E% %P%R%E%S%S% %E%N%T%E%R"
  12 INPUT X$
  14 RETURN 
  16 DIM X$(3)
  18 LET X1=INT (X/65536+.001)
  20 LET X$(1)=CHR$ X1
  21 LET X2=X-X1*65536
  23 LET X2=INT (X2/256+.001)
  24 LET X$(2)=CHR$ X2
  25 LET X3=INT (ABS (X-INT (X1*65536)-INT (X2*256)))
  27 LET X$(3)=CHR$ X3
  28 RETURN 
  36 LET X=CODE X$(1)*65536
  37 LET X=X+CODE X$(2)*256
  38 LET X=X+CODE X$(3)
  42 RETURN 
  44 INPUT X
  46 PRINT AT K+1,22;X
  48 GOSUB 16
  50 LET N$(F,K+10)=CHR$ X
  52 RETURN 
  56 FOR K=1 TO F
  58 LET X=K
  60 IF K>12 THEN LET X=K-12
  62 PRINT AT X,16*(K>12);K;TAB (4+(20*(K>12)));N$(K, TO 10);" ";N$(K,11 TO 12)
  64 NEXT K
  66 RETURN 
  70 CLS 
  71 PRINT AT 2,0;"1.LAST NAME="
  72 PRINT "2.INITIAL="
  76 PRINT "3.HOURLY RATE="
  78 PRINT "4.O.T( '/.  HRLY RATE)="
  80 PRINT "5. '/.  ";H$(2)
  82 PRINT "6. '/.  ";H$(3)
  84 PRINT "7. '/.  ";H$(8)
  90 PRINT "8.VAC/SICK DAYS="
  92 PRINT "9.";H$(8)
  94 RETURN 
 100 LET P=INT (100*P+.05)/100
 101 LET Y$=" "
 102 IF P=0 THEN GOTO 114
 103 LET Y$=STR$ P
 104 IF LEN Y$=1 THEN LET Y$=Y$+".00"
 106 IF LEN Y$=2 THEN LET Y$=Y$+".0"
 108 IF Y$(LEN Y$-1)="." THEN LET Y$=Y$+"0"
 110 IF Y$(LEN Y$-2)<>"." THEN LET Y$=Y$+".00"
 112 IF LEN Y$>6 THEN LET Y$=Y$( TO LEN Y$-6)+","+Y$(LEN Y$-5 TO LEN Y$)
 114 PRINT TAB (V+10-LEN Y$);Y$
 116 RETURN 
 200 CLS 
 202 PRINT N$(K, TO 10);",";N$(K,11);TAB 24;"%W%E%E%K:";Y
 204 LET X$="  "+N$(K,20+Y)
 206 GOSUB 36
 208 LET H=X/4
 232 LET I=0
 234 IF H>40 THEN LET I=H-40
 236 LET H=H-I
 238 LET X$=" "+N$(K,2*Y+70 TO 2*Y+71)
 240 GOSUB 36
 242 LET R=X/100
 244 PRINT 
 246 LET P=R*H
 247 LET G=P
 248 LET V=22
 250 PRINT "BASE PAY";
 251 LET J=1
 252 GOSUB 100
 253 PRINT "PREMIUM PAY";
 254 LET X$="  "+N$(K,14)
 255 GOSUB 36
 256 LET P=I*R*(1+X/100)
 257 LET G=G+P
 258 GOSUB 100
 259 PRINT "%G%R%O%S%S% %P%A%Y";
 260 LET P=G
 261 GOSUB 100
 262 IF Z=0 THEN LET T(8)=T(8)+P
 265 PRINT 
 266 PRINT H$(2);
 267 LET A=15
 268 LET B=180
 269 LET R=G
 270 GOSUB 272
 271 GOTO 296
 272 LET X$="  "+N$(K,A)
 273 GOSUB 36
 274 LET P=G*X/100
 275 LET V=13
 276 GOSUB 100
 277 IF Z>0 THEN GOTO 293
 278 LET X$=N$(K,B TO B+2)
 279 GOSUB 36
 280 LET X=X+P*100
 282 GOSUB 16
 284 LET N$(K,B TO B+2)=X$
 285 IF Z=0 THEN LET T(J)=T(J)+P
 286 IF Z=0 THEN LET W(J)=W(J)+P
 293 LET R=R-P
 294 RETURN 
 296 PRINT H$(3);
 297 LET J=2
 298 LET A=16
 300 LET B=183
 302 GOSUB 272
 304 PRINT H$(4);
 306 LET X$=N$(K,186 TO 188)
 308 GOSUB 36
 309 IF X/100<>T THEN GOTO 312
 310 LET P=0
 311 GOTO 324
 312 LET P=G*S/100
 314 IF P>T-X/100 THEN LET P=T-XV100
 317 LET X=X+P*100
 318 GOSUB 16
 319 LET N$(K,186 TO 188)=X$
 320 GOSUB 100
 321 IF Z>0 THEN GOTO 324
 322 LET T(3)=T(3)+P
 323 LET W(3)=W(3)+P
 324 LET R=R-P
 326 PRINT H$(7);
 327 LET J=6
 328 LET A=17
 330 LET B=195
 332 GOSUB 272
 334 PRINT H$(5);
 336 LET P=G*D/100
 337 LET B=189
 338 LET J=4
 340 GOSUB 276
 342 PRINT H$(6);
 344 LET P=G*U/100
 346 LET B=192
 348 LET J=5
 350 GOSUB 276
 362 PRINT H$(8);
 364 LET X$=" "+N$(K,19 TO 20)
 366 GOSUB 36
 368 LET P=X/100
 369 LET J=7
 370 LET B=198
 372 GOSUB 276
 384 PRINT 
 388 PRINT "%N%E%T% %P%A%Y";
 390 LET V=22
 395 LET P=R
 400 GOSUB 100
 402 IF Z>0 THEN GOTO 414
 404 LET X$=N$(K,177 TO 179)
 406 GOSUB 36
 408 LET X=X+G*100
 410 GOSUB 16
 412 LET N$(K,177 TO 179)=X$
 414 PRINT 
 415 IF Z=2 THEN RETURN 
 416 PRINT "%Y%E%A%R% %T%O%D%A%T%E%:"
 418 FOR J=1 TO 8
 420 LET A=16
 422 LET V=5
 424 IF J>4 THEN LET A=12
 426 IF J>4 THEN LET V=22
 428 PRINT AT A+J,V-5;H$(J);
 430 LET X$=N$(K,3*J+174 TO 3*J+176)
 432 GOSUB 36
 434 LET P=X/100
 436 GOSUB 100
 438 NEXT J
 440 RETURN 
 500 FAST 
 520 PRINT "     PAYROLL COPYRIGHT UAS      BOX 612 HADDONFIELD,N.J.08033"
 530 PRINT 
 540 GOTO 570
 550 FAST 
 560 CLS 
 570 PRINT "%P%R%E%S%S% %N%U%M%B%E%R% %D%E%S%I%R%E%D"
 580 PRINT 
 590 PRINT "1..ADD NAME"
 600 PRINT "2..INPUT WEEKLY INFO"
 610 PRINT "3..EMPLOYEE PAY STUB"
 620 PRINT "4..TOTAL PAYROLL"
 630 PRINT "5..TOTAL WITH-HOLDING TODATE"
 640 PRINT "6..CHANGE EMPLOYEE DATA"
 650 PRINT "7..INITIATE"
 660 PRINT "8..SAVE"
 665 PRINT "9..UPDATE CONSTANTS"
 670 SLOW 
 680 LET B$=INKEY$
 690 IF CODE B$<29 OR CODE B$>37 THEN GOTO 680
 700 GOTO 1000*(CODE B$-28)
 703 LET W=0
 1000 FAST 
 1010 CLS 
 1015 IF E=0 THEN GOTO 9100
 1020 IF E<33 THEN GOTO 1060
 1030 PRINT "%F%I%L%E% %F%U%L%L"
 1040 PAUSE 100
 1050 GOTO 550
 1060 PRINT "%A%D%D% %N%A%M%E..FILE NUMBER=";E
 1070 PRINT 
 1080 GOSUB 70
 1081 LET F=E
 1082 FOR K=1 TO 9
 1085 PRINT AT K+1,22;"% ";C$(23 TO 31)
 1090 GOSUB K*20+1500
 1100 NEXT K
 1110 LET E=E+1
 1120 GOSUB 10
 1130 GOTO 550
 1520 INPUT N$(F, TO 10)
 1522 PRINT AT K+1,22;N$(F, TO 10)
 1524 RETURN 
 1540 INPUT N$(F,11)
 1542 PRINT AT K+1,22;N$(F,11 TO 12)
 1544 RETURN 
 1560 INPUT X
 1562 PRINT AT K+1,22;X
 1564 LET X=X*100
 1566 GOSUB 16
 1568 LET N$(F,12 TO 13)=X$(2 TO )
 1570 RETURN 
 1580 GOTO 1600
 1600 GOSUB 44
 1602 RETURN 
 1620 GOTO 1600
 1660 GOTO 1600
 1680 INPUT X
 1682 PRINT AT K+1,22;X
 1684 LET X=X*100
 1686 GOSUB 16
 1688 LET N$(F,19 TO 20)=X$(2 TO )
 1690 RETURN 
 2000 FAST 
 2002 DIM T(8)
 2005 IF E=0 THEN GOTO 9100
 2010 CLS 
 2020 PRINT "%W%E%E%K%L%Y% %I%N%F%O"
 2025 PRINT 
 2026 PRINT "INPUT WEEK NO.="
 2030 INPUT X
 2040 IF X>W THEN GOTO 2070
 2050 PRINT "%A%L%R%E%A%D%Y% %E%N%T%E%R%E%D"
 2060 GOTO 1040
 2070 LET W=X
 2080 FOR K=1 TO E-1
 2090 FAST 
 2100 DIM X(2)
 2105 CLS 
 2110 PRINT N$(K, TO 10);",";N$(K,11)
 2120 PRINT 
 2130 PRINT "%I%N%P%U%T HRS(.25 PER 1/4 HR)=";
 2140 INPUT X(1)
 2150 PRINT X(1)
 2151 LET K$="PAID VAC/SICK DAYS"
 2155 PRINT 
 2156 PRINT K$;"  TODATE:";
 2157 LET X$="  "+N$(K,18)
 2158 GOSUB 36
 2159 PRINT X
 2160 PRINT "%I%N%P%U%T ";K$;"=";
 2170 INPUT X(2)
 2180 PRINT X(2)
 2190 PRINT AT 21,0;"CHANGE Y OR N?"
 2200 SLOW 
 2210 IF INKEY$="N" THEN GOTO 2270
 2220 IF INKEY$="Y" THEN GOTO 2090
 2230 GOTO 2210
 2270 FAST 
 2280 CLS 
 2290 LET X=X(1)*4+X(2)*32
 2300 GOSUB 16
 2310 LET N$(K,W+20)=X$(3)
 2320 LET X=X(2)
 2330 GOSUB 16
 2340 LET N$(K,18)=X$(3)
 2350 LET N$(K,W*2+70 TO W*2+71)=N$(K,12 TO 13)
 2360 LET Z=0
 2370 LET Y=W
 2380 GOSUB 200
 2390 GOSUB 10
 2400 NEXT K
 2410 GOTO 550
 3000 FAST 
 3005 IF E=0 THEN GOTO 9100
 3010 CLS 
 3015 GOSUB 3020
 3016 GOTO 3050
 3020 FOR K=1 TO E-1 STEP 2
 3030 PRINT CHR$ (K+156);TAB 3;N$(K, TO 10)+","+N$(K,11);TAB 16;CHR$ (K+157);TAB 20;N$(K+1, TO 10)+","+N$(K+1,11)
 3040 NEXT K
 3045 RETURN 
 3050 PRINT 
 3060 PRINT "%I%N%P%U%T NUMBER=";
 3070 INPUT K
 3080 PRINT K
 3090 PRINT "%I%N%P%U%T WEEK "
 3095 LET Z=1
 3100 INPUT Y
 3105 IF Y>W THEN GOTO 550
 3110 IF Y<>W THEN LET Z=2
 3120 GOSUB 200
 3130 GOSUB 10
 3140 GOTO 550
 4000 FAST 
 4010 CLS 
 4015 IF E=0 THEN GOTO 9100
 4020 PRINT "%P%A%Y%R%O%L%L% %F%O%R% %W%E%E%K%: ";W
 4030 PRINT 
 4040 PRINT "GROSS PAY        ";
 4045 LET V=15
 4050 LET P=T(8)
 4060 GOSUB 100
 4070 PRINT "%W%I%T%H%-%H%O%L%D%I%N%G%S"
 4074 PRINT 
 4075 LET V=7
 4080 FOR K=2 TO 8
 4090 PRINT H$(K);
 4100 LET P=T(K-1)
 4110 GOSUB 100
 4120 NEXT K
 4210 GOSUB 10
 4220 GOTO 550
 5000 FAST 
 5010 CLS 
 5015 IF E=0 THEN GOTO 9100
 5020 PRINT "%W%I%T%H%-%H%O%L%D%I%N%G%S% %T%O% %W%E%E%K ";W
 5030 PRINT 
 5090 LET V=8
 5100 FOR K=1 TO 7
 5105 PRINT H$(K+1);
 5110 LET P=W(K)
 5120 PRINT AT K+1,0;
 5130 GOSUB 100
 5140 NEXT K
 5150 GOSUB 10
 5160 GOTO 550
 6000 FAST 
 6005 IF E=0 THEN GOTO 9100
 6010 CLS 
 6020 PRINT "%C%H%A%N%G%E% %D%A%T%A"
 6025 GOSUB 3020
 6030 PRINT AT 21,0;"INPUT FILE NO."
 6032 INPUT Y
 6050 GOSUB 70
 6060 PRINT AT 2,22;N$(Y, TO 10)
 6070 PRINT AT 3,22;N$(Y,11)
 6110 LET X$=" "+N$(Y,12 TO 13)
 6120 GOSUB 36
 6130 PRINT AT 4,22;X/100
 6150 FOR K=14 TO 18
 6160 LET X$="  "+N$(Y,K)
 6170 GOSUB 36
 6180 PRINT AT K-9,22;X
 6190 NEXT K
 6200 LET X$=" "+N$(Y,19 TO 20)
 6210 GOSUB 36
 6220 PRINT AT 10,22;X/100
 6230 PRINT AT 21,0;"INPUT LINE NO,OR 0 FOR END"
 6240 INPUT K
 6250 IF K=0 THEN GOTO 550
 6260 IF K<1 OR K>10 THEN GOTO 6240
 6265 PRINT AT K+1,22;"% ";C$( TO 9)
 6268 PRINT AT 21,0;C$
 6269 LET F=Y
 6270 GOSUB K*20+1500
 6310 GOTO 6230
 7000 CLS 
 7001 PRINT "THIS MODE CLEARS FILES %P%R%E%S%S:     Y IF YOU WANT IT, N IF NOT"
 7002 SLOW 
 7003 IF INKEY$="N" THEN GOTO 550
 7004 IF INKEY$="Y" THEN GOTO 7010
 7005 GOTO 7003
 7010 FAST 
 7011 RUN 7015
 7015 DIM W(7)
 7020 DIM C$(32)
 7030 DIM N$(25,200)
 7031 DIM H$(8,4)
 7032 LET H$(2)="FWT"
 7033 LET H$(3)="STAX"
 7034 LET H$(4)="FICA"
 7035 LET H$(5)="DISA"
 7036 LET H$(6)="UNEM"
 7037 LET H$(7)="OTAX"
 7038 LET H$(8)="OTHR"
 7040 LET E=1
 7041 LET H$(1)="GRSS"
 7050 DIM W(7)
 7060 FAST 
 7070 CLS 
 7080 PRINT H$(4);"  '/.  RATE=";
 7090 INPUT S
 7100 PRINT S
 7110 PRINT H$(4);" $ LIMIT=";
 7120 INPUT T
 7130 PRINT T
 7140 PRINT H$(5);"  '/.  RATE=";
 7150 INPUT D
 7160 PRINT D
 7170 PRINT H$(6);"  '/.  RATE=";
 7180 INPUT W
 7190 PRINT W
 7200 PRINT AT 21,0;"CHANGE Y OR N?"
 7210 SLOW 
 7220 IF INKEY$="Y" THEN GOTO 7060
 7230 IF INKEY$="N" THEN GOTO 550
 7240 GOTO 7220
 8000 CLS 
 8010 SAVE "PA%Y"
 8020 GOTO 500
 9000 FAST 
 9010 CLS 
 9020 IF E=0 THEN GOTO 9100
 9030 PRINT H$(4);" '/.  RATE=";S
 9040 PRINT H$(4);" $ LIMIT=";T
 9050 PRINT H$(5);"  '/.  RATE=";D
 9060 PRINT H$(6);"  '/.  RATE=";U
 9070 GOTO 7200
 9100 PRINT "%I%N%I%T%I%A%T%E% %F%I%R%S%T"
 9110 GOTO 1040

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

People

No people associated with this content.

Scroll to Top