diff --git a/src/uk/me/parabola/imgfmt/app/Label.java b/src/uk/me/parabola/imgfmt/app/Label.java
index c7ca3a3..bbf7549 100644
--- a/src/uk/me/parabola/imgfmt/app/Label.java
+++ b/src/uk/me/parabola/imgfmt/app/Label.java
@@ -56,6 +56,16 @@ public class Label implements Comparable<Label> {
 		return text;
 	}
 
+	public String getTextSansGarminCodes() {
+		return stripGarminCodes(text);
+	}
+
+	public static String stripGarminCodes(String s) {
+		if(s == null)
+			return null;
+		return s.replaceAll("[\u0001-\u0006\u001b-\u001f]","");
+	}
+
 	/**
 	 * The offset of this label in the LBL file.  The first byte of this file
 	 * is zero and an offset of zero means that the label has a zero length/is
diff --git a/src/uk/me/parabola/imgfmt/app/labelenc/BaseEncoder.java b/src/uk/me/parabola/imgfmt/app/labelenc/BaseEncoder.java
index 0dc8390..fd06368 100644
--- a/src/uk/me/parabola/imgfmt/app/labelenc/BaseEncoder.java
+++ b/src/uk/me/parabola/imgfmt/app/labelenc/BaseEncoder.java
@@ -65,7 +65,7 @@ public class BaseEncoder {
 		return new EncodedText(out, out.length);
 	}
 
-	protected boolean isUpperCase() {
+	public boolean isUpperCase() {
 		return upperCase;
 	}
 
diff --git a/src/uk/me/parabola/imgfmt/app/labelenc/Format6Encoder.java b/src/uk/me/parabola/imgfmt/app/labelenc/Format6Encoder.java
index ec226a1..d1a267d 100644
--- a/src/uk/me/parabola/imgfmt/app/labelenc/Format6Encoder.java
+++ b/src/uk/me/parabola/imgfmt/app/labelenc/Format6Encoder.java
@@ -41,7 +41,7 @@ public class Format6Encoder extends BaseEncoder implements CharacterEncoder {
 	public static final String LETTERS =
 		" ABCDEFGHIJKLMNO" +	// 0x00-0x0F
 		"PQRSTUVWXYZxx   " +	// 0x10-0x1F
-		"0123456789xxxxxx";	// 0x20-0x2F
+		"0123456789\u0001\u0002\u0003\u0004\u0005\u0006";	// 0x20-0x2F
 
 	public static final String SYMBOLS =
 		"@!\"#$%&'()*+,-./" +	// 0x00-0x0F
diff --git a/src/uk/me/parabola/imgfmt/app/lbl/City.java b/src/uk/me/parabola/imgfmt/app/lbl/City.java
index 4fc7939..2ae6389 100644
--- a/src/uk/me/parabola/imgfmt/app/lbl/City.java
+++ b/src/uk/me/parabola/imgfmt/app/lbl/City.java
@@ -118,7 +118,7 @@ public class City implements Comparable<City> {
 		if(label != null)
 			result += label.getText();
 		if (subdivision != null)
-			result += subdivision.getNumber() + "/" + pointIndex;
+			result += " " + subdivision.getNumber() + "/" + pointIndex;
 		if(country != null)
 			result += " in country " + (0 + country.getIndex());
 		if(region != null)
diff --git a/src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java b/src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java
index 4d88bab..a2422ea 100644
--- a/src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java
+++ b/src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java
@@ -17,6 +17,7 @@
 package uk.me.parabola.imgfmt.app.lbl;
 
 import java.util.HashMap;
+import java.util.Locale;
 import java.util.Map;
 
 import uk.me.parabola.imgfmt.Utils;
@@ -27,6 +28,7 @@ import uk.me.parabola.imgfmt.app.Label;
 import uk.me.parabola.imgfmt.app.labelenc.BaseEncoder;
 import uk.me.parabola.imgfmt.app.labelenc.CharacterEncoder;
 import uk.me.parabola.imgfmt.app.labelenc.CodeFunctions;
+import uk.me.parabola.imgfmt.app.labelenc.Format6Encoder;
 import uk.me.parabola.imgfmt.app.trergn.Subdivision;
 import uk.me.parabola.imgfmt.fs.ImgChannel;
 import uk.me.parabola.log.Logger;
@@ -107,6 +109,13 @@ public class LBLFile extends ImgFile {
 	 * @return A reference to the created label.
 	 */
 	public Label newLabel(String text) {
+		// if required, fold case now so that labelCache doesn't
+		// contain multiple labels that only differ in letter case
+		if(text != null &&
+		   (textEncoder instanceof Format6Encoder ||
+			textEncoder instanceof BaseEncoder &&
+			((BaseEncoder)textEncoder).isUpperCase()))
+			text = text.toUpperCase(Locale.ENGLISH);
 		Label l = labelCache.get(text);
 		if (l == null) {
 			l = new Label(text);
diff --git a/src/uk/me/parabola/imgfmt/app/net/NETFile.java b/src/uk/me/parabola/imgfmt/app/net/NETFile.java
index 82f220b..e7abf26 100644
--- a/src/uk/me/parabola/imgfmt/app/net/NETFile.java
+++ b/src/uk/me/parabola/imgfmt/app/net/NETFile.java
@@ -18,8 +18,11 @@ package uk.me.parabola.imgfmt.app.net;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 
 import uk.me.parabola.imgfmt.Utils;
 import uk.me.parabola.imgfmt.app.BufferedImgFileWriter;
@@ -61,23 +64,44 @@ public class NETFile extends ImgFile {
 
 	public void writePost(ImgFileWriter rgn, boolean sortRoads) {
 		List<Sortable<Label, RoadDef>> sortedRoads = new ArrayList<Sortable<Label, RoadDef>>(roads.size());
+		// cleanedLabels holds "cleaned up" versions of the Label
+		// strings that are used when sorting the road names - the
+		// hope is that retrieving the String from the Map is faster than
+		// cleaning the Label text for each comparison in the sort
+		final Map<Label, String> cleanedLabels = new HashMap<Label, String>();
 
 		for (RoadDef rd : roads) {
 			rd.writeRgnOffsets(rgn);
 			if(sortRoads) {
 				Label[] l = rd.getLabels();
-				for(int i = 0; i < l.length && l[i] != null; ++i)
-					if(l[i].getLength() != 0)
+				for(int i = 0; i < l.length && l[i] != null; ++i) {
+					if(l[i].getLength() != 0) {
+						cleanedLabels.put(l[i], l[i].getTextSansGarminCodes());
+						//	System.err.println("Road " + rd + " has label " + l[i]);
 						sortedRoads.add(new Sortable<Label, RoadDef>(l[i], rd));
+					}
+				}
 			}
 		}
 
 		if(sortedRoads.size() > 0) {
-			Collections.sort(sortedRoads);
+			Collections.sort(sortedRoads, new Comparator<Sortable<Label, RoadDef>>() {
+					public int compare(Sortable<Label, RoadDef> a, Sortable<Label, RoadDef> b) {
+						// sort using cleaned versions of the labels
+						int diff = cleanedLabels.get(a.getKey()).compareToIgnoreCase(cleanedLabels.get(b.getKey()));
+						if(diff != 0)
+							return diff;
+						// the labels were the same, sort on the
+						// RoadDefs
+						return a.getValue().compareTo(b.getValue());
+					}
+				});
 			sortedRoads = simplifySortedRoads(new LinkedList<Sortable<Label, RoadDef>>(sortedRoads));
 			ImgFileWriter writer = netHeader.makeSortedRoadWriter(getWriter());
-			for(Sortable<Label, RoadDef> srd : sortedRoads)
+			for(Sortable<Label, RoadDef> srd : sortedRoads) {
+				//System.err.println("Road " + srd.getKey() + " is " + srd.getValue() + " " + srd.getValue().getCity());
 				srd.getValue().putSortedRoadEntry(writer, srd.getKey());
+			}
 			Utils.closeFile(writer);
 		}
 
@@ -95,7 +119,7 @@ public class NETFile extends ImgFile {
 	private List<Sortable<Label, RoadDef>> simplifySortedRoads(LinkedList<Sortable<Label, RoadDef>> in) {
 		List<Sortable<Label, RoadDef>> out = new ArrayList<Sortable<Label, RoadDef>>(in.size());
 		while(in.size() > 0) {
-			Label name0 = in.get(0).getKey();
+			String name0 = in.get(0).getKey().getTextSansGarminCodes();
 			RoadDef road0 = in.get(0).getValue();
 			City city0 = road0.getCity();
 			// transfer the 0'th entry to the output
@@ -104,7 +128,7 @@ public class NETFile extends ImgFile {
 			// firstly determine the entries whose name and city match
 			// name0 and city0
 			for(n = 0; (n < in.size() &&
-						name0 == in.get(n).getKey() &&
+						name0.equalsIgnoreCase(in.get(n).getKey().getTextSansGarminCodes()) &&
 						city0 == in.get(n).getValue().getCity()); ++n) {
 				// relax
 			}
diff --git a/src/uk/me/parabola/imgfmt/app/trergn/Subdivision.java b/src/uk/me/parabola/imgfmt/app/trergn/Subdivision.java
index 1202186..a2620b5 100644
--- a/src/uk/me/parabola/imgfmt/app/trergn/Subdivision.java
+++ b/src/uk/me/parabola/imgfmt/app/trergn/Subdivision.java
@@ -274,15 +274,20 @@ public class Subdivision {
 	}
 
 	public Polyline createLine(String name, String ref) {
+		// don't be tempted to "trim()" the name as it zaps the highway shields
 		Label label = lblFile.newLabel(name);
+		String nameSansGC = Label.stripGarminCodes(name);
 		Polyline pl = new Polyline(this);
 
 		pl.setLabel(label);
+
 		if(ref != null) {
 			// ref may contain multiple ids separated by ";"
 			for(String r : ref.split(";")) {
 				String tr = r.trim();
-				if(tr.length() > 0) {
+				String trSansGC = Label.stripGarminCodes(tr);
+				if(trSansGC.length() > 0 &&
+				   !trSansGC.equalsIgnoreCase(nameSansGC)) {
 					//System.err.println("Adding ref " + tr + " to road " + name);
 					pl.addRefLabel(lblFile.newLabel(tr));
 				}
diff --git a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
index 58500ef..de58e11 100644
--- a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
+++ b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
@@ -599,6 +599,24 @@ public class StyledConverter implements OsmConverter {
 			// use first ref as name
 			name = SEMI_PATTERN.split(refs)[0].trim();
 		}
+		else if(name != null) {
+			// remove leading spaces (don't use trim() to avoid zapping
+			// shield codes)
+			char leadingCode = 0;
+			if(name.length() > 1 &&
+			   name.charAt(0) < 0x20 &&
+			   name.charAt(1) == ' ') {
+				leadingCode = name.charAt(0);
+				name = name.substring(2);
+			}
+				
+			while(name.length() > 0 && name.charAt(0) == ' ')
+				name = name.substring(1);
+
+			if(leadingCode != 0)
+				name = new Character(leadingCode) + name;
+		}
+
 		if(name != null)
 			ms.setName(name);
 		if(refs != null)
