Grimm’s Fairy Trails

Developer(s): George Grimm
Date: 1983
Type: Cassette
Platform(s): TS 1000
Tags: Arcade, Game

Grimm’s Fairy Trails is a maze game in which the player guides “Prince Billy” through a maze, collecting 250 “B-lers” (life crystals) while being pursued by two maze dwellers named Murph and Drago. The game relies heavily on machine code routines called via USR at addresses such as 16608, 16642, 16664, 16750, 18000, 18220, and 18370, which handle sprite movement, collision detection, and screen rendering beyond what BASIC alone could achieve at playable speed. Six difficulty levels are selectable at startup, each POKEing a delay value (5 through 30) into address 18037 to control game speed. A title-screen animation routine draws the game’s name and a sponsoring label character-by-character using a DIM’d string array and a machine code character-plotting routine at USR 18370. A built-in machine code entry utility at line 9000 and a save routine at line 9200 are included for development purposes.


Program Analysis

Program Structure

The program is organized into several functional blocks:

  1. Line 10: A REM statement containing what appears to be embedded machine code data (the long token-heavy line is the ML payload stored in a REM).
  2. Lines 990–2070: Main game initialization and loop — sets up the screen, POKEs machine code parameters, and launches ML routines via USR.
  3. Lines 3000–3064: Game-over / replay prompt (“GO-AGAIN – PRINCE ? Y/N”).
  4. Lines 4000–4099: Instructions and difficulty-level selection subroutine.
  5. Lines 5000–5999: Animated title screen subroutine — draws the game name letter by letter.
  6. Lines 6000–6199: Helper subroutine for setting ML display parameters per title row.
  7. Lines 6200–6399: Story/introduction screen with character descriptions.
  8. Lines 9000–9220: Developer utilities: machine code entry tool, POKE-based hex entry, and a tape save routine.

Machine Code Integration

The game’s core logic — sprite movement, collision detection, and rendering — is implemented in machine code rather than BASIC. The ML routines are invoked repeatedly through USR calls, with results discarded into a dummy variable C1. Key addresses used include:

AddressPurpose (inferred)
16608Screen/display reset or CLS routine
16642Maze rendering routine
16664Additional screen setup
16750Sprite/character movement engine
18000Main game loop (movement, collision)
18220Score display update
18370Character-plotting routine for title animation

Machine code parameters are passed by POKEing values directly into fixed addresses immediately before calling USR. For example, sprite row/column coordinates are written to addresses 16751, 16753, 16771, and 16773, while game speed is stored at 18037.

The machine code payload itself is almost certainly stored inside the REM statement on line 10. This is the standard technique for embedding ML in BASIC: the tokenizer stores the REM body verbatim, allowing arbitrary byte sequences to be placed at a known address (just past the line header).

Difficulty Level System

Six difficulty levels are offered at startup (lines 4040–4088). Each level POKEs a different delay constant into address 18037, which the ML game loop presumably uses as a timing parameter:

KeyLabelPOKE 18037 value
1SUPER PRINCE5 (fastest)
2SKILLED HUNTER10
3SCHOOL DAZE15
4FIRST TIME20
5LEAD FEET25
6POISON APPLE30 (slowest)

Title Animation

The subroutine at line 5000 uses a DIM A$(6,7) string array to store six seven-character strings: a label row, a separator row, another label row, and three rows spelling “GRIMM S / FAIRY / TRAILS”. A nested loop iterates over each character, extracts it with A$(J,N TO N), POKEs its CODE and column index into addresses 18345 and 18346, then calls the ML plotter at USR 18370. An inner loop at lines 5032–5034 provides a brief inter-character pause. A special case at line 5036 clears the screen after row 3, and line 5037 prints a block-graphic character at a fixed position when row 4 is drawn.

Key BASIC Idioms

  • Dummy USR variable: All ML calls use LET C1=USR xxxxx to discard the return value while still invoking the routine.
  • Score display: Line 2070 uses PRINT AT 18,11;PEEK 16816 to read the score directly from a fixed ML variable address rather than tracking it in BASIC.
  • Input loop: Lines 4040–4088 use a tight IF INKEY$="" THEN GOTO 4038 spin-wait followed by LET Y=VAL INKEY$ to capture a single keypress and convert it to a number.
  • Replay loop: Lines 3010–3025 use a three-way INKEY$ branch (Y / N / empty) to manage the “play again” prompt without blocking.
  • SLOW/FAST: Line 990 sets SLOW mode for the BASIC sections; the ML routines operate independently of this setting.

