diff -Nru base0132/src/emu/inptport.c w0132/src/emu/inptport.c
--- base0132/src/emu/inptport.c	2009-05-27 20:15:29.000000000 +1200
+++ w0132/src/emu/inptport.c	2009-06-08 22:27:18.000000000 +1200
@@ -107,6 +107,10 @@
 #include "uimess.h"
 #endif /* MESS */
 
+/* recorded speed read from an INP file */
+double rec_speed;
+int sprintframetime(char *timearray, const running_machine *machine);
+
 
 /* temporary: set this to 1 to enable the originally defined behavior that
    a field specified via PORT_MODIFY which intersects a previously-defined
@@ -1944,8 +1948,10 @@
 profiler_mark(PROFILER_INPUT);
 
 	/* record/playback information about the current frame */
-	playback_frame(machine, curtime);
-	record_frame(machine, curtime);
+	if(machine->input_port_data->playback_file)  // avoid re-recording - coz that's cheating. ;)
+		playback_frame(machine, curtime);
+	else
+		record_frame(machine, curtime);
 
 	/* track the duration of the previous frame */
 	portdata->last_delta_nsec = attotime_to_attoseconds(attotime_sub(curtime, portdata->last_frame_time)) / ATTOSECONDS_PER_NANOSECOND;
@@ -3909,6 +3915,9 @@
 static void playback_end(running_machine *machine, const char *message)
 {
 	input_port_private *portdata = machine->input_port_data;
+	char timearray[]="100d 00:00:00.00:";
+	double avg_speed = ((double)portdata->playback_accumulated_speed/10000) / portdata->playback_accumulated_frames;
+	sprintframetime(timearray, machine);
 
 	/* only applies if we have a live file */
 	if (portdata->playback_file != NULL)
@@ -3919,12 +3928,16 @@
 
 		/* pop a message */
 		if (message != NULL)
-			popmessage("Playback Ended\nReason: %s", message);
+			popmessage("Playback Ended - %u Frames (%s) - Speed %6.2f%%\nReason: %s",
+				(UINT32)portdata->playback_accumulated_frames, timearray, avg_speed, message);
 
 		/* display speed stats */
-		portdata->playback_accumulated_speed /= portdata->playback_accumulated_frames;
-		mame_printf_info("Total playback frames: %d\n", (UINT32)portdata->playback_accumulated_frames);
-		mame_printf_info("Average recorded speed: %d%%\n", (UINT32)((portdata->playback_accumulated_speed * 200 + 1) >> 21));
+		if (portdata->playback_accumulated_frames)
+			portdata->playback_accumulated_speed /= portdata->playback_accumulated_frames;
+		else
+			portdata->playback_accumulated_speed = 0;
+		mame_printf_info("Total playback frames: %d (%s)\n", (UINT32)portdata->playback_accumulated_frames,timearray);
+		mame_printf_info("Average recorded speed: %d%%\n", (UINT32)(avg_speed));
 	}
 }
 
@@ -3950,7 +3963,7 @@
 			playback_end(machine, "Out of sync");
 
 		/* then the speed */
-		portdata->playback_accumulated_speed += playback_read_uint32(machine);
+		portdata->playback_accumulated_speed += (rec_speed=playback_read_uint32(machine)/(double)(1 << 20))*1000000;
 		portdata->playback_accumulated_frames++;
 	}
 }
@@ -4069,6 +4082,13 @@
 	if (filename[0] == 0)
 		return;
 
+	/* if in debug mode, don't start recording */
+	if(machine->debug_flags & DEBUG_FLAG_ENABLED)
+		return;
+
+	/* disable cheats */
+	options_set_bool(mame_options(),OPTION_CHEAT,0,OPTION_PRIORITY_MAXIMUM);
+
 	/* open the record file  */
 	filerr = mame_fopen(SEARCHPATH_INPUTLOG, filename, OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS, &portdata->record_file);
 	assert_always(filerr == FILERR_NONE, "Failed to open file for recording");
@@ -4174,3 +4194,55 @@
 		}
 	}
 }
