World Geography

Developer(s): Shawn Byrne
Date: 198x
Type: Program
Platform(s): TS 1000
Tags: Education

World Geography is an educational quiz program that tests knowledge of countries, islands, continents, oceans, and seas by flashing their locations on a world map displayed using ZX81 block graphics. The program operates in two modes: a review mode (option 1) that names each location while highlighting it, and an identify mode (option 2) that prompts the player to type the name from memory. A machine code routine stored in REM line 1 handles smooth scrolling of the map display, accessed via USR calls to calculated addresses based on the DFILE pointer at address 16396/16397. Coordinates for each of the 19 countries/islands or 17 geographic features are packed as two-byte entries in a string array P$, with screen positions encoded as raw character codes including values above 128 that are sign-extended by subtracting 256 to give signed offsets.


Program Analysis

Program Structure

The program is divided into several logical phases:

  1. Initialisation (lines 1–40): A machine code routine is embedded in REM line 1. Key system addresses are computed: DF (display file address), GET (a custom keypress-reading routine offset), and M (the fixed address 16540 for the map scroll routine).
  2. Mode selection (lines 100–210): The player chooses Review (1) or Identify (2), then chooses Countries/Islands (A) or Continents/Oceans/Seas (B).
  3. Data loading (lines 1000–1110 and 2000–2100): Two parallel string arrays, N$ (names) and P$ (map positions), are built from packed string literals A$ using fixed-stride slicing.
  4. Quiz loop (lines 5000–5520): Items are presented in random non-repeating order. The map is scrolled to the correct position, the location is flashed, and in Identify mode the player’s typed answer is checked.

Machine Code Usage

REM line 1 contains a substantial Z80 machine code payload. It is invoked in three distinct ways:

  • USR GET — reads the current keypress and stores it in G$; returns 0 (false) if no key is pressed, enabling the polling loops at lines 112 and 200.
  • USR M (address 16540) — scrolls the map one step; called in loops at lines 5012–5014, 5080–5100, and 5130–5134 to pan horizontally and vertically.
  • USR 16875 at line 5140 — performs a separate map operation (likely resetting or returning a status value used by the flash routine).

The address GET is dynamically computed as DF - 289, tying the routine’s entry point to the current display file location. This is a common ZX81 technique to make code position-independent relative to the BASIC/display file boundary.

Coordinate Encoding

Map positions are stored in P$(A) as two raw bytes. The first byte (accessed via CODE P$(D)) encodes the horizontal offset; the second byte (CODE P$(D,2)) encodes the vertical offset Y. Values above 128 are treated as negative by subtracting 256 at line 5065, giving a signed range of approximately −128 to +127. This compact two-byte encoding avoids the overhead of storing integer variables for each location.

Data Packing

Names and coordinates are stored in long string literals A$ and sliced into fixed-length arrays using a stride loop. For countries/islands, LN=17 (name length) and NN=19 (count); for geographic features, LN=18 and NN=17. The slice expression N$(A)=A$(1+LN*(A-1) TO ) relies on ZX81 string-array assignment truncating to the declared field width, neatly packing each name. CHR$ calls are used for characters that cannot be typed directly in the source editor.

Randomisation and Non-Repeating Order

A tracking array T$(NN) is used at lines 5016–5034 to avoid repeating items within a round. Each element starts as a null character (code 0); when an item is shown, T$(D) is set to "1". The test IF CODE T$(D) THEN GOTO 5030 re-draws a random index until an unseen one is found. When CT=NN the round restarts, re-dimensioning T$ implicitly resets it (via GOTO 5000 which re-executes DIM T$).

Map Flashing Technique

Lines 5190–5240 implement a flash effect at the map location. The display file address B is computed from DF, the row offset A (derived from Y), and a column of 33 characters per row. The character at B is read into F; a “complement” value C is computed as either 23 or 23+128 depending on whether the original character has bit 7 set (i.e., is already inverse). The cell is then toggled between C and F fifteen times in a short delay loop, producing a visible flash.

Scrolling Control

The POKE sequence at lines 5000–5004 initialises the scroll state. POKE 16522 at lines 5070 and 5120 sets the scroll direction: value 34 = right, 36 = left (or similar encoding). The number of scroll steps is computed from the difference between the current and target coordinates, with wrap-around logic handling the case where going the other way around the map is shorter (the B>0 AND B<42 OR B<-42 condition at line 5120).

