23
24
import java.util.List;
24
25
import java.util.Map;
27
import uk.me.parabola.imgfmt.FileExistsException;
26
28
import uk.me.parabola.imgfmt.FileNotWritableException;
27
29
import uk.me.parabola.imgfmt.FileSystemParam;
28
import uk.me.parabola.imgfmt.FileExistsException;
29
import uk.me.parabola.imgfmt.mps.MpsFile;
30
import uk.me.parabola.imgfmt.mps.MapBlock;
31
30
import uk.me.parabola.imgfmt.fs.DirectoryEntry;
32
31
import uk.me.parabola.imgfmt.fs.FileSystem;
33
32
import uk.me.parabola.imgfmt.fs.ImgChannel;
33
import uk.me.parabola.imgfmt.mps.MapBlock;
34
import uk.me.parabola.imgfmt.mps.MpsFile;
35
import uk.me.parabola.imgfmt.sys.FileImgChannel;
34
36
import uk.me.parabola.imgfmt.sys.ImgFS;
35
import uk.me.parabola.imgfmt.sys.FileImgChannel;
36
37
import uk.me.parabola.log.Logger;
37
38
import uk.me.parabola.mkgmap.CommandArgs;
72
73
private String overallDescription = "Combined map";
74
private static final int DIRECTORY_OFFSET_BLOCK = 2;
74
76
public void init(CommandArgs args) {
75
familyId = args.get("family-id", 1331);
77
familyId = args.get("family-id", 0);
76
78
productId = args.get("product-id", 1);
78
80
familyName = args.get("family-name", "family name");
79
areaName = args.get("area-name", "area name");
81
areaName = args.get("area-name", null);
81
83
overallDescription = args.getDescription();
133
135
MapBlock mb = new MapBlock();
134
136
mb.setMapNumber(info.getMapnameAsInt());
135
137
mb.setMapName(info.getDescription());
136
mb.setAreaName(areaName);
138
mb.setAreaName(areaName != null ? areaName : "Area " + info.getMapname());
137
139
mb.setTypeName(familyName);
138
140
mb.setIds(familyId, productId);
168
170
private MpsFile createMpsFile(FileSystem outfs) throws FileNotWritableException {
170
ImgChannel channel = outfs.create("MAPSOURC.MPS");
171
MpsFile mps = new MpsFile(channel);
172
ImgChannel channel = outfs.create("MAKEGMAP.MPS");
173
return new MpsFile(channel);
173
174
} catch (FileExistsException e) {
174
175
// well it shouldn't exist!
175
176
log.error("could not create MPS file as it already exists");
186
187
private void addFile(FileSystem outfs, String filename) {
187
188
ImgChannel chan = new FileImgChannel(filename);
189
copyFile(chan, outfs, filename);
190
String imgname = createImgFilename(filename);
191
copyFile(chan, outfs, imgname);
190
192
} catch (IOException e) {
191
193
log.error("Could not open file " + filename);
198
* Create a suitable filename for use in the .img file from the external
201
* The external file name might look something like /home/steve/foo.typ
202
* or c:\maps\foo.typ and we need to take the filename part and make
203
* sure that it is no more than 8+3 characters.
205
* @param pathname The external filesystem path name.
206
* @return The filename part, will be restricted to 8+3 characters.
208
private String createImgFilename(String pathname) {
209
File f = new File(pathname);
210
String name = f.getName();
211
int dot = name.lastIndexOf('.');
213
String base = name.substring(0, dot);
214
String ext = name.substring(dot+1);
215
if (base.length() > 8)
216
base = base.substring(0, 8);
217
if (ext.length() > 3)
218
ext = ext.substring(0, 3);
220
return base + '.' + ext;
196
224
* Add a complete .img file, that is all the consituent files from it.
198
226
* @param outfs The gmapsupp file to write to.
244
272
private FileSystem createGmapsupp() throws FileNotWritableException {
245
273
BlockInfo bi = calcBlockSize();
246
274
int blockSize = bi.blockSize;
247
int reserved = 2 + bi.reserveBlocks + bi.headerSlots;
248
log.info("bs of", blockSize, "reserving", reserved);
250
275
// Create this file, containing all the sub files
251
276
FileSystemParam params = new FileSystemParam();
252
277
params.setBlockSize(blockSize);
253
278
params.setMapDescription(overallDescription);
254
params.setDirectoryStartBlock(2);
279
params.setDirectoryStartBlock(DIRECTORY_OFFSET_BLOCK);
281
int reserved = DIRECTORY_OFFSET_BLOCK + bi.reserveBlocks + bi.headerSlots;
282
log.info("bs of", blockSize, "reserving", reserved);
256
284
int reserve = (int) Math.ceil(reserved * 512.0 / blockSize);
257
285
params.setReservedDirectoryBlocks(reserve);
258
286
log.info("reserved", reserve);
260
FileSystem outfs = ImgFS.createFs(GMAPSUPP, params);
288
return ImgFS.createFs(GMAPSUPP, params);
314
* Calculate the block size that we need to use. I am calculating it so
315
* that the special directory entry doesn't require more than one block
316
* to hold its own block list.
341
* Calculate the block size that we need to use. The block size must be such that
342
* the total number of blocks is less than 0xffff.
344
* I am making sure that the that the root directory entry doesn't require
345
* more than one block to hold its own block list.
318
347
* @return A suitable block size to use for the gmapsupp.img file.
326
355
for (int bs : ints) {
327
357
int totHeaderSlots = 0;
328
358
for (FileInfo info : files.values()) {
359
totBlocks += info.getNumBlocks(bs);
329
360
// Each file will take up at least one directory block.
330
361
// Each directory block can hold 480 block-references
331
362
int slots = info.getNumHeaderSlots(bs);
336
367
totHeaderSlots += 2;
337
int totBlocks = totHeaderSlots * 512 / bs;
339
log.info("total blocks for", bs, "is", totBlocks, "based on slots=", totHeaderSlots);
341
if (totBlocks <= ENTRY_SIZE) {
342
// Add at least one for the MPS file
368
int totHeaderBlocks = totHeaderSlots * 512 / bs;
370
log.info("total blocks for", bs, "is", totHeaderBlocks, "based on slots=", totHeaderSlots);
372
if (totBlocks < 0xfffe && totHeaderBlocks <= ENTRY_SIZE) {
373
// Add one for the MPS file
343
374
totHeaderSlots += 1;
344
375
return new BlockInfo(bs, totHeaderSlots, totHeaderSlots / bs + 1);