Developer Utilities

Lines 9000–9220 contain tools that were left in the final listing. Lines 9010–9060 implement a sequential POKE loop for entering ML byte by byte. Lines 9070–9150 provide a character-pair hex-entry utility that converts two-character strings to byte values using 16*CODE A$+CODE A$(2)-476. Line 9200 provides a tape save routine that calls a ML save entry point at address 8192 with a filename. These routines are unreachable during normal play and represent development scaffolding.

Notable Anomalies

  • Lines 5040–5042 contain two REM-commented-out BASIC statements (PRINT AT 20,1;"PRESS ENTER WHEN READY" and INPUT Y$), replaced by the more elaborate prompt at line 6385. The REM keyword causes the lines to be skipped entirely.
  • POKE 16625,8 at line 995 and POKE 16625,128 at line 6390 manipulate the system flags byte. Setting bit 3 (value 8) enables FAST mode within ML context; value 128 sets a high bit with a different effect, likely related to display mode control.
  • Address 14812 is POKEd at line 1041 (POKE 14812,1), which falls well below the typical ML and system variable ranges used elsewhere — this may be a display file or attribute area address used to place a specific screen element.
  • The score tracking uses POKE 16816,0 and POKE 16814,0 to reset two ML variables at game start (lines 1002–1004 and 3060–3062), and reads the score back with PEEK 16816 for display.

Content

Appears On

Related Products

Grimm’s Fairy Trails is a Pac-Man takeoff with six speed variations. By pressing the arrow keys, you control the movements...

Related Articles

Related Content

Image Gallery

