GET_GMC

Developer(s): Shawn Byrne
Date: 1983
Type: Program
Platform(s): TS 1000

GET is a relocatable 289-byte machine code subroutine, embedded in line 1’s REM statement, that provides controlled keyboard input for ZX81/TS1000 BASIC programs. It is invoked via USR GET, returns the length of the typed response, and stores the actual characters in a pre-defined string variable G$. The routine reads an allowable character set from the REM line immediately following the RAND USR GET call, supporting ranges (e.g., 0-9, A-F) and comma-separated lists. It features a flashing cursor, DELETE key support, an elapsed-time counter accessible via PEEK 16516–16518, and a configurable “key already pressed on entry” behaviour patchable at GET+129.


Program Analysis

Program Structure

The program divides cleanly into three layers: the machine code payload in line 1’s REM, a short BASIC runtime support block (lines 2–190), and a lengthy self-documenting demonstration that runs from line 1000 onward. Line 90 immediately branches to the demo, so lines 100–190 act as a reusable subroutine called repeatedly with GOSUB 100.

  1. Line 1 – REM holding 289 bytes of Z80 machine code (the GET routine itself).
  2. Line 2 – REM title/authorship label.
  3. Lines 3–4 – Variable initialisation: GET=16520 (entry point), A$ (prompt string).
  4. Line 90 – Unconditional branch to demo start at 1000.
  5. Lines 100–190 – “Press CONT or STOP” input subroutine, itself using USR GET.
  6. Lines 1000–2120 – Sequential demo/documentation pages, each terminated by GOSUB 100.
  7. Lines 9997–9999 – End-of-program housekeeping: STOP, SAVE, RUN loop.

Machine Code Payload (Line 1 REM)

The 289-byte Z80 routine stored from address 16520 (decimal) is fully relocatable; its entry point is defined by LET GET=16520, which must be adjusted if the routine is placed elsewhere. Key behaviours reconstructable from the hex dump include:

  • Reads the ZX81 system variable at address 0x4010 (E_LINE area) to locate the REM line immediately following the calling BASIC line, which specifies allowable characters as ranges (A-F) or comma-separated lists (2,7,C,R).
  • Maintains a 24-bit elapsed-tick counter written to addresses 16516–16518 (PEEK 16516 + 256*PEEK 16517 + 65536*PEEK 16518), allowing response-time measurement.
  • Uses a flashing cursor character whose ASCII code is held at GET+113 (default 0 = space), patchable at runtime with POKE GET+113,CODE "S" etc.
  • Entry-time key-press suppression logic is controlled by a single byte at GET+129: value 40 (normal, debounced) or 24 (accept key already held on entry).
  • The routine returns the length of the typed response in the ZX81 calculator stack/HL register pair, which BASIC reads as the result of USR GET; the response itself is written directly into the pre-allocated string G$.
  • DELETE key handling and automatic exit when G$ is filled are implemented entirely in machine code.

BASIC Invocation Pattern

The canonical calling sequence demonstrated in the program is:

  1. Allocate response buffer: LET G$=" " (length sets maximum input length).
  2. Position cursor: PRINT AT row,col;
  3. Call routine and capture length: LET N$=G$( TO USR GET)
  4. Immediately follow that line with a REM specifying valid characters: e.g., REM Q or REM 0-9.
  5. Test N$ for empty (ENTER pressed with no input) or specific values.

The slice G$( TO USR GET) is an elegant single-expression idiom: USR GET both executes the machine code and returns a number used immediately as the string slice upper bound, discarding trailing padding spaces.

The CONT/STOP Subroutine (Lines 100–190)

Lines 100–190 use GET recursively (the subroutine calls USR GET while itself being called from within the demo). It sets G$=" " (four spaces), calls USR GET constrained to REM C,N,O,P,S,T at line 140 (the six distinct characters in CONT and STOP), then pattern-matches the returned N$ against "STOP" and "CONT". An empty response (ENTER alone) loops back. A valid "CONT" clears the screen and returns; "STOP" halts execution.

Response-Time Counter Demo

Lines 1580–1670 demonstrate the timer feature. The user is asked to press Q; after the call returns, the counter bytes are read and converted to seconds using the empirical constant 446.1667 counts per second (noted as approximately 26,770 counts per minute). The author explicitly acknowledges this constant varies between machines and must be calibrated per unit.

Relocation and Memory Placement Notes

The demo text describes three valid placement strategies for the routine:

  • Inside a line 1 REM (as demonstrated here), with POKE 16419,2 to shift the BASIC display start past line 1 so LIST 2 shows the program without the binary garbage.
  • Above RAMTOP (in the space reserved by lowering RAMTOP before loading).
  • Between the BASIC program area and the display file.

The value GET=16520 corresponds to the byte immediately after the five-byte line header of line 1 (line number 2 bytes + length 2 bytes + REM token 1 byte = 5 bytes; line 1 starts at 16514 on a standard 16K machine, so the payload begins at 16519 or 16520 depending on the exact header count), consistent with standard ZX81 memory layout where BASIC starts at address 16509.

Notable Techniques

  • Self-documenting demo loop: The entire program is both documentation and live demonstration, using GET to page through its own manual.
  • Parameterised character filter via REM: Reading the following REM line at runtime to determine valid input is an unusually flexible design for a machine code routine of this era.
  • Single-expression capture: LET N$=G$( TO USR GET) avoids a separate variable assignment for the length.
  • Patch-in-place customisation: Cursor character and entry-debounce behaviour are exposed as documented POKE offsets rather than requiring re-assembly.

Bugs and Anomalies

  • Line 1130 concatenates without a newline after “G$.” and continues on line 1140 mid-sentence — a cosmetic flow artifact of the 32-column display wrapping, not a logic error.
  • Line 1790 contains the spelling “RECIEVED” (should be “RECEIVED”) — a typo in the documentation string only.
  • The SAVE line (9998) saves the program as "GET"; the program counter in line 9999 uses RUN to restart, meaning a loaded copy will auto-demo from the top.

Content

Appears On

Related Products

Related Articles

And now, here are a few more words about the last contest. First, we would like to thank all of...

Related Content

Image Gallery

