Index: src/uk/me/parabola/imgfmt/FileSystemParam.java
===================================================================
--- src/uk/me/parabola/imgfmt/FileSystemParam.java	(revision 341)
+++ src/uk/me/parabola/imgfmt/FileSystemParam.java	(revision )
@@ -1,18 +1,14 @@
 /*
- * Copyright (C) 2006 Steve Ratcliffe
+ * Copyright (C) 2006, 2011.
- * 
+ *
- *  This program is free software; you can redistribute it and/or modify
+ * This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2 as
- *  published by the Free Software Foundation.
+ * 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.
- * 
- * 
- * Author: Steve Ratcliffe
- * Create date: 02-Dec-2006
+ * 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;
 
@@ -25,7 +21,7 @@
 public class FileSystemParam {
 	private String mapDescription = "Open Street Map";
 	private int blockSize = 512;
-	private int directoryStartBlock = 2;
+	private int directoryStartEntry = 2; // Always in terms of entries of 512 bytes
 	private int reservedDirectoryBlocks = 202;
 
 	public String getMapDescription() {
@@ -44,12 +40,12 @@
 		this.blockSize = blockSize;
 	}
 
-	public int getDirectoryStartBlock() {
-		return directoryStartBlock;
+	public int getDirectoryStartEntry() {
+		return directoryStartEntry;
 	}
 
-	public void setDirectoryStartBlock(int directoryStartBlock) {
-		this.directoryStartBlock = directoryStartBlock;
+	public void setDirectoryStartEntry(int directoryStartBlock) {
+		this.directoryStartEntry = directoryStartBlock;
 	}
 
 	public int getReservedDirectoryBlocks() {
Index: src/uk/me/parabola/mkgmap/combiners/FileInfo.java
===================================================================
--- src/uk/me/parabola/mkgmap/combiners/FileInfo.java	(revision 1870)
+++ src/uk/me/parabola/mkgmap/combiners/FileInfo.java	(revision )
@@ -281,15 +281,16 @@
 	}
 
 	/**
-	 * Get the number of blocks required at a particular block size.
-	 * Each subfile will need at least one block and so we go through each
+	 * Get the number header slots (512 byte entry) required to represent this file
+	 * at the given block size.
+	 * Each sub-file will need at least one block and so we go through each
 	 * separately and round up for each and return the total.
 	 *
 	 * @param blockSize The block size.
-	 * @return The number of blocks that would be needed for all the subfiles
+	 * @return The number of 512 byte header entries that are needed for all the subfiles
 	 * in this .img file.
 	 */
