You are not logged in.    Login    New User    Forum Home    Search  RSS Feed 

Location:
James' Games Site  \  Meteor 1  \  User Announcements  \  Meteor 1 map format unraveled

Back to Threads

Viewing Thread: Meteor 1 map format unraveled

 

ParaSait

Joined: 26 June 2007
Posts: 1478
29 July 2011 18:39 (UK time)

Yesterday evening and today I have been studying the Meteor 1 .map format a bit, and I wrote a little analysis that describes everything in it. This is important information in case someone would want to make any 3rd party editors for it, or similar things.

It's alllmost complete. There is just 1 mysterious byte I haven't figured out so far; the one at $70E. But here it is:


Meteor 1 map format unraveled (almost complete) - by ParaSait
-------------------------------------------------------------

Notes:
- This file describes map version 13 (0D).
- All numeric values are little-endian.
- "$???" address numbers mean that the address is variable, depending on other values.



*** Map ***
$0: char(30) - "Meteor Map File"
$1E: long - Map format version number
$22: char(128) - Map title
$A2: long - Map height
$A6: long - Map width
$AA: StartZone - Single Start Zone
$BA: StartZone - Coop Start Zone
$CA: StartZone - H2H 2 Start Zone
$DA: StartZone - H2H 3 Start Zone
$EA: StartZone - H2H 4 Start Zone
$FA: long - Sprite count
$FE: long - Race count
$102: long - Powerup count
$106: long - Message count
$10A: long - Message trigger count
$10E: char(128) - Map author
$18E: char(128) - Web address
$20E: char(256) - Extended Tileset Filename
$30E: char(256) - Player Character Filename
$40E: char(256) - Map to start on exit flag of 1
$50E: char(256) - Map to start on exit flag of 2
$60E: char(256) - Map to start on exit flag of 3
$70E: byte - ???
$70F: char(52) - Map theatre name
$743: long - Theatre pick up color value (*1)
$747: long - Theatre start color value (*1)
$74B: long - Theatre range value
$74F: bool - Night
$750: bool - Rain
$751: bool - Storm
$752: bool - Battle
$752: long - Time limit
$757: bool - Conveyors on
$758: bool - Ignore Required Items in Head to Head
$759: Trigger(*4) - Message trigger list
$???: byte(*2) - Tile raster, least significant bytes
$???: byte(*2) - Tile raster, most significant bytes (*3)
$???: Sprite(*4) - Sprite list
$???: Race(*4) - Race list
$???: Powerup(*4) - Powerup list
$???: Message(*4) - Message list
$???: Trigger(*4) - Message trigger list (*7)

*** StartZone ***
$0: long - X position
$4: long - Y position
$8: long - Width
$B: long - Height

*** Sprite ***
$0: long - X position
$4: long - Y position
$8: char(256) - Filename
$108: long - Rotation

*** Race ***
$0: byte(8) - Unknown (*5)
$8: long - X position
$C: long - Y position
$10: bool - Active
$11: char(256) - Filename

*** Powerup ***
$0: long - X position
$4: long - Y position
$8: char(128) - Name

*** Message ***
$0: char(128) - Message text (*6)

*** Trigger ***
$0: long - (Y position * Map width in pixels) + X position
$4: long - Associated Message ID



Footnotes:
*1: Seems to be saved as a (4byte) long, but used as a (2byte) int to save a 16bit color, for the 2 last bytes seem to be unused.
*2: Map width * Map height
*3: So apparently the tile raster is split up in two; tile ID's are actually integers (2byte); and the first raster defines their LSB's, the second raster defines their MSB's.
*4: Amount of them on the map
*5: Seems to be always 00 00 00 00 00 00 00 00
*6: For a sound: /s:filename (without extension)
*7: Yes, apparently message triggers are saved twice in the file. I'm going to guess James screwed up a bit here. :>


I might do this for other file formats in the game too, and maybe also do the same for Meteor 2 later on. (^^,)


This link is dead. It's only still here because, err... yknow, it's some sort of... memorial.


Edited: 31 July 2011 01:36


You need to login to create posts in this thread.

Spy

Joined: 05 October 2007
Posts: 1031
30 July 2011 01:44 (UK time)

Interesting.. I don't understand any of that.
I was known as Naval War before.
I love and mod Amnesia: The Dark Descent.
Also an active osu! player: https://osu.ppy.sh/u/3971179


You need to login to create posts in this thread.

me_mantis

Joined: 26 September 2003
Posts: 1151
30 July 2011 03:44 (UK time)

random map generator time or what?

I kinda wish I knew how to code =)

You need to login to create posts in this thread.

ParaSait

Joined: 26 June 2007
Posts: 1478
30 July 2011 16:09 (UK time)

