Rev 1870 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
/*
* Copyright (C) 2009.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 or
* 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.
*/
package uk.me.parabola.imgfmt.mdxfmt;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* The MDX index file. Used with the global index. This is located
* at the family level in the windows registry and can perhaps index
* across different products (and maybe families), although such a thing
* hasn't been seen.
*
* @author Steve Ratcliffe
*/
public class MdxFile
{
private final char familyId
;
private final char productId
;
private final List<MapInfo
> maps =
new ArrayList<MapInfo
>();
/**
* Create with default family and product ids.
* @param familyId The default family id that will be used if no other one
* is supplied.
* @param productId The default product id for the maps indexed by this
* file.
*/
public MdxFile
(int familyId,
int productId
) {
this.
familyId =
(char) familyId
;
this.
productId =
(char) productId
;
}
/**
* Add a map with the default family and product id's and with equal
* name and hex name.
* @param name The map name (from the filename of the map) as an integer.
* @param hexname The map id that is inside the TRE header
* @param filename The file name of the map being added. Mainly for diagnostics,
* it is not needed for the file.
*/
public void addMap
(int name,
int hexname,
String filename
) {
MapInfo info =
new MapInfo
();
info.
setHexMapname(hexname
);
info.
setMapname(name
);
info.
setFamilyId(familyId
);
info.
setProductId(productId
);
info.
setFilename(filename
);
maps.
add(info
);
}
/**
* Write the file out to the given filename.
*/
public void write
(String filename
) throws IOException {
FileOutputStream stream =
new FileOutputStream(filename
);
FileChannel chan = stream.
getChannel();
ByteBuffer buf =
ByteBuffer.
allocate(1024);
buf.
order(ByteOrder.
LITTLE_ENDIAN);
try {
writeHeader
(chan, buf
);
writeBody
(chan, buf
);
} finally {
chan.
close();
}
}
private void writeHeader
(WritableByteChannel chan,
ByteBuffer buf
) throws IOException {
try {
buf.
put("Midx".
getBytes("ascii"));
} catch (UnsupportedEncodingException e
) {
throw new IOException("Could not write header");
}
buf.
putChar((char) 100);
buf.
putInt(12);
buf.
putInt(maps.
size());
buf.
flip();
chan.
write(buf
);
}
private void writeBody
(WritableByteChannel chan,
ByteBuffer buf
) throws IOException {
// Sort the maps by the hex number.
Collections.
sort(maps,
new Comparator<MapInfo
>() {
public int compare
(MapInfo o1, MapInfo o2
) {
if (o1.
getHexMapname() == o2.
getHexMapname())
return 0;
else if (o1.
getHexMapname() < o2.
getHexMapname())
return -
1;
else
return 1;
}
});
for (MapInfo info : maps
) {
// Although its not necessarily wrong for them to be zero, it probably
// sign that something is wrong.
if (info.
getHexMapname() ==
0 || info.
getMapname() ==
0)
System.
err.
println("Invalid mapname for " + info.
getFilename() +
", perhaps it is not a .img file");
buf.
compact();
info.
write(buf
);
buf.
flip();
chan.
write(buf
);
}
}
}