-	public int getNumHeaderSlots(int blockSize) {
+	public int getNumHeaderEntries(int blockSize) {
 		int totHeaderSlots = 0;
 		for (int size : fileSizes) {
 			// You use up one header slot for every 240 blocks with a minimum
@@ -301,9 +302,14 @@
 	}
 
 	/**
-	 * Get the number of blocks at the given block size.  Note that a complete block is
-	 * always used for a file.
+	 * Get the number of blocks for all the sub-files of this file at the given block size.
+	 * Note that a complete block is always used for a file.
+	 *
+	 * For TYP files and other files that do not have sub-files, then it is just the number of blocks
+	 * for the complete file.
+	 * 
 	 * @param bs The block size at which to calculate the value.
+	 * @return The number of blocks at the given size required to save all the sub-files of this file.
 	 */
 	public int getNumBlocks(int bs) {
 		int totBlocks = 0;
Index: src/uk/me/parabola/imgfmt/sys/Directory.java
===================================================================
--- src/uk/me/parabola/imgfmt/sys/Directory.java	(revision 1911)
+++ src/uk/me/parabola/imgfmt/sys/Directory.java	(revision )
@@ -44,13 +44,15 @@
 	private ImgChannel chan;
 
 	private final BlockManager headerBlockManager;
+	private final int startEntry;
 	private long startPos;
 
 	// The list of files themselves.
 	private final Map<String, DirectoryEntry> entries = new LinkedHashMap<String, DirectoryEntry>();
 
-	Directory(BlockManager headerBlockManager) {
+	Directory(BlockManager headerBlockManager, int startEntry) {
 		this.headerBlockManager = headerBlockManager;
+		this.startEntry = startEntry;
 	}
 
 	/**
@@ -140,19 +142,27 @@
 		// The first entry can't really be written until the rest of the directory is
 		// so we have to step through once to calculate the size and then again
 		// to write it out.
-		int blocks = 0;
+		int headerEntries = 0;
 		for (DirectoryEntry dir : entries.values()) {
 			Dirent ent = (Dirent) dir;
 			log.debug("ent size", ent.getSize());
 			int n = ent.numberHeaderBlocks();
-			blocks += n;
+			headerEntries += n;
 		}
+		System.out.println("dir: header blocks(slots) " + headerEntries);
 
 		// Save the current position
 		long dirPosition = chan.position();
+
 		int blockSize = headerBlockManager.getBlockSize();
 
-		int forHeader = (blocks + Dirent.ENTRY_SIZE - 1)/Dirent.ENTRY_SIZE;
+		// Get the number of blocks required for the directory entry representing the header.
+		// First calculate the number of blocks required for the directory entries.
+		int headerBlocks = (int) Math.ceil((startEntry + 1.0 + headerEntries) * Dirent.ENTRY_SIZE / blockSize);
+		System.out.println("dir: headerBlocks " + headerBlocks);
+		int forHeader = (headerBlocks + Dirent.ENTRY_SIZE - 1)/Dirent.ENTRY_SIZE;
+
+		System.out.println("header blocks needed " + forHeader);
 		log.debug("header blocks needed", forHeader);
 
 		// There is nothing really wrong with larger values (perhaps, I don't
@@ -162,7 +172,7 @@
 		// Write the blocks that will will contain the header blocks.
 		chan.position(dirPosition + (long) forHeader * Dirent.ENTRY_SIZE);
 
-		for (DirectoryEntry dir : entries.values()) {
+		for (DirectoryEntry dir : this.entries.values()) {
 			Dirent ent = (Dirent) dir;
 
 			if (!ent.isSpecial()) {
@@ -173,6 +183,7 @@
 		}
 
 		long end = (long) blockSize * headerBlockManager.getMaxBlock();
+		System.out.println("dir: end slot " + end/512);
 		ByteBuffer buf = ByteBuffer.allocate((int) (end - chan.position()));
 		for (int i = 0; i < buf.capacity(); i++)
 			buf.put((byte) 0);
@@ -181,7 +192,7 @@
 
 		// Now go back and write in the directory entry for the header.
 		chan.position(dirPosition);
-		Dirent ent = (Dirent) entries.values().iterator().next();
+		Dirent ent = (Dirent) this.entries.values().iterator().next();
 		log.debug("ent header size", ent.getSize());
 		ent.sync(chan);
 
Index: src/uk/me/parabola/imgfmt/sys/ImgFS.java
===================================================================
--- src/uk/me/parabola/imgfmt/sys/ImgFS.java	(revision 1751)
+++ src/uk/me/parabola/imgfmt/sys/ImgFS.java	(revision )
@@ -58,7 +58,9 @@
 
 	// The filesystem is responsible for allocating blocks
 	private BlockManager fileBlockManager;
-	private static final long BASIC_BLOCK_SIZE = 512L;
+
+	// The header entries are written in 512 blocks, regardless of the block size of the file itself.
+	private static final long ENTRY_BLOCK_SIZE = 512L;
 	private BlockManager headerBlockManager;
 
 	private byte xorByte;	// if non-zero, all bytes are XORed with this
@@ -242,6 +244,8 @@
 			log.debug("could not sync filesystem");
 		} finally {
 			try {
+				if (fileBlockManager != null)
+				System.out.println("file size in blocks " + file.size()/fileBlockManager.getBlockSize());
 				file.close();
 			} catch (IOException e) {
 				log.warn("Could not close file");
@@ -268,7 +272,7 @@
 		// to the header and directory, but to create one normally would involve
 		// it already existing, so it is created by hand.
 		try {
-			directory = new Directory(headerBlockManager);
+			directory = new Directory(headerBlockManager, params.getDirectoryStartEntry());
 
 			Dirent ent = directory.create(DIRECTORY_FILE_NAME, headerBlockManager);
 			ent.setSpecial(true);
@@ -313,8 +317,8 @@
 		BlockManager headerBlockManager = new BlockManager(params.getBlockSize(), 0);
 		headerBlockManager.setMaxBlock(params.getReservedDirectoryBlocks());
 
-		directory = new Directory(headerBlockManager);
-		directory.setStartPos(params.getDirectoryStartBlock() * BASIC_BLOCK_SIZE);
+		directory = new Directory(headerBlockManager, params.getDirectoryStartEntry());
+		directory.setStartPos(params.getDirectoryStartEntry() * ENTRY_BLOCK_SIZE);
 
 		Dirent ent = directory.create(DIRECTORY_FILE_NAME, headerBlockManager);
 		FileNode f = new FileNode(chan, ent, "r");
Index: src/uk/me/parabola/mkgmap/combiners/GmapsuppBuilder.java
===================================================================
--- src/uk/me/parabola/mkgmap/combiners/GmapsuppBuilder.java	(revision 1885)
+++ src/uk/me/parabola/mkgmap/combiners/GmapsuppBuilder.java	(revision )
@@ -66,7 +66,7 @@
 	 * The number of block numbers that will fit into one entry block
 	 */
 	private static final int ENTRY_SIZE = 240;
-	private static final int DIRECTORY_OFFSET_BLOCK = 2;
+	private static final int DIRECTORY_OFFSET_ENTRY = 2;
 
 	private final Map<String, FileInfo> files = new LinkedHashMap<String, FileInfo>();
 
@@ -350,15 +350,12 @@
 		FileSystemParam params = new FileSystemParam();
 		params.setBlockSize(blockSize);
 		params.setMapDescription(overallDescription);
-		params.setDirectoryStartBlock(DIRECTORY_OFFSET_BLOCK);
+		params.setDirectoryStartEntry(DIRECTORY_OFFSET_ENTRY);
 
-		int reserved = DIRECTORY_OFFSET_BLOCK + bi.reserveBlocks + bi.headerSlots;
-		log.info("bs of", blockSize, "reserving", reserved);
+		int reserveBlocks = (int) Math.ceil(bi.reserveEntries * 512.0 / blockSize);
+		System.out.println("bs: " + blockSize + " reserve blocks " + reserveBlocks);
+		params.setReservedDirectoryBlocks(reserveBlocks);
 
-		int reserve = (int) Math.ceil(reserved * 512.0 / blockSize);
-		params.setReservedDirectoryBlocks(reserve);
-		log.info("reserved", reserve);
-
 		FileSystem outfs = ImgFS.createFs(Utils.joinPath(outputDir, GMAPSUPP), params);
 		mpsFile = createMpsFile(outfs);
 		mpsFile.setMapsetName(mapsetName);
@@ -432,25 +429,33 @@
 
 		for (int bs : ints) {
 			int totBlocks = 0;
-			int totHeaderSlots = 0;
+			int totHeaderEntries = 0;
 			for (FileInfo info : files.values()) {
 				totBlocks += info.getNumBlocks(bs);
 				// Each file will take up at least one directory block.
 				// Each directory block can hold 480 block-references
-				int slots = info.getNumHeaderSlots(bs);
+				int slots = info.getNumHeaderEntries(bs);
 				log.info("adding", slots, "slots for", info.getFilename());
-				totHeaderSlots += slots;
+				totHeaderEntries += slots;
 			}
 
-			totHeaderSlots += 2;
-			int totHeaderBlocks = totHeaderSlots * 512 / bs;
+			// Estimate the number of blocks needed for the MPS file
+			int mpsSize = files.size() * 80 + 100;
+			int mpsBlocks = (mpsSize + (bs - 1)) / bs;
+			int mpsSlots = (mpsBlocks + ENTRY_SIZE-1) / ENTRY_SIZE;
 
-			log.info("total blocks for", bs, "is", totHeaderBlocks, "based on slots=", totHeaderSlots);
+			totBlocks += mpsBlocks;
+			totHeaderEntries += mpsSlots;
 
-			if (totBlocks < 0xfffe && totHeaderBlocks <= ENTRY_SIZE) {
-				// Add one for the MPS file
-				totHeaderSlots += 1;
-				return new BlockInfo(bs, totHeaderSlots, totHeaderSlots / bs + 1);
+			totHeaderEntries += 2;
+			int totHeaderBlocks = totHeaderEntries * 512 / bs;
+
+			log.info("total blocks for", bs, "is", totHeaderBlocks, "based on slots=", totHeaderEntries);
+
+			System.out.printf("bs %d: tot blocks %d, tot header blocks %d\n", bs, totBlocks, totHeaderBlocks);
+			int reserveEntries = (int) Math.ceil(DIRECTORY_OFFSET_ENTRY + 1 + totHeaderEntries);
+			if (totBlocks + reserveEntries < 0xfffe && totHeaderBlocks <= ENTRY_SIZE) {
+				return new BlockInfo(bs, totHeaderEntries, reserveEntries);
 			}
 		}
 
@@ -463,12 +468,12 @@
 	private static class BlockInfo {
 		private final int blockSize;
 		private final int headerSlots;
-		private final int reserveBlocks;
+		private final int reserveEntries;
 
-		private BlockInfo(int blockSize, int headerSlots, int reserveBlocks) {
+		private BlockInfo(int blockSize, int headerSlots, int reserveEntries) {
 			this.blockSize = blockSize;
 			this.headerSlots = headerSlots;
-			this.reserveBlocks = reserveBlocks;
+			this.reserveEntries = reserveEntries;
 		}
 	}
 }
Index: src/uk/me/parabola/imgfmt/sys/ImgHeader.java
===================================================================
--- src/uk/me/parabola/imgfmt/sys/ImgHeader.java	(revision 1919)
+++ src/uk/me/parabola/imgfmt/sys/ImgHeader.java	(revision )
@@ -114,6 +114,7 @@
 	 * @param params File system parameters.
 	 */
 	void createHeader(FileSystemParam params) {
+		System.out.println("create header " + params.getBlockSize());
 		this.fsParams = params;
 
 		header.put(OFF_XOR, (byte) 0);
@@ -146,7 +147,7 @@
 
 		// Actually this may not be the directory start block, I am guessing -
 		// always assume it is 2 anyway.
-		header.put(OFF_DIRECTORY_START_BLOCK, (byte) fsParams.getDirectoryStartBlock());
+		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
@@ -193,7 +194,7 @@
 		header.putInt(OFF_NUMBER_OF_SECTORS, endBlock+1);
 		log.info("number of blocks " + blocks);
 
-		setDirectoryStartBlock(params.getDirectoryStartBlock());
+		setDirectoryStartEntry(params.getDirectoryStartEntry());
 
 		// Set the times.
 		Date date = new Date();
@@ -216,7 +217,7 @@
 
 		fsParams = new FileSystemParam();
 		fsParams.setBlockSize(1 << (exp1 + exp2));
-		fsParams.setDirectoryStartBlock(header.get(OFF_DIRECTORY_START_BLOCK));
+		fsParams.setDirectoryStartEntry(header.get(OFF_DIRECTORY_START_BLOCK));
 
 		StringBuffer sb = new StringBuffer();
 		sb.append(Utils.bytesToString(buf, OFF_MAP_DESCRIPTION, LEN_MAP_DESCRIPTION));
@@ -245,7 +246,7 @@
 		header.rewind();
 		file.position(0);
 		file.write(header);
-		file.position(fsParams.getDirectoryStartBlock() * 512L);
+		file.position(fsParams.getDirectoryStartEntry() * 512L);
 	}
 
 	/**
@@ -312,9 +313,9 @@
 		return (byte) (y - 1900);
 	}
 
-	protected void setDirectoryStartBlock(int directoryStartBlock) {
-		header.put(OFF_DIRECTORY_START_BLOCK, (byte) directoryStartBlock);
-		fsParams.setDirectoryStartBlock(directoryStartBlock);
+	protected void setDirectoryStartEntry(int directoryStartEntry) {
+		header.put(OFF_DIRECTORY_START_BLOCK, (byte) directoryStartEntry);
+		fsParams.setDirectoryStartEntry(directoryStartEntry);
 	}
 
 	protected void setCreationTime(Date date) {
