the cutting room mirror

Magic Carpet (DOS)

This article has a talk page!
view on tcrf.net

This page contains notes for the game Magic Carpet (DOS).

Level.Dat Data Structures#

Included with the files of the original CD release of Magic Carpet is a file called GAM00088.DAT. This is an invaluable and interesting file for reverse engineering as it's some kind of internal format used to save the details of an unfinished map. Specifically, this seems to be the raw contents of the map LEV00088.DAT, based on the corresponding .inf file for that cut level (which made it into the game as level 65).

What's so useful is that the map includes headers for the data, therefore naming each attribute. Just as importantly, it also lists the map generator parameters. Magic Carpet is interesting, as while it includes the "MAPHACK" tool to generate height map levels out of user pictures, the game does NOT store height maps in the final levels. In fact they are all procedurally generated on runtime from a set of parameters stored in the level file. Note all levels are of a fixed size (38KB), and pad out any unused space with zero byte entries.

Map Header and Generation Parameters#

These begin from the very first byte of each level file up to position 2e. Names are mostly from GAM00088.DAT file, which only begins from the Seed attribute. Note most of the later attributes only seem to work with one byte, higher values seem to crash the game (like rivers).

Variable

Offset (hex)

Length (hex)

Notes

Level Mana Total

0x0

0x4

The level's total mana. Note this works in conjunction with the target percentage set at the end of the file.

Seed

0x4

0x2

Determines the fundamental map landscape shape

Blank

0x6

0x2

Off[set]

0x8

0x2

Offsets the generated landscape horizontally within the map frame

Blank

0xA

0x2

Raise

0xC

0x4

Raises height of landscape peaks

Gnarl

0x10

0x2

Gnarls landscape to create tree root style appearance. Rarely used

Blank

0x12

0x2

River

0x14

0x2

Generates more rivers on the map. Values above 255 seem to crash the game

Blank

0x16

0x2

Sourc

0x18

0x2

Seems to raise sea level/lower base level of terrain. While this seems to use two bytes, going beyond the first byte seems to crash the game

Blank

0x1A

0x2

SnLin

0x1C

0x2

Always C8/200. Not sure what it does

Blank

0x1E

0x2

SnFlt

0x20

0x2

Generally low number below 50. Unknown what this does

Blank

0x22

0x2

BhLin

0x24

0x2

Beach Line? Generally number below 30. This determines how desertified the level is - how much of the terrain is "beach". 255 is pretty much entirely sand.

Blank

0x26

0x2

BhFlt

0x28

0x2

Values generally below 20. Presumably beach related, but not apparent what this actually does

Blank

0x2A

0x2

RkSte

0x2C

0x2

Unknown. Values generally below 40

There is then a lots of zeroed data until position 442. This seems to be fixed across all levels as the start of Thing data.

Thing Definitions#

These always begin at position 442 in a level file. These include everything the player can see and interact with in the game, from enemies to collectables to switches. Each entry is 18 bytes long, and there are 1999 entries.

To do:
Fill this out, Michael Howard's work here already collects 99% of it

Variable

Offset (hex)

Length hex)

Notes

Class

0x0

0x2

What type of thing it is - enemy, scenery, etc

Model

0x1

0x2

Sub type. Which enemy type, what kind of scenery, etc

Xpos

0x3

0x2

X coordinate of Thing

Ypos

0x4

0x2

Y coordinate of Thing

DisId

0x6

0x2

Distinct ID? Used by switches, needs more research

SwiSz

0x8

0x2

Switch Size - the size of the area in which the player must enter to trigger the switch

SwiId

0xA

0x2

The switch number that this item is triggered by. Also used as a modifier for other values, for example what kind of spell

Paren

0xC

0x2

Joins together linked items, like segments of path and walls. Also used by teleports to store the X value of the destination. Also used as a modifier to e.g. determine what kind of building to place

Child

0xE

0x2

Joins together linked items, like segments of path and walls. Also used by teleports to store the Y value of the destination

Each entry contains the above variables. Each entry is numbered 1 - 1999, but this is implicit from their order and used for things like the Parent and Child values, it's not explicitly recorded in the entry.

Thing Types#

These go in the "Class" field. They define the basic Type of a Thing

Value

Type

Notes

02

Scenery

03

Player Spawn

05

Creatures

07

Weather

0A

Effects

0B

Switches

0C

Spells

Once a Thing type is set, the Thing Subtype (e.g. if a creature, what kind of creature it is) is then set in the "Model" field:

Scenery Thing SubTypes#

Value

Thing Subtype

Notes

00

Tree

There are two types of tree used in the game. It doesn't seem possible to choose which is used where, they are set pseudo-randomly (as they use a seed they will always be the same choice when the level is loaded)

01

Standing Stone

02

Dolmen

03

Bad Stone

The weird looking stone with the kind of witch creature statue carved into it

04

Blue Dome

A leftover from when the game used 2D billboard textures for buildings. Not used in any final game levels

05

Blue Dome

