summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd/modules/output
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2016-06-05 21:11:56 +0200
committer Miodrag Milanovic <mmicko@gmail.com>2016-06-05 21:11:56 +0200
commitdba7c1ac9420110762b635cffe605190399251e5 (patch)
tree0e0598f22988eacd7daf15874972b1f53d5e8dcc /src/osd/modules/output
parenteb2617f7ae2d4d052de0cdbb4c7dfff3d8dc2c96 (diff)
Placed back old output system as module "-output windows" need more things cleaned (nw)
Diffstat (limited to 'src/osd/modules/output')
-rw-r--r--src/osd/modules/output/output_module.h7
-rw-r--r--src/osd/modules/output/win32_output.cpp336
-rw-r--r--src/osd/modules/output/win32_output.h86
3 files changed, 428 insertions, 1 deletions
diff --git a/src/osd/modules/output/output_module.h b/src/osd/modules/output/output_module.h
index 81fcaae2cce..f3461d3e1f6 100644
--- a/src/osd/modules/output/output_module.h
+++ b/src/osd/modules/output/output_module.h
@@ -20,11 +20,16 @@
class output_module
{
public:
- output_module() { }
+ output_module(): m_machine(nullptr) { }
virtual ~output_module() { }
virtual void notify(const char *outname, INT32 value) = 0;
+
+ void set_machine(running_machine *machine) { m_machine = machine; };
+ running_machine &machine() const { return *m_machine; }
+private:
+ running_machine *m_machine;
};
#endif /* OUTPUT_MODULE_H_ */
diff --git a/src/osd/modules/output/win32_output.cpp b/src/osd/modules/output/win32_output.cpp
new file mode 100644
index 00000000000..419a1dc1692
--- /dev/null
+++ b/src/osd/modules/output/win32_output.cpp
@@ -0,0 +1,336 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+//============================================================
+//
+// output.c - Win32 implementation of MAME output routines
+//
+//============================================================
+
+#if defined(OSD_WINDOWS)
+
+// standard windows headers
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+// MAME headers
+#include "emu.h"
+#include "winmain.h"
+
+#include "winutil.h"
+#include "win32_output.h"
+
+
+//============================================================
+// CONSTANTS
+//============================================================
+
+// window styles
+#define WINDOW_STYLE WS_OVERLAPPEDWINDOW
+#define WINDOW_STYLE_EX 0
+
+
+
+//============================================================
+// TYPEDEFS
+//============================================================
+
+struct registered_client
+{
+ registered_client * next; // next client in the list
+ LPARAM id; // client-specified ID
+ HWND hwnd; // client HWND
+ running_machine * machine;
+};
+
+
+// message IDs
+static UINT om_mame_start;
+static UINT om_mame_stop;
+static UINT om_mame_update_state;
+static UINT om_mame_register_client;
+static UINT om_mame_unregister_client;
+static UINT om_mame_get_id_string;
+
+
+
+//============================================================
+// FUNCTION PROTOTYPES
+//============================================================
+
+static LRESULT CALLBACK output_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam);
+
+class output_win32 : public osd_module, public output_module
+{
+public:
+ output_win32()
+ : osd_module(OSD_OUTPUT_PROVIDER, "windows"), output_module()
+ {
+ }
+ virtual ~output_win32() { }
+
+ virtual int init(const osd_options &options) override;
+ virtual void exit() override;
+
+ // output_module
+
+ virtual void notify(const char *outname, INT32 value) override;
+
+ int create_window_class(void);
+ LRESULT register_client(HWND hwnd, LPARAM id);
+ LRESULT unregister_client(HWND hwnd, LPARAM id);
+ LRESULT send_id_string(HWND hwnd, LPARAM id);
+
+private:
+ // our HWND
+ HWND m_output_hwnd;
+
+ // client list
+ registered_client * m_clientlist;
+
+};
+
+
+//============================================================
+// output_init
+//============================================================
+
+int output_win32::init(const osd_options &options)
+{
+ int result;
+
+ // reset globals
+ m_clientlist = nullptr;
+
+ // create our window class
+ result = create_window_class();
+ assert(result == 0);
+ (void)result; // to silence gcc 4.6
+
+ // create a window
+ m_output_hwnd = CreateWindowEx(
+ WINDOW_STYLE_EX,
+ OUTPUT_WINDOW_CLASS,
+ OUTPUT_WINDOW_NAME,
+ WINDOW_STYLE,
+ 0, 0,
+ 1, 1,
+ nullptr,
+ nullptr,
+ GetModuleHandleUni(),
+ nullptr);
+ assert(m_output_hwnd != nullptr);
+
+ // set a pointer to the running machine
+ SetWindowLongPtr(m_output_hwnd, GWLP_USERDATA, (LONG_PTR)this);
+
+ // allocate message ids
+ om_mame_start = RegisterWindowMessage(OM_MAME_START);
+ assert(om_mame_start != 0);
+ om_mame_stop = RegisterWindowMessage(OM_MAME_STOP);
+ assert(om_mame_stop != 0);
+ om_mame_update_state = RegisterWindowMessage(OM_MAME_UPDATE_STATE);
+ assert(om_mame_update_state != 0);
+
+ om_mame_register_client = RegisterWindowMessage(OM_MAME_REGISTER_CLIENT);
+ assert(om_mame_register_client != 0);
+ om_mame_unregister_client = RegisterWindowMessage(OM_MAME_UNREGISTER_CLIENT);
+ assert(om_mame_unregister_client != 0);
+ om_mame_get_id_string = RegisterWindowMessage(OM_MAME_GET_ID_STRING);
+ assert(om_mame_get_id_string != 0);
+
+ // broadcast a startup message
+ PostMessage(HWND_BROADCAST, om_mame_start, (WPARAM)m_output_hwnd, 0);
+
+ return 0;
+}
+
+
+//============================================================
+// output_exit
+//============================================================
+
+void output_win32::exit()
+{
+ // free all the clients
+ while (m_clientlist != nullptr)
+ {
+ registered_client *temp = m_clientlist;
+ m_clientlist = temp->next;
+ global_free(temp);
+ }
+
+ // broadcast a shutdown message
+ PostMessage(HWND_BROADCAST, om_mame_stop, (WPARAM)m_output_hwnd, 0);
+}
+
+
+//============================================================
+// create_window_class
+//============================================================
+
+int output_win32::create_window_class(void)
+{
+ static UINT8 classes_created = FALSE;
+
+ /* only do this once */
+ if (!classes_created)
+ {
+ WNDCLASS wc = { 0 };
+
+ // initialize the description of the window class
+ wc.lpszClassName = OUTPUT_WINDOW_CLASS;
+ wc.hInstance = GetModuleHandleUni();
+ wc.lpfnWndProc = output_window_proc;
+
+ UnregisterClass(wc.lpszClassName, wc.hInstance);
+
+ // register the class; fail if we can't
+ if (!RegisterClass(&wc))
+ return 1;
+ classes_created = TRUE;
+ }
+
+ return 0;
+}
+
+
+//============================================================
+// output_window_proc
+//============================================================
+
+static LRESULT CALLBACK output_window_proc(HWND wnd, UINT message, WPARAM wparam, LPARAM lparam)
+{
+ LONG_PTR ptr = GetWindowLongPtr(wnd, GWLP_USERDATA);
+ output_win32 &output = *(output_win32 *)ptr;
+
+ // register a new client
+ if (message == om_mame_register_client)
+ return output.register_client((HWND)wparam, lparam);
+
+ // unregister a client
+ else if (message == om_mame_unregister_client)
+ return output.unregister_client((HWND)wparam, lparam);
+
+ // get a string for an ID
+ else if (message == om_mame_get_id_string)
+ return output.send_id_string((HWND)wparam, lparam);
+
+ else
+ return DefWindowProc(wnd, message, wparam, lparam);
+}
+
+
+//============================================================
+// register_client
+//============================================================
+
+LRESULT output_win32::register_client(HWND hwnd, LPARAM id)
+{
+ registered_client **client;
+
+ // find the end of the list; if we find ourself already registered,
+ // return 1
+ for (client = &m_clientlist; *client != nullptr; client = &(*client)->next)
+ if ((*client)->id == id)
+ {
+ (*client)->hwnd = hwnd;
+ machine().output().notify_all(this);
+ return 1;
+ }
+
+ // add us to the end
+ *client = global_alloc(registered_client);
+ (*client)->next = nullptr;
+ (*client)->id = id;
+ (*client)->hwnd = hwnd;
+ (*client)->machine = &machine();
+
+ // request a notification for all outputs
+ machine().output().notify_all(this);
+ return 0;
+}
+
+
+//============================================================
+// unregister_client
+//============================================================
+
+LRESULT output_win32::unregister_client(HWND hwnd, LPARAM id)
+{
+ registered_client **client;
+ int found = FALSE;
+
+ // find any matching IDs in the list and remove them
+ for (client = &m_clientlist; *client != nullptr; client = &(*client)->next)
+ if ((*client)->id == id)
+ {
+ registered_client *temp = *client;
+ *client = (*client)->next;
+ global_free(temp);
+ found = TRUE;
+ break;
+ }
+
+ // return an error if not found
+ return found ? 0 : 1;
+}
+
+
+//============================================================
+// send_id_string
+//============================================================
+
+LRESULT output_win32::send_id_string(HWND hwnd, LPARAM id)
+{
+ COPYDATASTRUCT copydata;
+ const char *name;
+ int datalen;
+
+ // id 0 is the name of the game
+ if (id == 0)
+ name = machine().system().name;
+ else
+ name = machine().output().id_to_name(id);
+
+ // a NULL name is an empty string
+ if (name == nullptr)
+ name = "";
+
+ // allocate memory for the message
+ datalen = sizeof(copydata_id_string) + strlen(name) + 1;
+ dynamic_buffer buffer(datalen);
+ copydata_id_string *temp = (copydata_id_string *)&buffer[0];
+ temp->id = id;
+ strcpy(temp->string, name);
+
+ // reply by using SendMessage with WM_COPYDATA
+ copydata.dwData = COPYDATA_MESSAGE_ID_STRING;
+ copydata.cbData = datalen;
+ copydata.lpData = temp;
+ SendMessage(hwnd, WM_COPYDATA, (WPARAM)m_output_hwnd, (LPARAM)&copydata);
+
+ return 0;
+}
+
+
+//============================================================
+// notifier_callback
+//============================================================
+
+void output_win32::notify(const char *outname, INT32 value)
+{
+ registered_client *client;
+ // loop over clients and notify them
+ for (client = m_clientlist; client != nullptr; client = client->next)
+ {
+ PostMessage(client->hwnd, om_mame_update_state, client->machine->output().name_to_id(outname), value);
+ }
+}
+
+
+
+#else
+MODULE_NOT_SUPPORTED(output_win32, OSD_OUTPUT_PROVIDER, "windows")
+#endif
+
+MODULE_DEFINITION(OUTPUT_WIN32, output_win32)
diff --git a/src/osd/modules/output/win32_output.h b/src/osd/modules/output/win32_output.h
new file mode 100644
index 00000000000..9d71332b44b
--- /dev/null
+++ b/src/osd/modules/output/win32_output.h
@@ -0,0 +1,86 @@
+// license:BSD-3-Clause
+// copyright-holders:Aaron Giles
+//============================================================
+//
+// output.h - Win32 implementation of MAME output routines
+//
+//============================================================
+
+#ifndef __WINDOWS_OUTPUT_H__
+#define __WINDOWS_OUTPUT_H__
+
+
+//============================================================
+// CONSTANTS
+//============================================================
+
+// window parameters
+#define OUTPUT_WINDOW_CLASS TEXT("MAMEOutput")
+#define OUTPUT_WINDOW_NAME TEXT("MAMEOutput")
+
+//
+// These messages are sent by MAME:
+//
+
+// OM_MAME_START: broadcast when MAME initializes
+// WPARAM = HWND of MAME's output window
+// LPARAM = unused
+#define OM_MAME_START TEXT("MAMEOutputStart")
+
+// OM_MAME_STOP: broadcast when MAME shuts down
+// WPARAM = HWND of MAME's output window
+// LPARAM = unused
+#define OM_MAME_STOP TEXT("MAMEOutputStop")
+
+// OM_MAME_UPDATE_STATE: sent to registered clients when the state
+// of an output changes
+// WPARAM = ID of the output
+// LPARAM = new value for the output
+#define OM_MAME_UPDATE_STATE TEXT("MAMEOutputUpdateState")
+
+
+//
+// These messages are sent by external clients to MAME:
+//
+
+// OM_MAME_REGISTER_CLIENT: sent to MAME to register a client
+// WPARAM = HWND of client's listener window
+// LPARAM = client-specified ID (must be unique)
+#define OM_MAME_REGISTER_CLIENT TEXT("MAMEOutputRegister")
+
+// OM_MAME_UNREGISTER_CLIENT: sent to MAME to unregister a client
+// WPARAM = HWND of client's listener window
+// LPARAM = client-specified ID (must match registration)
+#define OM_MAME_UNREGISTER_CLIENT TEXT("MAMEOutputUnregister")
+
+// OM_MAME_GET_ID_STRING: requests the string associated with a
+// given ID. ID=0 is always the name of the game. Other IDs are
+// only discoverable from a OM_MAME_UPDATE_STATE message. The
+// result will be sent back as a WM_COPYDATA message with MAME's
+// output window as the sender, dwData = the ID of the string,
+// and lpData pointing to a NULL-terminated string.
+// WPARAM = HWND of client's listener window
+// LPARAM = ID you wish to know about
+#define OM_MAME_GET_ID_STRING TEXT("MAMEOutputGetIDString")
+
+
+//
+// These constants are used to identify WM_COPYDATA messages
+// coming from MAME:
+//
+
+#define COPYDATA_MESSAGE_ID_STRING 1
+
+
+
+//============================================================
+// TYPE DEFINITIONS
+//============================================================
+
+struct copydata_id_string
+{
+ UINT32 id; // ID that was requested
+ char string[1]; // string array containing the data
+};
+
+#endif /* __WINDOWS_OUTPUT_H__ */