/*
* Copyright (C) 2007 Steve Ratcliffe
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* Author: Steve Ratcliffe
* Create date: Dec 19, 2007
*/
package uk.me.parabola.imgfmt.mps;
import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import uk.me.parabola.imgfmt.app.BufferedImgFileReader;
import uk.me.parabola.imgfmt.app.ImgFileReader;
import uk.me.parabola.imgfmt.app.labelenc.CharacterDecoder;
import uk.me.parabola.imgfmt.app.labelenc.CodeFunctions;
import uk.me.parabola.imgfmt.fs.ImgChannel;
/**
* This file is a description of the map set that is loaded into the
* gmapsupp.img file and an index of the maps that it contains.
*
* It is different than all the other files that fit inside the gmapsupp file
* in that it doesn't contain the common header. So it does not extend ImgFile.
*
* @author Steve Ratcliffe
*/
public class MpsFileReader implements Closeable {
private final List<MapBlock> maps = new ArrayList<>();
private final List<ProductBlock> products = new ArrayList<>();
private final ImgChannel chan;
private final ImgFileReader reader;
private final CharacterDecoder decoder;
private final int codePage;
public MpsFileReader(ImgChannel chan, int codePage) {
this.chan = chan;
this.reader = new BufferedImgFileReader(chan);
this.codePage = codePage;
CodeFunctions funcs = CodeFunctions.createEncoderForLBL(0, codePage);
decoder = funcs.getDecoder();
readBlocks();
}
private void readBlocks() {
byte type;
while ((type = reader.get()) > 0) {
int len = reader.getChar();
switch (type) {
case 0x4c:
readMapBlock();
break;
case 0x46:
readProductBlock();
break;
default:
// We always know the length, so just read over it
reader.get(len);
break;
}
}
}
private void readMapBlock() {
MapBlock block = new MapBlock(codePage);
int val = reader.getInt();
block.setIds(val >>> 16, val & 0xffff);
block.setMapNumber(reader.getInt());
byte[] zString = reader.getZString();
block.setSeriesName(decodeToString(zString));
block.setMapDescription(decodeToString(reader.getZString()));
block.setAreaName(decodeToString(reader.getZString()));
block.setHexNumber(reader.getInt());
reader.getInt();
maps.add(block);
}
private void readProductBlock() {
ProductBlock block = new ProductBlock(codePage);
block.setProductId(reader.getChar());
block.setFamilyId(reader.getChar());
block.setDescription(decodeToString(reader.getZString()));
products.add(block);
}
private String decodeToString(byte[] zString) {
decoder.reset();
for (byte b : zString)
decoder.addByte(b);
return decoder.getText().getText();
}
public List<MapBlock> getMaps() {
return maps;
}
public List<ProductBlock> getProducts() {
return products;
}
public void close() throws IOException {
chan.close();
}
}