Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

osys_psp.cpp

/* ScummVM - Graphic Adventure Engine
 *
 * ScummVM is the legal property of its developers, whose names
 * are too numerous to list here. Please refer to the COPYRIGHT
 * file distributed with this source distribution.
 *
 * 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.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-1-2-1/backends/platform/psp/osys_psp.cpp $
 * $Id: osys_psp.cpp 50116 2010-06-21 15:13:36Z Bluddy $
 *
 */

#include <pspuser.h>
#include <pspgu.h>
#include <pspdisplay.h>

#include <time.h>
#include <zlib.h>

#include "common/config-manager.h"
#include "common/events.h"
#include "common/scummsys.h"

#include "backends/platform/psp/psppixelformat.h"
#include "backends/platform/psp/osys_psp.h"
#include "backends/platform/psp/powerman.h"
#include "backends/platform/psp/rtc.h"

#include "backends/saves/psp/psp-saves.h"
#include "backends/timer/default/default-timer.h"
#include "graphics/surface.h"
#include "sound/mixer_intern.h"

//#define __PSP_DEBUG_FUNCS__ /* For debugging function calls */
//#define __PSP_DEBUG_PRINT__ /* For debug printouts */

#include "backends/platform/psp/trace.h"

#define     SAMPLES_PER_SEC   44100

static int timer_handler(int t) {
      DefaultTimerManager *tm = (DefaultTimerManager *)g_system->getTimerManager();
      tm->handler();
      return t;
}

OSystem_PSP::~OSystem_PSP() {}

#define PSP_SCREEN_WIDTH 480
#define PSP_SCREEN_HEIGHT 272

00065 void OSystem_PSP::initBackend() {
      DEBUG_ENTER_FUNC();

      // Instantiate real time clock
      PspRtc::instance();
      
      _cursor.enableCursorPalette(false);
      _cursor.setXY(PSP_SCREEN_WIDTH >> 1, PSP_SCREEN_HEIGHT >> 1);     // Mouse in the middle of the screen

      // Set pointers for display manager
      _displayManager.setCursor(&_cursor);
      _displayManager.setScreen(&_screen);
      _displayManager.setOverlay(&_overlay);
      _displayManager.setKeyboard(&_keyboard);
      _displayManager.init();

      // Set pointers for input handler
      _inputHandler.setCursor(&_cursor);
      _inputHandler.setKeyboard(&_keyboard);
      _inputHandler.init();

      _savefile = new PSPSaveFileManager;

      _timer = new DefaultTimerManager();

      PSP_DEBUG_PRINT("calling keyboard.load()\n");
      _keyboard.load(); // Load virtual keyboard files into memory

      setTimerCallback(&timer_handler, 10);

      setupMixer();

      OSystem::initBackend();
}

00100 bool OSystem_PSP::hasFeature(Feature f) {
      return (f == kFeatureOverlaySupportsAlpha || f == kFeatureCursorHasPalette);
}

00104 void OSystem_PSP::setFeatureState(Feature f, bool enable) {
}

00107 bool OSystem_PSP::getFeatureState(Feature f) {
      return false;
}

00111 const OSystem::GraphicsMode* OSystem_PSP::getSupportedGraphicsModes() const {
      return _displayManager.getSupportedGraphicsModes();
}

00115 int OSystem_PSP::getDefaultGraphicsMode() const {
      DEBUG_ENTER_FUNC();
      return _displayManager.getDefaultGraphicsMode();
}

00120 bool OSystem_PSP::setGraphicsMode(int mode) {
      DEBUG_ENTER_FUNC();
      _pendingUpdate = false;
      return _displayManager.setGraphicsMode(mode);
}

00126 bool OSystem_PSP::setGraphicsMode(const char *name) {
      DEBUG_ENTER_FUNC();
      _pendingUpdate = false;
      return _displayManager.setGraphicsMode(name);
}

00132 int OSystem_PSP::getGraphicsMode() const {
      DEBUG_ENTER_FUNC();
      return _displayManager.getGraphicsMode();
}

#ifdef USE_RGB_COLOR

Graphics::PixelFormat OSystem_PSP::getScreenFormat() const {
      return _screen.getScummvmPixelFormat();
}

Common::List<Graphics::PixelFormat> OSystem_PSP::getSupportedFormats() const {
      return _displayManager.getSupportedPixelFormats();
}

#endif

00149 void OSystem_PSP::initSize(uint width, uint height, const Graphics::PixelFormat *format) {
      DEBUG_ENTER_FUNC();
      _pendingUpdate = false; 
      _displayManager.setSizeAndPixelFormat(width, height, format);

      _cursor.setVisible(false);
      _cursor.setLimits(_screen.getWidth(), _screen.getHeight());
}

00158 int16 OSystem_PSP::getWidth() {
      DEBUG_ENTER_FUNC();
      return (int16)_screen.getWidth();
}

