Type DXCC

Date: 198x
Type: Program
Platform(s): TS 1000
Tags: Ham Radio

The first program is a DXCC (DX Century Club) countries log for amateur radio operators, storing up to 340 country records in a single large string array D$(340,32), where each 32-character row holds country number, callsign prefix, country name, and QSL card data. It provides search by number, prefix, or name; a paged review mode; and a totals screen showing worked, credited, and QSL-sent/received counts. The second program is a full-screen typewriter utility that tracks cursor position column-by-column across a 32-column display, uses SCROLL to handle page overflow, and supports backspace, newline, and direct cursor positioning by line and column number. Both programs use the SLOW/FAST idiom around PAUSE and POKE 16437,255 to debounce keyboard input reliably on the ZX81.


Program Analysis

Program 1: DXCC Countries List

This amateur radio utility, written by R. J. Lees (W3ZQN) in September 1982, maintains a database of up to 340 DXCC (DX Century Club) country entities. The entire database is stored in a single two-dimensional string array D$(340,32), where each row is exactly 32 characters wide and encodes structured fields at fixed byte offsets.

Record Layout

ColumnsFieldLength
1–3Country number3
4Separator (space)1
5–15Callsign prefix11
16Separator1
17–26Country name10
27Separator1
28–32QSL data (MMYY + S/R/C)5

Searching by prefix uses D$(C,5 TO 15)=P$ and by name uses D$(C,17 TO 26)=N$. The final character at position 32 encodes QSL status: S = sent/no return, R = sent and returned, C = DXCC credited. The TOTALS routine (lines 4000–4240) iterates all 340 records, testing individual character positions to accumulate five counters.

Program Structure

  • Lines 11–15: Array declarations (C$, P$, N$, I$, D$)
  • Lines 100–200: Main menu loop
  • Lines 1000–1050: Search sub-menu
  • Lines 1100–1260: Search by country number
  • Lines 1500–1710: Search by prefix
  • Lines 2000–2210: Search by name
  • Lines 3000–3120: Paged review mode
  • Lines 4000–4240: Totals computation and display
  • Lines 5000–5210: Data input routine
  • Lines 6000–6520: Shared display/change/another subroutines
  • Lines 7000–7020: Exit with warning message
  • Lines 8000–8120: Keypress wait and “not found” subroutines
  • Lines 9000–9010: SAVE and restart

Key BASIC Idioms and Techniques

The keypress-wait subroutine at line 8000 uses SLOW, PAUSE 20, POKE 16437,255, and a busy-wait loop on INKEY$. The POKE to address 16437 resets the ZX81’s internal frame counter, preventing a system BREAK. After returning, the calling code checks INKEY$ directly for the expected key — this is safe because SLOW mode retains the keyboard state long enough for the test.

The input routine at lines 5000–5190 stores the country number as a string in C$, then uses VAL C$ at line 5012 to obtain the numeric index C. The country number string is also written directly into the first three columns of the record via D$(C, TO 3)=C$.

The review routine (line 3030) steps by 21 with FOR B=PS TO 340 STEP 21 and prints a page of 22 records with an inner loop, using a guard at line 3050 to stop at record 341. The “B” key advances pages; any other key returns to the main menu — though the logic at lines 3090–3100 has a minor anomaly: line 3100 tests INKEY$<>"B" which is always true right after a non-B key exits line 3090, but the intent is simply to branch to 130 on any non-B input.

Notable Anomalies

  • Line 4050 is missing from the listing (skips from 4040 to 4060), suggesting a deleted line.
  • Lines 4100 and 4120–4130 are also absent, indicating further deletions in the totals section.
  • Line 1120 tests D$(C,1)=" " to detect an empty record, then calls subroutine 8100; however, execution falls through to line 1130 regardless, because there is no explicit RETURN path after the GOSUB — the program then checks INKEY$ for Y/N navigation, which works correctly in practice.
  • The SAVE line (9000) saves the file with an inverse-video character embedded in the name.

Program 2: TYPE — Full-Screen Typewriter

