Payroll

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

This program is a complete employee payroll management system that stores records for up to 50 employees in a two-dimensional string array. Each record is packed into a 60-character fixed-width string, with defined byte ranges for employee number (columns 1–6), last name (7–18), first name (19–30), hourly wage (31–35), regular hours (36–42), overtime hours (43–50), and extra deductions (51–60). The main menu offers seven functions: data entry, wage calculation, record editing, tape save, tax parameter setup, hours clearing, and program re-initialization. A currency formatting subroutine at line 9500 rounds values to two decimal places and inserts a thousands comma separator. Tax calculations support federal withholding, FICA (Social Security), and an optional state income tax, all stored as user-supplied percentages.


Program Analysis

Program Structure

The program is organized around a menu dispatcher at lines 10–250. After drawing a bordered screen and presenting seven options, it reads a keypress via subroutine 9000 and uses the idiom GOTO VAL B$*1000 at line 250 to branch directly to the routine for the chosen option. Each major function occupies a dedicated thousand-line block:

Line RangeFunction
1000–1900Employee data entry
2000–2030Wage calculation (redirects to record lookup)
3000–3890Record lookup, display, and editing
4000–4050Tape save
5000–5270Tax parameter setup
6000–6050Clear weekly hours
7000–7040Pay display subroutine
8000–8070Record write subroutine
9000–9020Keypress input subroutine
9500–9560Currency formatting subroutine

Data Storage: Fixed-Width String Array

All employee records are held in E$(50,60), a two-dimensional string array dimensioned at line 2. Each row stores one employee’s complete record packed into 60 characters with hard-coded column slices:

  • Columns 1–6: Employee number (P$)
  • Columns 7–18: Last name (N$)
  • Columns 19–30: First/middle name (F$)
  • Columns 31–35: Hourly wage (W$)
  • Columns 36–42: Regular hours (H$)
  • Columns 43–50: Overtime hours (O$)
  • Columns 51–60: Extra deductions (D$)

The counter R1 tracks how many records have been entered. Record search at line 3060 compares the entered employee number against E$(N, TO LEN P$), matching only the leading characters of the stored field.

Menu Dispatch Technique

The line 250 GOTO VAL B$*1000 is a classic ZX81 BASIC trick: multiplying the single-digit string value of the keypress by 1000 produces the exact line number of each routine, avoiding a chain of IF/GOTO statements. Option 7 is handled specially at line 225 with IF B$="7" THEN RUN, which re-initializes all variables before the dispatch would try to reach non-existent line 7000 (which is instead a subroutine, not the menu option target).

Edit Menu Dispatch

A second computed GOTO appears at line 3190: GOTO 3180+(20*VAL B$). Since edit options 1–8 are each 20 lines apart (3200, 3220, 3240, …, 3340), this neatly dispatches to the correct field editor. Each editor prints the old value, accepts a new string input, writes it back into the appropriate column slice of E$(N,...), and returns to the display/edit loop at line 3100.

Currency Formatting Subroutine (9500)

This subroutine is called with a value in X and returns a formatted string in X$. It performs the following steps:

  1. Round to two decimal places: INT(100*X+.05)/100
  2. Convert to string with STR$
  3. Pad cases where STR$ produces 1 or 2 characters (e.g., "5""5.00")
  4. Append a trailing zero if only one decimal digit is present
  5. Append ".00" if no decimal point is two characters from the end
  6. Insert a comma thousands separator if the string exceeds 6 characters

The rounding uses +.05 rather than the conventional +.5; since values are scaled by 100 first, the effective addition before truncation is 0.0005, which rounds to the nearest cent at the third decimal place rather than the second. This is a subtle rounding anomaly — the correct bias for cent rounding after multiplying by 100 should be +0.5, not +0.05. Values will only round up when the third decimal digit is 5 or above, but the rounding threshold for the second decimal is actually 0.005, which the code achieves correctly via +.05 applied after the ×100 scale — on reflection this is actually correct behavior.

Pay Calculation

Gross pay is computed at line 3590 by extracting stored string fields with VAL:

GP = wage * (reg_hours + 1.5 * ot_hours)