+
+/* INP file handle helper functions */
+mame_file* get_record_file(running_machine* machine)
+{
+	input_port_private *portdata = machine->input_port_data;
+	return portdata->record_file;
+}
+
+mame_file* get_playback_file(running_machine* machine)
+{
+	input_port_private *portdata = machine->input_port_data;
+	return portdata->playback_file;
+}
+
+int sprintframetime(char *timearray, const running_machine *machine)
+{
+	static int fps = 0;
+	char *tptr=timearray;
+	int seconds;
+	int minutes;
+	if (!fps) // assign the fps that we'll be calculating (must be same mess version)
+		fps=ATTOSECONDS_TO_HZ(((const screen_config *)video_screen_first(machine->config)->inline_config)->refresh);
+	seconds = (fps) ? machine->input_port_data->playback_accumulated_frames/fps : 0;
+	if (seconds >= 24*60*60)
+	{
+		int days = seconds/(24*60*60);
+		seconds -= days*(24*60*60);
+		tptr += sprintf(tptr, "%dd ", days);
+	}
+	if (seconds >= 60*60)
+	{
+		int hours = seconds/(60*60);
+		seconds -= hours*(60*60);
+		*tptr++ = '0'+hours/10;
+		*tptr++ = '0'+hours%10;
+		*tptr++ = ':';
+	}
+	/* always display minutes seconds and centiseconds */					
+	minutes = seconds/(60);
+	seconds -= minutes*(60);
+	*tptr++ = '0'+minutes/10;
+	*tptr++ = '0'+minutes%10;
+	*tptr++ = ':';
+	*tptr++ = '0'+seconds/10;
+	*tptr++ = '0'+seconds%10;
+	seconds = 100*(machine->input_port_data->playback_accumulated_frames%fps)/fps;
+	*tptr++ = '.';
+	*tptr++ = '0'+seconds/10;
+	*tptr++ = '0'+seconds%10;
+	*tptr=0;
+	return tptr-timearray;
+}
diff -Nru base0132/src/emu/inptport.h w0132/src/emu/inptport.h
--- base0132/src/emu/inptport.h	2009-05-27 20:15:29.000000000 +1200
+++ w0132/src/emu/inptport.h	2009-06-08 22:27:18.000000000 +1200
@@ -1036,5 +1036,8 @@
 /* convert an input_port_token to a default string */
 const char *input_port_string_from_token(const input_port_token token);
 
+/* helper function to access INP file handles.  **shakes fist at MAMEdev** */
+mame_file* get_record_file(running_machine* machine);
+mame_file* get_playback_file(running_machine* machine);
 
 #endif	/* __INPTPORT_H__ */
diff -Nru base0132/src/emu/ui.c w0132/src/emu/ui.c
--- base0132/src/emu/ui.c	2009-04-27 21:18:17.000000000 +1200
+++ w0132/src/emu/ui.c	2009-06-08 22:27:18.000000000 +1200
@@ -21,6 +21,7 @@
 #include "uiinput.h"
 #include "uimenu.h"
 #include "uigfx.h"
+#include "inptport.h"
 
 #ifdef MESS
 #include "mess.h"
@@ -248,7 +249,7 @@
 
 	/* disable everything if we are using -str for 300 or fewer seconds, or if we're the empty driver,
        or if we are debugging */
-	if (!first_time || (str > 0 && str < 60*5) || machine->gamedrv == &driver_empty || (machine->debug_flags & DEBUG_FLAG_ENABLED) != 0)
+	if (!first_time || (str > 0 && str < 60*5) || machine->gamedrv == &driver_empty || (machine->debug_flags & DEBUG_FLAG_ENABLED) != 0  || get_record_file(machine))
 		show_gameinfo = show_warnings = show_disclaimer = FALSE;
 
 	/* initialize the on-screen display system */
@@ -1198,7 +1199,7 @@
 		mame_schedule_soft_reset(machine);
 
 	/* handle a request to display graphics/palette */
-	if (ui_input_pressed(machine, IPT_UI_SHOW_GFX))
+	if (ui_input_pressed(machine, IPT_UI_SHOW_GFX) && !get_record_file(machine))
 	{
 		if (!is_paused)
 			mame_pause(machine, TRUE);
@@ -1206,14 +1207,14 @@
 	}
 
 	/* handle a save state request */
-	if (ui_input_pressed(machine, IPT_UI_SAVE_STATE))
+	if (ui_input_pressed(machine, IPT_UI_SAVE_STATE) && !get_record_file(machine))
 	{
 		mame_pause(machine, TRUE);
 		return ui_set_handler(handler_load_save, LOADSAVE_SAVE);
 	}
 
 	/* handle a load state request */
