Cosmo Level Format

From ModdingWiki
Jump to: navigation, search
Cosmo Level Format
Cosmo Level Format.png
Format typeMap/level
Map type2D tile-based
Layer count3
Tile size (pixels)8×8
Viewport (pixels)304×144
Games

File format

The file is in this basic layout:

Data type Description
UINT16LE iFlags Flags indicating music, backdrop and other stuff
UINT16LE iMapWidth Map width in tiles
UINT16LE iActorSize Number of UINT16 values in the actor block
ACTORDATA actorData[] Variable-length array of all the actors in the level
BYTE bgLayer[65528] The map data for the background layer

The iMapWidth values in the original Cosmo levels is either 64, 128, 256 or 512. The "view window" in the game is 304x144 Pixels, so the minimal map width would be 38. However, the width must be a power of 2 to work (from 32 to 2048).

The iActorSize values are reliable for all the original Cosmo level files (Version 1.20).

The map data is actually sized 65528 Bytes or 32764 Words. Each entry in this block is divisable by 8 (see #Mapping cell values to tiles).

Level Flags

The structure of the bits in the iFlags value is as follows:

[ mmmmm | ppp | yxr | bbbbb ]

m: music index
p: palette animation type
y: y-scrolling backdrop
x: x-scrolling backdrop
r: rain
b: backdrop index

The indices for music and backdrop refer to an array of filename strings stored in the executable. You can find them by searching for the first filename in each array. For backdrops, the first filename (index: 0) is BDBLANK.MNI, for music it's MCAVES.MNI. Note that some backdrop files are not used by the games. The complete list is:

Backdrop
value
Filename
0 bdblank.mni
1 bdpipe.mni
2 bdredsky.mni
3 bdrocktk.mni
4 bdjungle.mni
5 bdstar.mni
6 bdwierd.mni
7 bdcave.mni
8 bdice.mni
9 bdshrum.mni
10 bdtechms.mni
11 bdnewsky.mni
12 bdstar2.mni
13 bdstar3.mni
14 bdforest.mni
15 bdmountn.mni
16 bdguts.mni
17 bdbrktec.mni
18 bdclouds.mni
19 bdfutcty.mni
20 bdice2.mni
21 bdcliff.mni
22 bdspooky.mni
23 bdcrystl.mni
24 bdcircut.mni
25 bdcircpc.mni
26-31 Unused
Music
value
Filename
0 mcaves.mni
1 mscarry.mni
2 mboss.mni
3 mrunaway.mni
4 mcircus.mni
5 mtekwrd.mni
6 measylev.mni
7 mrockit.mni
8 mhappy.mni
9 mdevo.mni
10 mdadoda.mni
11 mbells.mni
12 mdrums.mni
13 mbanjo.mni
14 measy2.mni
15 mteck2.mni
16 mteck3.mni
17 mteck4.mni
18 mzztop.mni
19-31 Unused
Animation
value
Use Description
0 most levels no palette changes
1 A4 random lightning (with thunder soundeffect)
2 C8-C10 cycling: red -> yellow -> white
3 A7 cycling: red -> green -> blue
4 A8, B3, B4, B7 cycling: black -> grey -> white
5 C6, C7 flashing: red -> magenta -> white
6 C1 replace dark magenta with black,
no animation unless triggered by a bomb actor.
(ONLY PRESENT IN COSMO3.EXE AT THE MOMENT.)
7 None ! Unknown


Background Layer

The bgLayer block contains the grid/cell data:

Data type Description
UINT16LE iMapData[32764] Actual map data

Each "element" in iMapData refers to the foreground and/or background tile used in a single grid cell. The grids are arranged left to right, top to bottom, so the index can be calculated by this formula:

int iIndex = (y * iMapWidth) + x;
iMapData[iIndex] = <new value to set at x,y>

The map data in the original Cosmo level files is a constant 32764 UINT16LE cells long (65528 bytes), and the engine will never read more than 65535 bytes. However, the game calculates the map height by dividing the width in bytes by 65536:

int iMapHeight = 32768 / iMapWidth;

Since the width of the map is always a power of 2 (min. 64), you can see that each file is "missing" 8 Bytes (or 4 Words). That means the last line of the map will always be missing the last 4 tiles. The game ignores that last, incomplete line. However, in one level (A8.MNI), there is an actor placed in that last line. Since actors are saved as individual structures instead of a grid, that actor will still be loaded by the game. But for editing a level, you should make sure the last line is visible, so that it's possible to place actors in that line or remove them from there.

Mapping cell values to tiles

The method of mapping elements in the iMapData structure into tiles is fairly straightforward. Each cell value is a pixel index into the tilemap. Imagine the tileset laid out left to right all on the one row. Since each tile is 8x8 pixels, at 16 pixels into the image, the third tile will begin (x = 0 for first tile, x = 8 for second tile, x = 16 for third tile.) The cell value is essentially a pixel x-coordinate into the tileset.

Note that in the tileset file, the solid tiles are made up of 2000 4-plane (16-colour) images, and these are followed by 1000 5-plane images (16-colour + transparency.) Although separate images, they appear to be concatenated when the game loads them, as the cell value will be zero for the first solid tile, it will be eight for the second solid tile, it will be 15992 for the last solid tile, and it will be 16000 for the first masked tile.

This means that if the solid and masked tiles have been treated as separate images, a check will need to be performed so that any cell value below 16000 is loaded from the solid tileset, and any value larger than this is loaded from the masked tileset (after subtracting 16000 from the cell value, to put it at zero for the first masked tile.) However, for some reason the values for the masked tiles are at multiples of five tiles (tile #0 (x=0) is the first tile, tile #5 (x=40) is the second tile.) This formula can be used to convert the values into tile numbers once they stray into the masked tile area:

#define COSMO_TS_SOLID_NUMTILES   2000 // 40x25
#define COSMO_TS_MASKED_NUMTILES  1000 // 40x4

tile = cell_value / 8
if (tile > COSMO_TS_SOLID_NUMTILES) {
  // Once we're in the masked tileset it counts up in multiples of five planes
  tile = COSMO_TS_SOLID_NUMTILES + (tile - COSMO_TS_SOLID_NUMTILES) / 5;
}
// Now 'tile' will be between 0 and 2999 inclusive

As an example of a few tile values:

Cell value Tile number Tileset Index Comments
0 0 N/A N/A See through to map backdrop
8 1 Solid 1 First solid tile, note increment of 8
16 2 Solid 2 Second solid tile, increment of 8 again
15992 1999 Solid 1999 Last solid tile
16000 2000 Masked 0 First masked tile
16040 2001 Masked 1 Second masked tile, note increment of 40
16080 2002 Masked 2 Third masked tile, increment of 40 again
55960 2999 Masked 999 Last masked tile
56000 N/A N/A N/A Should never get a value this size or larger

Note that while the cell value cannot be out of range for the solid tiles/background layer (since any values larger than 16000 will be loaded from the masked tileset) the cell values for the masked tileset have no such restriction. (Although obviously out of range tiles will not be drawn correctly by the engine!)

Gotchas

  • The first tile in the solid tileset is used as a transparent tile. It will appear completely black if drawn (e.g. in a map editor) however the game does not draw this tile, so any cells with this as the background cell will be where the map backdrop shows through. If you wish to draw the map with the backdrop in-place, remember not to draw tile #0 over the top of the backdrop.

Actor data

The actorData block is in the following format:

Data type Description
UINT16LE iType Type of actor
UINT16LE iX X-coordinate of actor (in tile units)
UINT16LE iY Y-coordinate of actor (in tile units)

Because the iActorSize value in the header is in UINT16s and there are three UINT16s per actor, the number of actors can be obtained quite simply:

iNumActors = iActorSize / 3

This is assuming iActorSize is reliable - the original specs from Dave Bollinger indicate this is not always the case for DukeII, but no examples are known at the moment.

Mapping Actor Types to image indices

For the ActorTypes from 32 to 296 (inclusive), you can get an image index from ACTORS.MNI and ACTRINFO.MNI like this:

ImageIndex = ActorType - 31

However, this does not work for every ActorType. Some share the same images (e.g.: normal stars and falling stars), some use flipped versions of other images (like the pink eye plants) and some are invisible in the game. In either case, the index in the ACTRINFO.MNI will contain no data. You will either have to include hard-coded info to draw these, or just draw something else (like the actual ActorType as text).

List of Actor Types

This is a list of all the actor types that can be found in the original levels of the three episodes. There might be more ActorTypes that work in the game. For example, 69 is probably the (falling) "Cyan Fruit" item as you can guess by looking at the numbers 62-68.

  0	PLAYER:	Cosmo (Starting position facing right)
  1	moving platform (fixed path)
  2	PLAT/HAZARD:	mud fountain 1 (small)
  3	PLAT/HAZARD:	mud fountain 2 (normal)
  4	PLAT/HAZARD:	mud fountain 3 (big)
  5	PLAT/HAZARD:	mud fountain 4 (huge)
  6	BRIGHTNESS:	left border of light
  7	BRIGHTNESS:	light source (top center)
  8	BRIGHTNESS:	right border of light

 22	??? (only in A8.MNI, doesn't seem to be doing anything)

 32	BONUS:	Star	(200)
 33	PLAT:	Floor Spring
 34	HAZARD:	Extending Arrow Spear (from right to left)
 35	HAZARD:	Extending Arrow Spear (from left to right)
 36	HAZARD:	Plasma Fireball (from right to left)
 37	HAZARD:	Plasma Fireball (from left to right)
 38	Blue Switch (on ceiling)
 39	Red Switch (on ceiling)
 40	Green Switch 
 41	Yellow Switch
 42	Blue Door
 43	Red Door
 44	Green Door
 45	Yellow Door

 47	OBJECT:	Blue Mobile Trampoline Car
 48	HAZARD:	Non-Retracting Spikes
 49	HAZARD:	Retracting Spikes

 51	HAZARD:	Big Saw Blade

 56	HAZARD:	Green Pruny Cabbage Ball

 59	BONUS:	Power Up	(health/12800)
 60	BARREL:	Power Up	(health/12800)

 62	CRATE:	Green Tomato
 63	BONUS:	Green Tomato (falling)
 64	CRATE:	Tomato		(200)
 65	BONUS:	Tomato (falling)
 66	CRATE:	Yellow/Cyan Fruit
 67	BONUS:	Yellow/Cyan Fruit (falling)
 68	CRATE:	Cyan Fruit

 70	OBJECT:	Exit Sign (ends level on touch)

 72	HAZARD:	Spear (coming down from ceiling)
 73	HAZARD:	Leaking Green Acid
 74	HAZARD:	Dripping Green Acid
 75	ENEMY:	Plasma Energy Sprites (Blue Flame-like creatures)
 76	HAZARD:	"Two Tons" Weight going down & up
 77	ENEMY:	Jumping Bulletheads
 78	ENEMY:	Stone Heads (Only drops when Cosmo is close by)
 79	ENEMY:	Big Yellow Spike on ceiling
 80	ENEMY:	Big Yellow Spike on ceiling (falling down)
 81	ENEMY:	Big Yellow Spike on ground
 82	ENEMY:	Ghost
 83	CRATE:	Green thingy

 85	ENEMY:	Angry Moon (blue floating characters)
 86	ENEMY:	Small Red Plant
 87	BARREL:	Bomb	(100)
 88	BONUS:	Bomb	(100)

 90	OBJECT: switch (1) (Activates moving platform(s))

 92	OBJECT: switch (2) (Activates Question Mark Block Wall Generator)
 93	OBJECT: Question Mark Block (Generates a wall when activated by switch)
 94	HAZARD: Ground Claw Spikes
 95	OBJECT: Rubber Wall (can blow it up, throws Cosmo backwards when touched)
 96	ENEMY:	Mini Ghost (jumps)

100	CREATURE:	Green Roamer Worm
101	PIPE TRANSIT DIRECTION:	Arrow Up
102	PIPE TRANSIT DIRECTION:	Arrow Down
103	PIPE TRANSIT DIRECTION:	Arrow Left
104	PIPE TRANSIT DIRECTION:	Arrow Right
105	ENEMY:	Egg Head (special?) -- only 1x: in B2.MNI
106	ENEMY:	Egg Head

109	ENEMY:	Robotic Spike on ground

111	ENEMY:	Robotic Spike on ceiling
112	CRATE/BONUS:	Burger

114	ENEMY:	Blue/Red plant

116	BONUS:	Purple Grapes	(800)
117	ENEMY:	Blue Ball
118	ENEMY:	Spikes (on left wall)
119	ENEMY:	Retracting Spikes (on left wall)
120	ENEMY:	Spikes (on right wall)
121	ENEMY:	Robot with Blue Vertical Electric Arc
122	PLAT:	Blue Platform (splits open when standing on top)
123	ENEMY:	Spark

125	BONUS:	Cyan Dancing Mushroom	(400)
126	DECO:	Pink Eye Plant
127	DECO:	Pink Eye Plant (hanging upside down)

132	ENEMY:	Big Red Jumper (MAY ONLY WORK IN COSMO2 & COSMO3.EXE. APPEARS TO BE FROZEN IN COSMO1.EXE)
133	ENEMY:	BOSS (Purple Alien in Spike-bottomed ship)

135	PNEUMATIC PIPES:	Exit
136	PNEUMATIC PIPES:	Entrance
137	ENEMY:	Suction-Cup-Legged Alien
138	OBJECT: Teleporter A
139	OBJECT: Teleporter B

142	ENEMY:	Cyan Spitting Plant (on left wall)
143	ENEMY:	Cyan Spitting Plant (on right wall)
144	ENEMY:	Blue Turret Alien
145	PLAT:	Hoverboard
146	CRATE:	pile of green balls

148	BARREL:	Saxophone-like thing
149	ENEMY:	Red Chomper Alien
150	CRATE:	Salad
151	switch (3) (Possibly deactivates Actors 153 & 154; Energy Beams)
152	switch (4) (Possibly activates lights, if actors 6,7, & 8 are present in level.)
153	HAZARD: Vertical Energy Beam (Deactivated by Switch)
154	HAZARD: Horizontal Energy Beam (Deactivated by Switch)
155	CREATURE/HAZARD:	Pink slug/Worm (Turns to bubbling goo when jumped upon)
156	HINT:	"These hint globes will help you along your journey. Press the up key to reread them."
157	ENEMY:	Silver Robot (pushes player around)
158	ENEMY:	Security Robot (shoots flashing bullet, can act as moving floor spring)

160	PLAT/HAZARD:	Dragonfly
161	Crate/Box (can only be destroyed with bombs)

165	BONUS:	Bottle with red liquid
166	BONUS:	Green thing
167	BONUS:	Blue thing
168	BONUS:	Salad?
169	BONUS:	Pile of green things
170	BONUS:	whatever..

172	BONUS:	blue thing

174	DECO/BONUS:	Satellite

176	ENEMY:	Green Plant
177	BONUS:	5 Yellow Grapes	(800)
178	BONUS:	Headdress-like object
179	CRATE:	with item 178
180	DECO:	Jaws & Tongue
181	invisible exit marker (go right to exit)
182	small flame
183	ENEMY:	Big Red Plant (spitting Blue Balls/catapult)

185	BONUS:	Blue Crystal (on ground)
186	BONUS:	Red Crystal (on ground)
187	BARREL:	Red/Green Gem
188	BARREL:	Blue Crystal
189	BARREL:	Red Crystal
190	BONUS:	Green Tomato
191	BONUS:	Tomato
192	BONUS:	Yellow/Cyan Fruit	(200)
193	HAZARD:	Clamp Trap
194	PLAT:	Blue Cube (falls down when you walk off)
195	MESSAGE:	"What's happening? Is Cosmo falling to his doom?"
196	MESSAGE:	"Is there no end to this pit? An what danger awaits below?!"
197	Level End Object?
198	CRATE:	Root		(400)
199	BONUS:	Root
200	CRATE:	4 Brown Berries	(400)
201	BONUS:	4 Brown Berries

203	BONUS:	Potato-like vegetable
204	BARREL:	Green Gem
205	BONUS:	Green Gem
206	BARREL: Diamond		(3200)
207	BONUS:	Diamond

217	ENEMY:	Alien-Eating Space Plant (Exits the current level)
218	ENEMY:	Blue Bird
219	OBJECT:	Rocket
220	BONUS:	Invincibility Cube
221	PLAT:	Destructible Pedestal 1 (14 tiles high)
222	PLAT:	Destructible Pedestal 2 (20 tiles high)
223	PLAT:	Destructible Pedestal 3 (26 tiles high)
224	BARREL:	Diamond 2
225	BONUS:	Diamond 2 (falling)
226	BARREL:	Red Berry
227	BONUS:	Red Berry (falling)
228	BARREL:	Crystal		(800)
229	BONUS:	Crystal (falling)
230	BARREL:	Blue Gem
231	BONUS:	Blue Gem (falling)

233	DECO:	Rocket Exhaust
234	EXIT:	Teleporter
235	HINT:	"Bump head into switch above!"
236	HINT:	"The ice in this cave is very, very slippery."
237	HINT:	"Use this shield for temporary invincibility."
238	HINT:	"You found a secret area!!! Good Job!"
239	HINT:	"In hight places look up to find bonus objects."
240	HINT:	"Out of Order..."
241	HINT:	"This might be a good time to save your game!"
242	HINT:	"Press your up key to use the transporter."
243	HINT:	"(1) FOR..."
244	BONUS:	Diamond 2
245	BONUS:	Red Berry
246	BONUS:	Crystal
247	BONUS:	Blue Gem	(800)
248	PLAT:	Ceiling Spring
249	BARREL:	Headphones
250	BONUS:	Headphones
251	BONUS:	Headphones (falling)
252	OBJECT:	Frozen Duke NukUm

254	BONUS:	3 Bananas	(800)
255	CRATE:	Alien Raisin
256	BONUS:	Alien Raisin	(400)

258	CRATE:	Brown Pear
259	BONUS:	Brown Pear

261	CRATE:	Alien Chili Pepper
262	BONUS:	Alien Chili Pepper (400)

264	DANGER:	Flame (<-)
265	DANGER:	Flame (->)

267	HAZARD:	Leaking Red acid
268	HAZARD:	Dripping Red Acid
269	HINT:	"(2) EXTRA..."
270	HINT:	"(3) POINTS,..."
271	HINT:	"(4) DESTROY..."
272	HINT:	"(5) HINT..."
273	HINT:	"(6) GLOBES!!!"
274	HINT:	"The Clam Plants won't hurt you if their mouths are closed."+Clam Sprite

278	DECO:	Big Mouth (end of E1/start of E2)
279	DECO:	Normal Smoke Rising
280	DECO:	Big Smoke rising
281	EXIT: 	Horizontal Exit Marker (Invisible)

283	BONUS:	Red Crystal on ceiling
284	HINT:	"Collect the STARS to advance to BONUS STAGES."
285	HINT:	"Some creatures require more than one pounce to defeat!"
286	HINT:	"Cosmo can climb wall's with his suction hands."+CosmoWallSprite

294	BONUS:	Power Up Module (falling)	(health/12800)
295	BONUS:	Star (falling)	(200)
296	end of episode 2 trigger?

The hint texts are the messages you get in episode 1, the other episodes have different (and less!) messages. The later hint globes probably don't work in those episodes.

Credits

This file format was reverse engineered by Dave Bollinger. Most of this info came from the Duke II specs on his website, with Malvineous working out which bits to remove to read Cosmo maps. If you find this information helpful in a project you're working on, please give credit where credit is due. (A link back to this wiki would be nice too!)