--- title: "Loan Mortgage Amortizer" id: 51733 type: "computer_media" slug: "loan-mortgage-amortizer" url: "http://localhost/computer_media/loan-mortgage-amortizer/" markdown_url: "http://localhost/computer_media/loan-mortgage-amortizer.md" published_at: "2023-08-13T23:14:29+00:00" modified_at: "2026-04-04T20:18:04+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "A five-mode mortgage amortization tool that pre-calculates every monthly payment into a lookup array and offers reports from single-payment detail to a graphical interest/principal plot." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "Timex Computer Corporation" slug: "timex-computer-corporation" taxonomy: "post_tag" url: "http://localhost/tag/timex-computer-corporation/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Finance" slug: "finance" taxonomy: "genre" url: "http://localhost/type/finance/" media_type: "Cassette" download_url: "https://archive.org/download/timex-sinclair-software-archive/Loan Mortgage Amortizer (1982)(Timex)(US)(TS1000)(Cassette).zip" mediadate: "1982" producer_company: - id: 11401 title: "Timex Computer Corporation" type: "company" url: "http://localhost/company/timex-computer-corporation/" images: - url: "http://localhost/wp-content/uploads/2023/08/SCR-20260404-efdf.png" - url: "http://localhost/wp-content/uploads/2023/08/SCR-20260404-effd.png" related_products: - id: 14343 title: "The Loan/Mortgage Amortizer" type: "product" url: "http://localhost/product/the-loan-mortgage-amortizer/" media_type_tags: "Finance" --- This program calculates and displays amortization data for fixed-rate mortgages, accepting principal, term (up to 30 years), and annual interest rate as inputs. It pre-computes all monthly payment breakdowns into a two-dimensional array `T(N,3)`, storing per-payment interest, cumulative interest paid, and remaining principal balance for up to 360 entries. Five report modes are available: single payment detail, single year summary, monthly profile scrolling table, yearly profile scrolling table, and a character-graphics plot of the interest/principal split over the loan term. Column alignment for dollar amounts is handled manually by computing display offsets based on the magnitude of each value, using a cascading series of IF comparisons to set tab positions. *** ## Program Analysis ### Program Structure The program is organized as a main setup sequence with five subroutine modules and a main menu loop. Execution begins at line `10` with `GOTO 3500`, jumping past all subroutine code to the splash/intro section. Control flow is summarized below: | Line Range | Purpose | | --- | --- | | 10 | Entry point — jumps to initialization | | 95–496 | Subroutine: Single Payment Report | | 499–1090 | Subroutine: Single Year Report | | 1195–1530 | Subroutine: Monthly Profile (scrolling table) | | 1595–2020 | Subroutine: Yearly Profile (scrolling table) | | 2195–2470 | Subroutine: Interest/Principal Plot | | 3500–3730 | Splash screens and introduction text | | 3800–4180 | Data entry (principal, years, rate) and preliminary results | | 4200–4490 | First-payment date entry and amortization table computation loop | | 4490–4850 | Report menu and dispatch loop | | 4900–4910 | Program termination (`CLEAR`, `CLS`) | ### Amortization Table Computation After all inputs are validated, a `DIM T(N,3)` statement at line `4020` allocates the full payment table, where `N = Y * 12` (number of monthly payments, capped at 360 for a 30-year loan). The loop at lines `4410`–`4480` runs in `FAST` mode and fills three columns per payment: - `T(X,1)` — interest portion of payment X - `T(X,2)` — cumulative interest paid through payment X - `T(X,3)` — remaining principal balance after payment X The monthly payment amount `M` is computed using the standard annuity formula at line `4030`: `M = P*I / (1 - (1+I)^(-N))`, where `I = A/12` is the monthly rate. The rounded value `M1` is used for display, while the unrounded `M` is used in the amortization loop to avoid accumulating rounding errors over the life of the loan — a deliberate and correct design choice. ### Rounding Convention Throughout the program, monetary values are rounded to two decimal places using the idiom `(INT (X*100+.5))/100`. This banker-style rounding by half-up addition appears consistently in all five report subroutines and in the main computation. A threshold check, `IF T3<.1 THEN LET T3=0` (lines `250`, `850`) and `IF ABS T3<.6 THEN LET T3=0` (lines `1400`, `1900`), handles floating-point residuals in the final balance, preventing a nearly-zero balance from being displayed as a small non-zero number. ### Manual Column Alignment Because the platform’s PRINT statement does not support right-justified numeric output, the program manually computes a starting column `Z1`, `Z2`, or `Z3` for each dollar figure by testing its magnitude with a cascade of `IF` statements. For example, lines `300`–`330` set `Z1` to 5, 6, 7, or 8 depending on whether the interest amount is ≥1000, ≥100, ≥10, or smaller. This shifts the dollar sign leftward by one column for each additional digit, approximating right-alignment within a fixed field. ### Report Subroutines All five reports are implemented as `GOSUB` targets ending with `RETURN`, called from the dispatch block at lines `4760`–`4820`. After returning, a `PAUSE 40000` at line `4830` holds the display until a key is pressed (a standard long-pause keypress-wait idiom), then `FAST` is set and the menu redraws. The two profile reports (monthly at `1200`, yearly at `1600`) implement paginated output: a counter `CT` tracks rows printed, and at 19 rows the program hits a `STOP` statement at lines `1430` or `1930`. This is intended to pause output, but it unconditionally halts execution rather than waiting for a keypress and continuing — a functional bug. The `CLS` and header reprint at lines `1440`–`1460` and `1940`–`1960` are unreachable dead code because they follow `STOP` with no conditional path to reach them. ### Interest/Principal Plot The plot subroutine at lines `2200`–`2470` draws a character-graphics chart using `PLOT` commands. A Y-axis label is printed character by character from the string `Y$=" DOLLARS"` using `PRINT AT J,0;Y$(J)` in a loop, placing one character per screen row. Axis lines are drawn with `PLOT` loops. Data points are sampled every 6 payments (`STEP 6`) and scaled to a 40-unit vertical range proportional to the monthly payment `M`. Both the interest fraction and the principal fraction are plotted per sample, and labels “P” and “I” are positioned at the midpoints of their respective curves using computed `AT` coordinates. ### Input Validation All numeric inputs are validated with range checks, and invalid entries restart the relevant input section via `GOTO`. Notable constraints enforced include: - Principal must be positive (line `3834`) - Term must be 1–30 years (line `3864`); a special case at line `4015` handles a half-year term (`Y=.5`, `N=6`), inconsistent with the prompt restricting `Y>0` as integer - Rate must be in decimal form, between 0 and 1 exclusive (line `3894`) - Month inputs must be 1–12; year inputs must fall within the computed loan span A confirmation step at lines `3910`–`3930` allows the user to re-enter all data if any value is wrong, by checking whether the input string `K$` is empty. ### Notable Anomalies - Line `1230` contains a typo: “PLEAE ENTER” instead of “PLEASE ENTER”. - The `STOP`-based pagination in the profile routines (lines `1430`, `1930`) unconditionally terminates the program rather than pausing; the `CLS`/reprint code immediately following is dead code. - The variable `Y` is reused: it stores the loan term in years during setup, but within the yearly profile subroutine `Y1` is computed as the number of remaining years. If `Y` were overwritten this would corrupt data, but the subroutine uses `Y1` as its loop counter, so the loan-term value in `Y` is preserved. - Line `4015` tests `IF Y=.5 THEN LET N=6` to support a six-month loan term, but the input validation at line `3864` only rejects `Y<=0`, so fractional year values other than `0.5` would produce a non-integer `N` passed to `DIM`, likely causing an error. ## Source Code ``` 10 GOTO 3500 95 REM SINGLE PAYMENT ROUTINE 100 CLS 110 PRINT " SINGLE PAYMENT MODE" 120 PRINT " ''''''''''''''''''''''''''''''''''''''" 130 PRINT AT 5,1;"ENTER THE DATE OF THE PAYMENT IN WHICH YOU ARE INTERESTED" 140 PRINT AT 11,3;"FIRST THE MONTH (2 DIGITS)" 150 INPUT MN 160 IF MN<1 OR MN>12 THEN GOTO 100 170 PRINT AT 15,3;"AND THE YEAR (4 DIGITS)" 180 INPUT YR 190 LET X=(YR-FY)*12+MN-FM+1 200 IF X<1 OR X>N THEN GOTO 100 210 FAST 220 LET T1=(INT (T(X,1)*100+.5))/100 230 LET T2=(INT (T(X,2)*100+.5))/100 240 LET T3=(INT (T(X,3)*100+.5))/100 250 IF T3<.1 THEN LET T3=0 260 LET MP=M1-T1 270 LET MP=(INT (MP*100+.5))/100 280 LET TP=OP-T3+T2 290 LET TP=(INT (TP*100+.5))/100 300 LET Z1=5 310 IF T1<1000 THEN LET Z1=6 320 IF T1<100 THEN LET Z1=7 330 IF T1<10 THEN LET Z1=8 340 LET Z2=5 350 IF MP<1000 THEN LET Z2=6 360 IF MP<100 THEN LET Z2=7 370 IF MP<10 THEN LET Z2=8 380 LET Z3=5 390 IF M1<1000 THEN LET Z3=6 400 IF M1<100 THEN LET Z3=7 410 CLS 420 PRINT "MORTGAGE DATA FOR ";MN;"/";YR 430 PRINT AT 4,4;"PAYMENT:" 440 PRINT AT 6,Z1;"$";T1;TAB 13;" INTEREST" 450 PRINT AT 7,Z2;"$";MP;TAB 13;" PRINCIPAL" 460 PRINT AT 8,5;"................" 470 PRINT AT 9,Z3;"$";M1;TAB 13;" TOTAL" 475 PRINT AT 12,0;"AFTER THIS PAYMENT:" 480 PRINT AT 14,2;"PRINCIPAL BALANCE = $";T3 490 PRINT AT 16,2;"INTEREST PAID = $";T2 494 PRINT AT 18,2;"TOTAL PAID = $";TP 496 RETURN 499 REM SINGLE YEAR ROUTINE 500 CLS 510 LET YI=0 520 PRINT " SINGLE YEAR MODE" 530 PRINT " ''''''''''''''''''''''''''''''''" 540 PRINT AT 8,3;"ENTER THE YEAR IN WHICH YOU ARE INTERESTED (4 DIGITS)" 560 INPUT YR 570 LET LY=FY+Y 580 IF YRLY THEN GOTO 500 590 FAST 600 IF YR<>FY THEN GOTO 640 610 LET Z=1 620 LET W=13-FM 630 GOTO 680 640 LET Z=(YR-FY)*12+2-FM 650 LET W=Z+11 660 IF WN AND YR<>FY THEN GOTO 780 730 IF YR=FY THEN GOTO 760 740 LET YP=M1*LM-YI 750 GOTO 790 760 LET YP=M1*(13-FM)-YI 770 GOTO 790 780 LET YP=M1*12-YI 790 LET TPY=YI+YP 800 LET YP=(INT (YP*100+.5))/100 810 LET TP=OP-T(W,3)+T(W,2) 820 LET TP=(INT (TP*100+.5))/100 830 LET T2=(INT (T(W,2)*100+.5))/100 840 LET T3=(INT (T(W,3)*100+.5))/100 850 IF T3<.1 THEN LET T3=0 860 LET Z1=5 870 IF YI<10000 THEN LET Z1=6 880 IF YI<1000 THEN LET Z1=7 890 IF YI<100 THEN LET Z1=8 900 LET Z2=5 910 IF YP<10000 THEN LET Z2=6 920 IF YP<1000 THEN LET Z2=7 930 IF YP<100 THEN LET Z2=8 935 IF YP<10 THEN LET Z2=9 940 LET Z3=5 950 IF TPY<10000 THEN LET Z3=6 960 IF TPY<1000 THEN LET Z3=7 970 IF TPY<100 THEN LET Z3=8 980 CLS 990 PRINT "MORTGAGE DATA FOR YEAR ";YR 1000 PRINT AT 4,4;"TOTALS FOR THE YEAR:" 1010 PRINT AT 6,Z1;"$";YI;TAB 17;"INTEREST" 1020 PRINT AT 7,Z2;"$";YP;TAB 17;"PRINCIPAL" 1030 PRINT AT 8,5;"...................." 1040 PRINT AT 9,Z3;"$";TPY;TAB 17;"TOTAL" 1050 PRINT AT 12,0;"AT YEAR END:" 1060 PRINT AT 14,2;"PRINCIPAL BALANCE = $";T3 1070 PRINT AT 16,2;"INTEREST PAID = $";T2 1080 PRINT AT 18,2;"TOTAL PAID = $";TP 1090 RETURN 1195 REM MONTHLY PROFILE ROUTINE 1200 CLS 1210 PRINT " MONTHLY PROFILE MODE" 1220 PRINT " ''''''''''''''''''''''''''''''''''''''''" 1230 PRINT AT 6,2;"PLEAE ENTER THE DATE AT WHICH THE REPORT SHOULD START" 1240 PRINT AT 12,4;"FIRST THE MONTH (2 DIGITS)" 1250 INPUT MN 1260 IF MN<1 OR MN>12 THEN GOTO 1200 1270 PRINT AT 17,4;"NOW THE YEAR (4 DIGITS)" 1280 INPUT YR 1290 LET Z=(YR-FY)*12+MN-FM+1 1300 IF Z<1 OR Z>N THEN GOTO 1200 1310 FAST 1320 CLS 1330 PRINT "DATE INT TOTAL INT PRIN BAL" 1340 LET CT=0 1350 FOR X=Z TO N 1360 LET T1=(INT (T(X,1)*100+.5))/100 1370 LET T2=(INT (T(X,2)*100+.5))/100 1380 LET T3=(INT (T(X,3)*100+.5))/100 1390 LET CT=CT+1 1400 IF ABS T3<.6 THEN LET T3=0 1410 PRINT " ";MN;TAB 5;T1;TAB 13;T2;TAB 24;T3 1415 IF T3=0 THEN GOTO 1530 1420 IF CT<19 THEN GOTO 1470 1430 STOP 1440 CLS 1450 PRINT "DATE INT TOTAL INT PRIN BAL" 1460 LET CT=0 1470 LET MN=MN+1 1480 IF MN<=12 THEN GOTO 1520 1490 LET MN=1 1500 LET YR=YR+1 1510 PRINT YR 1520 NEXT X 1530 RETURN 1595 REM YEARLY PROFILE ROUTINE 1600 CLS 1610 LET CT=0 1620 LET YI=0 1630 PRINT " PROFILE BY YEAR MODE" 1640 PRINT " ''''''''''''''''''''''''''''''''''''''''" 1650 PRINT AT 8,2;"PLEASE ENTER THE YEAR AT WHICH THE REPORT SHOULD START" 1660 INPUT YR 1670 LET LY=FY+Y 1680 IF YRLY THEN GOTO 1600 1690 FAST 1700 IF YR<>FY THEN GOTO 1740 1710 LET Z=1 1720 LET W=13-FM 1730 GOTO 1760 1740 LET Z=(YR-FY)*12+2-FM 1750 LET W=Z+11 1760 LET Y1=FY+Y+1-YR 1770 IF W>N THEN LET W=N 1780 CLS 1790 PRINT "YEAR INT TOTAL INT PRIN BAL" 1800 FOR I=1 TO Y1 1810 LET YI=0 1820 FOR X=Z TO W 1830 LET YI=YI+T(X,1) 1840 NEXT X 1850 LET Y2=YR+I-1 1860 LET YI=(INT (YI*100+.5))/100 1870 LET T2=(INT (T(W,2)*100+.5))/100 1880 LET T3=(INT (T(W,3)*100+.5))/100 1890 LET CT=CT+1 1900 IF ABS T3<.6 THEN LET T3=0 1910 PRINT Y2;TAB 5;YI;TAB 14;T2;TAB 24;T3 1915 IF T3=0 THEN GOTO 2020 1920 IF CT<19 THEN GOTO 1970 1930 STOP 1940 CLS 1950 LET CT=0 1960 PRINT "YEAR INT TOTAL INT PRIN BAL" 1970 LET Z=X 1980 LET W=Z+11 1990 IF W30 THEN GOTO 3810 3870 PRINT AT 11,11;Y;" YEARS" 3880 PRINT AT 14,2;"AND THE RATE IN DECIMAL FORM" 3890 INPUT A 3894 IF A<=0 OR A>1 THEN GOTO 3810 3900 PRINT AT 16,11;A*100;" PERCENT" 3910 PRINT AT 19,0;" IF ALL DATA IS CORRECT PRESS ENTER. OTHERWISE PRESS ANY CHARACTER AND ENTER." 3920 INPUT K$ 3930 IF K$<>"" THEN GOTO 3800 3940 LET OP=P 3950 CLS 4000 LET I=A/12 4010 LET N=Y*12 4015 IF Y=.5 THEN LET N=6 4020 DIM T(N,3) 4030 LET M=P*I/(1-((1+I)**(-N))) 4040 LET M1=(INT (M*100+.5))/100 4050 LET TPD=(INT (M*N*100+.5))/100 4060 CLS 4064 PRINT " BASIC RESULTS" 4065 PRINT " ''''''''''''''''''''''''''" 4070 PRINT "$";P;" FOR ";Y;" YEARS AT ";A 4080 PRINT "$";M1;" MONTHLY" 4090 PRINT "$";TPD;" TOTAL" 4100 LET S=0 4110 LET ST=0 4120 PRINT AT 11,4;"SELECT OPTION CODE" 4130 PRINT AT 13,6;"CODE DESCRIPTION" 4140 PRINT AT 15,8;"1 NEW DATA" 4150 PRINT AT 16,8;"2 CONTINUE" 4155 PRINT AT 17,8;"3 END" 4160 INPUT C1 4164 LET C1=INT C1 4165 IF C1<1 OR C1>3 THEN GOTO 4060 4170 IF C1=1 THEN GOTO 3800 4180 IF C1=3 THEN GOTO 4900 4200 CLS 4205 PRINT " DATE DATA" 4206 PRINT " ''''''''''''''''''" 4210 PRINT AT 3,2;"PLEASE ENTER THE DATE OF THE FIRST PAYMENT" 4220 PRINT AT 8,2;"FIRST THE MONTH (2 DIGITS)" 4230 INPUT FM 4235 IF FM<=0 OR FM>12 THEN GOTO 4200 4240 PRINT AT 12,2;"NOW THE YEAR (4 DIGITS)" 4250 INPUT FY 4255 IF FY<=0 THEN GOTO 4200 4260 PRINT AT 18,4;"FIRST PAYMENT ";FM;"/";FY 4270 LET LM=FM-1 4280 IF LM<>0 THEN GOTO 4300 4290 LET LM=12 4300 PAUSE 200 4400 FAST 4410 FOR X=1 TO N 4420 LET S=I*P 4430 LET T(X,1)=S 4440 LET ST=ST+S 4450 LET T(X,2)=ST 4460 LET P=P-M+S 4470 LET T(X,3)=P 4480 NEXT X 4490 CLS 4500 SLOW 4600 PRINT " BASIC RESULTS" 4605 PRINT " ''''''''''''''''''''''''''" 4608 PRINT "$";OP;" FOR ";Y;" YEARS AT ";A 4610 PRINT "$";M1;" MONTHLY" 4620 PRINT "$";TPD;" TOTAL" 4625 PRINT AT 8,7;"REPORT MENU" 4626 PRINT AT 9,7;"''''''''''''''''''''''" 4630 PRINT AT 10,4;"SELECT REPORT CODE:" 4640 PRINT AT 12,4;"CODE DESCRIPTION" 4660 PRINT 4670 PRINT TAB 5;"1 SINGLE PAYMENT DATA" 4680 PRINT TAB 5;"2 SINGLE YEAR DATA" 4690 PRINT TAB 5;"3 PROFILE BY MONTH" 4700 PRINT TAB 5;"4 PROFILE BY YEAR" 4710 PRINT TAB 5;"5 INT/PRIN PLOT" 4720 PRINT TAB 5;"6 NEW DATA" 4730 PRINT TAB 5;"7 END" 4735 SLOW 4740 INPUT C2 4750 IF C2<1 OR C2>7 THEN GOTO 4840 4760 IF C2=1 THEN GOSUB 100 4770 IF C2=2 THEN GOSUB 500 4780 IF C2=3 THEN GOSUB 1200 4790 IF C2=4 THEN GOSUB 1600 4800 IF C2=5 THEN GOSUB 2200 4810 IF C2=6 THEN GOTO 3800 4820 IF C2=7 THEN GOTO 4900 4830 PAUSE 40000 4835 FAST 4840 CLS 4850 GOTO 4600 4900 CLEAR 4910 CLS ```