Conversion

Developer(s): Thomas Simon
Date: 198x
Type: Program
Platform(s): TS 2068

This program is a unit-conversion utility offering eleven conversion types, including temperature (Celsius to Fahrenheit), length (centimeters to inches), and several pharmacist/apothecary-related measurements such as drams, grains, and milligrams. The main menu is displayed at lines 30–80, and user selection dispatches via a chain of IF/GO SUB statements to individual subroutines starting at line 210. Each conversion subroutine uses FLASH 1/FLASH 0 to highlight the result value on screen. Lines 770–820 reveal a hidden developer utility, accessible only by running those lines directly, that provides renumber, rem-kill, delete, and variable-list functions by calling machine code routines via RANDOMIZE USR with addresses computed using a bitmask technique.


Program Analysis

Program Structure

The program divides cleanly into four regions:

  1. Menu display (lines 20–80): Sets up the display and prints all eleven conversion choices.
  2. Dispatch (lines 90–200): Reads the user’s choice into A and routes to the appropriate subroutine via a chain of IF … THEN GO SUB statements, falling through to GO TO 30 if no valid option is entered.
  3. Conversion subroutines (lines 210–750): Each subroutine follows the same pattern: CLS, print a heading, INPUT a value, compute the result, print it with FLASH highlighting, then call the shared “press any key” subroutine at line 250 before RETURNing.
  4. Hidden developer utilities (lines 760–820): A SAVE/verify block and a developer toolkit that is never reached during normal execution.

Shared “Press Any Key” Subroutine

Line 250 acts as a shared tail-end subroutine called by every conversion routine via GO SUB 250. It prints a prompt at the bottom of the screen using PRINT AT 21,0, waits for a keypress with PAUSE 0, clears the screen, and returns. The subsequent RETURN in the calling subroutine (e.g., line 300’s GO SUB 250: RETURN) correctly unwinds both stack frames.

FLASH Highlighting of Results

Each conversion result is bracketed with FLASH 1 and FLASH 0 inline within a single PRINT statement, so only the numeric answer blinks on screen while the surrounding label text remains static. This is a straightforward but effective way to draw the user’s eye to the converted value.

Hidden Developer Toolkit (Lines 770–820)

These lines are unreachable during normal program flow — line 760 is a SAVE command and line 200 loops back to 30 — so the toolkit can only be invoked by manually running from line 770 with RUN 770 or GO TO 770. It offers four built-in utility functions:

  • Renumber — machine code at address 64048
  • Remkill — machine code at address 64841
  • Delete (range) — machine code at address 65017
  • Variable list — machine code at address 65184

The target address is selected using a bitmask technique on line 770: LET zzz=(64048 AND fff=1)+(64841 AND fff=2)+(65017 AND fff=3)+(65184 AND fff=4). In Sinclair BASIC, a boolean expression evaluates to 1 (true) or 0 (false), so multiplying the address by the boolean effectively selects exactly one address while zeroing out the rest. IF NOT zzz THEN GO TO 770 rejects invalid input.

Lines 810–820 pass parameters to the machine code via POKEs into system variables at addresses 23299–23302, then invoke the routine with RANDOMIZE USR zzz. The variable-list function uses PRINT USR zzz: STOP instead, suggesting it returns a value rather than performing an in-place operation.

There is a minor bug on line 810: the first POKE calculates the low byte of fff as fff - 265 * PEEK 23300 instead of the correct fff - 256 * PEEK 23300. This off-by-nine error would corrupt the parameter for the renumber start line when fff >= 256.

Bugs and Anomalies

LineIssue
40, 260, 270, 290Consistent misspelling: “CENTEMETERS” should be “CENTIMETERS”.
490The drams-to-milliliters subroutine prints the result labeled “MILLIGRAMS” instead of “MILLILITERS”.
810Low-byte calculation uses multiplier 265 instead of 256, corrupting the parameter when fff ≥ 256.
30–80The menu heading and option 8 spell it “FARENHEIT”; lines 210 and 240 also use “FARENHEIT” — correct spelling is “FAHRENHEIT”.

Key BASIC Idioms

  • Chained IF A=n THEN GO SUB … without ELSE — standard dispatch pattern in Sinclair BASIC, which has no SELECT CASE.
  • Boolean arithmetic for address selection: (address AND condition) used as a multiply-by-boolean.
  • PAUSE 0 as an indefinite wait for any keypress (line 250).
  • Inline FLASH attribute changes within a single PRINT to selectively highlight output.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

Conversion