Source Code

   1 REM 257A925002A10403E80BEC83E4CBE2824CB6E2818CB7E28ECB762851112018823CB7E28FB11601918DB235E2356231918D3235E2356E519227B40E12322824021002284403E0328640218740360212140CBC62A84401110192284403073A86403C3286402AE403A8440CB772043601823680CDBB2444D5D212140CB462871C20CDCB8618C91C28C6CDBD77EFE7720232187403E0BE28B1352AE403602B3E76BE2012B22E402A82402B3602282401896FE762072AE4036018575F2A2940232346523232310218E4567BBA281D2310218DA3E16BE2863E1ABEC018E62310218CA7EBB38E77ABB30E3218740342AE407323F53E76BE2012322E402A8240F173232282402BED4B7B40AFED42209C602187404EC9
   2 REM %G%E%T BY SHAWN BYRNE 1983
   3 LET GET=16520
   4 LET A$="ENTER %C%O%N%T TO CONTINUE, %S%T%O%P TO STOP "
  90 GOTO 1000
 100 PRINT AT 20,0;A$
 110 LET G$="    "
 120 PRINT AT 21,12;
 130 LET N$=G$( TO USR GET)
 140 REM C,N,O,P,S,T
 150 IF N$="" THEN GOTO 110
 160 IF N$="STOP" THEN STOP 
 170 IF N$<>"CONT" THEN GOTO 110
 180 CLS 
 190 RETURN 
 1000 SLOW 
 1010 PRINT "*** :%G%E%T: *** BY SHAWN BYRNE  1983"
 1020 PRINT 
 1030 PRINT " :%G%E%T: IS A MACHINE LANGUAGE SUB- ROUTINE, 289 BYTES LONG, WHICH  CAN BE USED TO %G%E%T A USER INPUT.",,
 1040 PRINT "LINE 1 OF THE BASIC PROGRAM MUSTBE A REM STATEMENT CONTAINING 6 BYTES USED AS VARIABLES.THE SUB-ROUTINE ITSELF IS RELOCATABLE   AND CAN RESIDE ABOVE RAMTOP,IN AREM STATEMENT OR BETWEEN A BASICPROGRAM AND THE DISPLAY FILE."
 1050 PRINT 
 1060 PRINT "IF %G%E%T IS USED IN A 1 REM STATE-MENT, POKE 16419,2 SO THE BASIC (STARTING AT LINE 2) CAN BE DIS-PLAYED. DO NOT LIST;USE LIST 2."
 1070 GOSUB 100
 1080 PRINT "BEFORE  :%G%E%T: IS CALLED FROM WITH-IN A BASIC PROGRAM,IT£S STARTINGLOCATION MUST BE DEFINED:"
 1090 PRINT 
 1100 PRINT "EXAMPLE: 10 LET GET=16520"
 1110 GOSUB 100
 1120 PRINT "THE FUNCTION ""USR GET"" WILL RE- TURN THE LENGTH OF THE RESPONSE.THE STRING G$ MUST BE DEFINED   (A STRING OF SPACES) BEFORE %G%E%T IS CALLED AND THE LENGTH OF THE RESPONSE IS LIMITED BY THE"
 1130 PRINT "LENGTH OF G$. THE RESPONSE IS   RETURNED IN G$."
 1140 PRINT 
 1150 PRINT "THE RESPONSE IS INPUT ON THE    SCREEN WHEREVER THE PRINT"
 1160 PRINT "POSITION IS LOCATED. THE DELETE KEY WILL WORK. EXIT FROM %G%E%T IS PERFORMED WHEN ENTER IS PRESSED OR THE LENGTH OF THE INPUT = G$."
 1170 GOSUB 100
 1180 PRINT "IF THE RESPONSE IS NOT NEEDED ONTHE SCREEN, THE PRINT POSITION  CAN BE MOVED OFFSCREEN BY:"
 1190 PRINT 
 1200 PRINT TAB 8;"POKE 16399,0"
 1210 PRINT 
 1220 PRINT "OTHERWISE, THE RESPONSE CAN BE  POSITIONED ON THE SCREEN BY:"
 1230 PRINT 
 1240 PRINT TAB 5;"PRINT AT (LINE),(COL.);"
 1250 PRINT 
 1260 PRINT "BEFORE THE ROUTINE IS CALLED."
 1270 GOSUB 100
 1280 PRINT "IMMEDIATELY FOLLOWING THE LINE  NUMBER IN WHICH %G%E%T IS CALLED,"
 1290 PRINT "THERE MUST BE A REM LINE WHICH  SPECIFIES THE CHARACTER(S) WHICHARE TO BE USED IN THE RESPONSE. CHARACTERS MUST BE SEPARATED BY A COMMA OR A HYPHEN."
 1300 PRINT 
 1310 PRINT "EXAMPLE 1:  REM 0-9"
 1320 PRINT 
 1330 PRINT "WILL GIVE A RESPONSE TO ALL THE NUMBERS FROM 0 THROUGH 9."
 1340 PRINT 
 1350 PRINT "EXAMPLE 2:  REM 2,7,C,R"
 1360 PRINT 
 1370 PRINT "WILL GIVE A RESPONSE ONLY TO    THOSE CHARACTERS."
 1380 GOSUB 100
 1390 PRINT "EXAMPLE 3:  REM A-F"
 1400 PRINT 
 1410 PRINT "WILL GIVE A RESPONSE ONLY TO THELETTERS A THROUGH F."
 1420 PRINT 
 1430 PRINT "EXAMPLE 4:  REM 0-Z"
 1440 PRINT 
 1450 PRINT "WILL GIVE A RESPONSE TO ALL THE NUMBERS (0 THROUGH 9) AND TO ALLTHE LETTERS (A THROUGH Z)." 
 1460 GOSUB 100
 1470 PRINT "%G%E%T HAS A COUNTER WHICH CAN BE  USED AS A TIMER. AFTER %G%E%T HAS  EXECUTED, THIS COUNTER VALUE CANBE FOUND BY:"
 1480 PRINT 
 1490 PRINT "PEEK 16516+256*PEEK 16517+65536 *PEEK 16518"
 1500 PRINT 
 1510 PRINT "A %G%E%T EXECUTION TIME OF 1 MINUTEWILL RESULT IN A COUNT OF ABOUT 26,770."
 1520 PRINT 
 1530 PRINT "THE EXACT COUNT WILL VARY WITH  EACH COMPUTER AND WILL HAVE TO  BE DETERMINED BY EXPERIMENTING."
 1540 GOSUB 100
 1550 PRINT "EXAMPLE OF %G%E%T COUNTER:"
 1560 PRINT 
 1570 PRINT "PLEASE PRESS THE ""Q"" KEY."
 1580 LET G$=" "
 1590 PRINT AT 5,15;
 1600 RAND USR GET
 1610 REM Q
 1620 PRINT 
 1630 LET N=INT ((PEEK 16516+256*PEEK 16517+65536*PEEK 16518)/446.1667)
 1640 PRINT 
 1650 PRINT TAB 6;"YOUR RESPONSE TIME WAS "
 1660 PRINT 
 1670 PRINT TAB 10;N;" SECONDS."
 1680 GOSUB 100
 1690 POKE GET+113,CODE "S"
 1700 PRINT "THE FLASHING CURSER USED ON THE SCREEN CAN BE ANY CHARACTER.    FOR EXAMPLE, FOR A FLASHING ""S"":"
 1710 PRINT 
 1720 PRINT "POKE GET+113,CODE ""S"""
 1730 PRINT 
 1740 PRINT "TO RETURN TO THE FLASHING SPACE:"
 1750 PRINT 
 1760 PRINT "POKE GET+113,0"
 1770 GOSUB 100
 1780 POKE GET+113,0
 1790 PRINT "%G%E%T WILL NOT ACCEPT A CHARACTER UNTIL AFTER IT HAS RECIEVED THE SIGNAL THAT NO KEY IS BEING     PRESSED,SO UPON ENTERING %G%E%T,IF A KEY IS BEING PRESSED, IT WILL NOT BE ACCEPTED UNTIL THE FINGERIS LIFTED AND A KEY PRESSED     AGAIN."
 1800 PRINT "THIS PREVENTS A CHARACTER FROM  BEING REPEATED RAPIDLY."
 1810 PRINT "TO ALLOW A CHARACTER TO BE AC-  CEPTED ON ENTERING %G%E%T WHEN IT  IS ALREADY BEING PRESSED:"
 1820 PRINT 
 1830 PRINT TAB 4;"POKE GET+129,24"
 1840 PRINT 
 1850 PRINT "TO RETURN TO NORMAL:"
 1860 PRINT 
 1870 PRINT TAB 4;"POKE GET+129,40"
 1880 GOSUB 100
 1890 PRINT "AN EXAMPLE OF A BASIC LISTING TOUSE %G%E%T IS:"
 1900 PRINT 
 1910 PRINT "10 LET GET=16520"
 1920 PRINT "100 LET G$="" """
 1930 PRINT "110 PRINT AT 10,15;"
 1940 PRINT "120 LET N$=G$( TO USR GET)"
 1950 PRINT "130 REM N,Y"
 1960 PRINT "140 IF N$="""" THEN GOTO 100"
 1970 PRINT "150 IF N$=""N"" THEN GOTO 1000"
 1980 PRINT "160 IF N$=""Y"" THEN GOSUB 60"
 1990 PRINT 
 2000 PRINT "LINE 140 PREVENTS A RESPONSE TO ENTER."
 2010 PRINT "LINES 150 AND 160 DETERMINE THE RESPONSE ACTION."
 2020 GOSUB 100
 2030 PRINT "%G%E%T CAN BE USED AS MANY TIMES INA BASIC PROGRAM AS NEEDED. EACH TIME IT IS USED THE LENGTH OF   THE RESPONSE AND THE CHARACTERS CAN BE REDEFINED IN BASIC."
 2040 PRINT 
 2050 PRINT AT 10,10;"SHAWN A. BYRNE"
 2060 PRINT TAB 10;"RT. 3  BOX 342"
 2070 PRINT TAB 10;"COOKEVILLE, TN."
 2080 PRINT TAB 20;"38501"
 2090 PRINT 
 2100 PRINT TAB 10;"615/526-7914"
 2110 GOSUB 100
 2120 RUN 
 9997 STOP 
 9998 SAVE "GE%T"
 9999 RUN 

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

Scroll to Top