public override GameLevel GetLevel(int n) { if (n < 1 || n > levelCount) { throw new ArgumentException("Level outside of range"); } GameLevel gameLevel = null; try { int offset = GetLevelOffset(n); chipDat.Seek(offset); int numBytesLevel = chipDat.ReadUnsignedWord(); // So we don't have to skip over the same level again later levelOffsets[n + 1] = offset + numBytesLevel + 2; int levelNumber = chipDat.ReadUnsignedWord(); int numSeconds = chipDat.ReadUnsignedWord(); int numChipsNeeded = chipDat.ReadUnsignedWord(); int mapDetail = chipDat.ReadUnsignedWord(); gameLevel = new GameLevel(32, 32, numChipsNeeded, numSeconds, levelNumber); int numberOfBytesLayer1 = chipDat.ReadUnsignedWord(); ReadLayer(gameLevel, numberOfBytesLayer1, 1); // Layer 1, upper int numberOfBytesLayer2 = chipDat.ReadUnsignedWord(); ReadLayer(gameLevel, numberOfBytesLayer2, 0); // Layer 2, lower int numBytesOptional = chipDat.ReadUnsignedWord(); int numOptionalBytesRead = 0; while (numOptionalBytesRead < numBytesOptional) { int fieldType = chipDat.ReadUnsignedByte(); int sizeOfField = chipDat.ReadUnsignedByte(); numOptionalBytesRead += 2; switch (fieldType) { case 0x03: // Map title sbyte[] ASCIITitle = new sbyte[sizeOfField - 1]; chipDat.ReadFully(ASCIITitle); string title = StringHelperClass.NewString(ASCIITitle, "ASCII"); gameLevel.MapTitle = title; chipDat.SkipBytes(1); break; case 0x04: // Brown buttons to traps for (int i = 0; i < sizeOfField / 10; i++) { int buttonX = chipDat.ReadUnsignedWord(); int buttonY = chipDat.ReadUnsignedWord(); int trapX = chipDat.ReadUnsignedWord(); int trapY = chipDat.ReadUnsignedWord(); // Locate button BlockContainer bc = gameLevel.GetBlockContainer(buttonX, buttonY); Block button = bc.Find(Type.BROWNBUTTON); // Locate trap bc = gameLevel.GetBlockContainer(trapX, trapY); Block trap = bc.Find(Type.TRAP); if (button != null && trap != null) // Perhaps throw an exception otherwise { Buttons.AddBrownButtonListener(button, trap); } chipDat.SkipBytes(2); } break; case 0x05: for (int i = 0; i < sizeOfField / 8; i++) { int buttonX = chipDat.ReadUnsignedWord(); int buttonY = chipDat.ReadUnsignedWord(); int clonerX = chipDat.ReadUnsignedWord(); int clonerY = chipDat.ReadUnsignedWord(); // Locate button BlockContainer bc = gameLevel.GetBlockContainer(buttonX, buttonY); Block button = bc.Find(Type.REDBUTTON); // Locate cloner bc = gameLevel.GetBlockContainer(clonerX, clonerY); Block cloner = bc.Find(Type.CLONEMACHINE); if (button != null && cloner != null) // Perhaps throw an exception otherwise { Buttons.AddRedButtonListener(button, cloner); } } break; case 0x06: // Password string password = ReadPassword(sizeOfField); gameLevel.Password = password; passwordToLevel[password] = n; levelToPassword[n] = password; chipDat.SkipBytes(1); break; case 0x07: // Hint sbyte[] ASCIIHint = new sbyte[sizeOfField - 1]; chipDat.ReadFully(ASCIIHint); string hint = StringHelperClass.NewString(ASCIIHint, "ASCII"); gameLevel.Hint = hint; chipDat.SkipBytes(1); break; case 0x0A: // Movement for (int i = 0; i < sizeOfField / 2; i++) { int creatureX = chipDat.ReadUnsignedByte(); int creatureY = chipDat.ReadUnsignedByte(); Block creature = null; BlockContainer bc; Block upper; // Locate creature bc = gameLevel.GetBlockContainer(creatureX, creatureY); upper = bc.Upper; if (upper.Creature) { creature = upper; } if (creature != null) // Perhaps throw an exception otherwise { Creatures.AddCreature(creature); } } break; default: chipDat.SkipBytes(sizeOfField); break; } numOptionalBytesRead += sizeOfField; } } catch (Exception ex) { Debug.WriteLine(ex.ToString()); Debug.Write(ex.StackTrace); Debug.WriteLine("While loading level: " + ex.Message); } return(gameLevel); }