From gross pay, three deductions are subtracted:

  • Federal withholding tax: GP * 0.01 * FWT
  • FICA/Social Security: GP * 0.01 * SS
  • State income tax: GP * 0.01 * ST (skipped if ST=0)
  • Extra (non-tax) deductions: stored value from E$(N,51 TO 60)

Tax rates are stored as percentages (e.g., 7.65 for FICA) and divided by 100 implicitly via the *0.01 factor.

Screen Drawing

The main menu border is drawn using block graphics strings. Line 30 builds a row string A$ with left/right border characters and a field of inverse-space fills, then prints it 23 times in a FOR loop. Lines 70 then overprint the top and bottom rows with solid horizontal bar characters. The menu text uses inverse video characters (e.g., %E%M%P%L%O%Y%E%E) for highlighted labels.

FAST/SLOW Mode Switching

The program extensively toggles between FAST (no display refresh, faster execution) and SLOW (display active) modes. SLOW is entered just before INPUT statements so the user can see the prompt, and FAST is restored immediately after. This is standard practice to maximize execution speed while keeping the display readable during data entry.

Notable Bugs and Anomalies

  • Line 6010: LET E$(N,36 TO 50)="0 0" — this string is 8 characters wide but the target slice is 15 characters (columns 36–50). ZX81 BASIC pads with spaces, so regular hours get “0” and overtime gets “0” with intervening spaces, which VAL will correctly parse as 0.
  • Line 80: FOR N=1 TO 22 opens a loop that is never closed with NEXT N before the loop variable is reused throughout the program. ZX81 BASIC does not enforce loop stack integrity when GOTO exits a FOR block, so this stale loop context lingers harmlessly.
  • Lines 2020–2030 (the wage calculation path): after finding and displaying an employee record via AA=1, execution reaches line 2020 (PRINT AT 21,0;) then falls through to line 2030 (GOTO 5250), prompting the user to press Enter to return. This is functional but structurally awkward — the wage display for option 2 reuses the edit lookup routine (3000) via the AA flag.
  • The POKE 16418,0 at line 20 and POKE 16418,2 at line 240 manipulate the system variable DF_SZ (lower screen size), collapsing and expanding the editing area respectively.

Key BASIC Idioms

  • GOSUB 9000 / IF B$="" THEN GOTO 9000: a spin-wait keypress loop without PAUSE, returning the key in B$.
  • VAL B$*1000 in GOTO: computed branch replacing a multi-line IF chain.
  • All monetary values passed to subroutine 9500 via the shared variable X, with result returned in X$ — a parameter-passing convention using globals.
  • TAB 32-LEN X$ for right-aligning currency strings in a 32-column display.

Content

Appears On

Cassette to accompany the February 1983 issue of Synchro-Sette.

Related Products

Related Articles

Related Content

Image Gallery

Payroll

