Payroll

Date: 198x
Type: Cassette
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

Payroll

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
\n1000 FAST 
\n1010 CLS 
\n1015 IF E=0 THEN GOTO 9100
\n1020 IF E<33 THEN GOTO 1060
\n1030 PRINT "%F%I%L%E% %F%U%L%L"
\n1040 PAUSE 100
\n1050 GOTO 550
\n1060 PRINT "%A%D%D% %N%A%M%E..FILE NUMBER=";E
\n1070 PRINT 
\n1080 GOSUB 70
\n1081 LET F=E
\n1082 FOR K=1 TO 9
\n1085 PRINT AT K+1,22;"% ";C$(23 TO 31)
\n1090 GOSUB K*20+1500
\n1100 NEXT K
\n1110 LET E=E+1
\n1120 GOSUB 10
\n1130 GOTO 550
\n1520 INPUT N$(F, TO 10)
\n1522 PRINT AT K+1,22;N$(F, TO 10)
\n1524 RETURN 
\n1540 INPUT N$(F,11)
\n1542 PRINT AT K+1,22;N$(F,11 TO 12)
\n1544 RETURN 
\n1560 INPUT X
\n1562 PRINT AT K+1,22;X
\n1564 LET X=X*100
\n1566 GOSUB 16
\n1568 LET N$(F,12 TO 13)=X$(2 TO )
\n1570 RETURN 
\n1580 GOTO 1600
\n1600 GOSUB 44
\n1602 RETURN 
\n1620 GOTO 1600
\n1660 GOTO 1600
\n1680 INPUT X
\n1682 PRINT AT K+1,22;X
\n1684 LET X=X*100
\n1686 GOSUB 16
\n1688 LET N$(F,19 TO 20)=X$(2 TO )
\n1690 RETURN 
\n2000 FAST 
\n2002 DIM T(8)
\n2005 IF E=0 THEN GOTO 9100
\n2010 CLS 
\n2020 PRINT "%W%E%E%K%L%Y% %I%N%F%O"
\n2025 PRINT 
\n2026 PRINT "INPUT WEEK NO.="
\n2030 INPUT X
\n2040 IF X>W THEN GOTO 2070
\n2050 PRINT "%A%L%R%E%A%D%Y% %E%N%T%E%R%E%D"
\n2060 GOTO 1040
\n2070 LET W=X
\n2080 FOR K=1 TO E-1
\n2090 FAST 
\n2100 DIM X(2)
\n2105 CLS 
\n2110 PRINT N$(K, TO 10);",";N$(K,11)
\n2120 PRINT 
\n2130 PRINT "%I%N%P%U%T HRS(.25 PER 1/4 HR)=";
\n2140 INPUT X(1)
\n2150 PRINT X(1)
\n2151 LET K$="PAID VAC/SICK DAYS"
\n2155 PRINT 
\n2156 PRINT K$;"  TODATE:";
\n2157 LET X$="  "+N$(K,18)
\n2158 GOSUB 36
\n2159 PRINT X
\n2160 PRINT "%I%N%P%U%T ";K$;"=";
\n2170 INPUT X(2)
\n2180 PRINT X(2)
\n2190 PRINT AT 21,0;"CHANGE Y OR N?"
\n2200 SLOW 
\n2210 IF INKEY$="N" THEN GOTO 2270
\n2220 IF INKEY$="Y" THEN GOTO 2090
\n2230 GOTO 2210
\n2270 FAST 
\n2280 CLS 
\n2290 LET X=X(1)*4+X(2)*32
\n2300 GOSUB 16
\n2310 LET N$(K,W+20)=X$(3)
\n2320 LET X=X(2)
\n2330 GOSUB 16
\n2340 LET N$(K,18)=X$(3)
\n2350 LET N$(K,W*2+70 TO W*2+71)=N$(K,12 TO 13)
\n2360 LET Z=0
\n2370 LET Y=W
\n2380 GOSUB 200
\n2390 GOSUB 10
\n2400 NEXT K
\n2410 GOTO 550
\n3000 FAST 
\n3005 IF E=0 THEN GOTO 9100
\n3010 CLS 
\n3015 GOSUB 3020
\n3016 GOTO 3050
\n3020 FOR K=1 TO E-1 STEP 2
\n3030 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)
\n3040 NEXT K
\n3045 RETURN 
\n3050 PRINT 
\n3060 PRINT "%I%N%P%U%T NUMBER=";
\n3070 INPUT K
\n3080 PRINT K
\n3090 PRINT "%I%N%P%U%T WEEK "
\n3095 LET Z=1
\n3100 INPUT Y
\n3105 IF Y>W THEN GOTO 550
\n3110 IF Y<>W THEN LET Z=2
\n3120 GOSUB 200
\n3130 GOSUB 10
\n3140 GOTO 550
\n4000 FAST 
\n4010 CLS 
\n4015 IF E=0 THEN GOTO 9100
\n4020 PRINT "%P%A%Y%R%O%L%L% %F%O%R% %W%E%E%K%: ";W
\n4030 PRINT 
\n4040 PRINT "GROSS PAY        ";
\n4045 LET V=15
\n4050 LET P=T(8)
\n4060 GOSUB 100
\n4070 PRINT "%W%I%T%H%-%H%O%L%D%I%N%G%S"
\n4074 PRINT 
\n4075 LET V=7
\n4080 FOR K=2 TO 8
\n4090 PRINT H$(K);
\n4100 LET P=T(K-1)
\n4110 GOSUB 100
\n4120 NEXT K
\n4210 GOSUB 10
\n4220 GOTO 550
\n5000 FAST 
\n5010 CLS 
\n5015 IF E=0 THEN GOTO 9100
\n5020 PRINT "%W%I%T%H%-%H%O%L%D%I%N%G%S% %T%O% %W%E%E%K ";W
\n5030 PRINT 
\n5090 LET V=8
\n5100 FOR K=1 TO 7
\n5105 PRINT H$(K+1);
\n5110 LET P=W(K)
\n5120 PRINT AT K+1,0;
\n5130 GOSUB 100
\n5140 NEXT K
\n5150 GOSUB 10
\n5160 GOTO 550
\n6000 FAST 
\n6005 IF E=0 THEN GOTO 9100
\n6010 CLS 
\n6020 PRINT "%C%H%A%N%G%E% %D%A%T%A"
\n6025 GOSUB 3020
\n6030 PRINT AT 21,0;"INPUT FILE NO."
\n6032 INPUT Y
\n6050 GOSUB 70
\n6060 PRINT AT 2,22;N$(Y, TO 10)
\n6070 PRINT AT 3,22;N$(Y,11)
\n6110 LET X$=" "+N$(Y,12 TO 13)
\n6120 GOSUB 36
\n6130 PRINT AT 4,22;X/100
\n6150 FOR K=14 TO 18
\n6160 LET X$="  "+N$(Y,K)
\n6170 GOSUB 36
\n6180 PRINT AT K-9,22;X
\n6190 NEXT K
\n6200 LET X$=" "+N$(Y,19 TO 20)
\n6210 GOSUB 36
\n6220 PRINT AT 10,22;X/100
\n6230 PRINT AT 21,0;"INPUT LINE NO,OR 0 FOR END"
\n6240 INPUT K
\n6250 IF K=0 THEN GOTO 550
\n6260 IF K<1 OR K>10 THEN GOTO 6240
\n6265 PRINT AT K+1,22;"% ";C$( TO 9)
\n6268 PRINT AT 21,0;C$
\n6269 LET F=Y
\n6270 GOSUB K*20+1500
\n6310 GOTO 6230
\n7000 CLS 
\n7001 PRINT "THIS MODE CLEARS FILES %P%R%E%S%S:     Y IF YOU WANT IT, N IF NOT"
\n7002 SLOW 
\n7003 IF INKEY$="N" THEN GOTO 550
\n7004 IF INKEY$="Y" THEN GOTO 7010
\n7005 GOTO 7003
\n7010 FAST 
\n7011 RUN 7015
\n7015 DIM W(7)
\n7020 DIM C$(32)
\n7030 DIM N$(25,200)
\n7031 DIM H$(8,4)
\n7032 LET H$(2)="FWT"
\n7033 LET H$(3)="STAX"
\n7034 LET H$(4)="FICA"
\n7035 LET H$(5)="DISA"
\n7036 LET H$(6)="UNEM"
\n7037 LET H$(7)="OTAX"
\n7038 LET H$(8)="OTHR"
\n7040 LET E=1
\n7041 LET H$(1)="GRSS"
\n7050 DIM W(7)
\n7060 FAST 
\n7070 CLS 
\n7080 PRINT H$(4);" \ '/\.  RATE=";
\n7090 INPUT S
\n7100 PRINT S
\n7110 PRINT H$(4);" $ LIMIT=";
\n7120 INPUT T
\n7130 PRINT T
\n7140 PRINT H$(5);" \ '/\.  RATE=";
\n7150 INPUT D
\n7160 PRINT D
\n7170 PRINT H$(6);" \ '/\.  RATE=";
\n7180 INPUT W
\n7190 PRINT W
\n7200 PRINT AT 21,0;"CHANGE Y OR N?"
\n7210 SLOW 
\n7220 IF INKEY$="Y" THEN GOTO 7060
\n7230 IF INKEY$="N" THEN GOTO 550
\n7240 GOTO 7220
\n8000 CLS 
\n8010 SAVE "PA%Y"
\n8020 GOTO 500
\n9000 FAST 
\n9010 CLS 
\n9020 IF E=0 THEN GOTO 9100
\n9030 PRINT H$(4);"\ '/\.  RATE=";S
\n9040 PRINT H$(4);" $ LIMIT=";T
\n9050 PRINT H$(5);" \ '/\.  RATE=";D
\n9060 PRINT H$(6);" \ '/\.  RATE=";U
\n9070 GOTO 7200
\n9100 PRINT "%I%N%I%T%I%A%T%E% %F%I%R%S%T"
\n9110 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