From 59739a7a0e3e4826ba7b27d5270a8d7a26b787ef Mon Sep 17 00:00:00 2001 From: Chris Warren-Smith Date: Sun, 7 Aug 2011 21:33:32 +1000 Subject: BADA: Initial BADA port implementation --- backends/platform/bada/README.TXT | 79 ++++++ backends/platform/bada/application.cpp | 128 +++++++++ backends/platform/bada/application.h | 58 ++++ backends/platform/bada/audio.cpp | 256 +++++++++++++++++ backends/platform/bada/audio.h | 73 +++++ backends/platform/bada/bada.mk | 5 + backends/platform/bada/form.cpp | 442 +++++++++++++++++++++++++++++ backends/platform/bada/form.h | 108 +++++++ backends/platform/bada/fs.cpp | 428 ++++++++++++++++++++++++++++ backends/platform/bada/fs.h | 82 ++++++ backends/platform/bada/graphics.cpp | 309 ++++++++++++++++++++ backends/platform/bada/graphics.h | 72 +++++ backends/platform/bada/main.cpp | 70 +++++ backends/platform/bada/missing.cpp | 113 ++++++++ backends/platform/bada/portdefs.h | 84 ++++++ backends/platform/bada/sscanf.cpp | 182 ++++++++++++ backends/platform/bada/system.cpp | 500 +++++++++++++++++++++++++++++++++ backends/platform/bada/system.h | 101 +++++++ backends/platform/bada/timer.cpp | 124 ++++++++ backends/platform/bada/timer.h | 62 ++++ 20 files changed, 3276 insertions(+) create mode 100755 backends/platform/bada/README.TXT create mode 100755 backends/platform/bada/application.cpp create mode 100755 backends/platform/bada/application.h create mode 100755 backends/platform/bada/audio.cpp create mode 100755 backends/platform/bada/audio.h create mode 100755 backends/platform/bada/bada.mk create mode 100755 backends/platform/bada/form.cpp create mode 100755 backends/platform/bada/form.h create mode 100755 backends/platform/bada/fs.cpp create mode 100755 backends/platform/bada/fs.h create mode 100755 backends/platform/bada/graphics.cpp create mode 100755 backends/platform/bada/graphics.h create mode 100755 backends/platform/bada/main.cpp create mode 100755 backends/platform/bada/missing.cpp create mode 100755 backends/platform/bada/portdefs.h create mode 100755 backends/platform/bada/sscanf.cpp create mode 100755 backends/platform/bada/system.cpp create mode 100755 backends/platform/bada/system.h create mode 100755 backends/platform/bada/timer.cpp create mode 100755 backends/platform/bada/timer.h (limited to 'backends/platform') diff --git a/backends/platform/bada/README.TXT b/backends/platform/bada/README.TXT new file mode 100755 index 0000000000..dd56c8962c --- /dev/null +++ b/backends/platform/bada/README.TXT @@ -0,0 +1,79 @@ +Build instructions: + +1. Install BADA SDK (requires free registration): + + http://developer.bada.com/apis/index.do + +2. Install Cygwin: + + http://www.cygwin.com/ + + Add the following to your cygwin .bash_profile: + + alias mmake=/cygdrive/c/MinGW/bin/mingw32-make.exe + export BADA_SDK=/cygdrive/c/bada/1.2.1 + export ARM_BIN=c:/bada/1.2.1/Tools/Toolchains/ARM/bin + export CPPFLAGS="-fpic -fshort-wchar -mcpu=cortex-a8 -mfpu=vfpv3 \ + -mfloat-abi=hard -mlittle-endian -mthumb-interwork -Wno-psabi \ + -fno-strict-aliasing -fno-short-enums" + export LDFLAGS="-nostdlib -lc-newlib -lm-newlib -LC:/bada/1.2.1/Model/Wave_LP1/Target" + #export PATH=${BADA_SDK}/Tools/Toolchains/Win32/bin:${PATH} + export PATH=${BADA_SDK}/Tools/Toolchains/ARM/bin:~/utils:${PATH} + alias gcc=${ARM_BIN}/arm-samsung-nucleuseabi-gcc.exe + alias ar=${ARM_BIN}/arm-samsung-nucleuseabi-ar.exe + + The following were added to ~/utils for zlib: + + ar: + #!/bin/sh + ${ARM_BIN}/arm-samsung-nucleuseabi-ar.exe $* + + gcc: + #!/bin/sh + ${ARM_BIN}/arm-samsung-nucleuseabi-gcc.exe $* + +3. Build dependencies + + zlib, libogg, libvorbis, libmad, FLAC + + see: "Building the libraries" under: + http://wiki.scummvm.org/index.php/Compiling_ScummVM/MinGW#Building_the_libraries + for instructions on how to obtain these modules + + 3.1 For Target-Release configure ogg and mad with: + + ./configure --host=arm-samsung-nucleuseabi --disable-shared + + when building vorbis and flac: + + ./configure --host=arm-samsung-nucleuseabi --disable-shared --with-ogg=c:/cygwin/usr/local + + 3.2 for each module, after a successful configure, add the following + to the generated config.h (gzguts.h for zlib) + + #undef __MINGW32__ + #undef _WIN32 + #include "c:/src/scummvm/backends/platform/bada/portdefs.h" + + 3.3 Additional post configure edits: + + - removed -fforce-mem from the libMAD Makefile + - in libvorbis/lib/Makefile comment lines with vorbis_selftests + - edit libFLAC/Makefile ... CFLAGS = $(OGG_CFLAGS) + + Note: you can ignore the ranlib errors when doing make install. + +4. Build the ScummVM base library: + + ./configure --host=bada --enable-release + + To target the Win32 simulator: + + ./configure --host=bada --enable-debug + +5. Build the front end application using BADA-Ide: + + Copy the scummvm/dists/bada folder into a clean directory + outside of the scummvm package. Start the BADA IDE then + choose this folder as the eclipse workspace. Click + Project / Build. diff --git a/backends/platform/bada/application.cpp b/backends/platform/bada/application.cpp new file mode 100755 index 0000000000..d5bd1572be --- /dev/null +++ b/backends/platform/bada/application.cpp @@ -0,0 +1,128 @@ +/* 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. + * + */ + +#include "engines/engine.h" + +#include "backends/platform/bada/form.h" +#include "backends/platform/bada/system.h" +#include "backends/platform/bada/application.h" + +using namespace Osp::Base; +using namespace Osp::Base::Runtime; +using namespace Osp::Graphics; +using namespace Osp::Locales; +using namespace Osp::System; +using namespace Osp::App; +using namespace Osp::System; +using namespace Osp::Ui; +using namespace Osp::Ui::Controls; + +Application *BadaScummVM::createInstance() { + return new BadaScummVM(); +} + +BadaScummVM::BadaScummVM() : _appForm(0) { +} + +BadaScummVM::~BadaScummVM() { + logEntered(); + if (g_system) { + BadaSystem *system = (BadaSystem*)g_system; + system->destroyBackend(); + delete system; + g_system = 0; + } +} + +bool BadaScummVM::OnAppInitializing(AppRegistry &appRegistry) { + _appForm = systemStart(this); + return (_appForm != null); +} + +bool BadaScummVM::OnAppTerminating(AppRegistry &appRegistry, + bool forcedTermination) { + logEntered(); + return true; +} + +void BadaScummVM::OnUserEventReceivedN(RequestId requestId, + Osp::Base::Collection::IList *args) { + logEntered(); + + if (requestId == USER_MESSAGE_EXIT) { + // normal program termination + Terminate(); + } else if (requestId == USER_MESSAGE_EXIT_ERR) { + // assertion failure termination + String *message = null; + if (args) { + message = (String*) args->GetAt(0); + } + if (!message) { + message = new String("Unknown error"); + } + + MessageBox messageBox; + messageBox.Construct(L"Oops...", *message, MSGBOX_STYLE_OK); + int modalResult; + messageBox.ShowAndWait(modalResult); + Terminate(); + } +} + +void BadaScummVM::OnForeground(void) { + logEntered(); + pauseGame(false); +} + +void BadaScummVM::OnBackground(void) { + logEntered(); + pauseGame(true); +} + +void BadaScummVM::OnBatteryLevelChanged(BatteryLevel batteryLevel) { +} + +void BadaScummVM::OnLowMemory(void) { +} + +void BadaScummVM::OnScreenOn(void) { + logEntered(); +} + +void BadaScummVM::OnScreenOff(void) { + logEntered(); +} + +void BadaScummVM::pauseGame(bool pause) { + if (pause && _appForm && g_engine && !g_engine->isPaused()) { + _appForm->pushKey(Common::KEYCODE_SPACE); + } + + if (g_system) { + ((BadaSystem*)g_system)->setMute(pause); + } +} + +// +// end of application.cpp +// diff --git a/backends/platform/bada/application.h b/backends/platform/bada/application.h new file mode 100755 index 0000000000..f0de4a2c72 --- /dev/null +++ b/backends/platform/bada/application.h @@ -0,0 +1,58 @@ +/* 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. + * + */ + +#ifndef BADA_APPLICATION_H +#define BADA_APPLICATION_H + +#include +#include +#include +#include +#include + +#include "backends/platform/bada/system.h" + +class BadaScummVM : public Osp::App::Application, + public Osp::System::IScreenEventListener { + +public: + BadaScummVM(); + ~BadaScummVM(); + + static Osp::App::Application *createInstance(void); + + bool OnAppInitializing(Osp::App::AppRegistry &appRegistry); + bool OnAppTerminating(Osp::App::AppRegistry &appRegistry, bool forcedTermination = false); + void OnForeground(void); + void OnBackground(void); + void OnLowMemory(void); + void OnBatteryLevelChanged(Osp::System::BatteryLevel batteryLevel); + void OnScreenOn(void); + void OnScreenOff(void); + void OnUserEventReceivedN(RequestId requestId, Osp::Base::Collection::IList *pArgs); + +private: + void pauseGame(bool pause); + BadaAppForm *_appForm; +}; + +#endif diff --git a/backends/platform/bada/audio.cpp b/backends/platform/bada/audio.cpp new file mode 100755 index 0000000000..3510475b5c --- /dev/null +++ b/backends/platform/bada/audio.cpp @@ -0,0 +1,256 @@ +/* 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. + * + */ + +#include +#include + +#include "backends/platform/bada/audio.h" +#include "backends/platform/bada/system.h" + +#define TIMER_INCREMENT 10 +#define TIMER_INTERVAL 40 +#define MIN_TIMER_INTERVAL 10 +#define MAX_TIMER_INTERVAL 160 +#define INIT_LEVEL 3 +#define CONFIG_KEY L"audiovol" + +// sound level pre-sets +const int levels[] = {0, 1, 10, 45, 70, 99}; + +AudioThread::AudioThread() : + _mixer(0), + _timer(0), + _audioOut(0), + _head(0), + _tail(0), + _ready(0), + _interval(TIMER_INTERVAL), + _playing(-1), + _muted(true) { +} + +Audio::MixerImpl *AudioThread::Construct(OSystem *system) { + logEntered(); + + if (IsFailed(Thread::Construct(THREAD_TYPE_EVENT_DRIVEN))) { + AppLog("Failed to create AudioThread"); + return null; + } + + _mixer = new Audio::MixerImpl(system, 44100); + return _mixer; +} + +AudioThread::~AudioThread() { + logEntered(); +} + +bool AudioThread::isSilentMode() { + bool silentMode; + String key(L"SilentMode"); + Osp::System::SettingInfo::GetValue(key, silentMode); + return silentMode; +} + +void AudioThread::setMute(bool on) { + if (_audioOut && !isSilentMode()) { + _muted = on; + if (on) { + _timer->Cancel(); + } else { + _timer->Start(_interval); + } + } +} + +int AudioThread::setVolume(bool up, bool minMax) { + int level = -1; + int numLevels = sizeof(levels) / sizeof(levels[0]); + + if (_audioOut && !isSilentMode()) { + int volume = _audioOut->GetVolume(); + if (minMax) { + level = up ? numLevels - 1 : 0; + volume = levels[level]; + } else { + // adjust volume to be one of the preset values + for (int i = 0; i < numLevels && level == -1; i++) { + if (volume == levels[i]) { + level = i; + if (up) { + if (i + 1 < numLevels) { + level = i + 1; + } + } else if (i > 0) { + level = i - 1; + } + } + } + + // default to INIT_LEVEL when current not preset value + if (level == -1) { + level = INIT_LEVEL; + } + volume = levels[level]; + } + + _audioOut->SetVolume(volume); + + // remember the chosen setting + AppRegistry *registry = Application::GetInstance()->GetAppRegistry(); + if (registry) { + registry->Set(CONFIG_KEY, volume); + } + } + return level; +} + +bool AudioThread::OnStart(void) { + logEntered(); + + _audioOut = new Osp::Media::AudioOut(); + if (!_audioOut || + IsFailed(_audioOut->Construct(*this))) { + AppLog("Failed to create AudioOut"); + return false; + } + + int sampleRate = _mixer->getOutputRate(); + if (IsFailed(_audioOut->Prepare(AUDIO_TYPE_PCM_S16_LE, + AUDIO_CHANNEL_TYPE_STEREO, + sampleRate))) { + AppLog("Failed to prepare AudioOut %d", sampleRate); + return false; + } + + int bufferSize = _audioOut->GetMinBufferSize(); + AppLog("bufferSize = %d", bufferSize); + + for (int i = 0; i < NUM_AUDIO_BUFFERS; i++) { + if (IsFailed(_audioBuffer[i].Construct(bufferSize))) { + AppLog("Failed to create audio buffer"); + return false; + } + } + + _timer = new Timer(); + if (!_timer || IsFailed(_timer->Construct(*this))) { + AppLog("Failed to create audio timer"); + return false; + } + + if (IsFailed(_timer->Start(_interval))) { + AppLog("failed to start audio timer"); + return false; + } + + // get the volume from the app-registry + int volume = levels[INIT_LEVEL]; + AppRegistry *registry = Application::GetInstance()->GetAppRegistry(); + if (registry) { + if (E_KEY_NOT_FOUND == registry->Get(CONFIG_KEY, volume)) { + registry->Add(CONFIG_KEY, volume); + volume = levels[INIT_LEVEL]; + } else { + AppLog("Setting volume: %d", volume); + } + } + + _muted = false; + _mixer->setReady(true); + _audioOut->SetVolume(isSilentMode() ? 0 : volume); + _audioOut->Start(); + return true; +} + +void AudioThread::OnStop(void) { + logEntered(); + + _mixer->setReady(false); + + if (_timer) { + if (!_muted) { + _timer->Cancel(); + } + delete _timer; + } + + if (_audioOut) { + _audioOut->Reset(); + delete _audioOut; + } +} + +void AudioThread::OnAudioOutErrorOccurred(Osp::Media::AudioOut &src, result r) { + logEntered(); +} + +void AudioThread::OnAudioOutInterrupted(Osp::Media::AudioOut &src) { + logEntered(); +} + +void AudioThread::OnAudioOutReleased(Osp::Media::AudioOut &src) { + logEntered(); +} + +void AudioThread::OnAudioOutBufferEndReached(Osp::Media::AudioOut &src) { + if (_ready > 0) { + _playing = _tail; + _audioOut->WriteBuffer(_audioBuffer[_tail]); + _tail = (_tail + 1 == NUM_AUDIO_BUFFERS ? 0 : _tail + 1); + _ready--; + } else { + // audio buffer empty: decrease timer inverval + _playing = -1; + _interval -= TIMER_INCREMENT; + if (_interval < MIN_TIMER_INTERVAL) { + _interval = MIN_TIMER_INTERVAL; + } + } +} + +void AudioThread::OnTimerExpired(Timer &timer) { + if (_ready < NUM_AUDIO_BUFFERS) { + uint len = _audioBuffer[_head].GetCapacity(); + int samples = _mixer->mixCallback((byte*)_audioBuffer[_head].GetPointer(), len); + if (samples) { + _head = (_head + 1 == NUM_AUDIO_BUFFERS ? 0 : _head + 1); + _ready++; + } + } else { + // audio buffer full: increase timer inverval + _interval += TIMER_INCREMENT; + if (_interval > MAX_TIMER_INTERVAL) { + _interval = MAX_TIMER_INTERVAL; + } + } + + if (_ready && _playing == -1) { + OnAudioOutBufferEndReached(*_audioOut); + } + + _timer->Start(_interval); +} + +// +// end of audio.cpp +// diff --git a/backends/platform/bada/audio.h b/backends/platform/bada/audio.h new file mode 100755 index 0000000000..0b540645fb --- /dev/null +++ b/backends/platform/bada/audio.h @@ -0,0 +1,73 @@ +/* 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. + * + */ + +#ifndef AUDIO_H +#define AUDIO_H + +#include +#include +#include +#include + +#include "config.h" +#include "common/scummsys.h" +#include "common/system.h" +#include "audio/mixer_intern.h" + +using namespace Osp::Base; +using namespace Osp::Base::Collection; +using namespace Osp::Base::Runtime; +using namespace Osp::Media; +using namespace Osp::Io; + +#define NUM_AUDIO_BUFFERS 2 + +class AudioThread: public Osp::Media::IAudioOutEventListener, + public Osp::Base::Runtime::ITimerEventListener, + public Osp::Base::Runtime::Thread { +public: + AudioThread(void); + ~AudioThread(void); + + Audio::MixerImpl *Construct(OSystem *system); + bool isSilentMode(); + void setMute(bool on); + int setVolume(bool up, bool minMax); + + bool OnStart(void); + void OnStop(void); + void OnAudioOutErrorOccurred(Osp::Media::AudioOut &src, result r); + void OnAudioOutInterrupted(Osp::Media::AudioOut &src); + void OnAudioOutReleased(Osp::Media::AudioOut &src); + void OnAudioOutBufferEndReached(Osp::Media::AudioOut &src); + void OnTimerExpired(Timer &timer); + +private: + Audio::MixerImpl *_mixer; + Osp::Base::Runtime::Timer *_timer; + Osp::Media::AudioOut *_audioOut; + Osp::Base::ByteBuffer _audioBuffer[NUM_AUDIO_BUFFERS]; + int _head, _tail, _ready, _interval, _playing; + bool _muted; +}; + +#endif diff --git a/backends/platform/bada/bada.mk b/backends/platform/bada/bada.mk new file mode 100755 index 0000000000..fe90af4f8f --- /dev/null +++ b/backends/platform/bada/bada.mk @@ -0,0 +1,5 @@ +# Bada specific modules are built under eclipse + +$(EXECUTABLE): $(OBJS) + rm -f $@ + ar Tru $@ $(OBJS) diff --git a/backends/platform/bada/form.cpp b/backends/platform/bada/form.cpp new file mode 100755 index 0000000000..eb9c828b1b --- /dev/null +++ b/backends/platform/bada/form.cpp @@ -0,0 +1,442 @@ +/* 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. + * + */ + +#include + +#include "common/translation.h" +#include "base/main.h" + +#include "backends/platform/bada/form.h" +#include "backends/platform/bada/system.h" + +using namespace Osp::App; +using namespace Osp::Base; +using namespace Osp::Base::Runtime; +using namespace Osp::Graphics; +using namespace Osp::Ui; +using namespace Osp::Ui::Controls; + +#define SHORTCUT_TIMEOUT 3000 +#define SHORTCUT_SWAP_MOUSE 0 +#define SHORTCUT_ESCAPE 1 +#define SHORTCUT_F5 2 +#define LEVEL_RANGE 5 + +// +// BadaAppForm +// +BadaAppForm::BadaAppForm() : + _gameThread(0), + _state(InitState), + _buttonState(LeftButton), + _shortcutTimer(0), + _shortcutIndex(-1), + _touchCount(0) { + _eventQueueLock = new Mutex(); + _eventQueueLock->Create(); +} + +result BadaAppForm::Construct() { + result r = Form::Construct(Controls::FORM_STYLE_NORMAL); + if (IsFailed(r)) { + return r; + } + + BadaSystem *badaSystem = null; + _gameThread = null; + + badaSystem = new BadaSystem(this); + r = badaSystem != null ? E_SUCCESS : E_OUT_OF_MEMORY; + + if (!IsFailed(r)) { + r = badaSystem->Construct(); + } + + if (!IsFailed(r)) { + _gameThread = new Thread(); + r = _gameThread != null ? E_SUCCESS : E_OUT_OF_MEMORY; + } + + if (!IsFailed(r)) { + r = _gameThread->Construct(*this); + } + + if (IsFailed(r)) { + if (badaSystem != null) { + delete badaSystem; + } + if (_gameThread != null) { + delete _gameThread; + _gameThread = null; + } + } else { + g_system = badaSystem; + } + + return r; +} + +BadaAppForm::~BadaAppForm() { + logEntered(); + + if (_gameThread) { + terminate(); + _gameThread->Stop(); + _gameThread->Join(); + delete _gameThread; + _gameThread = null; + } + + if (_eventQueueLock) { + delete _eventQueueLock; + _eventQueueLock = null; + } + + logLeaving(); +} + +// +// abort the game thread +// +void BadaAppForm::terminate() { + if (_state == ActiveState) { + ((BadaSystem*) g_system)->setMute(true); + + _eventQueueLock->Acquire(); + + Common::Event e; + e.type = Common::EVENT_QUIT; + _eventQueue.push(e); + _state = ClosingState; + + _eventQueueLock->Release(); + + // block while thread ends + AppLog("waiting for shutdown"); + for (int i = 0; i < 10 && _state == ClosingState; i++) { + Thread::Sleep(250); + } + } +} + +void BadaAppForm::exitSystem() { + _state = ErrorState; + + if (_gameThread) { + _gameThread->Stop(); + delete _gameThread; + _gameThread = null; + } +} + +result BadaAppForm::OnInitializing(void) { + logEntered(); + + SetOrientation(ORIENTATION_LANDSCAPE); + AddOrientationEventListener(*this); + AddTouchEventListener(*this); + AddKeyEventListener(*this); + + Touch touch; + touch.SetMultipointEnabled(*this, true); + + // set focus to enable receiving key events + SetFocusable(true); + SetFocus(); + + return E_SUCCESS; +} + +result BadaAppForm::OnDraw(void) { + logEntered(); + + if (g_system) { + BadaSystem *system = (BadaSystem*)g_system; + BadaGraphicsManager *graphics = system->getGraphics(); + if (graphics && graphics->isReady()) { + g_system->updateScreen(); + } + } + + return E_SUCCESS; +} + +bool BadaAppForm::pollEvent(Common::Event &event) { + bool result = false; + + _eventQueueLock->Acquire(); + if (!_eventQueue.empty()) { + event = _eventQueue.pop(); + result = true; + } + _eventQueueLock->Release(); + + return result; +} + +void BadaAppForm::pushEvent(Common::EventType type, + const Point ¤tPosition) { + BadaSystem *system = (BadaSystem*)g_system; + BadaGraphicsManager *graphics = system->getGraphics(); + if (graphics) { + Common::Event e; + e.type = type; + e.mouse.x = currentPosition.x; + e.mouse.y = currentPosition.y; + + bool moved = graphics->moveMouse(e.mouse.x, e.mouse.y); + + _eventQueueLock->Acquire(); + + if (moved && type != Common::EVENT_MOUSEMOVE) { + Common::Event moveEvent; + moveEvent.type = Common::EVENT_MOUSEMOVE; + moveEvent.mouse = e.mouse; + _eventQueue.push(moveEvent); + } + + _eventQueue.push(e); + _eventQueueLock->Release(); + } +} + +void BadaAppForm::pushKey(Common::KeyCode keycode) { + Common::Event e; + e.synthetic = false; + e.kbd.keycode = keycode; + e.kbd.ascii = keycode; + e.kbd.flags = 0; + + _eventQueueLock->Acquire(); + + e.type = Common::EVENT_KEYDOWN; + _eventQueue.push(e); + e.type = Common::EVENT_KEYUP; + _eventQueue.push(e); + + _eventQueueLock->Release(); +} + +void BadaAppForm::OnOrientationChanged(const Control &source, + OrientationStatus orientationStatus) { + logEntered(); + if (_state == InitState) { + _state = ActiveState; + _gameThread->Start(); + } +} + +Object *BadaAppForm::Run(void) { + scummvm_main(0, 0); + + AppLog("scummvm_main completed"); + + if (_state == ActiveState) { + Application::GetInstance()->SendUserEvent(USER_MESSAGE_EXIT, null); + } + _state = DoneState; + return null; +} + +int BadaAppForm::getShortcutIndex() { + if (_shortcutTimer) { + uint32 nextTimer = g_system->getMillis(); + if (_shortcutTimer + SHORTCUT_TIMEOUT < nextTimer) { + // double tap has expired + _shortcutTimer = 0; + _shortcutIndex = -1; + } + } + return _shortcutIndex; +} + +void BadaAppForm::setVolume(bool up, bool minMax) { + int level = ((BadaSystem*)g_system)->setVolume(up, minMax); + if (level != -1) { + char message[32]; + char ind[LEVEL_RANGE]; // 1..5 (0=off) + int j = LEVEL_RANGE - 1; // 0..4 + for (int i = 1; i <= LEVEL_RANGE; i++) { + ind[j--] = level >= i ? '|' : ' '; + } + snprintf(message, sizeof(message), "Volume: [ %c%c%c%c%c ]", + ind[0], ind[1], ind[2], ind[3], ind[4]); + g_system->displayMessageOnOSD(message); + } +} + +void BadaAppForm::OnTouchDoublePressed(const Control &source, + const Point ¤tPosition, + const TouchEventInfo &touchInfo) { + if (getShortcutIndex() == -1) { + pushEvent(_buttonState == LeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN, + currentPosition); + pushEvent(_buttonState == LeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN, + currentPosition); + } +} + +void BadaAppForm::OnTouchFocusIn(const Control &source, + const Point ¤tPosition, + const TouchEventInfo &touchInfo) { +} + +void BadaAppForm::OnTouchFocusOut(const Control &source, + const Point ¤tPosition, + const TouchEventInfo &touchInfo) { +} + +void BadaAppForm::OnTouchLongPressed(const Control &source, + const Point ¤tPosition, + const TouchEventInfo &touchInfo) { + if (getShortcutIndex() == -1 && _buttonState != LeftButton) { + pushKey(Common::KEYCODE_RETURN); + } +} + +void BadaAppForm::OnTouchMoved(const Control &source, + const Point ¤tPosition, + const TouchEventInfo &touchInfo) { + if (getShortcutIndex() == -1) { + pushEvent(Common::EVENT_MOUSEMOVE, currentPosition); + } +} + +void BadaAppForm::OnTouchPressed(const Control &source, + const Point ¤tPosition, + const TouchEventInfo &touchInfo) { + Touch touch; + _touchCount = touch.GetPointCount(); + if (_touchCount > 1) { + int index = getShortcutIndex(); + _shortcutIndex = (index == -1 ? 0 : index + 1); + _shortcutTimer = g_system->getMillis(); + + switch (_shortcutIndex) { + case SHORTCUT_F5: + g_system->displayMessageOnOSD(_("Game Menu")); + break; + + case SHORTCUT_ESCAPE: + g_system->displayMessageOnOSD(_("Escape")); + break; + + default: + g_system->displayMessageOnOSD(_("Swap Buttons")); + _shortcutIndex = SHORTCUT_SWAP_MOUSE; + } + } else if (getShortcutIndex() == -1) { + pushEvent(_buttonState == LeftButton ? Common::EVENT_LBUTTONDOWN : Common::EVENT_RBUTTONDOWN, + currentPosition); + } +} + +void BadaAppForm::OnTouchReleased(const Control &source, + const Point ¤tPosition, + const TouchEventInfo &touchInfo) { + if (getShortcutIndex() == -1) { + pushEvent(_buttonState == LeftButton ? Common::EVENT_LBUTTONUP : Common::EVENT_RBUTTONUP, + currentPosition); + if (_buttonState == RightButtonOnce) { + _buttonState = LeftButton; + } + // flick to skip dialog + if (touchInfo.IsFlicked()) { + pushKey(Common::KEYCODE_PERIOD); + } + } else if (_touchCount == 1) { + bool repeat = false; + switch (_shortcutIndex) { + case SHORTCUT_SWAP_MOUSE: + switch (_buttonState) { + case LeftButton: + _buttonState = RightButtonOnce; + g_system->displayMessageOnOSD(_("Right Once")); + break; + case RightButtonOnce: + g_system->displayMessageOnOSD(_("Right Active")); + _buttonState = RightButton; + break; + case RightButton: + g_system->displayMessageOnOSD(_("Left Active")); + _buttonState = LeftButton; + break; + } + break; + + case SHORTCUT_F5: + pushKey(Common::KEYCODE_F5); + break; + + case SHORTCUT_ESCAPE: + pushKey(Common::KEYCODE_ESCAPE); + repeat = true; + break; + } + + // allow key repeat or terminate setup mode + _shortcutTimer = repeat ? g_system->getMillis() : -1; + } +} + +void BadaAppForm::OnKeyLongPressed(const Control &source, KeyCode keyCode) { + logEntered(); + switch (keyCode) { + case KEY_SIDE_UP: + setVolume(true, true); + return; + + case KEY_SIDE_DOWN: + setVolume(false, true); + return; + + default: + break; + } +} + +void BadaAppForm::OnKeyPressed(const Control &source, KeyCode keyCode) { + switch (keyCode) { + case KEY_SIDE_UP: + setVolume(true, false); + return; + + case KEY_SIDE_DOWN: + setVolume(false, false); + return; + + case KEY_CAMERA: + // display the soft keyboard + pushKey(Common::KEYCODE_F7); + return; + + default: + break; + } +} + +void BadaAppForm::OnKeyReleased(const Control &source, KeyCode keyCode) { +} + +// +// end of form.cpp +// diff --git a/backends/platform/bada/form.h b/backends/platform/bada/form.h new file mode 100755 index 0000000000..157cc8e365 --- /dev/null +++ b/backends/platform/bada/form.h @@ -0,0 +1,108 @@ +/* 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. + * + */ + +#ifndef BADA_FORM_H +#define BADA_FORM_H + +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "common/scummsys.h" +#include "common/events.h" +#include "common/queue.h" +#include "common/mutex.h" + +// +// BadaAppForm +// +class BadaAppForm : public Osp::Ui::Controls::Form, + public Osp::Ui::IOrientationEventListener, + public Osp::Ui::ITouchEventListener, + public Osp::Ui::IKeyEventListener, + public Osp::Base::Runtime::IRunnable { +public: + BadaAppForm(); + ~BadaAppForm(); + + result Construct(); + bool pollEvent(Common::Event &event); + bool isClosing() { return _state == ClosingState; } + void pushKey(Common::KeyCode keycode); + void exitSystem(); + +private: + Object *Run(); + result OnInitializing(void); + result OnDraw(void); + void OnOrientationChanged(const Osp::Ui::Control &source, + Osp::Ui::OrientationStatus orientationStatus); + void OnTouchDoublePressed(const Osp::Ui::Control &source, + const Osp::Graphics::Point ¤tPosition, + const Osp::Ui::TouchEventInfo &touchInfo); + void OnTouchFocusIn(const Osp::Ui::Control &source, + const Osp::Graphics::Point ¤tPosition, + const Osp::Ui::TouchEventInfo &touchInfo); + void OnTouchFocusOut(const Osp::Ui::Control &source, + const Osp::Graphics::Point ¤tPosition, + const Osp::Ui::TouchEventInfo &touchInfo); + void OnTouchLongPressed(const Osp::Ui::Control &source, + const Osp::Graphics::Point ¤tPosition, + const Osp::Ui::TouchEventInfo &touchInfo); + void OnTouchMoved(const Osp::Ui::Control &source, + const Osp::Graphics::Point ¤tPosition, + const Osp::Ui::TouchEventInfo &touchInfo); + void OnTouchPressed(const Osp::Ui::Control &source, + const Osp::Graphics::Point ¤tPosition, + const Osp::Ui::TouchEventInfo &touchInfo); + void OnTouchReleased(const Osp::Ui::Control &source, + const Osp::Graphics::Point ¤tPosition, + const Osp::Ui::TouchEventInfo &touchInfo); + void OnKeyLongPressed(const Osp::Ui::Control &source, + Osp::Ui::KeyCode keyCode); + void OnKeyPressed(const Osp::Ui::Control &source, + Osp::Ui::KeyCode keyCode); + void OnKeyReleased(const Osp::Ui::Control &source, + Osp::Ui::KeyCode keyCode); + + void pushEvent(Common::EventType type, + const Osp::Graphics::Point ¤tPosition); + void terminate(); + void setVolume(bool up, bool minMax); + int getShortcutIndex(); + + // event handling + Osp::Base::Runtime::Thread *_gameThread; + Osp::Base::Runtime::Mutex *_eventQueueLock; + Common::Queue _eventQueue; + enum {InitState, ActiveState, ClosingState, DoneState, ErrorState} _state; + enum {LeftButton, RightButtonOnce, RightButton} _buttonState; + uint32 _shortcutTimer; + int _shortcutIndex; + int _touchCount; +}; + +#endif diff --git a/backends/platform/bada/fs.cpp b/backends/platform/bada/fs.cpp new file mode 100755 index 0000000000..4ec0201445 --- /dev/null +++ b/backends/platform/bada/fs.cpp @@ -0,0 +1,428 @@ +/* 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. + */ + +#include "config.h" +#include "backends/platform/bada/system.h" +#include "backends/platform/bada/fs.h" + +#define BUFFER_SIZE 128 + +// +// BadaFileStream +// +class BadaFileStream : public Common::SeekableReadStream, + public Common::WriteStream, + public Common::NonCopyable { +public: + static BadaFileStream *makeFromPath(const String &path, bool writeMode); + + BadaFileStream(File *file, bool writeMode); + ~BadaFileStream(); + + bool err() const; + void clearErr(); + bool eos() const; + + uint32 write(const void *dataPtr, uint32 dataSize); + bool flush(); + + int32 pos() const; + int32 size() const; + bool seek(int32 offs, int whence = SEEK_SET); + uint32 read(void *dataPtr, uint32 dataSize); + +private: + byte buffer[BUFFER_SIZE]; + uint32 bufferIndex; + uint32 bufferLength; + bool writeMode; + File *file; +}; + +BadaFileStream::BadaFileStream(File *ioFile, bool writeMode) : + bufferIndex(0), + bufferLength(0), + writeMode(writeMode), + file(ioFile) { + AppAssert(ioFile != 0); +} + +BadaFileStream::~BadaFileStream() { + if (file) { + if (writeMode) { + flush(); + } + delete file; + } +} + +bool BadaFileStream::err() const { + return (GetLastResult() != E_SUCCESS); +} + +void BadaFileStream::clearErr() { + SetLastResult(E_SUCCESS); +} + +bool BadaFileStream::eos() const { + return (bufferLength - bufferIndex == 0) && (GetLastResult() == E_END_OF_FILE); +} + +int32 BadaFileStream::pos() const { + return file->Tell() - (bufferLength - bufferIndex); +} + +int32 BadaFileStream::size() const { + int32 oldPos = file->Tell(); + file->Seek(FILESEEKPOSITION_END, 0); + + int32 length = file->Tell(); + SetLastResult(file->Seek(FILESEEKPOSITION_BEGIN, oldPos)); + + return length; +} + +bool BadaFileStream::seek(int32 offs, int whence) { + bool result = false; + switch (whence) { + case SEEK_SET: + // set from start of file + SetLastResult(file->Seek(FILESEEKPOSITION_BEGIN, offs)); + result = (E_SUCCESS == GetLastResult()); + break; + + case SEEK_CUR: + // set relative to offs + if (bufferIndex < bufferLength && bufferIndex > (uint32) -offs) { + // re-position within the buffer + SetLastResult(E_SUCCESS); + bufferIndex += offs; + return true; + } else { + offs -= (bufferLength - bufferIndex); + if (offs < 0 && file->Tell() + offs < 0) { + // avoid negative positioning + offs = 0; + } + if (offs != 0) { + SetLastResult(file->Seek(FILESEEKPOSITION_CURRENT, offs)); + result = (E_SUCCESS == GetLastResult()); + } else { + result = true; + } + } + break; + + case SEEK_END: + // set relative to end - positive will increase the file size + SetLastResult(file->Seek(FILESEEKPOSITION_END, offs)); + result = (E_SUCCESS == GetLastResult()); + break; + + default: + AppLog("Invalid whence %d", whence); + return false; + } + + if (!result) { + AppLog("seek failed"); + } + + bufferIndex = bufferLength = 0; + return result; +} + +uint32 BadaFileStream::read(void *ptr, uint32 len) { + uint32 result = 0; + if (!eos()) { + if (bufferIndex < bufferLength) { + // use existing buffer + uint32 available = bufferLength - bufferIndex; + if (len <= available) { + // use allocation + memcpy((byte*) ptr, &buffer[bufferIndex], len); + bufferIndex += len; + result = len; + } else { + // use remaining allocation + memcpy((byte*) ptr, &buffer[bufferIndex], available); + uint32 remaining = len - available; + result = available; + + if (remaining) { + result += file->Read(((byte*) ptr) + available, remaining); + } + bufferIndex = bufferLength = 0; + } + } else if (len < BUFFER_SIZE) { + // allocate and use buffer + bufferIndex = 0; + bufferLength = file->Read(buffer, BUFFER_SIZE); + if (bufferLength) { + if (bufferLength < len) { + len = bufferLength; + } + memcpy((byte*) ptr, buffer, len); + result = bufferIndex = len; + } + } else { + result = file->Read((byte*) ptr, len); + bufferIndex = bufferLength = 0; + } + } else { + AppLog("Attempted to read past EOS"); + } + return result; +} + +uint32 BadaFileStream::write(const void *ptr, uint32 len) { + result r = file->Write(ptr, len); + SetLastResult(r); + return (r == E_SUCCESS ? len : 0); +} + +bool BadaFileStream::flush() { + logEntered(); + SetLastResult(file->Flush()); + return (E_SUCCESS == GetLastResult()); +} + +BadaFileStream *BadaFileStream::makeFromPath(const String &path, bool writeMode) { + File *ioFile = new File(); + + String filePath = path; + if (writeMode && (path[0] != '.' && path[0] != '/')) { + filePath.Insert("/Home/", 0); + } + + AppLog("Open file %S", filePath.GetPointer()); + + result r = ioFile->Construct(filePath, writeMode ? L"w" : L"r", writeMode); + if (r == E_SUCCESS) { + return new BadaFileStream(ioFile, writeMode); + } + + AppLog("Failed to open file"); + delete ioFile; + return 0; +} + +// +// converts a bada (wchar) String into a scummVM (char) string +// +Common::String fromString(const Osp::Base::String &in) { + ByteBuffer *buf = StringUtil::StringToUtf8N(in); + Common::String result((const char*) buf->GetPointer()); + delete buf; + + return result; +} + +// +// BadaFilesystemNode +// +BadaFilesystemNode::BadaFilesystemNode(const Common::String &nodePath) { + AppAssert(nodePath.size() > 0); + init(nodePath); +} + +BadaFilesystemNode::BadaFilesystemNode(const Common::String &root, + const Common::String &nodePath) { + // Make sure the string contains no slashes + AppAssert(!nodePath.contains('/')); + + // We assume here that path is already normalized (hence don't bother to + // call Common::normalizePath on the final path). + Common::String newPath(root); + if (root.lastChar() != '/') { + newPath += '/'; + } + newPath += nodePath; + + init(newPath); +} + +void BadaFilesystemNode::init(const Common::String &nodePath) { + // Normalize the path (that is, remove unneeded slashes etc.) + _path = Common::normalizePath(nodePath, '/'); + _displayName = Common::lastPathComponent(_path, '/'); + + StringUtil::Utf8ToString(_path.c_str(), _unicodePath); + _isVirtualDir = (_path == "/" || + _path == "/Home" || + _path == "/Home/Share" || + _path == "/Home/Share2" || + _path == "/Storagecard"); + _isValid = _isVirtualDir || !IsFailed(File::GetAttributes(_unicodePath, _attr)); +} + +bool BadaFilesystemNode::exists() const { + return _isValid; +} + +bool BadaFilesystemNode::isReadable() const { + return _isVirtualDir || _isValid; +} + +bool BadaFilesystemNode::isDirectory() const { + return _isVirtualDir || (_isValid && _attr.IsDirectory()); +} + +bool BadaFilesystemNode::isWritable() const { + bool result = (_isValid && !_isVirtualDir && !_attr.IsDirectory() && !_attr.IsReadOnly()); + if (_path == "/Home" || + _path == "/HomeExt" || + _path == "/Home/Share" || + _path == "/Home/Share2") { + result = true; + } + return result; +} + +AbstractFSNode *BadaFilesystemNode::getChild(const Common::String &n) const { + AppAssert(!_path.empty()); + AppAssert(isDirectory()); + return new BadaFilesystemNode(_path, n); +} + +bool BadaFilesystemNode::getChildren(AbstractFSList &myList, + ListMode mode, bool hidden) const { + AppAssert(isDirectory()); + + bool result = false; + + if (_isVirtualDir && mode != Common::FSNode::kListFilesOnly) { + // present well known BADA file system areas + if (_path == "/") { + myList.push_back(new BadaFilesystemNode("/Home")); + myList.push_back(new BadaFilesystemNode("/HomeExt")); + myList.push_back(new BadaFilesystemNode("/Media")); + myList.push_back(new BadaFilesystemNode("/Storagecard")); + result = true; // no more entries + } else if (_path == "/Storagecard") { + myList.push_back(new BadaFilesystemNode("/Storagecard/Media")); + result = true; // no more entries + } else if (_path == "/Home") { + // ensure share path is always included + myList.push_back(new BadaFilesystemNode("/Home/Share")); + myList.push_back(new BadaFilesystemNode("/Home/Share2")); + } + } + + if (!result) { + DirEnumerator *pDirEnum = 0; + Directory *pDir = new Directory(); + + // open directory + if (IsFailed(pDir->Construct(_unicodePath))) { + AppLog("Failed to open directory"); + } else { + // read all directory entries + pDirEnum = pDir->ReadN(); + if (pDirEnum) { + result = true; + } + + // loop through all directory entries + while (pDirEnum && pDirEnum->MoveNext() == E_SUCCESS) { + DirEntry dirEntry = pDirEnum->GetCurrentDirEntry(); + + // skip 'invisible' files if necessary + Osp::Base::String fileName = dirEntry.GetName(); + + if (fileName[0] == '.' && !hidden) { + continue; + } + + // skip '.' and '..' to avoid cycles + if ((fileName[0] == '.' && fileName[1] == 0) || + (fileName[0] == '.' && fileName[1] == '.')) { + continue; + } + + // Honor the chosen mode + if ((mode == Common::FSNode::kListFilesOnly && dirEntry.IsDirectory()) || + (mode == Common::FSNode::kListDirectoriesOnly && !dirEntry.IsDirectory())) { + continue; + } + myList.push_back(new BadaFilesystemNode(_path, fromString(fileName))); + } + } + + // cleanup + if (pDirEnum) { + delete pDirEnum; + } + + // close the opened directory + if (pDir) { + delete pDir; + } + } + + return result; +} + +AbstractFSNode *BadaFilesystemNode::getParent() const { + logEntered(); + if (_path == "/") { + return 0; // The filesystem root has no parent + } + + const char *start = _path.c_str(); + const char *end = start + _path.size(); + + // Strip of the last component. We make use of the fact that at this + // point, path is guaranteed to be normalized + while (end > start && *(end-1) != '/') { + end--; + } + + if (end == start) { + // This only happens if we were called with a relative path, for which + // there simply is no parent. + // TODO: We could also resolve this by assuming that the parent is the + // current working directory, and returning a node referring to that. + return 0; + } + + return new BadaFilesystemNode(Common::String(start, end)); +} + +Common::SeekableReadStream *BadaFilesystemNode::createReadStream() { + Common::SeekableReadStream *result = BadaFileStream::makeFromPath(_unicodePath, false); + if (result != null) { + _isValid = !IsFailed(File::GetAttributes(_unicodePath, _attr)); + } + return result; +} + +Common::WriteStream *BadaFilesystemNode::createWriteStream() { + Common::WriteStream *result = BadaFileStream::makeFromPath(_unicodePath, true); + if (result != null) { + _isValid = !IsFailed(File::GetAttributes(_unicodePath, _attr)); + } + return result; +} + +// +// end of fs.cpp +// diff --git a/backends/platform/bada/fs.h b/backends/platform/bada/fs.h new file mode 100755 index 0000000000..d7d368ac20 --- /dev/null +++ b/backends/platform/bada/fs.h @@ -0,0 +1,82 @@ +/* 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. + */ + +#ifndef BADA_FILESYSTEM_H +#define BADA_FILESYSTEM_H + +#include +#include +#include +#include + +#include "config.h" +#include "common/scummsys.h" +#include "common/stream.h" +#include "backends/fs/abstract-fs.h" + +using namespace Osp::Io; +using namespace Osp::Base; +using namespace Osp::Base::Utility; + +/** + * Implementation of the ScummVM file system API based on BADA. + * + * Parts of this class are documented in the base interface class, AbstractFSNode. + */ +class BadaFilesystemNode : public AbstractFSNode { +public: + /** + * Creates a BadaFilesystemNode for a given path. + * + * @param path the path the new node should point to. + */ + BadaFilesystemNode(const Common::String &path); + + Common::String getDisplayName() const { return _displayName; } + Common::String getName() const { return _displayName; } + Common::String getPath() const { return _path; } + + bool exists() const; + bool isDirectory() const; + bool isReadable() const; + bool isWritable() const; + + AbstractFSNode *getChild(const Common::String &n) const; + bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const; + AbstractFSNode *getParent() const; + + Common::SeekableReadStream *createReadStream(); + Common::WriteStream *createWriteStream(); + +protected: + BadaFilesystemNode(const Common::String &root, + const Common::String &p); + void init(const Common::String &nodePath); + + Common::String _displayName; + Common::String _path; + String _unicodePath; + bool _isValid; + bool _isVirtualDir; + FileAttributes _attr; +}; + +#endif diff --git a/backends/platform/bada/graphics.cpp b/backends/platform/bada/graphics.cpp new file mode 100755 index 0000000000..1679959b24 --- /dev/null +++ b/backends/platform/bada/graphics.cpp @@ -0,0 +1,309 @@ +/* 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. + * + */ + +#include "graphics/fontman.h" + +#include "backends/platform/bada/form.h" +#include "backends/platform/bada/system.h" +#include "backends/platform/bada/graphics.h" + +// +// BadaGraphicsManager +// +BadaGraphicsManager::BadaGraphicsManager(BadaAppForm *appForm) : + _appForm(appForm), + _eglDisplay(EGL_DEFAULT_DISPLAY), + _eglSurface(EGL_NO_SURFACE), + _eglConfig(0), + _eglContext(EGL_NO_CONTEXT), + _initState(true) { + assert(appForm != null); + _videoMode.fullscreen = true; + _videoMode.antialiasing = true; +} + +const Graphics::Font *BadaGraphicsManager::getFontOSD() { + return FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont); +} + +bool BadaGraphicsManager::moveMouse(int16 &x, int16 &y) { + int16 currentX = _cursorState.x; + int16 currentY = _cursorState.y; + + // save the current hardware coordinates + _cursorState.x = x; + _cursorState.y = y; + + // return x/y as game coordinates + adjustMousePosition(x, y); + + // convert current x/y to game coordinates + adjustMousePosition(currentX, currentY); + + // return whether game coordinates have changed + return (currentX != x || currentY != y); +} + +Common::List BadaGraphicsManager::getSupportedFormats() const { + logEntered(); + + Common::List res; + res.push_back(Graphics::PixelFormat(2, 4, 4, 4, 4, 12, 8, 4, 0)); + res.push_back(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0)); + res.push_back(Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)); + res.push_back(Graphics::PixelFormat::createFormatCLUT8()); + return res; +} + +bool BadaGraphicsManager::hasFeature(OSystem::Feature f) { + bool result = (f == OSystem::kFeatureFullscreenMode || + f == OSystem::kFeatureVirtualKeyboard || + OpenGLGraphicsManager::hasFeature(f)); + return result; +} + +void BadaGraphicsManager::setFeatureState(OSystem::Feature f, bool enable) { + OpenGLGraphicsManager::setFeatureState(f, enable); +} + +void BadaGraphicsManager::setReady() { + _initState = false; +} + +void BadaGraphicsManager::updateScreen() { + if (_transactionMode == kTransactionNone) { + internUpdateScreen(); + } +} + +// see: http://forums.badadev.com/viewtopic.php?f=7&t=208 +bool BadaGraphicsManager::loadEgl() { + logEntered(); + + EGLint numConfigs = 1; + EGLint eglConfigList[] = { + EGL_RED_SIZE, 5, + EGL_GREEN_SIZE, 6, + EGL_BLUE_SIZE, 5, + EGL_ALPHA_SIZE, 0, + EGL_DEPTH_SIZE, 8, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, + EGL_NONE + }; + + EGLint eglContextList[] = { + EGL_CONTEXT_CLIENT_VERSION, 1, + EGL_NONE + }; + + eglBindAPI(EGL_OPENGL_ES_API); + + if (_eglDisplay) { + unloadGFXMode(); + } + + _eglDisplay = eglGetDisplay((EGLNativeDisplayType) EGL_DEFAULT_DISPLAY); + if (EGL_NO_DISPLAY == _eglDisplay) { + systemError("eglGetDisplay() failed"); + return false; + } + + if (EGL_FALSE == eglInitialize(_eglDisplay, null, null) || + EGL_SUCCESS != eglGetError()) { + systemError("eglInitialize() failed"); + return false; + } + + if (EGL_FALSE == eglChooseConfig(_eglDisplay, eglConfigList, + &_eglConfig, 1, &numConfigs) || + EGL_SUCCESS != eglGetError()) { + systemError("eglChooseConfig() failed"); + return false; + } + + if (!numConfigs) { + systemError("eglChooseConfig() failed. Matching config does not exist \n"); + return false; + } + + _eglSurface = eglCreateWindowSurface(_eglDisplay, _eglConfig, + (EGLNativeWindowType)_appForm, null); + if (EGL_NO_SURFACE == _eglSurface || EGL_SUCCESS != eglGetError()) { + systemError("eglCreateWindowSurface() failed. EGL_NO_SURFACE"); + return false; + } + + _eglContext = eglCreateContext(_eglDisplay, _eglConfig, + EGL_NO_CONTEXT, eglContextList); + if (EGL_NO_CONTEXT == _eglContext || + EGL_SUCCESS != eglGetError()) { + systemError("eglCreateContext() failed"); + return false; + } + + if (false == eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface, _eglContext) || + EGL_SUCCESS != eglGetError()) { + systemError("eglMakeCurrent() failed"); + return false; + } + + logLeaving(); + return true; +} + +bool BadaGraphicsManager::loadGFXMode() { + logEntered(); + + if (!loadEgl()) { + unloadGFXMode(); + return false; + } + + int x, y, width, height; + _appForm->GetBounds(x, y, width, height); + _videoMode.overlayWidth = _videoMode.hardwareWidth = width; + _videoMode.overlayHeight = _videoMode.hardwareHeight = height; + _videoMode.scaleFactor = 3; // for proportional sized cursor in the launcher + + AppLog("screen size: %dx%d", _videoMode.hardwareWidth, _videoMode.hardwareHeight); + return OpenGLGraphicsManager::loadGFXMode(); +} + +void BadaGraphicsManager::internUpdateScreen() { + if (!_initState) { + OpenGLGraphicsManager::internUpdateScreen(); + eglSwapBuffers(_eglDisplay, _eglSurface); + } else { + showSplash(); + } +} + +void BadaGraphicsManager::unloadGFXMode() { + logEntered(); + + if (EGL_NO_DISPLAY != _eglDisplay) { + eglMakeCurrent(_eglDisplay, null, null, null); + + if (_eglContext != EGL_NO_CONTEXT) { + eglDestroyContext(_eglDisplay, _eglContext); + _eglContext = EGL_NO_CONTEXT; + } + + if (_eglSurface != EGL_NO_SURFACE) { + eglDestroySurface(_eglDisplay, _eglSurface); + _eglSurface = EGL_NO_SURFACE; + } + + eglTerminate(_eglDisplay); + _eglDisplay = EGL_NO_DISPLAY; + } + + _eglConfig = null; + + OpenGLGraphicsManager::unloadGFXMode(); + logLeaving(); +} + +void BadaGraphicsManager::refreshGameScreen() { + if (_screenNeedsRedraw) + _screenDirtyRect = Common::Rect(0, 0, _screenData.w, _screenData.h); + + int x = _screenDirtyRect.left; + int y = _screenDirtyRect.top; + int w = _screenDirtyRect.width(); + int h = _screenDirtyRect.height(); + + if (_screenData.format.bytesPerPixel == 1) { + // Create a temporary RGB888 surface + int sw = w; + int sh = h; + + if (_videoMode.screenWidth == w && _videoMode.screenHeight == h) { + // The extra border prevents random pixels from appearing in the right and bottom + // screen column/row. Not sure whether this should be applied to opengl-graphics.cpp + sw = w + 1; + sh = h + 1; + } + + byte *surface = new byte[sw * sh * 3]; + + // Convert the paletted buffer to RGB888 + const byte *src = (byte *)_screenData.pixels + y * _screenData.pitch; + src += x * _screenData.format.bytesPerPixel; + byte *dst = surface; + for (int i = 0; i < h; i++) { + for (int j = 0; j < w; j++) { + dst[0] = _gamePalette[src[j] * 3]; + dst[1] = _gamePalette[src[j] * 3 + 1]; + dst[2] = _gamePalette[src[j] * 3 + 2]; + dst += 3; + } + src += _screenData.pitch; + } + + // Update the texture + _gameTexture->updateBuffer(surface, w * 3, x, y, sw, sh); + + // Free the temp surface + delete[] surface; + } else { + // Update the texture + _gameTexture->updateBuffer((byte *)_screenData.pixels + y * _screenData.pitch + + x * _screenData.format.bytesPerPixel, _screenData.pitch, x, y, w, h); + } + + _screenNeedsRedraw = false; + _screenDirtyRect = Common::Rect(); +} + +// display a simple splash screen until launcher is ready +void BadaGraphicsManager::showSplash() { + Canvas canvas; + canvas.Construct(); + canvas.SetBackgroundColor(Color::COLOR_BLACK); + canvas.Clear(); + + int x = _videoMode.hardwareWidth / 3; + int y = _videoMode.hardwareHeight / 3; + + Font *pFont = new Font(); + pFont->Construct(FONT_STYLE_ITALIC | FONT_STYLE_BOLD, 55); + canvas.SetFont(*pFont); + canvas.SetForegroundColor(Color::COLOR_GREEN); + canvas.DrawText(Point(x, y), L"ScummVM"); + delete pFont; + + pFont = new Font(); + pFont->Construct(FONT_STYLE_ITALIC | FONT_STYLE_BOLD, 35); + canvas.SetFont(*pFont); + canvas.SetForegroundColor(Color::COLOR_WHITE); + canvas.DrawText(Point(x + 70, y + 50), L"Loading ..."); + delete pFont; + + canvas.Show(); + +} + +// +// end of graphics.cpp +// diff --git a/backends/platform/bada/graphics.h b/backends/platform/bada/graphics.h new file mode 100755 index 0000000000..24cff09731 --- /dev/null +++ b/backends/platform/bada/graphics.h @@ -0,0 +1,72 @@ +/* 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. + * + */ + +#ifndef BADA_GRAPHICS_H +#define BADA_GRAPHICS_H + +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "backends/graphics/opengl/opengl-graphics.h" +#include "graphics/font.h" +#include "backends/platform/bada/form.h" + +using namespace Osp::Graphics; +using namespace Osp::Graphics::Opengl; +using namespace Osp::App; + +class BadaGraphicsManager : public OpenGLGraphicsManager { +public: + BadaGraphicsManager(BadaAppForm *appForm); + + Common::List getSupportedFormats() const; + bool hasFeature(OSystem::Feature f); + void updateScreen(); + void setFeatureState(OSystem::Feature f, bool enable); + void setReady(); + bool isReady() {return !_initState;} + const Graphics::Font *getFontOSD(); + bool moveMouse(int16 &x, int16 &y); + +private: + void internUpdateScreen(); + bool loadGFXMode(); + void unloadGFXMode(); + void refreshGameScreen(); + void setInternalMousePosition(int x, int y) {} + void showSplash(); + + bool loadEgl(); + BadaAppForm *_appForm; + EGLDisplay _eglDisplay; + EGLSurface _eglSurface; + EGLConfig _eglConfig; + EGLContext _eglContext; + bool _initState; +}; + +#endif diff --git a/backends/platform/bada/main.cpp b/backends/platform/bada/main.cpp new file mode 100755 index 0000000000..154fec6462 --- /dev/null +++ b/backends/platform/bada/main.cpp @@ -0,0 +1,70 @@ +/* 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. + * + */ + +#include +#include +#include + +#include "backends/platform/bada/portdefs.h" +#include "backends/platform/bada/form.h" +#include "backends/platform/bada/system.h" +#include "backends/platform/bada/application.h" + +using namespace Osp::Base; +using namespace Osp::Base::Collection; + +C_LINKAGE_BEGIN + +_EXPORT_ int OspMain(int argc, char *pArgv[]); + +/** + * The entry function of bada application called by the operating system. + */ +int OspMain(int argc, char *pArgv[]) { + result r = E_SUCCESS; + + AppLog("Application started."); + ArrayList *pArgs = new ArrayList(); + pArgs->Construct(); + + for (int i = 0; i < argc; i++) { + pArgs->Add(*(new String(pArgv[i]))); + } + + r = Osp::App::Application::Execute(BadaScummVM::createInstance, pArgs); + if (IsFailed(r)) { + r &= 0x0000FFFF; + } + + pArgs->RemoveAll(true); + delete pArgs; + AppLog("Application finished."); + + return static_cast(r); +} + +C_LINKAGE_END + +// +// end of main.cpp +// + diff --git a/backends/platform/bada/missing.cpp b/backends/platform/bada/missing.cpp new file mode 100755 index 0000000000..57369f6f37 --- /dev/null +++ b/backends/platform/bada/missing.cpp @@ -0,0 +1,113 @@ +/* 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. + * + */ + +#include +#include +#include +#include +#include + +#include "backends/platform/bada/portdefs.h" + +#include +#include +#include +#include + +#define BUF_SIZE 255 + +void systemError(const char *message); + +C_LINKAGE_BEGIN + +int __errno; // for overridden method in saves/default/default-saves.cpp + +void __assert_func(const char *file, int line, + const char *func, const char *err) { + char buffer[BUF_SIZE]; + snprintf(buffer, sizeof(buffer), "%s %d %s %s", file, line, func, err); + systemError(buffer); +} + +void stderr_fprintf(void*, const char *format, ...) { + va_list ap; + char buffer[BUF_SIZE]; + + va_start(ap, format); + vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + AppLog(buffer); +} + +void stderr_vfprintf(void*, const char *format, va_list ap) { + char buffer[BUF_SIZE]; + vsnprintf(buffer, sizeof(buffer), format, ap); + AppLog(buffer); +} + +int printf(const char *format, ...) { + int result = 0; + va_list ap; + char buffer[BUF_SIZE]; + + va_start(ap, format); + result = vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + AppLog(buffer); + + return result; +} + +int sprintf(char *str, const char *format, ...) { + va_list ap; + int result; + char buffer[BUF_SIZE]; + + va_start(ap, format); + result = vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + strcpy(str, buffer); + + return result; +} + +char *strdup(const char *strSource) { + char *buffer; + int len = strlen(strSource) + 1; + buffer = (char*) malloc(len); + if (buffer) { + memcpy(buffer, strSource, len); + } + return buffer; +} + +int vsprintf(char *str, const char *format, va_list ap) { + char buffer[BUF_SIZE]; + int result = vsnprintf(buffer, sizeof(buffer), format, ap); + strcpy(str, buffer); + return result; +} + +C_LINKAGE_END diff --git a/backends/platform/bada/portdefs.h b/backends/platform/bada/portdefs.h new file mode 100755 index 0000000000..c96d6646b5 --- /dev/null +++ b/backends/platform/bada/portdefs.h @@ -0,0 +1,84 @@ +/* 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. + * + */ + +#ifndef PORT_DEFS_H +#define PORT_DEFS_H + +#include +#include +#include +#include +#include +#include +#include + +#define M_PI 3.14159265358979323846 + +#ifdef __cplusplus + #include // causes a link error when building c programs + #define C_LINKAGE_BEGIN extern "C" { + #define C_LINKAGE_END } +#else + #define C_LINKAGE_BEGIN + #define C_LINKAGE_END +#endif + +C_LINKAGE_BEGIN + +// for libFLAC +#undef fseeko +#undef ftello +#define fseeko fseek +#define ftello ftell + +// overcome use of fprintf since bada/newlib (1.2) does not +// support stderr/stdout (undefined reference to `_impure_ptr'). + +void stderr_fprintf(void*, const char *format, ...); +void stderr_vfprintf(void*, const char *format, va_list ap); + +#undef fprintf +#undef vfprintf +#undef stderr +#undef stdout +#undef stdin +#undef fputs +#undef fflush + +#define stderr (void*)0 +#define stdout (void*)1 +#define stdin (void*)2 +#define fputs(str, file) +#define fflush(file) +#define sscanf simple_sscanf +#define fprintf stderr_fprintf +#define vfprintf stderr_vfprintf + +int printf(const char *format, ...); +int sprintf(char *str, const char *format, ...); +int simple_sscanf(const char *buffer, const char *format, ...); +char *strdup(const char *s1); +int vsprintf(char *str, const char *format, va_list ap); + +C_LINKAGE_END + +#endif diff --git a/backends/platform/bada/sscanf.cpp b/backends/platform/bada/sscanf.cpp new file mode 100755 index 0000000000..2321833477 --- /dev/null +++ b/backends/platform/bada/sscanf.cpp @@ -0,0 +1,182 @@ +/* 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. + * + */ + +#include +#include +#include +#include +#include + +// +// simple sscanf replacement to match scummvm usage patterns +// + +bool scanInt(const char **in, va_list *ap, int max) { + while (**in && **in == ' ') { + (*in)++; + } + + int *arg = va_arg(*ap, int*); + char *end; + long n = strtol(*in, &end, 0); + + bool err = false; + if (end == *in || (max > 0 && (end - *in) > max)) { + err = true; + } else { + *arg = (int)n; + *in = end; + } + return err; +} + +bool scanHex(const char **in, va_list *ap) { + unsigned *arg = va_arg(*ap, unsigned*); + char *end; + long n = strtol(*in, &end, 16); + if (end == *in) { + return true; + } + + *in = end; + *arg = (unsigned) n; + return false; +} + +bool scanString(const char **in, va_list *ap) { + char *arg = va_arg(*ap, char*); + while (**in && **in != ' ' && **in != '\n' && **in != '\t') { + *arg = **in; + arg++; + (*in)++; + } + *arg = '\0'; + (*in)++; + return false; +} + +bool scanStringUntil(const char **in, va_list *ap, char c_end) { + char *arg = va_arg(*ap, char*); + while (**in && **in != c_end) { + *arg = **in; + *arg++; + (*in)++; + } + *arg = 0; + (*in)++; + return false; +} + +bool scanChar(const char **in, va_list *ap) { + char *arg = va_arg(*ap, char*); + if (**in) { + *arg = **in; + (*in)++; + } + return false; +} + +extern "C" int simple_sscanf(const char *input, const char *format, ...) { + va_list ap; + int result = 0; + const char *next = input; + + va_start(ap, format); + + while (*format) { + if (*format == '%') { + format++; + int max = 0; + while (isdigit(*format)) { + max = (max * 10) + (*format - '0'); + format++; + } + + bool err = false; + switch (*format++) { + case 'c': + err = scanChar(&next, &ap); + break; + case 'd': + case 'u': + err = scanInt(&next, &ap, max); + break; + case 'x': + err = scanHex(&next, &ap); + break; + case 's': + err = scanString(&next, &ap); + break; + case '[': + // assume %[^c] + if ('^' != *format) { + err = true; + } else { + format++; + if (*format && *(format+1) == ']') { + err = scanStringUntil(&next, &ap, *format); + format += 2; + } else { + err = true; + } + } + break; + default: + err = true; + break; + } + + if (err) { + break; + } else { + result++; + } + } else if (*format++ != *next++) { + // match input + break; + } + } + + va_end(ap); + return result; +} + +#if defined(TEST) +int main(int argc, char *pArgv[]) { + int x,y,h; + char buffer[100]; + unsigned u; + char c; + strcpy(buffer, "hello"); + char *b = buffer; + + // strcpy(buffer, "in the buffer something"); + if (simple_sscanf("CAT 123x-10 0x100 FONT large 1 enough\n 123456.AUD $", + "CAT %dx%d %x FONT %[^\n] %06u.AUD %c", + &x, &y, &h, b, &u, &c) != 6) { + printf("Failed\n"); + } else { + printf("Success %d %d %d %s %d '%c'\n", x, y, h, buffer, u, c); + } + return 0; +} +#endif diff --git a/backends/platform/bada/system.cpp b/backends/platform/bada/system.cpp new file mode 100755 index 0000000000..9b137d059a --- /dev/null +++ b/backends/platform/bada/system.cpp @@ -0,0 +1,500 @@ +/* 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. + * + */ + +#include + +#include "common/config-manager.h" +#include "common/file.h" +#include "engines/engine.h" +#include "graphics/font.h" +#include "graphics/fontman.h" +#include "graphics/fonts/bdf.h" +#include "backends/saves/default/default-saves.h" +#include "backends/events/default/default-events.h" +#include "backends/audiocd/default/default-audiocd.h" +#include "backends/mutex/mutex.h" +#include "backends/fs/fs-factory.h" + +#include "backends/platform/bada/form.h" +#include "backends/platform/bada/system.h" +#include "backends/platform/bada/graphics.h" +#include "backends/platform/bada/audio.h" +#include "backends/platform/bada/timer.h" + +using namespace Osp::Base; +using namespace Osp::Base::Runtime; +using namespace Osp::Ui::Controls; + +#define DEFAULT_CONFIG_FILE "/Home/scummvm.ini" +#define MUTEX_BUFFER_SIZE 5 + +// +// BadaFilesystemFactory +// +class BadaFilesystemFactory : public FilesystemFactory { + AbstractFSNode *makeRootFileNode() const; + AbstractFSNode *makeCurrentDirectoryFileNode() const; + AbstractFSNode *makeFileNodePath(const Common::String &path) const; +}; + +AbstractFSNode *BadaFilesystemFactory::makeRootFileNode() const { + return new BadaFilesystemNode("/"); +} + +AbstractFSNode *BadaFilesystemFactory::makeCurrentDirectoryFileNode() const { + return new BadaFilesystemNode("/Home"); +} + +AbstractFSNode *BadaFilesystemFactory::makeFileNodePath(const Common::String &path) const { + AppAssert(!path.empty()); + return new BadaFilesystemNode(path); +} + +// +// BadaSaveFileManager +// +struct BadaSaveFileManager : public DefaultSaveFileManager { + bool removeSavefile(const Common::String &filename); +}; + +bool BadaSaveFileManager::removeSavefile(const Common::String &filename) { + Common::String savePathName = getSavePath(); + + checkPath(Common::FSNode(savePathName)); + if (getError().getCode() != Common::kNoError) { + return false; + } + + // recreate FSNode since checkPath may have changed/created the directory + Common::FSNode savePath(savePathName); + Common::FSNode file = savePath.getChild(filename); + + String unicodeFileName; + StringUtil::Utf8ToString(file.getPath().c_str(), unicodeFileName); + + switch (Osp::Io::File::Remove(unicodeFileName)) { + case E_SUCCESS: + return true; + + case E_ILLEGAL_ACCESS: + setError(Common::kWritePermissionDenied, "Search or write permission denied: " + + file.getName()); + break; + + default: + setError(Common::kPathDoesNotExist, "removeSavefile: '" + file.getName() + + "' does not exist or path is invalid"); + break; + } + + return false; +} + +// +// BadaMutexManager +// +struct BadaMutexManager : public MutexManager { + BadaMutexManager(); + ~BadaMutexManager(); + OSystem::MutexRef createMutex(); + void lockMutex(OSystem::MutexRef mutex); + void unlockMutex(OSystem::MutexRef mutex); + void deleteMutex(OSystem::MutexRef mutex); +private: + Mutex *buffer[MUTEX_BUFFER_SIZE]; +}; + +BadaMutexManager::BadaMutexManager() { + for (int i = 0; i < MUTEX_BUFFER_SIZE; i++) { + buffer[i] = null; + } +} + +BadaMutexManager::~BadaMutexManager() { + for (int i = 0; i < MUTEX_BUFFER_SIZE; i++) { + if (buffer[i] != null) { + delete buffer[i]; + } + } +} + +OSystem::MutexRef BadaMutexManager::createMutex() { + Mutex *mutex = new Mutex(); + mutex->Create(); + + for (int i = 0; i < MUTEX_BUFFER_SIZE; i++) { + if (buffer[i] == null) { + buffer[i] = mutex; + break; + } + } + + return (OSystem::MutexRef) mutex; +} + +void BadaMutexManager::lockMutex(OSystem::MutexRef mutex) { + Mutex *m = (Mutex*)mutex; + m->Acquire(); +} + +void BadaMutexManager::unlockMutex(OSystem::MutexRef mutex) { + Mutex *m = (Mutex*)mutex; + m->Release(); +} + +void BadaMutexManager::deleteMutex(OSystem::MutexRef mutex) { + Mutex *m = (Mutex*)mutex; + + for (int i = 0; i < MUTEX_BUFFER_SIZE; i++) { + if (buffer[i] == m) { + buffer[i] = null; + } + } + + delete m; +} + +// +// BadaEventManager +// +struct BadaEventManager : public DefaultEventManager { + BadaEventManager(Common::EventSource *boss); + void init(); + int shouldQuit() const; +}; + +BadaEventManager::BadaEventManager(Common::EventSource *boss) : + DefaultEventManager(boss) { +} + +void BadaEventManager::init() { + DefaultEventManager::init(); + + // theme and vkbd should have now loaded - clear the splash screen + BadaSystem *system = (BadaSystem*)g_system; + BadaGraphicsManager *graphics = system->getGraphics(); + if (graphics) { + graphics->setReady(); + graphics->updateScreen(); + } +} + +int BadaEventManager::shouldQuit() const { + BadaSystem *system = (BadaSystem*)g_system; + return system->isClosing(); +} + +// +// BadaSystem +// +BadaSystem::BadaSystem(BadaAppForm *appForm) : + _appForm(appForm), + _audioThread(0), + _epoch(0) { +} + +result BadaSystem::Construct(void) { + logEntered(); + + _fsFactory = new BadaFilesystemFactory(); + if (!_fsFactory) { + return E_OUT_OF_MEMORY; + } + + return E_SUCCESS; +} + +BadaSystem::~BadaSystem() { + logEntered(); +} + +result BadaSystem::initModules() { + logEntered(); + + _mutexManager = new BadaMutexManager(); + if (!_mutexManager) { + return E_OUT_OF_MEMORY; + } + + _timerManager = new BadaTimerManager(); + if (!_timerManager) { + return E_OUT_OF_MEMORY; + } + + _savefileManager = new BadaSaveFileManager(); + if (!_savefileManager) { + return E_OUT_OF_MEMORY; + } + + _graphicsManager = (GraphicsManager*) new BadaGraphicsManager(_appForm); + if (!_graphicsManager) { + return E_OUT_OF_MEMORY; + } + + // depends on _graphicsManager when ENABLE_VKEYBD enabled + _eventManager = new BadaEventManager(this); + if (!_eventManager) { + return E_OUT_OF_MEMORY; + } + + _audioThread = new AudioThread(); + if (!_audioThread) { + return E_OUT_OF_MEMORY; + } + + _mixer = _audioThread->Construct(this); + if (!_mixer) { + return E_OUT_OF_MEMORY; + } + + _audiocdManager = (AudioCDManager*) new DefaultAudioCDManager(); + if (!_audiocdManager) { + return E_OUT_OF_MEMORY; + } + + if (IsFailed(_audioThread->Start())) { + AppLog("Failed to start audio thread"); + return E_OUT_OF_MEMORY; + } + + logLeaving(); + return E_SUCCESS; +} + +void BadaSystem::initBackend() { + logEntered(); + + // allow translations to be found + ConfMan.set("themepath", "/Res"); + + // use the mobile device theme + ConfMan.set("gui_theme", "/Res/scummmobile"); + + // allow virtual keypad pack to be found + ConfMan.set("vkeybdpath", "/Res/vkeybd_default"); + + // set default save path to writable area + if (!ConfMan.hasKey("savepath")) { + ConfMan.set("savepath", "/Home/Share"); + } + + // default to no auto-save + if (!ConfMan.hasKey("autosave_period")) { + ConfMan.setInt("autosave_period", 0); + } + + ConfMan.registerDefault("fullscreen", true); + ConfMan.registerDefault("aspect_ratio", true); + ConfMan.setBool("confirm_exit", false); + + Osp::System::SystemTime::GetTicks(_epoch); + + if (E_SUCCESS != initModules()) { + AppLog("initModules failed"); + } else { + OSystem::initBackend(); + } + + // replace kBigGUIFont using the large font from the scummmobile theme + Common::File fontFile; + Common::String fileName = "/Res/scummmobile/helvB14-ASCII.fcc"; + BadaFilesystemNode file(fileName); + if (file.exists()) { + Common::SeekableReadStream *stream = file.createReadStream(); + if (stream) { + if (fontFile.open(stream, fileName)) { + Graphics::BdfFont *font = Graphics::BdfFont::loadFromCache(fontFile); + if (font) { + // use this font for the vkbd and on-screen messages + FontMan.assignFontToUsage(Graphics::FontManager::kBigGUIFont, font); + } + } + } + } + + logLeaving(); +} + +void BadaSystem::destroyBackend() { + closeAudio(); + + delete _graphicsManager; + _graphicsManager = 0; + + delete _savefileManager; + _savefileManager = 0; + + delete _fsFactory; + _fsFactory = 0; + + delete _mixer; + _mixer = 0; + + delete _audiocdManager; + _audiocdManager = 0; + + delete _timerManager; + _timerManager = 0; + + delete _eventManager; + _eventManager = 0; + + delete _mutexManager; + _mutexManager = 0; + + delete g_engine; +} + +bool BadaSystem::pollEvent(Common::Event &event) { + return _appForm->pollEvent(event); +} + +uint32 BadaSystem::getMillis() { + long long result, ticks = 0; + Osp::System::SystemTime::GetTicks(ticks); + result = ticks - _epoch; + return result; +} + +void BadaSystem::delayMillis(uint msecs) { + if (!_appForm->isClosing()) { + Thread::Sleep(msecs); + } +} + +void BadaSystem::updateScreen() { + if (_graphicsManager != null) { + _graphicsManager->updateScreen(); + } +} + +void BadaSystem::getTimeAndDate(TimeDate &td) const { + DateTime currentTime; + + if (E_SUCCESS == Osp::System::SystemTime::GetCurrentTime(currentTime)) { + td.tm_sec = currentTime.GetSecond(); + td.tm_min = currentTime.GetMinute(); + td.tm_hour = currentTime.GetHour(); + td.tm_mday = currentTime.GetDay(); + td.tm_mon = currentTime.GetMonth(); + td.tm_year = currentTime.GetYear(); + } +} + +void BadaSystem::fatalError() { + systemError("ScummVM: Fatal internal error."); +} + +void BadaSystem::exitSystem() { + if (_appForm) { + closeAudio(); + closeGraphics(); + _appForm->exitSystem(); + } +} + +void BadaSystem::logMessage(LogMessageType::Type /*type*/, const char *message) { + AppLog(message); +} + +Common::SeekableReadStream *BadaSystem::createConfigReadStream() { + BadaFilesystemNode file(DEFAULT_CONFIG_FILE); + return file.createReadStream(); +} + +Common::WriteStream *BadaSystem::createConfigWriteStream() { + BadaFilesystemNode file(DEFAULT_CONFIG_FILE); + return file.createWriteStream(); +} + +void BadaSystem::closeAudio() { + if (_audioThread) { + _audioThread->Stop(); + _audioThread->Join(); + delete _audioThread; + _audioThread = 0; + } +} + +void BadaSystem::closeGraphics() { + if (_graphicsManager) { + delete _graphicsManager; + _graphicsManager = 0; + } +} + +void BadaSystem::setMute(bool on) { + if (_audioThread) { + _audioThread->setMute(on); + } +} + +int BadaSystem::setVolume(bool up, bool minMax) { + int level = -1; + if (_audioThread) { + level = _audioThread->setVolume(up, minMax); + } + return level; +} + +// +// create the scummVM system +// +BadaAppForm *systemStart(Osp::App::Application *app) { + logEntered(); + + BadaAppForm *appForm = new BadaAppForm(); + if (!appForm) { + AppLog("Failed to create appForm"); + return null; + } + + if (E_SUCCESS != appForm->Construct() || + E_SUCCESS != app->GetAppFrame()->GetFrame()->AddControl(*appForm)) { + delete appForm; + AppLog("Failed to construct appForm"); + return null; + } + + return appForm; +} + +// +// display a fatal error notification +// +void systemError(const char *message) { + AppLog("Fatal system error: %s", message); + + ArrayList *args = new ArrayList(); + args->Construct(); + args->Add(*(new String(message))); + Application::GetInstance()->SendUserEvent(USER_MESSAGE_EXIT_ERR, args); + + if (g_system) { + BadaSystem *system = (BadaSystem*)g_system; + system->exitSystem(); + } +} + +// +// end of system.cpp +// diff --git a/backends/platform/bada/system.h b/backends/platform/bada/system.h new file mode 100755 index 0000000000..7b5b9d87de --- /dev/null +++ b/backends/platform/bada/system.h @@ -0,0 +1,101 @@ +/* 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. + * + */ + +#ifndef BADA_SYSTEM_H +#define BADA_SYSTEM_H + +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "common/scummsys.h" +#include "backends/modular-backend.h" + +#include "backends/platform/bada/fs.h" +#include "backends/platform/bada/form.h" +#include "backends/platform/bada/audio.h" +#include "backends/platform/bada/graphics.h" + +#if defined(_DEBUG) +#define logEntered() AppLog("%s entered (%s %d)", \ + __FUNCTION__, __FILE__, __LINE__); +#define logLeaving() AppLog("%s leaving (%s %d)", \ + __FUNCTION__, __FILE__, __LINE__); +#else +#define logEntered() +#define logLeaving() +#endif + +BadaAppForm *systemStart(Osp::App::Application *app); +void systemError(const char *message); + +#define USER_MESSAGE_EXIT 1000 +#define USER_MESSAGE_EXIT_ERR 1001 + +// +// BadaSystem +// +class BadaSystem : public ModularBackend, + Common::EventSource { +public: + BadaSystem(BadaAppForm *appForm); + ~BadaSystem(); + + result Construct(); + void closeAudio(); + void closeGraphics(); + void destroyBackend(); + void setMute(bool on); + int setVolume(bool up, bool minMax); + void exitSystem(); + bool isClosing() { return _appForm->isClosing(); } + + BadaGraphicsManager *getGraphics() { + return (BadaGraphicsManager*)_graphicsManager; + } + +private: + void initBackend(); + result initModules(); + + void updateScreen(); + bool pollEvent(Common::Event &event); + uint32 getMillis(); + void delayMillis(uint msecs); + void getTimeAndDate(TimeDate &t) const; + void fatalError(); + void logMessage(LogMessageType::Type type, const char *message); + + Common::EventSource *getDefaultEventSource() {return this;} + Common::SeekableReadStream *createConfigReadStream(); + Common::WriteStream *createConfigWriteStream(); + + BadaAppForm *_appForm; + AudioThread *_audioThread; + long long _epoch; +}; + +#endif diff --git a/backends/platform/bada/timer.cpp b/backends/platform/bada/timer.cpp new file mode 100755 index 0000000000..0c941795d3 --- /dev/null +++ b/backends/platform/bada/timer.cpp @@ -0,0 +1,124 @@ +/* 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. + * + */ + +#include "backends/platform/bada/timer.h" +#include "backends/platform/bada/system.h" + +// +// TimerSlot +// +TimerSlot::TimerSlot(Common::TimerManager::TimerProc callback, + uint32 interval, void *refCon) : + _timer(0), + _callback(callback), + _interval(interval), + _refCon(refCon) { + logEntered(); +} + +TimerSlot::~TimerSlot() { + logEntered(); +} + +bool TimerSlot::OnStart() { + logEntered(); + + _timer = new Osp::Base::Runtime::Timer(); + if (!_timer || IsFailed(_timer->Construct(*this))) { + AppLog("Failed to create timer"); + return false; + } + + if (IsFailed(_timer->Start(_interval))) { + AppLog("failed to start timer"); + return false; + } + + AppLog("started timer %d", _interval); + return true; +} + +void TimerSlot::OnStop() { + logEntered(); + if (_timer) { + _timer->Cancel(); + delete _timer; + _timer = null; + } +} + +void TimerSlot::OnTimerExpired(Timer &timer) { + _callback(_refCon); + timer.Start(_interval); +} + +// +// BadaTimerManager +// +BadaTimerManager::BadaTimerManager() { + logEntered(); +} + +BadaTimerManager::~BadaTimerManager() { + logEntered(); + for (Common::List::iterator slot = _timers.begin(); + slot != _timers.end(); ++slot) { + slot->Stop(); + slot = _timers.erase(slot); + } +} + +bool BadaTimerManager::installTimerProc(TimerProc proc, int32 interval, void *refCon, + const Common::String &id) { + logEntered(); + TimerSlot *slot = new TimerSlot(proc, interval / 1000, refCon); + + if (IsFailed(slot->Construct(THREAD_TYPE_EVENT_DRIVEN))) { + AppLog("Failed to create timer thread"); + delete slot; + return false; + } + + if (IsFailed(slot->Start())) { + delete slot; + AppLog("Failed to start timer thread"); + return false; + } + + _timers.push_back(*slot); + return true; +} + +void BadaTimerManager::removeTimerProc(TimerProc proc) { + logEntered(); + for (Common::List::iterator slot = _timers.begin(); + slot != _timers.end(); ++slot) { + if (slot->_callback == proc) { + slot->Stop(); + slot = _timers.erase(slot); + } + } +} + +// +// end of timer.cpp +// diff --git a/backends/platform/bada/timer.h b/backends/platform/bada/timer.h new file mode 100755 index 0000000000..f9ed32c801 --- /dev/null +++ b/backends/platform/bada/timer.h @@ -0,0 +1,62 @@ +/* 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. + * + */ + +#ifndef BADA_TIMER_H +#define BADA_TIMER_H + +#include + +#include "common/timer.h" +#include "common/list.h" + +using namespace Osp::Base::Runtime; + +struct TimerSlot: public ITimerEventListener, public Thread { + TimerSlot(Common::TimerManager::TimerProc callback, + uint32 interval, + void *refCon); + ~TimerSlot(); + + bool OnStart(void); + void OnStop(void); + void OnTimerExpired(Timer &timer); + + Timer *_timer; + Common::TimerManager::TimerProc _callback; + uint32 _interval; // in microseconds + void *_refCon; +}; + +class BadaTimerManager : public Common::TimerManager { +public: + BadaTimerManager(); + ~BadaTimerManager(); + + bool installTimerProc(TimerProc proc, int32 interval, void *refCon, + const Common::String &id); + void removeTimerProc(TimerProc proc); + + private: + Common::List _timers; +}; + +#endif -- cgit v1.2.3