/*
** 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;
}
}