00163 int16 OSystem_PSP::getHeight() {
      DEBUG_ENTER_FUNC();
      return (int16)_screen.getHeight();
}

00168 void OSystem_PSP::setPalette(const byte *colors, uint start, uint num) {
      DEBUG_ENTER_FUNC();
      _pendingUpdate = false; 
      _screen.setPartialPalette(colors, start, num);
      _cursor.setScreenPalette(colors, start, num);
      _cursor.clearKeyColor();
}

00176 void OSystem_PSP::setCursorPalette(const byte *colors, uint start, uint num) {
      DEBUG_ENTER_FUNC();
      _pendingUpdate = false; 
      _cursor.setCursorPalette(colors, start, num);
      _cursor.enableCursorPalette(true);
      _cursor.clearKeyColor();      // Do we need this?
}

00184 void OSystem_PSP::disableCursorPalette(bool disable) {
      DEBUG_ENTER_FUNC();
      _pendingUpdate = false; 
      _cursor.enableCursorPalette(!disable);
}

00190 void OSystem_PSP::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {
      DEBUG_ENTER_FUNC();
      _pendingUpdate = false; 
      _screen.copyFromRect(buf, pitch, x, y, w, h);
}

00196 Graphics::Surface *OSystem_PSP::lockScreen() {
      DEBUG_ENTER_FUNC();
      _pendingUpdate = false; 
      return _screen.lockAndGetForEditing();
}

00202 void OSystem_PSP::unlockScreen() {
      DEBUG_ENTER_FUNC();
      _pendingUpdate = false; 
      // The screen is always completely updated anyway, so we don't have to force a full update here.
      _screen.unlock();
}

00209 void OSystem_PSP::updateScreen() {
      DEBUG_ENTER_FUNC();
      _pendingUpdate = !_displayManager.renderAll();  // if we didn't update, we have a pending update
}

00214 void OSystem_PSP::setShakePos(int shakeOffset) {
      DEBUG_ENTER_FUNC();
      _pendingUpdate = false;
      _screen.setShakePos(shakeOffset);
}

00220 void OSystem_PSP::showOverlay() {
      DEBUG_ENTER_FUNC();
      _pendingUpdate = false; 
      _overlay.setVisible(true);
      _cursor.setLimits(_overlay.getWidth(), _overlay.getHeight());
      _cursor.useGlobalScaler(false);     // mouse with overlay is 1:1
}

00228 void OSystem_PSP::hideOverlay() {
      DEBUG_ENTER_FUNC();
      _pendingUpdate = false; 
      _overlay.setVisible(false);
      _cursor.setLimits(_screen.getWidth(), _screen.getHeight());
      _cursor.useGlobalScaler(true);      // mouse needs to be scaled with screen
}

00236 void OSystem_PSP::clearOverlay() {
      DEBUG_ENTER_FUNC();
      _pendingUpdate = false; 
      _overlay.clearBuffer();
}

00242 void OSystem_PSP::grabOverlay(OverlayColor *buf, int pitch) {
      DEBUG_ENTER_FUNC();
      _overlay.copyToArray(buf, pitch);
}

00247 void OSystem_PSP::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
      DEBUG_ENTER_FUNC();
      _pendingUpdate = false; 
      _overlay.copyFromRect(buf, pitch, x, y, w, h);
}

00253 int16 OSystem_PSP::getOverlayWidth() {
      return (int16) _overlay.getWidth();
}

00257 int16 OSystem_PSP::getOverlayHeight() {
      return (int16) _overlay.getHeight();
}

00261 void OSystem_PSP::grabPalette(byte *colors, uint start, uint num) {
      DEBUG_ENTER_FUNC();
      _screen.getPartialPalette(colors, start, num);
}

00266 bool OSystem_PSP::showMouse(bool v) {
      DEBUG_ENTER_FUNC();
      _pendingUpdate = false;
      
      PSP_DEBUG_PRINT("%s\n", v ? "true" : "false");
      bool last = _cursor.isVisible();
      _cursor.setVisible(v);

      return last;
}

00277 void OSystem_PSP::warpMouse(int x, int y) {
      DEBUG_ENTER_FUNC();
      _pendingUpdate = false; 
      _cursor.setXY(x, y);
}

00283 void OSystem_PSP::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) {
      DEBUG_ENTER_FUNC();
      _pendingUpdate = false; 
      
      PSP_DEBUG_PRINT("pbuf[%p], w[%u], h[%u], hotspot:X[%d], Y[%d], keycolor[%d], scale[%d], pformat[%p]\n", buf, w, h, hotspotX, hotspotY, keycolor, cursorTargetScale, format);
      if (format) {
            PSP_DEBUG_PRINT("format: bpp[%d], rLoss[%d], gLoss[%d], bLoss[%d], aLoss[%d], rShift[%d], gShift[%d], bShift[%d], aShift[%d]\n", format->bytesPerPixel, format->rLoss, format->gLoss, format->bLoss, format->aLoss, format->rShift, format->gShift, format->bShift, format->aShift);
      }

      _cursor.setKeyColor(keycolor);
      _cursor.setCursorTargetScale(cursorTargetScale);
      _cursor.setSizeAndScummvmPixelFormat(w, h, format);
      _cursor.setHotspot(hotspotX, hotspotY);
      _cursor.clearKeyColor();
      _cursor.copyFromArray(buf);
}

