Type DXCC

Date: 198x
Type: Cassette
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

Type DXCC

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
\n1000 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"
\n1010 GOSUB 8000
\n1020 IF INKEY$="C" THEN GOTO 1100
\n1030 IF INKEY$="P" THEN GOTO 1500
\n1040 IF INKEY$="N" THEN GOTO 2000
\n1050 GOTO 1000
\n1100 PRINT "%E%N%T%E%R% %C%O%U%N%T%R%Y% %N%O%.%:"
\n1110 INPUT C
\n1120 IF D$(C,1)=" " THEN GOSUB 8100
\n1130 IF INKEY$="Y" THEN GOTO 1100
\n1140 IF INKEY$="N" THEN GOTO 130
\n1150 CLS 
\n1160 PRINT D$(C)
\n1170 GOSUB 6000
\n1180 IF INKEY$="N" THEN GOTO 1250
\n1190 IF INKEY$="Y" THEN GOSUB 6100
\n1195 IF INKEY$="Y" THEN GOTO 1100
\n1200 GOTO 130
\n1250 GOSUB 6500
\n1260 GOTO 1195
\n1500 PRINT "%E%N%T%E%R% %P%R%E%F%I%X"
\n1510 INPUT P$
\n1520 FOR C=1 TO 340
\n1530 IF D$(C,5 TO 15)=P$ THEN GOTO 1600
\n1540 NEXT C
\n1550 GOSUB 8100
\n1560 IF INKEY$="Y" THEN GOTO 1500
\n1570 IF INKEY$="N" THEN GOTO 130
\n1580 GOTO 1550
\n1600 CLS 
\n1610 PRINT D$(C)
\n1620 GOSUB 6000
\n1630 IF INKEY$="N" THEN GOTO 1700
\n1640 IF INKEY$="Y" THEN GOSUB 6100
\n1650 IF INKEY$="Y" THEN GOTO 1500
\n1660 GOTO 130
\n1700 GOSUB 6500
\n1710 GOTO 1650
\n2000 PRINT "%E%N%T%E%R% %C%O%U%N%T%R%Y% %N%A%M%E"
\n2010 INPUT N$
\n2020 FOR C=1 TO 340
\n2030 IF D$(C,17 TO 26)=N$ THEN GOTO 2100
\n2040 NEXT C
\n2050 GOSUB 8100
\n2060 IF INKEY$="Y" THEN GOTO 2000
\n2070 IF INKEY$="N" THEN GOTO 130
\n2080 GOTO 2050
\n2100 CLS 
\n2110 PRINT D$(C)
\n2120 GOSUB 6000
\n2130 IF INKEY$="N" THEN GOTO 2200
\n2140 IF INKEY$="Y" THEN GOSUB 6100
\n2150 IF INKEY$="Y" THEN GOTO 2000
\n2160 GOTO 130
\n2200 GOSUB 6500
\n2210 GOTO 2150
\n3000 PRINT "USE ""B"" (SCROLL) TO PAGE FORWARDHIT ANY KEY TO EXIT ROUTINE"
\n3010 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%.%?"
\n3020 INPUT PS
\n3025 CLS 
\n3030 FOR B=PS TO 340 STEP 21
\n3040 FOR C=B TO B+21
\n3050 IF C=341 THEN GOTO 3080
\n3060 PRINT D$(C)
\n3070 NEXT C
\n3080 GOSUB 8000
\n3090 IF INKEY$="B" THEN GOTO 3110
\n3100 IF INKEY$<>"B" THEN GOTO 130
\n3110 NEXT B
\n3120 GOTO 130
\n4000 LET CL=0
\n4010 LET CW=0
\n4020 LET CS=0
\n4030 LET CR=0
\n4040 LET CC=0
\n4060 FOR C=1 TO 340
\n4070 IF D$(C,5)<>" " THEN LET CL=CL+1
\n4080 IF D$(C,28)<>" " THEN LET CW=CW+1
\n4090 IF D$(C,32)="S" THEN LET CS=CS+1
\n4110 IF D$(C,32)="R" THEN LET CR=CR+1
\n4140 IF D$(C,32)="C" THEN LET CC=CC+1
\n4150 NEXT C
\n4160 PRINT CL,"COUNTRIES LISTED"
\n4170 PRINT ,,CW,"WORKED"
\n4180 PRINT ,,CL-CW,"NOT WORKED"
\n4190 PRINT ,,CS,"QSL SENT,NO RET"
\n4200 PRINT ,,CR,"QSL SENT AND RET"
\n4210 PRINT ,,CC,"DXCC CREDITED"
\n4220 PRINT ,,,,"%H%I%T% %A%N%Y% %K%E%Y% %T%O% %R%E%T%U%R%N"
\n4230 GOSUB 8000
\n4240 GOTO 130
\n5000 PRINT "%C%O%U%N%T%R%Y% %N%O%.%?% %(%0% %T%O% %E%X%I%T%)"
\n5010 INPUT C$
\n5012 LET C=VAL C$
\n5015 IF C<1 OR C>340 THEN GOTO 5200
\n5020 CLS 
\n5025 LET D$(C, TO 3)=C$
\n5030 PRINT "COUNTRY NUMBER: ";C;"       "
\n5040 PRINT AT 2,0;"%P%R%E%F%I%X%?% %(%1%1% %M%A%X%)"
\n5050 INPUT P$
\n5060 LET D$(C,5 TO 15)=P$
\n5070 PRINT AT 2,0;"        PREFIX: ";P$
\n5080 PRINT AT 4,0;"%N%A%M%E%?% %(%1%0% %M%A%X%)"
\n5090 INPUT N$
\n5100 LET D$(C,17 TO 26)=N$
\n5110 PRINT AT 4,0;"          NAME: ";N$
\n5120 PRINT AT 6,0;"%D%A%T%A%?% %(%M%M%Y%Y%S%/%R%/%C%)"
\n5130 INPUT I$
\n5140 LET D$(C,28 TO 32)=I$
\n5150 PRINT AT 6,0;"          DATA: ";I$
\n5160 PRINT AT 9,0;D$(C)
\n5170 PRINT AT 13,0;"%H%I%T% %A%N%Y% %K%E%Y% %T%O% %C%O%N%T%I%N%U%E"
\n5180 GOSUB 8000
\n5190 GOTO 5000
\n5200 CLS 
\n5210 GOTO 130
\n6000 PRINT ,,"CHANGE DATA? %Y%/%N"
\n6010 GOSUB 8000
\n6020 RETURN 
\n6100 PRINT AT 20,0;D$(C)
\n6110 PRINT AT 21,1;D$(C,28 TO )
\n6120 INPUT I$
\n6130 LET D$(C,28 TO )=I$
\n6140 CLS 
\n6150 PRINT D$(C)
\n6160 GOSUB 6500
\n6170 RETURN 
\n6500 PRINT ,,"ANOTHER? %Y%/%N"
\n6519 GOSUB 8000
\n6520 RETURN 
\n7000 CLS 
\n7010 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"
\n7020 STOP 
\n8000 SLOW 
\n8005 PAUSE 20
\n8006 POKE 16437,255
\n8010 IF INKEY$="" THEN GOTO 8010
\n8020 FAST 
\n8030 CLS 
\n8040 RETURN 
\n8100 CLS 
\n8105 PRINT "NOT FOUND. TRY AGAIN? %Y%/%N"
\n8110 GOSUB 8000
\n8120 RETURN 
\n9000 SAVE "DXC%C"
\n9010 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
\n9000 SAVE "TYP%E"
\n9010 GOTO 5

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

Scroll to Top