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

Reply via email to