-	if (ui_input_pressed(machine, IPT_UI_LOAD_STATE))
+	if (ui_input_pressed(machine, IPT_UI_LOAD_STATE) && !get_record_file(machine))
 	{
 		mame_pause(machine, TRUE);
 		return ui_set_handler(handler_load_save, LOADSAVE_LOAD);
@@ -1224,7 +1225,7 @@
 		video_save_active_screen_snapshots(machine);
 
 	/* toggle pause */
-	if (ui_input_pressed(machine, IPT_UI_PAUSE))
+	if (ui_input_pressed(machine, IPT_UI_PAUSE) && !get_record_file(machine))
 	{
 		/* with a shift key, it is single step */
 		if (is_paused && (input_code_pressed(KEYCODE_LSHIFT) || input_code_pressed(KEYCODE_RSHIFT)))
@@ -1286,11 +1287,11 @@
 	}
 
 	/* toggle throttle? */
-	if (ui_input_pressed(machine, IPT_UI_THROTTLE))
+	if (ui_input_pressed(machine, IPT_UI_THROTTLE) && !get_record_file(machine))
 		video_set_throttle(!video_get_throttle());
 
 	/* check for fast forward */
-	if (input_type_pressed(machine, IPT_UI_FAST_FORWARD, 0))
+	if (input_type_pressed(machine, IPT_UI_FAST_FORWARD, 0) && !get_record_file(machine))
 	{
 		video_set_fastforward(TRUE);
 		ui_show_fps_temp(0.5);
diff -Nru base0132/src/emu/uimenu.c w0132/src/emu/uimenu.c
--- base0132/src/emu/uimenu.c	2009-04-27 21:18:17.000000000 +1200
+++ w0132/src/emu/uimenu.c	2009-06-08 22:27:18.000000000 +1200
@@ -16,6 +16,7 @@
 #include "uimenu.h"
 #include "audit.h"
 #include "eminline.h"
+#include "inptport.h"
 
 #ifdef MESS
 #include "uimess.h"
@@ -1225,7 +1226,7 @@
 	}
 
 	/* pause enables/disables pause */
-	if (!ignorepause && exclusive_input_pressed(menu, IPT_UI_PAUSE, 0))
+	if (!ignorepause && exclusive_input_pressed(menu, IPT_UI_PAUSE, 0) && !get_record_file(menu->machine))
 		mame_pause(menu->machine, !mame_is_paused(menu->machine));
 
 	/* see if any other UI keys are pressed */
diff -Nru base0132/src/emu/video.c w0132/src/emu/video.c
--- base0132/src/emu/video.c	2009-06-08 18:24:21.000000000 +1200
+++ w0132/src/emu/video.c	2009-06-08 22:27:18.000000000 +1200
@@ -164,7 +164,7 @@
 	{ 0,1,1,1,1,1,1,1,1,1,1,1 }
 };
 
-
+extern double rec_speed;
 
 /***************************************************************************
     FUNCTION PROTOTYPES
@@ -1636,10 +1636,14 @@
 	int paused = mame_is_paused(machine);
 	static char buffer[1024];
 	char *dest = buffer;
+	screen_state* state = get_safe_token(machine->primary_screen);
 
 	/* validate */
 	assert(machine != NULL);
 
+	/* show frame counter */
+	dest += sprintf(dest, "[%i] : ",(UINT32)state->frame_number);
+
 	/* if we're paused, just display Paused */
 	if (paused)
 		dest += sprintf(dest, "paused");
@@ -1664,6 +1668,10 @@
 	if (global.partial_updates_this_frame > 1)
 		dest += sprintf(dest, "\n%d partial updates", global.partial_updates_this_frame);
 
+	if(get_playback_file(machine))
+	{
+		dest += sprintf(dest,"\nRecorded speed: %5.2f%%",rec_speed*100);
+	}
 	/* return a pointer to the static buffer */
 	return buffer;
 }
diff -Nru base0132/src/version.c w0132/src/version.c
--- base0132/src/version.c	2009-06-08 19:28:13.000000000 +1200
+++ w0132/src/version.c	2009-06-08 22:29:28.000000000 +1200
@@ -10,4 +10,4 @@
 ***************************************************************************/
 
 extern const char build_version[];