Hah, that sounds like an awesome idea. :D


This link is dead. It's only still here because, err... yknow, it's some sort of... memorial.


You need to login to create posts in this thread.

me_mantis

Joined: 26 September 2003
Posts: 1151
30 July 2011 19:38 (UK time)

it would be pretty fun for multiplayer - nobody would have any sort of knowledge of the map.

You need to login to create posts in this thread.

ParaSait

Joined: 26 June 2007
Posts: 1478
30 July 2011 23:13 (UK time)

This evening, I made this...

http://dl.dropbox.com/u/27586899/sdfsdafds.png

As you see, possibly the start of something... big. (^^,)


This link is dead. It's only still here because, err... yknow, it's some sort of... memorial.


You need to login to create posts in this thread.

Archie

Joined: 13 March 2010
Posts: 72
30 July 2011 23:18 (UK time)

Awesome! ;)

You need to login to create posts in this thread.

ParaSait

Joined: 26 June 2007
Posts: 1478
31 July 2011 01:37 (UK time)

I've made an amendment to the analysis... it seems like I had something wrong about message triggers.


This link is dead. It's only still here because, err... yknow, it's some sort of... memorial.


You need to login to create posts in this thread.

James Bunting
Joined: 17 September 2003
Posts: 1302
02 August 2011 08:46 (UK time)

Impressive

The way M1 saves strings is pretty poor being fixed length and all.

Anyway, here is the writer code.


int MF_WriteMapFile( char *filename)
{
FILE *f;
int i;
char str[ FILENAME_LEN];
MAP_FILE_HEADER hdr;

if(( f=fopen( filename, "wb")) == NULL)
return 0;

memset( hdr.id, 0, sizeof( hdr.id) );
strcpy( hdr.id, MAP_ID);
hdr.version=MAP_VERSION;

// write 30 byte file id
fwrite( &hdr.id, 30, 1, f);

// write version
fwrite( &hdr.version, sizeof( int), 1, f);

// ** write map header **

// map info
memset( str, 0, sizeof( str) );
strcpy( str, MapHeader.title);
fwrite( &str, sizeof( MapHeader.title), 1, f);
fwrite( &MapHeader.MapX, sizeof( MapHeader.MapX), 1, f);
fwrite( &MapHeader.MapY, sizeof( MapHeader.MapY), 1, f);

// start zones
for( i=0; i<SZ_COUNT; ++i)
{
fwrite( &MapHeader.StartZones[i].x, sizeof( int), 1, f);
fwrite( &MapHeader.StartZones[i].y, sizeof( int), 1, f);
fwrite( &MapHeader.StartZones[i].w, sizeof( int), 1, f);
fwrite( &MapHeader.StartZones[i].h, sizeof( int), 1, f);
}

// counts
fwrite( &MapHeader.SpritesUsed, sizeof(int), 1, f);
fwrite( &MapHeader.UnitsUsed, sizeof(int), 1, f);
fwrite( &MapHeader.PowerUpsUsed, sizeof(int), 1, f);
fwrite( &MapHeader.MessageStringsUsed, sizeof(int), 1, f);
fwrite( &MapHeader.MessageTriggersUsed, sizeof(int), 1, f);

fwrite( &MapHeader.author, sizeof( MapHeader.author), 1, f);
fwrite( &MapHeader.email, sizeof( MapHeader.email), 1, f);

// files
fwrite( &MapHeader.ExtendedTilesetFilename, FILENAME_LEN, 1, f);
fwrite( &MapHeader.PlayerCharacterFilename, FILENAME_LEN, 1, f);

// next level names
fwrite( &MapHeader.NextLevelNames[0], FILENAME_LEN, 1, f);
fwrite( &MapHeader.NextLevelNames[1], FILENAME_LEN, 1, f);
fwrite( &MapHeader.NextLevelNames[2], FILENAME_LEN, 1, f);

// theater type
fwrite( &MapHeader.GrassTheatre, sizeof( char), 1, f);

// grass pickup colour data (for custom theatre only)
fwrite( &MapHeader.GrassPickup, sizeof( MapHeader.GrassPickup), 1, f);

// extra flags
fwrite( &MapHeader.night, sizeof( char), 1, f);
fwrite( &MapHeader.rain, sizeof( char), 1, f);
fwrite( &MapHeader.storm, sizeof( char), 1, f);
fwrite( &MapHeader.battle, sizeof( char), 1, f);
fwrite( &MapHeader.TimeLimit, sizeof( int), 1, f);
fwrite( &MapHeader.ConveyorsOn, sizeof( char), 1, f);
fwrite( &MapHeader.IgnoreRequiredItemsInDeathmatch, sizeof( char), 1, f);

// message triggers
for( i=0; i<MapHeader.MessageTriggersUsed; ++i)
{
fwrite( &MapHeader.MessageTriggers[i].location, sizeof( long), 1, f);
fwrite( &MapHeader.MessageTriggers[i].MessageId, sizeof( int), 1, f);
}


// ** write terrain **
fwrite( TerrainData, MapHeader.MapX * MapHeader.MapY, 1, f);
fwrite( TerrainMul, MapHeader.MapX * MapHeader.MapY, 1, f);

// ** write sprites **
for( i=0; i<MapHeader.SpritesUsed; ++i)
{
fwrite( &MapSprites[i].x, sizeof( int), 1, f);
fwrite( &MapSprites[i].y, sizeof( int), 1, f);
fwrite( MapSprites[i].SpriteName, FILENAME_LEN, 1, f);
fwrite( &MapSprites[i].angle, sizeof( int), 1, f);
}

// ** write map units **
for( i=0; i<MapHeader.UnitsUsed; ++i)
{
fwrite( &MapUnits[i].ai, sizeof( MapUnits[i].ai), 1, f);
fwrite( &MapUnits[i].angle, sizeof( MapUnits[i].angle), 1, f);
fwrite( &MapUnits[i].x, sizeof( MapUnits[i].x), 1, f);
fwrite( &MapUnits[i].y, sizeof( MapUnits[i].y), 1, f);
fwrite( &MapUnits[i].StartActive, sizeof( MapUnits[i].StartActive), 1, f);

memset( str, 0, FILENAME_LEN);
strcpy( str, DAT_LoadedRaces.names[ MapUnits[i].RaceNumber]);
fwrite( str, FILENAME_LEN, 1, f);
}

// write map power ups
for( i=0; i<MapHeader.PowerUpsUsed; ++i)
{
fwrite( &MapPowerUps[i].x, sizeof( int), 1, f);
fwrite( &MapPowerUps[i].y, sizeof( int), 1, f);
fwrite( MapPowerUps[i].name, 128, 1, f);

memset( MapPowerUps[i].name, 0, 128);
strcpy( MapPowerUps[i].name, DAT_PowerUps[ MapPowerUps[i].PowerUpNumber ].name);
}


// ** write message strings **
for( i=0; i<MapHeader.MessageStringsUsed; ++i)
{
memset( str, 0, sizeof( str) );
strcpy( str, DAT_MapMessageStrings[i]);
fwrite( &str, sizeof( DAT_MapMessageStrings[i]), 1, f);
}

// ** write message triggers **
for( i=0; i<MapHeader.MessageTriggersUsed; ++i)
{
fwrite( &MapHeader.MessageTriggers[i].location, sizeof( long), 1, f);
fwrite( &MapHeader.MessageTriggers[i].MessageId, sizeof( int), 1, f);
}

fclose( f);

return 1;
}

