SCHEDI-MORT is a loan amortization scheduler that computes periodic payment amounts and produces a full schedule showing payment number, payment amount, interest portion, principal portion, and remaining balance for each period. The program supports five payment frequencies (daily, weekly, monthly, quarterly, and yearly) and uses the standard annuity formula H = (I1 / (1 − (1 + I1)^(−P))) × L to derive the fixed payment, with each period’s values rounded to the nearest cent using INT(…×100 + 0.5)/100. Output can be directed either to the screen or to a printer, with the printer path offering a choice between 32-column and 80-column widths, adjusting TAB positions via a scaling factor S. A decorative border routine at line 1020 draws a pixel-level rectangle using PLOT, and block-graphic characters (the inverse checkerboard \!!) form separator lines throughout the display.
Program Analysis
Program Structure
The program is organized into a linear sequence of distinct phases, with a subroutine for border drawing and a branch into a separate printer output path:
- Lines 20–220: Splash screen — fills the display with inverse characters, draws a pixel border, and shows title, publisher, and copyright notices with timed pauses.
- Lines 230–360: Publisher information and extended copyright warning screens.
- Lines 370–630: Input phase — borrower name, date, interest rate, loan amount, payment frequency, and number of payments.
- Lines 631–635: Printer selection branch; if printing is wanted, jumps to line 1110.
- Lines 640–920: Screen output path — computes and displays the amortization table.
- Lines 930–1010: Repeat-or-exit prompt, looping back to line 370 or stopping.
- Lines 1020–1100: Border subroutine using PLOT.
- Lines 1110–1440: Printer output path — mirrors the screen path but uses LPRINT with width-adjusted TAB positions, then falls through to the repeat prompt at line 940.
Amortization Formula
The fixed periodic payment H is computed at line 810 (screen) and line 1330 (printer) using the standard annuity formula:
H = INT(((I1 / (1 − (1 + I1)^(−P))) × L × 100) + 0.5) / 100
where I1 = I / R is the per-period interest rate, P is the total number of payments, and L is the loan principal. The ** operator is used for exponentiation. Each period’s interest portion V1 and updated balance L are also rounded to the nearest cent in the same way, preventing floating-point drift from accumulating across hundreds of periods.
Payment Frequency Handling
The variable R holds the number of periods per year, set by string comparison against the user’s single-letter input:
| Input | Period | R |
|---|---|---|
D | Daily | 365 |
W | Weekly | 52 |
M | Monthly | 12 |
Q | Quarterly | 4 |
Y | Yearly | 1 |
The program also normalizes the interest rate at line 480: if the entered value is greater than 1 (i.e., entered as a percentage rather than a decimal), it divides by 100.
Printer Output Path
When the user requests a printed copy (line 634–635), execution jumps to the subroutine starting at line 1110. The user selects between 32-column (Q$="A", S=0) and 80-column (Q$="B", S=5) output. All TAB positions in the LPRINT statements are scaled by multiples of S (e.g., TAB(5+2*S), TAB(10+4*S)) so that columns spread appropriately for wider paper. The 80-column separator uses 80 asterisk characters, while the 32-column version uses the block-graphic inverse checkerboard pattern.
Display Techniques
- Screen fill: Lines 30–90 allocate a 704-character string
A$, fill every element with the inverse@character (creating a solid block pattern), and PRINT it to cover the entire display. - Pixel border: The subroutine at lines 1020–1100 uses PLOT to draw a rectangular border along the edges of the 64×44 pixel ZX81 screen, called before each major text screen.
- Separator lines: The variable
Z$is assigned a 32-character string of the block-graphic inverse checkerboard (\!!escape sequences) to form decorative horizontal rules above and below the schedule header and footer. - Timed displays: PAUSE statements throughout (ranging from 60 to 900 frames) control how long each splash, copyright, and summary screen remains visible.
Key BASIC Idioms
- The FAST/SLOW pair (lines 20/110 and 240/260) switches the display mode for faster string initialization before returning to normal rendering.
- Repeated IF tests (lines 560–600, 710–750) replace a SELECT/CASE structure absent from this BASIC dialect.
- The loop at lines 50–70 pre-fills
A$(F)one character at a time, which is required because DIM initializes a string array to spaces and direct substring assignment fills all elements.
Bugs and Anomalies
- Final payment rounding: Because each payment is a fixed rounded value of
H, the final period’s remaining balanceLwill generally not reach exactly zero — a common artifact of fixed-payment amortization schedules that do not include a balloon-payment adjustment for the last period. - No input validation: There is no check that
B$matches one of the five valid letters; an unrecognized entry leavesRundefined (or retaining a prior value), which would produce incorrect results without any error message. - Column label mismatch: The column header uses “PRINCIPLE” (line 800/1320) rather than the standard spelling “PRINCIPAL.”
- LPRINT AT usage: Lines 1210 uses
LPRINT AT 7,0;— the AT modifier has no defined effect on a printer and the behaviour depends on the specific printer driver in use.
Content
Source Code
10 REM "SCHEDI-MORT"
20 FAST
30 DIM A$(704)
40 LET A$="\@@"
50 FOR F=1 TO 704
60 LET A$(F)=A$
70 NEXT F
80 PRINT AT 0,0;
90 PRINT A$
100 PRINT AT 0,0;
110 SLOW
120 GOSUB 1020
130 PAUSE 60
140 PRINT AT 7,8;"\ .\:'\''\''\''\''\''\''\''\''\''\''\''\':\. "
150 PRINT AT 8,8;"\ : SCHEDI-MORT \: "
160 PRINT AT 9,8;"\ '\:.\..\..\..\..\..\..\..\..\..\..\..\.:\' "
170 PAUSE 120
180 PRINT AT 13,10;"PROFESSIONAL"
190 PRINT AT 14,5;"AMORTIZATION SCHEDULER"
200 PAUSE 60
210 PRINT AT 18,9;"COPYRIGHT 1983"
220 PAUSE 360
230 CLS
240 FAST
250 GOSUB 1020
260 SLOW
270 PRINT AT 8,10;"SCHEDI-MORT"
280 PRINT TAB (8);"IS A PRODUCT OF"
290 PRINT TAB (4);"E. ARTHUR BROWN COMPANY"
300 PRINT TAB (5);"1702 OAK KNOLL DRIVE"
310 PRINT TAB (5);"ALEXANDRIA, MN 56308"
320 PAUSE 360
330 CLS
340 PRINT AT 5,0;"COPYRIGHT 1983 BY EBEN A. BROWN.ALL RIGHTS RESERVED. NO PART OFTHIS PROGRAM MAY BE REPRODUCEDFOR RESALE BY ANY MEANS,MECHANI-CAL OR ELECTRONIC, INCLUDINGPHOTOCOPYING, RECORDING, OR ANYINFORMATION STORAGE AND RETRIEV-AL SYSTEM WITHOUT WRITTEN PER-MISSION FROM THE AUTHOR.";
350 PRINT "CASSETTEAND PRINTED VERSIONS OF THISPROGRAM ARE PRODUCED ON COPY -DETECTING MAGNETIC TAPE ANDPAPER. COPYRIGHT INFRINGEMENTIS A FEDERAL OFFENSE."
360 PAUSE 900
370 CLS
380 PRINT AT 6,5;"ENTER NAME OF BORROWER"
390 INPUT F$
400 PRINT AT 10,7;"ENTER TODAYS DATE"
410 INPUT E$
420 CLS
430 PRINT AT 8,6;"ENTER INTEREST RATE"
440 INPUT I
450 PRINT AT 12,7;"ENTER LOAN AMOUNT"
460 INPUT L
470 CLS
480 IF I>1 THEN LET I=I/100
490 PRINT AT 2,3;"SELECT YOUR PAYMENT PERIOD"
500 PRINT TAB (6);"(D) DAILY"
510 PRINT TAB (6);"(W) WEEKLY"
520 PRINT TAB (6);"(M) MONTHLY"
530 PRINT TAB (6);"(Q) QUARTERLY"
540 PRINT TAB (6);"(Y) YEARLY"
550 INPUT B$
560 IF B$="D" THEN LET R=365
570 IF B$="W" THEN LET R=52
580 IF B$="M" THEN LET R=12
590 IF B$="Q" THEN LET R=4
600 IF B$="Y" THEN LET R=1
610 PRINT AT 9,1;"ENTER TOTAL NUMBER OF PAYMENTS"
620 INPUT P
630 CLS
631 PRINT AT 9,3;"WILL YOU BE NEEDING A PRINTEDCOPY?"
632 PRINT TAB (10);"(Y)YES"
633 PRINT TAB (10);"(N)NO"
634 INPUT Y$
635 IF Y$="Y" THEN GOTO 1110
640 LET Z$="\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!"
650 LET I1=I/R
655 CLS
660 PRINT AT 7,0;Z$
670 PRINT AT 9,5;"AMORTIZATION SCHEDULE"
680 PRINT TAB (7);"FOR ";F$
690 PRINT TAB (15);"ON"
700 PRINT TAB (12);E$
710 IF B$="D" THEN PRINT "$";L;" AT ";I*100;" PERCENT-PAID DAILY"
720 IF B$="W" THEN PRINT "$";L;" AT ";I*100;" PERCENT-PAID WEEKLY"
730 IF B$="Q" THEN PRINT "$";L;" AT ";I*100;" PERCENT-PAID QUARTERLY"
740 IF B$="M" THEN PRINT "$";L;" AT ";I*100;" PERCENT-PAID MONTHLY"
750 IF B$="Y" THEN PRINT "$";L;" AT ";I*100;" PERCENT-PAID YEARLY"
760 PRINT
770 PRINT Z$
780 PAUSE 360
790 CLS
800 PRINT "PERIOD";TAB (5);"PAYMENT";TAB (10);"INTEREST";TAB (15);"PRINCIPLE";TAB (20);"REM. BAL."
810 LET H=((INT (((I1/(1-(1+I1)**(-P)))*L*100)+.5)))/100
820 FOR V=1 TO P
830 LET V1=(INT (L*I1*100+.5))/100
840 LET L=(INT (((L-(H-V1))*100)+.5))/100
850 PRINT V;TAB (5);H;" ";TAB (10);V1;" ";TAB (15);H-V1;" ";TAB (20);L
860 NEXT V
870 PRINT Z$
880 PRINT
890 PRINT TAB (6);"PROCESSING COMPLETE"
900 PRINT
910 PRINT Z$
920 PAUSE 200
930 CLS
940 PRINT AT 10,0;"DO YOU WISH TO AMORTIZE ANY MORE LOANS? (YES) OR (NO)"
950 INPUT U$
960 IF U$="YES" THEN GOTO 370
970 CLS
980 PRINT AT 10,2;"OKAY,THAT ENDS THIS PROCESSING RUN"
990 PAUSE 240
\n1000 CLS
\n1010 STOP
\n1020 FOR G=0 TO 63
\n1030 PLOT G,0
\n1040 PLOT G,43
\n1050 NEXT G
\n1060 FOR J=0 TO 43
\n1070 PLOT 0,J
\n1080 PLOT 63,J
\n1090 NEXT J
\n1100 RETURN
\n1110 CLS
\n1120 PRINT AT 9,0;"PLEASE SELECT THE SIZE OF PRINT-OUT YOU DESIRE."
\n1130 PRINT TAB (6);"(A)32 CHARACTER WIDTH"
\n1140 PRINT TAB (6);"(B)80 CHARACTER WIDTH"
\n1150 INPUT Q$
\n1160 IF Q$="A" THEN LET S=0
\n1170 IF Q$="A" THEN LET Z$="\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!"
\n1180 IF Q$="B" THEN LET S=5
\n1189 IF Q$="B" THEN LET Z$="********************************************************************************"
\n1200 LET I1=I/R
\n1210 LPRINT AT 7,0;Z$
\n1220 LPRINT AT 9,5+3*S;"AMORTIZATION SCHEDULE"
\n1230 LPRINT TAB (7+3*S);"FOR ";F$
\n1240 LPRINT TAB (12+3*S);E$
\n1250 IF B$="D" THEN LPRINT TAB (3*S);"$";L;" AT ";I*100;" PERCENT-PAID DAILY"
\n1260 IF B$="W" THEN LPRINT TAB (3*S);"$";L;" AT ";I*100;" PERCENT-PAID WEEKLY"
\n1270 IF B$="Q" THEN LPRINT TAB (3*S);"$";L;" AT ";I*100;" PERCENT-PAID QUARTERLY"
\n1280 IF B$="M" THEN LPRINT TAB (3*S);"$";L;" AT ";I*100;" PERCENT-PAID MONTHLY"
\n1290 IF B$="Y" THEN LPRINT TAB (3*S);"$";L;" AT ";I*100;" PERCENT-PAID YEARLY"
\n1300 LPRINT
\n1310 LPRINT Z$
\n1320 LPRINT "PERIOD";TAB (5+2*S);"PAYMENT";TAB (10+4*S);"INTEREST";TAB (15+6*S);"PRINCIPLE";TAB (20+8*S);"REM.BAL."
\n1330 LET H=((INT (((I1/(1-(1+I1)**(-P)))*L*100)+.5)))/100
\n1340 FOR V=1 TO P
\n1350 LET V1=(INT (L*I1*100+.5))/100
\n1360 LET L=(INT (((L-(H-V1))*100)+.5))/100
\n1370 LPRINT V;TAB (5+2*S);H;" ";TAB (10+4*S);V1;" ";TAB (15+6*S);H-V1;" ";TAB (20+8*S);L
\n1380 NEXT V
\n1390 LPRINT Z$
\n1400 LPRINT
\n1410 LPRINT TAB (6+2*S);"PROCESSING COMPLETE"
\n1420 LPRINT
\n1430 LPRINT Z$
\n1435 CLS
\n1440 GOTO 940
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

