diff --git a/exec/load/cterm_lib.js b/exec/load/cterm_lib.js
index 76afcf082ba7b9d57d47e52be0afee6ef16fad5c..4ab1ff7a48e26a32be025afec7fe9c7d6d937130 100644
--- a/exec/load/cterm_lib.js
+++ b/exec/load/cterm_lib.js
@@ -2,6 +2,7 @@
 
 // Library for dealing with CTerm/SyncTERM enhanced features (e.g. fonts)
 
+load('sbbsdefs.js');
 var xbin = load({}, 'xbin_defs.js');
 var ansiterm = load({}, 'ansiterm_lib.js');
 
@@ -211,7 +212,37 @@ function load_font(slot, data, force)
 	return true;
 }
 
-function xbimage_draw(image, xpos, ypos, fg_color, bg_color, delay, cycle)
+function reset_palette()
+{
+	console.write("\x1b]104\x1b\\");
+}
+
+function redefine_palette(palette, bits)
+{
+	if(!bits)	// per color channel (options are 4, 8, 12, or 16)
+		bits = 8;
+	var str = "\x1b]4";
+	for(var i =0 ; i <  palette.length; i++)
+		str += format(";%u;rgb:%0*X/%0*X/%0*X", i
+			, bits / 4, palette[i].r
+			, bits / 4, palette[i].g
+			, bits / 4, palette[i].b);
+	str += "\x1b\\";
+//	log(LOG_DEBUG, "New palette: " + str);
+	console.write(str);
+}
+
+// Scale from 6-bit to 8-bit RGB color channel
+function scale_rgb_channel_value(val)
+{
+	var newval = Math.ceil(0xff / (0x3f / (val&0x3f)));
+
+//	log(LOG_DEBUG, format("scaled color channel from %d (%X) to %d (%x)", val, val, newval, newval));
+
+	return newval;
+}
+
+function xbin_draw(image, xpos, ypos, fg_color, bg_color, delay, cycle)
 {
 	load('graphic.js');
 
@@ -222,18 +253,19 @@ function xbimage_draw(image, xpos, ypos, fg_color, bg_color, delay, cycle)
 			delay = 0;
 	}
 
-	for(var i = 0; i < image.font.length; i++)	{
-//		print("Loading font " + image.font[i].length + " bytes");
-		this.load_font(0xff - i, image.font[i], true);
+	if(image.font) {
+		for(var i = 0; i < image.font.length; i++)	{
+	//		print("Loading font " + image.font[i].length + " bytes");
+			this.load_font(0xff - i, image.font[i], true);
+		}
 	}
-
-	if(image.flags&xbin.FLAG_NONHIGH)
-		ansiterm.send("ext_mode", "set", "no_bright_intensity");
 	console.clear(7);
 	for(var p in this.font_styles) {
 		var font_set = image[p];
-		if(font_set == undefined)
+		if(font_set == undefined) {
+			this.activate_font(this.font_styles[p], 0);
 			continue;
+		}
 //		printf("font_set = %u\r\n", font_set);
 		if(font_set < image.font_count) {
 //			print(format("Activating font " + font_set + " for " + p));
@@ -242,11 +274,78 @@ function xbimage_draw(image, xpos, ypos, fg_color, bg_color, delay, cycle)
 			}
 		}
 	}
+	if(image.flags&xbin.FLAG_NONHIGH)
+		ansiterm.send("ext_mode", "set", "no_bright_intensity");
+	if(image.flags&xbin.FLAG_NONBLINK)
+		ansiterm.send("ext_mode", "set", "no_blink");
 
