From 98a6781c271b004174052bbd1750351149bf91ce Mon Sep 17 00:00:00 2001 From: couriersud Date: Wed, 4 Mar 2015 01:39:52 +0100 Subject: First step to move osd_printf_* into osd again. Callbacks are now implemented using an interface and use a push/pop approach where the pop can happen out of order of pushes. [Couriersud] --- src/emu/validity.c | 82 +++++++++++++++++------------------ src/emu/validity.h | 14 +++--- src/osd/modules/lib/osdobj_common.c | 43 +++++++++++++++---- src/osd/modules/lib/osdobj_common.h | 5 ++- src/osd/osdcore.c | 85 ++++++++++++++----------------------- src/osd/osdcore.h | 28 +++++++++--- src/osd/windows/winmain.c | 63 +++++++++++++++------------ 7 files changed, 175 insertions(+), 145 deletions(-) diff --git a/src/emu/validity.c b/src/emu/validity.c index cacf92cdafa..4ad2453da32 100644 --- a/src/emu/validity.c +++ b/src/emu/validity.c @@ -199,18 +199,18 @@ void validity_checker::check_all() if (m_errors > 0 || m_warnings > 0) { astring tempstr; - output_via_delegate(m_saved_error_output, "Core: %d errors, %d warnings\n", m_errors, m_warnings); + output_via_delegate(OSD_OUTPUT_CHANNEL_ERROR, "Core: %d errors, %d warnings\n", m_errors, m_warnings); if (m_errors > 0) { m_error_text.replace("\n", "\n "); - output_via_delegate(m_saved_error_output, "Errors:\n %s", m_error_text.cstr()); + output_via_delegate(OSD_OUTPUT_CHANNEL_ERROR, "Errors:\n %s", m_error_text.cstr()); } if (m_warnings > 0) { m_warning_text.replace("\n", "\n "); - output_via_delegate(m_saved_error_output, "Warnings:\n %s", m_warning_text.cstr()); + output_via_delegate(OSD_OUTPUT_CHANNEL_ERROR, "Warnings:\n %s", m_warning_text.cstr()); } - output_via_delegate(m_saved_error_output, "\n"); + output_via_delegate(OSD_OUTPUT_CHANNEL_ERROR, "\n"); } // then iterate over all drivers and check them @@ -232,8 +232,7 @@ void validity_checker::check_all() void validity_checker::validate_begin() { // take over error and warning outputs - m_saved_error_output = osd_set_output_channel(OSD_OUTPUT_CHANNEL_ERROR, output_delegate(FUNC(validity_checker::error_output), this)); - m_saved_warning_output = osd_set_output_channel(OSD_OUTPUT_CHANNEL_WARNING, output_delegate(FUNC(validity_checker::warning_output), this)); + osd_output::push(this); // reset all our maps m_names_map.reset(); @@ -257,8 +256,7 @@ void validity_checker::validate_begin() void validity_checker::validate_end() { // restore the original output callbacks - osd_set_output_channel(OSD_OUTPUT_CHANNEL_ERROR, m_saved_error_output); - osd_set_output_channel(OSD_OUTPUT_CHANNEL_WARNING, m_saved_warning_output); + osd_output::pop(this); } @@ -301,18 +299,18 @@ void validity_checker::validate_one(const game_driver &driver) if (m_errors > start_errors || m_warnings > start_warnings) { astring tempstr; - output_via_delegate(m_saved_error_output, "Driver %s (file %s): %d errors, %d warnings\n", driver.name, core_filename_extract_base(tempstr, driver.source_file).cstr(), m_errors - start_errors, m_warnings - start_warnings); + output_via_delegate(OSD_OUTPUT_CHANNEL_ERROR, "Driver %s (file %s): %d errors, %d warnings\n", driver.name, core_filename_extract_base(tempstr, driver.source_file).cstr(), m_errors - start_errors, m_warnings - start_warnings); if (m_errors > start_errors) { m_error_text.replace("\n", "\n "); - output_via_delegate(m_saved_error_output, "Errors:\n %s", m_error_text.cstr()); + output_via_delegate(OSD_OUTPUT_CHANNEL_ERROR, "Errors:\n %s", m_error_text.cstr()); } if (m_warnings > start_warnings) { m_warning_text.replace("\n", "\n "); - output_via_delegate(m_saved_error_output, "Warnings:\n %s", m_warning_text.cstr()); + output_via_delegate(OSD_OUTPUT_CHANNEL_ERROR, "Warnings:\n %s", m_warning_text.cstr()); } - output_via_delegate(m_saved_error_output, "\n"); + output_via_delegate(OSD_OUTPUT_CHANNEL_ERROR, "\n"); } // reset the driver/device @@ -834,10 +832,10 @@ void validity_checker::validate_dip_settings(ioport_field &field) // if we have a coin error, demonstrate the correct way if (coin_error) { - output_via_delegate(m_saved_error_output, " Note proper coin sort order should be:\n"); + output_via_delegate(OSD_OUTPUT_CHANNEL_ERROR, " Note proper coin sort order should be:\n"); for (int entry = 0; entry < ARRAY_LENGTH(coin_list); entry++) if (coin_list[entry]) - output_via_delegate(m_saved_error_output, " %s\n", ioport_string_from_index(__input_string_coinage_start + entry)); + output_via_delegate(OSD_OUTPUT_CHANNEL_ERROR, " %s\n", ioport_string_from_index(__input_string_coinage_start + entry)); } } @@ -1057,53 +1055,51 @@ void validity_checker::build_output_prefix(astring &string) // error_output - error message output override //------------------------------------------------- -void validity_checker::error_output(const char *format, va_list argptr) +void validity_checker::output_callback(osd_output_channel channel, const char *msg, va_list args) { - // count the error - m_errors++; - - // output the source(driver) device 'tag' astring output; - build_output_prefix(output); - - // generate the string - output.catvprintf(format, argptr); - m_error_text.cat(output); -} - + switch (channel) + { + case OSD_OUTPUT_CHANNEL_ERROR: + // count the error + m_errors++; -//------------------------------------------------- -// warning_output - warning message output -// override -//------------------------------------------------- + // output the source(driver) device 'tag' + build_output_prefix(output); -void validity_checker::warning_output(const char *format, va_list argptr) -{ - // count the error - m_warnings++; + // generate the string + output.catvprintf(msg, args); + m_error_text.cat(output); + break; + case OSD_OUTPUT_CHANNEL_WARNING: + // count the error + m_warnings++; - // output the source(driver) device 'tag' - astring output; - build_output_prefix(output); + // output the source(driver) device 'tag' + build_output_prefix(output); - // generate the string and output to the original target - output.catvprintf(format, argptr); - m_warning_text.cat(output); + // generate the string and output to the original target + output.catvprintf(msg, args); + m_warning_text.cat(output); + break; + default: + chain_output(channel, msg, args); + break; + } } - //------------------------------------------------- // output_via_delegate - helper to output a // message via a varargs string, so the argptr // can be forwarded onto the given delegate //------------------------------------------------- -void validity_checker::output_via_delegate(output_delegate &delegate, const char *format, ...) +void validity_checker::output_via_delegate(osd_output_channel channel, const char *format, ...) { va_list argptr; // call through to the delegate with the proper parameters va_start(argptr, format); - delegate(format, argptr); + this->chain_output(channel, format, argptr); va_end(argptr); } diff --git a/src/emu/validity.h b/src/emu/validity.h index 1c1756f3c79..0dc58f6ff1d 100644 --- a/src/emu/validity.h +++ b/src/emu/validity.h @@ -26,7 +26,7 @@ class machine_config; // core validity checker class -class validity_checker +class validity_checker : public osd_output { // internal map types typedef tagmap_t game_driver_map; @@ -52,6 +52,11 @@ public: // generic registry of already-checked stuff bool already_checked(const char *string) { return (m_already_checked.add(string, 1, false) == TMERR_DUPLICATE); } + // osd_output interface + +protected: + virtual void output_callback(osd_output_channel channel, const char *msg, va_list args); + private: // internal helpers const char *ioport_string_from_index(UINT32 index); @@ -75,9 +80,7 @@ private: // output helpers void build_output_prefix(astring &string); - void error_output(const char *format, va_list argptr); - void warning_output(const char *format, va_list argptr); - void output_via_delegate(output_delegate &delegate, const char *format, ...) ATTR_PRINTF(3,4); + void output_via_delegate(osd_output_channel channel, const char *format, ...) ATTR_PRINTF(3,4); // internal driver list driver_enumerator m_drivlist; @@ -102,9 +105,6 @@ private: int_map m_region_map; tagmap_t m_already_checked; - // callbacks - output_delegate m_saved_error_output; - output_delegate m_saved_warning_output; }; #endif diff --git a/src/osd/modules/lib/osdobj_common.c b/src/osd/modules/lib/osdobj_common.c index df208356c52..222a7d0aca6 100644 --- a/src/osd/modules/lib/osdobj_common.c +++ b/src/osd/modules/lib/osdobj_common.c @@ -133,12 +133,24 @@ osd_options::osd_options() //------------------------------------------------- osd_common_t::osd_common_t(osd_options &options) - : m_machine(NULL), + : osd_output(), m_machine(NULL), m_options(options), m_sound(NULL), m_debugger(NULL) +{ + osd_output::push(this); +} + +//------------------------------------------------- +// osd_interface - destructor +//------------------------------------------------- +osd_common_t::~osd_common_t() { + for(int i= 0; i < m_video_names.count(); ++i) + osd_free(const_cast(m_video_names[i])); + //m_video_options,reset(); + osd_output::pop(this); } #define REGISTER_MODULE(_O, _X ) { extern const module_type _X; _O . register_module( _X ); } @@ -228,18 +240,33 @@ void osd_common_t::update_option(const char * key, dynamic_array & m_options.set_description(key, core_strdup(current_value.cat(new_option_value).cstr())); } + //------------------------------------------------- -// osd_interface - destructor +// output_callback - callback for osd_printf_... //------------------------------------------------- - -osd_common_t::~osd_common_t() +void osd_common_t::output_callback(osd_output_channel channel, const char *msg, va_list args) { - for(int i= 0; i < m_video_names.count(); ++i) - osd_free(const_cast(m_video_names[i])); - //m_video_options,reset(); + switch (channel) + { + case OSD_OUTPUT_CHANNEL_ERROR: + case OSD_OUTPUT_CHANNEL_WARNING: + vfprintf(stderr, msg, args); + break; + case OSD_OUTPUT_CHANNEL_INFO: + case OSD_OUTPUT_CHANNEL_VERBOSE: + case OSD_OUTPUT_CHANNEL_LOG: + vfprintf(stdout, msg, args); + break; + case OSD_OUTPUT_CHANNEL_DEBUG: +#ifdef MAME_DEBUG + vfprintf(stdout, msg, args); +#endif + break; + default: + break; + } } - //------------------------------------------------- // init - initialize the OSD system. //------------------------------------------------- diff --git a/src/osd/modules/lib/osdobj_common.h b/src/osd/modules/lib/osdobj_common.h index 36952dc1731..3b7ce43114c 100644 --- a/src/osd/modules/lib/osdobj_common.h +++ b/src/osd/modules/lib/osdobj_common.h @@ -140,7 +140,7 @@ private: // ======================> osd_interface // description of the currently-running machine -class osd_common_t : public osd_interface +class osd_common_t : public osd_interface, osd_output { public: // construction/destruction @@ -211,6 +211,9 @@ public: osd_options &options() { return m_options; } + // osd_output interface ... + virtual void output_callback(osd_output_channel channel, const char *msg, va_list args); + protected: virtual bool input_init(); virtual void input_pause(); diff --git a/src/osd/osdcore.c b/src/osd/osdcore.c index fff285c02da..ddba6866b22 100644 --- a/src/osd/osdcore.c +++ b/src/osd/osdcore.c @@ -3,69 +3,48 @@ bool g_print_verbose = false; +static const int MAXSTACK = 10; +static osd_output *m_stack[MAXSTACK]; +static int m_ptr = -1; /*------------------------------------------------- - osd_file_output_callback - default callback - for file output + osd_output -------------------------------------------------*/ -void osd_file_output_callback(FILE *param, const char *format, va_list argptr) +void osd_output::push(osd_output *delegate) { - vfprintf(param, format, argptr); + assert(m_ptr < MAXSTACK); + delegate->m_chain = (m_ptr >= 0 ? m_stack[m_ptr] : NULL); + m_ptr++; + m_stack[m_ptr] = delegate; + //printf("push m_ptr == %d\n", m_ptr); } - -/*------------------------------------------------- - osd_null_output_callback - default callback - for no output --------------------------------------------------*/ - -void osd_null_output_callback(FILE *param, const char *format, va_list argptr) +void osd_output::pop(osd_output *delegate) { + int f = -1; + for (int i=0; i<=m_ptr; i++) + if (m_stack[i] == delegate) + { + f = i; + break; + } + if (f >= 0) + { + if (f < m_ptr) + m_stack[f+1]->m_chain = m_stack[f]->m_chain; + m_ptr--; + for (int i = f; i <= m_ptr; i++) + m_stack[i] = m_stack[i+1]; + } + //printf("pop m_ptr == %d\n", m_ptr); } - -/* output channels */ -static output_delegate output_cb[OSD_OUTPUT_CHANNEL_COUNT] = -{ - output_delegate(FUNC(osd_file_output_callback), stderr), // OSD_OUTPUT_CHANNEL_ERROR - output_delegate(FUNC(osd_file_output_callback), stderr), // OSD_OUTPUT_CHANNEL_WARNING - output_delegate(FUNC(osd_file_output_callback), stdout), // OSD_OUTPUT_CHANNEL_INFO -#ifdef MAME_DEBUG - output_delegate(FUNC(osd_file_output_callback), stdout), // OSD_OUTPUT_CHANNEL_DEBUG -#else - output_delegate(FUNC(osd_null_output_callback), stdout), // OSD_OUTPUT_CHANNEL_DEBUG -#endif - output_delegate(FUNC(osd_file_output_callback), stdout), // OSD_OUTPUT_CHANNEL_VERBOSE - output_delegate(FUNC(osd_file_output_callback), stdout) // OSD_OUTPUT_CHANNEL_LOG -}; - - /*************************************************************************** OUTPUT MANAGEMENT ***************************************************************************/ -/*------------------------------------------------- - osd_set_output_channel - configure an output - channel --------------------------------------------------*/ - -output_delegate osd_set_output_channel(output_channel channel, output_delegate callback) -{ - if (!(channel < OSD_OUTPUT_CHANNEL_COUNT) || callback.isnull()) - { - throw std::exception(); - } - - /* return the originals if requested */ - output_delegate prevcb = output_cb[channel]; - - /* set the new ones */ - output_cb[channel] = callback; - return prevcb; -} - /*------------------------------------------------- osd_printf_error - output an error to the appropriate callback @@ -77,7 +56,7 @@ void CLIB_DECL osd_printf_error(const char *format, ...) /* do the output */ va_start(argptr, format); - output_cb[OSD_OUTPUT_CHANNEL_ERROR](format, argptr); + if (m_ptr >= 0) m_stack[m_ptr]->output_callback(OSD_OUTPUT_CHANNEL_ERROR, format, argptr); va_end(argptr); } @@ -93,7 +72,7 @@ void CLIB_DECL osd_printf_warning(const char *format, ...) /* do the output */ va_start(argptr, format); - output_cb[OSD_OUTPUT_CHANNEL_WARNING](format, argptr); + if (m_ptr >= 0) m_stack[m_ptr]->output_callback(OSD_OUTPUT_CHANNEL_WARNING, format, argptr); va_end(argptr); } @@ -109,7 +88,7 @@ void CLIB_DECL osd_printf_info(const char *format, ...) /* do the output */ va_start(argptr, format); - output_cb[OSD_OUTPUT_CHANNEL_INFO](format, argptr); + if (m_ptr >= 0) m_stack[m_ptr]->output_callback(OSD_OUTPUT_CHANNEL_INFO, format, argptr); va_end(argptr); } @@ -129,7 +108,7 @@ void CLIB_DECL osd_printf_verbose(const char *format, ...) /* do the output */ va_start(argptr, format); - output_cb[OSD_OUTPUT_CHANNEL_VERBOSE](format, argptr); + if (m_ptr >= 0) m_stack[m_ptr]->output_callback(OSD_OUTPUT_CHANNEL_VERBOSE, format, argptr); va_end(argptr); } @@ -145,7 +124,7 @@ void CLIB_DECL osd_printf_debug(const char *format, ...) /* do the output */ va_start(argptr, format); - output_cb[OSD_OUTPUT_CHANNEL_DEBUG](format, argptr); + if (m_ptr >= 0) m_stack[m_ptr]->output_callback(OSD_OUTPUT_CHANNEL_DEBUG, format, argptr); va_end(argptr); } diff --git a/src/osd/osdcore.h b/src/osd/osdcore.h index 8659592fc5c..ceb0cb45dbc 100644 --- a/src/osd/osdcore.h +++ b/src/osd/osdcore.h @@ -20,7 +20,6 @@ #define __OSDCORE_H__ #include "osdcomm.h" -#include "delegate.h" #include /*************************************************************************** @@ -926,7 +925,7 @@ const char *osd_get_volume_name(int idx); /* ----- output management ----- */ // output channels -enum output_channel +enum osd_output_channel { OSD_OUTPUT_CHANNEL_ERROR, OSD_OUTPUT_CHANNEL_WARNING, @@ -937,11 +936,26 @@ enum output_channel OSD_OUTPUT_CHANNEL_COUNT }; -// output channel callback -typedef delegate output_delegate; - -/* set the output handler for a channel, returns the current one */ -output_delegate osd_set_output_channel(output_channel channel, output_delegate callback); +class osd_output +{ +public: + osd_output() : m_chain(NULL) { } + virtual ~osd_output() { } + + virtual void output_callback(osd_output_channel channel, const char *msg, va_list args) = 0; + + static void push(osd_output *delegate); + static void pop(osd_output *delegate); +protected: + + void chain_output(osd_output_channel channel, const char *msg, va_list args) + { + if (m_chain != NULL) + m_chain->output_callback(channel, msg, args); + } +private: + osd_output *m_chain; +}; /* calls to be used by the code */ void CLIB_DECL osd_printf_error(const char *format, ...) ATTR_PRINTF(1,2); diff --git a/src/osd/windows/winmain.c b/src/osd/windows/winmain.c index ffda737bfbd..8a52feb921a 100644 --- a/src/osd/windows/winmain.c +++ b/src/osd/windows/winmain.c @@ -198,6 +198,31 @@ private: FPTR * m_buffer_end; }; +//============================================================ +// winui_output_error +//============================================================ + +class winui_output_error : public osd_output +{ +public: + virtual void output_callback(osd_output_channel channel, const char *msg, va_list args) + { + if (channel == OSD_OUTPUT_CHANNEL_ERROR) + { + char buffer[1024]; + + // if we are in fullscreen mode, go to windowed mode + if ((video_config.windowed == 0) && (win_window_list != NULL)) + winwindow_toggle_full_screen(); + + vsnprintf(buffer, ARRAY_LENGTH(buffer), msg, args); + win_message_box_utf8(win_window_list ? win_window_list->m_hwnd : NULL, buffer, emulator_info::get_appname(), MB_OK); + } + else + chain_output(channel, msg, args); + } +}; + @@ -237,7 +262,6 @@ static BOOL WINAPI control_handler(DWORD type); static int is_double_click_start(int argc); static DWORD WINAPI watchdog_thread_entry(LPVOID lpParameter); static LONG WINAPI exception_filter(struct _EXCEPTION_POINTERS *info); -static void winui_output_error(delegate_late_bind *__dummy, const char *format, va_list argptr); @@ -391,24 +415,27 @@ int main(int argc, char *argv[]) extern void (*s_debugger_stack_crawler)(); s_debugger_stack_crawler = winmain_dump_stack; - // if we're a GUI app, out errors to message boxes - if (win_is_gui_application() || is_double_click_start(argc)) - { - // if we are a GUI app, output errors to message boxes - osd_set_output_channel(OSD_OUTPUT_CHANNEL_ERROR, output_delegate(FUNC(winui_output_error), (delegate_late_bind *)0)); - - // make sure any console window that opened on our behalf is nuked - FreeConsole(); - } // parse config and cmdline options DWORD result = 0; { windows_options options; windows_osd_interface osd(options); + // if we're a GUI app, out errors to message boxes + // Initialize this after the osd interface so that we are first in the + // output order + winui_output_error winerror; + if (win_is_gui_application() || is_double_click_start(argc)) + { + // if we are a GUI app, output errors to message boxes + osd_output::push(&winerror); + // make sure any console window that opened on our behalf is nuked + FreeConsole(); + } osd.register_options(); cli_frontend frontend(options, osd); result = frontend.execute(argc, argv); + osd_output::pop(&winerror); } // free symbols symbols = NULL; @@ -464,22 +491,6 @@ static BOOL WINAPI control_handler(DWORD type) } -//============================================================ -// winui_output_error -//============================================================ - -static void winui_output_error(delegate_late_bind *param, const char *format, va_list argptr) -{ - char buffer[1024]; - - // if we are in fullscreen mode, go to windowed mode - if ((video_config.windowed == 0) && (win_window_list != NULL)) - winwindow_toggle_full_screen(); - - vsnprintf(buffer, ARRAY_LENGTH(buffer), format, argptr); - win_message_box_utf8(win_window_list ? win_window_list->m_hwnd : NULL, buffer, emulator_info::get_appname(), MB_OK); -} - //============================================================ -- cgit v1.2.3