Source Code

   1 FAST 
   2 DIM E$(50,60)
   3 LET R1=0
  10 FAST 
  15 CLS 
  20 POKE 16418,0
  30 LET A$=": @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ :"
  40 FOR N=1 TO 23
  50 PRINT A$
  60 NEXT N
  70 PRINT AT 0,0;":'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''':";AT 23,0;":..............................................................:"
  80 FOR N=1 TO 22
  90 PRINT AT 2,6;"% %E%M%P%L%O%Y%E%E% %P%A%Y%R%O%L%L% "
 100 PRINT AT 5,2;" TO ENTER EMPLOYEE INFO    %1"
 110 PRINT AT 7,2;" TO CALCULATE WEEKLY WAGES %2"
 120 PRINT AT 9,2;" TO EDIT EMPLOYEE INFO     %3"
 130 PRINT AT 11,2;" TO SAVE FILE ON TAPE      %4"
 140 PRINT AT 13,2;" TO SET TAX PARAMETERS     %5"
 150 PRINT AT 15,2;" TO CLEAR HOURS            %6"
 160 PRINT AT 17,2;" TO INITIALIZE PROGRAM     %7"
 170 LET AA=0
 199 SLOW 
 200 GOSUB 9000
 210 IF CODE B$<29 OR CODE B$>35 THEN GOTO 200
 220 FAST 
 225 IF B$="7" THEN RUN 
 230 CLS 
 240 POKE 16418,2
 250 GOTO VAL B$*1000
 1000 SCROLL 
 1010 SCROLL 
 1020 PRINT "IF NO MORE EMPLOYEES ARE TO BE"
 1030 SCROLL 
 1040 PRINT "ENTERED, JUST PRESS ENTER FOR"
 1050 SCROLL 
 1060 PRINT "THE LAST NAME:::"
 1070 FOR N=1 TO 14
 1075 LET O=0
 1080 SCROLL 
 1090 NEXT N
 1100 FOR N=R1+1 TO 100
 1110 SCROLL 
 1120 SCROLL 
 1130 PRINT "LAST NAME OF EMPLOYEE NO. ";N
 1140 SCROLL 
 1150 SLOW 
 1160 INPUT N$
 1170 FAST 
 1180 IF N$="" THEN GOTO 1900
 1190 SCROLL 
 1200 PRINT ,N$
 1210 SCROLL 
 1220 SCROLL 
 1230 PRINT "FIRST, MID NAME OF EMPLOYEE?"
 1240 SCROLL 
 1250 SLOW 
 1260 INPUT F$
 1270 FAST 
 1280 SCROLL 
 1290 PRINT ,F$
 1300 SCROLL 
 1310 SCROLL 
 1320 PRINT "EMPLOYEE NUMBER?"
 1330 SLOW 
 1340 INPUT P$
 1350 FAST 
 1360 SCROLL 
 1370 PRINT ,P$
 1380 SCROLL 
 1390 SCROLL 
 1400 PRINT "TOTAL HOURS WORKED DURING WEEK"
 1410 SLOW 
 1420 INPUT H
 1430 FAST 
 1440 IF H<=40 THEN LET H$=STR$ H
 1445 IF H>40 THEN LET H$="40"
 1450 IF H>40 THEN LET O=H-40
 1455 LET O$=STR$ O
 1460 SCROLL 
 1470 IF H<=40 THEN PRINT "REG HOURS = ";H
 1480 IF H>40 THEN PRINT "REG HOURS = 40, OT HOURS = ";O
 1490 SCROLL 
 1500 SCROLL 
 1510 PRINT "HOURLY WAGE?";
 1520 SCROLL 
 1530 SLOW 
 1540 INPUT W
 1550 FAST 
 1555 LET W$=STR$ W
 1560 PRINT ,W
 1570 SCROLL 
 1580 SCROLL 
 1581 PRINT "TOTAL NON-TAX DEDUCTIONS?"
 1582 SLOW 
 1583 INPUT D$
 1584 FAST 
 1585 IF D$="" THEN LET D$="0"
 1586 SCROLL 
 1587 PRINT ,D$
 1588 SCROLL 
 1589 SCROLL 
 1590 PRINT "DO YOU WANT TO SEE EMPLOYEE PAY?"
 1600 SLOW 
 1610 INPUT Y$
 1620 FAST 
 1625 GOSUB 8000
 1630 IF Y$(1)="Y" THEN GOSUB 7000
 1640 CLS 
 1650 NEXT N
 1660 STOP 
 1900 LET R1=N-1
 1910 GOTO 10
 2000 LET AA=1
 2010 GOTO 3000
 2020 PRINT AT 21,0;
 2030 GOTO 5250
 3000 PRINT ,,"WHAT IS THE EMPLOYEE NUMBER?"
 3010 SLOW 
 3020 INPUT P$
 3030 FAST 
 3040 CLS 
 3050 FOR N=1 TO R1
 3060 IF P$=E$(N, TO LEN P$) THEN GOTO 3100
 3065 NEXT N
 3070 PRINT AT 10,0;P$;" IS NOT IN THE FILE :::"
 3080 GOTO 5226
 3100 GOSUB 3500
 3105 IF AA=1 THEN GOTO 2020
 3110 PRINT ,,"1 %L%A%S%T% %N%A%M%E","5 %W%A%G%E"
 3120 PRINT ,,"2 %F%I%R%S%T% %N%A%M%E","6 %R%E%G%.% %H%O%U%R%S"
 3130 PRINT ,,"3 %E%M%P%.% %N%O%.","7 %O%.%T%.% %H%O%U%R%S",,,"4 %X%T%R%A% %D%E%D%.","8 %R%E%T%.% %T%O% %M%E%N%U"
 3140 SLOW 
 3150 GOSUB 9000
 3160 FAST 
 3170 IF CODE B$<29 OR CODE B$>36 THEN GOTO 3140
 3180 CLS 
 3190 GOTO 3180+(20*VAL B$)
 3200 PRINT ,,"OLD LAST NAME IS ";E$(N,7 TO 18),,,"TYPE IN NEW LAST NAME ::"
 3202 SLOW 
 3204 INPUT B$
 3206 FAST 
 3208 LET E$(N,7 TO 18)=B$
 3210 CLS 
 3212 GOTO 3100
 3220 PRINT ,,"OLD FIRST NAME IS ";E$(N,19 TO 30),,,"TYPE IN NEW FIRST NAME ::"
 3222 SLOW 
 3224 INPUT B$
 3226 FAST 
 3228 LET E$(N,19 TO 30)=B$
 3230 GOTO 3210
 3240 PRINT ,,"OLD EMP. NO. IS ";E$(N, TO 6),,,"TYPE IN NEW EMP. NO. ::"
 3242 SLOW 
 3244 INPUT B$
 3246 FAST 
 3248 LET E$(N, TO 6)=B$
 3250 GOTO 3210
 3260 PRINT ,,"OLD XTRA DED. ARE ";E$(N,51 TO 60),,,"TYPE IN NEW XTRA DED. ::"
 3262 SLOW 
 3264 INPUT B$
 3266 FAST 
 3268 LET E$(N,51 TO 60)=B$
 3270 GOTO 3210
 3280 PRINT ,,"OLD WAGES ARE ";E$(N,31 TO 35),,,"TYPE IN NEW WAGES ::"
 3282 SLOW 
 3284 INPUT B$
 3286 FAST 
 3288 LET E$(N,31 TO 35)=B$
 3290 GOTO 3210
 3300 PRINT ,,"OLD REG..HOURS ARE ";E$(N,36 TO 42),,,"TYPE IN NEW REG. HOURS ::"
 3302 SLOW 
 3304 INPUT B$
 3306 FAST 
 3308 LET E$(N,36 TO 42)=B$
 3310 GOTO 3210
 3320 PRINT ,,"OLD O.T..HOURS ARE ";E$(N,43 TO 50),,,"TYPE IN NEW O.T. HOURS ::"
 3322 SLOW 
 3324 INPUT B$
 3326 FAST 
 3328 LET E$(N,43 TO 50)=B$
 3330 GOTO 3210
 3340 CLS 
 3350 GOTO 10
 3500 PRINT ,,"EMPLOYEE NO.",E$(N, TO 6)
 3510 PRINT "NAME - ";E$(N,19 TO 30);" ";E$(N,7 TO 18)
 3520 PRINT "HOURLY WAGE";
 3530 LET X=VAL E$(N,31 TO 35)
 3540 GOSUB 9500
 3550 LET W$=X$
 3560 PRINT TAB 32-LEN W$;W$
 3570 PRINT "REGULAR HOURS",E$(N,36 TO 42)
 3580 IF VAL E$(N,43 TO 50)<>0 THEN PRINT "OVERTIME HOURS",E$(N,43 TO 50)
 3590 LET GP=VAL E$(N,31 TO 35)*(VAL E$(N,36 TO 42)+(1.5*(VAL E$(N,43 TO 50))))
 3600 LET X=GP
 3610 GOSUB 9500
 3620 PRINT "GROSS PAY -";TAB 32-LEN X$;X$
 3625 LET GP=VAL X$
 3630 PRINT "FED. WITH. TAX";
 3640 LET FT=GP*.01*FWT
 3650 LET X=FT
 3670 GOSUB 9500
 3680 PRINT TAB 32-LEN X$;X$
 3685 LET FT=VAL X$
 3690 PRINT "FICA";
 3700 LET FICA=GP*.01*SS
 3710 LET X=FICA
 3720 GOSUB 9500
 3730 PRINT TAB 32-LEN X$;X$
 3735 LET FICA=VAL X$
 3737 LET SWT=0
 3740 IF ST=0 THEN GOTO 3800
 3750 PRINT "STATE WITH. TAX";
 3760 LET SWT=GP*.01*ST
 3770 LET X=SWT
 3780 GOSUB 9500
 3790 PRINT TAB 32-LEN X$;X$
 3795 LET SWT=VAL X$
 3800 PRINT "EXTRA DEDUCTIONS -";
 3810 LET ED=VAL E$(N,51 TO 60)
 3815 LET X=ED
 3820 GOSUB 9500
 3830 PRINT TAB 32-LEN X$;X$
 3835 LET ED=VAL X$
 3840 PRINT ,,"NET PAY -";
 3850 LET NP=GP-FT-FICA-SWT-ED
 3860 LET X=NP
 3870 GOSUB 9500
 3880 PRINT TAB 32-LEN X$;X$
 3890 RETURN 
 4000 PRINT AT 10,4;"WHAT IS THE FILE NAME?"
 4010 INPUT N$
 4020 PRINT AT 12,0;"SET UP THE TAPE RECORDER AND    PRESS THE ENTER KEY TO SAVE :::"
 4030 INPUT B$
 4040 SAVE N$
 4050 GOTO 10
 5000 SCROLL 
 5010 PRINT "WHAT PERCENTAGE FOR FED W. TAX?"
 5020 SCROLL 
 5030 SLOW 
 5040 INPUT FWT
 5050 FAST 
 5060 SCROLL 
 5070 PRINT ,FWT;"  '/. "
 5080 SCROLL 
 5090 SCROLL 
 5100 PRINT "WHAT PERCENTAGE FOR SOC SEC?"
 5105 SCROLL 
 5110 SLOW 
 5120 INPUT SS
 5130 FAST 
 5140 SCROLL 
 5150 PRINT ,SS;"  '/. "
 5160 SCROLL 
 5170 SCROLL 
 5180 PRINT "WHAT PER. FOR STATE INC. TAX?" 
 5185 SCROLL 
 5190 SLOW 
 5200 INPUT ST
 5210 FAST 
 5220 SCROLL 
 5225 PRINT ,ST;"  '/. "
 5226 SCROLL 
 5230 SCROLL 
 5240 SCROLL 
 5250 PRINT "PRESS ENTER TO RETURN TO MENU ::"
 5260 INPUT A$
 5270 GOTO 10
 6000 FOR N=1 TO R1
 6010 LET E$(N,36 TO 50)="0      0"
 6020 NEXT N
 6030 PRINT AT 10,0;"HOURS CLEARED - READY FOR NEXT  WEEK"
 6050 GOTO 5226
 7000 CLS 
 7010 GOSUB 3500
 7020 PRINT AT 21,0;"PRESS ENTER TO CONTINUE :::"
 7030 INPUT B$
 7040 RETURN 
 8000 LET E$(N, TO 6)=P$
 8010 LET E$(N,7 TO 18)=N$
 8020 LET E$(N,19 TO 30)=F$
 8030 LET E$(N,31 TO 35)=W$
 8040 LET E$(N,36 TO 42)=H$
 8050 LET E$(N,43 TO 50)=O$
 8060 LET E$(N,51 TO 60)=D$
 8070 RETURN 
 9000 PRINT AT 21,5;" ENTER ONE OF ABOVE ";AT 21,5;"% %E%N%T%E%R% %O%N%E% %O%F% %A%B%O%V%E% "
 9005 LET B$=INKEY$
 9010 IF B$="" THEN GOTO 9000
 9020 RETURN 
 9500 LET X=INT (100*X+.05)/100
 9510 LET X$=STR$ X
 9520 IF LEN X$=1 THEN LET X$=X$+".00"
 9525 IF LEN X$=2 THEN LET X$=X$+".0"
 9530 IF X$(LEN X$-1)="." THEN LET X$=X$+"0"
 9540 IF X$(LEN X$-2)<>"." THEN LET X$=X$+".00"
 9550 IF LEN X$>6 THEN LET X$=X$( TO LEN X$-7)+","+X$(LEN X$-6 TO LEN X$)
 9560 RETURN 

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

People

No people associated with this content.

Scroll to Top