summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/output.c')
-rw-r--r--src/emu/output.c406
1 files changed, 406 insertions, 0 deletions
diff --git a/src/emu/output.c b/src/emu/output.c
new file mode 100644
index 00000000000..9fb63c490a7
--- /dev/null
+++ b/src/emu/output.c
@@ -0,0 +1,406 @@
+/***************************************************************************
+
+ output.c
+
+ General purpose output routines.
+
+ Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team.
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include "output.h"
+#include "mame.h"
+#include <zlib.h>
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+#define HASH_SIZE 53
+
+
+
+/***************************************************************************
+ TYPE DEFINITIONS
+***************************************************************************/
+
+typedef struct _output_notify output_notify;
+struct _output_notify
+{
+ output_notify * next; /* link to next item */
+ output_notifier notifier; /* callback to call */
+ void * param; /* parameter to pass the callback */
+};
+
+
+typedef struct _output_item output_item;
+struct _output_item
+{
+ output_item * next; /* next item in list */
+ const char * name; /* string name of the item */
+ UINT32 hash; /* hash for this item name */
+ UINT32 id; /* unique ID for this item */
+ INT32 value; /* current value */
+ output_notify * notifylist; /* list of notifier callbacks */
+};
+
+
+
+/***************************************************************************
+ GLOBAL VARIABLES
+***************************************************************************/
+
+static output_item *itemtable[HASH_SIZE];
+static output_notify *global_notifylist;
+static UINT32 uniqueid = 12345;
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void output_pause(running_machine *machine, int pause);
+static void output_exit(running_machine *machine);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ copy_string - make a copy of a string
+-------------------------------------------------*/
+
+INLINE const char *copy_string(const char *string)
+{
+ char *newstring = malloc_or_die(strlen(string) + 1);
+ strcpy(newstring, string);
+ return newstring;
+}
+
+
+/*-------------------------------------------------
+ get_hash - return the hash of an output value
+-------------------------------------------------*/
+
+INLINE UINT32 get_hash(const char *string)
+{
+ return crc32(0, (UINT8 *)string, (UINT32)strlen(string));
+}
+
+
+/*-------------------------------------------------
+ find_item - find an item based on a string
+-------------------------------------------------*/
+
+INLINE output_item *find_item(const char *string)
+{
+ UINT32 hash = get_hash(string);
+ output_item *item;
+
+ /* use the hash as a starting point and find an entry */
+ for (item = itemtable[hash % HASH_SIZE]; item != NULL; item = item->next)
+ if (item->hash == hash && strcmp(string, item->name) == 0)
+ return item;
+
+ return NULL;
+}
+
+
+/*-------------------------------------------------
+ create_new_item - create a new item
+-------------------------------------------------*/
+
+INLINE output_item *create_new_item(const char *outname, INT32 value)
+{
+ output_item *item = malloc_or_die(sizeof(*item));
+ UINT32 hash = get_hash(outname);
+
+ /* fill in the data */
+ item->next = itemtable[hash % HASH_SIZE];
+ item->name = copy_string(outname);
+ item->hash = hash;
+ item->id = uniqueid++;
+ item->value = value;
+ item->notifylist = NULL;
+
+ /* add us to the hash table */
+ itemtable[hash % HASH_SIZE] = item;
+ return item;
+}
+
+
+
+/***************************************************************************
+ CORE IMPLEMENTATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ output_init - initialize everything
+-------------------------------------------------*/
+
+void output_init(running_machine *machine)
+{
+ /* add pause callback */
+ add_pause_callback(machine, output_pause);
+
+ /* get a callback when done */
+ add_exit_callback(machine, output_exit);
+
+ /* reset the lists */
+ memset(itemtable, 0, sizeof(itemtable));
+ global_notifylist = NULL;
+}
+
+
+/*-------------------------------------------------
+ output_pause - send pause message
+-------------------------------------------------*/
+
+static void output_pause(running_machine *machine, int pause)
+{
+ output_set_value("pause", pause & 1);
+}
+
+
+/*-------------------------------------------------
+ output_exit - cleanup on exit
+-------------------------------------------------*/
+
+static void output_exit(running_machine *machine)
+{
+ output_notify *notify;
+ output_item *item;
+ int hash;
+
+ /* remove all items */
+ for (hash = 0; hash < HASH_SIZE; hash++)
+ for (item = itemtable[hash]; item != NULL; )
+ {
+ output_item *next = item->next;
+
+ /* remove all notifiers */
+ for (notify = item->notifylist; notify != NULL; )
+ {
+ output_notify *next = notify->next;
+ free(notify);
+ notify = next;
+ }
+
+ /* free the name and the item */
+ if (item->name != NULL)
+ free((void *)item->name);
+ free(item);
+ item = next;
+ }
+
+ /* remove all global notifiers */
+ for (notify = global_notifylist; notify != NULL; )
+ {
+ output_notify *next = notify->next;
+ free(notify);
+ notify = next;
+ }
+}
+
+
+/*-------------------------------------------------
+ output_set_value - set the value of an output
+-------------------------------------------------*/
+
+void output_set_value(const char *outname, INT32 value)
+{
+ output_item *item = find_item(outname);
+ output_notify *notify;
+ INT32 oldval;
+
+ /* if no item of that name, create a new one and send the item's state */
+ if (item == NULL)
+ {
+ item = create_new_item(outname, value);
+ oldval = value + 1;
+ }
+
+ else
+ {
+ /* set the new value */
+ oldval = item->value;
+ item->value = value;
+ }
+
+ /* if the value is different, signal the notifier */
+ if (oldval != value)
+ {
+ /* call the local notifiers first */
+ for (notify = item->notifylist; notify != NULL; notify = notify->next)
+ (*notify->notifier)(outname, value, notify->param);
+
+ /* call the global notifiers next */
+ for (notify = global_notifylist; notify != NULL; notify = notify->next)
+ (*notify->notifier)(outname, value, notify->param);
+ }
+}
+
+
+/*-------------------------------------------------
+ output_set_indexed_value - set the value of an
+ indexed output
+-------------------------------------------------*/
+
+void output_set_indexed_value(const char *basename, int index, int value)
+{
+ char buffer[100];
+ char *dest = buffer;
+
+ /* copy the string */
+ while (*basename != 0)
+ *dest++ = *basename++;
+
+ /* append the index */
+ if (index >= 1000) *dest++ = '0' + ((index / 1000) % 10);
+ if (index >= 100) *dest++ = '0' + ((index / 100) % 10);
+ if (index >= 10) *dest++ = '0' + ((index / 10) % 10);
+ *dest++ = '0' + (index % 10);
+ *dest++ = 0;
+
+ /* set the value */
+ output_set_value(buffer, value);
+}
+
+
+/*-------------------------------------------------
+ output_get_value - return the value of an
+ output
+-------------------------------------------------*/
+
+INT32 output_get_value(const char *outname)
+{
+ output_item *item = find_item(outname);
+
+ /* if no item, value is 0 */
+ if (item == NULL)
+ return 0;
+ return item->value;
+}
+
+
+/*-------------------------------------------------
+ output_get_indexed_value - get the value of an
+ indexed output
+-------------------------------------------------*/
+
+INT32 output_get_indexed_value(const char *basename, int index)
+{
+ char buffer[100];
+ char *dest = buffer;
+
+ /* copy the string */
+ while (*basename != 0)
+ *dest++ = *basename++;
+
+ /* append the index */
+ if (index >= 1000) *dest++ = '0' + ((index / 1000) % 10);
+ if (index >= 100) *dest++ = '0' + ((index / 100) % 10);
+ if (index >= 10) *dest++ = '0' + ((index / 10) % 10);
+ *dest++ = '0' + (index % 10);
+ *dest++ = 0;
+
+ /* set the value */
+ return output_get_value(buffer);
+}
+
+
+/*-------------------------------------------------
+ output_set_notifier - sets a notifier callback
+ for a particular output, or for all outputs
+ if NULL is specified
+-------------------------------------------------*/
+
+void output_set_notifier(const char *outname, output_notifier callback, void *param)
+{
+ output_notify **headptr;
+
+ /* if an item is specified, find it */
+ if (outname != NULL)
+ {
+ output_item *item = find_item(outname);
+
+ /* if no item of that name, create a new one */
+ if (item == NULL)
+ item = create_new_item(outname, 0);
+ headptr = &item->notifylist;
+ }
+
+ /* if no item is specified, we add to the global list */
+ else
+ headptr = &global_notifylist;
+
+ /* find the end of the list and add to it */
+ while (*headptr != NULL)
+ headptr = &(*headptr)->next;
+ *headptr = malloc_or_die(sizeof(**headptr));
+
+ /* fill in the new record */
+ (*headptr)->next = NULL;
+ (*headptr)->notifier = callback;
+ (*headptr)->param = param;
+}
+
+
+/*-------------------------------------------------
+ output_notify_all - immediately call the given
+ notifier for all outputs
+-------------------------------------------------*/
+
+void output_notify_all(output_notifier callback, void *param)
+{
+ output_item *item;
+ int hash;
+
+ /* remove all items */
+ for (hash = 0; hash < HASH_SIZE; hash++)
+ for (item = itemtable[hash]; item != NULL; item = item->next)
+ (*callback)(item->name, item->value, param);
+}
+
+
+/*-------------------------------------------------
+ output_name_to_id - returns a unique ID for
+ a given name
+-------------------------------------------------*/
+
+UINT32 output_name_to_id(const char *outname)
+{
+ output_item *item = find_item(outname);
+
+ /* if no item, ID is 0 */
+ if (item == NULL)
+ return 0;
+ return item->id;
+}
+
+
+/*-------------------------------------------------
+ output_id_to_name - returns a name that maps
+ to a given unique ID
+-------------------------------------------------*/
+
+const char *output_id_to_name(UINT32 id)
+{
+ output_item *item;
+ int hash;
+
+ /* remove all items */
+ for (hash = 0; hash < HASH_SIZE; hash++)
+ for (item = itemtable[hash]; item != NULL; item = item->next)
+ if (item->id == id)
+ return item->name;
+
+ /* nothing found, return NULL */
+ return NULL;
+}