public class ENDF {
	public static ENDF read(SmartByteBuffer data) throws Exception {
		ENDF instance = new ENDF();
		
		if (data.getInt() != 0 || data.position() != data.capacity()) {
			throw new Exception("Terminator mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream) throws Exception {
		outputStream.write("ENDF");
		outputStream.write(0);
	}
}
 public class SNDS {
	public List<Sound> sounds = new ArrayList<>();
	
	public static SNDS read(SmartByteBuffer data, boolean isYoda, File root) throws Exception {
		SNDS instance = new SNDS();
		
		int length = data.getInt();
		int lengthStart = data.position();

		short numSounds = (short) (data.getShort() * -1);

		for (int i = 0; i < numSounds; i++) {
			instance.sounds.add(Sound.read(data, isYoda, root));
		}
		
		if (lengthStart + length != data.position()) {
			throw new Exception("Length mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream, boolean isYoda, File root) throws Exception {
		outputStream.write("SNDS");
		outputStream.sectionStart();
		
		outputStream.write((short) (this.sounds.size() * -1));

		root = new File(root, isYoda ? "sfx/" : "");
		root.mkdirs();
		
		for (Sound sound : this.sounds) {
			sound.write(outputStream, isYoda, root);
		}
		
		byte[] section = outputStream.sectionEnd();
		outputStream.write(section.length);
		outputStream.write(section);
	}
	
	public static class Sound {
		public String name;
		public byte[] data;

		public static Sound read(SmartByteBuffer data, boolean isYoda, File root) throws Exception {
			Sound instance = new Sound();
			
			short nameLength = data.getShort();
			instance.name = new File(data.getString(-1, nameLength).trim()).getName();
			
			if (!instance.name.equals("")) {
				instance.data = Files.readAllBytes(new File(root, (isYoda ? "sfx/" : "") + instance.name).toPath());
			}
			
			return instance;
		}

		public void write(SmartByteArrayOutputStream outputStream, boolean isYoda, File root) throws Exception {
			outputStream.write((short) (this.name.length() + 1));
			outputStream.write(this.name);
			outputStream.write((byte) 0x00);
			
			if (!this.name.equals("")) {
				Files.write(new File(root, this.name).toPath(), this.data, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
			}
		}
	}
}
 public class STUP {
	public byte[] image = new byte[9 * 32 * 9 * 32];
	
	public static STUP read(SmartByteBuffer data) throws Exception {
		STUP instance = new STUP();
		
		int length = data.getInt();
		int lengthStart = data.position();
		
		data.get(instance.image);

		if (lengthStart + length != data.position()) {
			throw new Exception("Length mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream) {
		outputStream.write("STUP");
		outputStream.write(this.image.length);
		outputStream.write(this.image);
	}
}
 public class TILE {
	public List<Tile> tiles = new ArrayList<>();
	
	public static TILE read(SmartByteBuffer data) throws Exception {
		TILE instance = new TILE();
		
		int length = data.getInt();
		int lengthStart = data.position();
		
		while (data.position() < lengthStart + length) {
			instance.tiles.add(Tile.read(data));
		}

		if (lengthStart + length != data.position()) {
			throw new Exception("Length mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream) {
		outputStream.write("TILE");
		outputStream.sectionStart();
		
		for (Tile tile : this.tiles) {
			tile.write(outputStream);
		}

		byte[] section = outputStream.sectionEnd();
		outputStream.write(section.length);
		outputStream.write(section);
	}
	
	public static class Tile {
		public short type;
		public short subtype;
		public byte[] image = new byte[32 * 32];
		
		public static Tile read(SmartByteBuffer data) {
			Tile instance = new Tile();
			
			instance.type = data.getShort();
			instance.subtype = data.getShort();
			data.get(instance.image);
			
			return instance;
		}

		public void write(SmartByteArrayOutputStream outputStream) {
			outputStream.write(this.type);
			outputStream.write(this.subtype);
			outputStream.write(this.image);
		}
	}
}
 public class TNAM {
	public Map<Short, String> names = new LinkedHashMap<>();
	
	public static TNAM read(SmartByteBuffer data, boolean isYoda) throws Exception {
		TNAM instance = new TNAM();
		
		int length = data.getInt();
		int lengthStart = data.position();

		while (true) {
			short tileId = data.getShort();

			if (tileId == -1) {
				break;
			} else {
				instance.names.put(tileId, data.getString(-1, isYoda ? 24 : 16).trim());
			}
		}

		if (lengthStart + length != data.position()) {
			throw new Exception("Length mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream, boolean isYoda) {
		outputStream.write("TNAM");
		outputStream.sectionStart();
		
		for (Entry<Short, String> entry : this.names.entrySet()) {
			outputStream.write(entry.getKey());
			outputStream.write(entry.getValue());
			
			for (int i = entry.getValue().length(); i < (isYoda ? 24 : 16); i++) {
				outputStream.write((byte) 0);
			}
		}

		outputStream.write((short) -1);
		
		byte[] section = outputStream.sectionEnd();
		outputStream.write(section.length);
		outputStream.write(section);
	}
}
 public class VERS {
	public static VERS read(SmartByteBuffer data) throws Exception {
		VERS instance = new VERS();
		
		if (data.getInt() != 512) {
			throw new Exception("Version mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream) {
		outputStream.write("VERS");
		outputStream.write(512);
	}
}
 public class CHWP {
	private Map<Short, Weapon> weapons = new LinkedHashMap<>();
	
	public static CHWP read(SmartByteBuffer data) throws Exception {
		CHWP instance = new CHWP();
		
		int length = data.getInt();
		int lengthStart = data.position();

		while (true) {
			short characterId = data.getShort();

			if (characterId == -1) {
				break;
			} else {
				instance.weapons.put(characterId, Weapon.read(data));
			}
		}

		if (lengthStart + length != data.position()) {
			throw new Exception("Length mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream) throws Exception {
		outputStream.write("CHWP");
		outputStream.sectionStart();
		
		for (Entry<Short, Weapon> entry : this.weapons.entrySet()) {
			outputStream.write(entry.getKey());
			entry.getValue().write(outputStream);
		}

		outputStream.write((short) -1);
		
		byte[] section = outputStream.sectionEnd();
		outputStream.write(section.length);
		outputStream.write(section);
	}
	
	public static class Weapon {
		private short weaponOrSoundId;
		private short healthOrUnk;
		
		public static Weapon read(SmartByteBuffer data) {
			Weapon instance = new Weapon();
			
			instance.weaponOrSoundId = data.getShort();
			instance.healthOrUnk = data.getShort(); // TODO what is unk? 1? (if indy values change to 1 makes no difference, assume its 1 and 0 is buggy)

			return instance;
		}

		public void write(SmartByteArrayOutputStream outputStream) {
			outputStream.write(this.weaponOrSoundId);
			outputStream.write(this.healthOrUnk);
		}
	}
}
 public class HTSP {
	private Map<Short, List<Hotspot>> hotspots = new LinkedHashMap<>();
	
	public static HTSP read(SmartByteBuffer data) throws Exception {
		HTSP instance = new HTSP();

		int length = data.getInt();
		int lengthStart = data.position();

		while (true) {
			short zoneId = data.getShort();
			
			if (zoneId == -1) {
				break;
			}
			
			short amount = data.getShort();
			
			List<Hotspot> hotspots = new ArrayList<>();
			instance.hotspots.put(zoneId, hotspots);
			
			for (int i = 0; i < amount; i++) {
				hotspots.add(Hotspot.read(data));
			}
		}

		if (lengthStart + length != data.position()) {
			throw new Exception("Length mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream) {
		outputStream.write("HTSP");
		outputStream.sectionStart();

		for (Entry<Short, List<Hotspot>> entry : this.hotspots.entrySet()) {
			outputStream.write(entry.getKey());
			outputStream.write((short) entry.getValue().size());
			
			for (Hotspot hotspot : entry.getValue()) {
				hotspot.write(outputStream);
			}
		}
		
		outputStream.write((short) -1);
		
		byte[] section = outputStream.sectionEnd();
		outputStream.write(section.length);
		outputStream.write(section);
	}
	
	public static class Hotspot {
		private short type;
		private short x;
		private short y;
		private short param;

		public static Hotspot read(SmartByteBuffer data) {
			Hotspot instance = new Hotspot();
			
			instance.type = data.getShort();
			data.getShort(); // 0
			instance.x = data.getShort();
			instance.y = data.getShort();
			data.getShort(); // 1
			instance.param = data.getShort();
			
			return instance;
		}

		public void write(SmartByteArrayOutputStream outputStream) {
			outputStream.write(this.type);
			outputStream.write((short) 0);
			outputStream.write(this.x);
			outputStream.write(this.y);
			outputStream.write((short) 1);
			outputStream.write(this.param);
		}
	}
}
 public class ACTN {
	private Map<Short, List<IACT>> IACT = new LinkedHashMap<>();
	
	public static ACTN read(SmartByteBuffer data) throws Exception {
		ACTN instance = new ACTN();
		
		int length = data.getInt();
		int lengthStart = data.position();

		while (true) {
			short zoneId = data.getShort();
			
			if (zoneId == -1) {
				break;
			}
			
			short amount = data.getShort();
			
			List<IACT> iacts = new ArrayList<>();
			instance.IACT.put(zoneId, iacts);
			
			for (int i = 0; i < amount; i++) {
				String iact = data.getString(-1, 4);
				
				if (!iact.equals("IACT")) {
					throw new Exception("IACT mismatch.");
				}
				
				iacts.add(net.eiveo.original.sections.todo.determine_values.IACT.read(data, false));
			}
		}

		if (lengthStart + length != data.position()) {
			throw new Exception("Length mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream) {
		outputStream.write("ACTN");
		outputStream.sectionStart();

		for (Entry<Short, List<IACT>> entry : this.IACT.entrySet()) {
			outputStream.write(entry.getKey());
			outputStream.write((short) entry.getValue().size());
			
			for (IACT iact : entry.getValue()) {
				iact.write(outputStream, false);
			}
		}
		
		outputStream.write((short) -1);
		
		byte[] section = outputStream.sectionEnd();
		outputStream.write(section.length);
		outputStream.write(section);
	}
}
 public class ANAM {
	private Map<Short, Map<Short, String>> names = new LinkedHashMap<>();
	
	public static ANAM read(SmartByteBuffer data) throws Exception {
		ANAM instance = new ANAM();
		
		int length = data.getInt();
		int lengthStart = data.position();

		while (true) {
			short zoneId = data.getShort();

			if (zoneId == -1) {
				break;
			} else {
				Map<Short, String> names = new LinkedHashMap<>();
				instance.names.put(zoneId, names);

				while (true) {
					short actionId = data.getShort();

					if (actionId == -1) {
						break;
					} else {
						names.put(actionId, data.getString(-1, 16).trim());
					}
				}
			}
		}

		if (lengthStart + length != data.position()) {
			throw new Exception("Length mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream) {
		outputStream.write("ANAM");
		outputStream.sectionStart();
		
		for (Entry<Short, Map<Short, String>> entry : this.names.entrySet()) {
			outputStream.write(entry.getKey());
			
			for (Entry<Short, String> subEntry : entry.getValue().entrySet()) {
				outputStream.write(subEntry.getKey());
				outputStream.write(subEntry.getValue());
				
				for (int i = subEntry.getValue().length(); i < 16; i++) {
					outputStream.write((byte) 0);
				}
			}
			
			outputStream.write((short) -1);
		}

		outputStream.write((short) -1);
		
		byte[] section = outputStream.sectionEnd();
		outputStream.write(section.length);
		outputStream.write(section);
	}
}
 public class CAUX {
	private Map<Short, Short> damage = new LinkedHashMap<>();
	
	public static CAUX read(SmartByteBuffer data) throws Exception {
		CAUX instance = new CAUX();
		
		int length = data.getInt();
		int lengthStart = data.position();

		while (true) {
			short characterId = data.getShort();

			if (characterId == -1) {
				break;
			} else {
				instance.damage.put(characterId, data.getShort());
			}
		}

		if (lengthStart + length != data.position()) {
			throw new Exception("Length mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream) {
		outputStream.write("CAUX");
		outputStream.sectionStart();
		
		for (Entry<Short, Short> entry : this.damage.entrySet()) {
			outputStream.write(entry.getKey());
			outputStream.write(entry.getValue());
		}

		outputStream.write((short) -1);
		
		byte[] section = outputStream.sectionEnd();
		outputStream.write(section.length);
		outputStream.write(section);
	}
}
 public class CHAR {
	private List<ICHA> ICHA = new ArrayList<>();
	
	public static CHAR read(SmartByteBuffer data, boolean isYoda) throws Exception {
		CHAR instance = new CHAR();
		
		int length = data.getInt();
		int lengthStart = data.position();
		
		while (true) {
			short characterId = data.getShort();
			
			if (characterId == -1) {
				break;
			}

			String icha = data.getString(-1, 4);
			
			if (!icha.equals("ICHA")) {
				throw new Exception("ICHA mismatch.");
			}
			
			instance.ICHA.add(net.eiveo.original.sections.todo.not_converted_yet.ICHA.read(data, isYoda));
		}

		if (lengthStart + length != data.position()) {
			throw new Exception("Length mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream, boolean isYoda) throws Exception {
		outputStream.write("CHAR");
		outputStream.sectionStart();

		for (short i = 0; i < this.ICHA.size(); i++) {
			outputStream.write(i);
			this.ICHA.get(i).write(outputStream, isYoda);
		}

		outputStream.write((short) -1);
		
		byte[] section = outputStream.sectionEnd();
		outputStream.write(section.length);
		outputStream.write(section);
	}
}
 public class PNAM {
	private List<String> names = new ArrayList<>();
	
	public static PNAM read(SmartByteBuffer data) throws Exception {
		PNAM instance = new PNAM();
		
		int length = data.getInt();
		int lengthStart = data.position();

		short numEntries = data.getShort();

		for (int i = 0; i < numEntries; i++) {
			instance.names.add(data.getString(-1, 16).trim());
		}

		if (lengthStart + length != data.position()) {
			throw new Exception("Length mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream) {
		outputStream.write("PNAM");
		outputStream.sectionStart();
		
		outputStream.write((short) this.names.size());
		
		for (String name: this.names) {
			outputStream.write(name);
			
			for (int i = name.length(); i < 16; i++) {
				outputStream.write((byte) 0);
			}
		}
		
		byte[] section = outputStream.sectionEnd();
		outputStream.write(section.length);
		outputStream.write(section);
	}
}
 public class PUZ2 {
	private List<IPUZ> IPUZ = new ArrayList<>();

	public static PUZ2 read(SmartByteBuffer data, boolean isYoda) throws Exception {
		PUZ2 instance = new PUZ2();
		
		int length = data.getInt();
		int lengthStart = data.position();

		while (true) {
			short puzzleId = data.getShort();
			
			if (puzzleId == -1) {
				break;
			}

			String ipuz = data.getString(-1, 4);
			
			if (!ipuz.equals("IPUZ")) {
				throw new Exception("IPUZ mismatch.");
			}
			
			instance.IPUZ.add(net.eiveo.original.sections.todo.determine_values.IPUZ.read(data, isYoda));
		}

		if (lengthStart + length != data.position()) {
			throw new Exception("Length mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream, boolean isYoda) throws Exception {
		outputStream.write("PUZ2");
		outputStream.sectionStart();

		for (int i = 0; i < this.IPUZ.size(); i++) {
			outputStream.write((short) i);
			this.IPUZ.get(i).write(outputStream, isYoda);
		}

		outputStream.write((short) -1);
		
		byte[] section = outputStream.sectionEnd();
		outputStream.write(section.length);
		outputStream.write(section);
	}
}
 public class ZAUX {
	private List<IZAX> IZAX = new ArrayList<>();
	
	public static ZAUX read(SmartByteBuffer data) throws Exception {
		ZAUX instance = new ZAUX();
		
		int length = data.getInt();
		int lengthStart = data.position();
		
		while (length + lengthStart > data.position()) {
			String izax = data.getString(-1, 4);
			
			if (!izax.equals("IZAX")) {
				throw new Exception("IZAX mismatch.");
			}
			
			instance.IZAX.add(net.eiveo.original.sections.todo.determine_values.IZAX.read(data, false));
		}

		if (lengthStart + length != data.position()) {
			throw new Exception("Length mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream) {
		outputStream.write("ZAUX");
		outputStream.sectionStart();

		for (IZAX izax : this.IZAX) {
			izax.write(outputStream, false);
		}
		
		byte[] section = outputStream.sectionEnd();
		outputStream.write(section.length);
		outputStream.write(section);
	}
}
 public class ZAX2 {
	private List<IZX2> IZX2 = new ArrayList<>();
	
	public static ZAX2 read(SmartByteBuffer data) throws Exception {
		ZAX2 instance = new ZAX2();
		
		int length = data.getInt();
		int lengthStart = data.position();
		
		while (length + lengthStart > data.position()) {
			String izx2 = data.getString(-1, 4);
			
			if (!izx2.equals("IZX2")) {
				throw new Exception("IZX2 mismatch.");
			}

			instance.IZX2.add(net.eiveo.original.sections.todo.not_converted_yet.IZX2.read(data));
		}

		if (lengthStart + length != data.position()) {
			throw new Exception("Length mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream) {
		outputStream.write("ZAX2");
		outputStream.sectionStart();

		for (IZX2 izx2 : this.IZX2) {
			izx2.write(outputStream);
		}
		
		byte[] section = outputStream.sectionEnd();
		outputStream.write(section.length);
		outputStream.write(section);
	}
}
 public class ZAX3 {
	private List<IZX3> IZX3 = new ArrayList<>();
	
	public static ZAX3 read(SmartByteBuffer data) throws Exception {
		ZAX3 instance = new ZAX3();
		
		int length = data.getInt();
		int lengthStart = data.position();
		
		while (length + lengthStart > data.position()) {
			String izx3 = data.getString(-1, 4);
			
			if (!izx3.equals("IZX3")) {
				throw new Exception("IZX3 mismatch.");
			}

			instance.IZX3.add(net.eiveo.original.sections.todo.not_converted_yet.IZX3.read(data));
		}

		if (lengthStart + length != data.position()) {
			throw new Exception("Length mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream) {
		outputStream.write("ZAX3");
		outputStream.sectionStart();

		for (IZX3 izx3 : this.IZX3) {
			izx3.write(outputStream);
		}
		
		byte[] section = outputStream.sectionEnd();
		outputStream.write(section.length);
		outputStream.write(section);
	}
}
 public class ZAX4 {
	private List<IZX4> IZX4 = new ArrayList<>();
	
	public static ZAX4 read(SmartByteBuffer data) throws Exception {
		ZAX4 instance = new ZAX4();
		
		int length = data.getInt();
		int lengthStart = data.position();
		
		while (length + lengthStart > data.position()) {
			String izx4 = data.getString(-1, 4);
			
			if (!izx4.equals("IZX4")) {
				throw new Exception("IZX4 mismatch.");
			}

			instance.IZX4.add(net.eiveo.original.sections.todo.determine_values.IZX4.read(data));
		}

		if (lengthStart + length != data.position()) {
			throw new Exception("Length mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream) {
		outputStream.write("ZAX4");
		outputStream.sectionStart();

		for (IZX4 izx4 : this.IZX4) {
			izx4.write(outputStream);
		}
		
		byte[] section = outputStream.sectionEnd();
		outputStream.write(section.length);
		outputStream.write(section);
	}
}
 public class ZNAM {
	private Map<Short, String> names = new LinkedHashMap<>();
	
	public static ZNAM read(SmartByteBuffer data) throws Exception {
		ZNAM instance = new ZNAM();
		
		int length = data.getInt();
		int lengthStart = data.position();

		while (true) {
			short zoneId = data.getShort();

			if (zoneId == -1) {
				break;
			} else {
				int nameStart = data.position();
				instance.names.put(zoneId, data.getString()); // Filled with trash - bug
				data.position(nameStart + 16);
			}
		}

		if (lengthStart + length != data.position()) {
			throw new Exception("Length mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream) {
		outputStream.write("ZNAM");
		outputStream.sectionStart();
		
		for (Entry<Short, String> entry : this.names.entrySet()) {
			outputStream.write(entry.getKey());
			outputStream.write(entry.getValue());
			
			for (int i = entry.getValue().length(); i < 16; i++) {
				outputStream.write((byte) 0);
			}
		}

		outputStream.write((short) -1);
		
		byte[] section = outputStream.sectionEnd();
		outputStream.write(section.length);
		outputStream.write(section);
	}
}
 public class ZONE {
	public List<Zone> zones = new ArrayList<>();
	
	public static ZONE read(SmartByteBuffer data, boolean isYoda) throws Exception {
		ZONE instance = new ZONE();
		
		int length = 0;
		int lengthStart = 0;

		if (!isYoda) {
			length = data.getInt();
			lengthStart = data.position();
		}
		
		short zoneCount = data.getShort();
		
		for (short i = 0; i < zoneCount; i++) {
			instance.zones.add(Zone.read(data, isYoda, i));
		}
		
		if (!isYoda && lengthStart + length != data.position()) {
			throw new Exception("Length mismatch.");
		}
		
		return instance;
	}

	public void write(SmartByteArrayOutputStream outputStream, boolean isYoda) {
		outputStream.write("ZONE");
		outputStream.sectionStart();
		
		outputStream.write((short) this.zones.size());
		
		for (short i = 0; i < this.zones.size(); i++) {
			this.zones.get(i).write(outputStream, isYoda, i);
		}

		byte[] section = outputStream.sectionEnd();
		
		if (!isYoda) {
			outputStream.write(section.length);
		}
		
		outputStream.write(section);
	}
	
	public static class Zone {
		public short world;
		public IZON IZON;
		private List<Hotspot> hotspots = new ArrayList<>();
		public IZAX IZAX;
		public IZX2 IZX2;
		public IZX3 IZX3;
		public IZX4 IZX4;
		private List<IACT> IACT = new ArrayList<>();

		public static Zone read(SmartByteBuffer data, boolean isYoda, short zoneId) throws Exception {
			Zone instance = new Zone();

			int length = 0;
			int lengthStart = 0;
			
			if (isYoda) {
				instance.world = data.getShort();
				length = data.getInt();
				lengthStart = data.position();
				
				if (zoneId != data.getShort()) {
					throw new Exception("ZoneId Mismatch.");
				}
			}
			
			String izon = data.getString(-1, 4);
			
			if (!izon.equals("IZON")) {
				throw new Exception("IZON mismatch.");
			}
			
			instance.IZON = net.eiveo.original.sections.IZON.read(data, isYoda, instance.world);
			
			if (isYoda) {
				short amount = data.getShort();

				for (int j = 0; j < amount; j++) {
					instance.hotspots.add(Hotspot.read(data));
				}
				
				String izax = data.getString(-1, 4);
				
				if (!izax.equals("IZAX")) {
					throw new Exception("IZAX mismatch.");
				}
				
				instance.IZAX = net.eiveo.original.sections.todo.determine_values.IZAX.read(data, isYoda);
				
				String izx2 = data.getString(-1, 4);
				
				if (!izx2.equals("IZX2")) {
					throw new Exception("IZX2 mismatch.");
				}
				
				instance.IZX2 = net.eiveo.original.sections.todo.not_converted_yet.IZX2.read(data);
				
				String izx3 = data.getString(-1, 4);
				
				if (!izx3.equals("IZX3")) {
					throw new Exception("IZX3 mismatch.");
				}

				instance.IZX3 = net.eiveo.original.sections.todo.not_converted_yet.IZX3.read(data);
				
				String izx4 = data.getString(-1, 4);
				
				if (!izx4.equals("IZX4")) {
					throw new Exception("IZX4 mismatch.");
				}

				instance.IZX4 = net.eiveo.original.sections.todo.determine_values.IZX4.read(data);
				
				amount = data.getShort();
				
				for (int j = 0; j < amount; j++) {
					String iact = data.getString(-1, 4);
					
					if (!iact.equals("IACT")) {
						throw new Exception("IACT mismatch.");
					}
					
					instance.IACT.add(net.eiveo.original.sections.todo.determine_values.IACT.read(data, isYoda));
				}
			}
			
			if (isYoda && lengthStart + length != data.position()) {
				throw new Exception("Length mismatch.");
			}
			
			return instance;
		}

		public void write(SmartByteArrayOutputStream outputStream, boolean isYoda, short zoneId) {
			outputStream.sectionStart();

			if (isYoda) {
				outputStream.write(zoneId);
			}
			
			this.IZON.write(outputStream, isYoda);
			
			if (isYoda) {
				outputStream.write((short) this.hotspots.size());

				for (Hotspot hotspot : this.hotspots) {
					hotspot.write(outputStream);
				}
				
				this.IZAX.write(outputStream, isYoda);
				this.IZX2.write(outputStream);
				this.IZX3.write(outputStream);
				this.IZX4.write(outputStream);

				outputStream.write((short) this.IACT.size());
				
				for (IACT iact : this.IACT) {
					iact.write(outputStream, isYoda);
				}
			}

			byte[] section = outputStream.sectionEnd();
			
			if (isYoda) {
				outputStream.write(this.world);
				outputStream.write(section.length);
			}
			
			outputStream.write(section);
		}
	}
}
 public class SmartByteArrayOutputStream {
	private List<ByteArrayOutputStream> sections = new ArrayList<>();
	private ByteArrayOutputStream section;
	
	public SmartByteArrayOutputStream() {
		this.section = new ByteArrayOutputStream();
		this.sections.add(this.section);
	}

	public void sectionStart() {
		this.section = new ByteArrayOutputStream();
		this.sections.add(this.section);
	}
	
	public byte[] sectionEnd() {
		byte[] result = this.section.toByteArray();
		sections.remove(sections.size() - 1);
		this.section = sections.get(sections.size() - 1);
		return result;
	}

	public byte[] toByteArray() {
		return this.section.toByteArray();
	}

	public void write(String string) {
		for (byte byteData : string.getBytes()) {
			this.section.write(byteData);
		}
	}

	public void write(byte value) {
		this.section.write(value);
	}

	public void write(byte[] value) {
		for (byte byteData : value) {
			this.section.write(byteData);
		}
	}

	public void write(short value) {
		for (byte byteData : new byte[] {
	        (byte) value,
	        (byte)(value >> 8)
        }) {
			this.section.write(byteData);
		}
	}

	public void write(int value) {
		for (byte byteData : new byte[] {
	        (byte) value,
	        (byte)(value >> 8),
	        (byte)(value >> 16),
	        (byte)(value >> 24)
        }) {
			this.section.write(byteData);
		}
	}
}
 public class SmartByteBuffer {
	private ByteBuffer byteBuffer;

	public int capacity() {
		return this.byteBuffer.capacity();
	}

	public byte get() {
		return this.byteBuffer.get();
	}

	public void get(byte[] dst) {
		this.byteBuffer.get(dst);
	}

	public int getInt() {
		return this.byteBuffer.getInt();
	}

	public short getShort() {
		return this.byteBuffer.getShort();
	}

	public String getString() {
		String string = "";
		
		while (true) {
			byte character = this.get();
			if ((character & 0xff) == 0) {
				break;
			} else {
				string += new String(new byte[] { character });
			}
		}
		
		return string;
	}

	public String getString(int index, int length) {
		byte[] output = new byte[length];
		if (index > -1) {
			this.position(index);
		}
		this.byteBuffer.get(output);
		return new String(output);
	}

	public void order(ByteOrder bo) {
		this.byteBuffer.order(bo);
	}

	public int position() {
		return this.byteBuffer.position();
	}
	
	public void position(int newPosition) {
		this.byteBuffer.position(newPosition);
	}

	public static SmartByteBuffer wrap(byte[] array) {
		SmartByteBuffer instance = new SmartByteBuffer();
		instance.byteBuffer = ByteBuffer.wrap(array);
		return instance;
	}
}

import java.io.File;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import net.eiveo.original.sections.ENDF;
import net.eiveo.original.sections.SNDS;
import net.eiveo.original.sections.STUP;
import net.eiveo.original.sections.TILE;
import net.eiveo.original.sections.TNAM;
import net.eiveo.original.sections.VERS;
import net.eiveo.original.sections.todo.determine_values.CHWP;
import net.eiveo.original.sections.todo.determine_values.HTSP;
import net.eiveo.original.sections.todo.not_converted_yet.ACTN;
import net.eiveo.original.sections.todo.not_converted_yet.ANAM;
import net.eiveo.original.sections.todo.not_converted_yet.CAUX;
import net.eiveo.original.sections.todo.not_converted_yet.CHAR;
import net.eiveo.original.sections.todo.not_converted_yet.PNAM;
import net.eiveo.original.sections.todo.not_converted_yet.PUZ2;
import net.eiveo.original.sections.todo.not_converted_yet.ZAUX;
import net.eiveo.original.sections.todo.not_converted_yet.ZAX2;
import net.eiveo.original.sections.todo.not_converted_yet.ZAX3;
import net.eiveo.original.sections.todo.not_converted_yet.ZAX4;
import net.eiveo.original.sections.todo.not_converted_yet.ZNAM;
import net.eiveo.original.sections.todo.not_converted_yet.ZONE;
import net.eiveo.utils.SmartByteArrayOutputStream;
import net.eiveo.utils.SmartByteBuffer;

package net.eiveo.original;



public class Container {
	public VERS VERS; // VERSion

	public STUP STUP; // STartUP
	public SNDS SNDS; // SouNDS
	public TILE TILE; // TILEs
	
	public ZONE ZONE; // ZONEs
		// => IZON; // Items of ZONe
		// => IZAX; // Items of Zone AuXiliary 1 - Only in Yoda Stories
		// => IZX2; // Items of Zone AuXiliary 2 - Only in Yoda Stories
		// => IZX3; // Items of Zone AuXiliary 3 - Only in Yoda Stories
		// => IZX4; // Items of Zone AuXiliary 4 - Only in Yoda Stories
		// => IACT; // Items of ACTion - Only in Yoda Stories
	public ZAUX ZAUX; // Zone AUXiliary 1 - Not in Yoda Stories - has been merged into ZONE
		// => IZAX; // Items of Zone AuXiliary 1
	public ZAX2 ZAX2; // Zone AUXiliary 2 - Not in Yoda Stories - has been merged into ZONE
		// => IZX2; // Items of Zone AuXiliary 2
	public ZAX3 ZAX3; // Zone AUXiliary 3 - Not in Yoda Stories - has been merged into ZONE
		// => IZX3; // Items of Zone AuXiliary 3
	public ZAX4 ZAX4; // Zone AUXiliary 4 - Not in Yoda Stories - has been merged into ZONE
		// => IZX4; // Items of Zone AuXiliary 4
	public HTSP HTSP; // HoTSPots - Not in Yoda Stories - has been merged into ZONE
	public ACTN ACTN; // ACTioN - Not in Yoda Stories - has been merged into ZONE
		// => IACT; // Items of ACTion
	
	public PUZ2 PUZ2; // PUZzles
		// => IPUZ; // Items of PUZzle
	
	public CHAR CHAR; // CHARacters
		// => ICHA; // Items of CHAracters
	public CHWP CHWP; //CHaracter WeaPons

	public CAUX CAUX; // Character-AUXiliary
