--- title: "Grimm’s Fairy Trails" id: 51890 type: "computer_media" slug: "grimms-fairy-trails" url: "http://localhost/computer_media/grimms-fairy-trails/" markdown_url: "http://localhost/computer_media/grimms-fairy-trails.md" published_at: "2023-08-16T01:42:21+00:00" modified_at: "2026-04-03T07:59:10+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "Guide Prince Billy through a treacherous maze, collecting 250 life crystals while dodging relentless pursuers in this machine-code-driven arcade adventure." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "Timex Computer Corporation" slug: "timex-computer-corporation" taxonomy: "post_tag" url: "http://localhost/tag/timex-computer-corporation/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" indiv: - name: "George Grimm" slug: "george-grimm" taxonomy: "indiv" url: "http://localhost/indiv/george-grimm/" genre: - name: "Arcade" slug: "arcade" taxonomy: "genre" url: "http://localhost/type/arcade/" - name: "Game" slug: "game" taxonomy: "genre" url: "http://localhost/type/game/" media_type: "Cassette" programmers: - name: "George Grimm" slug: "george-grimm" taxonomy: "indiv" url: "http://localhost/indiv/george-grimm/" download_url: "https://archive.org/download/timex-sinclair-software-archive/Grimm's Fairy Trails (1983)(Timex)(US)(TS1000)(Cassette).zip" mediadate: "1983" producer_company: - id: 11401 title: "Timex Computer Corporation" type: "company" url: "http://localhost/company/timex-computer-corporation/" related_products: - id: 12781 title: "Grimm’s Fairy Trails" type: "product" url: "http://localhost/product/grimms-fairy-trails/" media_type_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: | Address | Purpose (inferred) | | --- | --- | | `16608` | Screen/display reset or CLS routine | | `16642` | Maze rendering routine | | `16664` | Additional screen setup | | `16750` | Sprite/character movement engine | | `18000` | Main game loop (movement, collision) | | `18220` | Score display update | | `18370` | Character-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: | Key | Label | POKE 18037 value | | --- | --- | --- | | 1 | SUPER PRINCE | 5 (fastest) | | 2 | SKILLED HUNTER | 10 | | 3 | SCHOOL DAZE | 15 | | 4 | FIRST TIME | 20 | | 5 | LEAD FEET | 25 | | 6 | POISON APPLE | 30 (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. ## 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 ```