Notable BASIC Idioms

  • IF USR M THEN REM — calls machine code but discards any return value; the REM acts as a no-op target. The IF condition is always evaluated, ensuring the USR call executes every iteration.
  • FOR A=1 TO ABS(...) with empty body — used as a delay loop and also as a counted scroll loop, with the loop variable serving double duty.
  • LET G$=G$( TO USR GET) at line 5260 — uses the machine code return value as a string slice length to extract exactly the typed portion of the padded answer string.
  • Lines 5010–5014 call USR M four times per iteration over eight iterations (32 total) — likely performing an initial map setup or centering scroll before the quiz begins.

Possible Anomalies

  • Line 5180 computes B=DF+412+33*A*(Y<1 OR Y>26): the multiplication by a boolean condition means that when Y is out of range 1–26, B jumps by 33×A, which could point outside valid display memory. This may be intentional (off-map items skip the flash) or a latent boundary issue.
  • The coordinate data in P$ is built from raw character codes embedded in string literals, some via CHR$ and some as literal block-graphic escape sequences. The mixing of methods makes the data difficult to audit without running the code.
  • REM line 2 contains what appears to be a garbled BASIC listing artifact — its tokens do not form valid statements and are likely the residue of a previously different line or an encoding artifact from the file format.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM 3C5B5163003B1A213E6F327A4132C6413E6732874132D341C93E67327A4132C6413E6F32874132D341ED5BC403A8A40CB4F282CCB473A894020FFE1AC83C21210191F72EDB0185BFE0C83D2117319545D1210ED421F72EDB8184560CB473A8840201C3CFE55201AF32884013626B233E18E1FEDB0232313133D20F518233DFEFF2023E543288402117319545D2B3E18E1FEDB82B2B1B1B3D20F5183328940ED4B884043A8A40FE222043E17804711C392AC40AFED5211550C578D61AC13853C47CD8B401910FDE593A8A40CB4F282FE52AC4023CB4720411F7219EBE16203E56CB9202E1E5AFED6FEB77CB5F284CBFECB9EEBED67231310E4C1C9C1ED4B8840CB4720D3E1F5F19811E55BB383ED5237E52AC40233031E1F19EBE14861818F3E19B920ACD8B40D5114D8ED52D1AFED6FEB77CB5F284CBFECB9EEBED67D51155019E31E2119D1EBC10D3C9
   2 REM M$5 DIM INKEY$6-RNDLN 0)777 FAST E£RND)7 ;SGN ' 3  GOSUB %K7:4 GOSUB %KTAN 
   4 REM *** :%W%O%R%L%D% %G%E%O%G%R%A%P%H%Y: ***     BY        SHAWN BYRNE
   5 RAND 
   7 SLOW 
  10 LET DF=PEEK 16396+256*PEEK 16397
  20 LET GET=DF-289
  30 LET M=16540
  40 LET M$="                                                               "
 100 PRINT "DO YOU WANT TO ";TAB 2;"%1-REVIEW";TAB 2;"%2-IDENTIFY";AT 4,2;"PRESS 1 OR 2";AT 4,0;
 110 LET G$=" "
 112 IF NOT USR GET THEN GOTO 112
 113 REM 1,2
 120 PRINT AT 4,2;"            "
 130 LET O$=G$
 190 PRINT AT 9,0;"CHOOSE";TAB 2;"%A-COUNTRIES AND ISLANDS";TAB 2;"%B-CONTINENTS, OCEANS, AND SEAS";AT 13,2;"PRESS A OR B";AT 13,0;
 200 IF NOT USR GET THEN GOTO 200
 202 REM A,B
 210 CLS 
 220 LET C$=G$
 240 IF C$="B" THEN GOTO 2000
 1000 LET LN=17
 1002 LET NN=19
 1016 DIM N$(NN,LN)
 1018 LET A$="FRANCE          .'ITALY           : BRITISH ISLES   $CANADA          .'MEXICO          .'NORWAY          .'SPAIN           : INDIA           : SAUDI ARABIA    £GRENADA         :'FALKLAND ISLANDS(GREENLAND       ,,JAPAN           : CUBA            . NEWFOUNDLAND    £NEW ZEALAND     "+CHR$ 11+"HAWAII          .'ICELAND         :'INDONESIA       ,,"
 1020 FOR A=1 TO NN
 1030 LET N$(A)=A$(1+LN*(A-1) TO )
 1040 NEXT A
 1060 DIM P$(NN,2)
 1070 LET A$=",. 1.'; '' ' ' $0 RETURN ;.'H$9"+CHR$ 11+CHR$ 11+"?£8( SAVE W.'.'$£. "+CHR$ 69+"2"+CHR$ 72+":+ CLEAR S<"
 1080 FOR A=1 TO NN
 1090 LET P$(A)=A$(2*A-1 TO )
 1100 NEXT A
 1110 GOTO 5000
 2000 LET LN=18
 2002 LET NN=17
 2016 DIM N$(NN,LN)
 2018 LET A$="NORTH AMERICA    $SOUTH AMERICA    $AFRICA           .'EUROPE           .'ASIA             . AUSTRALIA        ,,PACIFIC OCEAN    $ATLANTIC OCEAN   :INDIAN OCEAN     £ARCTIC OCEAN     £MEDITERRANEAN SEA)GREAT LAKES      "+CHR$ 11+"GULF OF MEXICO   :RED SEA          :'HUDSON BAY       ~~BERING STRAIT    $PERSIAN GULF     £"
 2020 FOR A=1 TO NN
 2030 LET N$(A)=A$(1+LN*(A-1) TO )
 2040 NEXT A
 2060 DIM P$(NN,2)
 2070 LET A$=CHR$ 84+".'"+CHR$ 11+",2<2''M''V,"+CHR$ 77+">:?H-"+CHR$ 72+" PLOT 2##: : . £8$:  "+CHR$ 71+" CLEAR B"+CHR$ 11
 2080 FOR A=1 TO NN
 2090 LET P$(A)=A$(2*A-1 TO )
 2100 NEXT A
 5000 POKE 16520,0
 5002 POKE 16521,0
 5004 POKE 16522,36
 5010 FOR A=1 TO 8
 5012 IF USR M OR USR M OR USR M OR USR M THEN REM 
 5014 NEXT A
 5016 DIM T$(NN)
 5018 LET CT=0
 5030 LET D=INT (RND*NN)+1
 5032 IF CODE T$(D) THEN GOTO 5030
 5034 LET T$(D)="1"
 5040 LET L$=N$(D, TO CODE N$(D,LN))
 5060 LET Y=CODE P$(D,2)
 5065 IF Y>128 THEN LET Y=Y-256
 5070 POKE 16522,34+(Y<PEEK 16521)
 5080 FOR A=1 TO ABS (Y-PEEK 16521)
 5090 IF USR M THEN REM 
 5100 NEXT A
 5110 LET B=PEEK 16520-CODE P$(D)
 5120 POKE 16522,36-3*(B>0 AND B<42 OR B<-42)
 5130 FOR A=1 TO ABS (85*(ABS B>42)-ABS B)
 5132 IF USR M THEN REM 
 5134 NEXT A
 5140 LET A=USR 16875
 5160 PRINT AT 1,1;
 5165 IF O$="1" THEN PRINT L$
 5170 LET A=Y-26*(Y>26)
 5180 LET B=DF+412+33*A*(Y<1 OR Y>26)
 5190 LET F=PEEK B
 5200 LET C=23+128*(F>127)
 5210 FOR A=1 TO 15
 5220 POKE B,C
 5225 FOR D=1 TO 2
 5226 NEXT D
 5230 POKE B,F
 5240 NEXT A
 5245 IF O$="1" THEN GOTO 5500
 5250 LET G$=L$+"  "
 5260 LET G$=G$( TO USR GET)
 5262 REM A-Z, 
 5270 IF L$<>G$ THEN GOTO 5300
 5280 LET A=INT (RND*3)*6+1
 5282 PRINT AT 2,1;"RIGHT.GREAT.SUPER."(A TO A+5)
 5290 FOR A=1 TO 12
 5292 NEXT A
 5295 GOTO 5500
 5300 PRINT AT 2,1;"NO, THIS IS ";L$;"."
 5310 FOR A=1 TO 35
 5312 NEXT A
 5500 LET CT=CT+1
 5502 IF CT=NN THEN GOTO 5000
 5510 PRINT AT 1,1;M$
 5520 GOTO 5030
 9998 SAVE "GE%O"
 9999 RUN 

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

Scroll to Top