Source Code

   10 REM               FECIT T. SIMON
   20 BORDER 0: PAPER 0: INK 7: CLS 
   30 PRINT "  THIS IS A CONVERSION PROGRAM"'"  CHOOSE ONE OF THE FOLLOWING: "''''
   40 PRINT TAB 4;"1. CELSIUS TO FARENHEIT"';TAB 4;"2. CENTIMETERS TO INCHES";TAB 4;"3. GRAMS TO GRAINS"
   50 PRINT TAB 4;"4. MILLILITERS TO OUNCES";TAB 4;"5. GRAINS TO MILLIGRAMS"
   60 PRINT TAB 4;"6. DRAMS TO MILLILITERS";TAB 4;"7. DRAMS (AVDP) TO GRAINS"
   70 PRINT TAB 4;"8. IMP.OZS. TO US.FL.OZ.";TAB 4;"9. IMP. GALLONS TO LITERS"
   80 PRINT TAB 3;"10. POUNDS TO GRAMS";TAB 3;"11. OUNCES TO MILLILITERS"
   90 INPUT A: IF A=1 THEN GO SUB 210
  100 IF A=2 THEN GO SUB 260
  110 IF A=3 THEN GO SUB 310
  120 IF A=4 THEN GO SUB 360
  130 IF A=5 THEN GO SUB 410
  140 IF A=6 THEN GO SUB 460
  150 IF A=7 THEN GO SUB 510
  160 IF A=8 THEN GO SUB 560
  170 IF A=9 THEN GO SUB 610
  180 IF A=10 THEN GO SUB 660
  190 IF A=11 THEN GO SUB 710
  200 GO TO 30
  210 CLS : PRINT "CONVERTING CELSIUS TO FAHRENHEIT"'''
  220 INPUT "ENTER CELSIUS TEMPERATURE ";C
  230 LET F=1.8*C+32
  240 PRINT ''C;" CELSIUS= "; FLASH 1;F; FLASH 0;" FARENHEIT"
  250 PRINT AT 21,0;"PRESS ANY KEY TO RESTART": PAUSE 0: CLS : RETURN 
  260 CLS : PRINT "CONVERTING CENTEMETERS TO INCHES"
  270 INPUT "ENTER CENTEMETERS ";C
  280 LET I=.3937*C
  290 PRINT ''C;" CENTEMETERS = "; FLASH 1;I; FLASH 0;" INCHES"
  300 GO SUB 250: RETURN 
  310 CLS : PRINT "CONVERTING GRAMS TO GRAINS"
  320 INPUT ''"ENTER GRAMS ";G
  330 LET N=15.432*G
  340 PRINT ''G;" GRAMS = "; FLASH 1;N; FLASH 0;" GRAINS"
  350 GO SUB 250: RETURN 
  360 CLS : PRINT "CONVERTING MILLILITERS TO OUNCES"
  370 INPUT ''"ENTER MILLILITERS ";M
  380 LET O=M/29.573
  390 PRINT ''M;" MILLITERS = "; FLASH 1;O; FLASH 0;" OUNCES"
  400 GO SUB 250: RETURN 
  410 CLS : PRINT "CONVERTING GRAINS TO MILLIGRAMS "'''
  420 INPUT '"ENTER GRAINS ";N
  430 LET G=N*64.799
  440 PRINT N;" GRAINS = "; FLASH 1;G; FLASH 0;" MILLIGRAMS"
  450 GO SUB 250: RETURN 
  460 CLS : PRINT "CONVERTING DRAMS TO MILLILITERS"''
  470 INPUT "ENTER DRAMS ";D
  480 LET M=3.552*D
  490 PRINT D;" DRAMS = "; FLASH 1;M; FLASH 0;" MILLIGRAMS"
  500 GO SUB 250: RETURN 
  510 CLS : PRINT "CONVERTING DRAMS(AVDP) TO GRAINS"
  520 INPUT "ENTER DRAMS ";D
  530 LET G=27.334*D
  540 PRINT ''D;" DRAMS = "; FLASH 1;G; FLASH 0;" GRAINS"
  550 GO SUB 250: RETURN 
  560 CLS : PRINT "CONVERTING IMP.OZS. TO US.FL.OZS"
  570 INPUT "ENTER IMPERIAL OUNCES ";I
  580 LET U=1.041*I
  590 PRINT ''I;" IMP. OUNCES = "; FLASH 1;U; FLASH 0;" US. OUNCES"
  600 GO SUB 250: RETURN 
  610 CLS : PRINT "CONVERTING IMP.GALLONS TO LITERS"''
  620 INPUT "ENTER IMPERIAL GALLONS ";I
  630 LET L=4.546*I
  640 PRINT I;" IMP.GALS. = "; FLASH 1;L; FLASH 0;" LITERS"
  650 GO SUB 250: RETURN 
  660 CLS : PRINT "CONVERTING POUNDS TO GRAMS"''
  670 INPUT "ENTER POUNDS ";P
  680 LET G=453.59*P
  690 PRINT P;" POUNDS = "; FLASH 1;G; FLASH 0;" GRAMS"
  700 GO SUB 250: RETURN 
  710 CLS : PRINT "CONVERTING OUNCES TO MILLILITERS"
  720 INPUT "ENTER OUNCES ";O
  730 LET M=29.573*O
  740 PRINT O;" OUNCES = "; FLASH 1;M; FLASH 0;" MILLILITERS"
  750 GO SUB 250: RETURN 
  760 SAVE "CONVERSION" LINE 5: PRINT "REWIND TAPE AND VERIFY": VERIFY "": RUN 
  770 CLS : PRINT "1) Renumber"'"2) Remkill"'"3) Delete"'"4) Variable list": INPUT fff: LET zzz=(64048 AND fff=1)+(64841 AND fff=2)+(65017 AND fff=3)+(65184 AND fff=4): IF NOT zzz THEN GO TO 770
  780 LET ttt=100: LET fff=ttt: IF zzz=64048 THEN INPUT "Start ";fff,"Step ";ttt
  790 IF zzz=65017 THEN INPUT "From ";fff,"To ";ttt
  800 IF fff>9999 OR fff<1 OR ttt>9999 OR ttt<1 OR (fff>ttt AND zzz=65017) THEN GO TO 770
  810 POKE 23300,INT (fff/256): POKE 23299,fff-265*PEEK 23300: POKE 23302,INT (ttt/256): POKE 23301,ttt-256*PEEK 23302: IF zzz=65184 THEN PRINT USR zzz: STOP 
  820 RANDOMIZE USR zzz

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

Scroll to Top