Attached Files
 FILES.C (49 KB) C Source Code File
 MapEditor.c (79.7 KB) C Source Code File
 MapFiles.c (22.3 KB) C Source Code File
 TYPES.H (20.2 KB) C Header File


You need to login to create posts in this thread.

James Bunting
Joined: 17 September 2003
Posts: 1302
02 August 2011 09:02 (UK time)

So to summarise Meteor 1 is written in straight C using MSVC6. The code is a big tangle held together with sticky tape but it worked quite well.

I doubt Meteor 1's code could be worked with nowadays. I am already toying with the idea of a full M2 rewrite but have not really thought much about M1.

Frankly I am quite excited about the idea of rewriting 1 & 2 before moving onto 3.

The questions are:
1) Should M1 be rewritten at all?
2) Should it be done before M3?
3) Should it be called "Meteor 1 Gold" or simply superceed the current version?

Ditto for M2.

Also, I am always happy to release file specs for all games if anyone wanted to do anything. Generally speaking older games could have their source code released but working with it would require a pretty good knowledge of C++ and Allegro.

James

PS. Like the random map editor idea. This should be possible with M1 but it WILL do your head in. Would be amazing to see.



You need to login to create posts in this thread.

me_mantis

Joined: 26 September 2003
Posts: 1151
02 August 2011 19:42 (UK time)

The random maps could be made up of randomly placed previously created 20x20 blocks of tiles, or you could create a maze sort or structure and then have a setup that stuck the appropriate tiles inside, outside, and on the edges.

Then it'd assign start points, and randomly spawn weapons at certain distances from the start points.

I probably don't have time to do it =)

You need to login to create posts in this thread.

ParaSait

Joined: 26 June 2007
Posts: 1478
02 August 2011 21:23 (UK time)