-//	console.getkey();
-//	return true;
+	if(image.palette) {
+		var palette = [];
+		for(var i = 0; i < 16; i++) {
+			/* Must send the color definitions in the Xterm/ANSI order: */
+			var offset;
+			switch(i) {
+				case 0:
+					offset = BLACK;
+					break;
+				case 1:	/* Maroon */
+					offset = RED;
+					break;
+				case 2:	/* Green */
+					offset = GREEN;
+					break;
+				case 3: /* Olive */
+					offset = BROWN;
+					break;
+				case 4:	/* Navy */
+					offset = BLUE;
+					break;
+				case 5:	/* Purple */
+					offset = MAGENTA;
+					break;
+				case 6:	/* Teal */
+					offset = CYAN;
+					break;
+				case 7: /* Silver */
+					offset = LIGHTGRAY;
+					break;
+				case 8:	/* Grey */
+					offset = DARKGRAY;
+					break;
+				case 9:	/* Red */
+					offset = LIGHTRED;
+					break;
+				case 10:	/* Lime */
+					offset = LIGHTGREEN;
+					break;
+				case 11:
+					offset = YELLOW;
+					break;
+				case 12:	/* Blue */
+					offset = LIGHTBLUE;
+					break;
+				case 13:	/* Fuchsia */
+					offset = LIGHTMAGENTA;
+					break;
+				case 14:	/* Aqua */
+					offset = LIGHTCYAN;
+					break;
+				case 15:	/* White */
+					offset = WHITE;
+					break;
+			}
+			offset *= 3;
+			palette.push({ 
+				  r:scale_rgb_channel_value(ascii(image.palette.charAt(offset)))
+				, g:scale_rgb_channel_value(ascii(image.palette.charAt(offset+1)))
+				, b:scale_rgb_channel_value(ascii(image.palette.charAt(offset+2)))
+				});
+		}
+		this.redefine_palette(palette);
+	}
 	
 	ansiterm.send("ext_mode", "clear", "cursor");
+//	log(LOG_DEBUG, 'Enabled modes ' + this.query_mode());
 	var graphic = new Graphic(image.width, image.height);
 	graphic.BIN = image.bin;
 	var width = image.width;
@@ -262,8 +361,8 @@ function xbimage_draw(image, xpos, ypos, fg_color, bg_color, delay, cycle)
 	do {
 		if(xoff && xoff + width > image.width)
 			xoff = image.width - width;
-		if(yoff && yoff + height >= image.height)
-			yoff = image.height - (height + 1);
+		if(yoff && yoff + height > image.height)
+			yoff = image.height - height;
 		if(xoff < 0)
 			xoff = 0;
 		if(yoff < 0)
@@ -292,24 +391,54 @@ function xbimage_draw(image, xpos, ypos, fg_color, bg_color, delay, cycle)
 		else
 			key = console.inkey(K_UPPER, delay);
 		switch(key) {
+			case '5':	/* middle */
+				xoff = Math.floor(width / 2);
+				yoff = Math.floor(height / 2);
+				break;
+			case '6':
 			case KEY_RIGHT:
 				xoff++;
 				break;
+			case '4':
 			case KEY_LEFT:
 				xoff--;
 				break;
+			case '8':
 			case KEY_UP:
 				yoff--;
 				break;
+			case '7':
+				yoff--;
+				xoff--;
+				break;
+			case '9':
+				yoff--;
+				xoff++;
+				break;
+			case '3':
+				yoff++;
+				xoff++;
+				break;
+			case '1':
+				yoff++;
+				xoff--;
+				break;
+			case KEY_PAGEUP:
+				yoff -= height;
+				break;
+			case '2':
 			case KEY_DOWN:
 				yoff++;
 				break;
+			case KEY_PAGEDN:
+				yoff += height;
+				break;
 			case KEY_HOME:
 				xoff = 0;
 				yoff = 0;
 				break;
 			case KEY_END:
-				yoff = image.height - (height + 1);
+				yoff = image.height - height;
 				break;
 			case 'Q':
 				return false;
@@ -321,9 +450,12 @@ function xbimage_draw(image, xpos, ypos, fg_color, bg_color, delay, cycle)
 	return true;
 }
 
-function xbimage_cleanup(image)
+function xbin_cleanup(image)
 {
-	console.clear(ansiterm.LIGHTGRAY);
+	if(image && image.palette)
+		this.reset_palette();
+
+	console.clear(ansiterm.LIGHTGRAY|ansiterm.BG_BLACK);
 	ansiterm.send("ext_mode", "set", "cursor");
 
 	for(var p in this.font_styles)
@@ -332,6 +464,8 @@ function xbimage_cleanup(image)
 
 	if(image==undefined || image.flags&xbin.FLAG_NONHIGH)
 		ansiterm.send("ext_mode", "clear", "no_bright_intensity");
+	if(image==undefined || image.flags&xbin.FLAG_NONBLINK)
+		ansiterm.send("ext_mode", "clear", "no_blink");
 }
 
 // Leave as last line: