Hi
Just another thought ... could it be that C/H/S information should be
calculated dynamically based on the actual size of a .img-file?
Maybe this could save memory on a GPS when the tiles are loaded ... this
is speculation since I don't know exactly how this is implemented.
Yes it should be. I just hoped that it would not be required, as it
always worked when the max size was smaller. ;)
I'll see what it would take to get the size into the header.
After merging changes from trunk to locator branch I have the same
problem with the mkgmap-locator. Is there any other information I can
supply or any test to run to help debugging this issue?
_______________________________________________
mkgmap-dev mailing list
mkgmap-dev@lists.mkgmap.org.uk
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev
OK the attached patch should now take into account the exact size of the
file when setting the 'partition size' in the header.
There is a minimum size of 2048 512 byte sectors, anything larger than
that is calculated just a little larger, so any mistake will cause a
problem. Works for me so far.
..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,7 +31,7 @@
private int currentBlock;
private int maxBlock = 0xfffe;
- private int numberAllocated;
+ private int maxBlockAllocated;
BlockManager(int blockSize, int initialBlock) {
this.blockSize = blockSize;
@@ -57,7 +57,7 @@
blockSize * 2, blockSize * 4);
throw new MapFailedException(message);
}
- numberAllocated++;
+ maxBlockAllocated++;
return n;
}
@@ -74,8 +74,13 @@
}
public void setCurrentBlock(int n) {
- if (numberAllocated != 0)
+ if (maxBlockAllocated != 0)
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;
@@ -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,17 +152,10 @@
// always assume it is 2 anyway.
header.put(OFF_DIRECTORY_START_BLOCK, (byte) fsParams.getDirectoryStartEntry());
- // 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);
+ //writeSizeValues(bs);
+
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.position(OFF_CREATION_YEAR);
Utils.setCreationTime(header, creationTime);
@@ -166,44 +163,83 @@
// 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;
+ //int endBlock = numBlocks;
+
+ 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) {
+ int endSector = (int) (((long) ((numBlocks+1) * bs + 511) / 512) - 1);
+ if (endSector < 2048)
+ endSector = 2047;
+
+ // 16 heads to 128
+ // 4 sectors to 32
+
+ System.out.println("endSector=" + endSector + ", from " + numBlocks);
+ int sectors = 32; // 6 bit value
+ int heads = 128;
+ out:
+ for (int h : Arrays.asList(16, 32, 64, 128)) {
+
+ for (int s : Arrays.asList(4, 8, 16, 32)) {
+
+ int tot = s * h * 0x3ff;
+ int mb = endSector;
+ System.out.println("try " + tot + ", for mb=" + mb);
+ if (tot > mb) {
+ heads = h;
+ sectors = s;
+ break out;
+ }
+ }
+ }
+
+ // 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.
+ header.putShort(OFF_SECTORS, (short) sectors);
+ header.putShort(OFF_HEADS, (short) heads);
+ header.putShort(OFF_HEADS2, (short) heads);
+ header.putShort(OFF_SECTORS2, (short) sectors);
// 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 = numBlocks;
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 = (endSector / sectors) % heads;
+ int s = (endSector % sectors) + 1;
+ int c = endSector / (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);
+ header.putInt(OFF_NUMBER_OF_SECTORS, endSector + 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);
}
void setHeader(ByteBuffer buf) {
@@ -242,6 +278,8 @@
public void sync() throws IOException {
setUpdateTime(new Date());
+ writeSizeValues(fsParams.getBlockSize());
+
header.rewind();
file.position(0);
file.write(header);
@@ -320,4 +358,8 @@
protected void setCreationTime(Date date) {
this.creationTime = date;
}
+
+ public void setNumBlocks(int numBlocks) {
+ this.numBlocks = numBlocks;
-}
+ }
+}
_______________________________________________
mkgmap-dev mailing list
mkgmap-dev@lists.mkgmap.org.uk
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev