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 }