Hello.
How do I read a .map file in code? So I can render it the way I want.
I've seen this documentation: http://fabiensanglar...3d/BUILDINF.TXT
But I don't know where to start.
I can see there is a struct for the walls (walltype), which I believe it is what I need.
But how do I "extract" these structs from the .map file?
Any directions will be appreciated!
(I've just realized that I posted this in the wrong section, should be on "Duke Nukem 3D maps & level editing")
Page 1 of 1
How to read a .MAP file in code
#1 Posted 11 July 2017 - 08:35 PM
This post has been edited by Blackthorn: 11 July 2017 - 08:39 PM
#2 Posted 11 July 2017 - 11:17 PM
You can't really extract any other way than simply reading the contents and doing basic calculations on byte sizes.
Let's see...
A map file can be split in to four basic blocks:
> HEADER
> SECTORS
> WALLS
> SPRITES
They are all in one block, HEADER is mostly stuff like starting positions. This is always fixed in size to be 20 bytes
Each block (sector/wall/sprite) has 2 bytes at the start that tell you how many instances there are, a single instance is fixed in size but the amount is variable and is specified on the first 2 bytes of each block.
From the doc, a single sector definition is 40 bytes total, these 40 bytes are fixed in size and contain all the needed information for handling a single sector.
Walls are 32 bytes and sprites 44 bytes.
Let's pretend that a map has 11 sectors, 80 walls and 23 sprites.
-20 bytes header-
After this, the 2 bytes would be 11 to tell us that there are 11 sectors, the next bytes after are the sectors themselves.
11 * 40 bytes = 440 bytes
This means that walls would start at 440 bytes (sectors) + 2 bytes (sector amount indicator) + 20 bytes (header) = 462 bytes in.
Same formula repeats for walls/sprites.
So in short:
20 bytes of header
--
2 bytes of sector count
440 bytes of sectordata
--
2 bytes of wallcount
2560 bytes of walldata
--
2 bytes of spritecount
1012 bytes of spritedata
This results in a 4038 byte .map file.
Now you have the basics for reading map contents, but you still should study the data types inside those structs (easy way would be to display sprites only as it's x/y/z). For wall drawing and sectors, you'll need to cross reference stuff from walls when reading sectors.
I'll provide you the source for my svg stuff later.
Let's see...
A map file can be split in to four basic blocks:
> HEADER
> SECTORS
> WALLS
> SPRITES
They are all in one block, HEADER is mostly stuff like starting positions. This is always fixed in size to be 20 bytes
Each block (sector/wall/sprite) has 2 bytes at the start that tell you how many instances there are, a single instance is fixed in size but the amount is variable and is specified on the first 2 bytes of each block.
From the doc, a single sector definition is 40 bytes total, these 40 bytes are fixed in size and contain all the needed information for handling a single sector.
Walls are 32 bytes and sprites 44 bytes.
Let's pretend that a map has 11 sectors, 80 walls and 23 sprites.
-20 bytes header-
After this, the 2 bytes would be 11 to tell us that there are 11 sectors, the next bytes after are the sectors themselves.
11 * 40 bytes = 440 bytes
This means that walls would start at 440 bytes (sectors) + 2 bytes (sector amount indicator) + 20 bytes (header) = 462 bytes in.
Same formula repeats for walls/sprites.
So in short:
20 bytes of header
--
2 bytes of sector count
440 bytes of sectordata
--
2 bytes of wallcount
2560 bytes of walldata
--
2 bytes of spritecount
1012 bytes of spritedata
This results in a 4038 byte .map file.
Now you have the basics for reading map contents, but you still should study the data types inside those structs (easy way would be to display sprites only as it's x/y/z). For wall drawing and sectors, you'll need to cross reference stuff from walls when reading sectors.
I'll provide you the source for my svg stuff later.
#3 Posted 12 July 2017 - 06:51 AM
Hey oasiz.
Wow, this is golden information! Thanks a lot for being so supportive!
I think I just got it. I've created a simple .map with 1 sector and 4 walls, then ran this bit of code (C#):
The counter values seems to be correct, I just don't understand what the second byte is.
Ran the same code with a bigger map (mapster says it has 603 sectors, 3876 walls and 1531 sprites), got:
What does it mean? Am I reading it the wrong way?
Wow, this is golden information! Thanks a lot for being so supportive!
I think I just got it. I've created a simple .map with 1 sector and 4 walls, then ran this bit of code (C#):
var sectorSize = 40; var wallSize = 32; var spriteSize = 44; var fileStream = File.OpenRead(map); // map is the path to the .map file var binaryReader = new BinaryReader(fileStream); var header = binaryReader.ReadBytes(20); var sectorCount = binaryReader.ReadBytes(2)[0]; // 1 var sectors = binaryReader.ReadBytes(sectorCount * sectorSize); var wallCount = binaryReader.ReadBytes(2)[0]; // 4 var walls = binaryReader.ReadBytes(wallCount * wallSize); var spriteCount = binaryReader.ReadBytes(2)[0]; // 0 var sprites = binaryReader.ReadBytes(spriteCount * spriteSize);
The counter values seems to be correct, I just don't understand what the second byte is.
Ran the same code with a bigger map (mapster says it has 603 sectors, 3876 walls and 1531 sprites), got:
sectorCount[0] // 91 sectorCount[1] // 2
What does it mean? Am I reading it the wrong way?
#4 Posted 12 July 2017 - 06:58 AM
You're trying to read the values as individual byte values, rather than the correct types. The sector count is a short (which is a two-byte value), so you should use BinaryReader::ReadInt16 instead of BinaryReader::ReadBytes (unless you want to use the BitConverter class).
#5 Posted 12 July 2017 - 07:08 AM
TheZombieKiller, on 12 July 2017 - 06:58 AM, said:
You're trying to read the values as individual byte values, rather than the correct types. The sector count is a short (which is a two-byte value), so you should use BinaryReader::ReadInt16 instead of BinaryReader::ReadBytes (unless you want to use the BitConverter class).
Silly me, thanks a lot mate!
Now I'll figure out how to deserialize the struct types to the actual structs.
#6 Posted 12 July 2017 - 11:15 AM
sources sent, also linked a svgmap that works with parameters and doesn't ask difficult questions (plus is a lot faster)
#7 Posted 12 July 2017 - 02:09 PM
Hell yeah boyz!
Just successfully unserialized the structs from the .map file.
Understood what each member meant, it's all pretty easy now.
I'vepseudorendered a simple map with C# (see the attachment).
Now I can keep going on by my own.
Huge thanks to oasiz and TheZombieKiller, that information was crucial for me.
I'll share my code here when I fully understand what each member of all structs mean and where to render them.
Soon (dn4ever scale) you guys will see my new netplay guider/launcher!
Thanks again!
Just successfully unserialized the structs from the .map file.
Understood what each member meant, it's all pretty easy now.
I've
Now I can keep going on by my own.
Huge thanks to oasiz and TheZombieKiller, that information was crucial for me.
I'll share my code here when I fully understand what each member of all structs mean and where to render them.
Soon (dn4ever scale) you guys will see my new netplay guider/launcher!
Thanks again!
#8 Posted 14 July 2017 - 09:53 AM
Ken has his directions to read Build maps written in terms of C coding, but reading and interpreting his map format is pretty much straightforward as far as you're familiar with structures, bitfields, and integer types. Of course, there are some peculiarities which need to be taken into account (for example, all Z coordinates are scaled by a factor of 16 compared to horizontal coordinates). Perhaps you'll figure most things out using trial-and-error approach. Good luck with your app!
#9 Posted 16 July 2017 - 08:46 AM
This might be useful for someone. A friend and I wrote this in QBASIC years ago (17 or so) to learn the map format so we could screw with it a bit in other applications.
http://blackwell.duk...progs/build.bas
http://blackwell.duk...progs/build.bas
Share this topic:
Page 1 of 1