Hi
Can you get me a compiled jar including the fix? I'm not a dev guy ...
I can reproduce the new problem and so far I've discovered another
constraint on the allowed values in the header, I will post a new
patch and build when I've got to the bottom of it.
New patch attached.
A jar is uploaded at:
URL: http://files.mkgmap.org.uk/download/12/mkgmap.jar
File: mkgmap.jar created on 05 may 2011
Description: version of mkgmap with patch for header size values.
..Steve
Index: src/uk/me/parabola/imgfmt/sys/BlockManager.java
===================================================================
--- src/uk/me/parabola/imgfmt/sys/BlockManager.java (revision 1634)
+++ src/uk/me/parabola/imgfmt/sys/BlockManager.java (revision )
@@ -31,11 +31,14 @@
private int currentBlock;
private int maxBlock = 0xfffe;
- private int numberAllocated;
+ private int maxBlockAllocated;
+ private final int initialBlock;
BlockManager(int blockSize, int initialBlock) {
this.blockSize = blockSize;
this.currentBlock = initialBlock;
+ this.initialBlock = initialBlock;
+ this.maxBlockAllocated = initialBlock;
}
/**
@@ -57,7 +60,7 @@
blockSize * 2, blockSize * 4);
throw new MapFailedException(message);
}
- numberAllocated++;
+ maxBlockAllocated++;
return n;
}
@@ -74,8 +77,13 @@
}
public void setCurrentBlock(int n) {
- if (numberAllocated != 0)
+ if (maxBlockAllocated != initialBlock)
throw new IllegalStateException("Blocks already allocated");
currentBlock = n;
+ maxBlockAllocated = n;
}
+
+ public int getMaxBlockAllocated() {
+ return maxBlockAllocated;
-}
+ }
+}
Index: src/uk/me/parabola/imgfmt/sys/ImgFS.java
===================================================================
--- src/uk/me/parabola/imgfmt/sys/ImgFS.java (revision 1932)
+++ src/uk/me/parabola/imgfmt/sys/ImgFS.java (revision )
@@ -239,7 +239,12 @@
public void close() {
try {
+ if (!readOnly) {
+ int allocatedBlocks = fileBlockManager.getMaxBlockAllocated();
+ System.out.println("max block " + allocatedBlocks);
+ header.setNumBlocks(allocatedBlocks);
- sync();
+ sync();
+ }
} catch (IOException e) {
log.debug("could not sync filesystem");
} finally {
Index: src/uk/me/parabola/imgfmt/sys/ImgHeader.java
===================================================================
--- src/uk/me/parabola/imgfmt/sys/ImgHeader.java (revision 1932)
+++ src/uk/me/parabola/imgfmt/sys/ImgHeader.java (revision )
@@ -19,6 +19,7 @@
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
+import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
@@ -48,7 +49,7 @@
// If this was a real boot sector these would be the meanings
private static final int OFF_SECTORS = 0x18;
private static final int OFF_HEADS = 0x1a;
- private static final int OFF_UNK_2 = 0x1c; // Previously cylinders, but no longer thought to be that
+ private static final int OFF_CYLS = 0x1c;
private static final int OFF_CREATION_YEAR = 0x39;
// private static final int OFF_CREATION_MONTH = 0x3b;
@@ -104,6 +105,8 @@
private static final byte[] SIGNATURE = {
'D', 'S', 'K', 'I', 'M', 'G', '\0'};
+ private int numBlocks;
+
ImgHeader(ImgChannel chan) {
this.file = chan;
header.order(ByteOrder.LITTLE_ENDIAN);
@@ -115,6 +118,7 @@
*/
void createHeader(FileSystemParam params) {
this.fsParams = params;
+ System.out.println("file size " + file.position());
header.put(OFF_XOR, (byte) 0);
@@ -148,62 +152,89 @@
// always assume it is 2 anyway.
header.put(OFF_DIRECTORY_START_BLOCK, (byte) fsParams.getDirectoryStartEntry());
+ header.position(OFF_CREATION_YEAR);
+ Utils.setCreationTime(header, creationTime);
+
+ setDirectoryStartEntry(params.getDirectoryStartEntry());
+
+ // Set the times.
+ Date date = new Date();
+ setCreationTime(date);
+ setUpdateTime(date);
+ setDescription(params.getMapDescription());
+
+ // Checksum is not checked.
+ int check = 0;
+ header.put(OFF_CHECKSUM, (byte) check);
+ }
+
+ private void writeSizeValues(int bs) {
+ System.out.println("numBlocks=" + numBlocks + ", bs=" + bs);
+ int endSector = (int) (((long) ((numBlocks+1) * bs + 511) / 512) + 1);
+
+ // 16 heads to 128
+ // 4 sectors to 32
+
+ System.out.println("endSector=" + endSector + ", from " + numBlocks);
+ int sectors = 32; // 6 bit value
+ int heads = 128;
+ int cyls = 0x400;
+
+ out:
+ for (int h : Arrays.asList(16, 32, 64, 128)) {
+ for (int s : Arrays.asList(4, 8, 16, 32)) {
+ for (int c = 0x20; c < 0x3ff; c += 0x20) {
+ int tot = s * h * c;
+ System.out.println("try " + tot + ", for mb=" + endSector);
+ if (tot > endSector) {
+ heads = h;
+ sectors = s;
+ cyls = c;
+ break out;
+ }
+ }
+ }
+ }
+
+ endSector = heads * sectors * cyls;
+ int lastSector = endSector - 1;
+
// This sectors, head, cylinders stuff appears to be used by mapsource
// and they have to be larger than the actual size of the map. It
// doesn't appear to have any effect on a garmin device or other software.
- int sectors = 0x20; // 0x3f is the max
header.putShort(OFF_SECTORS, (short) sectors);
- int heads = 0x80;
header.putShort(OFF_HEADS, (short) heads);
- int unknown = 0x400; // not known, doesn't appear to be related to fs size
- header.putShort(OFF_UNK_2, (short) unknown);
header.putShort(OFF_HEADS2, (short) heads);
header.putShort(OFF_SECTORS2, (short) sectors);
+ header.putShort(OFF_CYLS, (short) cyls);
- header.position(OFF_CREATION_YEAR);
- Utils.setCreationTime(header, creationTime);
-
- // The last LBA number in the partition. We always claim a large partition without
- // regard to what is actually stored. Total number of sectors is this plus one
- // as sector numbers start at zero.
- int endBlock = 0x3fffff;
-
// Since there are only 2 bytes here but it can easily overflow, if it
// does we replace it with 0xffff, it doesn't work to set it to say zero
- int blocks = endBlock / (1 << exp - 9);
+ int blocks = (int) (endSector * 512L / bs);
char shortBlocks = blocks > 0xffff ? 0xffff : (char) blocks;
header.putChar(OFF_BLOCK_SIZE, shortBlocks);
header.put(OFF_PARTITION_SIG, (byte) 0x55);
- header.put(OFF_PARTITION_SIG+1, (byte) 0xaa);
+ header.put(OFF_PARTITION_SIG + 1, (byte) 0xaa);
header.put(OFF_START_HEAD, (byte) 0);
header.put(OFF_START_SECTOR, (byte) 1);
header.put(OFF_START_CYLINDER, (byte) 0);
header.put(OFF_SYSTEM_TYPE, (byte) 0);
- int h = (endBlock / sectors) % heads;
- int s = (endBlock % sectors) + 1;
- int c = endBlock / (sectors * heads);
+ int h = (lastSector / sectors) % heads;
+ int s = (lastSector % sectors) + 1;
+ int c = lastSector / (sectors * heads);
+ assert h <= heads;
+ assert s <= sectors;
+ assert c < 0x400;
header.put(OFF_END_HEAD, (byte) (h));
- header.put(OFF_END_SECTOR, (byte) ((s) | ((c>>2) & 0xc0)));
+ header.put(OFF_END_SECTOR, (byte) ((s) | ((c >> 2) & 0xc0)));
header.put(OFF_END_CYLINDER, (byte) (c & 0xff));
header.putInt(OFF_REL_SECTORS, 0);
- header.putInt(OFF_NUMBER_OF_SECTORS, endBlock+1);
- log.info("number of blocks " + blocks);
-
- setDirectoryStartEntry(params.getDirectoryStartEntry());
-
- // Set the times.
- Date date = new Date();
- setCreationTime(date);
- setUpdateTime(date);
- setDescription(params.getMapDescription());
-
- // Checksum is not checked.
- int check = 0;
- header.put(OFF_CHECKSUM, (byte) check);
+ header.putInt(OFF_NUMBER_OF_SECTORS, endSector);
+ log.info("number of blocks " + lastSector);
}
void setHeader(ByteBuffer buf) {
@@ -242,6 +273,8 @@
public void sync() throws IOException {
setUpdateTime(new Date());
+ writeSizeValues(fsParams.getBlockSize());
+
header.rewind();
file.position(0);
file.write(header);
@@ -320,4 +353,8 @@
protected void setCreationTime(Date date) {
this.creationTime = date;
}
+
+ public void setNumBlocks(int numBlocks) {
+ this.numBlocks = numBlocks;
-}
+ }
+}
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev