diff -ur angband-3.0.1-orig/src/cave.c angband-3.0.1/src/cave.c
--- angband-3.0.1-orig/src/cave.c	Tue Jul 16 20:08:57 2002
+++ angband-3.0.1/src/cave.c	Wed Jul 17 10:49:31 2002
@@ -1009,6 +1009,360 @@
 	(*cp) = c;
 }
 
+/*
+ * Same as map_info, but always return the char/attr specified by the
+ * info files.
+ * This IS an hack, I dont like to duplicate code like that, but the only
+ * other way it to hack map_info itself and put lots of if statements in it,
+ * which could reduce speed.
+ */
+void map_info_default(int y, int x, byte *ap, char *cp)
+{
+	byte a;
+	char c;
+
+	byte feat;
+	byte info;
+
+	feature_type *f_ptr;
+
+	s16b this_o_idx, next_o_idx = 0;
+
+	s16b m_idx;
+
+	s16b image = p_ptr->image;
+
+	int floor_num = 0;
+
+	/* Monster/Player */
+	m_idx = cave_m_idx[y][x];
+
+	/* Feature */
+	feat = cave_feat[y][x];
+
+	/* Cave flags */
+	info = cave_info[y][x];
+
+	/* Hack -- rare random hallucination on non-outer walls */
+	if (image && (!rand_int(256)) && (feat < FEAT_PERM_SOLID))
+	{
+		int i = image_random();
+
+		a = PICT_A(i);
+		c = PICT_C(i);
+	}
+
+	/* Boring grids (floors, etc) */
+	else if (feat <= FEAT_INVIS)
+	{
+		/* Memorized (or seen) floor */
+		if ((info & (CAVE_MARK)) ||
+		    (info & (CAVE_SEEN)))
+		{
+			/* Get the floor feature */
+			f_ptr = &f_info[FEAT_FLOOR];
+
+			/* Normal attr */
+                        a = f_ptr->d_attr;
+
+			/* Normal char */
+                        c = f_ptr->d_char;
+
+			/* Special lighting effects */
+                        if (view_special_lite && (a == TERM_WHITE))
+			{
+				/* Handle "seen" grids */
+				if (info & (CAVE_SEEN))
+				{
+					/* Only lit by "torch" lite */
+					if (view_yellow_lite && !(info & (CAVE_GLOW)))
+					{
+                                                /* Use "yellow" */
+                                                a = TERM_YELLOW;
+					}
+				}
+
+				/* Handle "blind" */
+				else if (p_ptr->blind)
+				{
+                                        /* Use "dark gray" */
+                                        a = TERM_L_DARK;
+				}
+
+				/* Handle "dark" grids */
+				else if (!(info & (CAVE_GLOW)))
+				{
+                                        /* Use "dark gray" */
+                                        a = TERM_L_DARK;
+				}
+
+				/* Handle "view_bright_lite" */
+				else if (view_bright_lite)
+				{
+                                        /* Use "gray" */
+                                        a = TERM_SLATE;
+				}
+			}
+		}
+
+		/* Unknown */
+		else
+		{
+			/* Get the darkness feature */
+			f_ptr = &f_info[FEAT_NONE];
+
+			/* Normal attr */
+                        a = f_ptr->d_attr;
+
+			/* Normal char */
+                        c = f_ptr->d_char;
+		}
+	}
+
+	/* Interesting grids (non-floors) */
+	else
+	{
+		/* Memorized grids */
+		if (info & (CAVE_MARK))
+		{
+			/* Apply "mimic" field */
+			feat = f_info[feat].mimic;
+
+			/* Get the feature */
+			f_ptr = &f_info[feat];
+
+			/* Normal attr */
+                        a = f_ptr->d_attr;
+
+			/* Normal char */
+                        c = f_ptr->d_char;
+
+			/* Special lighting effects (walls only) */
+			if (view_granite_lite &&
+                            (((a == TERM_WHITE) && (feat >= FEAT_SECRET)) ||
+                             (feat_supports_lighting(feat))))
+			{
+				/* Handle "seen" grids */
+				if (info & (CAVE_SEEN))
+				{
+                                        /* Use "white" */
+				}
+
+				/* Handle "blind" */
+				else if (p_ptr->blind)
+				{
+                                        /* Use "dark gray" */
+                                        a = TERM_L_DARK;
+				}
+
+				/* Handle "view_bright_lite" */
+				else if (view_bright_lite)
+				{
+                                        /* Use "gray" */
+                                        a = TERM_SLATE;
+				}
+				else
+				{
+                                        /* Use "white" */
+				}
+			}
+		}
+
+		/* Unknown */
+		else
+		{
+			/* Get the darkness feature */
+			f_ptr = &f_info[FEAT_NONE];
+
+			/* Normal attr */
+                        a = f_ptr->d_attr;
+
+			/* Normal char */
+                        c = f_ptr->d_char;
+		}
+	}
+
+	/* Objects */
+	for (this_o_idx = cave_o_idx[y][x]; this_o_idx; this_o_idx = next_o_idx)
+	{
+		object_type *o_ptr;
+
+		/* Get the object */
+		o_ptr = &o_list[this_o_idx];
+
+		/* Get the next object */
+		next_o_idx = o_ptr->next_o_idx;
+
+		/* Memorized objects */
+		if (o_ptr->marked)
+		{
+			/* Hack -- object hallucination */
+			if (image)
+			{
+				int i = image_object();
+
+				a = PICT_A(i);
+				c = PICT_C(i);
+
+				break;
+			}
+
+			/* Normal attr */
+			a = object_attr(o_ptr);
+
+			/* Normal char */
+			c = object_char(o_ptr);
+
+			/* First marked object */
+			if (!show_piles) break;
+
+			/* Special stack symbol */
+			if (++floor_num > 1)
+			{
+				object_kind *k_ptr;
+
+				/* Get the "pile" feature */
+				k_ptr = &k_info[0];
+
+				/* Normal attr */
+                                a = k_ptr->d_attr;
+
+				/* Normal char */
+                                c = k_ptr->d_char;
+
+				break;
+			}
+		}
+	}
+
+
+	/* Monsters */
+	if (m_idx > 0)
+	{
+		monster_type *m_ptr = &mon_list[m_idx];
+
+		/* Visible monster */
+		if (m_ptr->ml)
+		{
+			monster_race *r_ptr = &r_info[m_ptr->r_idx];
+
+			byte da;
+			char dc;
+
+			/* Desired attr */
+                        da = r_ptr->d_attr;
+
+			/* Desired char */
+                        dc = r_ptr->d_char;
+
+			/* Hack -- monster hallucination */
+			if (image)
+			{
+				int i = image_monster();
+
+				a = PICT_A(i);
+				c = PICT_C(i);
+			}
+
+			/* Ignore weird codes */
+			else if (avoid_other)
+			{
+				/* Use attr */
+				a = da;
+
+				/* Use char */
+				c = dc;
+			}
+
+			/* Special attr/char codes */
+			else if ((da & 0x80) && (dc & 0x80))
+			{
+				/* Use attr */
+				a = da;
+
+				/* Use char */
+				c = dc;
+			}
+
+			/* Multi-hued monster */
+			else if (r_ptr->flags1 & (RF1_ATTR_MULTI))
+			{
+				/* Multi-hued attr */
+				a = randint(15);
+
+				/* Normal char */
+				c = dc;
+			}
+
+			/* Normal monster (not "clear" in any way) */
+			else if (!(r_ptr->flags1 & (RF1_ATTR_CLEAR | RF1_CHAR_CLEAR)))
+			{
+				/* Use attr */
+				a = da;
+
+				/* Use char */
+				c = dc;
+			}
+
+			/* Hack -- Bizarre grid under monster */
+			else if ((a & 0x80) || (c & 0x80))
+			{
+				/* Use attr */
+				a = da;
+
+				/* Use char */
+				c = dc;
+			}
+
+			/* Normal char, Clear attr, monster */
+			else if (!(r_ptr->flags1 & (RF1_CHAR_CLEAR)))
+			{
+				/* Normal char */
+				c = dc;
+			}
+
+			/* Normal attr, Clear char, monster */
+			else if (!(r_ptr->flags1 & (RF1_ATTR_CLEAR)))
+			{
+				/* Normal attr */
+				a = da;
+			}
+		}
+	}
+
+	/* Handle "player" */
+	else if ((m_idx < 0) && !(p_ptr->running && hidden_player))
+	{
+		monster_race *r_ptr = &r_info[0];
+
+		/* Get the "player" attr */
+                a = r_ptr->d_attr;
+
+		/* Get the "player" char */
+                c = r_ptr->d_char;
+	}
+
+#ifdef MAP_INFO_MULTIPLE_PLAYERS
+	/* Players */
+	else if (m_idx < 0)
+#else /* MAP_INFO_MULTIPLE_PLAYERS */
+	/* Handle "player" */
+	else if ((m_idx < 0) && !(p_ptr->running && hidden_player))
+#endif /* MAP_INFO_MULTIPLE_PLAYERS */
+	{
+		monster_race *r_ptr = &r_info[0];
+
+		/* Get the "player" attr */
+                a = r_ptr->d_attr;
+
+		/* Get the "player" char */
+                c = r_ptr->d_char;
+	}
+
+	/* Result */
+	(*ap) = a;
+	(*cp) = c;
+}
 
 
 /*
diff -ur angband-3.0.1-orig/src/cmd4.c angband-3.0.1/src/cmd4.c
--- angband-3.0.1-orig/src/cmd4.c	Tue Jul 16 20:08:57 2002
+++ angband-3.0.1/src/cmd4.c	Wed Jul 17 11:49:27 2002
@@ -2621,92 +2621,14 @@
  */
 void do_cmd_save_screen(void)
 {
-	int y, x;
+	char tmp_val[81];
 
-	byte a = 0;
-	char c = ' ';
+	/* Ask for a file */
+	strcpy(tmp_val, "dump.html");
+	if (!get_string("File: ", tmp_val, 80)) return;
 
-	FILE *fff;
-
-	char buf[1024];
-
-
-	/* Build the filename */
-	path_build(buf, sizeof(buf), ANGBAND_DIR_USER, "dump.txt");
-
-	/* File type is "TEXT" */
-	FILE_TYPE(FILE_TYPE_TEXT);
-
-	/* Append to the file */
-	fff = my_fopen(buf, "w");
-
-	/* Oops */
-	if (!fff) return;
-
-
-	/* Save screen */
-	screen_save();
-
-
-	/* Dump the screen */
-	for (y = 0; y < 24; y++)
-	{
-		/* Dump each row */
-		for (x = 0; x < 79; x++)
-		{
-			/* Get the attr/char */
-			(void)(Term_what(x, y, &a, &c));
-
-			/* Dump it */
-			buf[x] = c;
-		}
-
-		/* Terminate */
-		buf[x] = '\0';
-
-		/* End the row */
-		fprintf(fff, "%s\n", buf);
-	}
-
-	/* Skip a line */
-	fprintf(fff, "\n");
-
-
-	/* Dump the screen */
-	for (y = 0; y < 24; y++)
-	{
-		/* Dump each row */
-		for (x = 0; x < 79; x++)
-		{
-			/* Get the attr/char */
-			(void)(Term_what(x, y, &a, &c));
-
-			/* Dump it */
-			buf[x] = hack[a&0x0F];
-		}
-
-		/* Terminate */
-		buf[x] = '\0';
-
-		/* End the row */
-		fprintf(fff, "%s\n", buf);
-	}
-
-	/* Skip a line */
-	fprintf(fff, "\n");
-
-
-	/* Close it */
-	my_fclose(fff);
-
-
-	/* Message */
-	msg_print("Screen dump saved.");
-	message_flush();
-
-
-	/* Load screen */
-	screen_load();
+	html_screenshot(tmp_val);
+	msg_print("Dump saved.");
 }
 
 
diff -ur angband-3.0.1-orig/src/externs.h angband-3.0.1/src/externs.h
--- angband-3.0.1-orig/src/externs.h	Tue Jul 16 20:08:57 2002
+++ angband-3.0.1/src/externs.h	Wed Jul 17 10:49:16 2002
@@ -246,6 +246,7 @@
 extern bool cave_valid_bold(int y, int x);
 extern bool feat_supports_lighting(byte feat);
 extern void map_info(int y, int x, byte *ap, char *cp, byte *tap, char *tcp);
+extern void map_info_default(int y, int x, byte *ap, char *cp);
 extern void move_cursor_relative(int y, int x);
 extern void print_rel(char c, byte a, int y, int x);
 extern void note_spot(int y, int x);
@@ -361,6 +362,7 @@
 extern void play_game(bool new_game);
 
 /* files.c */
+extern void html_screenshot(cptr name);
 extern void safe_setuid_drop(void);
 extern void safe_setuid_grab(void);
 extern s16b tokenize(char *buf, s16b num, char **tokens);
diff -ur angband-3.0.1-orig/src/files.c angband-3.0.1/src/files.c
--- angband-3.0.1-orig/src/files.c	Tue Jul 16 20:08:57 2002
+++ angband-3.0.1/src/files.c	Wed Jul 17 10:49:16 2002
@@ -4646,4 +4646,160 @@
 
 #endif	/* HANDLE_SIGNALS */
 
+/*
+ * Attr value-to-char convertion table
+ */
+static byte conv_color[16] =
+{
+	'd',
+	'w',
+	's',
+	'o',
+	'r',
+	'g',
+	'b',
+	'u',
+	'D',
+	'W',
+	'v',
+	'y',
+	'R',
+	'G',
+	'B',
+	'U',
+};
+
+/*
+ * Clean up a line for recording via cmovie or html dump
+ */
+void cmovie_clean_line(int y, char *abuf, char *cbuf)
+{
+	const byte *ap = Term->scr->a[y];
+	const char *cp = Term->scr->c[y];
+
+	byte a;
+	char c;
+
+	int x;
+	int wid, hgt;
+	int screen_wid, screen_hgt;
+
+	/* Retrieve current screen size */
+	Term_get_size(&wid, &hgt);
+
+	/* Calculate the size of dungeon map area */
+	screen_wid = wid - (COL_MAP + 1);
+	screen_hgt = hgt - (ROW_MAP + 1);
+
+	/* For the time being, assume 80 column display XXX XXX XXX */
+	for (x = 0; x < wid; x++)
+	{
+		/* Convert dungeon map into default attr/chars */
+		if (!character_icky &&
+                    ((x - COL_MAP) >= 0) &&
+		    ((x - COL_MAP) < screen_wid) &&
+		    ((y - ROW_MAP) >= 0) &&
+		    ((y - ROW_MAP) < screen_hgt))
+		{
+			/* Retrieve default attr/char */
+                        map_info_default(y + p_ptr->wy - ROW_MAP, x + p_ptr->wx - COL_MAP, &a, &c);
+
+			abuf[x] = conv_color[a & 0xf];
+
+			if (c == '\0') cbuf[x] = ' ';
+			else cbuf[x] = c;
+		}
+
+		else
+		{
+			abuf[x] = conv_color[ap[x] & 0xf];
+			cbuf[x] = cp[x];
+		}
+	}
+
+	/* Null-terminate the prepared strings */
+	abuf[x] = '\0';
+	cbuf[x] = '\0';
+}
+
+/* Take an html screenshot */
+void html_screenshot(cptr name)
+{
+	int y, x;
+	int wid, hgt;
+
+	byte a = 0, oa = TERM_WHITE;
+	char c = ' ';
+
+	FILE *htm;
+
+	char buf[1024];
+
+	/* The terms package supports up to 255x255 screen size */
+	char abuf[256];
+	char cbuf[256];
+
+
+	/* Build the filename */
+	path_build(buf, 1024, ANGBAND_DIR_USER, name);
+
+	/* File type is "TEXT" */
+	FILE_TYPE(FILE_TYPE_TEXT);
+
+	/* Hack -- drop permissions */
+	/* safe_setuid_drop(); */
+
+	/* Append to the file */
+	htm = my_fopen(buf, "w");
+
+	/* Hack -- grab permissions */
+	/* safe_setuid_grab(); */
+
+	/* Oops */
+	if (!htm) return;
+
+	/* Retrieve current screen size */
+	Term_get_size(&wid, &hgt);
+
+	fprintf(htm, "<HTML>\n");
+	fprintf(htm, "<HEAD>\n");
+        fprintf(htm, "<META NAME=\"GENERATOR\" Content=\"Angband %d.%d.%d\">\n", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
+	fprintf(htm, "<TITLE>%s</TITLE>\n", name);
+	fprintf(htm, "</HEAD>\n");
+	fprintf(htm, "<BODY TEXT=\"#FFFFFF\" BGCOLOR=\"#000000\">");
+	fprintf(htm, "<FONT COLOR=\"#%02X%02X%02X\">\n<PRE><TT>",
+	             angband_color_table[TERM_WHITE][1],
+	             angband_color_table[TERM_WHITE][2],
+	             angband_color_table[TERM_WHITE][3]);
+
+	/* Dump the screen */
+	for (y = 0; y < hgt; y++)
+	{
+		cmovie_clean_line(y, abuf, cbuf);
+
+		/* Dump each row */
+		for (x = 0; x < wid; x++)
+		{
+			a = color_char_to_attr(abuf[x]);
+			c = cbuf[x];
+
+			if (oa != a)
+			{
+				fprintf(htm, "</FONT><FONT COLOR=\"#%02X%02X%02X\">", angband_color_table[a][1], angband_color_table[a][2], angband_color_table[a][3]);
+				oa = a;
+			}
+			fprintf(htm, "%c", c);
+		}
+
+		/* End the row */
+		fprintf(htm, "\n");
+	}
+	fprintf(htm, "</TT></PRE></FONT>\n");
+
+	fprintf(htm, "</BODY>\n");
+	fprintf(htm, "</HTML>\n");
+
+	/* Close it */
+	my_fclose(htm);
+}
 