I have various ideas in mind. Mazes, mazes of rooms, towns with houses, connected rooms, arena style levels,...
Some time back I've also been toying around with an algorithm to generate somewhat natural looking caves (see attachments), it's not yet complete but that could also come in handy.

@James:
Thanks for the map editor/saver sources... it seems like I had it all pretty right, except the unit ai and angle. :D

Also I think it'd be a good idea to do a Meteor 2 cleanup/rewrite, plus some bugfixes, improvements (collision detection, netcode), and maybe some new features (like more script commands would be great).
Meteor 1, maybe not, for I think it's Meteor 2 that has most potential for mods and netplay and so on; the thing is just that it has some annoying flaws and multiplayer is not very playable at this point, and that's a bummer. Meteor 1 however is probably good as it is. Well, except the maps should be completely resaved I think, because when inspecting the map files I saw a bizarre, but somehow working mishmash of the current map format and older map formats (it took me a while to figure that out).

Should it be done before M3? Well, perhaps that'd be best. I reckon you'll still have quite a lot of work on it, and it would be nice to see something new relatively soon, be it any updates of existing games or whatever.

Release it as a "gold" version? Well, maybe it would be a good idea finish the beta stage of development first, lol.
Attached Files
 cave1.png (14.5 KB) PNG File
 cave2.png (6.5 KB) PNG File



This link is dead. It's only still here because, err... yknow, it's some sort of... memorial.


Edited: 02 August 2011 21:39


You need to login to create posts in this thread.

nyasudah
 Official Sponsor

Joined: 06 February 2005
Posts: 831
03 August 2011 06:49 (UK time)

ParaSait wrote:
I have various ideas in mind. Mazes, mazes of rooms, towns with houses, connected rooms, arena style levels,...

Sounds just like DoomRL :D

@James
I agree with ParaSait
nyasudah / masuda / mp / PetiX / PtX


Edited: 03 August 2011 06:50


You need to login to create posts in this thread.

James Bunting
Joined: 17 September 2003
Posts: 1302
03 August 2011 09:36 (UK time)

M1 and M2 "Gold" or (whatever) would be complete rewrites as the old code for both M1 and M2 and not really workable.

In effect this would be a total port from C to C++ for both games.

Thinking about M1, the changes I can see are 32x32 pixel tiles to handle modern screen resoutions and upsizing/improving all other graphics.

There would be be no real limits on the number of things due to proper memory allocation (std vectors) and new net code. Basically the new code will be very stable!


You need to login to create posts in this thread.

nyasudah
 Official Sponsor

Joined: 06 February 2005
Posts: 831
03 August 2011 14:02 (UK time)

new netcode is welcomed, the current one is barely working. it desyncs after a while for example which causes interesting results (like i remember parasait said on teh chat that he killed me again, but i was still moving and then just died seemingly randomly). reconnecting to server helps this a bit but it still goes out of sync. hopefully with the new code we can play smoothly over the internet
nyasudah / masuda / mp / PetiX / PtX


You need to login to create posts in this thread.

ParaSait

Joined: 26 June 2007
Posts: 1478
03 August 2011 14:44 (UK time)

Masuda wrote:
Sounds just like DoomRL :D
Oh, for sure. DoomRL is a very inspiring game you know. :p

James Bunting wrote:
M1 and M2 "Gold" or (whatever) would be complete rewrites as the old code for both M1 and M2 and not really workable.

In effect this would be a total port from C to C++ for both games.

Thinking about M1, the changes I can see are 32x32 pixel tiles to handle modern screen resoutions and upsizing/improving all other graphics.

There would be be no real limits on the number of things due to proper memory allocation (std vectors) and new net code. Basically the new code will be very stable!
Sound great... I'd say, GFI! :D

And yeah, netcode should be a very important (if not the most important) thing to improve. The Meteor games will be at least 5x the fun with properly working multiplayer I imagine.


This link is dead. It's only still here because, err... yknow, it's some sort of... memorial.


You need to login to create posts in this thread.

arezey

Joined: 16 June 2005
Posts: 1599
07 August 2011 11:05 (UK time)

ParaSait wrote:
And yeah, netcode should be a very important (if not the most important) thing to improve. The Meteor games will be at least 5x the fun with properly working multiplayer I imagine.

Working in multiplayer in Meteor? what is this blasphemy?!

:p



You need to login to create posts in this thread.

me_mantis

Joined: 26 September 2003
Posts: 1151
08 August 2011 21:06 (UK time)

Meteor /2 is a super fun MP game, and with a little bit of additions to the MP code, it would probably be wildly popular. It's fully featured, fully customizable, and way better than so many games out there.

The m1 lan code seems pretty stable though.. it's just missing "win" states. =)

You need to login to create posts in this thread.



Forums system (C) 1999, 2017 by James Bunting.

Terms of Use