diff --git a/docs/config.txt b/docs/config.txt index 658cc82e5e5..fc3acc532cc 100644 --- a/docs/config.txt +++ b/docs/config.txt @@ -1004,3 +1004,11 @@ Core misc options Forces MAME to skip displaying the game info screen. The default is OFF (-noskip_gameinfo). + +-uifont + + Specifies the name of a BDF font file to use for the UI font. If this + font cannot be found or cannot be loaded, the system will fall back + to its built-in UI font. On some platforms 'fontname' can be a system + font name instead of a BDF font file. The default is 'default' (use + the OSD-determined default font). diff --git a/src/emu/emuopts.c b/src/emu/emuopts.c index ce880e3d133..77b188db99f 100644 --- a/src/emu/emuopts.c +++ b/src/emu/emuopts.c @@ -164,6 +164,7 @@ const options_entry mame_core_options[] = { "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" }, + { "uifont", "default", 0, "specify a font to use" }, /* image device options */ { OPTION_ADDED_DEVICE_OPTIONS, "0", OPTION_BOOLEAN | OPTION_INTERNAL, "image device-specific options have been added" }, diff --git a/src/emu/emuopts.h b/src/emu/emuopts.h index d4355a2009c..73011bbdc87 100644 --- a/src/emu/emuopts.h +++ b/src/emu/emuopts.h @@ -154,6 +154,7 @@ #define OPTION_BIOS "bios" #define OPTION_CHEAT "cheat" #define OPTION_SKIP_GAMEINFO "skip_gameinfo" +#define OPTION_UI_FONT "uifont" /* image device options */ #define OPTION_ADDED_DEVICE_OPTIONS "added_device_options" diff --git a/src/emu/rendfont.c b/src/emu/rendfont.c index 836526ef36e..4f027170c10 100644 --- a/src/emu/rendfont.c +++ b/src/emu/rendfont.c @@ -79,16 +79,18 @@ inline const char *next_line(const char *ptr) inline render_font::glyph &render_font::get_char(unicode_char chnum) { static glyph dummy_glyph; - + // grab the table; if none, return the dummy character glyph *glyphtable = m_glyphs[chnum / 256]; + if (glyphtable == NULL && m_format == FF_OSD) + glyphtable = m_glyphs[chnum / 256] = auto_alloc_array_clear(&m_manager.machine(), glyph, 256); if (glyphtable == NULL) return dummy_glyph; // if the character isn't generated yet, do it now glyph &gl = glyphtable[chnum % 256]; if (gl.bitmap == NULL) - char_expand(gl); + char_expand(chnum, gl); // return the resulting character return gl; @@ -111,9 +113,26 @@ render_font::render_font(render_manager &manager, const char *filename) m_yoffs(0), m_scale(1.0f), m_rawdata(NULL), - m_rawsize(0) + m_rawsize(0), + m_osdfont(NULL) { memset(m_glyphs, 0, sizeof(m_glyphs)); + + // if this is an OSD font, we're done + if (filename != NULL) + { + m_osdfont = manager.machine().osd().font_open(filename, m_height); + if (m_osdfont != NULL) + { + m_scale = 1.0f / (float)m_height; + m_format = FF_OSD; + return; + } + } + + // if the filename is 'default' default to 'ui.bdf' for backwards compatibility + if (mame_stricmp(filename, "default") == 0) + filename = "ui.bdf"; // attempt to load the cached version of the font first if (filename != NULL && load_cached_bdf(filename)) @@ -154,6 +173,10 @@ render_font::~render_font() // free the raw data and the size itself auto_free(&m_manager.machine(), m_rawdata); + + // release the OSD font + if (m_osdfont != NULL) + m_manager.machine().osd().font_close(m_osdfont); } @@ -162,68 +185,89 @@ render_font::~render_font() // character into a bitmap //------------------------------------------------- -void render_font::char_expand(glyph &gl) +void render_font::char_expand(unicode_char chnum, glyph &gl) { - // punt if nothing there - if (gl.bmwidth == 0 || gl.bmheight == 0 || gl.rawdata == NULL) - return; - - // allocate a new bitmap of the size we need - gl.bitmap = auto_alloc(&m_manager.machine(), bitmap_t(gl.bmwidth, m_height, BITMAP_FORMAT_ARGB32)); - bitmap_fill(gl.bitmap, NULL, 0); - - // extract the data - const char *ptr = gl.rawdata; - UINT8 accum = 0, accumbit = 7; - for (int y = 0; y < gl.bmheight; y++) + // if we're an OSD font, query the info + if (m_format == FF_OSD) { - int desty = y + m_height + m_yoffs - gl.yoffs - gl.bmheight; - UINT32 *dest = (desty >= 0 && desty < m_height) ? BITMAP_ADDR32(gl.bitmap, desty, 0) : NULL; + // we set bmwidth to -1 if we've previously queried and failed + if (gl.bmwidth == -1) + return; + + // attempt to get the font bitmap; if we fail, set bmwidth to -1 + gl.bitmap = m_manager.machine().osd().font_get_bitmap(m_osdfont, chnum, gl.width, gl.xoffs, gl.yoffs); + if (gl.bitmap == NULL) + return; - // text format - if (m_format == FF_TEXT) + // populate the bmwidth/bmheight fields + gl.bmwidth = gl.bitmap->width; + gl.bmheight = gl.bitmap->height; + } + + // other formats need to parse their data + else + { + // punt if nothing there + if (gl.bmwidth == 0 || gl.bmheight == 0 || gl.rawdata == NULL) + return; + + // allocate a new bitmap of the size we need + gl.bitmap = auto_alloc(&m_manager.machine(), bitmap_t(gl.bmwidth, m_height, BITMAP_FORMAT_ARGB32)); + bitmap_fill(gl.bitmap, NULL, 0); + + // extract the data + const char *ptr = gl.rawdata; + UINT8 accum = 0, accumbit = 7; + for (int y = 0; y < gl.bmheight; y++) { - // loop over bytes - for (int x = 0; x < gl.bmwidth; x += 4) + int desty = y + m_height + m_yoffs - gl.yoffs - gl.bmheight; + UINT32 *dest = (desty >= 0 && desty < m_height) ? BITMAP_ADDR32(gl.bitmap, desty, 0) : NULL; + + // text format + if (m_format == FF_TEXT) { - // scan for the next hex digit - int bits = -1; - while (*ptr != 13 && bits == -1) + // loop over bytes + for (int x = 0; x < gl.bmwidth; x += 4) { - if (*ptr >= '0' && *ptr <= '9') - bits = *ptr++ - '0'; - else if (*ptr >= 'A' && *ptr <= 'F') - bits = *ptr++ - 'A' + 10; - else if (*ptr >= 'a' && *ptr <= 'f') - bits = *ptr++ - 'a' + 10; - else - ptr++; + // scan for the next hex digit + int bits = -1; + while (*ptr != 13 && bits == -1) + { + if (*ptr >= '0' && *ptr <= '9') + bits = *ptr++ - '0'; + else if (*ptr >= 'A' && *ptr <= 'F') + bits = *ptr++ - 'A' + 10; + else if (*ptr >= 'a' && *ptr <= 'f') + bits = *ptr++ - 'a' + 10; + else + ptr++; + } + + // expand the four bits + if (dest != NULL) + { + *dest++ = (bits & 8) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff); + *dest++ = (bits & 4) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff); + *dest++ = (bits & 2) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff); + *dest++ = (bits & 1) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff); + } } - // expand the four bits - if (dest != NULL) - { - *dest++ = (bits & 8) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff); - *dest++ = (bits & 4) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff); - *dest++ = (bits & 2) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff); - *dest++ = (bits & 1) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff); - } + // advance to the next line + ptr = next_line(ptr); } - // advance to the next line - ptr = next_line(ptr); - } - - // cached format - else if (m_format == FF_CACHED) - { - for (int x = 0; x < gl.bmwidth; x++) + // cached format + else if (m_format == FF_CACHED) { - if (accumbit == 7) - accum = *ptr++; - if (dest != NULL) - *dest++ = (accum & (1 << accumbit)) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff); - accumbit = (accumbit - 1) & 7; + for (int x = 0; x < gl.bmwidth; x++) + { + if (accumbit == 7) + accum = *ptr++; + if (dest != NULL) + *dest++ = (accum & (1 << accumbit)) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff); + accumbit = (accumbit - 1) & 7; + } } } } diff --git a/src/emu/rendfont.h b/src/emu/rendfont.h index 1eba3bc1a71..293ac3f4af2 100644 --- a/src/emu/rendfont.h +++ b/src/emu/rendfont.h @@ -79,12 +79,12 @@ private: class glyph { public: - INT32 width; /* width from this character to the next */ - INT32 xoffs, yoffs; /* X and Y offset from baseline to top,left of bitmap */ - INT32 bmwidth, bmheight; /* width and height of bitmap */ - const char * rawdata; /* pointer to the raw data for this one */ - bitmap_t * bitmap; /* pointer to the bitmap containing the raw data */ - render_texture * texture; /* pointer to a texture for rendering and sizing */ + INT32 width; // width from this character to the next + INT32 xoffs, yoffs; // X and Y offset from baseline to top,left of bitmap + INT32 bmwidth, bmheight; // width and height of bitmap + const char * rawdata; // pointer to the raw data for this one + bitmap_t * bitmap; // pointer to the bitmap containing the raw data + render_texture * texture; // pointer to a texture for rendering and sizing }; // internal format @@ -92,12 +92,13 @@ private: { FF_UNKNOWN, FF_TEXT, - FF_CACHED + FF_CACHED, + FF_OSD }; // helpers glyph &get_char(unicode_char chnum); - void char_expand(glyph &ch); + void char_expand(unicode_char chnum, glyph &ch); bool load_cached_bdf(const char *filename); bool load_bdf(); bool load_cached(mame_file *file, UINT32 hash); @@ -105,13 +106,14 @@ private: // internal state render_manager & m_manager; - format m_format; /* format of font data */ - int m_height; /* height of the font, from ascent to descent */ - int m_yoffs; /* y offset from baseline to descent */ - float m_scale; /* 1 / height precomputed */ - glyph * m_glyphs[256]; /* array of glyph subtables */ - const char * m_rawdata; /* pointer to the raw data for the font */ - UINT64 m_rawsize; /* size of the raw font data */ + format m_format; // format of font data + int m_height; // height of the font, from ascent to descent + int m_yoffs; // y offset from baseline to descent + float m_scale; // 1 / height precomputed + glyph * m_glyphs[256]; // array of glyph subtables + const char * m_rawdata; // pointer to the raw data for the font + UINT64 m_rawsize; // size of the raw font data + osd_font m_osdfont; // handle to the OSD font // constants static const int CACHED_CHAR_SIZE = 12; diff --git a/src/emu/ui.c b/src/emu/ui.c index 61031514f1a..9324df20d81 100644 --- a/src/emu/ui.c +++ b/src/emu/ui.c @@ -240,7 +240,7 @@ int ui_init(running_machine *machine) machine->add_notifier(MACHINE_NOTIFY_EXIT, ui_exit); /* allocate the font and messagebox string */ - ui_font = machine->render().font_alloc("ui.bdf"); + ui_font = machine->render().font_alloc(options_get_string(machine->options(), OPTION_UI_FONT)); /* initialize the other UI bits */ ui_menu_init(machine); diff --git a/src/osd/osdepend.c b/src/osd/osdepend.c index 7ea9dd57d2e..8b3cf6d359a 100644 --- a/src/osd/osdepend.c +++ b/src/osd/osdepend.c @@ -196,3 +196,38 @@ void osd_interface::customize_input_type_list(input_type_desc *typelist) // Scan the list, and change the keys/joysticks you want. // } + + +//------------------------------------------------- +// font_open - attempt to "open" a handle to the +// font with the given name +//------------------------------------------------- + +osd_font osd_interface::font_open(const char *name, int &height) +{ + return NULL; +} + + +//------------------------------------------------- +// font_close - release resources associated with +// a given OSD font +//------------------------------------------------- + +void osd_interface::font_close(osd_font font) +{ +} + + +//------------------------------------------------- +// font_get_bitmap - allocate and populate a +// BITMAP_FORMAT_ARGB32 bitmap containing the +// pixel values MAKE_ARGB(0xff,0xff,0xff,0xff) +// or MAKE_ARGB(0x00,0xff,0xff,0xff) for each +// pixel of a black & white font +//------------------------------------------------- + +bitmap_t *osd_interface::font_get_bitmap(osd_font font, unicode_char chnum, INT32 &width, INT32 &xoffs, INT32 &yoffs) +{ + return NULL; +} diff --git a/src/osd/osdepend.h b/src/osd/osdepend.h index a344482d4f1..b227844b571 100644 --- a/src/osd/osdepend.h +++ b/src/osd/osdepend.h @@ -44,6 +44,7 @@ #include "emucore.h" #include "osdcore.h" +#include "unicode.h" //************************************************************************** @@ -53,6 +54,7 @@ // forward references class input_type_desc; class device_t; +typedef void *osd_font; // ======================> osd_interface @@ -82,6 +84,11 @@ public: // input overridables virtual void customize_input_type_list(input_type_desc *typelist); + + // font overridables + virtual osd_font font_open(const char *name, int &height); + virtual void font_close(osd_font font); + virtual bitmap_t *font_get_bitmap(osd_font font, unicode_char chnum, INT32 &width, INT32 &xoffs, INT32 &yoffs); private: // internal state diff --git a/src/osd/windows/winmain.c b/src/osd/windows/winmain.c index f3c4d9fc405..440243b8895 100644 --- a/src/osd/windows/winmain.c +++ b/src/osd/windows/winmain.c @@ -659,6 +659,226 @@ void windows_osd_interface::osd_exit(running_machine &machine) } +//------------------------------------------------- +// font_open - attempt to "open" a handle to the +// font with the given name +//------------------------------------------------- + +osd_font windows_osd_interface::font_open(const char *_name, int &height) +{ + // accept qualifiers from the name + astring name(_name); + if (name == "default") name = "Tahoma"; + bool bold = (name.replace(0, "[B]", "") + name.replace(0, "[b]", "") > 0); + bool italic = (name.replace(0, "[I]", "") + name.replace(0, "[i]", "") > 0); + + // build a basic LOGFONT description of what we want + LOGFONT logfont; + logfont.lfHeight = DEFAULT_FONT_HEIGHT; + logfont.lfWidth = 0; + logfont.lfEscapement = 0; + logfont.lfOrientation = 0; + logfont.lfWeight = bold ? FW_BOLD : FW_MEDIUM; + logfont.lfItalic = italic; + logfont.lfUnderline = FALSE; + logfont.lfStrikeOut = FALSE; + logfont.lfCharSet = ANSI_CHARSET; + logfont.lfOutPrecision = OUT_DEFAULT_PRECIS; + logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS; + logfont.lfQuality = NONANTIALIASED_QUALITY; + logfont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; + + // copy in the face name + TCHAR *face = tstring_from_utf8(name); + _tcsncpy(logfont.lfFaceName, face, sizeof(logfont.lfFaceName) / sizeof(TCHAR)); + logfont.lfFaceName[sizeof(logfont.lfFaceName) / sizeof(TCHAR) - 1] = 0; + osd_free(face); + + // create the font + height = logfont.lfHeight; + osd_font font = reinterpret_cast(CreateFontIndirect(&logfont)); + if (font == NULL) + return NULL; + + // select it into a temp DC and get the real font name + HDC dummyDC = CreateCompatibleDC(NULL); + HGDIOBJ oldfont = SelectObject(dummyDC, reinterpret_cast(font)); + TCHAR realname[100]; + GetTextFace(dummyDC, ARRAY_LENGTH(realname), realname); + SelectObject(dummyDC, oldfont); + DeleteDC(dummyDC); + + // if it doesn't match our request, fail + char *utf = utf8_from_tstring(realname); + int result = mame_stricmp(utf, name); + osd_free(utf); + + // if we didn't match, nuke our font and fall back + if (result != 0) + { + DeleteObject(reinterpret_cast(font)); + font = NULL; + } + return font; +} + + +//------------------------------------------------- +// font_close - release resources associated with +// a given OSD font +//------------------------------------------------- + +void windows_osd_interface::font_close(osd_font font) +{ + // delete the font ojbect + if (font != NULL) + DeleteObject(reinterpret_cast(font)); +} + + +//------------------------------------------------- +// font_get_bitmap - allocate and populate a +// BITMAP_FORMAT_ARGB32 bitmap containing the +// pixel values MAKE_ARGB(0xff,0xff,0xff,0xff) +// or MAKE_ARGB(0x00,0xff,0xff,0xff) for each +// pixel of a black & white font +//------------------------------------------------- + +bitmap_t *windows_osd_interface::font_get_bitmap(osd_font font, unicode_char chnum, INT32 &width, INT32 &xoffs, INT32 &yoffs) +{ + // create a dummy DC to work with + HDC dummyDC = CreateCompatibleDC(NULL); + HGDIOBJ oldfont = SelectObject(dummyDC, reinterpret_cast(font)); + + // get the text metrics + TEXTMETRIC metrics = { 0 }; + GetTextMetrics(dummyDC, &metrics); + + // get the width of this character + ABC abc; + if (!GetCharABCWidths(dummyDC, chnum, chnum, &abc)) + { + abc.abcA = 0; + abc.abcC = 0; + GetCharWidth32(dummyDC, chnum, chnum, reinterpret_cast(&abc.abcB)); + } + width = abc.abcA + abc.abcB + abc.abcC; + + // determine desired bitmap size + int bmwidth = (50 + abc.abcA + abc.abcB + abc.abcC + 50 + 31) & ~31; + int bmheight = 50 + metrics.tmHeight + 50; + + // describe the bitmap we want + BYTE bitmapinfodata[sizeof(BITMAPINFOHEADER) + 2 * sizeof(RGBQUAD)] = { 0 }; + BITMAPINFO &info = *reinterpret_cast(bitmapinfodata); + info.bmiHeader.biSize = sizeof(info.bmiHeader); + info.bmiHeader.biWidth = bmwidth; + info.bmiHeader.biHeight = -bmheight; + info.bmiHeader.biPlanes = 1; + info.bmiHeader.biBitCount = 1; + info.bmiHeader.biCompression = BI_RGB; + info.bmiHeader.biSizeImage = 0; + info.bmiHeader.biXPelsPerMeter = GetDeviceCaps(dummyDC, HORZRES) / GetDeviceCaps(dummyDC, HORZSIZE); + info.bmiHeader.biYPelsPerMeter = GetDeviceCaps(dummyDC, VERTRES) / GetDeviceCaps(dummyDC, VERTSIZE); + info.bmiHeader.biClrUsed = 0; + info.bmiHeader.biClrImportant = 0; + info.bmiColors[0].rgbBlue = info.bmiColors[0].rgbGreen = info.bmiColors[0].rgbRed = 0x00; + info.bmiColors[1].rgbBlue = info.bmiColors[1].rgbGreen = info.bmiColors[1].rgbRed = 0xff; + + // create a DIB to render to + BYTE *bits; + HBITMAP dib = CreateDIBSection(dummyDC, &info, DIB_RGB_COLORS, reinterpret_cast(&bits), NULL, 0); + HGDIOBJ oldbitmap = SelectObject(dummyDC, dib); + + // clear the bitmap + int rowbytes = bmwidth / 8; + memset(bits, 0, rowbytes * bmheight); + + // now draw the character + WCHAR tempchar = chnum; + SetTextColor(dummyDC, RGB(0xff,0xff,0xff)); + SetBkColor(dummyDC, RGB(0x00,0x00,0x00)); + ExtTextOutW(dummyDC, 50 + abc.abcA, 50, ETO_OPAQUE, NULL, &tempchar, 1, NULL); + + // characters are expected to be full-height + rectangle actbounds; + actbounds.min_y = 50; + actbounds.max_y = 50 + metrics.tmHeight - 1; + + // determine the actual left of the character + for (actbounds.min_x = 0; actbounds.min_x < rowbytes; actbounds.min_x++) + { + BYTE *offs = bits + actbounds.min_x; + UINT8 summary = 0; + for (int y = 0; y < bmheight; y++) + summary |= offs[y * rowbytes]; + if (summary != 0) + { + actbounds.min_x *= 8; + if (!(summary & 0x80)) actbounds.min_x++; + if (!(summary & 0xc0)) actbounds.min_x++; + if (!(summary & 0xe0)) actbounds.min_x++; + if (!(summary & 0xf0)) actbounds.min_x++; + if (!(summary & 0xf8)) actbounds.min_x++; + if (!(summary & 0xfc)) actbounds.min_x++; + if (!(summary & 0xfe)) actbounds.min_x++; + break; + } + } + + // determine the actual right of the character + for (actbounds.max_x = rowbytes - 1; actbounds.max_x >= 0; actbounds.max_x--) + { + BYTE *offs = bits + actbounds.max_x; + UINT8 summary = 0; + for (int y = 0; y < bmheight; y++) + summary |= offs[y * rowbytes]; + if (summary != 0) + { + actbounds.max_x *= 8; + if (summary & 0x7f) actbounds.max_x++; + if (summary & 0x3f) actbounds.max_x++; + if (summary & 0x1f) actbounds.max_x++; + if (summary & 0x0f) actbounds.max_x++; + if (summary & 0x07) actbounds.max_x++; + if (summary & 0x03) actbounds.max_x++; + if (summary & 0x01) actbounds.max_x++; + break; + } + } + + // allocate a new bitmap + bitmap_t *bitmap = NULL; + if (actbounds.max_x >= actbounds.min_x && actbounds.max_y >= actbounds.min_y) + { + bitmap = auto_alloc(&machine(), bitmap_t(actbounds.max_x + 1 - actbounds.min_x, actbounds.max_y + 1 - actbounds.min_y, BITMAP_FORMAT_ARGB32)); + + // copy the bits into it + for (int y = 0; y < bitmap->height; y++) + { + UINT32 *dstrow = BITMAP_ADDR32(bitmap, y, 0); + UINT8 *srcrow = &bits[(y + actbounds.min_y) * rowbytes]; + for (int x = 0; x < bitmap->width; x++) + { + int effx = x + actbounds.min_x; + dstrow[x] = ((srcrow[effx / 8] << (effx % 8)) & 0x80) ? MAKE_ARGB(0xff,0xff,0xff,0xff) : MAKE_ARGB(0x00,0xff,0xff,0xff); + } + } + + // set the final offset values + xoffs = actbounds.min_x - (50 + abc.abcA); + yoffs = actbounds.max_y - (50 + metrics.tmAscent); + } + + // de-select the font and release the DC + SelectObject(dummyDC, oldbitmap); + DeleteObject(dib); + SelectObject(dummyDC, oldfont); + DeleteDC(dummyDC); + return bitmap; +} + + //============================================================ // winmain_dump_stack //============================================================ diff --git a/src/osd/windows/winmain.h b/src/osd/windows/winmain.h index 56ff0ae7c88..c3b3eb4b975 100644 --- a/src/osd/windows/winmain.h +++ b/src/osd/windows/winmain.h @@ -156,8 +156,15 @@ public: // input overridables virtual void customize_input_type_list(input_type_desc *typelist); + // font overridables + virtual osd_font font_open(const char *name, int &height); + virtual void font_close(osd_font font); + virtual bitmap_t *font_get_bitmap(osd_font font, unicode_char chnum, INT32 &width, INT32 &xoffs, INT32 &yoffs); + private: static void osd_exit(running_machine &machine); + + static const int DEFAULT_FONT_HEIGHT = 200; };