00300 bool OSystem_PSP::pollEvent(Common::Event &event) {

      // If we're polling for events, we should check for pausing the engine
      // Pausing the engine is a necessary fix for games that use the timer for music synchronization
      //    recovering many hours later causes the game to crash. We're polling without mutexes since it's not critical to
      //  get it right now.
      PowerMan.pollPauseEngine();

      // A hack:
      // Check if we have a pending update that we missed for some reason (FPS throttling for example)
      // Time between event polls is usually 5-10ms, so waiting for 4 calls before checking to update the screen should be fine
      if (_pendingUpdate) {
            _pendingUpdateCounter++;
            
            if (_pendingUpdateCounter >= 4) {
                  PSP_DEBUG_PRINT("servicing pending update\n");
                  updateScreen();
                  if (!_pendingUpdate)    // we handled the update
                        _pendingUpdateCounter = 0;                      
            }
      } else 
            _pendingUpdateCounter = 0;    // reset the counter, no pending
            
      return _inputHandler.getAllInputs(event);
}

00326 uint32 OSystem_PSP::getMillis() {
      return PspRtc::instance().getMillis();
}

00330 void OSystem_PSP::delayMillis(uint msecs) {
      PspThread::delayMillis(msecs);
}

void OSystem_PSP::setTimerCallback(TimerProc callback, int interval) {
      _pspTimer.setCallback((PspTimer::CallbackFunc)callback);
      _pspTimer.setIntervalMs(interval);
      _pspTimer.start();
}

00340 OSystem::MutexRef OSystem_PSP::createMutex(void) {
      return (MutexRef) new PspMutex(true);     // start with a full mutex
}

00344 void OSystem_PSP::lockMutex(MutexRef mutex) {
      ((PspMutex *)mutex)->lock();
}

00348 void OSystem_PSP::unlockMutex(MutexRef mutex) {
      ((PspMutex *)mutex)->unlock();
}

00352 void OSystem_PSP::deleteMutex(MutexRef mutex) {
      delete (PspMutex *)mutex;
}

void OSystem_PSP::mixCallback(void *sys, byte *samples, int len) {
      OSystem_PSP *this_ = (OSystem_PSP *)sys;
      assert(this_);

      if (this_->_mixer)
            this_->_mixer->mixCallback(samples, len);
}

void OSystem_PSP::setupMixer(void) {

      // Determine the desired output sampling frequency.
      uint32 samplesPerSec = 0;
      if (ConfMan.hasKey("output_rate"))
            samplesPerSec = ConfMan.getInt("output_rate");
      if (samplesPerSec <= 0)
            samplesPerSec = SAMPLES_PER_SEC;

      // Determine the sample buffer size. We want it to store enough data for
      // at least 1/16th of a second (though at most 8192 samples). Note
      // that it must be a power of two. So e.g. at 22050 Hz, we request a
      // sample buffer size of 2048.
      uint32 samples = 8192;
      while (samples * 16 > samplesPerSec * 2)
            samples >>= 1;

      assert(!_mixer);

      if (!_audio.open(samplesPerSec, 2, samples, mixCallback, this)) {
            PSP_ERROR("failed to open audio\n");
            return;
      }
      samplesPerSec = _audio.getFrequency();    // may have been changed by audio system
      _mixer = new Audio::MixerImpl(this, samplesPerSec);
      assert(_mixer);
      _mixer->setReady(true);
      _audio.unpause();
}

00394 void OSystem_PSP::quit() {
      _audio.close();
      sceKernelExitGame();
}

00399 void OSystem_PSP::getTimeAndDate(TimeDate &td) const {
      time_t curTime = time(0);
      struct tm t = *localtime(&curTime);
      td.tm_sec = t.tm_sec;
      td.tm_min = t.tm_min;
      td.tm_hour = t.tm_hour;
      td.tm_mday = t.tm_mday;
      td.tm_mon = t.tm_mon;
      td.tm_year = t.tm_year;
}

#define PSP_CONFIG_FILE "ms0:/scummvm.ini"

00412 Common::SeekableReadStream *OSystem_PSP::createConfigReadStream() {
      Common::FSNode file(PSP_CONFIG_FILE);
      return file.createReadStream();
}

00417 Common::WriteStream *OSystem_PSP::createConfigWriteStream() {
      Common::FSNode file(PSP_CONFIG_FILE);
      return file.createWriteStream();
}

Generated by  Doxygen 1.6.0   Back to index