/* ** 2011 April 5 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. */ package info.ata4.bsplib.lump; import info.ata4.bsplib.BspFile; import info.ata4.io.buffer.ByteBufferUtils; import info.ata4.log.LogUtils; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.file.Path; import java.util.logging.Level; import java.util.logging.Logger; /** * Low-level LMP file class for header and lump data access. * * @author Nico Bergemann <barracuda415 at yahoo.de> */ public class LumpFile { private static final Logger L = LogUtils.getLogger(); public static final int HEADER_SIZE = 20; // lump data private Lump lump; // .lmp source file private Path file; // required to create the lump object private int bspVersion; // fields from lumpfileheader_t private int mapRev; public LumpFile(BspFile bsp) { this(bsp.getVersion()); mapRev = bsp.getRevision(); } public LumpFile(int bspVersion) { this.bspVersion = bspVersion; } public void load(Path file, ByteOrder bo) throws IOException { this.file = file; L.log(Level.FINE, "Loading lump header from {0}", file.getFileName()); ByteBuffer bb = ByteBufferUtils.openReadOnly(file); bb.order(bo); // make sure we have enough room for reading if (bb.capacity() < HEADER_SIZE) { throw new LumpException("Invalid or missing lump header"); } // header int lumpOffset = bb.getInt(); int lumpIndex = bb.getInt(); int lumpVersion = bb.getInt(); int lumpSize = bb.getInt(); mapRev = bb.getInt(); L.log(Level.FINER, "Lump offset: {0}", lumpOffset); L.log(Level.FINER, "Lump ID: {0}", lumpIndex); L.log(Level.FINER, "Lump version: {0}", lumpVersion); L.log(Level.FINER, "Lump size: {0}", lumpSize); L.log(Level.FINER, "Map revision: {0}", mapRev); if (lumpOffset != HEADER_SIZE) { throw new LumpException("Unexpected lump offset: " + lumpOffset); } if (lumpIndex < 0 || lumpIndex > BspFile.HEADER_LUMPS) { throw new LumpException("Invalid lump ID: " + lumpIndex); } if (lumpSize < 0 || lumpOffset > bb.limit()) { throw new LumpException("Invalid lump size: " + lumpOffset); } // lump data lump = new Lump(lumpIndex, LumpType.get(lumpIndex, bspVersion)); lump.setBuffer(ByteBufferUtils.getSlice(bb, lumpOffset, lumpSize)); lump.setOffset(lumpOffset); lump.setParentFile(file); } public void load(Path file) throws IOException { load(file, ByteOrder.LITTLE_ENDIAN); } public void save(Path file) throws IOException { if (lump == null) { throw new NullPointerException("Lump is undefined"); } L.log(Level.FINE, "Saving lump header to {0}", file.getFileName()); int size = HEADER_SIZE + lump.getLength(); ByteBuffer bb = ByteBufferUtils.openReadWrite(file, 0, size); bb.order(lump.getBuffer().order()); // header bb.putInt(HEADER_SIZE); bb.putInt(lump.getIndex()); bb.putInt(lump.getVersion()); bb.putInt(lump.getLength()); bb.putInt(mapRev); L.log(Level.FINE, "Saving lump data to {0}", file.getFileName()); // lump data bb.put(lump.getBuffer()); } public Lump getLump() { return lump; } public void setLump(Lump lump) { this.lump = lump; } public Path getFile() { return file; } public int getMapRev() { return mapRev; } public void setMapRev(int mapRev) { this.mapRev = mapRev; } public int getBspVersion() { return bspVersion; } public void setBspVersion(int bspVersion) { this.bspVersion = bspVersion; } }