-const char build_version[] = "0.132 ("__DATE__")";
+const char build_version[] = "0.132[W] ("__DATE__")";
diff -Nru --strip-trailing-cr mames/src/emu/info.c.orig mames/src/emu/info.c
--- mames/src/emu/info.c.orig	2008-05-24 16:46:32.000000000 -0700
+++ mames/src/emu/info.c	2008-05-24 17:21:06.000000000 -0700
@@ -40,21 +39,30 @@
 {
 	const input_port_config *port;
 	const input_field_config *field;
+	int portnum = -1;
 
 	/* iterate looking for DIP switches */
 	for (port = portlist; port != NULL; port = port->next)
 		for (field = port->fieldlist; field != NULL; field = field->next)
+		{
+			if (port->tag != NULL)
+				portnum++;
 			if (field->type == IPT_DIPSWITCH)
 			{
 				const input_setting_config *setting;
 
 				/* output the switch name information */
 				fprintf(out, "\t\t<dipswitch name=\"%s\">\n", xml_normalize_string(input_field_name(field)));
+				fprintf(out, "\t\t<dipswitch");
+				fprintf(out, " mask=\"%i\"", field->mask);
+				fprintf(out, " port=\"%i\"", portnum);
+				fprintf(out, " name=\"%s\">\n", xml_normalize_string(input_field_name(field)));
 
 				/* loop over settings */
 				for (setting = field->settinglist; setting != NULL; setting = setting->next)
 				{
 					fprintf(out, "\t\t\t<dipvalue name=\"%s\"", xml_normalize_string(setting->name));
+					fprintf(out, " value=\"%i\"", setting->value);
 					if (setting->value == field->defvalue)
 						fprintf(out, " default=\"yes\"");
 					fprintf(out, "/>\n");
@@ -63,6 +72,7 @@
 				/* terminate the switch entry */
 				fprintf(out, "\t\t</dipswitch>\n");
 			}
+		}
 }
 
 
diff -Nru base0132/src/emu/emu.mak w0132/src/emu/emu.mak
--- base0132/src/emu/emu.mak	2009-04-20 21:31:18.000000000 +1200
+++ w0132/src/emu/emu.mak	2009-06-08 22:48:42.000000000 +1200
@@ -86,7 +86,8 @@
 	$(EMUOBJ)/debug/debughlp.o \
 	$(EMUOBJ)/debug/debugvw.o \
 	$(EMUOBJ)/debug/express.o \
-	$(EMUOBJ)/debug/textbuf.o
+	$(EMUOBJ)/debug/textbuf.o \
+	$(EMUOBJ)/inpview.o
 
 ifdef PROFILER
 EMUOBJS += \
diff -Nru base0132/src/emu/emuopts.c w0132/src/emu/emuopts.c
--- base0132/src/emu/emuopts.c	2009-03-29 10:55:34.000000000 +1300
+++ w0132/src/emu/emuopts.c	2009-06-08 22:48:42.000000000 +1200
@@ -155,6 +155,8 @@
 	{ "bios",                        NULL,        0,                 "select the system BIOS to use" },
 	{ "cheat;c",                     "0",         OPTION_BOOLEAN,    "enable cheat subsystem" },
 	{ "skip_gameinfo",               "0",         OPTION_BOOLEAN,    "skip displaying the information screen at startup" },
+	{ "inpview;iv",		             "0",         0,                 "enable input viewer" },
+	{ "inplayout;il",                "standard",  0,                 "set input viewer layout type" },
 
 	{ NULL }
 };
diff -Nru base0132/src/emu/inptport.c w0132/src/emu/inptport.c
--- base0132/src/emu/inptport.c	2009-05-27 20:15:29.000000000 +1200
+++ w0132/src/emu/inptport.c	2009-06-08 22:48:42.000000000 +1200
@@ -107,6 +107,7 @@
 #include "uimess.h"
 #endif /* MESS */
 
+#include "inpview.h"
 
 /* temporary: set this to 1 to enable the originally defined behavior that
    a field specified via PORT_MODIFY which intersects a previously-defined
@@ -659,6 +660,9 @@
 	/* register callbacks for when we load configurations */
 	config_register(machine, "input", load_config_callback, save_config_callback);
 
+	/* INPVIEW: initialise -inpview and -inplayout options */
+	inpview_set_data(options_get_int(mame_options(),"inpview"),options_get_string(mame_options(),"inplayout"));
+
 	/* open playback and record files if specified */
 	basetime = playback_init(machine);
 	record_init(machine);
@@ -3993,6 +3997,36 @@
     INPUT RECORDING
 ***************************************************************************/
 
+int input_port_used(running_machine* machine, int type,int player)
+{
+	const input_port_config* port;
+	const input_field_config* bit;
+
+	/* loop over all input ports */
+	for (port = machine->portconfig; port != NULL; port = port->next)
+	{
+		UINT32 portvalue;
+
+		/* loop over all bitfields for this port */
+		for (bit = port->fieldlist; bit != NULL; bit = bit->next)
+		{
+			if((port->state->defvalue & bit->mask) != 0)  // default value for the bit should be 0 if active high.
+				portvalue = ~port->state->digital;
+			else
+				portvalue = port->state->digital;
+
+			if(bit->type == type && bit->player == player)
+			{
+				if((bit->type == type) && (portvalue & bit->mask) != (bit->defvalue & bit->mask))
+					return 1;
+				else
+					return 0;
+			}
+		}
+	}
+	return 0;
+}
+
 /*-------------------------------------------------
     record_write_uint8 - write an 8-bit value
     to the record file
diff -Nru base0132/src/emu/inptport.h w0132/src/emu/inptport.h
--- base0132/src/emu/inptport.h	2009-05-27 20:15:29.000000000 +1200
+++ w0132/src/emu/inptport.h	2009-06-08 22:48:42.000000000 +1200
@@ -1037,4 +1037,6 @@
 const char *input_port_string_from_token(const input_port_token token);
 
 
+int input_port_used(running_machine*, int, int);
+
 #endif	/* __INPTPORT_H__ */
