Lords of Time Disassembly

discuss classic text/graphic adventures for the bbc micro & electron
Post Reply
fuzzel
Posts: 1191
Joined: Sun Jan 02, 2005 1:16 pm
Location: Cullercoats, North Tyneside
Contact:

Lords of Time Disassembly

Post by fuzzel »

Inspired by Mark Moxon's work on Elite and various other projects on stardot (viewtopic.php?p=330473#p330473) I've decided to have a crack at understanding Lords of Time by Level 9, firstly because it's such a gem, secondly because it's easier than most of their other games (it loads into memory above &1100, thereby allowing me to save various interrogation and data files to disc), thirdly because hoglet has already archived the game as an .ASM file (https://github.com/hoglet67/AtomSoftwar ... F.ASM.ORIG) but mainly because I've been wondering for years how they managed to cram in such a large game into less than 32k without the use of magic (it's scarcely believable but the actual game code only takes up 2133 bytes - the verbs and nouns take up more space at 2272 bytes!) First up I'm taking a look at their input routine. The verbs and nouns are stored at &1220 onwards and I've located the subroutine for the text input (&7768). I've been trying to find out where the verb and noun numbers are stored assuming they're located somewhere in zero page (each word is followed by a single code number) but unfortunately no luck so far. I have discovered, however, that &0000 onwards is where the inputted string is stored, &76 stores the length of the input string, &78 stores the number of words in the string and &86 stores the ascii value of the second word (the noun) although I'm not sure yet why this is - maybe they have a different way of matching the inputted string to their vocabulary list. That's enough for the moment but I intend to keep returning to this as it's actually quite fun now that I know a bit (and I mean a bit) about assembler.
User avatar
hoglet
Posts: 12662
Joined: Sat Oct 13, 2012 7:21 pm
Location: Bristol
Contact:

Re: Lords of Time Disassembly

Post by hoglet »

You might find this thread interesting and/or useful: Specification of Level 9 A-Code

I would see if you can get a copy of the l9dis tool and run it over the game data.

Dave
fuzzel
Posts: 1191
Joined: Sun Jan 02, 2005 1:16 pm
Location: Cullercoats, North Tyneside
Contact:

Re: Lords of Time Disassembly

Post by fuzzel »

Many thanks for that hoglet, I've had a quick look and there's plenty of food for thought there. In fact there are a multitude of approaches I can take to understand the game code, one of which is to look at the save game file and find where the objects and flags are stored in memory. I can then hopefully locate the individual puzzles they relate to. I think I'll also do a map of the subroutines for the main elements of the game such as command line interpreter and message printer. I should be able to then create standalone programs for each of these and get a better understanding of the variables in each one without being deafened by the noise of general gameplay. Lots of fun to be had anyway!
User avatar
8bitAG
Posts: 180
Joined: Wed Nov 07, 2018 5:03 pm
Contact:

Re: Lords of Time Disassembly

Post by 8bitAG »

There was some talk about the Austins allowing access to their archive of material, so hopefully that will also help unlock some of the unexplored secrets of A-Code. Such as, the actual date it was conceived... Lots of sites quote "1979" but there seems to be no real primary source for that and I think that date may just stem from confusion with the other A-Code, that was created in 1979. by David Platt for his Adventure550 game.
melchett
Posts: 478
Joined: Tue Jan 28, 2003 9:52 am
Contact:

Re: Lords of Time Disassembly

Post by melchett »

fuzzel wrote: Thu Feb 17, 2022 4:11 pm Inspired by Mark Moxon's work on Elite and various other projects on stardot (viewtopic.php?p=330473#p330473) I've decided to have a crack at understanding Lords of Time by Level 9, firstly because it's such a gem, secondly because it's easier than most of their other games (it loads into memory above &1100, thereby allowing me to save various interrogation and data files to disc), thirdly because hoglet has already archived the game as an .ASM file (https://github.com/hoglet67/AtomSoftwar ... F.ASM.ORIG) but mainly because I've been wondering for years how they managed to cram in such a large game into less than 32k without the use of magic (it's scarcely believable but the actual game code only takes up 2133 bytes - the verbs and nouns take up more space at 2272 bytes!) First up I'm taking a look at their input routine. The verbs and nouns are stored at &1220 onwards and I've located the subroutine for the text input (&7768). I've been trying to find out where the verb and noun numbers are stored assuming they're located somewhere in zero page (each word is followed by a single code number) but unfortunately no luck so far. I have discovered, however, that &0000 onwards is where the inputted string is stored, &76 stores the length of the input string, &78 stores the number of words in the string and &86 stores the ascii value of the second word (the noun) although I'm not sure yet why this is - maybe they have a different way of matching the inputted string to their vocabulary list. That's enough for the moment but I intend to keep returning to this as it's actually quite fun now that I know a bit (and I mean a bit) about assembler.
I started a documented disassembly of the the source a few months ago too Fuzzel - mainly because it was my favourite from back in the day and I have also been fascinated by its size, the dictionary and the mystery of the a-code. I didn't know that hoglet had made an ASM so have been handcrafting my own. I have almost finished but COVID is slowing me down at the moment which I hope to shake in a couple of days.

In addition, I have written a Python interpreter/parser of Level 9's A-Code - I struggled to understand the C code because it's largely undocumented in Github. I don't have a problem with C, it's just it's pretty much a port of the 6502/Z80/Other directly into C without the why. A highly respectful effort especially given the number of years ago it was written.

But I almost have a complete spec too for the byte code stream that is the game - I'll release that when I'm happier with it.

I'm sure you know that it's a virtual machine driven off of byte code - and the 6502 code that you're looking at implements that engine to interpret that virtual machine. And it has a number of key parts that are implemented by the 6502:

- Stack (for gosubs / returns) - this is independent of the 6502 stack
- A virtual machine byte code pointer - so it knows what it's processing (command vs parameters which can be variables or constants or +/- offsets)
- A double byte variable memory area - each of these are used to track game progress from $0400 to $04EF
- A single byte list memory area - from $0550 to $05FF
- A set of pointers in the game code that point to where e.g. where the virtual machine byte code starts, the variable memory starts, the dictionary starts, the list area starts, the common compressed word fragments are etc - most are at $7349 (run time location)

So to answer a few of your questions above, and correcting the typo of where it loads ($1200 on my version at least):
1. Yes the words you type appear at $0000+
2. When they are mapped to cmds/objects they are also stored initially at $0000+ along with the "word count", but only temporarily
3. You can have a maximum of three cmd/obj matches - anything else is ignored
4. This is where the variable memory then kicks in - as those are they stored in 0448, 044A, 044C with the word count in 044E (the inbetween most significant bytes are set to $00 on the Beeb)
5. So most of the interesting stuff happens in 0400 - 05FF across variables and lists (although again 0500 - 054F doesn't yet appear to be used on Lords of Time)

In zero page, some most interesting addresses are:

1. $80/$81 - pointer into the current virtual machine byte code address (which command am I executing)
2. $70/$71 - mostly used as an index into the dictionary when scanning it and then separately used to track the "lists" but...
3. $70/$71 - used to hold command variable 1's address sometimes
4. $72/$73 - used to hold the value of the command's variable 1
5. $74/$75 - used to hold command variable 2's address sometimes
6. $76/$77 - used to hold command variable 2's address sometimes
7. $78 - used to temporarily hold and increment the word count when parsing your input
8. $82/$83 - dictionary start address cached
9. $6E - if the 7th bit of the command is set -
10. $6F - if the 8th bit of the command is set
11. $6A/$6B/$6C - used as general caches for values

The implementation of the a-code is quite a clever design - with many of the high bits having meanings in commands (do I have a single or a double byte constant that follows, is this a command or an instruction for the list handler etc) - similar with the dictionary encoding. As an example, for the comparisons of a variable against a constant commands:

Code: Select all

    <cmd x11xxxxx> <variable> <constant> <offset>
    <cmd x10xxxxx> <variable> <constant> <offset lsb> <offset msb>
    <cmd x01xxxxx> <variable> <constant lsb> <constant msb> <offset>
    <cmd x00xxxxx> <variable> <constant lsb> <constant msb> <offset lsb> <offset msb>
I will try upload to github soon.

Andy
melchett
Posts: 478
Joined: Tue Jan 28, 2003 9:52 am
Contact:

Re: Lords of Time Disassembly

Post by melchett »

fuzzel wrote: Thu Feb 17, 2022 4:11 pm The verbs and nouns are stored at &1220 onwards and I've located the subroutine for the text input (&7768). I've been trying to find out where the verb and noun numbers are stored assuming they're located somewhere in zero page (each word is followed by a single code number) but unfortunately no luck so far.
Here is a list of the Lords of Time dictionary of nouns (commands and objects) - I have a python routine that will extract them that should work on any V2 game:

Code: Select all

Data length: 27135
0x14  /  0x1220 AGAIG    
0x1  /  0x1226 NORTH     
0x3  /  0x122c EAST      
0x2  /  0x1231 NEAST     
0x4  /  0x1237 SOUTH     
0x2  /  0x123d NORTHEAST 
0x5  /  0x1247 SOUTHEAST 
0x7  /  0x1251 WEST      
0x6  /  0x1256 SOUTHWEST 
0x8  /  0x1260 NWEST     
0x5  /  0x1266 SEAST     
0x8  /  0x126c NORTHWEST 
0x6  /  0x1276 SWEST     
0x2  /  0x127c NORTH-EAST
0x5  /  0x1287 SOUTH-EAST
0x8  /  0x1292 NORTH-WEST
0x6  /  0x129d SOUTH-WEST
0x9  /  0x12a8 UPWARDS   
0xa  /  0x12b0 DOWNWARDS
0xb  /  0x12ba INSIDE
0xb  /  0x12c1 ENTER
0xb  /  0x12c7 INTO
0xb  /  0x12cc BOARD
0xc  /  0x12d2 OUTSIDE
0xc  /  0x12da LEAVE
0xd  /  0x12e0 CROSS
0xd  /  0x12e6 ACROSS
0xe  /  0x12ed CLIMB
0xf  /  0x12f3 JUMP
0x10  /  0x12f8 BACKWARDS
0x11  /  0x1302 FORWARDS
0x11  /  0x130b AHEAD
0x12  /  0x1311 LEFT
0x13  /  0x1316 RIGHT
0x15  /  0x131c ATTACK
0x15  /  0x1323 KICK
0x15  /  0x1328 FIGHT
0x15  /  0x132e KILL
0x15  /  0x1333 CHOP
0x15  /  0x1338 HIT
0x15  /  0x133c SMASH
0x15  /  0x1342 CUT
0x15  /  0x1346 BREAK
0x16  /  0x134c INVENTORY
0x17  /  0x1356 LISTEN
0x17  /  0x135d HEAR
0x19  /  0x1362 PLUGH
0x19  /  0x1368 PLOVER
0x19  /  0x136f SESAME
0x19  /  0x1376 XYZZY
0x1a  /  0x137c QUIT
0x1b  /  0x1381 RESTORE
0x1c  /  0x1389 SAVE
0x1d  /  0x138e SCORE/
0x1e  /  0x1395 YES
0x1e  /  0x1399 AFFERMATIVE
0x1f  /  0x13a5 NEGATIVE
0x20  /  0x13ae WAIT
0x21  /  0x13b3 SHOUT
0x22  /  0x13b9 SAY
0x23  /  0x13bd SEARCH
0x23  /  0x13c4 EXAMINE
0x23  /  0x13cc READ
0x24  /  0x13d1 BLINK
0x24  /  0x13d7 WINK
0x25  /  0x13dc LOOK
0x26  /  0x13e1 KNEEL
0x26  /  0x13e7 GROVEL
0x27  /  0x13ee PRAY
0x27  /  0x13f3 WORSHIP
0x28  /  0x13fb TAKE
0x28  /  0x1400 GET
0x28  /  0x1404 CARRY
0x29  /  0x140a DROP
0x29  /  0x140f PUT
0x29  /  0x1413 ABANDON
0x2a  /  0x141b WEAR
0x2b  /  0x1420 THROW
0x2b  /  0x1426 HURL
0x2c  /  0x142b GIVE
0x2c  /  0x1430 FEED
0x2c  /  0x1435 PAY
0x2d  /  0x1439 FILL
0x2e  /  0x143e EMPTY
0x2e  /  0x1444 POUR
0x2f  /  0x1449 OPEN
0x2f  /  0x144e UNLOCK
0x2f  /  0x1455 UNDO
0x2f  /  0x145a UNTIE
0x30  /  0x1460 CLOSE
0x30  /  0x1466 LOCK
0x30  /  0x146b SHUT
0x31  /  0x1470 BITE
0x31  /  0x1475 EAT
0x65  /  0x1479 NIBBLE
0x31  /  0x1480 SWALLOW
0x31  /  0x1488 TASTE
0x32  /  0x148e DRINK
0x32  /  0x1494 SIP
0x33  /  0x1498 LIGHT
0x34  /  0x149e EXTINGUISH
0x35  /  0x14a9 PRESS
0x35  /  0x14af PUSH
0x35  /  0x14b4 SWING
0x36  /  0x14ba FASTEN
0x36  /  0x14c1 TIE
0x36  /  0x14c5 ATTACH
0x36  /  0x14cc FIX
0x37  /  0x14d0 SHAKE
0x37  /  0x14d6 WAVE
0x38  /  0x14db BLOW
0x38  /  0x14e0 PLAY
0x39  /  0x14e5 FIRE
0x39  /  0x14ea SHOOT
0x3a  /  0x14f0 RUB
0x3a  /  0x14f4 PAT
0x3b  /  0x14f8 DIG
0x3c  /  0x14fc UNTIE
0x3c  /  0x1502 UNFASTEN
0x3c  /  0x150b UNDO
0x3d  /  0x1510 INSERT
0x3e  /  0x1517 TURN
0x3e  /  0x151c TWIST
0x3e  /  0x1522 ROTATE
0x40  /  0x1529 PULL
0x41  /  0x152e WIND
0x42  /  0x1533 KISS
0x43  /  0x1538 SHUFFLE
0x43  /  0x1540 MIX
0x50  /  0x1544 OLIVE
0x50  /  0x154a BRANCH
0x51  /  0x1551 BUCKLE
0x52  /  0x1558 CAP
0x53  /  0x155c MICROCHIP
0x53  /  0x1566 SILICON
0x53  /  0x156e CHIP
0x54  /  0x1573 EVIL
0x54  /  0x1578 EYE
0x54  /  0x157c BOX
0x55  /  0x1580 DIAMOND
0x55  /  0x1588 TEARDROP
0x56  /  0x1591 IVORY
0x56  /  0x1597 TUSK
0x57  /  0x159c WING
0x58  /  0x15a1 EGG
0x59  /  0x15a5 APPLE
0x5a  /  0x15ab ARMOUR
0x5b  /  0x15b2 BONE
0x5c  /  0x15b7 POISON
0x5c  /  0x15be BOTTLE
0x5d  /  0x15c5 BUNCH
0x5d  /  0x15cb LEAVES
0x5e  /  0x15d2 PACK
0x5e  /  0x15d7 CARDS
0x5f  /  0x15dd CARPET
0x5f  /  0x15e4 RUG
0x60  /  0x15e8 CASE
0x60  /  0x15ed JEWELRY
0x60  /  0x15f5 JEWELLERY
0x61  /  0x15ff CASK
0x61  /  0x1604 ALE
0x62  /  0x1608 FROG
0x63  /  0x160d KEYS
0x64  /  0x1612 GAUNTLET
0x64  /  0x161b GLOVE
0x65  /  0x1621 DRINKING
0x65  /  0x162a HORN
0x66  /  0x162f HOURGLASS
0x66  /  0x1639 HOUR-GLASS
0x67  /  0x1644 ICICLE
0x68  /  0x164b LIGHTSABRE
0x68  /  0x1656 SABRE
0x69  /  0x165c GLASS
0x69  /  0x1662 LOOKING-GLASS
0x6a  /  0x1670 LUTE
0x6b  /  0x1675 MATCHES
0x6b  /  0x167d MATCHBOX
0x6c  /  0x1686 METRONOME
0x6d  /  0x1690 MILESTONE
0x6d  /  0x169a HOPE
0x6e  /  0x169f MIRROR
0x6f  /  0x16a6 POT
0x70  /  0x16aa SCREWDRIVER
0x71  /  0x16b6 SPEAR
0x72  /  0x16bc SWEETMEATS
0x73  /  0x16c7 VALERIAN
0x74  /  0x16d0 WHEEL
0x76  /  0x16d6 AXE
0x77  /  0x16da BELL
0x78  /  0x16df CAN
0x78  /  0x16e3 PETROL
0x79  /  0x16ea CANDELABRA
0x7a  /  0x16f5 CANDLE
0x7c  /  0x16fc CLOAK
0x7b  /  0x1702 CANDLESTICK
0x7d  /  0x170e CLUB
0x7e  /  0x1713 COAT
0x7f  /  0x1718 COFFER
0x80  /  0x171f COINS
0x81  /  0x1725 CROWN
0x82  /  0x172b EMERALD
0x84  /  0x1733 ONYX
0x84  /  0x1738 FIGURINE
0x85  /  0x1741 FIREFLY
0x85  /  0x1749 FLY
0x86  /  0x174d FOOD
0x87  /  0x1752 GALACTIC
0x87  /  0x175b GROAT
0x88  /  0x1761 JOKER
0x89  /  0x1767 SWORD
0x8a  /  0x176d LODESTONE
0x8a  /  0x1777 MAGNET
0x8b  /  0x177e LUR
0x8c  /  0x1782 MAP
0x8c  /  0x1786 PARCHMENT
0x8d  /  0x1790 MATTRESS
0x8d  /  0x1799 MATRESS
0x8e  /  0x17a1 NET
0x8f  /  0x17a5 NUGGET
0x90  /  0x17ac OPENER
0x91  /  0x17b3 PEBBLE
0x92  /  0x17ba PHIAL
0x93  /  0x17c0 PICK
0x94  /  0x17c5 PLANKS
0x95  /  0x17cc ROCKET
0x96  /  0x17d3 COIL
0x96  /  0x17d8 ROPE
0x97  /  0x17dd RUBY
0x97  /  0x17e2 LENSE
0x98  /  0x17e8 RUCKSACK
0x99  /  0x17f1 SHOES
0x99  /  0x17f7 SANDALS
0x98  /  0x17ff BACKPACK
0x9a  /  0x1808 SHOVEL
0x9a  /  0x180f SPADE
0x9b  /  0x1815 STAR
0x9c  /  0x181a TIN
0x9c  /  0x181e CATFOOD
0x9c  /  0x1826 KATTOMUSH
0x9d  /  0x1830 TRIDENT
0x9f  /  0x1838 TOOTH
0xa1  /  0x183e CLOCK
0xa3  /  0x1844 PENDULUM
0xa2  /  0x184d COGS
0xa4  /  0x1852 CAULDRON
0xa5  /  0x185b JUNK
0xa5  /  0x1860 PILE
0xa5  /  0x1865 RUBBISH
0xa6  /  0x186d CUPBOARD
0xa7  /  0x1876 TREE
0xa7  /  0x187b WILLOW
0xa8  /  0x1882 CAR
0xa8  /  0x1886 PORSCHE
0xa9  /  0x188e WALL
0xaa  /  0x1893 LAKE
0xab  /  0x1898 SHEET
0xac  /  0x189e CUBE
0xad  /  0x18a3 SHIP
0xad  /  0x18a8 LONGSHIP
0xae  /  0x18b1 STONE
0xaf  /  0x18b7 CHEST
0xb0  /  0x18bd HANDLE
0xb1  /  0x18c4 OTTOMAN
0xb2  /  0x18cc WELL
0xb3  /  0x18d1 GRATE
0xb4  /  0x18d7 BASIN
0xb5  /  0x18dd ARCHWAY
0xb6  /  0x18e5 ROBOTS
0xb7  /  0x18ec BENCH
0xb7  /  0x18f2 WORKBENCH
0xb8  /  0x18fc CAGES
0xb9  /  0x1902 BARS
0xb9  /  0x1907 BARRED
0xba  /  0x190e COMPOST
0xba  /  0x1916 HEAP
0xbb  /  0x191b WOOD
0xbc  /  0x1920 PICTURE
0xbd  /  0x1928 RING
0xbd  /  0x192d MUSHROOMS
0xc9  /  0x1937 FAIRY
0xca  /  0x193d MAMMOTH
0xcb  /  0x1945 TIGER
0xcc  /  0x194b ALLOSAURUS
0xcd  /  0x1956 TYRANNOSAURUS
0xcd  /  0x1964 REX
0xce  /  0x1968 BRONTOSAURUS
0xcf  /  0x1975 CAVEMEN
0xd0  /  0x197d CAVEPEOPLE
0xd0  /  0x1988 CAVEMAN
0xd0  /  0x1990 CAVEWOMAN
0xd1  /  0x199a SKELETON
0xd2  /  0x19a3 BARTENDER
0xd3  /  0x19ad UNFORTUNATE
0xd3  /  0x19b9 WRETCH
0xd3  /  0x19c0 STOCKS
0xd4  /  0x19c7 MESSANGER
0xd4  /  0x19d1 MESSENGER
0xd5  /  0x19db DRAGON
0xd6  /  0x19e2 KNIGHT
0xd7  /  0x19e9 PRINCE
0xd8  /  0x19f0 PIRATE
0xd8  /  0x19f7 PETE
0xd9  /  0x19fc JESTER
0xda  /  0x1a03 VIKING
0xdb  /  0x1a0a GHOST
0xdc  /  0x1a10 SENTRY
0xdc  /  0x1a17 SENTRIES
0xdd  /  0x1a20 GLADIATOR
0xde  /  0x1a2a LIONESS
0xdf  /  0x1a32 ANDROID
0xdf  /  0x1a3a CHAIN
0xe0  /  0x1a40 CYBERMAN
0xe0  /  0x1a49 CYBERMEN
0xe1  /  0x1a52 NARCISSUS
0xe2  /  0x1a5c FOX
0xe3  /  0x1a60 DOGS
0xe3  /  0x1a65 BEAGLES
0xe6  /  0x1a6d EUREKA
0xe6  /  0x1a74 UREKA
0xe7  /  0x1a7a JAMES
0xe8  /  0x1a80 WATT
0xf0  /  0x1a85 DOOR
0xf0  /  0x1a8a TRAPDOOR
0xf1  /  0x1a93 ONE
0xf1  /  0x1a97 1.
0xf2  /  0x1a9a TWO
0xf2  /  0x1a9e 2.
0xf3  /  0x1aa1 THREE
0xf3  /  0x1aa7 3.
0xf4  /  0x1aaa FOUR
0xf4  /  0x1aaf 4.
0xf5  /  0x1ab2 FIVE
0xf5  /  0x1ab7 5.
0xf6  /  0x1aba SIX
0xf6  /  0x1abe 6.
0xf7  /  0x1ac1 SEVEN
0xf7  /  0x1ac7 7.
0xf8  /  0x1aca EIGHT
0xf8  /  0x1ad0 8.
0xf9  /  0x1ad3 NINE
0xf9  /  0x1ad8 9.
0xfa  /  0x1adb AT
0xfb  /  0x1ade ITS
0xfb  /  0x1ae2 THEM
0xfc  /  0x1ae7 ON
0xfd  /  0x1aea EVERYTHING

Dictionary length : 0x8d5  /  2261
What is curious here is that my version, from one of my old disks, has a bug or corruption in the dictionary - the first entry should say AGAIN but it is "AGAIG".

There's also a bug in the game engine on mine that when you examine the matchbox, it says "4tches" left instead of "4 matches" left. Interesting my Python interpreter / parser correctly says "4 matches" with the same virtual machine so will be interesting to work out that game engine bug and compare it against e.g. Hoglet's. Also notice the "/" after "SCORE".
melchett
Posts: 478
Joined: Tue Jan 28, 2003 9:52 am
Contact:

Re: Lords of Time Disassembly

Post by melchett »

fuzzel wrote: Thu Feb 17, 2022 4:11 pm .. but mainly because I've been wondering for years how they managed to cram in such a large game into less than 32k without the use of magic...
I also wrote a Python script to pull out the descriptions - again it's quite clever as each location description is a composite of many of these depending on the state of the room and the objects within it.

Code: Select all

Data length: 27135
0x0  /  0x2082  :  
0x1  /  0x2084  :

0x2  /  0x2086  :
0x3  /  0x2087  : ,

0x4  /  0x208a  : .

0x5  /  0x208d  :


0x6  /  0x208f  :  and

0x7  /  0x2094  : .


0x8  /  0x2097  : north
0x9  /  0x209b  : northeast
0xa  /  0x20a1  : east
0xb  /  0x20a4  : south
0xc  /  0x20a6  : southeast
0xd  /  0x20ac  : southwest
0xe  /  0x20b0  : west
0xf  /  0x20b3  : northwest
0x10  /  0x20b9  : up
0x11  /  0x20bc  : down
0x12  /  0x20c0  : in
0x13  /  0x20c2  : out
0x14  /  0x20c5  : across
0x15  /  0x20c9  : Exits are

0x16  /  0x20d1  :  (through a door)
0x17  /  0x20db  :  (through an open door)
0x18  /  0x20e9  :

You are

0x19  /  0x20ee  : You own

0x1a  /  0x20f3  : And you're wearing

0x1b  /  0x2101  : You can see

0x1c  /  0x2108  :

What now?
0x1d  /  0x2110  : I don't understand
0x1e  /  0x211c  : Eh?
0x1f  /  0x2120  : Arfle barfle gloop?
0x20  /  0x212e  : You'll need to say more than that!
0x21  /  0x2143  : Could you elaborate?
0x22  /  0x2152  : Sorry, I can't guess what you mean
0x23  /  0x2169  : Could you rephrase that?
0x24  /  0x2179  : Please be more specific
0x25  /  0x2187  : I don't quite understand
0x26  /  0x2197  : Keep it simple, please
0x27  /  0x21a6  : You can't.
0x28  /  0x21ad  : Don't be silly!
0x29  /  0x21b7  : You can't see
0x2a  /  0x21bf  : You don't have
0x2b  /  0x21c8  : You already have

0x2c  /  0x21d3  : You can't carry any more
0x2d  /  0x21e1  : You can't take
0x2e  /  0x21ea  : You can't wear
0x2f  /  0x21f3  : You're carrying too much to take
0x30  /  0x2209  :
0x31  /  0x220a  :
0x32  /  0x220b  : Nothing happens
0x33  /  0x2216  : Doesn't seem to work
0x34  /  0x2225  : There's no effect
0x35  /  0x2232  : Really stop?
0x36  /  0x223b  :

Another game?
0x37  /  0x2246  : Really restore?
0x38  /  0x2250  :

YES or NO, please
0x39  /  0x225e  :

You score

0x3a  /  0x2265  :  out of 1000
0x3b  /  0x226e  : Sorry, I can't tell you any more
0x3c  /  0x2282  :  nothing.


0x3d  /  0x228a  : You can't go in that direction
0x3e  /  0x229b  : You bump into a door
0x3f  /  0x22a5  : The door closes behind you
0x40  /  0x22b2  : It's already open
0x41  /  0x22be  : It's already closed
0x42  /  0x22cb  : There's nothing to open
0x43  /  0x22d8  : There's nothing to close
0x44  /  0x22e5  : Only a fool would attack
0x45  /  0x22f5  : You find nothing
0x46  /  0x22ff  : The only visible exit is

0x47  /  0x230f  :
0x48  /  0x2310  :  tied together
0x49  /  0x2318  :  which is open
0x4a  /  0x2321  :  (one match is lit)
0x4b  /  0x232e  :  burning brightly
0x4c  /  0x2338  :  peering down from above
0x4d  /  0x2347  :  full of water
0x4e  /  0x234f  :  tied up
0x4f  /  0x2355  :  glowing white-hot
0x50  /  0x2362  : an olive branch
0x51  /  0x236e  : a golden buckle
0x52  /  0x2379  : the jester's cap
0x53  /  0x2382  : a silicon chip
0x54  /  0x238c  : a tightly-closed box
0x55  /  0x239a  : a diamond teardrop
0x56  /  0x23a5  : an ivory tusk
0x57  /  0x23b0  : a little dragon's wing
0x58  /  0x23bd  : a dinosaur egg
0x59  /  0x23c6  : a rotten apple
0x5a  /  0x23d0  : a battered suit of armour
0x5b  /  0x23df  : a meaty bone
0x5c  /  0x23e8  : a grimy brown bottle
0x5d  /  0x23f6  : a bunch of green leaves
0x5e  /  0x2406  : a pack of playing cards
0x5f  /  0x2415  : an oriental rug
0x60  /  0x2420  : a jewellery case
0x61  /  0x242b  : a cask of ale
0x62  /  0x2434  : a green frog
0x63  /  0x243d  : a bunch of keys
0x64  /  0x244a  : a rugged gauntlet
0x65  /  0x2457  : a drinking horn
0x66  /  0x2461  : a fine golden hourglass
0x67  /  0x2470  : a little icicle
0x68  /  0x2479  : a lightsabre
0x69  /  0x2482  : an inlaid looking-glass
0x6a  /  0x2492  : a lute
0x6b  /  0x2497  : a matchbox
0x6c  /  0x24a0  : a fine metronome
0x6d  /  0x24ab  : a milestone
0x6e  /  0x24b3  : a mirror
0x6f  /  0x24b9  : a stone pot
0x70  /  0x24c0  : a delicate little screwdriver
0x71  /  0x24d1  : a Masai spear
0x72  /  0x24db  : some sweetmeats
0x73  /  0x24e7  : valerian
0x74  /  0x24ed  : The Wheel
0x75  /  0x24f2  :
0x76  /  0x24f3  : a sharp axe
0x77  /  0x24fb  : a silver bell
0x78  /  0x2500  : a gallon petrol can
0x79  /  0x250b  : a silver candelabra
0x7a  /  0x2515  : a candle
0x7b  /  0x251b  :
0x7c  /  0x251c  : a filmy cloak
0x7d  /  0x2527  : a stone club
0x7e  /  0x2530  : a fur coat
0x7f  /  0x2537  : a jewelled coffer
0x80  /  0x2544  : a silver coin
0x81  /  0x254a  : a jewelled crown
0x82  /  0x2556  : an emerald
0x83  /  0x255e  :
0x84  /  0x255f  : an onyx figurine
0x85  /  0x256b  : a firefly
0x86  /  0x2572  : some delicious food
0x87  /  0x257f  : a galactic groat
0x88  /  0x2589  : a joker
0x89  /  0x258f  : a fine sharp sword
0x8a  /  0x259b  : a carved lodestone
0x8b  /  0x25a6  : a lur
0x8c  /  0x25aa  : a scrap of parchment
0x8d  /  0x25b8  : an old mattress
0x8e  /  0x25c1  : a weighted net
0x8f  /  0x25cb  : a gold nugget
0x90  /  0x25d5  : a tin opener
0x91  /  0x25dd  : a painted pebble
0x92  /  0x25e7  : a glass phial
0x93  /  0x25f1  : a grubby pick
0x94  /  0x25fb  : two short planks
0x95  /  0x2608  : a grapple-firing rocket
0x96  /  0x2617  : a coil of rope
0x97  /  0x2621  : a curved ruby
0x98  /  0x262a  : a battered rucksack
0x99  /  0x2637  : winged shoes
0x9a  /  0x263f  : a shovel
0x9b  /  0x2645  : a fallen star
0x9c  /  0x264d  : a tin of catfood
0x9d  /  0x2658  : a long trident
0x9e  /  0x2662  : a porcelain vase
0x9f  /  0x266e  : a tiger tooth
0xa0  /  0x2676  : Welcome to "Lords of Time" from Level 9 Computing. You are sitting in the comfort of your own home, debugging your latest program before submitting it for us to market. Suddenly there is a blinding flash...


0xa1  /  0x26f0  : a grandfather clock large enough to climb into
0xa2  /  0x270e  : huge cogs numbered 1 to 9
0xa3  /  0x2722  : a massive pendulum
0xa4  /  0x2730  : a cast-iron cauldron
0xa5  /  0x273e  : a pile of family rubbish
0xa6  /  0x274d  : a wall cupboard
0xa7  /  0x2758  : a weeping willow
0xa8  /  0x2761  : a red Porsche
0xa9  /  0x2769  : a wall of ice blocking the way south
0xaa  /  0x277b  : a clear lake of very cold water to the northwest
0xab  /  0x2794  : a sheet of smooth ice leading northwest
0xac  /  0x27a8  : a cube of ice round the throne
0xad  /  0x27ba  : a moored viking longship with a fierce dragon prow
0xae  /  0x27d9  : a rocking stone to the west
0xaf  /  0x27e6  : a huge iron-bound chest
0xb0  /  0x27f6  : a recessed handle
0xb1  /  0x2801  : an ottoman
0xb2  /  0x2809  : a twee little well labelled "Water of Strength"
0xb3  /  0x2826  : a grate in the south wall
0xb4  /  0x2831  : a marble basin full of water
0xb5  /  0x2842  : a crude black archway
0xb6  /  0x2852  : a jumble of broken robots
0xb7  /  0x2864  : a silicate workbench
0xb8  /  0x2871  : many cruel metal cages in which the evil Timelords have imprisoned zillions of cute creatures
0xb9  /  0x28a8  : thick bars which imprison hundreds of poor people
0xba  /  0x28c7  : a compost heap, spilling onto the path
0xbb  /  0x28d9  : a jumble of dry wood
0xbc  /  0x28e6  : a picture of a kindly old man
0xbd  /  0x28f7  : a mushroom ring
0xbe  /  0x2901  : It's dark!


0xbf  /  0x290a  : Be more careful in future!
0xc0  /  0x291c  : The picture comes to life: "I am Father Time and I have chosen youn to help defend history against 9 evil Timelords. You must collect 9 items, each marked with an 
hourglass. Good Luck!"
0xc1  /  0x2995  : The animals bound away
0xc2  /  0x29a3  : The people are free and hurry away, handing you 
a reward
0xc3  /  0x29c2  : The bottle is loosened
0xc4  /  0x29cf  : It's held fast
0xc5  /  0x29d9  :

A skeleton hand strangles you!
0xc6  /  0x29ee  :

A scorpion stings!
0xc7  /  0x29fb  :

Lightning strikes!
0xc8  /  0x2a08  :

Father Time appears. "Do not be afraid. What you are about to see is the future if the Timelords win. There is still time to defeat them."


0xc9  /  0x2a5b  : the Tooth Fairy
0xca  /  0x2a65  : a woolly mammoth blocking your escape
0xcb  /  0x2a7c  : a sabre-toothed tiger
0xcc  /  0x2a89  : an Allosaurus
0xcd  /  0x2a92  : a Tyrannosaurus Rex
0xce  /  0x2aa0  : a Brontosaurus
0xcf  /  0x2aa9  : a group of cavemen
0xd0  /  0x2ab5  : a caveman dragging a struggling cavewoman by her hair
0xd1  /  0x2ad3  : an animated cave skeleton
0xd2  /  0x2ae4  : a rotund bartender
0xd3  /  0x2af0  : an unfortunate wretch in the stocks
0xd4  /  0x2b07  : a thirsty messenger of the King
0xd5  /  0x2b19  : a genuine fire-breathing dragon
0xd6  /  0x2b2d  : the Black Knight
0xd7  /  0x2b31  : a fair prince
0xd8  /  0x2b3a  : Pirate Pete
0xd9  /  0x2b40  : a jester
0xda  /  0x2b45  : a shivering Viking guard
0xdb  /  0x2b54  : a ghost
0xdc  /  0x2b59  : two Roman sentries beside the gate
0xdd  /  0x2b6c  : a massively-muscled gladiator
0xde  /  0x2b7e  : a fierce lion
0xdf  /  0x2b87  : a splendid android
0xe0  /  0x2b92  : a fierce cyberman waving a sword
0xe1  /  0x2ba7  : a single beautiful narcissus standing proudly amongst the weeds
0xe2  /  0x2bcc  : a silver fox
0xe3  /  0x2bd2  : two hunting dogs
0xe4  /  0x2bdf  : Needs winding
0xe5  /  0x2be6  : The room shakes
0xe6  /  0x2bee  : That magic word doesn't work
0xe7  /  0x2c01  : A force field blocks you: "Payment, please"
0xe8  /  0x2c1f  : "Entry now authorised today"
0xe9  /  0x2c33  : An inspection panel opens
0xea  /  0x2c43  : The cyberman blocks you
0xeb  /  0x2c51  : "Ta, love"


0xec  /  0x2c5a  : No one here wants
0xed  /  0x2c67  : You can't fill
0xee  /  0x2c6f  : You can't empty
0xef  /  0x2c7a  : YEUCH! No, you can't eat
0xf0  /  0x2c8c  : There's no one to give it to
0xf1  /  0x2c9e  : You find
0xf2  /  0x2ca3  : It's closed
0xf3  /  0x2cab  : If you insist.. There's no accounting for taste!
0xf4  /  0x2cc9  : That was delicious!
0xf5  /  0x2cd6  : Your vision clears. Someone's here!
0xf6  /  0x2cec  : Something slaps the coin from your hand!
0xf7  /  0x2d02  : The fairy snatches it back. "This coin may not be taken", she trills, "It may only be exchanged
for a tooth!"
0xf8  /  0x2d41  : You can't quite reach the keys
0xf9  /  0x2d53  : The magnetic lodestone attracts the keys
0xfa  /  0x2d6a  : The tree speaks: "When I was planted the stream
was clear and sparkling. Now I am old, it is polluted and I just want to die."
0xfb  /  0x2db6  : You need an axe
0xfc  /  0x2dc0  : With one swift blow you cut down the tree and it falls with a peaceful sigh. One sparkling teardrop remains.
0xfd  /  0x2dff  : The planks are too short to cross the stream
0xfe  /  0x2e14  : You tie the planks into a longer plank
0xff  /  0x2e28  : The tied planks bridge the stream
0x100  /  0x2e38  : With what shall you tie them?
0x101  /  0x2e47  : The stream is too wide to cross
0x102  /  0x2e55  : You've already done that!
0x103  /  0x2e66  :

You have no spear! The tiger attacks..
0x104  /  0x2e7e  : The lake freezes round the icicle!
0x105  /  0x2e92  : Petrol soaks into the ground.


0x106  /  0x2ea5  : You pour out the petrol and discard its can
0x107  /  0x2ebc  : That's towards the mammoth! You are trapped.
0x108  /  0x2ed5  : The petrol burns up with a whoosh!
0x109  /  0x2ee9  :
The mammoth is so surprised that it jumps clean out of its skin and runs off in terror!
0x10a  /  0x2f1b  : You have no fire
0x10b  /  0x2f26  : It burns brightly
0x10c  /  0x2f31  : It's empty!
0x10d  /  0x2f3b  : It burns well
0x10e  /  0x2f44  : The match goes out
0x10f  /  0x2f4f  : And goes out.


0x110  /  0x2f5a  :

The candle flickers


0x111  /  0x2f68  :

You feel very cold!


0x112  /  0x2f75  : The cavepeople grunt to each other
0x113  /  0x2f89  : The cavepeople grunt louder, at you
0x114  /  0x2f9c  : The cavemen advance, waving sticks
0x115  /  0x2fb0  : The cavemen attack!
0x116  /  0x2fbc  : The door opens.
0x117  /  0x2fc4  : The Black Knight strides forwards
0x118  /  0x2fd1  : The Black Knight draws his sword
0x119  /  0x2fde  : The Black Knight attacks

0x11a  /  0x2fe8  : The Black Knight attacks again!
0x11b  /  0x2ff5  : but the armour protects you.

0x11c  /  0x3007  : The prince leaps to your defence 

0x11d  /  0x301b  : but can find no sword and is killed easily.
0x11e  /  0x3034  : and kills the evil Black Knight. He carries the
body away
0x11f  /  0x3050  : You're in a hole
0x120  /  0x305b  : You're in a deep hole
0x121  /  0x3067  : You're in a deep hole which collapses, burying you!
0x122  /  0x3085  :

Pirate Pete steals
0x123  /  0x3090  : The lur booms out, summoning a horde of Vikings.

0x124  /  0x30ae  : They are furious that Pirate Pete is not here!
0x125  /  0x30c7  : They grab the pirate and drag him off, rewarding you with an olive branch
0x126  /  0x30f1  : The viking is delighted by the warm fur and hands you a lur. "There is 
a reward for capturing the pirate", he says
0x127  /  0x312d  :

It's very hot


0x128  /  0x3138  :

You'll die without water!


0x129  /  0x3146  :

The heat is too much!


0x12a  /  0x3153  :

The lion struggles free
0x12b  /  0x3161  : The lion attacks!
0x12c  /  0x316b  : Tears rain down from the willow tree
0x12d  /  0x317f  : The tree is dead
0x12e  /  0x3187  : Planks bridge the stream
0x12f  /  0x3194  : There's a hole to the south
0x130  /  0x31a0  : The wood burns warmly
0x131  /  0x31ad  : The dinosaur approaches menacingly
0x132  /  0x31c0  : A secret door leads east
0x133  /  0x31cc  : The plant is eating you
0x134  /  0x31d8  : I didn't expect that!
0x135  /  0x31e7  : The Timelords notice you and summon their tebbit
0x136  /  0x3202  :  releasing liquid paraquat

0x137  /  0x3212  : which kills the plant
0x138  /  0x321f  : "Woof!"
0x139  /  0x3226  : "WOOF! WOOF! YAP! GRRR!"
0x13a  /  0x323c  : "ARF! ARF! ARF! AOOOUL!" Guards arrive..
0x13b  /  0x325c  : You feel VERY strong!
0x13c  /  0x326b  : Just what you needed!

0x13d  /  0x327a  : , chasing the cavemen
0x13e  /  0x3287  : It wanders away
0x13f  /  0x3290  :  and from the debris appears
0x140  /  0x329f  : The air shimmers
0x141  /  0x32a8  : The dinosaur kills you
0x142  /  0x32b4  : The killer dinosaurs kill each other
0x143  /  0x32c7  : The dinosaur blocks you
0x144  /  0x32d3  : The ice cube shatters, freeing the Snow Queen. She smiles, taps your shoulder with a sword and glides away
0x145  /  0x3311  : The ice wall shatters
0x146  /  0x331c  : MMMMMMM!
0x147  /  0x3325  : Only a real dodo would kiss
0x148  /  0x3337  : The frog turns into a handsome prince!
0x149  /  0x334f  : Nice try, but the icicle is out of reach
0x14a  /  0x3366  :

The din shakes the icicle loose
0x14b  /  0x3378  : Noisy little beggar, aren't you!
0x14c  /  0x338e  : The bad tooth comes loose easily. The tiger is delighted and bounds off joyfully
0x14d  /  0x33b9  : It has a lean and hungry look, and could be in pain. Be careful!       
0x14e  /  0x33e0  : The tiger is friendly now, but seems to be in pain
0x14f  /  0x33fb  : The tiger purrs deafeningly
0x150  /  0x340b  : The tiger pats one puffy cheek with a paw
0x151  /  0x3423  : The tiger winces and roars quietly
0x152  /  0x3435  : The fox grabs the bone and slinks off
0x153  /  0x344a  : The fox trips you up
0x154  /  0x3457  : The tiger blocks you, snarling to show its impressive array of mottled 
teeth
0x155  /  0x3482  : You forgot to open it!

0x156  /  0x3491  : The tiger does not like that one bit. It attacks..
0x157  /  0x34af  : Oops! Smashed to smithereens
0x158  /  0x34c1  : The vile smell of whale-meat assails your nostris
0x159  /  0x34e2  : The dragon stalks off in a huff
0x15a  /  0x34f4  : The dragon lets you climb on his back and you travel along quite happily, back the way you came, until you reach the edge of a moat. The dragon
tries to fly over it but only succeeds in belly-flopping into the water. It slinks off, dripping
0x15b  /  0x3577  : "I feel like a walk now, would you like a ride on my back?"
0x15c  /  0x359e  : The dragon eats the food with obvious relish: "Thanks mate, that was very good - could have done with a touch more mustard though."


0x15d  /  0x35e6  : The android exchanges your coin for a Galactic Groat
0x15e  /  0x3606  : The tooth fairy examines it closely and says, "This isn't our usual kind of tooth, most odd - tell you what, I'll swap it for one silver coin. Is that a deal?"   
0x15f  /  0x365e  : "Mmm. Perhaps I could throw in a firefly too. OK?"
0x160  /  0x367f  : "Then you'll get NOTHING!"
0x161  /  0x3693  :

The fairy takes your tooth and leaves.
0x162  /  0x36a7  : The tiger gulps down the food greedily and purrs at you
0x163  /  0x36c6  : The brontosaurus grabs the leaves and pulls them into the air. It carries you out of the pit!
0x164  /  0x36f2  : "OK, the ale's yours"
0x165  /  0x3700  : Not worth enough
0x166  /  0x370b  : "Thanks very much! Just what I wanted!" The messenger drinks the ale and shares some of his food with you
0x167  /  0x3745  : The Jester laughs with glee, "Thank you my friend"! He gives you his belled cap before dancing off
0x168  /  0x377a  : The narcissus squeaks with joy and rewards you with a lodestone. He admires himself delightedly
in the looking-glass
0x169  /  0x37bc  : The dogs gulp down the delicacies, wagging their tails, before waddling off for a nap
0x16a  /  0x37ee  : What a queer thing to do to
0x16b  /  0x37fe  : Your blows are futile
0x16c  /  0x380c  : You attack ferociously, scaring off
0x16d  /  0x3822  :

It is marked with an hourglass symbol
0x16e  /  0x383a  : Time goes by

0x16f  /  0x3844  :

It is a valuable treasure
0x170  /  0x3853  :  balanced precariously on a shelf
0x171  /  0x3865  :  rolling on the ground
0x172  /  0x3871  :  hanging on the wall
0x173  /  0x387a  :  lying on blood-stained snow
0x174  /  0x388b  :  poking out of the earth
0x175  /  0x3894  :  scattered about
0x176  /  0x389f  :  on a green-baize table
0x177  /  0x38af  :  hanging on the wall
0x178  /  0x38b8  :  on the dressing table
0x179  /  0x38c1  :  on a rough wooden table
0x17a  /  0x38cf  :  sitting on a lily pad
0x17b  /  0x38da  :  pushed out of reach under the shed door
0x17c  /  0x38ec  :  in the dust
0x17d  /  0x38f2  :  on a table
0x17e  /  0x38f9  :  on the mantlepiece
0x17f  /  0x3904  :  hanging from the ceiling
0x180  /  0x3913  :  standing in a rack
0x181  /  0x391c  :  on the wall
0x182  /  0x3920  :  propped in the corner
0x183  /  0x392b  :  on the table
0x184  /  0x3930  :  in pride of place
0x185  /  0x393b  :  beside the road
0x186  /  0x3941  :  half-buried in the earth
0x187  /  0x394c  :  on a stone shelf
0x188  /  0x3956  :  on the workbench
0x189  /  0x395f  :  hanging on the wall
0x18a  /  0x3968  :  on a carved sideboard
0x18b  /  0x3977  :  hidden amongst the delphiniums
0x18c  /  0x398a  :  propped up in a corner
0x18d  /  0x3998  :
0x18e  /  0x3999  :
0x18f  /  0x399a  :
0x190  /  0x399b  :

You've been killed.


0x191  /  0x39a9  : in your own living room
0x192  /  0x39b4  : in a large, cold looking room
0x193  /  0x39c3  : inside a gigantic clock
0x194  /  0x39d0  : at the end of a gravel drive which bends to the
southwest. The grassy lawns beside the drive are edged with the vibrant colours of summer flowers. A narrow country road runs north-south
0x195  /  0x3a2f  : at roadworks where the road ends
0x196  /  0x3a41  : on a winding gravel drive
0x197  /  0x3a4e  : outside a delightful country cottage
0x198  /  0x3a63  : in a bright hallway at the foot of a carpetted stairway
0x199  /  0x3a7e  : on the landing at the top of the stairs
0x19a  /  0x3a8e  : in a cramped store-room
0x19b  /  0x3a9b  : in a plushly carpeted master bedroom
0x19c  /  0x3aae  : in a lovely old-fashioned kitchen
0x19d  /  0x3ac3  : in the living room, a long comfortable room decorated in autumn shades 
of brown and gold. A patio door leads to the garden
0x19e  /  0x3b03  : on a patio, decorated with urns of flowers. A crazy-paving path winds southwest across the lawn
to a garden shed. The garden ends at a wooden fence
0x19f  /  0x3b50  : in the flower garden
0x1a0  /  0x3b5a  : at the end of the garden beside a five foot fence covered in ivy       
0x1a1  /  0x3b7b  : beside a fence on the east bank of a wide, dirty stream clogged with crisp packets and MacRonalds boxes
0x1a2  /  0x3bb1  : further upstream where the filthy stream is quite narrow. A lone narcissus grows amidst the nettles on the opposite bank
0x1a3  /  0x3bf4  : west of the stream
0x1a4  /  0x3bfc  : outside a garden shed
0x1a5  /  0x3c06  : in a cluttered garden shed
0x1a6  /  0x3c16  : beside the polluted stream
0x1a7  /  0x3c21  : at a garden gate which opens onto a paved path leading east
0x1a8  /  0x3c3f  : on a paved path which leads east-west beside the garden
0x1a9  /  0x3c5a  : in a carport with an an examination pit in the floor
0x1aa  /  0x3c76  : standing on splintered ice in a deep valley. The sky is very grey and the wind is blowing very hard
0x1ab  /  0x3ca6  : walking unsteadily across a slippery ice sheet
0x1ac  /  0x3cbf  : on very smooth ice
0x1ad  /  0x3cca  : at the edge of the ice, where drifting snow has
banked up at the foot of the mountains
0x1ae  /  0x3cf5  : where a rocky track leads up the mountain
0x1af  /  0x3d0e  : laboriously climbing the snowcovered mountain
0x1b0  /  0x3d2a  : at an armchair hollow in the mountainside, below a cave
0x1b1  /  0x3d47  : on a ledge outside an odoriferous cave
0x1b2  /  0x3d5d  : in a huge subterranean chamber with smooth walls
0x1b3  /  0x3d7a  : in the freezing cave
0x1b4  /  0x3d83  : at a junction
0x1b5  /  0x3d87  : in a silver fox lair
0x1b6  /  0x3d91  : in the silver-veined cave
0x1b7  /  0x3d9a  : in the hidden silver vault
0x1b8  /  0x3da7  : in a splendid frost chamber
0x1b9  /  0x3db7  : in a dark, eerie cave melted from slushy black ice
0x1ba  /  0x3dd8  : in the frozen forest, amidst tall, snow-laden trees
0x1bb  /  0x3df3  : in an intricate alpine garden
0x1bc  /  0x3e05  : in a miniature throne room. A crack in the ice leads south
0x1bd  /  0x3e20  :  beside a pool of icy water
0x1be  /  0x3e2c  : ankle-deep in icy water
0x1bf  /  0x3e38  : sloshing along, thigh deep in icy water which is getting deeper        
0x1c0  /  0x3e59  : swimming in freezing water
0x1c1  /  0x3e67  : standing below a small hill rising from a lush green grassy valley. There's an opening in the hillside. Far to the east is a watering hole, surrounded by grazing 
animals
0x1c2  /  0x3ebc  : west of the waterhole. The grazing animals watch you with interest: some of them look very large
0x1c3  /  0x3eed  : by a pool of muddy water. The grazing dinosaurs
walk slowly away as you approach
0x1c4  /  0x3f1d  : west of the hill
0x1c5  /  0x3f24  : on the prairie
0x1c6  /  0x3f2c  : in a deep pit, presumably an animal trap
0x1c7  /  0x3f43  : by the edge of the pit
0x1c8  /  0x3f4d  : climbing a well-worn path
0x1c9  /  0x3f5d  : on a wide ledge outside a warm cave
0x1ca  /  0x3f6d  : in a large dry cave, warmed by a blazing fire
0x1cb  /  0x3f87  : in a store cave
0x1cc  /  0x3f8f  : in the handicraft cave. The cavemen have obviously been very busy as there are lots of bone bowls and stone dishes on the floor
0x1cd  /  0x3fd3  : the junk-strewn pebble and shell room where the
cave people make cheap gifts for barter with travellers
0x1ce  /  0x400e  : in the smallest cave
0x1cf  /  0x4015  : in the painting studio. Clearly minimalism is all the rage
0x1d0  /  0x4030  : in the stone age armoury
0x1d1  /  0x403d  : in the trophy cave. Skeleton heads hang from the walls - some of them were human
0x1d2  /  0x4068  : in the treasure vault
0x1d3  /  0x4073  : crossing a wooden bridge over an exceedingly deep crevasse
0x1d4  /  0x4094  : in the invention room. You find odd scribblings
on the walls and find half-finished tools on the floor
0x1d5  /  0x40c8  : in the invention alcove: "JWAAMTETS" is enscribed high on one wall     
0x1d6  /  0x40ef  : in a small recess which sounds hollow underfoot
0x1d7  /  0x410a  : at the end of a road leading north. High stone walls block the view to 
east and west
0x1d8  /  0x4135  : at a bend in the enclosed road
0x1d9  /  0x4144  : on the road, which now cuts across a small village green. To the north 
is a small medieval ale-house with wattled walls and a thatched roof
0x1da  /  0x418e  : in the bar: a grubby room with straw on the floor - not at all the sort of place you usually frequent
0x1db  /  0x41be  : on a cobbled street leading past a dense copse to a splendid castle in 
the east
0x1dc  /  0x41e4  : at the Cobble Square west of the castle. There are pillories and stocks here, surrounded by a jeering crowd
0x1dd  /  0x421c  : in front of the imposing castle entrance. The drawbridge is raised     
0x1de  /  0x423f  : in the copse
0x1df  /  0x4245  : at the edge of the copse
0x1e0  /  0x424f  : deep in the copse
0x1e1  /  0x4257  : in the copse
0x1e2  /  0x425d  : on the north bank of the moat
0x1e3  /  0x426c  : standing in ankle deep scummy water below the south bank of the moat
0x1e4  /  0x428c  : at the castle entrance, between two tall battle-scarred towers
0x1e5  /  0x42b0  : in the courtyard within the castle walls. Battered armour and notched swords litter the blood-soaked ground. The Keep stands open to the southeast
0x1e6  /  0x42fb  : in the armoury
0x1e7  /  0x4302  : at the Keep entrance, in a small stone room
0x1e8  /  0x4316  : in a storeroom piled high with kegs and barrels
0x1e9  /  0x4332  : in the rush-strewn Great Hall
0x1ea  /  0x4340  : above a narrow flight of stairs
0x1eb  /  0x4353  : descending the steep stairs
0x1ec  /  0x435f  : in the dungeons which are dank and depressing. There's a red cross on the wall and the earth floor looks disturbed
0x1ed  /  0x4399  : on a beach in a small bay surrounded by overhanging cliffs. Breakers roll in from the sea to the north, rocking the viking longship drawn up on
the sand north of you
0x1ee  /  0x43f3  : at the edge of the sea
0x1ef  /  0x43fb  : on board the ship
0x1f0  /  0x4405  : between the sea and towering cliffs
0x1f1  /  0x4419  : on the beach. There's a cave to the southeast
0x1f2  /  0x442f  : outside a sea cave
0x1f3  /  0x4437  : in a low cave smelling of seaweed
0x1f4  /  0x444a  : in an empty cave
0x1f5  /  0x4455  : an old, musty, dry cave floored with very soft earth
0x1f6  /  0x4474  : walking along a sloping east-west passage. The ground is very damp and 
seaweed clings to the walls
0x1f7  /  0x44a8  : further along the damp passage, beside the entrance to a small cave    
0x1f8  /  0x44c8  : in an obnoxious cave deep down in the rocks, beside a slimy little pool0x1f9  /  0x44ec  :
0x1fa  /  0x44ed  : in a hands and knees crawl. An opening slopes down to the north        
0x1fb  /  0x4510  :
0x1fc  /  0x4511  : at a junction of the tunnel and a vertical fissure
0x1fd  /  0x4529  :
0x1fe  /  0x452a  : in a tight fissure
0x1ff  /  0x4535  : above the hole in a cave which shows signs of habitation: the ashes from a recent fire smoulder
acridly
0x200  /  0x4571  : in the pirate's hideout
0x201  /  0x457d  : in the large, empty chest
0x202  /  0x458b  : in the entrance porch of an impressive country house with exposed oak beams
0x203  /  0x45b7  : in a u-shaped hallway with doors to east and west. A magnificent staircase sweeps upwards to a gallery above
0x204  /  0x45f4  : at the north end of the banqueting hall
0x205  /  0x4605  : at the south end of the hall
0x206  /  0x460f  : at the north end of a long room used for relaxation
0x207  /  0x462a  : at the south end of the long room, between two tables
0x208  /  0x4644  : at the top of the stairway, in the minstrel's gallery. A short staircase leads up
0x209  /  0x4669  : climbing the short stairs. Several wall panels sound hollow
0x20a  /  0x468b  : in the middle of a long east-west portrait gallery. Leaded windows overlook the beautiful knot gardens below
0x20b  /  0x46cb  : at the west end of the portrait gallery
0x20c  /  0x46de  : in a bedroom with a four poster bed
0x20d  /  0x46f0  : in the bedroom of the master of the house
0x20e  /  0x4701  : at the east end of the long gallery
0x20f  /  0x4710  : in a bedroom, hung about with lavender
0x210  /  0x4726  : in the music room
0x211  /  0x472e  : in a hedge maze
0x212  /  0x4736  : in a hedge maze
0x213  /  0x473e  : in a hedge maze
0x214  /  0x4746  : in a hedge maze
0x215  /  0x474e  : in the middle of the maze
0x216  /  0x4758  : in a hedge maze
0x217  /  0x4760  : in a hedge maze
0x218  /  0x4768  : in a hedge maze
0x219  /  0x4770  : in a hedge maze
0x21a  /  0x4778  : down the well, within reach of the water
0x21b  /  0x478d  : on a road leading north through the gates of a walled city
0x21c  /  0x47aa  : outside the north entrance of an amphitheatre: an enormous circular building of gleaming marble
and decorated with heroic statues. You can hear
the roar of the crowds inside
0x21d  /  0x4806  : just inside the gates, at a junction
0x21e  /  0x4813  : on the steps of a small temple. Stone columns support the lintel over its doorway
0x21f  /  0x4840  : inside the temple, which contains shrines to many gods
0x220  /  0x485e  : at a road junction
0x221  /  0x4865  : in a spartan barracks, beside an iron-bound locker
0x222  /  0x4883  : inside the locker where soldiers store their weapons
0x223  /  0x489d  : on a long straight road north from the gatehouse. Around you are the buildings of a small garrison town
0x224  /  0x48d4  : in the forum: an open courtyard surrounded by buildings
0x225  /  0x48f5  : in the market, at a vegetable stall. Ladies, wearing long flowing robes gathered at the waist and clasped at the shoulder, are jostling to get the best buy       
0x226  /  0x4941  : in the market, at a bread stall
0x227  /  0x4950  : in a butcher's shop
0x228  /  0x495d  : outside a tavern
0x229  /  0x4965  : in the deserted treasury
0x22a  /  0x4970  : in the arena of the amphitheatre, surrounded by
an immense cheering crowd
0x22b  /  0x4996  : in the south end of the caldarium. Steps lead down into a great square 
bath decorated with dolphin mosaics
0x22c  /  0x49ce  : beside a stone dolphin which pours out cold water
0x22d  /  0x49e8  : in the hot baths
0x22e  /  0x49f1  : in the hypocaust
0x22f  /  0x49f9  : in the hypocaust
0x230  /  0x4a01  : in the hypocaust
0x231  /  0x4a09  : in the hypocaust
0x232  /  0x4a11  : in the hypocaust
0x233  /  0x4a19  : in the hypocaust
0x234  /  0x4a21  : on a flat rocky plain which stretches for miles. It is covered by fine 
grey dust. The night air
is cold. Luminous walkways travel east and west
0x235  /  0x4a74  : at a walkway junction
0x236  /  0x4a7d  : at the Intergalactic Bureau-de-Change
0x237  /  0x4a95  : at the foot of the Milky Way, a long sparkling pathway which climbs up 
into space
0x238  /  0x4ac3  : halfway up the Milky Way
0x239  /  0x4ad4  : at the top of the Milky Way, amidst brightly twinkling stars
0x23a  /  0x4af6  : lost among the stars
0x23b  /  0x4b00  : on a walkway south. A neon sign flashes "Walkway to Mars"
0x23c  /  0x4b21  : at a walkway junction on the grey plain
0x23d  /  0x4b31  : at the end of the north walkway. If you continue it will be on foot    
0x23e  /  0x4b55  : standing on a floating metal platform, suspended in mid-air. To the north is a starship
0x23f  /  0x4b82  : inside the starship
0x240  /  0x4b8a  : in a green sleep room
0x241  /  0x4b97  : in a space swimming pool, splashing around on a 
colossal water drop which wobbles in mid-air
0x242  /  0x4bcb  : in a control room, surrounded by instrument panels
0x243  /  0x4be8  : on the edge of a wide crater
0x244  /  0x4bf6  : in a dull, lifeless crater. High up the west wall is an opening        
0x245  /  0x4c1b  : in a colossal habidome
0x246  /  0x4c29  : in a long room. A guard stands beside each door
0x247  /  0x4c43  : in the alcove room. Only one alcove is open
0x248  /  0x4c5a  : in a cubicle
0x249  /  0x4c62  : in a room with no roof. An opening is visible far above
0x24a  /  0x4c81  : outside a sports and aerobotics arena
0x24b  /  0x4c96  : beside a deep tropical pool
0x24c  /  0x4ca3  : in a dark, dingy hole between a ladder and a low tunnel
0x24d  /  0x4cc1  : in the fencing hall
0x24e  /  0x4cc9  : in a robot repair shop
0x24f  /  0x4cd7  : in a fair field full of flowers. Butterflies flitter happily in the bright sunshine and a heady
perfume fills the air. You could be in paradise
0x250  /  0x4d24  : in front of an ugly arch: "ABANDON HOPE ALL YE WHO ENTER HERE"
0x251  /  0x4d59  : in the Ruined Land. Where trees and grasses once grew is a smouldering 
wasteland and the sun hangs low as a huge ball of red fire. The heat is terrible and the ground below your feet quivers as though in agony
0x252  /  0x4dc6  : amidst the smoking ruins of a small village
0x253  /  0x4ddb  : on the brink of a deep crack
0x254  /  0x4dea  : at the bottom of a deep, earthy pit. The walls are too crumbly to climb0x255  /  0x4e0e  : in a stifling maze of decayed earthy passages
0x256  /  0x4e25  : in a putrescent chamber
0x257  /  0x4e33  : at a junction between foul passages
0x258  /  0x4e45  : in a square white room, some sort of experimental laboratory
0x259  /  0x4e68  : in a worse laboratory
0x25a  /  0x4e74  : in a room full of strange plants which grab at you. One flower is enormous
0x25b  /  0x4e9f  : inside the plant. Sharp hairs block your escape
and the walls ooze digestive juices
0x25c  /  0x4ecc  : climbing down a sticky tube
0x25d  /  0x4edd  : inside the tangled roots of the giant plant
0x25e  /  0x4ef1  : in a low, earthy tunnel
0x25f  /  0x4efe  : at the end of the earthy tunnel. Crude steps lead upwards
0x260  /  0x4f1c  : climbing steep, treacherous stairs
0x261  /  0x4f2f  : squeezing your way up the narrow stairs
0x262  /  0x4f45  : at the top of the stairs. You can feel a trapdoor above
0x263  /  0x4f5f  : under a long table. Seated round it are nine men, presumably the Evil Timelords
0x264  /  0x4f8f  : standing behind the Evil Timelords as they discuss their evil plans    
0x265  /  0x4fb5  : at a dark dead end
0x266  /  0x4fc0  : at a dark dead end
0x267  /  0x4fcb  : at a dark dead end
0x268  /  0x4fd6  : at a crossing of country roads
0x269  /  0x4fe7  : on a long, straight road. To the west, it shimmers and fades away      
0x26a  /  0x500d  : on a long road. It fades to mist in the east
0x26b  /  0x5023  : lost in the mists of time
0x26c  /  0x502f  : A water scorpion bites you!
0x26d  /  0x5040  : A giant squid attacks!
0x26e  /  0x5050  : Seaweed engulfs you!
0x26f  /  0x505f  : This walkway is under construction and collapses!
0x270  /  0x507d  : Would you like to be resurrected?
0x271  /  0x5092  : Sorry, the sand's run out
0x272  /  0x50a1  : Clouds of sand billow up...


0x273  /  0x50b3  : Into the cauldron!
0x274  /  0x50bf  :

The recipe is complete! Your surroundings fade
away as the structure of time is repaired. You have won!


0x275  /  0x50fa  :
0x276  /  0x50fb  : A symbol of peace
0x277  /  0x5107  : Solid gold. Very Valuable!
0x278  /  0x5118  : A floppy, red and blue cap with bells attached
0x279  /  0x5134  : A 68006, I think
0x27a  /  0x5141  : "This box contains an evil eye;

if opened, you would surely die!"
0x27b  /  0x516c  : It sparkles brightly
0x27c  /  0x5178  : Heavy, but very valuable
0x27d  /  0x5189  : Too small for flying!
0x27e  /  0x5196  : Large, warm and leathery
0x27f  /  0x51a3  : Yeuch!
0x280  /  0x51aa  : Just your size
0x281  /  0x51b5  : Delicious, if you like that sort of thing
0x282  /  0x51cd  : Marked with a skull
0x283  /  0x51d9  : They seem fresh-cut
0x284  /  0x51e7  : A complete set of playing cards
0x285  /  0x51fa  : Hand-embroidered
0x286  /  0x5207  : Very valuable!
0x287  /  0x5210  : Real Ale, of course
0x288  /  0x521d  : Cute
0x289  /  0x5221  : The keys are of all sizes
0x28a  /  0x522f  : An ordinary asbestos glove
0x28b  /  0x5240  : A great ox-horn, bound with gold
0x28c  /  0x5255  : The sands have almost run through!
0x28d  /  0x5269  : Nothing special
0x28e  /  0x5273  : A weapon
0x28f  /  0x5279  : Cor! You look prettier every day
0x290  /  0x528c  : A mediaeval guitar
0x291  /  0x529a  :  matches are left
0x292  /  0x52a6  : I dunno what this does!
0x293  /  0x52b6  : "Hope village"
0x294  /  0x52c1  : The mirror seems to expand, sucking you in!
0x295  /  0x52da  : A fine example of stone age work
0x296  /  0x52ed  : Extremely delicate
0x297  /  0x52f8  : A colourful souvenir
0x298  /  0x5306  : Delicious pastries
0x299  /  0x5311  : A magical herb
0x29a  /  0x531c  : The first hard disc!
0x29b  /  0x5327  :
0x29c  /  0x5328  : A general-purpose axe
0x29d  /  0x5336  : Small and dainty
0x29e  /  0x5340  : It's full
0x29f  /  0x5347  : Solid silver
0x2a0  /  0x534d  : Wax
0x2a1  /  0x5351  :
0x2a2  /  0x5352  : It seems to diffract light oddly
0x2a3  /  0x5367  : Heavy and viscious-looking
0x2a4  /  0x537a  : Warm, course fur, rather smelly
0x2a5  /  0x538f  : Empty, but bejewelled
0x2a6  /  0x53a1  : Very small, very thin and very old
0x2a7  /  0x53ae  : Wow!
0x2a8  /  0x53b2  : Very big!
0x2a9  /  0x53b8  :
0x2aa  /  0x53b9  : a carved tiger
0x2ab  /  0x53c2  : It glows brightly
0x2ac  /  0x53cd  : Spiced bread with pickles
0x2ad  /  0x53dd  : A black metal disc with a gold edge
0x2ae  /  0x53f2  : It shows the picture of a jester
0x2af  /  0x5401  :
0x2b0  /  0x5402  : A chunk of metallic ore
0x2b1  /  0x5411  : A musical instrument made from a horn
0x2b2  /  0x5428  : To the sunset
you must go,

keeping high and never low.

In a sheltered, hidden cove

you will find a treasure trove.

Pitfalls you are sure to meet,

you may even get wet feet!,

but in the end you're sure to
greet

that dreadful scoundrel, Pirate Pete!
0x2b3  /  0x54bd  : Well padded
0x2b4  /  0x54c6  : Tough ropes with lead weights round the edge
0x2b5  /  0x54e0  : Very valuable
0x2b6  /  0x54e8  : A tin-opener of the "butterfly" type
0x2b7  /  0x54ff  : Painted white, with black eye-markings
0x2b8  /  0x551a  : Glass
0x2b9  /  0x551e  : For hacking at hard material
0x2ba  /  0x552d  : The planks are sturdy wood
0x2bb  /  0x553c  : a grapple-firing rocket
0x2bc  /  0x554b  : A short hessian rope
0x2bd  /  0x5557  : The ruby acts as a lense
0x2be  /  0x5564  : If worn, the backpack should help you carry more
0x2bf  /  0x5581  : Magical winged shoes!
0x2c0  /  0x5590  : Battered and rusty
0x2c1  /  0x559b  : A most unusual object!
0x2c2  /  0x55ac  : Kattomush: "Maiow-thwatering goodness for Kitty"
0x2c3  /  0x55cd  : a lethal weapon
0x2c4  /  0x55d6  : A small, valuable vase
0x2c5  /  0x55e3  : It is in poor shape
0x2c6  /  0x55ee  :
0x2c7  /  0x55ef  : Water? Where?
0x2c8  /  0x55f9  : Pete blocks you
0x2c9  /  0x5601  : Ghostly footsteps plod to the short stairs and fade away
0x2ca  /  0x5622  : A panel moves!
0x2cb  /  0x562c  : A jester appears: "The Lord of Misrule is angry
for I have lost one of the tools of my trade. Have you seen it?"
0x2cc  /  0x566d  : The god Mercury appears and solemnly hands you a pair of winged sandals0x2cd  /  0x5697  : "SHOW SOME RESPECT!"
0x2ce  /  0x56ac  : It's very good
0x2cf  /  0x56b5  : The skeleton collapses in a heap of dry bones
0x2d0  /  0x56d0  : The skeleton blocks you
0x2d1  /  0x56de  : The vile caveman is knocked off the bridge. The
rescued woman thanks you profusely and presses something into your hand
0x2d2  /  0x5720  : You receive 6,000,000 volts up the arm
0x2d3  /  0x573a  : The narcissus bends away, sadly, "I'm doomed to
spend my life admiring my reflection. But this water's so dirty that I can hardly see to admire
my beautiful face in it."
0x2d4  /  0x57a2  : "Oy! Pay for that!"
0x2d5  /  0x57b1  : Shame on you! You're in the stocks now!
0x2d6  /  0x57c7  : The Black Knight is in the way
0x2d7  /  0x57ce  : The ground is too hard
0x2d8  /  0x57da  : The ground under your feet gives way
0x2d9  /  0x57ef  : I don't really want that, but thanks!
0x2da  /  0x5806  : It rolls away
0x2db  /  0x580e  : The chest opens and a bearded rogue leaps out: "Ahoy there me hearty! Oi be Pirate Pete what gets me pleasure from robbing weary travellers like thee!"


0x2dc  /  0x5866  : You've nothing left to steal! Pirate Pete is furious..
0x2dd  /  0x5885  : The stone blocks you
0x2de  /  0x5890  : The dogs turn up their cultured noses
0x2df  /  0x58a9  : A gladiator steals the buckle and runs south to
the arena!
0x2e0  /  0x58c9  : It comes loose
0x2e1  /  0x58d1  : You're not strong enough
0x2e2  /  0x58e1  : The grating blocks you
0x2e3  /  0x58ed  : It entangles the lion
0x2e4  /  0x58f7  : The trident pins the net in place, holding the lion securely
0x2e5  /  0x5914  : The gladiator is too quick for you - he blocks your escape
0x2e6  /  0x5933  : The hot star burns you!
0x2e7  /  0x5941  : The gauntlet finally catches fire!

0x2e8  /  0x5958  : The water cools the star in a hissing of steam
0x2e9  /  0x596c  : "YOU'RE NOT AUTHORISED TO DO THAT!"
0x2ea  /  0x5990  : There's nothing to break your fall
0x2eb  /  0x59a2  : The mattress breaks your fall
0x2ec  /  0x59b2  : and you climb its rope
0x2ed  /  0x59c0  : The components are too minute to see
0x2ee  /  0x59d3  : Your lightsabre makes short work of the cyberman
0x2ef  /  0x59f2  : The rocket shoots up

0x2f0  /  0x59ff  : but falls back
0x5a09
0x5c17
The decompression of this is quite straightforward - most letters are just there if they weren't common fragments so the rules are:
1. If the byte value is < $5E and the byte value is > $02, it's a printable ascii letter when you add $1D to it
2. If the byte value is >= $5E then the it's a common word fragment and it needs to be looked up but when found these same rules apply (so there could be words that contain word fragments that contain word fragments). Recursion back in the day...

For looking up the different word fragments:
1. There can be a maximum I think of $FF - $5E word fragments (at least for my Lords of Time) - so 161?
2. So to figure out which word fragment you need fragment = code - $5E
3. You then loop through the data block that starts at $5A0B looking for the start of the nth common word fragment - each common word fragment is separated by a $01 and the block ends when the first $00 is found.
4. Then the first set of rules apply

Andy
melchett
Posts: 478
Joined: Tue Jan 28, 2003 9:52 am
Contact:

Re: Lords of Time Disassembly

Post by melchett »

fuzzel wrote: Thu Feb 17, 2022 4:11 pm ... I've decided to have a crack at understanding Lords of Time by Level 9...
This is as far as I have reached with my Level 9 Lords of Time Python interpreter/parser

It has a couple of bugs I need to track down but mostly it's working which I'm pretty pleased about.

(I know I need to work on nice word wrapping and the redundant new line characters, but that's cosmetic so it'll come last).

Andy
User avatar
KenLowe
Posts: 4675
Joined: Mon Oct 18, 2004 5:35 pm
Location: UK
Contact:

Re: Lords of Time Disassembly

Post by KenLowe »

Looks good!
fuzzel
Posts: 1191
Joined: Sun Jan 02, 2005 1:16 pm
Location: Cullercoats, North Tyneside
Contact:

Re: Lords of Time Disassembly

Post by fuzzel »

Wow! I'll have a detailed look through your posts a bit later on. From what I can gather Level 9 have used the standard method of taking a text message and compressing it by utilising spare ascii codes (max 256) to create a dictionary of oft-used words (word fragments as you more accurately call them). So if I take the first of these compressed phrases as an example from your post above, "I don't understand" at &2110 "2C 9E 86 0A 7F 58 51 E8 8E 85 47 01" with 01 being the end byte:
&2C - "I" - CHR$(&2C+&1D)
&9E - word fragment number &9E-&5E=&40 or 64
&86 - word fragment number &86-&5E=&28 or 40
&0A - "'" (apostrophe)- CHR$(&0A+&1D)
&7F - word fragment number &7F-&5E=&21 or 33
&58 - "u"- CHR$(&58+&1D)
&51 - "n"- CHR$(&51+&1D)
&E8 - word fragment number &E8-&5E=&8A or 138
&85 - word fragment number &9E-&5E=&27 or 39
&47 - "d"- CHR$(&47+&1D)
&01 - end byte
I can therefore deduce that word fragment &21 or 33 is "t "
Sure enough, looking up the 33rd occurrence of 01 from &5A0B onwards gives at &5A80 - "57 03 01"
&57 - "t" - CHR$(&57+&1D)
&03 - " " - CHR$(&03+&1D)
&01 - end byte
Hey presto! Looking forward to seeing what else you come up with.
melchett
Posts: 478
Joined: Tue Jan 28, 2003 9:52 am
Contact:

Re: Lords of Time Disassembly

Post by melchett »

fuzzel wrote: Wed Feb 23, 2022 1:54 pm Wow! I'll have a detailed look through your posts a bit later on. From what I can gather Level 9 have used the standard method of taking a text message and compressing it by utilising spare ascii codes (max 256) to create a dictionary of oft-used words (word fragments as you more accurately call them). So if I take the first of these compressed phrases as an example from your post above, "I don't understand" at &2110 "2C 9E 86 0A 7F 58 51 E8 8E 85 47 01" with 01 being the end byte:
&2C - "I" - CHR$(&2C+&1D)
&9E - word fragment number &9E-&5E=&40 or 64
&86 - word fragment number &86-&5E=&28 or 40
&0A - "'" (apostrophe)- CHR$(&0A+&1D)
&7F - word fragment number &7F-&5E=&21 or 33
&58 - "u"- CHR$(&58+&1D)
&51 - "n"- CHR$(&51+&1D)
&E8 - word fragment number &E8-&5E=&8A or 138
&85 - word fragment number &9E-&5E=&27 or 39
&47 - "d"- CHR$(&47+&1D)
&01 - end byte
I can therefore deduce that word fragment &21 or 33 is "t "
Sure enough, looking up the 33rd occurrence of 01 from &5A0B onwards gives at &5A80 - "57 03 01"
&57 - "t" - CHR$(&57+&1D)
&03 - " " - CHR$(&03+&1D)
&01 - end byte
Hey presto! Looking forward to seeing what else you come up with.
Perfect and a good example you show above. And this has actually made my day Fuzzel - I managed to explain something, that's relatively complex, clearly for another person to just pick up and understand!
melchett
Posts: 478
Joined: Tue Jan 28, 2003 9:52 am
Contact:

Re: Lords of Time Disassembly

Post by melchett »

fuzzel wrote: Wed Feb 23, 2022 1:54 pm Hey presto! Looking forward to seeing what else you come up with.
There are so other print rules too given you got this far:
1. If it's a "%" then change it to CR 0x0D
2. If it's a "_" then change it to a space 0x20

Also some rules about not displaying a word if it cannot fit on a line (pretty self explanatory in the code) and only applying a CR if there's more than 2 characters in the message.
fuzzel
Posts: 1191
Joined: Sun Jan 02, 2005 1:16 pm
Location: Cullercoats, North Tyneside
Contact:

Re: Lords of Time Disassembly

Post by fuzzel »

I've knocked up a little basic program to print the messages based on your rules. Just *LOAD TIME4 and TIME5 into memory, set PAGE=&E00 then NEW then type it in and run. It's a little bit untidy in places but seems to do the trick. Note that I've gone as high as &5A00, not sure if I need to go a bit further. I've had to copy PROCD to PROCE because sometimes a bit of recursion occurs and there are fragments within fragments. Hopefully this only occurs once and not several times. I read somewhere that Level 9 managed to squeeze Colossal Adventure and Adventure Quest into 16k by doing several recursions but what it would gain in memory savings it would lose in speed. Hopefully one of these 16k versions will show up and we can see if that's the case. Or perhaps someone could take the full text and create a multi-recursive version that does just that. Now there's a challenge...

Code: Select all

1FORA%=&2110TO&5A0A 
2IF?A%=8THENPRINTCHR$13:NEXTA%
3IF?A%=66THENPRINTCHR$32:NEXTA% 
4IF?A%=1THENPRINT:NEXTA%
5IF?A%<&5E THENPRINTCHR$(?A%+&1D);
6IF?A%>=&5E THENPROCD 
7NEXTA% 
19END
20DEFPROCD 
21Y%=0 
22Z%=&5A0B:REPEAT
23Z%=Z%+1:IF?Z%=1THENY%=Y%+1 
24UNTILY%=(?A%-&5E)
25X%=Z%:REPEAT 
26IF?X%=8THENPRINTCHR$13;:GOTO29 
27IF?X%=66THENPRINTCHR$32;:GOTO29
28IF?X%<&5E AND?X%>2 THENPRINTCHR$(?X%+&1D); 
29IF?X%>=&5E THENPROCE 
30X%=X%+1
31UNTIL?X%=1 
32ENDPROC
40DEFPROCE 
41C%=0 
42D%=&5A0B:REPEAT
43D%=D%+1:IF?D%=1THENC%=C%+1 
44UNTILC%=(?X%-&5E)
45B%=D%:REPEAT 
46IF?B%=8THENPRINTCHR$13;:GOTO29 
47IF?B%=66THENPRINTCHR$32;:GOTO29
48IF?B%<&5E AND?B%>2 THENPRINTCHR$(?B%+&1D); 
49REM
50B%=B%+1
51UNTIL?B%=1
52ENDPROC
melchett
Posts: 478
Joined: Tue Jan 28, 2003 9:52 am
Contact:

Re: Lords of Time Disassembly

Post by melchett »

fuzzel wrote: Wed Feb 23, 2022 4:24 pm Note that I've gone as high as &5A00, not sure if I need to go a bit further.
The messages data block is terminated with a $00 so when you hit that byte you can stop. It goes higher on my disk version, if you look at my dump of the messages from earlier you can see the addresses (first column is just cardinal number, second is the starting byte's memory address).
fuzzel wrote: Wed Feb 23, 2022 4:24 pm I read somewhere that Level 9 managed to squeeze Colossal Adventure and Adventure Quest into 16k by doing several recursions but what it would gain in memory savings it would lose in speed.
They must have experimented with what was acceptable for each platform - the BBC's speed is quite pleasing as it unpacks in front of you. I never felt it was a problem or too slow. But yes, every time there is a word fragment token, it has to rescan from the beginning which adds a great deal of time per layer of recursion.

You'll be amazed at the number of "commands" that are executed by the virtual machine especially at start up. And that's multiple by differing amounts per command as the "6502 engine" works hards to do the work the virtual machine requested. Understanding the 6502 engine is one part - understanding the virtual machine "game code" quite another thing altogether. They MUST have had some higher level programming tool than we see in the virtual machine - that tied together the dictionary, the location information, the description and the variables. I hope that isn't lost to the world.
melchett
Posts: 478
Joined: Tue Jan 28, 2003 9:52 am
Contact:

Re: Lords of Time Disassembly

Post by melchett »

I'm sure you were all on tenterhooks - this is the Python interpreter running with a full game script of Lords of Time from a file as input. It's a thrilling watch.

I had forgotten how good the writing and text was in the adventure and the details of many of the "zones". Not sure what's missing in the script as it only reaches 975/1000 - wonder if it was possible to get a maximum score.

Looks flawless though (word wrapping and superfluous newlines aside). So a little more tidy up and I can release this - just wanted something scripted and portable without having to recompile something every time, hence the Level 9 Lords of Time Python interpreter/parser.
fuzzel
Posts: 1191
Joined: Sun Jan 02, 2005 1:16 pm
Location: Cullercoats, North Tyneside
Contact:

Re: Lords of Time Disassembly

Post by fuzzel »

Very nicely done indeed. Have you checked your solution against the one on CASA?
melchett
Posts: 478
Joined: Tue Jan 28, 2003 9:52 am
Contact:

Re: Lords of Time Disassembly

Post by melchett »

Some interesting stats:
  • Just to initialise the virtual machine and display the intro text for the Lords of Time, it executes 942 A-code opcodes.
  • But then to move North from the initial location, it's another 2,091 A-code opcodes
  • And to complete the game (I think optimally) takes 684,997 A-code opcodes
Most of those in loops in the A-code - but still, that's all then multiplied up by the 6502 used to implement them. Impressive stuff.
melchett
Posts: 478
Joined: Tue Jan 28, 2003 9:52 am
Contact:

Re: Lords of Time Disassembly

Post by melchett »

fuzzel wrote: Wed Feb 23, 2022 8:10 pm Very nicely done indeed. Have you checked your solution against the one on CASA?
No, just lifted the one v1 solution from the David Kinder site I found earlier today and wrote a quick input parser for it. I'll look at CASA another day, thanks for the suggestion. Just wanted something that worked somehow through to the end without me remembering how to play it all again.

EDIT: Looking now, they look identical (Jacob Guinness 1990). Wonder if I have a bug or if that only gives 975... or if my version is a pre-release or early version. There are some oddities in the words that aren't there in the bbcmicro.co.uk versions e.g. "4tches are left" for "4 matches are left", "agaig" rather than "again" in the dictionary, the description of the picture has a typo "youn" instead of "you" when examining the picture of "a kindly old man" at the start, "SCORE/" in the dictionary, "AFFERMATIVE" and a few others.

Code: Select all

0xc0  /  0x291c  : The picture comes to life: "I am Father Time and I have chosen youn to help defend history against 9 evil Timelords. You must collect 9 items, each marked with an hourglass. Good Luck!"

0x291  /  0x529a  :  matches are left  <--- correct so engine issue

0x14  /  0x1220 AGAIG

0x1d  /  0x138e SCORE/

0x1e  /  0x1399 AFFERMATIVE

Will check against the STH versions (is there a library somewhere of official disk or tape rips?)

Also, one lovely Easter Egg in the dictionary is the presence of these two synonyms:

Code: Select all

0x9c  /  0x181e CATFOOD
0x9c  /  0x1826 KATTOMUSH
fuzzel
Posts: 1191
Joined: Sun Jan 02, 2005 1:16 pm
Location: Cullercoats, North Tyneside
Contact:

Re: Lords of Time Disassembly

Post by fuzzel »

With reference to my little basic program to print the messages I've just downloaded Colossal Adventure to &E00 and got my program to print the messages for that too. I just changed &2110 to &2860 and &5A0B to &70B7 so the compression system appears to be largely unchanged for the first few years. It needs a few tweaks to work properly though...
col.png
fuzzel
Posts: 1191
Joined: Sun Jan 02, 2005 1:16 pm
Location: Cullercoats, North Tyneside
Contact:

Re: Lords of Time Disassembly

Post by fuzzel »

melchett wrote:
I also wrote a Python script to pull out the descriptions - again it's quite clever as each location description is a composite of many of these depending on the state of the room and the objects within it.
I'm having a look at the code again today, is there a byte anywhere storing the location number? I haven't been able to find it so far.
melchett
Posts: 478
Joined: Tue Jan 28, 2003 9:52 am
Contact:

Re: Lords of Time Disassembly

Post by melchett »

fuzzel wrote: Sat Feb 26, 2022 10:24 am I'm having a look at the code again today, is there a byte anywhere storing the location number? I haven't been able to find it so far.
It doesn't do it like that unfortunately.... each string fragment is referenced by a constant from the virtual machine code or from a variable in the variable area. Regardless of variable or constant source, it uses that number to find the "nth" string fragment and pulls together many fragments for a room location based on the code doing the following:
1. Adding a common starting sentence such as "You are"
2. Then adding a room description like "in a large cold looking room"
3. Then adding a full stop and maybe a new line
4. Then adding a constant like "You can see"
5. Then adding "object 1" such as "a matchbox" then adding a comma if more than one object left other wise an "and"
6. Then adding more constants such as "Exists are" then looping through the available exits and adding (with qualifiers if there is a state such a door opened or closed).

I'm feeling MUCH better today so I added some bits to github - my python extractors for dictionaries and descriptions can be found there.

BBC Micro Level 9 Version 1 A-Code Dictionary and Description Extractors

I'll add the parser for Lords of Time later this weekend I hope - just want to tidy it up a bit before another human can see it...
fuzzel
Posts: 1191
Joined: Sun Jan 02, 2005 1:16 pm
Location: Cullercoats, North Tyneside
Contact:

Re: Lords of Time Disassembly

Post by fuzzel »

Hi melchett, I'm glad you're feeling better, I did wonder why you'd disappeared for a few days! I've just been looking at your dictionaries and I very much hope there's more to come. I've been taking a look at the messages for Colossal Adventure using my own little basic extractor program which was based on your tips on how the fragments dictionary / decompression system worked. I reckon Level 9 managed a 52% level of compression for text, which, as a comparison is slightly better than my 56% for Urban Upstart, although given it's at least three times the size of my game I assumed it would be a lot better (but then I have the advantage of 30 years of improvements in memory and processor speeds). What's incredibly impressive about the Level 9 games is not text compression but this virtual a-code system they had for the game coding (handling nouns, verbs, movements, objects etc). Colossal has 8.8k of non-message code whilst Urban Upstart has more but given their game is 3-4 times the size of mine that is seriously impressive. I'm hoping you can enlighten me some more in the coming days about how the heck it all works. And hopefully you'll be publishing the dictionaries for their other games as well.
User avatar
8bitAG
Posts: 180
Joined: Wed Nov 07, 2018 5:03 pm
Contact:

Re: Lords of Time Disassembly

Post by 8bitAG »

Just adding a link to the fact that there's a parallel discussion going on at the IF forums - https://intfiction.org/t/specification- ... code/51478

...where a few things are mentioned, such as the fact that Mike Austin may eventually be making the Level 9 material, such as the A-Code tools, available on GitHub.

There's also a link to this work on decoding the Level 9 format and creating an interpreter, here:
https://github.com/heasm66/L9Terp
Post Reply

Return to “8-bit acorn software: classic adventure games”