Duplicate of above

Player Spawn Subtypes#

These are wizard (player) start positions. If the wizard (other than the player) has a castle level set above zero, they will build their castle here on level start

Value

Thing Subtype

Notes

04

Flyer1

The player

05

Flyer2

06

Flyer3

07

Flyer4

08

Flyer5

09

Flyer6

0A

Flyer7

0B

Flyer8

Creature Thing Subtypes#

Creatures with a SwiId value are spawned by triggering the switch with the corresponding SwiId value

Value

Thing Subtype

Notes

00

Dragon

01

Vulture

02

Bee

03

Worm

04

Archer

05

Crab

06

Kraken

07

Troll/Ape

It turns out there is a random chance for either of these enemies to appear using this Creature ID.

08

Griffin

09

Skeleton

0A

Emu

0B

Genie

0C

Builder

0D

Townie

0E

Trader

10

Wyvern

Weather Thing Subtypes#

The weather code seems to be totally removed from the game, and none of the values do anything.

Value

Thing Subtype

Notes

0

Tornado

1

Rain Cloud

2

Thunder Cloud

3

Thermals

4

Wind

This remains in a few multiplayer levels but does nothing

Effect Thing Subtypes#

"Effects" range from all objects that are not creatures or scenery (buildings, Craters, walls, etc) to one-off effects like explosions and traps usually triggered by switches

Value

Thing Subtype

Notes

0

Explosion

1

Big explosion

2

Dust

3

Blood

4

Spark

5

Splash

6

Fire

7

Freeze

8

Mini Volcano

9

Volcano

0A

Mini crater

0B

Crater

0C

Possession

0D

White smoke

0E

Black smoke

0F

Earthquake

11

Meteor

15

Steal Mana

Trap

17

Lightning

18

Rain of Fire

19

Unknown

1C

Wall

Always have a DisID of 65535 and SwiId of 1. They work by having a minimum of two points (Things) defined in the level and linked via the Parent and Child values (based on their Thing number in the list) to draw the wall to fit between the points.

1D

Path

Works exactly the same as Walls above

1F

Canyon

Again, works exactly the same as Walls do

22

Teleport

Uses the Parent field to store the X coordinate of its destination, and the Child field for its destination's Y coordinate

27

Mana Ball

These start as a single small ball with a value of 512 mana. To get bigger values, more small balls are placed on the same point, and they will auto-merge into a larger size on level start.

2D

Villager Building

The Parent field value determines building type. 1 = Tent, various other values determine other building types

31

Unknown

32

Ridge Node

Again, works exactly the same as Walls do

34

Crab Egg

Switch Thing Subtypes#

Switches cause either Effects to trigger, or Creatures/spells to spawn. The SwiId (Switch ID) field is used to give each switch a unique ID, and also to assign Effects and Creature spawns to trigger by giving them the same ID. However, there is more at play, the DisId field is also used to trigger switches in sequence (so they will only trigger after the previously linked switch in that attribute has been fired). Switch areas are always circular, and the SwiSz (Switch Size) field determines the radius of this circle. Things that are to be triggered by a switch need the SwiId and DisId set to that of the switch. If both are not set, the object will start the level already spawned.

Value

Type

Notes

0

Hidden Inside

A hidden switch activated once by the player moving inside its area

1

Hidden outside

A hidden switch activated once by the player moving outside its area

2

Hidden Inside re

A recurring/repeatable hidden switch activated by the player moving inside its area.

3

Hidden outside re

A recurring/repeatable hidden switch activated by the player moving outside its area.

4

On victory

This switch type triggers when the player completes the level (i.e. hit mana target). Levels 20 and 22 use this.

5

Death Inside

The "Death" switch types don't actually do anything special. They work exactly the same as regular hidden switches. The intention is that these are two be used when the outcome of the switch will be bad for the player (i.e. can make them dead!) so that it is obvious that is what the switch is for in the editor. An example of this is LEV00025 - lots of Death traps that trigger lethal meteor storms.

6

Death Outside

7

Death inside re

8

Death Outside re

9

Obvious Inside

A visible switch that triggers by the player moving inside its area. Note, this and all obvious type switches shows a small X at its centre

0A

Obvious outside

A visible switch that triggers by the player moving outside its area

0B

Obvious Inside re

A repeatable visible switch that triggers by the player moving inside its area

0C

Obvious outside re

A repeatable visible switch that triggers by the player moving outside its area

0D

Dragon

These "creature" switches trigger once all creatures of their respective type on the map have been killed.

0E

Vulture

0F

Bee

10

Worm

11

Archer

12

Crab

13

Kraken

14

Troll

15

Griffon

18

Genie

1D

Wyvern

1E

Creature all

Triggers once all creatures of all types on the map have been killed

1F

Exit Level

LEV000049 Uses this switch type, it marks the final level of the game

Spell Thing SubTypes#

Spell jars. Note that these MUST have the SwiId value populated to tell the game which type of spell it is, or the player cannot pick up the item. There seem to be two accepted values: 1 for normal spell jar (red) and 5 for the non-mana-limited (blue) variety. If a spell jar is spawned by a switch, the DisId field is used to mark which one it is, NOT the SwiId field (which still marks what kind of jar it is).

Value

Type

Notes

0

Fireball

1

Heal

2

Speed Up

3

Possession

4

Shield

5

Beyond Sight

6

Earthquake

7

Meteor

8

Volcano

9

Crater

0A

Teleport

0B

Duel

Called "Rubber band" internally

0C

Invisible

0D

Steal Mana

0E

Rebound

0F

Lightning

10

Castle

11

Skeleton

12

Thunderbolt

13

Mana Magnet

14

Fire Wall

15

Reverse Speed

16

Global Death

Called "Smart Bomb" internally

17

Rapid Fireball

Called "Mini Fireball" internally

Wizard Stats Block#

These are always in the same place in the file, starting at position 90D4. The first 12 bytes are actually the APR stats for the player... Which unless you're some kind of robot, don't have any effect.

Player Spells#

Player spells are defined at 90E0. There are 24 bytes, each one simply a boolean value for a spell. There does seem to be some logic involved in which spells are unlocked, however (some seem to need e.g. castle unlocked first).

Spell

Offset (hex)

Length hex)

Notes

Fireball

0x0

0x1

All are booleans, 1 = character has this spell

Shield

0x1

0x1

Accelerate

0x2

0x1

Possession

0x3

0x1

Health

0x4

0x1

Beyond Sight

0x5

0x1

Earthquake

0x6

0x1

Meteor

0x7

0x1

Volcano

0x8

0x1

Crater

0x9

0x1

Teleport

0xA

0x1

Duel

0xB

0x1

Invisible

0xC

0x1

Steal Mana

0xD

0x1

Rebound

0xE

0x1

Lightning

0xF

0x1

Castle

0x10

0x1

Undead Army

0x11

0x1

Lightning Storm

0x12

0x1

Mana Magnet

0x13

0x1

Wall of Fire

0x14

0x1

Reverse Acceleration

0x15

0x1

Global Death

0x16

0x1

Rapid Fireball

0x17

0x1

Enemy Wizard Definitions#

After the above, there is a block of 100 bytes of what is usually 01 for each wizard. These actually seem to be Boolean values for what appears to be which tactics this particular wizard will use in the level. Most of the time these are all enabled, but on some earlier levels some are set to 00, which seems to be how to dumb down the AI in how it fights the player. It's not known what each specific value does.

Five Bytes after this are the definitions for that wizard's Aggression, Perception, and Reflexes stats, as explained in the Official Strategy Guide. While they can range from 0 - 255 as explained in the guide, the baseline default for all is actually 128.

The fourth byte after the Reflex value is the start of the spell loadout for the wizard, which works exactly as per the player's spells, listed above.

Attribute

Offset (hex)

Length (hex)

Notes

Aggression

0x0

0x1

Blank

0x1

0x4

Perception

0x5

0x1

Blank

0x6

0x4

Reflexes

0xA

0x1

Blank

0xB

0x4

Spell Loadout

0xE

0x18

Some levels have wizards defined beyond the default stats even though they are not present in the level, suggesting they may have been cut (e.g. the first level has a very low level Vodor defined despite it not featuring any enemy wizards).

Misc Level Setup#

This is always found after the wizard definitions at 9790. These define the target amount of mana for the player to collect on the level, the number of wizards in the level, and starting castle levels of each wizard (from 0 to 7).

Attribute

Offset (hex)

Length (hex)

Notes

Mana Target (%)

0x0

0x1

The percentage of the total mana defined in the first four bytes of the file needed to beat the level

Blank

0x1

0x1

Number of Wizards in level

0x2

0x1

Only the player is 1. Therefore 2 would be the player and one enemy wizard (Vodor). Max is 8

Blank

0x3

0x1

Player Castle Level

0x4

0x1

Always set to 0

Vodor Castle Level

0x5

0x1

Determines what level this wizard's castle starts at, and therefore their mana state

Gryshnak Castle Level

0x6

0x1

Determines what level this wizard's castle starts at, and therefore their mana state

Mahmoud Castle Level

0x7

0x1

Determines what level this wizard's castle starts at, and therefore their mana state

Syed Castle Level

0x8

0x1

Determines what level this wizard's castle starts at, and therefore their mana state

Raschid Castle Level

0x9

0x1

Determines what level this wizard's castle starts at, and therefore their mana state

Alhabbal Castle Level

0xA

0x1

Determines what level this wizard's castle starts at, and therefore their mana state

Scheherazade Castle Level

0xB

0x1

Determines what level this wizard's castle starts at, and therefore their mana state

Spell Loadouts#

Keep in mind that the final game only respects spell loadouts on certain levels. Early on the game ignores what is set in the level to use the inventory the player has built up so far in the game. If a different level is played in one of these slots (most obviously level one), the player will start with no spells at all.