Written by R. J. Lees (revision 1, May 1983), this utility turns the display into a typewriter, printing characters at a tracked cursor position (N,C) and displaying a block-graphic cursor character (\##, inverse hash) at the current position. It supports 22 lines of 32 columns.

Program Structure

  • Lines 1–5: REMs and initialization (L=0 line count)
  • Lines 10–210: Main character-input loop; cursor display and movement
  • Lines 300–320: Space (character 118 = newline/enter on ZX81 — actually this handles ENTER as space+advance)
  • Lines 400–450: Newline/carriage return handling with SCROLL at row 21
  • Lines 500–530: Backspace (character 119)
  • Lines 600–630: Cursor jump by line and column (triggered by character 117 at column 0)
  • Lines 700–800: End-of-screen (22 lines filled) — waits for keypress, optionally prints/copies
  • Lines 900–930: Cursor repositioning after end-of-screen
  • Line 9000–9010: SAVE and restart

Cursor and Column Tracking

The variable C tracks the current column (0–31) and N tracks the current row. After each character is printed, C is incremented. When C reaches 27–31, the code at lines 160–200 places inverse digit characters (%5 through %1) as a visual countdown to the end of the line, alerting the typist that the margin is near. At C=32, a newline is forced.

Control Key Mapping

CHR$ codeAction
118Print space and advance (treated as spacebar or ENTER)
114Carriage return / newline
119Backspace (move cursor left)
117 at C=0Jump to specific line and column
117 (end-of-screen)Jump to specific line and column after full page
14 (end-of-screen)COPY screen to printer, then scroll and continue

Notable Techniques

The main input loop uses the classic double-wait idiom: lines 50–60 first flush any held key (INKEY$<>"" busy-wait), then wait for a new keypress (INKEY$="" busy-wait), bracketed by SLOW/FAST for display stability. The cursor is a block-graphic inverse character printed with PRINT AT N,C;"\##".

The line counter L is reset to 0 at line 5 (not line 10), and L=L-1 appears in the cursor-jump routines to compensate for the increment that will occur when execution resumes normally — this prevents double-counting of lines when repositioning.

The revision note in line 2 documents that lines 630 and 930 were changed from GOTO 20 to GOTO 30, which skips the LET N=21 reset, allowing the cursor jump to land at an arbitrary row rather than always resetting to row 21.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

Source Code

  11 DIM C$(3)
  12 DIM P$(11)
  13 DIM N$(10)
  14 DIM I$(5)
  15 DIM D$(340,32)
 100 PRINT TAB 5;"DXCC COUNTRIES LIST"
 101 PRINT "PROG. BY W3ZQN, R J LEES, 09/82"
 105 PRINT "%T%O% %R%U%N% %U%S%E% %"%G%O%T%O% %1%0%0%"% % % % % % % % % % % %T%O% %S%A%V%E% %U%S%E% %"%G%O%T%O% %9%0%0%0%"% % % % % % % % % %I%F% %"%R%U%N%"% %U%S%E%D%,% %A%L%L% %D%A%T%A% %I%S% %L%O%S%T% "
 110 PRINT ,,"EACH DATA LINE HAS:",TAB 2;"COUNTRY NUMBER- 3 SPACES",TAB 10;"PREFIX-11",TAB 10;"NAME  -10",TAB 10;"DATA  - 5"
 120 PRINT ,,"  DATA IS MO, YR, AND DXCC CODE:  (S)ENT/(R)ECEIVED/(C)REDITED"
 130 PRINT ,,,,"%E%N%T%E%R% %R%O%U%T%I%N%E% %D%E%S%I%R%E%D%:","  S-SEARCH (LOCATE/CHANGE DATA)","  R-REVIEW (BY PAGES)","  T-TOTALS (WORKED,CREDITED,ETC)  I-INPUT  (CHANGE DATA BASE)","  E-EXIT   (STOP THE PROGRAM)"
 140 GOSUB 8000
 150 IF INKEY$="S" THEN GOTO 1000
 160 IF INKEY$="R" THEN GOTO 3000
 170 IF INKEY$="T" THEN GOTO 4000
 180 IF INKEY$="I" THEN GOTO 5000
 190 IF INKEY$="E" THEN GOTO 7000
 200 GOTO 130
 1000 PRINT "%S%E%L%E%C%T% %S%E%A%R%C%H% %R%O%U%T%I%N%E%:",TAB 3;"C-BY NUMBER",,TAB 3;"P-BY PREFIX",,TAB 3;"N-BY NAME"
 1010 GOSUB 8000
 1020 IF INKEY$="C" THEN GOTO 1100
 1030 IF INKEY$="P" THEN GOTO 1500
 1040 IF INKEY$="N" THEN GOTO 2000
 1050 GOTO 1000
 1100 PRINT "%E%N%T%E%R% %C%O%U%N%T%R%Y% %N%O%.%:"
 1110 INPUT C
 1120 IF D$(C,1)=" " THEN GOSUB 8100
 1130 IF INKEY$="Y" THEN GOTO 1100
 1140 IF INKEY$="N" THEN GOTO 130
 1150 CLS 
 1160 PRINT D$(C)
 1170 GOSUB 6000
 1180 IF INKEY$="N" THEN GOTO 1250
 1190 IF INKEY$="Y" THEN GOSUB 6100
 1195 IF INKEY$="Y" THEN GOTO 1100
 1200 GOTO 130
 1250 GOSUB 6500
 1260 GOTO 1195
 1500 PRINT "%E%N%T%E%R% %P%R%E%F%I%X"
 1510 INPUT P$
 1520 FOR C=1 TO 340
 1530 IF D$(C,5 TO 15)=P$ THEN GOTO 1600
 1540 NEXT C
 1550 GOSUB 8100
 1560 IF INKEY$="Y" THEN GOTO 1500
 1570 IF INKEY$="N" THEN GOTO 130
 1580 GOTO 1550
 1600 CLS 
 1610 PRINT D$(C)
 1620 GOSUB 6000
 1630 IF INKEY$="N" THEN GOTO 1700
 1640 IF INKEY$="Y" THEN GOSUB 6100
 1650 IF INKEY$="Y" THEN GOTO 1500
 1660 GOTO 130
 1700 GOSUB 6500
 1710 GOTO 1650
 2000 PRINT "%E%N%T%E%R% %C%O%U%N%T%R%Y% %N%A%M%E"
 2010 INPUT N$
 2020 FOR C=1 TO 340
 2030 IF D$(C,17 TO 26)=N$ THEN GOTO 2100
 2040 NEXT C
 2050 GOSUB 8100
 2060 IF INKEY$="Y" THEN GOTO 2000
 2070 IF INKEY$="N" THEN GOTO 130
 2080 GOTO 2050
 2100 CLS 
 2110 PRINT D$(C)
 2120 GOSUB 6000
 2130 IF INKEY$="N" THEN GOTO 2200
 2140 IF INKEY$="Y" THEN GOSUB 6100
 2150 IF INKEY$="Y" THEN GOTO 2000
 2160 GOTO 130
 2200 GOSUB 6500
 2210 GOTO 2150
 3000 PRINT "USE ""B"" (SCROLL) TO PAGE FORWARDHIT ANY KEY TO EXIT ROUTINE"
 3010 PRINT ,,"%S%T%A%R%T% %P%A%G%E% %A%T% %W%H%A%T% %C%O%U%N%T%R%Y% %N%O%.%?"
 3020 INPUT PS
 3025 CLS 
 3030 FOR B=PS TO 340 STEP 21
 3040 FOR C=B TO B+21
 3050 IF C=341 THEN GOTO 3080
 3060 PRINT D$(C)
 3070 NEXT C
 3080 GOSUB 8000
 3090 IF INKEY$="B" THEN GOTO 3110
 3100 IF INKEY$<>"B" THEN GOTO 130
 3110 NEXT B
 3120 GOTO 130
 4000 LET CL=0
 4010 LET CW=0
 4020 LET CS=0
 4030 LET CR=0
 4040 LET CC=0
 4060 FOR C=1 TO 340
 4070 IF D$(C,5)<>" " THEN LET CL=CL+1
 4080 IF D$(C,28)<>" " THEN LET CW=CW+1
 4090 IF D$(C,32)="S" THEN LET CS=CS+1
 4110 IF D$(C,32)="R" THEN LET CR=CR+1
 4140 IF D$(C,32)="C" THEN LET CC=CC+1
 4150 NEXT C
 4160 PRINT CL,"COUNTRIES LISTED"
 4170 PRINT ,,CW,"WORKED"
 4180 PRINT ,,CL-CW,"NOT WORKED"
 4190 PRINT ,,CS,"QSL SENT,NO RET"
 4200 PRINT ,,CR,"QSL SENT AND RET"
 4210 PRINT ,,CC,"DXCC CREDITED"
 4220 PRINT ,,,,"%H%I%T% %A%N%Y% %K%E%Y% %T%O% %R%E%T%U%R%N"
 4230 GOSUB 8000
 4240 GOTO 130
 5000 PRINT "%C%O%U%N%T%R%Y% %N%O%.%?% %(%0% %T%O% %E%X%I%T%)"
 5010 INPUT C$
 5012 LET C=VAL C$
 5015 IF C<1 OR C>340 THEN GOTO 5200
 5020 CLS 
 5025 LET D$(C, TO 3)=C$
 5030 PRINT "COUNTRY NUMBER: ";C;"       "
 5040 PRINT AT 2,0;"%P%R%E%F%I%X%?% %(%1%1% %M%A%X%)"
 5050 INPUT P$
 5060 LET D$(C,5 TO 15)=P$
 5070 PRINT AT 2,0;"        PREFIX: ";P$
 5080 PRINT AT 4,0;"%N%A%M%E%?% %(%1%0% %M%A%X%)"
 5090 INPUT N$
 5100 LET D$(C,17 TO 26)=N$
 5110 PRINT AT 4,0;"          NAME: ";N$
 5120 PRINT AT 6,0;"%D%A%T%A%?% %(%M%M%Y%Y%S%/%R%/%C%)"
 5130 INPUT I$
 5140 LET D$(C,28 TO 32)=I$
 5150 PRINT AT 6,0;"          DATA: ";I$
 5160 PRINT AT 9,0;D$(C)
 5170 PRINT AT 13,0;"%H%I%T% %A%N%Y% %K%E%Y% %T%O% %C%O%N%T%I%N%U%E"
 5180 GOSUB 8000
 5190 GOTO 5000
 5200 CLS 
 5210 GOTO 130
 6000 PRINT ,,"CHANGE DATA? %Y%/%N"
 6010 GOSUB 8000
 6020 RETURN 
 6100 PRINT AT 20,0;D$(C)
 6110 PRINT AT 21,1;D$(C,28 TO )
 6120 INPUT I$
 6130 LET D$(C,28 TO )=I$
 6140 CLS 
 6150 PRINT D$(C)
 6160 GOSUB 6500
 6170 RETURN 
 6500 PRINT ,,"ANOTHER? %Y%/%N"
 6519 GOSUB 8000
 6520 RETURN 
 7000 CLS 
 7010 PRINT "YOU HAVE STOPPED THE PROGRAM",,,"REMEMBER: TO START IT AGAIN USE",TAB 10;"""GOTO 100""; TO SAVE IT";TAB 10;"USE ""GOTO 9000""",TAB 10;"NEVER USE ""RUN"" OR ",TAB 10;"DATA WILL BE LOST"
 7020 STOP 
 8000 SLOW 
 8005 PAUSE 20
 8006 POKE 16437,255
 8010 IF INKEY$="" THEN GOTO 8010
 8020 FAST 
 8030 CLS 
 8040 RETURN 
 8100 CLS 
 8105 PRINT "NOT FOUND. TRY AGAIN? %Y%/%N"
 8110 GOSUB 8000
 8120 RETURN 
 9000 SAVE "DXC%C"
 9010 GOTO 100
 
   1 REM PROGRAM "TYPE" BY W3ZQN- R. J. LEES, 705 JONATHAN RD., KING OF PRUSSIA, PA. 19406, JAN,1983
   2 REM REV. 1, 5/83: ADDED    LINES 625 AND 925; REVISED      LINES 630  AND 930 FROM "GOTO   20" TO "GOTO 30" - THIS ALLOWS  EDITING BY LINE NO. AND COLUMN  NO. 
   5 LET L=0
  10 LET N=21
  20 LET C=0
  30 PRINT AT N,C;"##"
  40 SLOW 
  50 IF INKEY$<>"" THEN GOTO 50
  60 IF INKEY$="" THEN GOTO 60
  70 FAST 
  80 PRINT AT N,C;INKEY$;
  90 IF INKEY$=CHR$ 118 THEN GOTO 300
 100 IF INKEY$=CHR$ 114 THEN GOTO 400
 110 IF INKEY$=CHR$ 119 THEN GOTO 500
 120 IF INKEY$=CHR$ 117 AND C=0 THEN GOTO 600
 130 LET C=C+1
 140 IF C=32 THEN GOTO 410
 150 IF C<27 THEN PRINT AT N,C;"##"
 160 IF C=27 THEN PRINT AT N,C;"%5"
 170 IF C=28 THEN PRINT AT N,C;"%4"
 180 IF C=29 THEN PRINT AT N,C;"%3"
 190 IF C=30 THEN PRINT AT N,C;"%2"
 200 IF C=31 THEN PRINT AT N,C;"%1"
 210 GOTO 40
 300 PRINT AT N,C;" "
 320 GOTO 130
 400 PRINT AT N,C;" "
 410 LET L=L+1
 420 IF L=22 THEN GOTO 700
 430 IF N<>21 THEN GOTO 10
 440 SCROLL 
 450 GOTO 20
 500 PRINT AT N,C;" "
 510 IF C=0 THEN GOTO 530
 520 LET C=C-1
 530 GOTO 30
 600 INPUT EL
 610 LET N=21-EL
 620 LET L=L-1
 625 INPUT C
 630 GOTO 30
 700 SLOW 
 710 IF INKEY$<>"" THEN GOTO 710
 720 IF INKEY$="" THEN GOTO 720
 730 FAST 
 740 IF INKEY$=CHR$ 117 THEN GOTO 900
 750 IF INKEY$=CHR$ 14 THEN GOTO 770
 760 GOTO 700
 770 COPY 
 780 PRINT AT 21,0;"-----"
 790 SCROLL 
 800 GOTO 5
 900 INPUT EM
 910 LET N=22-EM
 920 LET L=L-1
 925 INPUT C
 930 GOTO 30
 9000 SAVE "TYP%E"
 9010 GOTO 5

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

Scroll to Top