1 module pixelperfectengine.map.mapdata;
2 /*
3  * Copyright (C) 2015-2017, by Laszlo Szeremi under the Boost license.
4  *
5  * Pixel Perfect Engine, map module
6  */
7 import std.stdio;
8 import std.file;
9 import std.conv;
10 import std.base64;
11 import pixelperfectengine.graphics.bitmap;
12 import pixelperfectengine.graphics.layers;
13 import pixelperfectengine.system.exc;
14 import pixelperfectengine.system.etc;
15 import core.stdc.stdlib;
16 import core.stdc.stdio;
17 import std.string;
18 
19 version(Windows){
20 	import core.sys.windows.windows;
21 	import std.windows.syserror;
22 }else{
23 	import core.stdc.errno;
24 }
25 
26 public import pixelperfectengine.system.exc;
27 
28 /**
29  * Contains the very basic data for the map binary file (*.mbf).
30  * Length of the map is calculated as `length = sizeX * sizeY`, all words are 32 bits long, so size of map in bytes
31  * equals `mapSize = length * 4`, and header should be 12 bytes in size.
32  * Maps are always starting in the top-left corner of their tile layers.
33  */
34 public struct MapDataHeader{
35 	public uint flags;		///Stores additional data about the binary map file as a boolean array. Bit 24-31 are user definable.
36 	public int sizeX;		///width of the map
37 	public int sizeY;		///Height of the map
38 	public enum RegisteredFlags {
39 		UD_PriorityField	=	1<<0,	///Priority field contains user-defined data
40 		UD_PalShiftField	=	1<<1,	///Palette-shift field contains user defined data
41 		Bit10AxisSwitch		=	1<<2,	///Bit 10 (bit 0 of priority field) switches X and Y axes
42 	}
43 	/**
44 	 * Creates a MapDataHeader with the supplied parameters.
45 	 * Params:
46 	 *   sizeX = Width of the map.
47 	 *   sizeY = Height of the map.
48 	 */
49 	this(int sizeX, int sizeY){
50 		//this.fileLength = cast(uint)(sizeX * sizeY + MapDataHeader.sizeof);
51 		this.sizeX = sizeX;
52 		this.sizeY = sizeY;
53 	}
54 }
55 
56 /**
57  * Saves a map to an external file.
58  * Will be deprecated soon.
59  */
60 public deprecated void saveMapFile(MapDataHeader* header, ref MappingElement[] map, string name){
61 	FILE* outputStream = fopen(toStringz(name), "wb");
62 	if(outputStream is null){
63 		import std.conv;
64 		version(Windows){
65 			DWORD errorCode = GetLastError();
66 		}else version(Posix){
67 			int errorCode = errno;
68 		}
69 		throw new FileAccessException("File access error! Error number: " ~ to!string(errorCode));
70 	}
71 
72 	fwrite(cast(void*)header, MapDataHeader.sizeof, 1, outputStream);
73 	fwrite(cast(void*)map.ptr, MappingElement.sizeof, map.length, outputStream);
74 
75 	fclose(outputStream);
76 }
77 /**
78  * Saves a map to an external file.
79  * See documentation about the format.
80  */ 
81 public void saveMapFile(F = File)(MapDataHeader header, MappingElement[] map, F file) @trusted {
82 	ubyte[] writeBuf = reinterpretAsArray!(ubyte)(header);
83 	file.rawWrite(writeBuf);
84 	file.rawWrite(map);
85 }
86 /**
87  * Loads a map from an external file.
88  */
89 public MappingElement[] loadMapFile(F = File)(F file, ref MapDataHeader header){
90 	ubyte[] readbuffer;
91 	MappingElement[] result;
92 	readbuffer.length = MapDataHeader.sizeof;
93 	readbuffer = file.rawRead(readbuffer);
94 	header = reinterpretGet!MapDataHeader(readbuffer);
95 	result.length = header.sizeX * header.sizeY;
96 	result = file.rawRead(result);
97 	return result;
98 }
99 
100 /**
101  * Loads a map from a BASE64 string.
102  */
103 public MappingElement[] loadMapFromBase64(in char[] input, int length){
104 	MappingElement[] result;
105 	result.length = length;
106 	Base64.decode(input, cast(ubyte[])cast(void[])result);
107 	return result;
108 }
109 
110 /**
111  * Saves a map to a BASE64 string.
112  */
113 public char[] saveMapToBase64(in MappingElement[] input){
114 	char[] result;
115 	Base64.encode(cast(ubyte[])cast(void[])input, result);
116 	return result;
117 }