diff -r 397d77b6e346 configure.in --- a/configure.in Tue Jul 21 20:53:05 2009 +1000 +++ b/configure.in Tue Jul 28 22:45:41 2009 -0400 @@ -256,7 +256,9 @@ ]) - +dnl OSD support - needs Freetype 2 and fontconfig +PKG_CHECK_MODULES(FREETYPE, [freetype2]) +PKG_CHECK_MODULES(FONTCONFIG, [fontconfig]) AM_CONDITIONAL(VIDEO_OSMESA, [test "x$HAVE_OSMESA" = "xyes"]) AM_CONDITIONAL(VIDEO_GLX, [test "x$HAVE_GLX" = "xyes"]) @@ -297,7 +299,7 @@ AC_DEFINE([HAVE_SDL],1,[Have SDL support]) ], [ if test "x$with_sdl" = "xyes"; then - AC_MSG_FAILURE( ["SDL libraries could not be found (but were required)] ) + AC_MSG_FAILURE( [SDL libraries could not be found (but were required)] ) fi ]) fi diff -r 397d77b6e346 src/Makefile.am --- a/src/Makefile.am Tue Jul 21 20:53:05 2009 +1000 +++ b/src/Makefile.am Tue Jul 28 22:45:41 2009 -0400 @@ -6,7 +6,7 @@ -DPACKAGE_PLUGIN_DIR=\""$(pkglibdir)"\" \ -DPACKAGE_CONF_DIR=\""$(sysconfdir)"\" \ -Ish4 \ - @GLIB_CFLAGS@ @GTK_CFLAGS@ @LIBPNG_CFLAGS@ @PULSE_CFLAGS@ @ESOUND_CFLAGS@ @ALSA_CFLAGS@ @SDL_CFLAGS@ + @GLIB_CFLAGS@ @GTK_CFLAGS@ @LIBPNG_CFLAGS@ @PULSE_CFLAGS@ @ESOUND_CFLAGS@ @ALSA_CFLAGS@ @SDL_CFLAGS@ @FREETYPE_CFLAGS@ @FONTCONFIG_CFLAGS@ SOEXT=@SOEXT@ PLUGINCFLAGS = @PLUGINCFLAGS@ @@ -38,7 +38,7 @@ gendec_SOURCES = tools/gendec.c tools/gendec.h tools/insparse.c tools/actparse.c genglsl_SOURCES = tools/genglsl.c lxdream_LINK = $(LINK) @LXDREAMLDFLAGS@ -lxdream_LDADD = @LXDREAM_LIBS@ @GLIB_LIBS@ @GTK_LIBS@ @LIBPNG_LIBS@ $(INTLLIBS) +lxdream_LDADD = @LXDREAM_LIBS@ @GLIB_LIBS@ @GTK_LIBS@ @LIBPNG_LIBS@ @FREETYPE_LIBS@ @FONTCONFIG_LIBS@ $(INTLLIBS) lxdream_SOURCES = \ main.c version.c config.c config.h lxdream.h dream.h gui.h cpu.h hook.h \ gettext.h mem.c mem.h sdram.c mmio.h watch.c \ @@ -69,6 +69,7 @@ display.c display.h dckeysyms.h \ drivers/audio_null.c drivers/video_null.c drivers/cd_mmc.c \ drivers/video_gl.c drivers/video_gl.h drivers/gl_fbo.c \ + drivers/osd.h drivers/osd_freetype.c \ sh4/sh4.def sh4/sh4core.in sh4/sh4x86.in sh4/sh4dasm.in sh4/sh4stat.in \ hotkeys.c hotkeys.h lxdream_CPPFLAGS = @LXDREAMCPPFLAGS@ @@ -100,7 +101,7 @@ lxdream_SOURCES += gtkui/gtkui.c gtkui/gtkui.h \ gtkui/gtk_win.c gtkui/gtkcb.c gtkui/gtk_cfg.c \ gtkui/gtk_mmio.c gtkui/gtk_debug.c gtkui/gtk_dump.c \ - gtkui/gtk_ctrl.c gtkui/gtk_gd.c \ + gtkui/gtk_ctrl.c gtkui/gtk_gd.c gtkui/gtk_video.c\ drivers/net_glib.c drivers/video_gtk.c endif diff -r 397d77b6e346 src/drivers/osd.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/drivers/osd.h Tue Jul 28 22:45:41 2009 -0400 @@ -0,0 +1,45 @@ +/** + * $Id: $ + * + * Adds OSD support to the video driver + * + * Copyright (c) 2009 wahrhaft. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef lxdream_osd_H +#define lxdream_osd_H 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define OSD_POS_LEFT 0 +#define OSD_POS_CENTER 1 +#define OSD_POS_RIGHT 2 +#define OSD_POS_TOP 0 +#define OSD_POS_MIDDLE 1 +#define OSD_POS_BOTTOM 2 + + +gboolean osd_init(); +void osd_clean_up(); +void osd_render(); +void osd_show_text(gchar *text, int hpos, int vpos, int duration); + +#ifdef __cplusplus +} +#endif + +#endif //lxdream_osd_H diff -r 397d77b6e346 src/drivers/osd_freetype.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/drivers/osd_freetype.c Tue Jul 28 22:45:41 2009 -0400 @@ -0,0 +1,306 @@ +/** + * $Id: $ + * + * Adds OSD support to the video driver + * + * Copyright (c) 2009 wahrhaft. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include FT_FREETYPE_H +#include +#include "lxdream.h" +#include "display.h" +#include "osd.h" + +#define OSD_FONT_SIZE 14 +#define MAX_CHAR 128 + +typedef struct { + gchar *text; + struct timeval end_time; +} osd_entry; + + +static void measure_text(gchar *text, int *width, int *height); +static int next_p2(int val); + +osd_entry osd_entries[3][3]; + +FT_Library ft_library; +FT_Face ft_font_face; +int font_char_advances[MAX_CHAR]; +int font_char_height; +GLuint *font_textures; +GLuint font_dlist_base; + +gboolean is_init = FALSE; + +extern uint32_t video_width, video_height; + +gboolean osd_init() +{ + if (is_init) + return TRUE; + + font_char_height = 0; + + //find a bold, monospaced font that comes in size 18 + FcPattern *pattern = FcPatternBuild(NULL, + FC_SCALABLE, FcTypeBool, FcTrue, + FC_WEIGHT, FcTypeInteger, FC_WEIGHT_BOLD, + FC_SLANT, FcTypeInteger, FC_SLANT_ROMAN, + FC_SPACING, FcTypeInteger, FC_MONO, + FC_SIZE, FcTypeDouble, (double)OSD_FONT_SIZE, + NULL); + FcConfigSubstitute(NULL, pattern, FcMatchPattern); + + FcResult result; + FcPattern *matched = FcFontMatch (0, pattern, &result); + + FcChar8 *filename; + + if (FcPatternGetString (matched, FC_FILE, 0, &filename) != FcResultMatch) { + ERROR("Error with font pattern match"); + } else { + //We found a font, let's turn it into something we can use + DEBUG("Using OSD font: %s", filename); + + if (FT_Init_FreeType(&ft_library) || FT_New_Face(ft_library, filename, 0, &ft_font_face)) { + ERROR("Could not initialize Freetype"); + if (ft_font_face != NULL) + FT_Done_Face(ft_font_face); + if (ft_library != NULL) + FT_Done_FreeType(ft_library); + } else { + FT_Set_Pixel_Sizes(ft_font_face, 0, OSD_FONT_SIZE); + + font_textures = malloc(MAX_CHAR * sizeof(GLuint)); + font_dlist_base = glGenLists(MAX_CHAR); + glGenTextures(MAX_CHAR, font_textures); + + //create dlist for each character + for (guchar ch = 0; ch < MAX_CHAR; ++ch) { + //generate freetype bitmap + if (FT_Load_Char(ft_font_face, ch, FT_LOAD_RENDER)) + continue; + + font_char_advances[ch] = ft_font_face->glyph->advance.x; + if (ft_font_face->glyph->advance.y > font_char_height) + font_char_height = ft_font_face->glyph->advance.y; + FT_Bitmap bitmap = ft_font_face->glyph->bitmap; + int tex_width = next_p2(bitmap.width); + int tex_height = next_p2(bitmap.rows); + + + //copy from bitmap to texture data, using a 2 channel texture of luminosity and alpha + GLubyte *tex_data = malloc(2 * tex_width * tex_height); + for (int j = 0; j < tex_height; j++) { + for (int i = 0; i < tex_width; i++) { + tex_data[2 * (i + j * tex_width)] = 255; + tex_data[2 * (i + j * tex_width) + 1] = + (i >= bitmap.width || j >= bitmap.rows) ? + 0 : bitmap.buffer[i + bitmap.width * j]; + } + } + + //create texture + glBindTexture(GL_TEXTURE_2D, font_textures[ch]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_width, tex_height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, tex_data); + free(tex_data); + + //create dlist + glNewList(font_dlist_base + ch, GL_COMPILE); + glBindTexture(GL_TEXTURE_2D, font_textures[ch]); + glPushMatrix(); + glTranslatef(ft_font_face->glyph->bitmap_left, 0, 0); + glTranslatef(0, ft_font_face->glyph->bitmap_top - bitmap.rows, 0); + + float x = (float)bitmap.width / tex_width; + float y = (float)bitmap.rows / tex_height; + + //draw quad with texture + glBegin(GL_QUADS); + glTexCoord2d(0, 0); glVertex2f(0, bitmap.rows); + glTexCoord2d(0, y); glVertex2f(0, 0); + glTexCoord2d(x, y); glVertex2f(bitmap.width, 0); + glTexCoord2d(x, 0); glVertex2f(bitmap.width, bitmap.rows); + glEnd(); + glPopMatrix(); + glTranslatef(font_char_advances[ch] / 64, 0, 0); + + glEndList(); + } //loop back to do next character + is_init = TRUE; + } + } + + if (font_char_height == 0) + font_char_height = OSD_FONT_SIZE; + + //clean up FontConfig + FcPatternDestroy(matched); + FcPatternDestroy(pattern); + + for (int i=0; i < 3; ++i) + for (int j=0; j < 3; ++j) + osd_entries[i][j].text = NULL; + + +/* Uncomment to test the OSD + int delay = 14; + osd_show_text("Left Top", OSD_POS_LEFT, OSD_POS_TOP, delay++); + osd_show_text("Center Top", OSD_POS_CENTER, OSD_POS_TOP, delay++); + osd_show_text("Right Top", OSD_POS_RIGHT, OSD_POS_TOP, delay++); + osd_show_text("Left Middle", OSD_POS_LEFT, OSD_POS_MIDDLE, delay++); + osd_show_text("Center Middle", OSD_POS_CENTER, OSD_POS_MIDDLE, delay++); + osd_show_text("Right Middle", OSD_POS_RIGHT, OSD_POS_MIDDLE, delay++); + osd_show_text("Left Bottom", OSD_POS_LEFT, OSD_POS_BOTTOM, delay++); + osd_show_text("Center Bottom", OSD_POS_CENTER, OSD_POS_BOTTOM, delay++); + osd_show_text("Right Bottom", OSD_POS_RIGHT, OSD_POS_BOTTOM, delay++); +*/ + return is_init; +} + +void osd_clean_up() +{ + if (is_init) + { + glDeleteLists(font_dlist_base, MAX_CHAR); + glDeleteTextures(MAX_CHAR, font_textures); + free(font_textures); + + FT_Done_Face(ft_font_face); + FT_Done_FreeType(ft_library); + } +} + +void osd_render() +{ + if (is_init) + { + for (int i = 0 ; i < 3; i++) + { + for (int j = 0; j < 3; j++) + { + if (osd_entries[i][j].text != NULL) + { + //see if we are done displaying the text, + //or if we are close, start fading out + float alpha = 1; + struct timeval current_time, diff_time; + gettimeofday(¤t_time, NULL); + timersub(&osd_entries[i][j].end_time, ¤t_time, &diff_time); + if (diff_time.tv_sec < 0) + { + g_free(osd_entries[i][j].text); + osd_entries[i][j].text = NULL; + break; + } + if (diff_time.tv_sec == 0) + alpha = (float)diff_time.tv_usec / 1000000; + + gchar *text = osd_entries[i][j].text; + DEBUG("Printing text: %s", text); + //determine the screen location to draw the text + int x = 0, y = 0; + + //float bbox[6]; + //ftglGetFontBBox(font1, osd_entries[i][j].text, -1, bbox); + int text_width = 0;//bbox[3] - bbox[0]; + int text_height = 0;//bbox[4] - bbox[1]; + measure_text(text, &text_width, &text_height); + + if (i == OSD_POS_CENTER) + x = video_width / 2 - text_width / 2; + else if (i == OSD_POS_RIGHT) + x = video_width - text_width;// - MARGIN; + + if (j == OSD_POS_TOP) + y = text_height; + if (j == OSD_POS_MIDDLE) + y = video_height / 2 - text_height / 2; + else if (j == OSD_POS_BOTTOM) + y = video_height - text_height; + + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glListBase(font_dlist_base); + + glScalef(1, -1, 1); + glTranslatef(x, -y, 0); + glColor4f(0, 0, 0, alpha); + glCallLists(strlen(text), GL_UNSIGNED_BYTE, text); + glLoadIdentity(); + + glScalef(1, -1, 1); + glTranslatef(x - 2, -y + 2, 0); + glColor4f(1, 1, 1, alpha); + glCallLists(strlen(text), GL_UNSIGNED_BYTE, text); + + + glLoadIdentity(); + } + } + } + } +} + +void osd_show_text(gchar *text, int hpos, int vpos, int duration) +{ + if (text == NULL) + { + if (osd_entries[hpos][vpos].text != NULL) + { + g_free(osd_entries[hpos][vpos].text); + osd_entries[hpos][vpos].text = NULL; + } + } + else + { + osd_entries[hpos][vpos].text = g_strdup(text); + gettimeofday(&osd_entries[hpos][vpos].end_time, NULL); + osd_entries[hpos][vpos].end_time.tv_sec += duration; + } +} + +void measure_text(gchar *text, int *width, int *height) +{ + *width = 0; + for (guchar *ch = text; *ch != '\0'; ++ch) { + if (*ch < MAX_CHAR) + *width += font_char_advances[*ch]; + } + *width /= 64; + + //multiline support not needed at the moment + *height = font_char_height; +} + +//rounds up to the next highest power of 2 +int next_p2(int val) +{ + int ret = 2; + while (ret < val) + ret *= 2; + return ret; +} diff -r 397d77b6e346 src/drivers/video_gl.c --- a/src/drivers/video_gl.c Tue Jul 21 20:53:05 2009 +1000 +++ b/src/drivers/video_gl.c Tue Jul 28 22:45:41 2009 -0400 @@ -21,6 +21,7 @@ #include "display.h" #include "pvr2/pvr2.h" #include "drivers/video_gl.h" +#include "drivers/osd.h" extern uint32_t video_width, video_height; @@ -147,6 +148,7 @@ glVertex2f( x1, y2 ); glEnd(); glDisable( GL_TEXTURE_RECTANGLE_ARB ); + osd_render(); glFlush(); } @@ -169,6 +171,7 @@ gl_reset_state(); glColor3ub( (colour >> 16) & 0xFF, (colour >> 8) & 0xFF, colour & 0xFF ); glRecti(0,0, video_width, video_height ); + osd_render(); glFlush(); } diff -r 397d77b6e346 src/gdrom/ide.c --- a/src/gdrom/ide.c Tue Jul 21 20:53:05 2009 +1000 +++ b/src/gdrom/ide.c Tue Jul 28 22:45:41 2009 -0400 @@ -482,7 +482,7 @@ uint32_t lba, status; /* Okay we have the packet in the command buffer */ - INFO( "ATAPI packet: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", + DEBUG( "ATAPI packet: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X", cmd[0], cmd[1], cmd[2], cmd[3], cmd[4], cmd[5], cmd[6], cmd[7], cmd[8], cmd[9], cmd[10], cmd[11] ); diff -r 397d77b6e346 src/gtkui/gtk_video.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/gtkui/gtk_video.c Tue Jul 28 22:45:41 2009 -0400 @@ -0,0 +1,76 @@ +/** + * $Id$ + * + * Define the main (emu) GTK window, along with its menubars, + * toolbars, etc. + * + * Copyright (c) 2005 Nathan Keynes. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include + +#include "lxdream.h" +#include "display.h" +#include "gtkui/gtkui.h" + + +static void video_dialog_done( GtkWidget *panel, gboolean isOK ) +{ + if( isOK ) { + //lxdream_save_config(); + } else { + } + +} + +static GtkWidget *video_panel_new() +{ + GtkWidget *osd_frame = gtk_frame_new("OSD Settings"); + GtkWidget *table = gtk_table_new( 5, 2, TRUE); + gtk_container_add(GTK_CONTAINER(osd_frame), table); + int i,j,k; + const struct maple_device_class **devices = maple_get_device_classes(); + + gtk_table_set_row_spacings(GTK_TABLE(table), 3); + gtk_table_set_col_spacings(GTK_TABLE(table), 5); + + gtk_table_attach_defaults(GTK_TABLE(table), gtk_label_new("Show OSD"), 0, 1, 0, 1); + + GtkWidget *combo = gtk_combo_box_new_text(); + gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Always"); + gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Fullscreen Only"); + gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Never"); + gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 1); + gtk_table_attach_defaults(GTK_TABLE(table), combo, 1, 2, 0, 1); + + gtk_table_attach_defaults(GTK_TABLE(table), gtk_label_new("Font size"), 0, 1, 1, 2); + combo = gtk_combo_box_new_text(); + gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Small"); + gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Large"); + gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); + gtk_table_attach_defaults(GTK_TABLE(table), combo, 1, 2, 1, 2); + + gtk_table_attach_defaults(GTK_TABLE(table), gtk_check_button_new_with_label("Show emulation speed"), 0, 2, 2, 3); + gtk_table_attach_defaults(GTK_TABLE(table), gtk_check_button_new_with_label("Show info messages"), 0, 2, 3, 4); + gtk_table_attach_defaults(GTK_TABLE(table), gtk_check_button_new_with_label("Show warning messages"), 0, 2, 4, 5); + + return osd_frame; +} + +void video_dialog_run( ) +{ + gtk_gui_run_property_dialog( _("Video Settings"), video_panel_new(), video_dialog_done ); +} diff -r 397d77b6e346 src/gtkui/gtk_win.c --- a/src/gtkui/gtk_win.c Tue Jul 21 20:53:05 2009 +1000 +++ b/src/gtkui/gtk_win.c Tue Jul 28 22:45:41 2009 -0400 @@ -37,7 +37,7 @@ #include "gdrom/gdrom.h" #include "gtkui/gtkui.h" #include "drivers/video_gl.h" - +#include "drivers/osd.h" struct main_window_info { GtkWidget *window; @@ -381,6 +381,7 @@ snprintf( buf, 32, "Running (%2.4f%%)", speed ); main_window_set_status_text( win, buf ); + osd_show_text(buf, OSD_POS_LEFT, OSD_POS_BOTTOM, 5); } GtkWidget *main_window_get_renderarea( main_window_t win ) @@ -429,5 +430,6 @@ char buf[256]; snprintf( buf, sizeof(buf), "%s - %s", lxdream_package_name, disc ); gtk_window_set_title( GTK_WINDOW(win->window), buf ); + osd_show_text(disc, OSD_POS_CENTER, OSD_POS_TOP, 5); } } diff -r 397d77b6e346 src/gtkui/gtkcb.c --- a/src/gtkui/gtkcb.c Tue Jul 21 20:53:05 2009 +1000 +++ b/src/gtkui/gtkcb.c Tue Jul 28 22:45:41 2009 -0400 @@ -275,6 +275,7 @@ void video_settings_callback( GtkAction *action, gpointer user_data) { + video_dialog_run(); } void hotkey_settings_callback( GtkAction *action, gpointer user_data) diff -r 397d77b6e346 src/gtkui/gtkui.c --- a/src/gtkui/gtkui.c Tue Jul 21 20:53:05 2009 +1000 +++ b/src/gtkui/gtkui.c Tue Jul 28 22:45:41 2009 -0400 @@ -263,7 +263,6 @@ dreamcast_get_quick_state(), G_CALLBACK(quick_state_action_callback), NULL ); gtk_gui_enable_action("AudioSettings", FALSE); gtk_gui_enable_action("NetworkSettings", FALSE); - gtk_gui_enable_action("VideoSettings", FALSE); global_ui_manager = gtk_ui_manager_new(); gtk_ui_manager_set_add_tearoffs(global_ui_manager, TRUE); diff -r 397d77b6e346 src/gtkui/gtkui.h --- a/src/gtkui/gtkui.h Tue Jul 21 20:53:05 2009 +1000 +++ b/src/gtkui/gtkui.h Tue Jul 28 22:45:41 2009 -0400 @@ -74,6 +74,7 @@ void maple_dialog_run(); void path_dialog_run(); void hotkeys_dialog_run(); +void video_dialog_run(); void gtk_gui_update( void ); main_window_t gtk_gui_get_main(); diff -r 397d77b6e346 src/main.c --- a/src/main.c Tue Jul 21 20:53:05 2009 +1000 +++ b/src/main.c Tue Jul 28 22:45:41 2009 -0400 @@ -39,6 +39,7 @@ #include "vmu/vmulist.h" #include "hotkeys.h" #include "plugin.h" +#include "drivers/osd.h" char *option_list = "a:A:c:dfg:G:hHl:m:npt:T:uvV:x?"; struct option longopts[] = { @@ -236,7 +237,6 @@ display_set_driver( &display_null_driver ); } else { gui_init(show_debugger, show_fullscreen); - display_driver_t display_driver = get_display_driver_by_name(display_driver_name); if( display_driver == NULL ) { ERROR( "Video driver '%s' not found, aborting.", display_driver_name ); @@ -246,6 +246,7 @@ display_driver->name ); exit(2); } + osd_init(); } hotkeys_init(); diff -r 397d77b6e346 src/util.c --- a/src/util.c Tue Jul 21 20:53:05 2009 +1000 +++ b/src/util.c Tue Jul 28 22:45:41 2009 -0400 @@ -33,6 +33,7 @@ #include "dreamcast.h" #include "gui.h" #include "sh4/sh4.h" +#include "drivers/osd.h" char *msg_levels[] = { "FATAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE" }; int global_msg_level = EMIT_WARN; @@ -336,8 +337,13 @@ return; } } - - + + //TODO: should this be hidden by global_msg_level? + if (level == EMIT_WARN || level == EMIT_INFO) + { + osd_show_text(text, OSD_POS_RIGHT, OSD_POS_BOTTOM, 5); + } + strftime( buf, sizeof(buf), "%H:%M:%S", localtime(&tm) ); fprintf( stderr, "%s %08X %-5s %s\n", buf, sh4r.pc, msg_levels[level], text ); g_free(text);