Source Code

  10 REM       A #ACS 9ACS 9ACS 9ACS 9ACS 9ACS =#- ;#; GOSUB #£RND;)▘ ;##TAN                                                        :-E£RND7)5 ▞4 GOSUB #6 COPYRNDQ█7▌TAB  LIST RNDE COPYRND$TAB  DIM RNDTAN [X]# ▞2:?Y.LN [▒]RND$# RETURN▘4 PRINT :?▌4 LIST TAN  :~~▞1Y█LN [▒]RND$# RETURN▞4 PRINT :~~▌▌# RETURN?4 GOTO :~~▞:Y█LN [▒]RND$# RETURN▞4 PRINT :~~▌▌# RETURN 4 GOTO ▞(:~~Y█LN [▒]RND▌# RETURN:4 PRINT :▛▞(Y█LN [▒]RND▌# RETURN:4 PRINT TAN        ▞1:£Y█LN [▒]RND▌LN [▒]RND▌▌# RETURN▝4 LIST ▞1:▀Y█LN [▒]RND▌LN [▒]RND▌▌# RETURN▝4 LIST TAN          ▝2(,,▝2  ,,/4#▘▘                                      5[5]INKEY$ #5[4]INKEY$ #YOLN [▒]RNDTAN     LN USR INKEY$ 7# RETURN█COS  RETURN.ATN [(]PI)[K]INKEY$ , RETURNCOS COS Y LN [▒]RND▖YOLN [▒]RND#M[5]INKEY$ TAN     LN USR INKEY$ F# RETURN█COS  RETURN.ATN [(]PI)[K]INKEY$ , RETURNCOS COS Y LN [▒]RND▌YOLN [▒]RND#M[5]INKEY$ TAN     LN USR INKEY$ )5  GOSUB ## RETURN█COS  RETURN.ATN [(]PI)[K]INKEY$ , RETURNCOS COS Y LN [▒]RND$YOLN [▒]RND#M[4]INKEY$ TAN      LN USR INKEY$ )5  GOSUB ## RETURN█COS  RETURN.ATN [(]PI)[K]INKEY$ , RETURNCOS COS Y LN [▒]RND£YOLN [▒]RND#M[4]INKEY$ TAN      U[K]INKEY$ LEN ▘M[K]INKEY$ TAN                                                                                                                                    LN  RAND #LN K#U[I]INKEY$  RETURNXCOS #0#     U[4]INKEY$ 5[8]INKEY$ [-] IF ##-▝#U[5]INKEY$ 5[9]INKEY$ [-] IF ##2▝##[S] IF ## PAUSE ##-▘ GOSUB ##W#2▘ GOSUB ##### RETURN▘ASN [▒]#TAB ### RETURN▘ASN [2]#TAB [O]#LN ## RETURN█""LN ""# RETURN█""LN  CONT # RETURN█""LN [,]#TAN LN [,]# RETURN█""LN ""# RETURN█""LN  CONT # RETURN█""LN ##TAN LN  CONT # RETURN█""LN [,]# RETURN█""LN ## RETURN█""LN ""#TAN LN ""# RETURN█""LN ## RETURN█""LN [,]# RETURN█""LN  CONT #TAN                                               7U9RND UARND#U9RND[T]TAB $#UARND[S]COS UARND#U9RND# RETURN COPYCOS 2 COPY- #?##[3] PLOT AI▌[+]▐R##3##S RUN #HI▘4 LET 5# #;#M SAVE # RETURN5ATN :PI RETURN6ATN #PI RETURN7ATN QPI RETURN8ATN  NEWINKEY$ TAN  RAND #       5[9]INKEY$ #5[8]INKEY$ #Y▒LN [▒]RNDTAN ##TAN [6]#TAN        LN ##)5  GOSUB ##ACS #"" RETURNOATN [▒]# RETURN▒COS LN [▒]RND£Y▒LN [▒]RND#M[8]INKEY$ TAN  LN ##)5  GOSUB ##ACS #"" RETURNOATN [▒]# RETURN▒COS LN [▒]RND$Y▒LN [▒]RND#M[8]INKEY$ TAN INKEY$ TAN [3]#LN ##7#ACS #"" RETURNOATN [▒]# RETURN▒COS LN [▒]RND▖Y▒LN [▒]RND#M[9]INKEY$ TAN           LN ##F#ACS #"" RETURNOATN [▒]# RETURN▒COS LN [▒]RND▌Y▒LN [▒]RND#M[9]INKEY$ TAN                               5[D]INKEY$ #5[C]INKEY$ #Y▒LN [▒]RNDTAN [▒]LN 8#)5  GOSUB ##ACS #"" RETURNOATN [▒]# RETURN▒COS LN [▒]RND£Y▒LN [▒]RND#M[C]INKEY$ TAN LN LN 8#)5  GOSUB ##ACS #"" RETURNOATN [▒]# RETURN▒COS LN [▒]RND$Y▒LN [▒]RND#M[C]INKEY$ TAN                 U[G]INKEY$  RETURN▝ASN [-]#YXM[I]INKEY$ TAN LN ##TAN   LN 8#7#ACS #"" RETURNOATN [▒]# RETURN▒COS LN [▒]RND▖Y▒LN [▒]RND#M[D]INKEY$ TAN LN 8#F#ACS #"" RETURNOATN [▒]# RETURN▒COS LN [▒]RND▌Y▒LN [▒]RND#M[D]INKEY$ TAN                                                                                                                         LN  RAND #U[H]INKEY$  RETURN▝TAB ##Y▘M[H]INKEY$ LN K#LN [O]#U[I]INKEY$  RETURNXCOS ###LEN ▘M[H]INKEY$ :▌▞ IF Y▘▌4 CLS$4 PLOT U[K]INKEY$  RETURN IF COS E[E]INKEY$ ## RETURNOATN #######                               U[4]INKEY$ 5[C]INKEY$ [-] IF CHR$ #-▝#U[5]INKEY$ 5[D]INKEY$ [-] IF <>#2▝##[S] IF  SLOW# PAUSE  GOSUB #-▘ GOSUB ##""#2▘ GOSUB ##LN ## RETURN▘ASN £#TAB  PLOT ## RETURN▘ASN +#TAB 2#LN N# RETURN█""LN [U]# RETURN█""LN [0]# RETURN█""LN ##TAN LN ## RETURN█""   LN [U]# RETURN█""# PLOT #LN [0]# RETURN█""# PLOT #     5[6]INKEY$ #5[7]INKEY$ #Y[*]LN [▒]RND6[E]INKEY$ TAN              U[G]INKEY$ LEN ▘M[G]INKEY$ ▞(:,,Y LN [▒]RNDY(M[5]INKEY$ Y?M[4]INKEY$ YOLN USR INKEY$ TAN                  XM[G]INKEY$ Y(M[5]INKEY$ Y?M[4]INKEY$ YOVAL STR$  FASTLN USR INKEY$  LPRINT SGN AT Y TAN                   ▛    ▗▖▄▝▐▞▟▘▚▌▙▀▜▛█    E£RND7▘ LET ▘U[E]# RETURN▘TAB CHR$ # GOSUB #6:RND5[D]##[B]*****- ACS >#5 2;:▖▞▖#7#7 FAST[J]ACS >*ACS >*ACS <*ACS <*5[I]#▐##E:RND#76:RND( STOPSTR$ )1 ;6:RNDSGN  LPRINT $4INT )█ COPYE:RND;6:RND#TAN                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           
 990 SLOW
 995 POKE 16625,8
 1000 LET C1=USR 16608
 1002 POKE 16816,0
 1004 POKE 16814,0
 1006 GOSUB 4000
 1010 LET C1=USR 16642
 1011 PRINT AT 15,1;"                              "
 1012 PRINT AT 8,15;" "
 1014 PRINT AT 8,16;" "
 1016 PRINT AT 9,16;" "
 1018 PRINT AT 9,15;" "
 1020 LET C1=USR 16664
 1022 POKE 16751,30
 1024 POKE 16753,14
 1026 POKE 16771,30
 1028 POKE 16773,5
 1030 POKE 16767,0
 1032 POKE 16787,0
 1034 LET C1=USR 16750
 1036 POKE 16751,29
 1038 POKE 16753,12
 1040 POKE 16771,29
 1041 POKE 14812,1
 1042 POKE 16773,3
 1044 POKE 16767,2
 1046 POKE 16787,2
 1048 LET C1=USR 16750
 1049 PRINT AT 8,14;"."
 1050 PRINT AT 3,1;".█"
 1051 PRINT AT 14,30;"."
 1052 PRINT AT 12,1;".█"
 1053 PRINT AT 5,30;"."
 1056 PRINT AT 18,5;"[S][C][O][R][E]"
 1057 POKE 16802,16
 1058 POKE 16803,9
 1059 LET C1=USR 18220
 1060 POKE 16801,16
 1062 POKE 16800,15
 1064 PRINT AT 15,16;"O"
 2020 PRINT AT 6,16;"[▒]"
 2022 PRINT AT 6,15;"[▒]"
 2024 POKE 16804,6
 2028 POKE 16805,16
 2030 POKE 16808,6
 2032 POKE 16809,15
 2035 POKE 16813,1
 2055 LET C1=USR 18000
 2070 PRINT AT 18,11;PEEK 16816
 3000 PRINT AT 20,3;"GO-AGAIN - PRINCE ? Y/N"
 3010 IF INKEY$ ="Y" THEN GOTO 3050
 3015 IF INKEY$ ="N" THEN GOTO 1
 3020 IF INKEY$ ="" THEN GOTO 3000
 3025 GOTO 3000
 3030 STOP
 3050 LET C1=USR 16608
 3060 POKE 16814,0
 3062 POKE 16816,0
 3064 GOTO 1010
 4000 REM 
 4005 GOSUB 5000
 4007 GOSUB 6200
 4010 PRINT AT 2,1;"USING THE ROYAL ARROW KEYS"
 4012 PRINT AT 3,1;"YOU MUST GUIDE PRINCE BILLY"
 4014 PRINT AT 4,1;"THROUGH THE MAZE AND GET"
 4016 PRINT AT 5,1;"ALL THE B-LERS"
 4017 PRINT AT 7,1;"GOOD LUCK"
 4019 PRINT AT 12,2;"WHAT LEVEL OF PLAY?"
 4020 PRINT AT 14,2;"1=SUPER PRINCE"
 4030 PRINT AT 15,2;"2=SKILLED HUNTER"
 4032 PRINT AT 16,2;"3=SCHOOL DAZE"
 4034 PRINT AT 17,2;"4=FIRST TIME"
 4036 PRINT AT 18,2;"5=LEAD FEET"
 4038 PRINT AT 19,2;"6=POISON APPLE"
 4040 IF INKEY$ ="" THEN GOTO 4038
 4080 LET Y=VAL INKEY$ 
 4082 IF Y=1 THEN POKE 18037,5
 4083 IF Y=2 THEN POKE 18037,10
 4084 IF Y=3 THEN POKE 18037,15
 4085 IF Y=4 THEN POKE 18037,20
 4086 IF Y=5 THEN POKE 18037,25
 4087 IF Y=6 THEN POKE 18037,30
 4088 IF Y<1 OR Y>6 THEN GOTO 4019
 4090 LET C1=USR 16608
 4099 RETURN
 5000 REM 
 5002 DIM A$(6,7)
 5004 LET A$(1)=" TIMEX "
 5006 LET A$(2)="*******"
 5008 LET A$(3)=" TIMEX "
 5010 LET A$(4)="GRIMM S"
 5012 LET A$(5)=" FAIRY "
 5014 LET A$(6)="TRAILS "
 5016 FOR J=1 TO 6
 5018 GOSUB 6000
 5020 FOR N=1 TO 7
 5022 LET B$=A$(J,N TO N)
 5024 POKE 18345,CODE B$
 5026 POKE 18346,N
 5028 LET C1=USR 18370
 5030 NEXT N
 5032 FOR L=1 TO 3
 5034 NEXT L
 5036 IF J=3 THEN LET C1=USR 16608
 5037 IF J=4 THEN PRINT AT 5,24;"▞"
 5038 NEXT J
 5040 REM  PRINT AT 20,1;"PRESS ENTER WHEN READY"
 5042 REM  INPUT Y$
 5990 POKE 16625,0
 5995 LET C1=USR 16608
 5999 RETURN
 6000 REM 
 6002 IF J=1 OR J=4 THEN POKE 18375,167
 6004 IF J=1 OR J=4 THEN POKE 18376,0
 6006 IF J=2 OR J=5 THEN POKE 18375,76
 6008 IF J=2 OR J=5 THEN POKE 18376,1
 6010 IF J=3 OR J=6 THEN POKE 18375,241
 6020 IF J=3 OR J=6 THEN POKE 18376,1
 6199 RETURN
 6200 REM 
 6202 PRINT AT 1,0;"ONCE UPON A TIME, IN A FAR"
 6204 PRINT "AND DISTANT LAND THERE LIVED"
 6206 PRINT "THE FOLLOWING PEOPLE:"
 6208 PRINT 
 6210 PRINT "O  =  PRINCE BILLY"
 6212 PRINT "[▒]  =  MAZE DWELLER MURPH"
 6213 PRINT 
 6214 PRINT "[▒]  =  MAZE DWELLER DRAGO"
 6216 PRINT   
 6218 PRINT "THE MAZE DWELLERS WOULD CHASE "
 6220 PRINT "PRINCE BILLY DAY AND NIGHT"
 6222 PRINT 
 6224 PRINT "HIS ONLY HOPE WAS TO GATHER 250"
 6226 PRINT "B-LERS (...), HIS LIFE CRYSTALS."
 6228 PRINT 
 6230 PRINT "IF PRINCE BILLY COULD TOUCH"
 6232 PRINT "THE SACRED STONE OF ROSS  [*]   "
 6234 PRINT "IN THE CENTER OF THE MAZE HE"
 6236 PRINT "CAN ESCAPE CAPTURE--ONLY ONCE"
 6385 PRINT AT 21,1;"[P][R][E][S][S]█[E][N][T][E][R]█[W][H][E][N]█[R][E][A][D][Y]"
 6387 INPUT Y$
 6390 POKE 16625,128
 6392 LET C1=USR 16608
 6399 RETURN
 9000 STOP
 9010 INPUT A
 9020 INPUT B
 9030 PRINT B
 9040 POKE A,B
 9050 LET A=A+1
 9060 GOTO 9020
 9070 INPUT X
 9080 LET A$=""
 9090 IF A$="" THEN INPUT A$
 9100 IF A$="S" THEN STOP
 9110 POKE X,16*CODE A$+CODE A$(2)-476
 9120 PRINT X;" ";A$
 9130 LET X=X+1
 9140 LET A$=A$(3 TO )
 9150 GOTO 9090
 9200 PRINT "SET TAPE"
 9205 INPUT Y$
 9210 PRINT USR 8192;"SAVE:P:GRIMM:"
 9212 CLS
 9220 GOTO 1

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

Scroll to Top