From d158280425efac5f4ec72e00fb2b7389cdfb5a75 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 24 Feb 2004 22:39:42 +0000 Subject: the OSystem changes we discussed on the ML (note: renaming of the existing OSystem API is not yet finished); porters will have to fix their ports to get them to compile again svn-id: r13036 --- backends/PalmOS/Src/palm.cpp | 7 +- backends/PalmOS/Src/palm.h | 11 +- backends/dc/audio.cpp | 4 +- backends/dc/dc.h | 6 +- backends/dc/display.cpp | 2 +- backends/gp32/gp32.cpp | 6 +- backends/gp32/gp32.h | 6 +- backends/intern.h | 2 +- backends/midi/adlib.cpp | 6 +- backends/morphos/morphos.cpp | 8 +- backends/morphos/morphos.h | 6 +- backends/null/null.cpp | 6 +- backends/sdl/sdl-common.cpp | 199 ++++++++++++++++++++++++---------- backends/sdl/sdl-common.h | 28 +++-- backends/sdl/sdl.cpp | 47 +------- backends/wince/wince-sdl.cpp | 6 +- backends/wince/wince-sdl.h | 4 +- backends/x11/x11.cpp | 19 ++-- base/gameDetector.cpp | 64 +++-------- base/gameDetector.h | 9 -- base/main.cpp | 31 +++--- common/debugger.cpp | 8 +- common/system.cpp | 42 ++++++-- common/system.h | 250 ++++++++++++++++++++++++++++--------------- gui/options.cpp | 25 ++--- queen/queen.cpp | 2 +- scumm/dialogs.cpp | 9 +- scumm/player_mod.cpp | 2 +- scumm/player_v2.cpp | 2 +- scumm/scummvm.cpp | 9 +- simon/items.cpp | 21 ++-- simon/simon.cpp | 8 +- sky/control.cpp | 8 +- sky/music/adlibmusic.cpp | 9 +- sky/screen.cpp | 2 +- sky/sky.cpp | 2 +- sound/fmopl.cpp | 24 +++++ sound/fmopl.h | 3 + sound/mixer.cpp | 6 +- sword1/sword1.cpp | 2 +- sword2/driver/d_draw.cpp | 2 +- sword2/driver/rdwin.cpp | 5 +- 42 files changed, 498 insertions(+), 420 deletions(-) diff --git a/backends/PalmOS/Src/palm.cpp b/backends/PalmOS/Src/palm.cpp index 98f15d7944..05ebe67520 100644 --- a/backends/PalmOS/Src/palm.cpp +++ b/backends/PalmOS/Src/palm.cpp @@ -230,7 +230,7 @@ void OSystem_PALMOS::unload_gfx_mode() { } -void OSystem_PALMOS::init_size(uint w, uint h) { +void OSystem_PALMOS::initSize(uint w, uint h) { _screenWidth = w; _screenHeight = h; _offScreenPitch = gVars->screenPitch; // direct screen / flipping use this, reset later if buffered @@ -1593,13 +1593,12 @@ static Err sndCallback(void* UserDataP, SndStreamRef stream, void* bufferP, UInt return errNone; } -bool OSystem_PALMOS::set_sound_proc(SoundProc proc, void *param, SoundFormat format) { +bool OSystem_PALMOS::setSoundCallback(SoundProc proc, void *param) { Boolean success = false; if (!_sound.active) { _sound.proc = proc; _sound.param = param; - _sound.format = format; _sound.active = true; // always true when we call this function // try to create sound stream @@ -1622,7 +1621,7 @@ bool OSystem_PALMOS::set_sound_proc(SoundProc proc, void *param, SoundFormat for return success; } -void OSystem_PALMOS::clear_sound_proc() { +void OSystem_PALMOS::clearSoundCallback() { if (_sound.active) { if (!_sound.useHandler) { SndStreamStop(_sound.sndRefNum); diff --git a/backends/PalmOS/Src/palm.h b/backends/PalmOS/Src/palm.h index c1dbc29140..cd87daf12c 100644 --- a/backends/PalmOS/Src/palm.h +++ b/backends/PalmOS/Src/palm.h @@ -37,7 +37,6 @@ Err HwrDisplayPalette(UInt8 operation, Int16 startIndex, typedef struct { OSystem::SoundProc proc; void *param; - OSystem::SoundFormat format; SndStreamRef sndRefNum; bool active, useHandler; @@ -51,7 +50,7 @@ public: // Set the size of the video bitmap. // Typically, 320x200 - void init_size(uint w, uint h); + void initSize(uint w, uint h); // Draw a bitmap to screen. // The screen will not be updated to reflect the new bitmap @@ -103,14 +102,14 @@ public: * @param param an arbitrary parameter which is stored and passed to proc. * @param format the sample type format. */ - bool set_sound_proc(SoundProc proc, void *param, SoundFormat format); + bool setSoundCallback(SoundProc proc, void *param); /** - * Remove any audio callback previously set via set_sound_proc, thus effectively + * Remove any audio callback previously set via setSoundCallback, thus effectively * stopping all audio output immediately. - * @see set_sound_proc + * @see setSoundCallback */ - void clear_sound_proc(); + void clearSoundCallback(); //@} // Poll cdrom status diff --git a/backends/dc/audio.cpp b/backends/dc/audio.cpp index a31d4b1884..2838e0779d 100644 --- a/backends/dc/audio.cpp +++ b/backends/dc/audio.cpp @@ -34,7 +34,7 @@ void initSound() do_sound_command(CMD_SET_BUFFER(3)); } -bool OSystem_Dreamcast::set_sound_proc(SoundProc proc, void *param, SoundFormat format) +bool OSystem_Dreamcast::setSoundCallback(SoundProc proc, void *param) { #if SAMPLE_MODE == 0 assert(format == SOUND_16BIT); @@ -49,7 +49,7 @@ bool OSystem_Dreamcast::set_sound_proc(SoundProc proc, void *param, SoundFormat return true; } -void OSystem_Dreamcast::clear_sound_proc() +void OSystem_Dreamcast::clearSoundCallback() { _sound_proc = NULL; _sound_proc_param = NULL; diff --git a/backends/dc/dc.h b/backends/dc/dc.h index 57ba12ef51..b39d442856 100644 --- a/backends/dc/dc.h +++ b/backends/dc/dc.h @@ -35,7 +35,7 @@ class OSystem_Dreamcast : public OSystem { // Set the size of the video bitmap. // Typically, 320x200 - void init_size(uint w, uint h); + void initSize(uint w, uint h); int16 get_height() { return _screen_h; } int16 get_width() { return _screen_w; } @@ -71,8 +71,8 @@ class OSystem_Dreamcast : public OSystem { bool poll_event(Event *event); // Set function that generates samples - bool set_sound_proc(SoundProc proc, void *param, SoundFormat format); - void clear_sound_proc(); + bool setSoundCallback(SoundProc proc, void *param); + void clearSoundCallback(); // Poll cdrom status // Returns true if cd audio is playing diff --git a/backends/dc/display.cpp b/backends/dc/display.cpp index 2900e1e363..13d23d6eb1 100644 --- a/backends/dc/display.cpp +++ b/backends/dc/display.cpp @@ -141,7 +141,7 @@ void OSystem_Dreamcast::set_palette(const byte *colors, uint start, uint num) _screen_dirty = true; } -void OSystem_Dreamcast::init_size(uint w, uint h) +void OSystem_Dreamcast::initSize(uint w, uint h) { assert(w <= SCREEN_W && h <= SCREEN_H); diff --git a/backends/gp32/gp32.cpp b/backends/gp32/gp32.cpp index 88527fef32..1d529e25bd 100644 --- a/backends/gp32/gp32.cpp +++ b/backends/gp32/gp32.cpp @@ -56,7 +56,7 @@ void OSystem_GP32::set_palette(const byte *colors, uint start, uint num) { // Set the size of the video bitmap. // Typically, 320x200 -void OSystem_GP32::init_size(uint w, uint h) { +void OSystem_GP32::initSize(uint w, uint h) { // Avoid redundant res changes if ((int)w == _screenWidth && (int)h == _screenHeight) return; @@ -976,11 +976,11 @@ bool OSystem_GP32::poll_event(Event *event) { // fixme: make more user-friendly // Set the function to be invoked whenever samples need to be generated // Format is the sample type format. // Only 16-bit signed mode is needed for simon & scumm -bool OSystem_GP32::set_sound_proc(SoundProc proc, void *param, SoundFormat format) { +bool OSystem_GP32::setSoundCallback(SoundProc proc, void *param) { return false; } -void OSystem_GP32::clear_sound_proc() { +void OSystem_GP32::clearSoundCallback() { //_sound_proc = NULL; //_sound_proc_param = NULL; } diff --git a/backends/gp32/gp32.h b/backends/gp32/gp32.h index 0faf3f0cf2..2b692f0493 100644 --- a/backends/gp32/gp32.h +++ b/backends/gp32/gp32.h @@ -39,7 +39,7 @@ public: // Set the size of the video bitmap. // Typically, 320x200 - void init_size(uint w, uint h); + void initSize(uint w, uint h); int16 get_height() { return _screenHeight; } int16 get_width() { return _screenWidth; } @@ -80,8 +80,8 @@ public: // Set the function to be invoked whenever samples need to be generated // Format is the sample type format. // Only 16-bit signed mode is needed for simon & scumm - bool set_sound_proc(SoundProc proc, void *param, SoundFormat format); - void clear_sound_proc(); + bool setSoundCallback(SoundProc proc, void *param); + void clearSoundCallback(); // Get or set a property uint32 property(int param, Property *value); diff --git a/backends/intern.h b/backends/intern.h index 57a763a17c..9d07aba0c0 100644 --- a/backends/intern.h +++ b/backends/intern.h @@ -27,7 +27,7 @@ /* Factory functions. This means we don't have to include the headers for * all backends. */ -extern OSystem *OSystem_SDL_create(int gfx_driver); +extern OSystem *OSystem_SDL_create(); extern OSystem *OSystem_NULL_create(); extern OSystem *OSystem_MorphOS_create(int gfx_driver, bool full_screen); extern OSystem *OSystem_Dreamcast_create(); diff --git a/backends/midi/adlib.cpp b/backends/midi/adlib.cpp index 02261fed71..7fb0de39b1 100644 --- a/backends/midi/adlib.cpp +++ b/backends/midi/adlib.cpp @@ -852,11 +852,7 @@ int MidiDriver_ADLIB::open() { _adlib_reg_cache = (byte *)calloc(256, 1); - // We need to emulate one YM3812 chip - int env_bits = g_system->property(OSystem::PROP_GET_FMOPL_ENV_BITS, NULL); - int eg_ent = g_system->property(OSystem::PROP_GET_FMOPL_EG_ENT, NULL); - OPLBuildTables((env_bits ? env_bits : FMOPL_ENV_BITS_HQ), (eg_ent ? eg_ent : FMOPL_EG_ENT_HQ)); - _opl = OPLCreate(OPL_TYPE_YM3812, 3579545, _mixer->getOutputRate()); + _opl = makeAdlibOPL(_mixer->getOutputRate()); adlib_write(1, 0x20); adlib_write(8, 0x40); diff --git a/backends/morphos/morphos.cpp b/backends/morphos/morphos.cpp index 2482d5e274..d36965538d 100644 --- a/backends/morphos/morphos.cpp +++ b/backends/morphos/morphos.cpp @@ -1436,13 +1436,13 @@ void OSystem_MorphOS::set_mouse_cursor(const byte *buf, uint w, uint h, int hots UndrawMouse(); } -bool OSystem_MorphOS::set_sound_proc(OSystem::SoundProc proc, void *param, OSystem::SoundFormat format) +bool OSystem_MorphOS::setSoundCallback(OSystem::SoundProc proc, void *param) { if (ScummSoundThread) { if (SoundProc == proc) return true; - clear_sound_proc(); + clearSoundCallback(); } SoundProc = proc; @@ -1479,7 +1479,7 @@ void OSystem_MorphOS::fill_sound(byte *stream, int len) memset(stream, 0x0, len); } -void OSystem_MorphOS::clear_sound_proc() +void OSystem_MorphOS::clearSoundCallback() { if (ScummSoundThread) { @@ -1490,7 +1490,7 @@ void OSystem_MorphOS::clear_sound_proc() } } -void OSystem_MorphOS::init_size(uint w, uint h) +void OSystem_MorphOS::initSize(uint w, uint h) { if (ScummBuffer) { diff --git a/backends/morphos/morphos.h b/backends/morphos/morphos.h index deea09bbf7..49ea1a654a 100644 --- a/backends/morphos/morphos.h +++ b/backends/morphos/morphos.h @@ -47,7 +47,7 @@ class OSystem_MorphOS : public OSystem // Set the size of the video bitmap. // Typically, 320x200 - virtual void init_size(uint w, uint h); + virtual void initSize(uint w, uint h); // Draw a bitmap to screen. // The screen will not be updated to reflect the new bitmap @@ -101,9 +101,9 @@ class OSystem_MorphOS : public OSystem virtual void warp_mouse(int x, int y); // Set the function to be invoked whenever samples need to be generated - virtual bool set_sound_proc(SoundProc proc, void *param, SoundFormat format); + virtual bool setSoundCallback(SoundProc proc, void *param); void fill_sound (byte * stream, int len); - void clear_sound_proc(); + void clearSoundCallback(); virtual uint32 property(int param, Property *value); diff --git a/backends/null/null.cpp b/backends/null/null.cpp index d5c53b78ce..6e60044b2c 100644 --- a/backends/null/null.cpp +++ b/backends/null/null.cpp @@ -30,7 +30,7 @@ class OSystem_NULL : public OSystem { public: void set_palette(const byte *colors, uint start, uint num) {} - void init_size(uint w, uint h); + void initSize(uint w, uint h); void copy_rect(const byte *buf, int pitch, int x, int y, int w, int h) {} void move_screen(int dx, int dy) {} void update_screen() {} @@ -41,7 +41,7 @@ public: uint32 get_msecs(); void delay_msecs(uint msecs); bool poll_event(Event *event) { return false; } - bool set_sound_proc(SoundProc proc, void *param, SoundFormat format) {} + bool setSoundCallback(SoundProc proc, void *param) {} void quit() { exit(1); } uint32 property(int param, Property *value) { return 0; } static OSystem *create(int gfx_mode, bool full_screen); @@ -52,7 +52,7 @@ private: uint32 get_ticks(); }; -void OSystem_NULL::init_size(uint w, uint h, byte sound) { +void OSystem_NULL::initSize(uint w, uint h, byte sound) { msec_start = get_ticks(); } diff --git a/backends/sdl/sdl-common.cpp b/backends/sdl/sdl-common.cpp index 3ecd5197e8..4e4d522f41 100644 --- a/backends/sdl/sdl-common.cpp +++ b/backends/sdl/sdl-common.cpp @@ -47,29 +47,23 @@ #define JOY_BUT_SPACE 4 #define JOY_BUT_F5 5 -OSystem *OSystem_SDL_create(int gfx_mode) { - return OSystem_SDL_Common::create(gfx_mode); +OSystem *OSystem_SDL_create() { + return OSystem_SDL_Common::create(); } -OSystem *OSystem_SDL_Common::create(int gfx_mode) { +OSystem *OSystem_SDL_Common::create() { OSystem_SDL_Common *syst = OSystem_SDL_Common::create_intern(); - syst->init_intern(gfx_mode); + syst->init_intern(); return syst; } -void OSystem_SDL_Common::init_intern(int gfx_mode) { +void OSystem_SDL_Common::init_intern() { int joystick_num = ConfMan.getInt("joystick_num"); uint32 sdlFlags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER; - cksum_valid = false; - _mode = gfx_mode; - _full_screen = ConfMan.getBool("fullscreen"); - _adjustAspectRatio = ConfMan.getBool("aspect_ratio"); - _mode_flags = 0; - if (joystick_num > -1) sdlFlags |= SDL_INIT_JOYSTICK; @@ -84,6 +78,13 @@ void OSystem_SDL_Common::init_intern(int gfx_mode) { // Enable unicode support if possible SDL_EnableUNICODE(1); + cksum_valid = false; + _mode = GFX_DOUBLESIZE; + _full_screen = ConfMan.getBool("fullscreen"); + _adjustAspectRatio = ConfMan.getBool("aspect_ratio"); + _mode_flags = 0; + + #ifndef MACOSX // Don't set icon on OS X, as we use a nicer external icon there // Setup the icon setup_icon(); @@ -133,7 +134,7 @@ OSystem_SDL_Common::~OSystem_SDL_Common() { SDL_Quit(); } -void OSystem_SDL_Common::init_size(uint w, uint h) { +void OSystem_SDL_Common::initSize(uint w, uint h) { // Avoid redundant res changes if ((int)w == _screenWidth && (int)h == _screenHeight) return; @@ -622,7 +623,7 @@ bool OSystem_SDL_Common::poll_event(Event *event) { // Alt-Return toggles full screen mode if (b == KBD_ALT && ev.key.keysym.sym == SDLK_RETURN) { - property(PROP_TOGGLE_FULLSCREEN, NULL); + setFeatureState(kFeatureFullscreenMode, !_full_screen); break; } @@ -654,7 +655,7 @@ bool OSystem_SDL_Common::poll_event(Event *event) { #else // Ctrl-m toggles mouse capture if (b == KBD_CTRL && ev.key.keysym.sym == 'm') { - property(PROP_TOGGLE_MOUSE_GRAB, NULL); + toggleMouseGrab(); break; } @@ -695,13 +696,11 @@ bool OSystem_SDL_Common::poll_event(Event *event) { } } - - Property prop; int factor = _scaleFactor - 1; // Ctrl-Alt-a toggles aspect ratio correction if (ev.key.keysym.sym == 'a') { - property(PROP_TOGGLE_ASPECT_RATIO, NULL); + setFeatureState(kFeatureAspectRatioCorrection, !_adjustAspectRatio); break; } @@ -710,8 +709,7 @@ bool OSystem_SDL_Common::poll_event(Event *event) { if (ev.key.keysym.sym == '=' || ev.key.keysym.sym == '+' || ev.key.keysym.sym == '-') { factor += (ev.key.keysym.sym == '-' ? -1 : +1); if (0 <= factor && factor < 4 && gfxModes[_scalerType][factor] >= 0) { - prop.gfx_mode = gfxModes[_scalerType][factor]; - property(PROP_SET_GFX_MODE, &prop); + setGraphicsMode(gfxModes[_scalerType][factor]); } break; } @@ -725,8 +723,7 @@ bool OSystem_SDL_Common::poll_event(Event *event) { assert(factor > 0); factor--; } - prop.gfx_mode = gfxModes[_scalerType][factor]; - property(PROP_SET_GFX_MODE, &prop); + setGraphicsMode(gfxModes[_scalerType][factor]); break; } } @@ -1014,12 +1011,11 @@ bool OSystem_SDL_Common::poll_event(Event *event) { return false; } -bool OSystem_SDL_Common::set_sound_proc(SoundProc proc, void *param, SoundFormat format) { +bool OSystem_SDL_Common::setSoundCallback(SoundProc proc, void *param) { SDL_AudioSpec desired; memset(&desired, 0, sizeof(desired)); - /* only one format supported at the moment */ desired.freq = SAMPLES_PER_SEC; desired.format = AUDIO_S16SYS; desired.channels = 2; @@ -1033,55 +1029,140 @@ bool OSystem_SDL_Common::set_sound_proc(SoundProc proc, void *param, SoundFormat return true; } -void OSystem_SDL_Common::clear_sound_proc() { +void OSystem_SDL_Common::clearSoundCallback() { SDL_CloseAudio(); } -uint32 OSystem_SDL_Common::property(int param, Property *value) { - switch(param) { +static const OSystem::GraphicsMode gfx_modes[] = { + {"1x", "Normal (no scaling)", GFX_NORMAL}, + {"2x", "2x", GFX_DOUBLESIZE}, + {"3x", "3x", GFX_TRIPLESIZE}, + {"2xsai", "2xSAI", GFX_2XSAI}, + {"super2xsai", "Super2xSAI", GFX_SUPER2XSAI}, + {"supereagle", "SuperEagle", GFX_SUPEREAGLE}, + {"advmame2x", "AdvMAME2x", GFX_ADVMAME2X}, + {"advmame3x", "AdvMAME3x", GFX_ADVMAME3X}, + {"hq2x", "HQ2x", GFX_HQ2X}, + {"hq3x", "HQ3x", GFX_HQ3X}, + {"tv2x", "TV2x", GFX_TV2X}, + {"dotmatrix", "DotMatrix", GFX_DOTMATRIX}, + {0, 0, 0} +}; + +const OSystem::GraphicsMode *OSystem_SDL_Common::getSupportedGraphicsModes() const { + return gfx_modes; +} - case PROP_WANT_RECT_OPTIM: - _mode_flags |= DF_WANT_RECT_OPTIM; - break; +bool OSystem_SDL_Common::setGraphicsMode(int mode) { + Common::StackLock lock(_graphicsMutex, this); - case PROP_GET_FULLSCREEN: - return _full_screen; + // FIXME! HACK, hard coded threshold, not good + // Really should check the 'mode' against the list of supported + // modes, and then decide whether to accept it. + if (mode > 11) + return false; - case PROP_GET_GFX_MODE: - return _mode; - - case PROP_SET_WINDOW_CAPTION: - SDL_WM_SetCaption(value->caption, value->caption); - return 1; - - case PROP_OPEN_CD: - if (SDL_InitSubSystem(SDL_INIT_CDROM) == -1) - _cdrom = NULL; - else { - _cdrom = SDL_CDOpen(value->cd_num); - // Did it open? Check if _cdrom is NULL - if (!_cdrom) { - warning("Couldn't open drive: %s", SDL_GetError()); - } else { - cd_num_loops = 0; - cd_stop_time = 0; - cd_end_time = 0; - } + _mode = mode; + hotswap_gfx_mode(); + return true; +} + +int OSystem_SDL_Common::getGraphicsMode() const { + return _mode; +} + + +void OSystem_SDL_Common::setWindowCaption(const char *caption) { + SDL_WM_SetCaption(caption, caption); +} + +bool OSystem_SDL_Common::openCD(int drive) { + if (SDL_InitSubSystem(SDL_INIT_CDROM) == -1) + _cdrom = NULL; + else { + _cdrom = SDL_CDOpen(drive); + // Did it open? Check if _cdrom is NULL + if (!_cdrom) { + warning("Couldn't open drive: %s", SDL_GetError()); + } else { + cd_num_loops = 0; + cd_stop_time = 0; + cd_end_time = 0; } - break; + } + + return (_cdrom != NULL); +} + +int OSystem_SDL_Common::getOutputSampleRate() const { + return SAMPLES_PER_SEC; +} - case PROP_GET_SAMPLE_RATE: - return SAMPLES_PER_SEC; - case PROP_TOGGLE_MOUSE_GRAB: - if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) - SDL_WM_GrabInput(SDL_GRAB_ON); +bool OSystem_SDL_Common::hasFeature(Feature f) { + return + (f == kFeatureFullscreenMode) || + (f == kFeatureAspectRatioCorrection) || + (f == kFeatureAutoComputeDirtyRects); +} + +void OSystem_SDL_Common::setFeatureState(Feature f, bool enable) { + Common::StackLock lock(_graphicsMutex, this); + + switch (f) { + case kFeatureFullscreenMode: + if (_full_screen != enable) { + //assert(_hwscreen != 0); + _full_screen ^= true; +#ifdef MACOSX + // On OS X, SDL_WM_ToggleFullScreen is currently not implemented. Worse, + // it still always returns -1. So we simply don't call it at all and + // use hotswap_gfx_mode() directly to switch to fullscreen mode. + hotswap_gfx_mode(); +#else + if (!SDL_WM_ToggleFullScreen(_hwscreen)) { + // if ToggleFullScreen fails, achieve the same effect with hotswap gfx mode + hotswap_gfx_mode(); + } +#endif + } + break; + case kFeatureAspectRatioCorrection: + if (_screenHeight == 200 && _adjustAspectRatio != enable) { + //assert(_hwscreen != 0); + _adjustAspectRatio ^= true; + hotswap_gfx_mode(); + } + break; + case kFeatureAutoComputeDirtyRects: + if (enable) + _mode_flags |= DF_WANT_RECT_OPTIM; else - SDL_WM_GrabInput(SDL_GRAB_OFF); + _mode_flags &= ~DF_WANT_RECT_OPTIM; + break; + default: break; } +} - return 0; +bool OSystem_SDL_Common::getFeatureState(Feature f) { + switch (f) { + case kFeatureFullscreenMode: + return _full_screen; + case kFeatureAspectRatioCorrection: + return _adjustAspectRatio; + case kFeatureAutoComputeDirtyRects: + return _mode_flags & DF_WANT_RECT_OPTIM; + default: + return false; + } +} + +void OSystem_SDL_Common::toggleMouseGrab() { + if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF) + SDL_WM_GrabInput(SDL_GRAB_ON); + else + SDL_WM_GrabInput(SDL_GRAB_OFF); } void OSystem_SDL_Common::quit() { diff --git a/backends/sdl/sdl-common.h b/backends/sdl/sdl-common.h index 3d47ca582e..cdd5b0c1de 100644 --- a/backends/sdl/sdl-common.h +++ b/backends/sdl/sdl-common.h @@ -33,7 +33,7 @@ class OSystem_SDL_Common : public OSystem { public: // Set the size of the video bitmap. // Typically, 320x200 - void init_size(uint w, uint h); + void initSize(uint w, uint h); // Set colors of the palette void set_palette(const byte *colors, uint start, uint num); @@ -72,9 +72,9 @@ public: bool poll_event(Event *event); // Set function that generates samples - bool set_sound_proc(SoundProc proc, void *param, SoundFormat format); + bool setSoundCallback(SoundProc proc, void *param); - void clear_sound_proc(); + void clearSoundCallback(); // Poll CD status // Returns true if cd audio is playing @@ -92,8 +92,6 @@ public: // Quit void quit(); - // Set a parameter - uint32 property(int param, Property *value); // Add a callback timer void set_timer(TimerProc callback, int timer); @@ -117,7 +115,21 @@ public: virtual int16 RGBToColor(uint8 r, uint8 g, uint8 b); virtual void colorToRGB(int16 color, uint8 &r, uint8 &g, uint8 &b); - static OSystem *create(int gfx_mode); + + virtual const GraphicsMode *getSupportedGraphicsModes() const; + virtual bool setGraphicsMode(int mode); + virtual int getGraphicsMode() const; + + virtual void setWindowCaption(const char *caption); + virtual bool openCD(int drive); + virtual int getOutputSampleRate() const; + + virtual bool hasFeature(Feature f); + virtual void setFeatureState(Feature f, bool enable); + virtual bool getFeatureState(Feature f); + + + static OSystem *create(); protected: OSystem_SDL_Common(); @@ -125,7 +137,7 @@ protected: static OSystem_SDL_Common *create_intern(); - void init_intern(int gfx_mode); + void init_intern(); // unseen game screen SDL_Surface *_screen; @@ -218,10 +230,12 @@ protected: /** Set the position of the virtual mouse cursor. */ void set_mouse_pos(int x, int y); void fillMouseEvent(Event &event, int x, int y); + void toggleMouseGrab(); virtual void load_gfx_mode() = 0; virtual void unload_gfx_mode() = 0; + virtual void hotswap_gfx_mode() = 0; virtual bool save_screenshot(const char *filename) = 0; diff --git a/backends/sdl/sdl.cpp b/backends/sdl/sdl.cpp index 456ed2c5bf..384af1673c 100644 --- a/backends/sdl/sdl.cpp +++ b/backends/sdl/sdl.cpp @@ -31,9 +31,6 @@ public: // Update the dirty areas of the screen void update_screen(); - // Set a parameter - uint32 property(int param, Property *value); - protected: SDL_Surface *_hwscreen; // hardware screen @@ -42,7 +39,7 @@ protected: virtual void load_gfx_mode(); virtual void unload_gfx_mode(); virtual bool save_screenshot(const char *filename); - void hotswap_gfx_mode(); + virtual void hotswap_gfx_mode(); }; OSystem_SDL_Common *OSystem_SDL_Common::create_intern() { @@ -363,48 +360,6 @@ void OSystem_SDL::update_screen() { _forceFull = false; } -uint32 OSystem_SDL::property(int param, Property *value) { - - Common::StackLock lock(_graphicsMutex, this); // Lock the mutex until this function ends - - if (param == PROP_TOGGLE_FULLSCREEN) { - assert(_hwscreen != 0); - _full_screen ^= true; -#ifdef MACOSX - // On OS X, SDL_WM_ToggleFullScreen is currently not implemented. Worse, - // it still always returns -1. So we simply don't call it at all and - // use hotswap_gfx_mode() directly to switch to fullscreen mode. - hotswap_gfx_mode(); -#else - if (!SDL_WM_ToggleFullScreen(_hwscreen)) { - // if ToggleFullScreen fails, achieve the same effect with hotswap gfx mode - hotswap_gfx_mode(); - } -#endif - return 1; - } else if (param == PROP_SET_GFX_MODE) { - if (value->gfx_mode > 11) // FIXME! HACK, hard coded threshold, not good - return 0; - - _mode = value->gfx_mode; - hotswap_gfx_mode(); - - return 1; - } else if (param == PROP_TOGGLE_ASPECT_RATIO) { - if (_screenHeight == 200) { - assert(_hwscreen != 0); - _adjustAspectRatio ^= true; - hotswap_gfx_mode(); - } - } else if (param == PROP_HAS_SCALER) { - if (value->gfx_mode <= 11) // FIXME: Hardcoded - return 1; - return 0; - } - - return OSystem_SDL_Common::property(param, value); -} - bool OSystem_SDL::save_screenshot(const char *filename) { assert(_hwscreen != NULL); diff --git a/backends/wince/wince-sdl.cpp b/backends/wince/wince-sdl.cpp index df2dbe574c..6fb88a4948 100644 --- a/backends/wince/wince-sdl.cpp +++ b/backends/wince/wince-sdl.cpp @@ -219,7 +219,7 @@ void OSystem_WINCE3::get_sample_rate() { #endif } -bool OSystem_WINCE3::set_sound_proc(SoundProc proc, void *param, SoundFormat format) { +bool OSystem_WINCE3::setSoundCallback(SoundProc proc, void *param) { SDL_AudioSpec desired; int thread_priority; @@ -322,7 +322,7 @@ void OSystem_WINCE3::update_game_settings() { } } -void OSystem_WINCE3::init_size(uint w, uint h) { +void OSystem_WINCE3::initSize(uint w, uint h) { if (w == 320 && h == 200) h = 240; // use the extra 40 pixels height for the toolbar @@ -333,7 +333,7 @@ void OSystem_WINCE3::init_size(uint w, uint h) { else _toolbarHandler.setOffset(400); - OSystem_SDL_Common::init_size(w, h); + OSystem_SDL_Common::initSize(w, h); update_game_settings(); diff --git a/backends/wince/wince-sdl.h b/backends/wince/wince-sdl.h index 81c0bb2c26..a8e131f5cd 100644 --- a/backends/wince/wince-sdl.h +++ b/backends/wince/wince-sdl.h @@ -46,7 +46,7 @@ public: // Set a parameter uint32 property(int param, Property *value); - void init_size(uint w, uint h); + void initSize(uint w, uint h); // Overloaded from SDL_Common (toolbar handling) bool poll_event(Event *event); @@ -61,7 +61,7 @@ public: // Overloaded from SDL_Commmon void quit(); // Overloaded from SDL_Commmon (master volume and sample rate subtleties) - bool set_sound_proc(SoundProc proc, void *param, SoundFormat format); + bool setSoundCallback(SoundProc proc, void *param); // GUI and action stuff void swap_panel_visibility(); diff --git a/backends/x11/x11.cpp b/backends/x11/x11.cpp index 32e02b848d..3ce815a728 100644 --- a/backends/x11/x11.cpp +++ b/backends/x11/x11.cpp @@ -60,7 +60,7 @@ public: // Set the size of the video bitmap. // Typically, 320x200 - void init_size(uint w, uint h); + void initSize(uint w, uint h); // Draw a bitmap to screen. // The screen will not be updated to reflect the new bitmap @@ -99,9 +99,9 @@ public: bool poll_event(Event *event); // Set function that generates samples - bool set_sound_proc(SoundProc proc, void *param, SoundFormat format); + bool setSoundCallback(SoundProc proc, void *param); - void clear_sound_proc(); + void clearSoundCallback(); // Poll cdrom status // Returns true if cd audio is playing @@ -203,7 +203,6 @@ private: typedef struct { OSystem::SoundProc sound_proc; void *param; - byte format; } THREAD_PARAM; #undef CAPTURE_SOUND @@ -417,7 +416,7 @@ uint32 OSystem_X11::get_msecs() ((current_time.tv_usec - start_time.tv_usec) / 1000)); } -void OSystem_X11::init_size(uint w, uint h) +void OSystem_X11::initSize(uint w, uint h) { static XShmSegmentInfo shminfo; @@ -456,24 +455,20 @@ void OSystem_X11::init_size(uint w, uint h) palette = (uint16 *)calloc(256, sizeof(uint16)); } -bool OSystem_X11::set_sound_proc(SoundProc proc, void *param, SoundFormat format) +bool OSystem_X11::setSoundCallback(SoundProc proc, void *param) { static THREAD_PARAM thread_param; /* And finally start the music thread */ thread_param.param = param; thread_param.sound_proc = proc; - thread_param.format = format; - if (format == SOUND_16BIT) - pthread_create(&sound_thread, NULL, sound_and_music_thread, (void *)&thread_param); - else - warning("Only support 16 bit sound for now. Disabling sound "); + pthread_create(&sound_thread, NULL, sound_and_music_thread, (void *)&thread_param); return true; } -void OSystem_X11::clear_sound_proc() { +void OSystem_X11::clearSoundCallback() { // TODO implement this... // The sound_thread has to be stopped in a nice way. In particular, // using pthread_kill would be a bad idea. Rather, use pthread_cancel, diff --git a/base/gameDetector.cpp b/base/gameDetector.cpp index d5cb1eaef2..037a3efce9 100644 --- a/base/gameDetector.cpp +++ b/base/gameDetector.cpp @@ -96,46 +96,12 @@ static const char USAGE_STRING[] = ; #endif -/** - * List of graphic 'modes' we potentially support. Potentially because not all - * backends actually support all the filters listed here. At this point only - * the SDL backend supports all (except for the PalmOS ones of course). - * @todo Remove this explicit list of graphic modes and rather extend the - * OSystem API to allow querying a backend for the modes it supports. - */ -const GraphicsMode g_gfx_modes[] = { - {"normal", "Normal (no scaling)", GFX_NORMAL}, - {"1x", "Normal (no scaling)", GFX_NORMAL}, -#ifndef __PALM_OS__ // reduce contant data size - {"2x", "2x", GFX_DOUBLESIZE}, - {"3x", "3x", GFX_TRIPLESIZE}, - {"2xsai", "2xSAI", GFX_2XSAI}, - {"super2xsai", "Super2xSAI", GFX_SUPER2XSAI}, - {"supereagle", "SuperEagle", GFX_SUPEREAGLE}, - {"advmame2x", "AdvMAME2x", GFX_ADVMAME2X}, - {"advmame3x", "AdvMAME3x", GFX_ADVMAME3X}, - {"hq2x", "HQ2x", GFX_HQ2X}, - {"hq3x", "HQ3x", GFX_HQ3X}, - {"tv2x", "TV2x", GFX_TV2X}, - {"dotmatrix", "DotMatrix", GFX_DOTMATRIX}, -#else - {"flipping", "Page Flipping", GFX_FLIPPING}, - {"buffered", "Buffered", GFX_BUFFERED}, - {"wide", "Wide (HiRes+ only)", GFX_WIDE}, -#endif - {0, 0, 0} -}; - GameDetector::GameDetector() { // Graphics ConfMan.registerDefault("fullscreen", false); ConfMan.registerDefault("aspect_ratio", false); -#ifndef _WIN32_WCE - ConfMan.registerDefault("gfx_mode", "2x"); -#else ConfMan.registerDefault("gfx_mode", "normal"); -#endif // Sound & Music ConfMan.registerDefault("master_volume", 192); @@ -350,12 +316,22 @@ void GameDetector::parseCommandLine(int argc, char **argv) { END_OPTION DO_OPTION('g', "gfx-mode") - int gfx_mode = parseGraphicsMode(option); + // Check whether 'option' specifies a valid graphics mode. + bool isValid = false; + if (!scumm_stricmp(option, "normal") || !scumm_stricmp(option, "default")) + isValid = true; + if (!isValid) { + const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes(); + while (gm->name && !isValid) { + isValid = !scumm_stricmp(gm->name, option); + gm++; + } + } // TODO: Instead of just showing the generic help text, // maybe print a message like: // "'option' is not a supported graphic mode on this machine. // Available graphic modes: ..." - if (gfx_mode == -1) + if (!isValid) goto ShowHelpAndExit; ConfMan.set("gfx_mode", option, kTransientDomain); END_OPTION @@ -493,22 +469,6 @@ void GameDetector::setTarget(const String &name) { ConfMan.setActiveDomain(name); } -int GameDetector::parseGraphicsMode(const String &str) { - if (str.isEmpty()) - return -1; - - const char *s = str.c_str(); - const GraphicsMode *gm = g_gfx_modes; - while (gm->name) { - if (!scumm_stricmp(gm->name, s)) { - return gm->id; - } - gm++; - } - - return -1; -} - bool GameDetector::detectGame() { String realGame; diff --git a/base/gameDetector.h b/base/gameDetector.h index 62fc365055..cd02fba45d 100644 --- a/base/gameDetector.h +++ b/base/gameDetector.h @@ -54,14 +54,6 @@ struct GameSettings { uint32 features; }; -struct GraphicsMode { - const char *name; - const char *description; - int id; -}; - -extern const GraphicsMode g_gfx_modes[]; - class GameDetector { typedef Common::String String; @@ -85,7 +77,6 @@ public: static SoundMixer *createMixer(); static MidiDriver *createMidi(int midiDriver); - static int parseGraphicsMode(const String &s); // Used in main() static int detectMusicDriver(int midiFlags); static GameSettings findGame(const String &gameName, const Plugin **plugin = NULL); diff --git a/base/main.cpp b/base/main.cpp index 2141c9d05a..85cfc059fd 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -176,12 +176,15 @@ static void do_memory_test(void) { #endif static int launcherDialog(GameDetector &detector, OSystem *system) { - // FIXME - we need to call init_size() here so that we can display for example + // Set the user specified graphics mode (if any). + system->setGraphicsMode(ConfMan.get("gfx_mode").c_str()); + + // FIXME - we need to call initSize() here so that we can display for example // the launcher dialog. But the Engine object will also call it again (possibly // with a different widht/height!9 However, this method is not for all OSystem // implementations reentrant (it is so now for the SDL backend). Thus we need // to fix all backends to support it, if they don't already. - system->init_size(320, 200); + system->initSize(320, 200); // FIXME - mouse cursors are currently always set via 8 bit data. // Thus for now we need to setup a dummy palette. On the long run, we might @@ -219,7 +222,6 @@ static int launcherDialog(GameDetector &detector, OSystem *system) { } static void runGame(GameDetector &detector, OSystem *system) { - OSystem::Property prop; // Set the window caption to the game name Common::String caption(ConfMan.get("description", detector._targetName)); @@ -229,26 +231,22 @@ static void runGame(GameDetector &detector, OSystem *system) { if (caption.isEmpty()) caption = detector._targetName; if (!caption.isEmpty()) { - prop.caption = caption.c_str(); - system->property(OSystem::PROP_SET_WINDOW_CAPTION, &prop); + system->setWindowCaption(caption.c_str()); } // See if the game should default to 1x scaler if (!ConfMan.hasKey("gfx_mode", detector._targetName) && (detector._game.features & GF_DEFAULT_TO_1X_SCALER)) { - prop.gfx_mode = GFX_NORMAL; - system->property(OSystem::PROP_SET_GFX_MODE, &prop); + system->setGraphicsMode(GFX_NORMAL); } else { // Override global scaler with any game-specific define if (ConfMan.hasKey("gfx_mode")) { - prop.gfx_mode = detector.parseGraphicsMode(ConfMan.get("gfx_mode")); - system->property(OSystem::PROP_SET_GFX_MODE, &prop); + system->setGraphicsMode(ConfMan.get("gfx_mode").c_str()); } } // (De)activate fullscreen mode as determined by the config settings - if (ConfMan.getBool("fullscreen") != (system->property(OSystem::PROP_GET_FULLSCREEN, 0) != 0)) - system->property(OSystem::PROP_TOGGLE_FULLSCREEN, 0); + system->setFeatureState(OSystem::kFeatureFullscreenMode, ConfMan.getBool("fullscreen")); // Create the game engine Engine *engine = detector.createEngine(system); @@ -258,18 +256,17 @@ static void runGame(GameDetector &detector, OSystem *system) { engine->go(); // Stop all sound processing now (this prevents some race conditions later on) - system->clear_sound_proc(); + system->clearSoundCallback(); // Free up memory delete engine; }; #ifndef _WIN32_WCE -int main(int argc, char *argv[]) { +extern "C" int main(int argc, char *argv[]) { #else extern "C" int scummvm_main(GameDetector &detector, int argc, char *argv[]) { #endif - OSystem::Property prop; char *cfgFilename = NULL, *s=argv[1]; #if defined(UNIX) @@ -346,15 +343,15 @@ extern "C" int scummvm_main(GameDetector &detector, int argc, char *argv[]) { #endif detector.parseCommandLine(argc, argv); - // Create the system object + // Ensure the system object exists (it may have already been created + // at an earlier point, though!) OSystem *system = OSystem::instance(); // Create the timer services g_timer = new Timer(system); // Set initial window caption - prop.caption = gScummVMFullVersion; - system->property(OSystem::PROP_SET_WINDOW_CAPTION, &prop); + system->setWindowCaption(gScummVMFullVersion); // Unless a game was specified, show the launcher dialog if (detector._targetName.isEmpty()) diff --git a/common/debugger.cpp b/common/debugger.cpp index 03fd28688d..39460c863a 100644 --- a/common/debugger.cpp +++ b/common/debugger.cpp @@ -67,9 +67,7 @@ int Debugger::DebugPrintf(const char *format, ...) { template void Debugger::attach(const char *entry) { - OSystem::Property prop; - prop.show_keyboard = true; - g_system->property(OSystem::PROP_TOGGLE_VIRTUAL_KEYBOARD, &prop); + g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); if (entry) { _errStr = strdup(entry); @@ -82,9 +80,7 @@ void Debugger::attach(const char *entry) { template void Debugger::detach() { - OSystem::Property prop; - prop.show_keyboard = false; - g_system->property(OSystem::PROP_TOGGLE_VIRTUAL_KEYBOARD, &prop); + g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); _detach_now = false; _isAttached = false; diff --git a/common/system.cpp b/common/system.cpp index 59dcee87b3..348273a4c8 100644 --- a/common/system.cpp +++ b/common/system.cpp @@ -29,11 +29,13 @@ #include "common/config-manager.h" #include "common/system.h" -OSystem *g_system = 0; +static OSystem *s_system = 0; static OSystem *createSystem() { - int gfx_mode = GameDetector::parseGraphicsMode(ConfMan.get("gfx_mode")); // FIXME: Get rid of this again! - + // Attention: Do not call parseGraphicsMode() here, nor any other function + // which needs to access the OSystem instance, else you get stuck in an + // endless loop. + #if defined(USE_NULL_DRIVER) return OSystem_NULL_create(); #elif defined(__DC__) @@ -52,12 +54,38 @@ static OSystem *createSystem() { return OSystem_PALMOS_create(gfx_mode); #else /* SDL is the default driver for now */ - return OSystem_SDL_create(gfx_mode); + return OSystem_SDL_create(); #endif } OSystem *OSystem::instance() { - if (!g_system) - g_system = createSystem(); - return g_system; + if (!s_system) + s_system = createSystem(); + return s_system; +} + + +bool OSystem::setGraphicsMode(const char *name) { + if (!name) + return false; + + const GraphicsMode *gm = getSupportedGraphicsModes(); + + // Sepcial case for the 'default' filter + if (!scumm_stricmp(name, "normal") || !scumm_stricmp(name, "default")) { +#ifdef _WIN32_WCE + name = "1x"; +#else + name = "2x"; +#endif + } + + while (gm->name) { + if (!scumm_stricmp(gm->name, name)) { + return setGraphicsMode(gm->id); + } + gm++; + } + + return false; } diff --git a/common/system.h b/common/system.h index d8ead1f7d1..288a92eb18 100644 --- a/common/system.h +++ b/common/system.h @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "common/savefile.h" + /** * Interface for ScummVM backends. If you want to port ScummVM to a system * which is not currently covered by any of our backends, this is the place @@ -38,105 +39,115 @@ */ class OSystem { public: + /** + * Return a pointer to the (singleton) OSystem instance, i.e. the backend. + * This is not a proper singleton, since OSystem is an interface, not + * a real class. + */ static OSystem *instance(); public: - typedef struct Mutex *MutexRef; - typedef void (*SoundProc)(void *param, byte *buf, int len); - typedef int (*TimerProc)(int interval); + /** Virtual destructor */ + virtual ~OSystem() {} + + + /** @name Graphics */ + //@{ + /** - * The types of events backends can generate. - * @see Event + * A feature in this context means an ability of the backend which can be + * either on or off. Examples include: + * - fullscreen mode + * - aspect ration correction + * - a virtual keyboard for text entry (on PDAs) */ - enum EventCode { - EVENT_KEYDOWN = 1, - EVENT_KEYUP = 2, - EVENT_MOUSEMOVE = 3, - EVENT_LBUTTONDOWN = 4, - EVENT_LBUTTONUP = 5, - EVENT_RBUTTONDOWN = 6, - EVENT_RBUTTONUP = 7, - EVENT_WHEELUP = 8, - EVENT_WHEELDOWN = 9, - - EVENT_QUIT = 10, - EVENT_SCREEN_CHANGED = 11 + enum Feature { + kFeatureFullscreenMode, + kFeatureAspectRatioCorrection, + kFeatureVirtualKeyboard, + kFeatureAutoComputeDirtyRects }; - - enum { - KBD_CTRL = 1, - KBD_ALT = 2, - KBD_SHIFT = 4 - }; - + /** - * Data structure for an event. A pointer to an instance of Event - * can be passed to poll_event. + * Determine whether the backend supports the specified feature. */ - struct Event { - EventCode event_code; - struct { - int keycode; - uint16 ascii; - byte flags; - } kbd; - struct { - int x; - int y; - } mouse; - }; + virtual bool hasFeature(Feature f) { return false; } - enum { - PROP_TOGGLE_FULLSCREEN = 1, - PROP_SET_WINDOW_CAPTION, - PROP_OPEN_CD, - PROP_SET_GFX_MODE, - PROP_GET_GFX_MODE, - PROP_GET_SAMPLE_RATE, - PROP_GET_FULLSCREEN, - PROP_GET_FMOPL_ENV_BITS, - PROP_GET_FMOPL_EG_ENT, - PROP_TOGGLE_ASPECT_RATIO, - PROP_TOGGLE_MOUSE_GRAB, - PROP_WANT_RECT_OPTIM, - PROP_HAS_SCALER, - PROP_TOGGLE_VIRTUAL_KEYBOARD - }; - union Property { - const char *caption; - int cd_num; - int gfx_mode; - bool show_cursor; - bool show_keyboard; - }; + /** + * En-/disable the specified feature. For example, this may be used to + * enable fullscreen mode, or to deactivate aspect correction, etc. + */ + virtual void setFeatureState(Feature f, bool enable) {} - enum SoundFormat { - SOUND_8BIT = 0, - SOUND_16BIT = 1 - }; - + /** + * Query the state of the specified feature. For example, test whether + * fullscreen mode is active or not. + */ + virtual bool getFeatureState(Feature f) { return false; } - /** Virtual destructor */ - virtual ~OSystem() {} + //@} /** @name Graphics */ //@{ - /** Set the size of the video bitmap. Typically 320x200 pixels. */ - virtual void init_size(uint w, uint h) = 0; + struct GraphicsMode { + const char *name; + const char *description; + int id; + }; + + /** + * Retrieve a list of all graphics modes supported by this backend. + * This can be both video modes as well as graphic filters/scalers; + * it is completely up to the backend maintainer to decide what is + * appropriate here and what not. + * The list is terminated by an all-zero entry. + * @return a list of supported graphics modes + */ + virtual const GraphicsMode *getSupportedGraphicsModes() const = 0; + + /** + * Switch to the specified graphics mode. If switching to the new mode + * failed, this method returns false. + * @param mode the ID of the new graphics mode + * @return true if the switch was successful, false otherwise + */ + virtual bool setGraphicsMode(int mode) = 0; + + /** + * Switch to the graphics mode with the given name. If 'name' is unknown, + * or if switching to the new mode failed, this method returns false. + * @param mode the name of the new graphics mode + * @return true if the switch was successful, false otherwise + */ + virtual bool setGraphicsMode(const char *name); + + /** + * Determine which graphics mode is currently active. + * @return the active graphics mode + */ + virtual int getGraphicsMode() const = 0; + + /** + * Set the size of the video bitmap. Typical sizes include: + * - 320x200 (e.g. for most SCUMM games, and Simon) + * - 320x240 (e.g. for FM-TOWN SCUMM games) + * - 640x480 (e.g. for Curse of Monkey Island) + */ + virtual void initSize(uint w, uint h) = 0; /** * Returns the currently set screen height. - * @see init_size + * @see initSize * @return the currently set screen height */ virtual int16 get_height() = 0; /** * Returns the currently set screen width. - * @see init_size + * @see initSize * @return the currently set screen width */ virtual int16 get_width() = 0; @@ -220,6 +231,50 @@ public: /** @name Events and Time */ //@{ + typedef int (*TimerProc)(int interval); + + /** + * The types of events backends can generate. + * @see Event + */ + enum EventCode { + EVENT_KEYDOWN = 1, + EVENT_KEYUP = 2, + EVENT_MOUSEMOVE = 3, + EVENT_LBUTTONDOWN = 4, + EVENT_LBUTTONUP = 5, + EVENT_RBUTTONDOWN = 6, + EVENT_RBUTTONUP = 7, + EVENT_WHEELUP = 8, + EVENT_WHEELDOWN = 9, + + EVENT_QUIT = 10, + EVENT_SCREEN_CHANGED = 11 + }; + + enum { + KBD_CTRL = 1, + KBD_ALT = 2, + KBD_SHIFT = 4 + }; + + /** + * Data structure for an event. A pointer to an instance of Event + * can be passed to poll_event. + */ + struct Event { + EventCode event_code; + struct { + int keycode; + uint16 ascii; + byte flags; + } kbd; + struct { + int x; + int y; + } mouse; + }; + /** Get the number of milliseconds since the program was started. */ virtual uint32 get_msecs() = 0; @@ -242,22 +297,30 @@ public: /** @name Sound */ //@{ + typedef void (*SoundProc)(void *param, byte *buf, int len); + /** * Set the audio callback which is invoked whenever samples need to be generated. * Currently, only the 16-bit signed mode is ever used for Simon & Scumm * @param proc pointer to the callback. * @param param an arbitrary parameter which is stored and passed to proc. - * @param format the sample type format. */ - virtual bool set_sound_proc(SoundProc proc, void *param, SoundFormat format) = 0; + virtual bool setSoundCallback(SoundProc proc, void *param) = 0; /** - * Remove any audio callback previously set via set_sound_proc, thus effectively + * Remove any audio callback previously set via setSoundCallback, thus effectively * stopping all audio output immediately. - * @see set_sound_proc + * @see setSoundCallback */ - virtual void clear_sound_proc() = 0; - //@} + virtual void clearSoundCallback() = 0; + + /** + * Determine the output sample rate. Audio data provided by the sound + * callback will be played using this rate. + * @return the output sample rate + */ + virtual int getOutputSampleRate() const = 0; + //@} @@ -268,7 +331,13 @@ public: //@{ /** - * Poll CD status + * Initialise the specified CD drive for audio playback. + * @return true if the CD drive was inited succesfully + */ + virtual bool openCD(int drive) = 0; + + /** + * Poll CD status. * @return true if CD audio is playing */ virtual bool poll_cdrom() = 0; @@ -283,20 +352,24 @@ public: virtual void play_cdrom(int track, int num_loops, int start_frame, int duration) = 0; /** - // Stop audio CD playback + * Stop audio CD playback. */ virtual void stop_cdrom() = 0; /** - // Update cdrom audio status + * Update cdrom audio status. */ virtual void update_cdrom() = 0; + //@} /** @name Mutex handling */ //@{ + + typedef struct Mutex *MutexRef; + /** * Create a new mutex. * @return the newly created mutex, or 0 if an error occured. @@ -341,12 +414,16 @@ public: /** @name Miscellaneous */ //@{ - /** Get or set a backend property. */ - virtual uint32 property(int param, Property *value) = 0; - /** Quit (exit) the application. */ virtual void quit() = 0; + /** + * Set a window caption or any other comparable status display to the + * given value. + * @param caption the window caption to use from now on + */ + virtual void setWindowCaption(const char *caption) {} + /** Savefile management. */ virtual SaveFileManager *get_savefile_manager() { return new SaveFileManager(); @@ -355,6 +432,7 @@ public: }; /** The global OSystem instance. Inited in main(). */ -extern OSystem *g_system; +#define g_system (OSystem::instance()) + #endif diff --git a/gui/options.cpp b/gui/options.cpp index 0b56991b1e..cb42735246 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -77,15 +77,11 @@ void OptionsDialog::open() { _gfxPopUp->setEnabled(false); if (ConfMan.hasKey("gfx_mode", _domain)) { - const GraphicsMode *gm = g_gfx_modes; + const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes(); String gfxMode = ConfMan.get("gfx_mode", _domain); int gfxCount = 1; while (gm->name) { - OSystem::Property prop; - prop.gfx_mode = gm->id; - - if (g_system->property(OSystem::PROP_HAS_SCALER, &prop) != 0) - gfxCount++; + gfxCount++; if (scumm_stricmp(gm->name, gfxMode.c_str()) == 0) _gfxPopUp->setSelected(gfxCount); @@ -255,7 +251,7 @@ void OptionsDialog::setVolumeSettingsState(bool enabled) { int OptionsDialog::addGraphicControls(GuiObject *boss, int yoffset) { const int x = 10; const int w = _w - 2 * 10; - const GraphicsMode *gm = g_gfx_modes; + const OSystem::GraphicsMode *gm = g_system->getSupportedGraphicsModes(); // The GFX mode popup _gfxPopUp = new PopUpWidget(boss, x-5, yoffset, w+5, kLineHeight, "Graphics mode: ", 100); @@ -263,17 +259,10 @@ int OptionsDialog::addGraphicControls(GuiObject *boss, int yoffset) { _gfxPopUp->appendEntry(""); _gfxPopUp->appendEntry(""); - while (gm->name) { - OSystem::Property prop; - prop.gfx_mode = gm->id; - - if (g_system->property(OSystem::PROP_HAS_SCALER, &prop) != 0) { - _gfxPopUp->appendEntry(gm->name, gm->id); - - } - - gm++; - } + while (gm->name) { + _gfxPopUp->appendEntry(gm->name, gm->id); + gm++; + } // Fullscreen checkbox _fullscreenCheckbox = new CheckboxWidget(boss, x, yoffset, w, 16, "Fullscreen mode"); diff --git a/queen/queen.cpp b/queen/queen.cpp index 8e105126bc..52ab3a9b82 100644 --- a/queen/queen.cpp +++ b/queen/queen.cpp @@ -97,7 +97,7 @@ QueenEngine::QueenEngine(GameDetector *detector, OSystem *syst) _mixer->setVolume(ConfMan.getInt("sfx_volume")); - _system->init_size(GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT); + _system->initSize(GAME_SCREEN_WIDTH, GAME_SCREEN_HEIGHT); } QueenEngine::~QueenEngine() { diff --git a/scumm/dialogs.cpp b/scumm/dialogs.cpp index e663085cfe..ce7884eb48 100644 --- a/scumm/dialogs.cpp +++ b/scumm/dialogs.cpp @@ -321,9 +321,7 @@ MainMenuDialog::~MainMenuDialog() { } void MainMenuDialog::open() { - OSystem::Property prop; - prop.show_keyboard = true; - g_system->property(OSystem::PROP_TOGGLE_VIRTUAL_KEYBOARD, &prop); + g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); ScummDialog::open(); } @@ -360,12 +358,9 @@ void MainMenuDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 dat } void MainMenuDialog::close() { - OSystem::Property prop; - ScummDialog::close(); - prop.show_keyboard = false; - g_system->property(OSystem::PROP_TOGGLE_VIRTUAL_KEYBOARD, &prop); + g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); } void MainMenuDialog::save() { diff --git a/scumm/player_mod.cpp b/scumm/player_mod.cpp index 2c4d197c63..64ad8e4eae 100644 --- a/scumm/player_mod.cpp +++ b/scumm/player_mod.cpp @@ -31,7 +31,7 @@ namespace Scumm { Player_MOD::Player_MOD(ScummEngine *scumm) { int i; _mixer = scumm->_mixer; - _samplerate = scumm->_system->property(OSystem::PROP_GET_SAMPLE_RATE, 0); + _samplerate = scumm->_system->getOutputSampleRate(); _mixamt = 0; _mixpos = 0; diff --git a/scumm/player_v2.cpp b/scumm/player_v2.cpp index e44cb7ae98..53d9b88cee 100644 --- a/scumm/player_v2.cpp +++ b/scumm/player_v2.cpp @@ -348,7 +348,7 @@ Player_V2::Player_V2(ScummEngine *scumm, bool pcjr) { _vm = scumm; _system = scumm->_system; _mixer = scumm->_mixer; - _sample_rate = _system->property(OSystem::PROP_GET_SAMPLE_RATE, 0); + _sample_rate = _system->getOutputSampleRate(); _mutex = _system->create_mutex(); _header_len = (scumm->_features & GF_OLD_BUNDLE) ? 4 : 6; diff --git a/scumm/scummvm.cpp b/scumm/scummvm.cpp index 4154bfb7c1..a66c7a8c1d 100644 --- a/scumm/scummvm.cpp +++ b/scumm/scummvm.cpp @@ -314,7 +314,6 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS _features(gs.features), gdi(this), _pauseDialog(0), _optionsDialog(0), _mainMenuDialog(0), _targetName(detector->_targetName) { - OSystem::Property prop; // Init all vars - maybe now we can get rid of our custom new/delete operators? _imuse = NULL; @@ -666,10 +665,10 @@ ScummEngine::ScummEngine(GameDetector *detector, OSystem *syst, const ScummGameS } // Initialize backend - syst->init_size(_screenWidth, _screenHeight); - prop.cd_num = ConfMan.getInt("cdrom"); - if (prop.cd_num >= 0 && (_features & GF_AUDIOTRACKS)) - syst->property(OSystem::PROP_OPEN_CD, &prop); + syst->initSize(_screenWidth, _screenHeight); + int cd_num = ConfMan.getInt("cdrom"); + if (cd_num >= 0 && (_features & GF_AUDIOTRACKS)) + syst->openCD(cd_num); // Setup GDI object gdi._numStrips = _screenWidth / 8; diff --git a/simon/items.cpp b/simon/items.cpp index 828f5ab89d..32ec73de41 100644 --- a/simon/items.cpp +++ b/simon/items.cpp @@ -731,22 +731,16 @@ int SimonEngine::runScript() { break; case 132:{ /* save game */ - OSystem::Property prop; - prop.show_keyboard = true; - _system->property(OSystem::PROP_TOGGLE_VIRTUAL_KEYBOARD, &prop); + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); o_save_game(); - prop.show_keyboard = false; - _system->property(OSystem::PROP_TOGGLE_VIRTUAL_KEYBOARD, &prop); + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); } break; case 133:{ /* load game */ - OSystem::Property prop; - prop.show_keyboard = true; - _system->property(OSystem::PROP_TOGGLE_VIRTUAL_KEYBOARD, &prop); + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); o_load_game(); - prop.show_keyboard = false; - _system->property(OSystem::PROP_TOGGLE_VIRTUAL_KEYBOARD, &prop); + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); } break; @@ -757,12 +751,9 @@ int SimonEngine::runScript() { break; case 135:{ /* quit if user presses y */ - OSystem::Property prop; - prop.show_keyboard = true; - _system->property(OSystem::PROP_TOGGLE_VIRTUAL_KEYBOARD, &prop); + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); o_quit_if_user_presses_y(); - prop.show_keyboard = false; - _system->property(OSystem::PROP_TOGGLE_VIRTUAL_KEYBOARD, &prop); + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); } break; diff --git a/simon/simon.cpp b/simon/simon.cpp index dac8e1bc8f..dca760e181 100644 --- a/simon/simon.cpp +++ b/simon/simon.cpp @@ -585,10 +585,10 @@ SimonEngine::SimonEngine(GameDetector *detector, OSystem *syst) if (ConfMan.hasKey("slow_down") && ConfMan.getInt("slow_down") >= 1) _speed = ConfMan.getInt("slow_down"); - _system->init_size(320, 200); + _system->initSize(320, 200); // FIXME Use auto dirty rects cleanup code to reduce CPU usage - _system->property(OSystem::PROP_WANT_RECT_OPTIM,0); + g_system->setFeatureState(OSystem::kFeatureAutoComputeDirtyRects, true); } SimonEngine::~SimonEngine() { @@ -2888,9 +2888,7 @@ get_out:; delay(10); } while (i == _timer_4); - OSystem::Property prop; - prop.show_keyboard = false; - g_system->property(OSystem::PROP_TOGGLE_VIRTUAL_KEYBOARD, &prop); + g_system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); } void SimonEngine::o_file_error(FillOrCopyStruct *fcs, bool save_error) { diff --git a/sky/control.cpp b/sky/control.cpp index dbeff2c5e5..61def9a1ce 100644 --- a/sky/control.cpp +++ b/sky/control.cpp @@ -803,11 +803,9 @@ uint16 Control::saveRestorePanel(bool allowSave) { uint16 cnt; uint8 lookListLen; if (allowSave) { - OSystem::Property prop; lookList = _savePanLookList; lookListLen = 6; - prop.show_keyboard = true; - _system->property(OSystem::PROP_TOGGLE_VIRTUAL_KEYBOARD, &prop); + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); } else { lookList = _restorePanLookList; if (autoSaveExists()) @@ -915,9 +913,7 @@ uint16 Control::saveRestorePanel(bool allowSave) { free(saveGameTexts); if (allowSave) { - OSystem::Property prop; - prop.show_keyboard = false; - _system->property(OSystem::PROP_TOGGLE_VIRTUAL_KEYBOARD, &prop); + _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, false); } return clickRes; diff --git a/sky/music/adlibmusic.cpp b/sky/music/adlibmusic.cpp index 0f605b2a65..5a0a8d468b 100644 --- a/sky/music/adlibmusic.cpp +++ b/sky/music/adlibmusic.cpp @@ -33,16 +33,13 @@ void AdlibMusic::passMixerFunc(void *param, int16 *buf, uint len) { AdlibMusic::AdlibMusic(SoundMixer *pMixer, Disk *pDisk, OSystem *system) : MusicBase(pDisk, system) { - + _driverFileBase = 60202; _mixer = pMixer; _sampleRate = pMixer->getOutputRate(); + + _opl = makeAdlibOPL(_sampleRate); - int env_bits = g_system->property(OSystem::PROP_GET_FMOPL_ENV_BITS, NULL); - int eg_ent = g_system->property(OSystem::PROP_GET_FMOPL_EG_ENT, NULL); - OPLBuildTables((env_bits ? env_bits : FMOPL_ENV_BITS_HQ), (eg_ent ? eg_ent : FMOPL_EG_ENT_HQ)); - _opl = OPLCreate(OPL_TYPE_YM3812, 3579545, _sampleRate); - _mixer->setupPremix(passMixerFunc, this); } diff --git a/sky/screen.cpp b/sky/screen.cpp index a6bced09f2..b471bbed28 100644 --- a/sky/screen.cpp +++ b/sky/screen.cpp @@ -57,7 +57,7 @@ Screen::Screen(OSystem *pSystem, Disk *pDisk) { int i; uint8 tmpPal[1024]; - _system->init_size(FULL_SCREEN_WIDTH, FULL_SCREEN_HEIGHT); + _system->initSize(FULL_SCREEN_WIDTH, FULL_SCREEN_HEIGHT); _gameGrid = (uint8 *)malloc(GRID_X * GRID_Y * 2); forceRefresh(); diff --git a/sky/sky.cpp b/sky/sky.cpp index 5556e1c500..f149e4988c 100644 --- a/sky/sky.cpp +++ b/sky/sky.cpp @@ -127,7 +127,7 @@ SkyEngine::SkyEngine(GameDetector *detector, OSystem *syst) _fastMode = 0; - _system->init_size(320, 200); + _system->initSize(320, 200); } SkyEngine::~SkyEngine() { diff --git a/sound/fmopl.cpp b/sound/fmopl.cpp index 8b34779da6..60dacbfc33 100644 --- a/sound/fmopl.cpp +++ b/sound/fmopl.cpp @@ -1117,3 +1117,27 @@ int OPLTimerOver(FM_OPL *OPL, int c) { (OPL->TimerHandler)(OPL->TimerParam + c, (double)OPL->T[c] * OPL->TimerBase); return OPL->status >> 7; } + +FM_OPL *makeAdlibOPL(int rate) { + // We need to emulate one YM3812 chip + int env_bits = FMOPL_ENV_BITS_HQ; + int eg_ent = FMOPL_EG_ENT_HQ; +#ifdef _WIN32_WCE + // TODO: On WinCE, use low quality FMOPL by default. + // FIXME: Don't use 'CE_' or similar prefixes if you need platform specific + // config keys. Rather use a seperate config domain - e.g. for WinCE we have + // two such domains already, "wince" and "smartfon-keys" (although I wonder + // a bit about the latter one). + if (ConfMan.getBool("CE_FM_high_quality")) + env_bits = FMOPL_ENV_BITS_HQ; + else + env_bits = FMOPL_ENV_BITS_LQ; + + if (ConfMan.getBool("CE_FM_high_quality")) + eg_ent = FMOPL_EG_ENT_HQ; + else + eg_ent = FMOPL_EG_ENT_LQ; +#endif + OPLBuildTables(env_bits, eg_ent); + return OPLCreate(OPL_TYPE_YM3812, 3579545, rate); +} diff --git a/sound/fmopl.h b/sound/fmopl.h index 65a1a47b05..509f0abc80 100644 --- a/sound/fmopl.h +++ b/sound/fmopl.h @@ -159,3 +159,6 @@ int OPLTimerOver(FM_OPL *OPL, int c); void OPLWriteReg(FM_OPL *OPL, int r, int v); void YM3812UpdateOne(FM_OPL *OPL, int16 *buffer, int length); #endif + +// Factory method +FM_OPL *makeAdlibOPL(int rate); diff --git a/sound/mixer.cpp b/sound/mixer.cpp index c7260ee02e..afe31813f4 100644 --- a/sound/mixer.cpp +++ b/sound/mixer.cpp @@ -111,7 +111,7 @@ SoundMixer::SoundMixer() { _premixProc = 0; int i = 0; - _outputRate = (uint) _syst->property(OSystem::PROP_GET_SAMPLE_RATE, 0); + _outputRate = (uint) _syst->getOutputSampleRate(); if (_outputRate == 0) error("OSystem returned invalid sample rate"); @@ -124,11 +124,11 @@ SoundMixer::SoundMixer() { for (i = 0; i != NUM_CHANNELS; i++) _channels[i] = 0; - _mixerReady = _syst->set_sound_proc(mixCallback, this, OSystem::SOUND_16BIT); + _mixerReady = _syst->setSoundCallback(mixCallback, this); } SoundMixer::~SoundMixer() { - _syst->clear_sound_proc(); + _syst->clearSoundCallback(); stopAll(); _syst->delete_mutex(_mutex); } diff --git a/sword1/sword1.cpp b/sword1/sword1.cpp index 13927327c8..517a403366 100644 --- a/sword1/sword1.cpp +++ b/sword1/sword1.cpp @@ -97,7 +97,7 @@ SwordEngine::~SwordEngine() { } void SwordEngine::initialize(void) { - _system->init_size(640, 480); + _system->initSize(640, 480); debug(5, "Starting memory manager"); _memMan = new MemMan(); debug(5, "Starting resource manager"); diff --git a/sword2/driver/d_draw.cpp b/sword2/driver/d_draw.cpp index f4462f695f..934e82bfde 100644 --- a/sword2/driver/d_draw.cpp +++ b/sword2/driver/d_draw.cpp @@ -39,7 +39,7 @@ Graphics::Graphics(Sword2Engine *vm, int16 width, int16 height) if (!_buffer) error("Could not initialise display"); - _vm->_system->init_size(width, height); + _vm->_system->initSize(width, height); _gridWide = width / CELLWIDE; _gridDeep = height / CELLDEEP; diff --git a/sword2/driver/rdwin.cpp b/sword2/driver/rdwin.cpp index 28f00003d8..cf7f5f0ff9 100644 --- a/sword2/driver/rdwin.cpp +++ b/sword2/driver/rdwin.cpp @@ -147,10 +147,7 @@ void Graphics::updateDisplay(bool redrawScene) { */ void Graphics::setWindowName(const char *windowName) { - OSystem::Property prop; - - prop.caption = windowName; - _vm->_system->property(OSystem::PROP_SET_WINDOW_CAPTION, &prop); + _vm->_system->setWindowCaption(windowName); } } // End of namespace Sword2 -- cgit v1.2.3