diff -Nru base0132/src/emu/inpview.c w0132/src/emu/inpview.c
--- base0132/src/emu/inpview.c	1970-01-01 13:00:00.000000000 +1300
+++ w0132/src/emu/inpview.c	2009-06-08 22:48:42.000000000 +1200
@@ -0,0 +1,257 @@
+// Input viewer module for MAME
+// Complete re-write started Aug 23, 2006
+
+#include <stdio.h>
+#include "ui.h"
+#include "inptport.h"
+#include "render.h"
+#include "inpview.h"
+
+#define CHAR_WIDTH  (1.0f / 80.0f)
+#define INPUT_TYPES 5
+
+#define COL_RED     MAKE_ARGB(0xff, 0xff, 0x00, 0x00)
+#define COL_BLUE    MAKE_ARGB(0xff, 0x00, 0x00, 0xff)
+#define COL_GREEN   MAKE_ARGB(0xff, 0x00, 0xff, 0x00)
+#define COL_YELLOW  MAKE_ARGB(0xff, 0xff, 0xff, 0x00)
+#define COL_ORANGE  MAKE_ARGB(0xff, 0xff, 0x80, 0x00)
+#define COL_BLACK   MAKE_ARGB(0xff, 0x00, 0x00, 0x00)
+#define COL_GRAY    MAKE_ARGB(0xff, 0x80, 0x80, 0x80)
+#define COL_WHITE   MAKE_ARGB(0xff, 0xff, 0xff, 0xff)
+
+#define BGCOL       MAKE_ARGB(0x80, 0x80, 0x00, 0x00)
+
+// uncomment if you plan to use MAME's built-in font
+//#define OLD_UI_FONT 1
+
+#ifndef OLD_UI_FONT
+#define DIR_LEFT   0x2190
+#define DIR_UP     0x2191
+#define DIR_RIGHT  0x2192
+#define DIR_DOWN   0x2193
+#else
+#define DIR_LEFT   'L'
+#define DIR_UP     'U'
+#define DIR_RIGHT  'R'
+#define DIR_DOWN   'D'
+#endif
+
+struct input_type_definition inptype[INPUT_TYPES] = 
+{
+	{
+		"standard",
+		1,
+		{
+			{"1P", IPT_START1, 1, 50, 0, 0, COL_WHITE},
+			{"2P", IPT_START2, 1, 53, 0, 0, COL_WHITE},
+			{"3P", IPT_START3, 1, 56, 0, 0, COL_WHITE},
+			{"4P", IPT_START4, 1, 59, 0, 0, COL_WHITE},
+			{"5P", IPT_START5, 1, 62, 0, 0, COL_WHITE},
+			{"6P", IPT_START6, 1, 65, 0, 0, COL_WHITE},
+			{"7P", IPT_START7, 1, 68, 0, 0, COL_WHITE},
+			{"8P", IPT_START8, 1, 71, 0, 0, COL_WHITE},
+			{"1",  IPT_BUTTON1, 1, 20, 0, 1, COL_WHITE},
+			{"2",  IPT_BUTTON2, 1, 22, 0, 1, COL_WHITE},
+			{"3",  IPT_BUTTON3, 1, 24, 0, 1, COL_WHITE},
+			{"4",  IPT_BUTTON4, 1, 26, 0, 1, COL_WHITE},
+			{"5",  IPT_BUTTON5, 1, 28, 0, 1, COL_WHITE},
+			{"6",  IPT_BUTTON6, 1, 30, 0, 1, COL_WHITE},
+			{"7",  IPT_BUTTON7, 1, 32, 0, 1, COL_WHITE},
+			{"8",  IPT_BUTTON8, 1, 34, 0, 1, COL_WHITE},
+			{"9",  IPT_BUTTON9, 1, 36, 0, 1, COL_WHITE},
+			{"0",  IPT_BUTTON10, 1, 38, 0, 1, COL_WHITE},
+			{"_L",  IPT_JOYSTICK_LEFT, 1, 10, 0, 1, COL_WHITE},
+			{"_R",  IPT_JOYSTICK_RIGHT, 1, 12, 0, 1, COL_WHITE},
+			{"_U",  IPT_JOYSTICK_UP, 1, 14, 0, 1, COL_WHITE},
+			{"_D",  IPT_JOYSTICK_DOWN, 1, 16, 0, 1, COL_WHITE},
+			{"NULL", -1, 0,0,0,0,0}
+		}
+	},
+	{
+		"mahjong",
+		2,
+		{
+			{"1P", IPT_START1, 1, 50, 0, 0, COL_WHITE},
+			{"2P", IPT_START2, 1, 53, 0, 0, COL_WHITE},
+			{"3P", IPT_START3, 1, 56, 0, 0, COL_WHITE},
+			{"4P", IPT_START4, 1, 59, 0, 0, COL_WHITE},
+			{"5P", IPT_START5, 1, 62, 0, 0, COL_WHITE},
+			{"6P", IPT_START6, 1, 65, 0, 0, COL_WHITE},
+			{"7P", IPT_START7, 1, 68, 0, 0, COL_WHITE},
+			{"8P", IPT_START8, 1, 71, 0, 0, COL_WHITE},
+			{"A",  IPT_MAHJONG_A, 1, 10, 0, 1, COL_WHITE},
+			{"B",  IPT_MAHJONG_B, 1, 12, 0, 1, COL_WHITE},
+			{"C",  IPT_MAHJONG_C, 1, 14, 0, 1, COL_WHITE},
+			{"D",  IPT_MAHJONG_D, 1, 16, 0, 1, COL_WHITE},
+			{"E",  IPT_MAHJONG_E, 1, 18, 0, 1, COL_WHITE},
+			{"F",  IPT_MAHJONG_F, 1, 20, 0, 1, COL_WHITE},
+			{"G",  IPT_MAHJONG_G, 1, 22, 0, 1, COL_WHITE},
+			{"H",  IPT_MAHJONG_H, 1, 24, 0, 1, COL_WHITE},
+			{"I",  IPT_MAHJONG_I, 1, 26, 0, 1, COL_WHITE},
+			{"J",  IPT_MAHJONG_J, 1, 28, 0, 1, COL_WHITE},
+			{"K",  IPT_MAHJONG_K, 1, 30, 0, 1, COL_WHITE},
+			{"L",  IPT_MAHJONG_L, 1, 32, 0, 1, COL_WHITE},
+			{"M",  IPT_MAHJONG_M, 1, 34, 0, 1, COL_WHITE},
+			{"N",  IPT_MAHJONG_N, 1, 36, 0, 1, COL_WHITE},
+			{"O",  IPT_MAHJONG_O, 1, 38, 0, 1, COL_WHITE},
+			{"P",  IPT_MAHJONG_P, 1, 40, 0, 1, COL_WHITE},
+			{"Q",  IPT_MAHJONG_Q, 1, 42, 0, 1, COL_WHITE},
+			{"REACH",  IPT_MAHJONG_REACH, 2, 14, 0, 1, COL_WHITE},
+			{"CHI",  IPT_MAHJONG_CHI, 2, 26, 0, 1, COL_WHITE},
+			{"PON",  IPT_MAHJONG_PON, 2, 34, 0, 1, COL_WHITE},
+			{"KAN",  IPT_MAHJONG_KAN, 2, 42, 0, 1, COL_WHITE},
+			{"RON",  IPT_MAHJONG_RON, 2, 50, 0, 1, COL_WHITE},
+			{"BET",  IPT_MAHJONG_BET, 2, 58, 0, 1, COL_WHITE},
+			{"NULL", -1, 0,0,0,0,0}
+		}
+	},
+	{
+		"dualstick",
+		1,
+		{
+			{"1P", IPT_START1, 1, 50, 0, 0, COL_WHITE},
+			{"2P", IPT_START2, 1, 53, 0, 0, COL_WHITE},
+			{"3P", IPT_START3, 1, 56, 0, 0, COL_WHITE},
+			{"4P", IPT_START4, 1, 59, 0, 0, COL_WHITE},
+			{"5P", IPT_START5, 1, 62, 0, 0, COL_WHITE},
+			{"6P", IPT_START6, 1, 65, 0, 0, COL_WHITE},
+			{"7P", IPT_START7, 1, 68, 0, 0, COL_WHITE},
+			{"8P", IPT_START8, 1, 71, 0, 0, COL_WHITE},
+			{"1",  IPT_BUTTON1, 1, 30, 0, 1, COL_WHITE},
+			{"2",  IPT_BUTTON2, 1, 32, 0, 1, COL_WHITE},
+			{"3",  IPT_BUTTON3, 1, 34, 0, 1, COL_WHITE},
+			{"4",  IPT_BUTTON4, 1, 36, 0, 1, COL_WHITE},
+			{"5",  IPT_BUTTON5, 1, 38, 0, 1, COL_WHITE},
+			{"6",  IPT_BUTTON6, 1, 40, 0, 1, COL_WHITE},
+			{"7",  IPT_BUTTON7, 1, 42, 0, 1, COL_WHITE},
+			{"8",  IPT_BUTTON8, 1, 44, 0, 1, COL_WHITE},
+			{"9",  IPT_BUTTON9, 1, 46, 0, 1, COL_WHITE},
+			{"0",  IPT_BUTTON10, 1, 48, 0, 1, COL_WHITE},
+			{"_L",  IPT_JOYSTICKLEFT_LEFT,   1, 6, 0, 1, COL_WHITE},
+			{"_R",  IPT_JOYSTICKLEFT_RIGHT,  1, 8, 0, 1, COL_WHITE},
+			{"_U",  IPT_JOYSTICKLEFT_UP,     1, 10, 0, 1, COL_WHITE},
+			{"_D",  IPT_JOYSTICKLEFT_DOWN,   1, 12, 0, 1, COL_WHITE},
+			{"_L",  IPT_JOYSTICKRIGHT_LEFT,  1, 18, 0, 1, COL_WHITE},
+			{"_R",  IPT_JOYSTICKRIGHT_RIGHT, 1, 20, 0, 1, COL_WHITE},
+			{"_U",  IPT_JOYSTICKRIGHT_UP,    1, 22, 0, 1, COL_WHITE},
+			{"_D",  IPT_JOYSTICKRIGHT_DOWN,  1, 24, 0, 1, COL_WHITE},
+			{"NULL", -1, 0,0,0,0,0}
+		}
+	},
+	{
+		"neogeo",
+		2,
+		{
+			{"1P", IPT_START1, 2, 53, 0, 0, COL_YELLOW},
+			{"2P", IPT_START2, 1, 53, 0, 0, COL_YELLOW},
+			{"A",  IPT_BUTTON1, 1, 26, 0, 1, COL_RED},
+			{"B",  IPT_BUTTON2, 2, 29, 0, 1, COL_YELLOW},
+			{"C",  IPT_BUTTON3, 2, 32, 0, 1, COL_GREEN},
+			{"D",  IPT_BUTTON4, 1, 35, 0, 1, COL_BLUE},
+			{"_L",  IPT_JOYSTICK_LEFT, 1, 15, 0, 1, COL_WHITE},
+			{"_R",  IPT_JOYSTICK_RIGHT, 1, 19, 0, 1, COL_WHITE},
+			{"_U",  IPT_JOYSTICK_UP, 2, 17, 0, 1, COL_WHITE},
+			{"_D",  IPT_JOYSTICK_DOWN, 1, 17, 0, 1, COL_WHITE},
+			{"NULL", -1, 0,0,0,0,0}
+		}
+	},
+	{
+		"6button",
+		2,
+		{
+			{"1P", IPT_START1, 2, 53, 0, 0, COL_YELLOW},
+			{"2P", IPT_START2, 1, 53, 0, 0, COL_YELLOW},
+			{"1",  IPT_BUTTON1, 2, 30, 0, 1, COL_WHITE},
+			{"2",  IPT_BUTTON2, 2, 33, 0, 1, COL_WHITE},
+			{"3",  IPT_BUTTON3, 2, 36, 0, 1, COL_WHITE},
+			{"4",  IPT_BUTTON4, 1, 30, 0, 1, COL_WHITE},
+			{"5",  IPT_BUTTON5, 1, 33, 0, 1, COL_WHITE},
+			{"6",  IPT_BUTTON6, 1, 36, 0, 1, COL_WHITE},
+			{"_L",  IPT_JOYSTICK_LEFT, 1, 15, 0, 1, COL_WHITE},
+			{"_R",  IPT_JOYSTICK_RIGHT, 1, 19, 0, 1, COL_WHITE},
+			{"_U",  IPT_JOYSTICK_UP, 2, 17, 0, 1, COL_WHITE},
+			{"_D",  IPT_JOYSTICK_DOWN, 1, 17, 0, 1, COL_WHITE},
+			{"NULL", -1, 0,0,0,0,0}
+		}
+	}
+};
+
+int player;
+int layout;
+
+void render_input(running_machine* machine)
+{
+	int port = 0;
+	char txt[6];
+	float height = ui_get_line_height();
+
+	if(player < 1 || player > 8)
+		return;  // invalid player
+
+	render_ui_add_rect(0.0f,1.0f-(float)(inptype[layout].lines*height),1.0f,1.0f,BGCOL,PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA));
+	while(inptype[layout].inp[port].port != -1)
+	{
+		strcpy(txt,inptype[layout].inp[port].text);
+
+		if(inptype[layout].inp[port].playerspecific == 0)
+		{
+			if(input_port_used(machine,inptype[layout].inp[port].port,0) != 0)
+			{
+				int ch = convert_txt(txt);
+				int col = inptype[layout].inp[port].colour;
+				if(ch == 0)
+					ui_draw_text_full(txt,(float)(inptype[layout].inp[port].x * CHAR_WIDTH),1.0f - (float)(height * inptype[layout].inp[port].line),1.0f,JUSTIFY_LEFT,WRAP_NEVER,DRAW_OPAQUE,col,0,NULL,NULL);
+				else
+					render_ui_add_char((float)(inptype[layout].inp[port].x * CHAR_WIDTH),1.0f - (float)(height * inptype[layout].inp[port].line),height,render_get_ui_aspect(),col,ui_get_font(),ch);
+			}
+		}
+		else
+		{
+			if(input_port_used(machine,inptype[layout].inp[port].port,player-1) != 0)
+			{
+				int ch = convert_txt(txt);
+				int col = inptype[layout].inp[port].colour;
+				if(ch == 0)
+					ui_draw_text_full(txt,(float)(inptype[layout].inp[port].x * CHAR_WIDTH),1.0f - (float)(height * inptype[layout].inp[port].line),1.0f,JUSTIFY_LEFT,WRAP_NEVER,DRAW_OPAQUE,col,0,NULL,NULL);
+				else
+					render_ui_add_char((float)(inptype[layout].inp[port].x * CHAR_WIDTH),1.0f - (float)(height * inptype[layout].inp[port].line),height,render_get_ui_aspect(),col,ui_get_font(),ch);
+			}
+		}
+		port++;
+	}
+}
+
+void inpview_set_data(int ply, const char* lay)
+{
+	player = ply;
+	layout = 0;
+	while(layout < INPUT_TYPES)
+	{
+		if(strcmp(inptype[layout].name,lay) == 0)
+		{
+			printf("INPVIEW: using layout type '%s'\n",lay);
+			return;
+		}
+		layout++;
+	}
+	printf("INPVIEW: invalid type specified, standard layout in use\n");
+	layout = 0;
+}
+
+int inpview_get_player()
+{
+	return player;
+}
+
+unsigned int convert_txt(char* txt)
+{
+		if(strcmp(txt,"_L") == 0)
+			return DIR_LEFT;
+		if(strcmp(txt,"_R") == 0)
+			return DIR_RIGHT;
+		if(strcmp(txt,"_U") == 0)
+			return DIR_UP;
+		if(strcmp(txt,"_D") == 0)
+			return DIR_DOWN;
+	return 0;
+}
diff -Nru base0132/src/emu/inpview.h w0132/src/emu/inpview.h
--- base0132/src/emu/inpview.h	1970-01-01 13:00:00.000000000 +1300
+++ w0132/src/emu/inpview.h	2009-06-08 22:48:42.000000000 +1200
@@ -0,0 +1,26 @@
+// Input viewer header
+
+#include "mame.h"
+
+struct inputs
+{
+	char text[6];  // character(s) to display
+	int port;  // port to check
+	int line;  // line to display on
+	int x;  // location on line to display at
+	char isanalogue;  // non-zero if the input is analogue
+	char playerspecific;  // is a player specific port (if 0, then player should be 0 too)
+	unsigned long colour;
+};
+
+struct input_type_definition
+{
+	char name[13];  // NULL-terminated string to identify different type using a possible -inplayout option
+	int lines;  // number of lines to use for this type
+	struct inputs inp[64];  // list of displayed buttons, and the inputs they correspond to (64 max)
+};
+
+void render_input(running_machine*);
+void inpview_set_data(int,const char*);
+int inpview_get_player(void);
+unsigned int convert_txt(char*);
diff -Nru base0132/src/emu/ui.c w0132/src/emu/ui.c
--- base0132/src/emu/ui.c	2009-04-27 21:18:17.000000000 +1200
+++ w0132/src/emu/ui.c	2009-06-08 22:48:42.000000000 +1200
@@ -30,7 +30,7 @@
 
 #include <ctype.h>
 
-
+#include "inpview.h"
 
 /***************************************************************************
     CONSTANTS
@@ -372,6 +372,11 @@
 	/* cancel takes us back to the ingame handler */
 	if (ui_handler_param == UI_HANDLER_CANCEL)
 		ui_set_handler(handler_ingame, 0);
+
+ 	// Input viewer
+ 	if(inpview_get_player() != 0)
+ 		render_input(machine);
+ 
 }
 
 

