Merged revisions 33452-33453,33455-33459,33463-33464,33466-33471,33473-33474,33478,33490,33492,33495-33496,33509-33512,33518-33519,33522-33527,33529-33530,33537,33541,33544,33546,33550,33552-33554,33556,33558,33561-33562,33565,33568,33570,33574,33576,33578-33581,33584-33587,33590,33596,33604-33611,33614-33615,33617-33618,33620-33621,33623,33626-33627,33632-33633,33635,33637,33639-33640,33642-33645,33648,33654-33655,33664,33667-33670,33673-33674,33678,33682,33686-33691,33693,33696,33698,33700,33703,33708,33710,33712-33714,33716,33719,33721-33723,33725-33727,33729-33730,33733,33736,33742,33754,33756,33758,33761,33763,33766,33777,33781-33788,33790,33792-33793,33795,33797,33805,33807-33812,33815-33817,33819,33822,33826,33829,33837,33839,33844,33847,33858-33861,33864,33871-33873,33875,33877-33879,33886,33889-33892,33894,33896,33900,33902-33903,33919,33928,33930,33932-33936,33938-33940,33942-33943,33948,33950,33953,33967,33973,33976,33978,33980,33985,33991,33993,33999-34000,34006,34009,34011,34013,34015,34019,34021-34023,34025,34027-34028,34030,34032-34034,34036,34038-34039,34041,34046-34048,34050-34055,34057,34059-34065,34067,34072,34074,34076,34078-34081,34084,34086-34087,34089-34090,34093,34096-34102,34104,34107,34113,34116,34119,34122,34124,34126,34128,34131-34132,34135,34138,34141,34144,34146,34149,34152-34154,34156-34157,34160,34163-34164,34169,34173,34179-34194,34196-34198,34200-34201,34205-34206,34208-34217,34219-34225,34227-34228,34234-34237,34239-34249,34251-34279,34281-34284,34286-34288,34290-34320,34323-34324,34326,34328-34329,34332,34334,34336,34338-34340,34343-34353,34356-34357,34359-34371,34373,34375,34378,34381-34382,34384-34385,34389-34391,34393-34394,34396-34397,34399-34405,34407-34409,34411,34413,34415,34417-34420,34423-34426,34428-34438,34440-34454,34456-34458,34460,34462-34469,34472,34474,34479-34481,34483-34498,34501-34505,34508,34511-34518,34520-34524,34526-34563,34566-34569,34571-34590,34592,34595-34599,34602-34603,34605,34613-34615,34617,34619-34624,34627-34628,34630-34639,34642-34649 via svnmerge from

https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk

svn-id: r34654
This commit is contained in:
Stephen Kennedy 2008-09-26 21:53:08 +00:00
commit a7bb113e83
749 changed files with 31575 additions and 16864 deletions

22
AUTHORS
View file

@ -6,6 +6,11 @@ ScummVM Team
Max Horn
Eugene Sandulenko
Retired Project Leaders
-----------------------
Vincent Hamm - ScummVM co-founder, Original Cruise/CinE author
Ludvig Strigeus - Original ScummVM and SimonVM author
Engine Teams
------------
SCUMM:
@ -134,7 +139,6 @@ ScummVM Team
Kostas Nakos
PlayStation 2:
Robert Goeffringmann
Max Lingua
PSP (PlayStation Portable):
@ -163,9 +167,12 @@ ScummVM Team
Johannes Schickel
Miscellaneous:
David Corrales-Lopez - Filesystem access improvements
David Corrales-Lopez - Filesystem access improvements (GSoC 2007
task)
Jerome Fisher - MT-32 emulator
Jochen Hoenicke - Speaker & PCjr sound support, Adlib work
Chris Page - Return to launcher, savestate improvements,
leak fixes, ... (GSoC 2008 task)
Robin Watts - ARM assembly routines for nice speedups on
several ports; improvements to the sound mixer
@ -184,13 +191,14 @@ ScummVM Team
Nicolas Bacca - Former WinCE porter
Ralph Brorsen - Help with GUI implementation
Jamieson Christian - iMUSE, MIDI, all things musical
Hans-Jorg Frieden - Former AmigaOS 4 packager
Robert Goeffringmann - Original PS2 porter
Ruediger Hanke - Port: MorphOS
Vincent Hamm - ScummVM co-founder, Original Cruise/CinE author
Felix Jakschitsch - Zak256 reverse engineering
Mutwin Kraus - Original MacOS porter
Peter Moraliyski - Port: GP32
Juha Niemimaki - Formaer AmigaOS 4 packager
Jeremy Newman - Former webmaster
Ludvig Strigeus - Original ScummVM and SimonVM author
Lionel Ulmer - Port: X11
Won Star - Former GP32 porter
@ -199,9 +207,7 @@ Other contributions
Packages
--------
AmigaOS 4:
Hans-Jorg Frieden
Hubert Maier
Juha Niemimaki
Atari/FreeMiNT:
Keith Scroggins
@ -260,6 +266,7 @@ Other contributions
Stuart Caie - Decoders for Simon 1 Amiga data files
Paolo Costabel - PSP port contributions
Thierry Crozat - Support for Broken Sword 1 Macintosh version
Martin Doucha - CinE engine objectification
Thomas Fach-Pedersen - ProTracker module player
Benjamin Haisch - Heavily improved de-/encoder for DXA videos
Janne Huttunen - V3 actor mask support, Dig/FT SMUSH audio
@ -289,15 +296,18 @@ Special thanks to
Sander Buskens - For his work on the initial reversing of Monkey2
Canadacow - For the original MT-32 emulator
Kevin Carnes - For Scumm16, the basis of ScummVM's older gfx codecs
Curt Coder - For the original TrollVM (preAGI) code
Patrick Combet - For the original Gobliiins ADL player
Ivan Dubrov - For contributing the initial version of the Gobliiins
engine
Till Kresslein - For design of modern ScummVM GUI
Jezar - For his freeverb filter implementation
Jim Leiterman - Various info on his FM-TOWNS/Marty SCUMM ports
lloyd - For deep tech details about C64 Zak & MM
Sarien Team - Original AGI engine code
Jimmi Thogersen - For ScummRev, and much obscure code/documentation
Tristan - For additional work on the original MT-32 emulator
James Woodcock - Soundtrack enhancements
Tony Warriner and everyone at Revolution Software Ltd. for sharing with us
the source of some of their brilliant games, allowing us to release

View file

@ -60,6 +60,7 @@ Eugene Sandulenko
Johannes Schickel
Won Star
Ludvig Strigeus
Keith Scroggins
David Symonds
Jordi Vilalta
Robin Watts
@ -74,23 +75,34 @@ Patches contributed by:
Laura Abbott "sageofminerva"
Vikram Aggarwal "youngelf"
the rara avis "theraraavis"
Dieter Baron "dillo"
Alban Bedel "albeu"
Bodo Bellut "bellut"
Bramvandijk "bramvandijk"
Andreas Bierfert "awjb"
Elio Blanca "eblanca76"
Bastien Bouclet "bgk"
David Breakey "dbreakey"
Robert Buchholz "prendi"
Rainer Canavan
Rainer Canavan "canavan"
Mathieu Carot "yokna"
Stefano Ceccherini "jackburton"
Travis S Coady "theealien"
Josh Coalson "jcoalson"
Thomas Combeleran "hibernatus"
Kees Cook "keescook"
Carlos Corbacho "cathectic"
Roberto Costa "fiix76"
Thiery Crozat "criezy"
dc france "erwan2004"
dewt "mncl"
Martin Doucha "next_ghost"
Michael Drueing "doc_wagon"
dubsdj
Matthew Duggan "stauff1"
Olivier Duverne "richiefs"
Andrei Dziahel "develop7"
John Eckerdal "johneck"
Thomas Fach-Pedersen "madm00se"
Florent "flobo"
@ -109,6 +121,7 @@ Stefan Haubenthal "polluks"
Alexander Holler "holler"
Falk Hueffner "mellum"
Casey Hutchinson "nnooiissee"
j0tt
Gregor Jasny "gjasny"
Jellby "jellby"
Joerg "macdrega"
@ -122,38 +135,49 @@ Janne Kujanpaa "jukuja"
Jay Lanagan "r0ni"
Norbert Lange "nolange"
Manuel Lauss "mlau2"
Rolf Leggewie "leggewie"
Duncan Lock "dflock"
Mark Lodato "itsr0y"
Fridvin Logi "phillip_j_fry"
Lostech "lostech"
Georg Lukas "ge0rg"
Dmitry Marakasov "amdmi3"
Markus "meist3r"
Connor McLeod "mcleod2032"
Mickey McMurray "metafox"
Vladimir Menshakov "megath"
Adam Metcalf "gamblore"
Frank Meyering "frank_m24"
Gael Le Migno "kilobug"
Alyssa Anne Milburn "fuzzie"
Andy Molloy "maloi"
Sean Murrau "lightcast"
Armin Mueller "arm_in"
Andrea Musuruane "musuruan"
KO Myung-Hun "lvzuufx"
Markus Napp "meist3r"
Peter Naulls "pnaulls"
Christian Neumair "mannythegnome"
Nicos "anarxia"
Juha Niemimaki "capehill"
Markus Niemisto "niemisto"
ole
Chris Paras "paras_rasmatazz"
Aubin Paul "outlyer"
Vincent Pelletier "subdino"
phi1
Pix2 "pix2"
Carsten Pohl "carstenpohl"
Markus Pyykko "mankeli"
Richard "trinity78"
Felix Riemann "kirschsaft"
Thomas Richter "thorfdbg"
Timo Roehling "t1m0"
Andreas Roever "roever"
Jonathan Rogers "jonner"
Marek Roth "logicdeluxe"
Uwe Ryssel "uweryssel"
Simon Sawatzki "simsaw"
Scarlatti "escarlate"
Daniel Schepler "dschepler"
Florian Schmitt "fatpenguin"
Mark Schreiber "mark7"
@ -161,12 +185,17 @@ Ben Shadwick "benshadwick"
Jean-Yves Simon "lethalwp"
Andrej Sinicyn "andrej4000"
Andre Souza "luke_br"
spookypeanut "spookypeanut"
Steve Stavropoulos "isnothere"
Daniel Steinberger "amorphousshape"
Sven Strothoff "dataslayer"
Andrea Suatoni "mrhandler"
tbcarey
Tim "tipabu"
Tobigun "tobigun"
Luigi Toscano "ltosky"
Xavier Trochu "xtrochu"
Michal Tulacek "tutchek"
Michael Udaltsov "cccp99"
Kristof Vansant "lupusbe"
Tim Walters "realmz"
@ -174,16 +203,6 @@ David Weinehall "weine"
Eric A. Welsh "eweish42"
Yudhi Widyatama "yudhi97"
Robert Wohlrab "moshroum"
Xanathar "xanathar"
Grant Yeager "glo_kidd"
Benjamin W. Zale "junior_aepi"
the rara avis "theraraavis"
dewt "mncl"
dubsdj
exo "exofreeze"
dc france "erwan2004"
j0tt
glo kidd "glo_kidd"
ole
phi1
spookypeanut "spookypeanut"
tbcarey
Tim "tipabu"

18
NEWS
View file

@ -2,10 +2,22 @@ For a more comprehensive changelog for the latest experimental SVN code, see:
http://scummvm.sourceforge.net/daily/ChangeLog
0.13.0 (????-??-??)
General:
- Added MIDI driver for Atari ST / FreeMint.
- Added a 'Load' button to the Launcher (not supported by all engines).
- Added a new global main menu (GMM) dialog usable from all engines.
- Added the ability to return to the launcher from running games (via the GMM).
New Games:
- Added support for Discworld.
0.12.0 (????-??-??)
KYRA:
- Added support for Auto-save feature.
SCUMM:
- Fixed a long-time bug which caused talkspeed and talkdelay to be mixed up.
0.12.0 (2008-08-31)
New Games:
- Added support for The Legend of Kyrandia: Book Two: Hand of Fate.
- Added support for The Legend of Kyrandia: Book Three: Malcolm's Revenge.
@ -30,6 +42,10 @@ For a more comprehensive changelog for the latest experimental SVN code, see:
Simon the Sorcerer 1.
- Fixed palette issues in Amiga versions of Simon the Sorcerer 1.
Queen:
- Speech is played at the correct sample rate. (It used to be pitched a bit
too low.)
SCUMM:
- Rewrote parts of Digital iMUSE, fixing some bugs.
- Rewrote the internal timer code, fixing some speed issues in e.g. COMI.

158
README
View file

@ -39,10 +39,12 @@ Table of Contents:
* 5.1 Command Line Options
* 5.2 Language Options
* 5.3 Graphics Filters
* 5.4 Hotkeys
* 5.4 Global Menu
* 5.5 Hotkeys
6.0) Savegames
* 6.1 Autosaves
* 6.2 Converting savegames
* 6.3 Viewing/Loading savegames from the command line
7.0) Music and Sound
* 7.1 Adlib emulation
* 7.2 FluidSynth MIDI emulation
@ -182,17 +184,23 @@ GOB Games by Coktel Vision:
Gobliiins [gob1]
Gobliins 2 [gob2]
Goblins 3 [gob3]
Lost in Time [lostintime]
The Bizarre Adventures of Woodruff
and the Schnibble [woodruff]
Ween: The Prophecy [ween]
Other Games:
Beneath a Steel Sky [sky]
Broken Sword 1: The Shadow of the Templars [sword1]
Broken Sword 2: The Smoking Mirror [sword2]
Drascula: The Vampire Strikes Back [drascula]
Flight of the Amazon Queen [queen]
Future Wars [fw]
Inherit the Earth: Quest for the Orb [ite]
Nippon Safes Inc. [nippon]
The Legend of Kyrandia [kyra1]
The Legend of Kyrandia: The Hand of Fate [kyra2]
The Legend of Kyrandia: Malcolm's Revenge [kyra3]
Touche: The Adventures of the Fifth
Musketeer [touche]
@ -781,6 +789,7 @@ arguments -- see the next section.
-h, --help Display a brief help text and exit
-z, --list-games Display list of supported games and exit
-t, --list-targets Display list of configured targets and exit
--list-saves=TARGET Display a list of savegames for the game (TARGET) specified
-c, --config=CONFIG Use alternate configuration file
-p, --path=PATH Path to where the game is installed
@ -968,7 +977,38 @@ Likewise, games that originally were using 640x480 (such as COMI or Broken Sword
will be scaled to 1280x960 and 1920x1440.
5.4) Hot Keys:
5.4) Global Menu:
---- ------------
The Global Menu is a general menu which is available to all of the game engines
by pressing F6. From this menu there are the following buttons: Resume,
Options, About, Return to Launcher, and Quit. Selecting 'Options' will display
a dialog where basic audio settings, such as volume levels, can be adjusted.
Selecting 'Return to Launcher' will close the current game and return the user
back to the ScummVM Launcher, where another game may be selected to play.
Note: Returning to the Launcher is not supported by all of the engines,
and the button will be disabled in the Global Menu if it is not supported.
Engines which currently support Returning to the Launcher are:
AGI
AGOS
CINE
GOB
KYRA
LURE
PARALLACTION
QUEEN
SAGA
SCUMM
SKY
SWORD1
SWORD2
TOUCHE
5.5) Hot Keys:
---- ---------
TODO
TODO: Rework this section to clearly state which hotkeys are implemented in *all*
@ -982,6 +1022,7 @@ ScummVM supports various in-game hotkeys. They differ between SCUMM games and
other games.
Common:
F6 - Displays the Global Menu
Cmd-q - Quit (Mac OS X)
Ctrl-q - Quit (other unices including Linux)
Ctrl-z OR Alt-x - Quit (other platforms)
@ -1138,45 +1179,93 @@ The platforms that currently have a different default directory are:
6.1) Autosaves:
---- ----------
For some games (namely "Beneath a Steel Sky", "Flight of the Amazon
Queen" and all SCUMM games), ScummVM will by default automatically
save the current state every five minutes (adjustable via the
"autosave_period" config setting). For the SCUMM engine, it will save
in Slot 0. This savestate can then be loaded again via Ctrl-0, or the
F5 menu.
For some games, (namely "Beneath a Steel Sky", "Flight of the Amazon Queen",
all AGI games, and all SCUMM games), ScummVM will by default automatically
save the current state every five minutes (adjustable via the "autosave_period"
config setting). For the AGI and SCUMM engines, it will save in Slot 0. For the
SCUMM engine, this savestate can then be loaded again via Ctrl-0, or the F5
menu.
6.2) Converting Savegames:
---- ----------
Using savegames from original versions, isn't supported by all game engines. Only
the following games, can use savedgames from their original versions.
---- ---------------------
Using savegames from original versions, isn't supported by all game engines.
Only the following games, can use savegames from their original versions.
Elvira 1
- Add 8 bytes (savedgame name) to the start of the savegame file
- Rename the savedgame to 'elvira1.xxx'
- Add 8 bytes (savegame name) to the start of the savegame file
- Rename the savegame to 'elvira1.xxx'
Elvira 2
- Add 8 bytes (savedgame name) to the start of the savegame file
- Rename the savedgame to 'elvira2-pc.xxx' (DOS version) or
- Add 8 bytes (savegame name) to the start of the savegame file
- Rename the savegame to 'elvira2-pc.xxx' (DOS version) or
'elvira2.xxx' (Other versions)
Waxworks
- Add 8 bytes (savedgame name) to the start of the savegame file
- Rename the savedgame to 'waxworks-pc.xxx' (DOS version) or
- Add 8 bytes (savegame name) to the start of the savegame file
- Rename the savegame to 'waxworks-pc.xxx' (DOS version) or
'waxworks.xxx' (Other versions)
Simon the Sorcerer 1
- Rename the savedgame to 'simon1.xxx'
- Rename the savegame to 'simon1.xxx'
Simon the Sorcerer 1
- Rename the savedgame to 'simon2.xxx'
- Rename the savegame to 'simon2.xxx'
The Feeble Files
- Rename the savedgame to 'feeble.xxx'
- Rename the savegame to 'feeble.xxx'
Where 'xxx' is exact the saved game slot (ie 001) under ScummVM
6.3) Viewing/Loading savegames from the command line:
---- ------------------------------------------------
--list-saves:
This switch may be used to display a list of the current savegames
of the specified target game and their corresponding save slots.
Usage: --list-saves=[TARGET], where [TARGET] is the target game.
Engines which currently support --list-saves are:
AGI
AGOS
CINE
KYRA
LURE
PARALLACTION
QUEEN
SAGA
SCUMM
SKY
SWORD1
SWORD2
TOUCHE
--save-slot/-x:
This switch may be used to load a savegame directly from the command line.
Usage: --save-slot[SLOT] or -x[SLOT], where [SLOT] is the save slot number.
Engines which currently support --save-slot/-x are:
AGI
CINE
KYRA
LURE
PARALLACTION
QUEEN
SAGA
SCUMM
SKY
SWORD1
SWORD2
TOUCHE
7.0) Music and Sound:
---- ----------------
@ -1322,34 +1411,39 @@ sequencer support does not work, you can always fall back on Adlib emulation.
7.6.1) Playing sound with ALSA sequencer: [UNIX ONLY]
------ ----------------------------------
If you have installed the ALSA driver with the sequencer support, then
set the environment variable SCUMMVM_PORT or the config file parameter
alsa_port to your sequencer port. The default is "65:0".
If you have installed the ALSA driver with the sequencer support, then set the
environment variable SCUMMVM_PORT or the config file parameter alsa_port to
your sequencer port. The default is to try both "65:0" and "17:0".
Here is a little howto on how to use the ALSA sequencer with your soundcard.
In all cases, to have a list of all the sequencer ports you have, try the
command "aconnect -o -l". This should give output similar to:
client 64: 'External MIDI 0' [type=kernel]
0 'MIDI 0-0 '
client 65: 'Emu10k1 WaveTable' [type=kernel]
client 14: 'Midi Through' [type=kernel]
0 'Midi Through Port-0'
client 16: 'SBLive! Value [CT4832]' [type=kernel]
0 'EMU10K1 MPU-401 (UART)'
client 17: 'Emu10k1 WaveTable' [type=kernel]
0 'Emu10k1 Port 0 '
1 'Emu10k1 Port 1 '
2 'Emu10k1 Port 2 '
3 'Emu10k1 Port 3 '
client 128: 'Client-128' [type=user]
client 128: 'TiMidity' [type=user]
0 'TiMidity port 0 '
1 'TiMidity port 1 '
2 'TiMidity port 2 '
3 'TiMidity port 3 '
This means the external MIDI output of the sound card is located on the
port 64:0, four WaveTable MIDI outputs in 65:0, 65:1, 65:2
and 65:3, and two TiMidity ports, located at 128:0 and 128:1.
The most important bit here is that there are four WaveTable MIDI outputs
located at 17:0, 17:1, 17:2 and 17:3, and four TiMidity ports located at 128:0,
128:1, 128:2 and 128:3.
If you have a FM-chip on your card, like the SB16, then you have to load
the SoundFonts using the sbiload software. Example:
sbiload -p 65:0 /etc/std.o3 /etc/drums.o3
sbiload -p 17:0 /etc/std.o3 /etc/drums.o3
If you have a WaveTable capable sound card, you have to load a sbk or sf2
SoundFont using the sfxload software. Example:
SoundFont using the sfxload or asfxload software. Example:
sfxload /path/to/8mbgmsfx.sf2
If you don't have a MIDI capable soundcard, there are two options: FluidSynth

View file

@ -96,7 +96,8 @@ DefaultEventManager::DefaultEventManager(OSystem *boss) :
_boss(boss),
_buttonState(0),
_modifierState(0),
_shouldQuit(false) {
_shouldQuit(false),
_shouldRTL(false) {
assert(_boss);
@ -211,6 +212,9 @@ DefaultEventManager::~DefaultEventManager() {
_boss->unlockMutex(_timeMutex);
_boss->unlockMutex(_recorderMutex);
if (!artificialEventQueue.empty())
artificialEventQueue.clear();
if (_playbackFile != NULL) {
delete _playbackFile;
}
@ -372,10 +376,8 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
if (!_artificialEventQueue.empty()) {
event = _artificialEventQueue.pop();
result = true;
}
// poll for event from backend
if (!result) {
} else {
// poll for event from backend
result = _boss->pollEvent(event);
if (result) {
// send key press events to keymapper
@ -415,7 +417,6 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
switch (event.type) {
case Common::EVENT_KEYDOWN:
_modifierState = event.kbd.flags;
// init continuous event stream
// not done on PalmOS because keyboard is emulated and keyup is not generated
#if !defined(PALMOS_MODE)
@ -424,8 +425,39 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
_currentKeyDown.flags = event.kbd.flags;
_keyRepeatTime = time + kKeyRepeatInitialDelay;
#endif
// Global Main Menu
// FIXME: F6 is not the best trigger, it conflicts with some games!!!
if (event.kbd.keycode == Common::KEYCODE_F6) {
if (g_engine && !g_engine->isPaused()) {
Common::Event menuEvent;
menuEvent.type = Common::EVENT_MAINMENU;
// FIXME: GSoC RTL branch passes the F6 key event to the
// engine, and also enqueues a EVENT_MAINMENU. For now,
// we just drop the key event and return an EVENT_MAINMENU
// instead. This way, we don't have to add special cases
// to engines (like it was the case for LURE in the RTL branch).
//
// However, this has other consequences, possibly negative ones.
// Like, what happens with key repeat for the trigger key?
//pushEvent(menuEvent);
event = menuEvent;
if (event.kbd.keycode == Common::KEYCODE_F6 && event.kbd.flags == 0) {
// FIXME: Since now we do not push another MAINMENU event onto
// our event stack, the GMM would never open, so we have to do
// that here. Of course when the engine would handle MAINMENU
// as an event now and open up the GMM itself it would open the
// menu twice.
if (g_engine && !g_engine->isPaused())
g_engine->mainMenuDialog();
if (_shouldQuit)
event.type = Common::EVENT_QUIT;
else if (_shouldRTL)
event.type = Common::EVENT_RTL;
}
} else if (event.kbd.keycode == Common::KEYCODE_F7 && event.kbd.flags == 0) {
if (_vk->isDisplaying()) {
_vk->close(true);
} else {
@ -435,7 +467,7 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
if (!isPaused) g_engine->pauseEngine(false);
result = false;
}
} else if (event.kbd.keycode == Common::KEYCODE_F7 && event.kbd.flags == 0) {
} else if (event.kbd.keycode == Common::KEYCODE_F8 && event.kbd.flags == 0) {
if (!_remap) {
_remap = true;
Common::RemapDialog _remapDialog;
@ -446,8 +478,8 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
_remap = false;
}
}
break;
case Common::EVENT_KEYUP:
_modifierState = event.kbd.flags;
if (event.kbd.keycode == _currentKeyDown.keycode) {
@ -464,6 +496,7 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
_mousePos = event.mouse;
_buttonState |= LBUTTON;
break;
case Common::EVENT_LBUTTONUP:
_mousePos = event.mouse;
_buttonState &= ~LBUTTON;
@ -473,11 +506,26 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
_mousePos = event.mouse;
_buttonState |= RBUTTON;
break;
case Common::EVENT_RBUTTONUP:
_mousePos = event.mouse;
_buttonState &= ~RBUTTON;
break;
case Common::EVENT_MAINMENU:
if (g_engine && !g_engine->isPaused())
g_engine->mainMenuDialog();
if (_shouldQuit)
event.type = Common::EVENT_QUIT;
else if (_shouldRTL)
event.type = Common::EVENT_RTL;
break;
case Common::EVENT_RTL:
_shouldRTL = true;
break;
case Common::EVENT_QUIT:
if (ConfMan.getBool("confirm_exit")) {
if (g_engine)
@ -488,6 +536,7 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
g_engine->pauseEngine(false);
} else
_shouldQuit = true;
break;
default:
@ -511,7 +560,13 @@ bool DefaultEventManager::pollEvent(Common::Event &event) {
}
void DefaultEventManager::pushEvent(const Common::Event &event) {
_artificialEventQueue.push(event);
// If already received an EVENT_QUIT, don't add another one
if (event.type == Common::EVENT_QUIT) {
if (!_shouldQuit)
artificialEventQueue.push(event);
} else
artificialEventQueue.push(event);
}
#endif // !defined(DISABLE_DEFAULT_EVENTMANAGER)

View file

@ -60,6 +60,7 @@ class DefaultEventManager : public Common::EventManager {
int _buttonState;
int _modifierState;
bool _shouldQuit;
bool _shouldRTL;
class RandomSourceRecord {
public:
@ -128,6 +129,9 @@ public:
virtual int getButtonState() const { return _buttonState; }
virtual int getModifierState() const { return _modifierState; }
virtual int shouldQuit() const { return _shouldQuit; }
virtual int shouldRTL() const { return _shouldRTL; }
virtual void resetRTL() { _shouldRTL = false; }
virtual Common::Keymapper *getKeymapper() { return _keymapper; }
};

View file

@ -0,0 +1,40 @@
/* 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$
* $Id$
*/
#include "backends/fs/abstract-fs.h"
const char *AbstractFilesystemNode::lastPathComponent(const Common::String &str, const char sep) {
// TODO: Get rid of this eventually! Use Common::lastPathComponent instead
if(str.empty())
return "";
const char *start = str.c_str();
const char *cur = start + str.size() - 2;
while (cur >= start && *cur != sep) {
--cur;
}
return cur + 1;
}

View file

@ -43,28 +43,27 @@ typedef Common::Array<AbstractFilesystemNode *> AbstractFSList;
*/
class AbstractFilesystemNode {
protected:
friend class FilesystemNode;
typedef Common::String String;
typedef FilesystemNode::ListMode ListMode;
friend class Common::FilesystemNode;
typedef Common::FilesystemNode::ListMode ListMode;
/**
* Returns the child node with the given name. If no child with this name
* exists, returns 0. When called on a non-directory node, it should
* handle this gracefully by returning 0.
* Returns the child node with the given name. When called on a non-directory
* node, it should handle this gracefully by returning 0.
* When called with a name not matching any of the files/dirs contained in this
* directory, a valid node shold be returned, which returns 'false' upon calling
* the exists() method. The idea is that this node can then still can be used to
* create a new file via the openForWriting() method.
*
* Example:
* Calling getChild() for a node with path "/foo/bar" using name="file.txt",
* would produce a new node with "/foo/bar/file.txt" as path.
*
* @note This function will append a separator char (\ or /) to the end of the
* path if needed.
*
* @note Handling calls on non-dir nodes gracefully makes it possible to
* switch to a lazy type detection scheme in the future.
*
* @param name String containing the name of the child to create a new node.
*/
virtual AbstractFilesystemNode *getChild(const String &name) const = 0;
virtual AbstractFilesystemNode *getChild(const Common::String &name) const = 0;
/**
* The parent node of this directory.
@ -72,6 +71,19 @@ protected:
*/
virtual AbstractFilesystemNode *getParent() const = 0;
/**
* Returns the last component of a given path.
*
* Examples:
* /foo/bar.txt would return /bar.txt
* /foo/bar/ would return /bar/
*
* @param str String containing the path.
* @param sep character used to separate path components
* @return Pointer to the first char of the last component inside str.
*/
static const char *lastPathComponent(const Common::String &str, const char sep);
public:
/**
* Destructor.
@ -100,7 +112,7 @@ public:
*
* @note By default, this method returns the value of getName().
*/
virtual String getDisplayName() const { return getName(); }
virtual Common::String getDisplayName() const { return getName(); }
/**
* Returns the last component of the path pointed by this FilesystemNode.
@ -111,12 +123,12 @@ public:
*
* @note This method is very architecture dependent, please check the concrete implementation for more information.
*/
virtual String getName() const = 0;
virtual Common::String getName() const = 0;
/**
* Returns the 'path' of the current node, usable in fopen().
*/
virtual String getPath() const = 0;
virtual Common::String getPath() const = 0;
/**
* Indicates whether this path refers to a directory or not.
@ -149,9 +161,26 @@ public:
*/
virtual bool isWritable() const = 0;
/* TODO:
bool isFile();
*/
/**
* Creates a SeekableReadStream instance corresponding to the file
* referred by this node. This assumes that the node actually refers
* to a readable file. If this is not the case, 0 is returned.
*
* @return pointer to the stream object, 0 in case of a failure
*/
virtual Common::SeekableReadStream *openForReading() = 0;
/**
* Creates a WriteStream instance corresponding to the file
* referred by this node. This assumes that the node actually refers
* to a readable file. If this is not the case, 0 is returned.
*
* @return pointer to the stream object, 0 in case of a failure
*/
virtual Common::WriteStream *openForWriting() = 0;
};
#endif //BACKENDS_ABSTRACT_FS_H

View file

@ -26,8 +26,6 @@
#include "backends/fs/amigaos4/amigaos4-fs-factory.h"
#include "backends/fs/amigaos4/amigaos4-fs.cpp"
DECLARE_SINGLETON(AmigaOSFilesystemFactory);
AbstractFilesystemNode *AmigaOSFilesystemFactory::makeRootFileNode() const {
return new AmigaOSFilesystemNode();
}
@ -36,7 +34,7 @@ AbstractFilesystemNode *AmigaOSFilesystemFactory::makeCurrentDirectoryFileNode()
return new AmigaOSFilesystemNode();
}
AbstractFilesystemNode *AmigaOSFilesystemFactory::makeFileNodePath(const String &path) const {
AbstractFilesystemNode *AmigaOSFilesystemFactory::makeFileNodePath(const Common::String &path) const {
return new AmigaOSFilesystemNode(path);
}
#endif

View file

@ -25,7 +25,6 @@
#ifndef AMIGAOS_FILESYSTEM_FACTORY_H
#define AMIGAOS_FILESYSTEM_FACTORY_H
#include "common/singleton.h"
#include "backends/fs/fs-factory.h"
/**
@ -33,19 +32,11 @@
*
* Parts of this class are documented in the base interface class, FilesystemFactory.
*/
class AmigaOSFilesystemFactory : public FilesystemFactory, public Common::Singleton<AmigaOSFilesystemFactory> {
class AmigaOSFilesystemFactory : public FilesystemFactory {
public:
typedef Common::String String;
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
protected:
AmigaOSFilesystemFactory() {};
private:
friend class Common::Singleton<SingletonBaseType>;
virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
};
#endif /*AMIGAOS_FILESYSTEM_FACTORY_H*/

View file

@ -36,8 +36,8 @@
#endif
#include "common/util.h"
#include "engines/engine.h"
#include "backends/fs/abstract-fs.h"
#include "backends/fs/stdiostream.h"
#define ENTER() /* debug(6, "Enter") */
#define LEAVE() /* debug(6, "Leave") */
@ -52,8 +52,8 @@ const uint32 kExAllBufferSize = 40960; // TODO: is this okay for sure?
class AmigaOSFilesystemNode : public AbstractFilesystemNode {
protected:
BPTR _pFileLock;
String _sDisplayName;
String _sPath;
Common::String _sDisplayName;
Common::String _sPath;
bool _bIsDirectory;
bool _bIsValid;
@ -74,9 +74,9 @@ public:
/**
* Creates a AmigaOSFilesystemNode for a given path.
*
* @param path String with the path the new node should point to.
* @param path Common::String with the path the new node should point to.
*/
AmigaOSFilesystemNode(const String &p);
AmigaOSFilesystemNode(const Common::String &p);
/**
* FIXME: document this constructor.
@ -96,17 +96,20 @@ public:
virtual ~AmigaOSFilesystemNode();
virtual bool exists() const;
virtual String getDisplayName() const { return _sDisplayName; };
virtual String getName() const { return _sDisplayName; };
virtual String getPath() const { return _sPath; };
virtual Common::String getDisplayName() const { return _sDisplayName; };
virtual Common::String getName() const { return _sDisplayName; };
virtual Common::String getPath() const { return _sPath; };
virtual bool isDirectory() const { return _bIsDirectory; };
virtual bool isReadable() const;
virtual bool isWritable() const;
virtual AbstractFilesystemNode *getChild(const String &n) const;
virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
virtual Common::SeekableReadStream *openForReading();
virtual Common::WriteStream *openForWriting();
/**
* Creates a list with all the volumes present in the root node.
*/
@ -116,7 +119,7 @@ public:
/**
* Returns the last component of a given path.
*
* @param str String containing the path.
* @param str Common::String containing the path.
* @return Pointer to the first char of the last component inside str.
*/
const char *lastPathComponent(const Common::String &str) {
@ -148,10 +151,10 @@ AmigaOSFilesystemNode::AmigaOSFilesystemNode() {
LEAVE();
}
AmigaOSFilesystemNode::AmigaOSFilesystemNode(const String &p) {
AmigaOSFilesystemNode::AmigaOSFilesystemNode(const Common::String &p) {
ENTER();
int len = 0, offset = p.size();
int offset = p.size();
//assert(offset > 0);
@ -161,7 +164,7 @@ AmigaOSFilesystemNode::AmigaOSFilesystemNode(const String &p) {
}
_sPath = p;
_sDisplayName = lastPathComponent(_sPath);
_sDisplayName = ::lastPathComponent(_sPath);
_pFileLock = 0;
_bIsDirectory = false;
@ -299,14 +302,14 @@ bool AmigaOSFilesystemNode::exists() const {
return nodeExists;
}
AbstractFilesystemNode *AmigaOSFilesystemNode::getChild(const String &n) const {
AbstractFilesystemNode *AmigaOSFilesystemNode::getChild(const Common::String &n) const {
ENTER();
if (!_bIsDirectory) {
debug(6, "Not a directory");
return 0;
}
String newPath(_sPath);
Common::String newPath(_sPath);
if (_sPath.lastChar() != '/')
newPath += '/';
@ -368,10 +371,10 @@ bool AmigaOSFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, b
struct ExAllData *ead = data;
do {
if ((mode == FilesystemNode::kListAll) ||
(EAD_IS_DRAWER(ead) && (mode == FilesystemNode::kListDirectoriesOnly)) ||
(EAD_IS_FILE(ead) && (mode == FilesystemNode::kListFilesOnly))) {
String full_path = _sPath;
if ((mode == Common::FilesystemNode::kListAll) ||
(EAD_IS_DRAWER(ead) && (mode == Common::FilesystemNode::kListDirectoriesOnly)) ||
(EAD_IS_FILE(ead) && (mode == Common::FilesystemNode::kListFilesOnly))) {
Common::String full_path = _sPath;
full_path += (char*)ead->ed_Name;
BPTR lock = IDOS->Lock((STRPTR)full_path.c_str(), SHARED_LOCK);
@ -566,4 +569,12 @@ AbstractFSList AmigaOSFilesystemNode::listVolumes() const {
return myList;
}
Common::SeekableReadStream *AmigaOSFilesystemNode::openForReading() {
return StdioStream::makeFromPath(getPath().c_str(), false);
}
Common::WriteStream *AmigaOSFilesystemNode::openForWriting() {
return StdioStream::makeFromPath(getPath().c_str(), true);
}
#endif //defined(__amigaos4__)

View file

@ -45,7 +45,7 @@ AbstractFilesystemNode *DSFilesystemFactory::makeCurrentDirectoryFileNode() cons
}
}
AbstractFilesystemNode *DSFilesystemFactory::makeFileNodePath(const String &path) const {
AbstractFilesystemNode *DSFilesystemFactory::makeFileNodePath(const Common::String &path) const {
if (DS::isGBAMPAvailable()) {
return new DS::GBAMPFileSystemNode(path);
} else {

View file

@ -35,11 +35,9 @@
*/
class DSFilesystemFactory : public FilesystemFactory, public Common::Singleton<DSFilesystemFactory> {
public:
typedef Common::String String;
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
protected:
DSFilesystemFactory() {};

View file

@ -24,6 +24,7 @@
#include "common/util.h"
//#include <NDS/ARM9/console.h> //basic print funcionality
#include "backends/fs/ds/ds-fs.h"
#include "backends/fs/stdiostream.h"
#include "dsmain.h"
#include "fat/gba_nds_fat.h"
@ -55,7 +56,7 @@ DSFileSystemNode::DSFileSystemNode() {
}
}
DSFileSystemNode::DSFileSystemNode(const String& path) {
DSFileSystemNode::DSFileSystemNode(const Common::String& path) {
// consolePrintf("--%s ",path.c_str());
char disp[128];
@ -70,7 +71,7 @@ DSFileSystemNode::DSFileSystemNode(const String& path) {
strcpy(disp, pathStr + lastSlash + 1);
_displayName = String(disp);
_displayName = Common::String(disp);
_path = path;
// _isValid = true;
// _isDirectory = false;
@ -98,7 +99,7 @@ DSFileSystemNode::DSFileSystemNode(const String& path) {
// consolePrintf("%s - Found: %d, Dir: %d\n", pathStr, _isValid, _isDirectory);
}
DSFileSystemNode::DSFileSystemNode(const String& path, bool isDir) {
DSFileSystemNode::DSFileSystemNode(const Common::String& path, bool isDir) {
// consolePrintf("--%s ",path.c_str());
char disp[128];
@ -112,7 +113,7 @@ DSFileSystemNode::DSFileSystemNode(const String& path, bool isDir) {
strcpy(disp, pathStr + lastSlash + 1);
_displayName = String(disp);
_displayName = Common::String(disp);
_path = path;
_isValid = true;
_isDirectory = isDir;
@ -167,10 +168,10 @@ bool DSFileSystemNode::getChildren(AbstractFSList &dirList, ListMode mode, bool
_zipFile->getFileName(n);
// consolePrintf("file: %s\n", n);
if ( (_zipFile->isDirectory() && ((mode == FilesystemNode::kListDirectoriesOnly) || (mode == FilesystemNode::kListAll)) )
|| (!_zipFile->isDirectory() && ((mode == FilesystemNode::kListFilesOnly) || (mode == FilesystemNode::kListAll)) ) )
if ( (_zipFile->isDirectory() && ((mode == Common::FilesystemNode::kListDirectoriesOnly) || (mode == Common::FilesystemNode::kListAll)) )
|| (!_zipFile->isDirectory() && ((mode == Common::FilesystemNode::kListFilesOnly) || (mode == Common::FilesystemNode::kListAll)) ) )
{
DSFileSystemNode* dsfsn = new DSFileSystemNode("ds:/" + String(n), _zipFile->isDirectory());
DSFileSystemNode* dsfsn = new DSFileSystemNode("ds:/" + Common::String(n), _zipFile->isDirectory());
dsfsn->_isDirectory = _zipFile->isDirectory();
dirList.push_back((dsfsn));
}
@ -195,7 +196,7 @@ AbstractFilesystemNode* DSFileSystemNode::getParent() const {
}
}
p = new DSFileSystemNode(String(path, lastSlash));
p = new DSFileSystemNode(Common::String(path, lastSlash));
((DSFileSystemNode *) (p))->_isDirectory = true;
} else {
p = new DSFileSystemNode();
@ -204,6 +205,14 @@ AbstractFilesystemNode* DSFileSystemNode::getParent() const {
return p;
}
Common::SeekableReadStream *DSFileSystemNode::openForReading() {
return StdioStream::makeFromPath(getPath().c_str(), false);
}
Common::WriteStream *DSFileSystemNode::openForWriting() {
return StdioStream::makeFromPath(getPath().c_str(), true);
}
//////////////////////////////////////////////////////////////////////////
// GBAMPFileSystemNode - File system using GBA Movie Player and CF card //
//////////////////////////////////////////////////////////////////////////
@ -216,7 +225,7 @@ GBAMPFileSystemNode::GBAMPFileSystemNode() {
_path = "mp:/";
}
GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path) {
GBAMPFileSystemNode::GBAMPFileSystemNode(const Common::String& path) {
// consolePrintf("'%s'",path.c_str());
char disp[128];
@ -245,13 +254,13 @@ GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path) {
}
// consolePrintf("Path: %s (%d)\n", check, success);
_displayName = String(disp);
_displayName = Common::String(disp);
_path = path;
_isValid = success == FT_FILE;
_isDirectory = success == FT_DIR;
}
GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path, bool isDirectory) {
GBAMPFileSystemNode::GBAMPFileSystemNode(const Common::String& path, bool isDirectory) {
// consolePrintf("'%s'",path.c_str());
char disp[128];
@ -265,7 +274,7 @@ GBAMPFileSystemNode::GBAMPFileSystemNode(const String& path, bool isDirectory) {
strcpy(disp, pathStr + lastSlash + 1);
_displayName = String(disp);
_displayName = Common::String(disp);
_path = path;
_isValid = true;
_isDirectory = isDirectory;
@ -313,8 +322,8 @@ bool GBAMPFileSystemNode::getChildren(AbstractFSList& dirList, ListMode mode, bo
while (entryType != TYPE_NO_MORE) {
if ( ((entryType == TYPE_DIR) && ((mode == FilesystemNode::kListDirectoriesOnly) || (mode == FilesystemNode::kListAll)))
|| ((entryType == TYPE_FILE) && ((mode == FilesystemNode::kListFilesOnly) || (mode == FilesystemNode::kListAll))) ) {
if ( ((entryType == TYPE_DIR) && ((mode == Common::FilesystemNode::kListDirectoriesOnly) || (mode == Common::FilesystemNode::kListAll)))
|| ((entryType == TYPE_FILE) && ((mode == Common::FilesystemNode::kListFilesOnly) || (mode == Common::FilesystemNode::kListAll))) ) {
GBAMPFileSystemNode* dsfsn;
consolePrintf("Fname: %s\n", fname);
@ -322,9 +331,9 @@ bool GBAMPFileSystemNode::getChildren(AbstractFSList& dirList, ListMode mode, bo
if (strcmp(fname, ".") && strcmp(fname, "..")) {
if (!strcmp(path, "/")) {
dsfsn = new GBAMPFileSystemNode("mp:" + String(path) + String(fname), entryType == TYPE_DIR);
dsfsn = new GBAMPFileSystemNode("mp:" + Common::String(path) + Common::String(fname), entryType == TYPE_DIR);
} else {
dsfsn = new GBAMPFileSystemNode("mp:" + String(path) + String("/") + String(fname), entryType == TYPE_DIR);
dsfsn = new GBAMPFileSystemNode("mp:" + Common::String(path) + Common::String("/") + Common::String(fname), entryType == TYPE_DIR);
}
// dsfsn->_isDirectory = entryType == DIR;
@ -358,7 +367,7 @@ AbstractFilesystemNode* GBAMPFileSystemNode::getParent() const {
}
}
p = new GBAMPFileSystemNode(String(path, lastSlash));
p = new GBAMPFileSystemNode(Common::String(path, lastSlash));
p->_isDirectory = true;
} else {
p = new GBAMPFileSystemNode();
@ -367,6 +376,14 @@ AbstractFilesystemNode* GBAMPFileSystemNode::getParent() const {
return p;
}
Common::SeekableReadStream *GBAMPFileSystemNode::openForReading() {
return StdioStream::makeFromPath(getPath().c_str(), false);
}
Common::WriteStream *GBAMPFileSystemNode::openForWriting() {
return StdioStream::makeFromPath(getPath().c_str(), true);
}
// Stdio replacements
#define MAX_FILE_HANDLES 32
@ -399,6 +416,7 @@ FILE* std_fopen(const char* name, const char* mode) {
if (DS::isGBAMPAvailable()) {
FAT_chdir("/");
// Turn all back slashes into forward slashes for gba_nds_fat
char* p = realName;
while (*p) {
if (*p == '\\') *p = '/';
@ -422,8 +440,12 @@ FILE* std_fopen(const char* name, const char* mode) {
// Allocate a file handle
int r = 0;
while (handle[r].used) r++;
while (handle[r].used) {
r++;
assert(r < MAX_FILE_HANDLES);
}
#ifdef GBA_SRAM_SAVE
if (strchr(mode, 'w')) {
// consolePrintf("Writing %s\n", realName);
handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, true);
@ -431,6 +453,7 @@ FILE* std_fopen(const char* name, const char* mode) {
// consolePrintf("Reading %s\n", realName);
handle[r].sramFile = (DSSaveFile *) DSSaveFileManager::instance()->openSavefile(realName, false);
}
#endif
if (handle[r].sramFile) {
handle[r].used = true;
@ -512,69 +535,6 @@ size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) {
return bytes / size;
}
return numItems;
/* int item = 0;
u8* data = (u8 *) ptr;
while ((item < numItems) && (!FAT_feof((FAT_FILE *) handle))) {
int bytes = 0;
while ((bytes < size) && (!FAT_feof((FAT_FILE *) handle))) {
*data++ = FAT_fgetc((FAT_FILE *) handle);
bytes++;
}
item++;
}
return item;
*/
int items = 0;
//for (int r = 0; r < numItems; r++) {
if (!std_feof(handle)) {
/* for (int t = 0; t < size; t++) {
if (feof(handle)) eof = true;
*(((char *) (ptr)) + r * size + t) = getc(handle);
}*/
int left = size * numItems;
int bytesRead = -1;
while ((left > 0) && (!FAT_feof((FAT_FILE *) handle))) {
int amount = left > 8192? 8192: left;
// do {
bytesRead = FAT_fread((void *) ptr, 1, amount, (FAT_FILE *) handle);
/* if (bytesRead == 0) {
consolePrintf("Pos:%d items:%d num:%d amount:%d read:%d\n", ftell(handle), items, numItems, amount, bytesRead);
left++;
int pos = ftell(handle);
fseek(handle, 0, SEEK_SET);
int c = getc(handle);
fseek(handle, pos - 1024, SEEK_SET);
fread(ptr, 1024, 1, handle);
swiWaitForVBlank();
//while (true);
}
} while (bytesRead == 0);
*/
left -= bytesRead;
ptr = ((char *) (ptr)) + bytesRead;
}
items = numItems - (left / size);
// FAT_fread((void *) ptr, size, 1, ((int) (handle)) - 1);
// ptr = ((char *) (ptr)) + size;
}
// }
// consolePrintf("...done %d \n", items)
return items;
}
if (handle->sramFile) {
@ -641,10 +601,6 @@ size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) {
}
}
void std_fprintf(FILE* handle, const char* fmt, ...) {
consolePrintf(fmt);
}
bool std_feof(FILE* handle) {
// consolePrintf("feof ");
@ -660,42 +616,10 @@ bool std_feof(FILE* handle) {
return handle->pos >= handle->size;
}
void std_fflush(FILE* handle) {
int std_fflush(FILE* handle) {
//FIXME: not implemented?
// consolePrintf("fflush ");
}
char* std_fgets(char* str, int size, FILE* file) {
// consolePrintf("fgets file=%d ", file);
if (DS::isGBAMPAvailable()) {
char* s = str;
while ((*s++ = std_getc(file)) >= 32) {
// consolePrintf("%d ", *s);
}
*s = 0;
// consolePrintf("Read:%s\n", str);
return str;
}
if (file->sramFile) {
file->pos--;
int p = -1;
do {
file->pos++;
p++;
file->sramFile->read((char *) &str[p], 1);
// consolePrintf("%d,", str[p]);
} while ((str[p] >= 32) && (!std_feof(file)) && (p < size));
str[p + 1] = 0;
file->pos++;
// consolePrintf("Read:%s\n", str);
return str;
}
return NULL;
return 0;
}
long int std_ftell(FILE* handle) {
@ -731,92 +655,20 @@ int std_fseek(FILE* handle, long int offset, int whence) {
return 0;
}
int std_ferror(FILE* handle) {
//FIXME: not implemented?
// consolePrintf("ferror ");
return 0;
}
void std_clearerr(FILE* handle) {
//FIXME: not implemented?
// consolePrintf("clearerr ");
}
int std_getc(FILE* handle) {
if (DS::isGBAMPAvailable()) {
char c;
FAT_fread(&c, 1, 1, (FAT_FILE *) handle);
return c;
}
// consolePrintf("fgetc ");
return 0; // Not supported yet
void std_fprintf(FILE* handle, const char* fmt, ...) {
consolePrintf(fmt);
}
char* std_getcwd(char* dir, int dunno) {
// consolePrintf("getcwd ");
dir[0] = '\0';
return dir; // Not supported yet
}
void std_cwd(char* dir) {
char buffer[128];
strcpy(buffer, dir);
char* realName = buffer;
if (DS::isGBAMPAvailable()) {
if ((strlen(dir) >= 4) && (dir[0] == 'm') && (dir[1] == 'p') && (dir[2] == ':') && (dir[3] == '/')) {
realName += 4;
}
// consolePrintf("Real cwd:%d\n", realName);
char* p = realName;
while (*p) {
if (*p == '\\') *p = '/';
p++;
}
// consolePrintf("Real cwd:%d\n", realName);
FAT_chdir(realName);
} else {
if ((strlen(dir) >= 4) && (dir[0] == 'd') && (dir[1] == 's') && (dir[2] == ':') && (dir[3] == '/')) {
realName += 4;
}
char* p = realName;
while (*p) {
if (*p == '\\') *p = '/';
p++;
}
strcpy(currentDir, realName);
if (*(currentDir + strlen(currentDir) - 1) == '/') {
*(currentDir + strlen(currentDir) - 1) = '\0';
}
// consolePrintf("CWD: %s\n", currentDir);
}
}
int std_ferror(FILE* handle) {
return 0;
}
} // namespace DS
/**
* Returns the last component of a given path.
*
* Examples:
* /foo/bar.txt would return /bar.txt
* /foo/bar/ would return /bar/
*
* @param str String containing the path.
* @return Pointer to the first char of the last component inside str.
*/
const char *lastPathComponent(const Common::String &str) {
const char *start = str.c_str();
const char *cur = start + str.size() - 2;
while (cur >= start && *cur != '/' && *cur != '\\') {
--cur;
}
return cur + 1;
}

View file

@ -41,12 +41,10 @@ namespace DS {
*/
class DSFileSystemNode : public AbstractFilesystemNode {
protected:
typedef class Common::String String;
static ZipFile* _zipFile;
String _displayName;
String _path;
Common::String _displayName;
Common::String _path;
bool _isDirectory;
bool _isValid;
@ -61,7 +59,7 @@ public:
*
* @param path String with the path the new node should point to.
*/
DSFileSystemNode(const String &path);
DSFileSystemNode(const Common::String &path);
/**
* Creates a DSFilesystemNode for a given path.
@ -69,7 +67,7 @@ public:
* @param path String with the path the new node should point to.
* @param path true if path is a directory, false otherwise.
*/
DSFileSystemNode(const String& path, bool isDir);
DSFileSystemNode(const Common::String& path, bool isDir);
/**
* Copy constructor.
@ -77,9 +75,9 @@ public:
DSFileSystemNode(const DSFileSystemNode *node);
virtual bool exists() const { return true; } //FIXME: this is just a stub
virtual String getDisplayName() const { return _displayName; }
virtual String getName() const { return _displayName; }
virtual String getPath() const { return _path; }
virtual Common::String getDisplayName() const { return _displayName; }
virtual Common::String getName() const { return _displayName; }
virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return true; } //FIXME: this is just a stub
virtual bool isWritable() const { return true; } //FIXME: this is just a stub
@ -89,9 +87,12 @@ public:
*/
virtual AbstractFilesystemNode *clone() const { return new DSFileSystemNode(this); }
virtual AbstractFilesystemNode *getChild(const Common::String& name) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode = FilesystemNode::kListDirectoriesOnly, bool hidden = false) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
virtual Common::SeekableReadStream *openForReading();
virtual Common::WriteStream *openForWriting();
/**
* Returns the zip file this node points to.
* TODO: check this documentation.
@ -107,10 +108,8 @@ public:
*/
class GBAMPFileSystemNode : public AbstractFilesystemNode {
protected:
typedef class Common::String String;
String _displayName;
String _path;
Common::String _displayName;
Common::String _path;
bool _isDirectory;
bool _isValid;
@ -125,7 +124,7 @@ public:
*
* @param path String with the path the new node should point to.
*/
GBAMPFileSystemNode(const String &path);
GBAMPFileSystemNode(const Common::String &path);
/**
* Creates a DSFilesystemNode for a given path.
@ -133,7 +132,7 @@ public:
* @param path String with the path the new node should point to.
* @param path true if path is a directory, false otherwise.
*/
GBAMPFileSystemNode(const String &path, bool isDirectory);
GBAMPFileSystemNode(const Common::String &path, bool isDirectory);
/**
* Copy constructor.
@ -141,9 +140,9 @@ public:
GBAMPFileSystemNode(const GBAMPFileSystemNode *node);
virtual bool exists() const { return _isValid || _isDirectory; }
virtual String getDisplayName() const { return _displayName; }
virtual String getName() const { return _displayName; }
virtual String getPath() const { return _path; }
virtual Common::String getDisplayName() const { return _displayName; }
virtual Common::String getName() const { return _displayName; }
virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return true; } //FIXME: this is just a stub
virtual bool isWritable() const { return true; } //FIXME: this is just a stub
@ -153,8 +152,11 @@ public:
*/
virtual AbstractFilesystemNode *clone() const { return new GBAMPFileSystemNode(this); }
virtual AbstractFilesystemNode *getChild(const Common::String& name) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode = FilesystemNode::kListDirectoriesOnly, bool hidden = false) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
virtual Common::SeekableReadStream *openForReading();
virtual Common::WriteStream *openForWriting();
};
struct fileHandle {
@ -179,15 +181,14 @@ struct fileHandle {
// Please do not remove any of these prototypes that appear not to be required.
FILE* std_fopen(const char* name, const char* mode);
void std_fclose(FILE* handle);
int std_getc(FILE* handle);
size_t std_fread(const void* ptr, size_t size, size_t numItems, FILE* handle);
size_t std_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle);
bool std_feof(FILE* handle);
long int std_ftell(FILE* handle);
int std_fseek(FILE* handle, long int offset, int whence);
void std_clearerr(FILE* handle);
void std_cwd(char* dir);
void std_fflush(FILE* handle);
int std_fflush(FILE* handle);
int std_ferror(FILE* handle);
} //namespace DS

View file

@ -36,7 +36,7 @@ AbstractFilesystemNode *PalmOSFilesystemFactory::makeCurrentDirectoryFileNode()
return new PalmOSFilesystemNode();
}
AbstractFilesystemNode *PalmOSFilesystemFactory::makeFileNodePath(const String &path) const {
AbstractFilesystemNode *PalmOSFilesystemFactory::makeFileNodePath(const Common::String &path) const {
return new PalmOSFilesystemNode(path);
}
#endif

View file

@ -35,11 +35,9 @@
*/
class PalmOSFilesystemFactory : public FilesystemFactory, public Common::Singleton<PalmOSFilesystemFactory> {
public:
typedef Common::String String;
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
protected:
PalmOSFilesystemFactory() {};

View file

@ -28,6 +28,7 @@
#include "globals.h"
#include "backends/fs/abstract-fs.h"
#include "backends/fs/stdiostream.h"
/**
* Implementation of the ScummVM file system API based on PalmOS VFS API.
@ -36,8 +37,8 @@
*/
class PalmOSFilesystemNode : public AbstractFilesystemNode {
protected:
String _displayName;
String _path;
Common::String _displayName;
Common::String _path;
bool _isDirectory;
bool _isValid;
bool _isPseudoRoot;
@ -51,22 +52,25 @@ public:
/**
* Creates a POSIXFilesystemNode for a given path.
*
* @param path String with the path the new node should point to.
* @param path Common::String with the path the new node should point to.
*/
PalmOSFilesystemNode(const String &p);
PalmOSFilesystemNode(const Common::String &p);
virtual bool exists() const { return _isValid; }
virtual String getDisplayName() const { return _displayName; }
virtual String getName() const { return _displayName; }
virtual String getPath() const { return _path; }
virtual Common::String getDisplayName() const { return _displayName; }
virtual Common::String getName() const { return _displayName; }
virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return true; } //FIXME: this is just a stub
virtual bool isWritable() const { return true; } //FIXME: this is just a stub
virtual AbstractFilesystemNode *getChild(const String &n) const;
virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
virtual Common::SeekableReadStream *openForReading();
virtual Common::WriteStream *openForWriting();
private:
/**
* Adds a single WindowsFilesystemNode to a given list.
@ -74,44 +78,20 @@ private:
*
* @param list List to put the file entry node in.
* @param mode Mode to use while adding the file entry to the list.
* @param base String with the directory being listed.
* @param base Common::String with the directory being listed.
* @param find_data Describes a file that the FindFirstFile, FindFirstFileEx, or FindNextFile functions find.
*/
static void addFile(AbstractFSList &list, ListMode mode, const Char *base, FileInfoType* find_data);
};
/**
* Returns the last component of a given path.
*
* Examples:
* /foo/bar.txt would return /bar.txt
* /foo/bar/ would return /bar/
*
* @param str String containing the path.
* @return Pointer to the first char of the last component inside str.
*/
const char *lastPathComponent(const Common::String &str) {
if(str.empty())
return "";
const char *start = str.c_str();
const char *cur = start + str.size() - 2;
while (cur >= start && *cur != '/') {
--cur;
}
return cur + 1;
}
void PalmOSFilesystemNode::addFile(AbstractFSList &list, ListMode mode, const char *base, FileInfoType* find_data) {
PalmOSFilesystemNode entry;
bool isDir;
isDir = (find_data->attributes & vfsFileAttrDirectory);
if ((!isDir && mode == FilesystemNode::kListDirectoriesOnly) ||
(isDir && mode == FilesystemNode::kListFilesOnly))
if ((!isDir && mode == Common::FilesystemNode::kListDirectoriesOnly) ||
(isDir && mode == Common::FilesystemNode::kListFilesOnly))
return;
entry._isDirectory = isDir;
@ -136,9 +116,9 @@ PalmOSFilesystemNode::PalmOSFilesystemNode() {
_isPseudoRoot = false;
}
PalmOSFilesystemNode::PalmOSFilesystemNode(const String &p) {
PalmOSFilesystemNode::PalmOSFilesystemNode(const Common::String &p) {
_path = p;
_displayName = lastPathComponent(_path);
_displayName = lastPathComponent(_path, '/');
UInt32 attr;
FileRef handle;
@ -159,10 +139,10 @@ PalmOSFilesystemNode::PalmOSFilesystemNode(const String &p) {
_isPseudoRoot = false;
}
AbstractFilesystemNode *PalmOSFilesystemNode::getChild(const String &n) const {
AbstractFilesystemNode *PalmOSFilesystemNode::getChild(const Common::String &n) const {
assert(_isDirectory);
String newPath(_path);
Common::String newPath(_path);
if (_path.lastChar() != '/')
newPath += '/';
newPath += n;
@ -215,17 +195,25 @@ AbstractFilesystemNode *PalmOSFilesystemNode::getParent() const {
if (!_isPseudoRoot) {
const char *start = _path.c_str();
const char *end = lastPathComponent(_path);
const char *end = lastPathComponent(_path, '/');
p = new PalmOSFilesystemNode();
p->_path = String(start, end - start);
p->_path = Common::String(start, end - start);
p->_isValid = true;
p->_isDirectory = true;
p->_displayName = lastPathComponent(p->_path);
p->_displayName = lastPathComponent(p->_path, '/');
p->_isPseudoRoot =(p->_path == "/");
}
return p;
}
Common::SeekableReadStream *PalmOSFilesystemNode::openForReading() {
return StdioStream::makeFromPath(getPath().c_str(), false);
}
Common::WriteStream *PalmOSFilesystemNode::openForWriting() {
return StdioStream::makeFromPath(getPath().c_str(), true);
}
#endif // PALMOS_MODE

View file

@ -26,19 +26,18 @@
#include "backends/fs/posix/posix-fs-factory.h"
#include "backends/fs/posix/posix-fs.cpp"
DECLARE_SINGLETON(POSIXFilesystemFactory);
AbstractFilesystemNode *POSIXFilesystemFactory::makeRootFileNode() const {
return new POSIXFilesystemNode();
return new POSIXFilesystemNode("/");
}
AbstractFilesystemNode *POSIXFilesystemFactory::makeCurrentDirectoryFileNode() const {
char buf[MAXPATHLEN];
getcwd(buf, MAXPATHLEN);
return new POSIXFilesystemNode(buf, true);
return new POSIXFilesystemNode(buf);
}
AbstractFilesystemNode *POSIXFilesystemFactory::makeFileNodePath(const String &path) const {
return new POSIXFilesystemNode(path, true);
AbstractFilesystemNode *POSIXFilesystemFactory::makeFileNodePath(const Common::String &path) const {
assert(!path.empty());
return new POSIXFilesystemNode(path);
}
#endif

View file

@ -25,7 +25,6 @@
#ifndef POSIX_FILESYSTEM_FACTORY_H
#define POSIX_FILESYSTEM_FACTORY_H
#include "common/singleton.h"
#include "backends/fs/fs-factory.h"
/**
@ -33,19 +32,10 @@
*
* Parts of this class are documented in the base interface class, FilesystemFactory.
*/
class POSIXFilesystemFactory : public FilesystemFactory, public Common::Singleton<POSIXFilesystemFactory> {
public:
typedef Common::String String;
class POSIXFilesystemFactory : public FilesystemFactory {
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
protected:
POSIXFilesystemFactory() {};
private:
friend class Common::Singleton<SingletonBaseType>;
virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
};
#endif /*POSIX_FILESYSTEM_FACTORY_H*/

View file

@ -24,85 +24,20 @@
#if defined(UNIX)
#include "backends/fs/abstract-fs.h"
#include "backends/fs/posix/posix-fs.h"
#include "backends/fs/stdiostream.h"
#include "common/algorithm.h"
#ifdef MACOSX
#include <sys/types.h>
#endif
#include <sys/param.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdio.h>
#include <unistd.h>
/**
* Implementation of the ScummVM file system API based on POSIX.
*
* Parts of this class are documented in the base interface class, AbstractFilesystemNode.
*/
class POSIXFilesystemNode : public AbstractFilesystemNode {
protected:
String _displayName;
String _path;
bool _isDirectory;
bool _isValid;
#ifdef __OS2__
#define INCL_DOS
#include <os2.h>
#endif
public:
/**
* Creates a POSIXFilesystemNode with the root node as path.
*/
POSIXFilesystemNode();
/**
* Creates a POSIXFilesystemNode for a given path.
*
* @param path String with the path the new node should point to.
* @param verify true if the isValid and isDirectory flags should be verified during the construction.
*/
POSIXFilesystemNode(const String &path, bool verify);
virtual bool exists() const { return access(_path.c_str(), F_OK) == 0; }
virtual String getDisplayName() const { return _displayName; }
virtual String getName() const { return _displayName; }
virtual String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; }
virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; }
virtual AbstractFilesystemNode *getChild(const String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
private:
/**
* Tests and sets the _isValid and _isDirectory flags, using the stat() function.
*/
virtual void setFlags();
};
/**
* Returns the last component of a given path.
*
* Examples:
* /foo/bar.txt would return /bar.txt
* /foo/bar/ would return /bar/
*
* @param str String containing the path.
* @return Pointer to the first char of the last component inside str.
*/
const char *lastPathComponent(const Common::String &str) {
if(str.empty())
return "";
const char *start = str.c_str();
const char *cur = start + str.size() - 2;
while (cur >= start && *cur != '/') {
--cur;
}
return cur + 1;
}
void POSIXFilesystemNode::setFlags() {
struct stat st;
@ -111,15 +46,7 @@ void POSIXFilesystemNode::setFlags() {
_isDirectory = _isValid ? S_ISDIR(st.st_mode) : false;
}
POSIXFilesystemNode::POSIXFilesystemNode() {
// The root dir.
_path = "/";
_displayName = _path;
_isValid = true;
_isDirectory = true;
}
POSIXFilesystemNode::POSIXFilesystemNode(const String &p, bool verify) {
POSIXFilesystemNode::POSIXFilesystemNode(const Common::String &p) {
assert(p.size() > 0);
// Expand "~/" to the value of the HOME env variable
@ -134,30 +61,85 @@ POSIXFilesystemNode::POSIXFilesystemNode(const String &p, bool verify) {
} else {
_path = p;
}
#ifdef __OS2__
// On OS/2, 'X:/' is a root of drive X, so we should not remove that last
// slash.
if (!(_path.size() == 3 && _path.hasSuffix(":/")))
#endif
// Normalize the path (that is, remove unneeded slashes etc.)
_path = Common::normalizePath(_path, '/');
_displayName = Common::lastPathComponent(_path, '/');
_displayName = lastPathComponent(_path);
if (verify) {
setFlags();
// TODO: should we turn relative paths into absolute ones?
// Pro: Ensures the "getParent" works correctly even for relative dirs.
// Contra: The user may wish to use (and keep!) relative paths in his
// config file, and converting relative to absolute paths may hurt him...
//
// An alternative approach would be to change getParent() to work correctly
// if "_path" is the empty string.
#if 0
if (!_path.hasPrefix("/")) {
char buf[MAXPATHLEN+1];
getcwd(buf, MAXPATHLEN);
strcat(buf, "/");
_path = buf + _path;
}
#endif
// TODO: Should we enforce that the path is absolute at this point?
//assert(_path.hasPrefix("/"));
setFlags();
}
AbstractFilesystemNode *POSIXFilesystemNode::getChild(const String &n) const {
// FIXME: Pretty lame implementation! We do no error checking to speak
// of, do not check if this is a special node, etc.
AbstractFilesystemNode *POSIXFilesystemNode::getChild(const Common::String &n) const {
assert(!_path.empty());
assert(_isDirectory);
// Make sure the string contains no slashes
assert(!n.contains('/'));
String newPath(_path);
// We assume here that _path is already normalized (hence don't bother to call
// Common::normalizePath on the final path).
Common::String newPath(_path);
if (_path.lastChar() != '/')
newPath += '/';
newPath += n;
return new POSIXFilesystemNode(newPath, true);
return makeNode(newPath);
}
bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool hidden) const {
assert(_isDirectory);
#ifdef __OS2__
if (_path == "/") {
// Special case for the root dir: List all DOS drives
ULONG ulDrvNum;
ULONG ulDrvMap;
DosQueryCurrentDisk(&ulDrvNum, &ulDrvMap);
for (int i = 0; i < 26; i++) {
if (ulDrvMap & 1) {
char drive_root[] = "A:/";
drive_root[0] += i;
POSIXFilesystemNode *entry = new POSIXFilesystemNode();
entry->_isDirectory = true;
entry->_isValid = true;
entry->_path = drive_root;
entry->_displayName = "[" + Common::String(drive_root, 2) + "]";
myList.push_back(entry);
}
ulDrvMap >>= 1;
}
return true;
}
#endif
DIR *dirp = opendir(_path.c_str());
struct dirent *dp;
@ -175,12 +157,12 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, boo
continue;
}
String newPath(_path);
if (newPath.lastChar() != '/')
newPath += '/';
newPath += dp->d_name;
POSIXFilesystemNode entry(newPath, false);
// Start with a clone of this node, with the correct path set
POSIXFilesystemNode entry(*this);
entry._displayName = dp->d_name;
if (_path.lastChar() != '/')
entry._path += '/';
entry._path += entry._displayName;
#if defined(SYSTEM_NOT_SUPPORTING_D_TYPE)
/* TODO: d_type is not part of POSIX, so it might not be supported
@ -215,13 +197,10 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, boo
continue;
// Honor the chosen mode
if ((mode == FilesystemNode::kListFilesOnly && entry._isDirectory) ||
(mode == FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
if ((mode == Common::FilesystemNode::kListFilesOnly && entry._isDirectory) ||
(mode == Common::FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
continue;
if (entry._isDirectory)
entry._path += "/";
myList.push_back(new POSIXFilesystemNode(entry));
}
closedir(dirp);
@ -231,12 +210,39 @@ bool POSIXFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, boo
AbstractFilesystemNode *POSIXFilesystemNode::getParent() const {
if (_path == "/")
return 0;
return 0; // The filesystem root has no parent
#ifdef __OS2__
if (_path.size() == 3 && _path.hasSuffix(":/"))
// This is a root directory of a drive
return makeNode("/"); // return a virtual root for a list of drives
#endif
const char *start = _path.c_str();
const char *end = lastPathComponent(_path);
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--;
return new POSIXFilesystemNode(String(start, end - start), true);
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 makeNode(Common::String(start, end));
}
Common::SeekableReadStream *POSIXFilesystemNode::openForReading() {
return StdioStream::makeFromPath(getPath().c_str(), false);
}
Common::WriteStream *POSIXFilesystemNode::openForWriting() {
return StdioStream::makeFromPath(getPath().c_str(), true);
}
#endif //#if defined(UNIX)

View file

@ -0,0 +1,86 @@
/* 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$
* $Id$
*/
#ifndef POSIX_FILESYSTEM_H
#define POSIX_FILESYSTEM_H
#include "backends/fs/abstract-fs.h"
#ifdef MACOSX
#include <sys/types.h>
#endif
#include <unistd.h>
/**
* Implementation of the ScummVM file system API based on POSIX.
*
* Parts of this class are documented in the base interface class, AbstractFilesystemNode.
*/
class POSIXFilesystemNode : public AbstractFilesystemNode {
protected:
Common::String _displayName;
Common::String _path;
bool _isDirectory;
bool _isValid;
virtual AbstractFilesystemNode *makeNode(const Common::String &path) const {
return new POSIXFilesystemNode(path);
}
/**
* Plain constructor, for internal use only (hence protected).
*/
POSIXFilesystemNode() : _isDirectory(false), _isValid(false) {}
public:
/**
* Creates a POSIXFilesystemNode for a given path.
*
* @param path the path the new node should point to.
*/
POSIXFilesystemNode(const Common::String &path);
virtual bool exists() const { return access(_path.c_str(), F_OK) == 0; }
virtual Common::String getDisplayName() const { return _displayName; }
virtual Common::String getName() const { return _displayName; }
virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; }
virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; }
virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
virtual Common::SeekableReadStream *openForReading();
virtual Common::WriteStream *openForWriting();
private:
/**
* Tests and sets the _isValid and _isDirectory flags, using the stat() function.
*/
virtual void setFlags();
};
#endif /*POSIX_FILESYSTEM_H*/

View file

@ -36,7 +36,7 @@ AbstractFilesystemNode *Ps2FilesystemFactory::makeCurrentDirectoryFileNode() con
return new Ps2FilesystemNode();
}
AbstractFilesystemNode *Ps2FilesystemFactory::makeFileNodePath(const String &path) const {
AbstractFilesystemNode *Ps2FilesystemFactory::makeFileNodePath(const Common::String &path) const {
// return new Ps2FilesystemNode(path);
Ps2FilesystemNode *nf = new Ps2FilesystemNode(path, true);

View file

@ -35,11 +35,9 @@
*/
class Ps2FilesystemFactory : public FilesystemFactory, public Common::Singleton<Ps2FilesystemFactory> {
public:
typedef Common::String String;
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
protected:
Ps2FilesystemFactory() {};

View file

@ -23,6 +23,7 @@
*/
#include "backends/fs/abstract-fs.h"
#include "backends/fs/stdiostream.h"
#include <kernel.h>
#include <stdio.h>
#include <stdlib.h>
@ -47,8 +48,8 @@ class Ps2FilesystemNode : public AbstractFilesystemNode {
friend class Ps2FilesystemFactory;
protected:
String _displayName;
String _path;
Common::String _displayName;
Common::String _path;
bool _isDirectory;
bool _isRoot;
@ -65,10 +66,10 @@ public:
/**
* Creates a PS2FilesystemNode for a given path.
*
* @param path String with the path the new node should point to.
* @param path Common::String with the path the new node should point to.
*/
Ps2FilesystemNode(const String &path);
Ps2FilesystemNode(const String &path, bool verify);
Ps2FilesystemNode(const Common::String &path);
Ps2FilesystemNode(const Common::String &path, bool verify);
/**
* Copy constructor.
@ -77,9 +78,9 @@ public:
virtual bool exists(void) const;
virtual String getDisplayName() const { return _displayName; }
virtual String getName() const { return _displayName; }
virtual String getPath() const { return _path; }
virtual Common::String getDisplayName() const { return _displayName; }
virtual Common::String getName() const { return _displayName; }
virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const {
return _isDirectory;
@ -95,33 +96,14 @@ public:
}
virtual AbstractFilesystemNode *clone() const { return new Ps2FilesystemNode(this); }
virtual AbstractFilesystemNode *getChild(const String &n) const;
virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
virtual Common::SeekableReadStream *openForReading();
virtual Common::WriteStream *openForWriting();
};
/**
* Returns the last component of a given path.
*
* @param str String containing the path.
* @return Pointer to the first char of the last component inside str.
*/
const char *lastPathComponent(const Common::String &str) {
if (str.empty())
return "";
const char *start = str.c_str();
const char *cur = start + str.size() - 2;
while (cur >= start && *cur != '/' && *cur != ':') {
--cur;
}
printf("romeo : lastPathComponent = %s\n", cur + 1);
return cur + 1;
}
Ps2FilesystemNode::Ps2FilesystemNode() {
_isDirectory = true;
_isRoot = true;
@ -129,12 +111,12 @@ Ps2FilesystemNode::Ps2FilesystemNode() {
_path = "";
}
Ps2FilesystemNode::Ps2FilesystemNode(const String &path) {
Ps2FilesystemNode::Ps2FilesystemNode(const Common::String &path) {
_path = path;
_isDirectory = true;
if (strcmp(path.c_str(), "") == 0) {
_isRoot = true;
_displayName = String("PlayStation 2");
_displayName = Common::String("PlayStation 2");
} else {
_isRoot = false;
const char *dsplName = NULL, *pos = path.c_str();
@ -142,18 +124,18 @@ Ps2FilesystemNode::Ps2FilesystemNode(const String &path) {
if (*pos++ == '/')
dsplName = pos;
if (dsplName)
_displayName = String(dsplName);
_displayName = Common::String(dsplName);
else
_displayName = getDeviceDescription(path.c_str());
}
}
Ps2FilesystemNode::Ps2FilesystemNode(const String &path, bool verify) {
Ps2FilesystemNode::Ps2FilesystemNode(const Common::String &path, bool verify) {
_path = path;
if (strcmp(path.c_str(), "") == 0) {
_isRoot = true; /* root is always a dir*/
_displayName = String("PlayStation 2");
_displayName = Common::String("PlayStation 2");
_isDirectory = true;
} else {
_isRoot = false;
@ -163,7 +145,7 @@ Ps2FilesystemNode::Ps2FilesystemNode(const String &path, bool verify) {
dsplName = pos;
if (dsplName) {
_displayName = String(dsplName);
_displayName = Common::String(dsplName);
if (verify)
_isDirectory = getDirectoryFlag(path.c_str());
else
@ -228,7 +210,7 @@ bool Ps2FilesystemNode::getDirectoryFlag(const char *path) {
return false;
}
AbstractFilesystemNode *Ps2FilesystemNode::getChild(const String &n) const {
AbstractFilesystemNode *Ps2FilesystemNode::getChild(const Common::String &n) const {
if (!_isDirectory)
return NULL;
@ -306,9 +288,9 @@ bool Ps2FilesystemNode::getChildren(AbstractFSList &list, ListMode mode, bool hi
while ((dreadRes = fio.dread(fd, &dirent)) > 0) {
if (dirent.name[0] == '.')
continue; // ignore '.' and '..'
if (((mode == FilesystemNode::kListDirectoriesOnly) && (dirent.stat.mode & FIO_S_IFDIR)) ||
((mode == FilesystemNode::kListFilesOnly) && !(dirent.stat.mode & FIO_S_IFDIR)) ||
(mode == FilesystemNode::kListAll)) {
if (((mode == Common::FilesystemNode::kListDirectoriesOnly) && (dirent.stat.mode & FIO_S_IFDIR)) ||
((mode == Common::FilesystemNode::kListFilesOnly) && !(dirent.stat.mode & FIO_S_IFDIR)) ||
(mode == Common::FilesystemNode::kListAll)) {
dirEntry._isDirectory = (bool)(dirent.stat.mode & FIO_S_IFDIR);
dirEntry._isRoot = false;
@ -344,7 +326,7 @@ AbstractFilesystemNode *Ps2FilesystemNode::getParent() const {
}
if (slash)
return new Ps2FilesystemNode(String(_path.c_str(), slash - _path.c_str()));
return new Ps2FilesystemNode(Common::String(_path.c_str(), slash - _path.c_str()));
else
return new Ps2FilesystemNode();
}
@ -359,3 +341,10 @@ char *Ps2FilesystemNode::getDeviceDescription(const char *path) const {
return "Harddisk";
}
Common::SeekableReadStream *Ps2FilesystemNode::openForReading() {
return StdioStream::makeFromPath(getPath().c_str(), false);
}
Common::WriteStream *Ps2FilesystemNode::openForWriting() {
return StdioStream::makeFromPath(getPath().c_str(), true);
}

View file

@ -36,7 +36,7 @@ AbstractFilesystemNode *PSPFilesystemFactory::makeCurrentDirectoryFileNode() con
return new PSPFilesystemNode();
}
AbstractFilesystemNode *PSPFilesystemFactory::makeFileNodePath(const String &path) const {
AbstractFilesystemNode *PSPFilesystemFactory::makeFileNodePath(const Common::String &path) const {
return new PSPFilesystemNode(path, true);
}
#endif

View file

@ -35,11 +35,9 @@
*/
class PSPFilesystemFactory : public FilesystemFactory, public Common::Singleton<PSPFilesystemFactory> {
public:
typedef Common::String String;
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
protected:
PSPFilesystemFactory() {};

View file

@ -26,6 +26,7 @@
#include "engines/engine.h"
#include "backends/fs/abstract-fs.h"
#include "backends/fs/stdiostream.h"
#include <sys/stat.h>
#include <unistd.h>
@ -39,8 +40,8 @@
*/
class PSPFilesystemNode : public AbstractFilesystemNode {
protected:
String _displayName;
String _path;
Common::String _displayName;
Common::String _path;
bool _isDirectory;
bool _isValid;
@ -53,48 +54,27 @@ public:
/**
* Creates a PSPFilesystemNode for a given path.
*
* @param path String with the path the new node should point to.
* @param path Common::String with the path the new node should point to.
* @param verify true if the isValid and isDirectory flags should be verified during the construction.
*/
PSPFilesystemNode(const Common::String &p, bool verify);
virtual bool exists() const { return access(_path.c_str(), F_OK) == 0; }
virtual String getDisplayName() const { return _displayName; }
virtual String getName() const { return _displayName; }
virtual String getPath() const { return _path; }
virtual Common::String getDisplayName() const { return _displayName; }
virtual Common::String getName() const { return _displayName; }
virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; }
virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; }
virtual AbstractFilesystemNode *getChild(const String &n) const;
virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
virtual Common::SeekableReadStream *openForReading();
virtual Common::WriteStream *openForWriting();
};
/**
* Returns the last component of a given path.
*
* Examples:
* /foo/bar.txt would return /bar.txt
* /foo/bar/ would return /bar/
*
* @param str String containing the path.
* @return Pointer to the first char of the last component inside str.
*/
const char *lastPathComponent(const Common::String &str) {
if(str.empty())
return "";
const char *start = str.c_str();
const char *cur = start + str.size() - 2;
while (cur >= start && *cur != '/') {
--cur;
}
return cur + 1;
}
PSPFilesystemNode::PSPFilesystemNode() {
_isDirectory = true;
_displayName = "Root";
@ -106,7 +86,7 @@ PSPFilesystemNode::PSPFilesystemNode(const Common::String &p, bool verify) {
assert(p.size() > 0);
_path = p;
_displayName = lastPathComponent(_path);
_displayName = lastPathComponent(_path, '/');
_isValid = true;
_isDirectory = true;
@ -117,12 +97,12 @@ PSPFilesystemNode::PSPFilesystemNode(const Common::String &p, bool verify) {
}
}
AbstractFilesystemNode *PSPFilesystemNode::getChild(const String &n) const {
AbstractFilesystemNode *PSPFilesystemNode::getChild(const Common::String &n) const {
// FIXME: Pretty lame implementation! We do no error checking to speak
// of, do not check if this is a special node, etc.
assert(_isDirectory);
String newPath(_path);
Common::String newPath(_path);
if (_path.lastChar() != '/')
newPath += '/';
newPath += n;
@ -157,8 +137,8 @@ bool PSPFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool
entry._path += "/";
// Honor the chosen mode
if ((mode == FilesystemNode::kListFilesOnly && entry._isDirectory) ||
(mode == FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
if ((mode == Common::FilesystemNode::kListFilesOnly && entry._isDirectory) ||
(mode == Common::FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
continue;
myList.push_back(new PSPFilesystemNode(entry));
@ -176,9 +156,17 @@ AbstractFilesystemNode *PSPFilesystemNode::getParent() const {
return 0;
const char *start = _path.c_str();
const char *end = lastPathComponent(_path);
const char *end = lastPathComponent(_path, '/');
return new PSPFilesystemNode(String(start, end - start), false);
return new PSPFilesystemNode(Common::String(start, end - start), false);
}
Common::SeekableReadStream *PSPFilesystemNode::openForReading() {
return StdioStream::makeFromPath(getPath().c_str(), false);
}
Common::WriteStream *PSPFilesystemNode::openForWriting() {
return StdioStream::makeFromPath(getPath().c_str(), true);
}
#endif //#ifdef __PSP__

161
backends/fs/stdiostream.cpp Normal file
View file

@ -0,0 +1,161 @@
/* 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$
* $Id$
*
*/
#include "backends/fs/stdiostream.h"
#include <errno.h>
#if defined(MACOSX) || defined(IPHONE)
#include "CoreFoundation/CoreFoundation.h"
#endif
#ifdef __PLAYSTATION2__
// for those replaced fopen/fread/etc functions
typedef unsigned long uint64;
typedef signed long int64;
#include "backends/platform/ps2/fileio.h"
#define fopen(a, b) ps2_fopen(a, b)
#define fclose(a) ps2_fclose(a)
#define fseek(a, b, c) ps2_fseek(a, b, c)
#define ftell(a) ps2_ftell(a)
#define feof(a) ps2_feof(a)
#define fread(a, b, c, d) ps2_fread(a, b, c, d)
#define fwrite(a, b, c, d) ps2_fwrite(a, b, c, d)
//#define fprintf ps2_fprintf // used in common/util.cpp
//#define fflush(a) ps2_fflush(a) // used in common/util.cpp
//#define fgetc(a) ps2_fgetc(a) // not used
//#define fgets(a, b, c) ps2_fgets(a, b, c) // not used
//#define fputc(a, b) ps2_fputc(a, b) // not used
//#define fputs(a, b) ps2_fputs(a, b) // not used
//#define fsize(a) ps2_fsize(a) // not used -- and it is not a standard function either
#endif
#ifdef __DS__
// These functions replace the standard library functions of the same name.
// As this header is included after the standard one, I have the chance to #define
// all of these to my own code.
//
// A #define is the only way, as redefinig the functions would cause linker errors.
// These functions need to be #undef'ed, as their original definition
// in devkitarm is done with #includes (ugh!)
#undef feof
#undef clearerr
//#undef getc
//#undef ferror
#include "backends/fs/ds/ds-fs.h"
// Only functions used in the ScummVM source have been defined here!
#define fopen(name, mode) DS::std_fopen(name, mode)
#define fclose(handle) DS::std_fclose(handle)
#define fread(ptr, size, items, file) DS::std_fread(ptr, size, items, file)
#define fwrite(ptr, size, items, file) DS::std_fwrite(ptr, size, items, file)
#define feof(handle) DS::std_feof(handle)
#define ftell(handle) DS::std_ftell(handle)
#define fseek(handle, offset, whence) DS::std_fseek(handle, offset, whence)
#define clearerr(handle) DS::std_clearerr(handle)
#define fflush(file) DS::std_fflush(file)
#define ferror(handle) DS::std_ferror(handle)
#endif
StdioStream::StdioStream(void *handle) : _handle(handle) {
assert(handle);
}
StdioStream::~StdioStream() {
fclose((FILE *)_handle);
}
bool StdioStream::err() const {
return ferror((FILE *)_handle) != 0;
}
void StdioStream::clearErr() {
clearerr((FILE *)_handle);
}
bool StdioStream::eos() const {
return feof((FILE *)_handle) != 0;
}
int32 StdioStream::pos() const {
return ftell((FILE *)_handle);
}
int32 StdioStream::size() const {
int32 oldPos = ftell((FILE *)_handle);
fseek((FILE *)_handle, 0, SEEK_END);
int32 length = ftell((FILE *)_handle);
fseek((FILE *)_handle, oldPos, SEEK_SET);
return length;
}
bool StdioStream::seek(int32 offs, int whence) {
return fseek((FILE *)_handle, offs, whence) == 0;
}
uint32 StdioStream::read(void *ptr, uint32 len) {
return fread((byte *)ptr, 1, len, (FILE *)_handle);
}
uint32 StdioStream::write(const void *ptr, uint32 len) {
return fwrite(ptr, 1, len, (FILE *)_handle);
}
bool StdioStream::flush() {
return fflush((FILE *)_handle) == 0;
}
StdioStream *StdioStream::makeFromPath(const Common::String &path, bool writeMode) {
FILE *handle = fopen(path.c_str(), writeMode ? "wb" : "rb");
#ifdef __amigaos4__
//
// Work around for possibility that someone uses AmigaOS "newlib" build
// with SmartFileSystem (blocksize 512 bytes), leading to buffer size
// being only 512 bytes. "Clib2" sets the buffer size to 8KB, resulting
// smooth movie playback. This forces the buffer to be enough also when
// using "newlib" compile on SFS.
//
if (handle && !writeMode) {
setvbuf(handle, NULL, _IOFBF, 8192);
}
#endif
if (handle)
return new StdioStream(handle);
return 0;
}

View file

@ -23,70 +23,40 @@
*
*/
#ifndef SCUMM_SMUSH_CHUNK_H
#define SCUMM_SMUSH_CHUNK_H
#ifndef BACKENDS_FS_STDIOSTREAM_H
#define BACKENDS_FS_STDIOSTREAM_H
#include "common/scummsys.h"
#include "common/str.h"
#include "common/noncopyable.h"
#include "common/stream.h"
#include "common/str.h"
namespace Scumm {
class BaseScummFile;
class Chunk : public Common::SeekableReadStream {
public:
typedef uint32 type;
virtual type getType() const = 0;
virtual Chunk *subBlock() = 0;
virtual void reseek() = 0;
};
// Common functionality for concrete chunks (FileChunk, MemoryChunk)
class BaseChunk : public Chunk {
class StdioStream : public Common::SeekableReadStream, public Common::WriteStream, public Common::NonCopyable {
protected:
Chunk::type _type;
uint32 _size;
uint32 _curPos;
Common::String _name;
BaseChunk();
/** File handle to the actual file. */
void *_handle;
public:
Chunk::type getType() const;
uint32 size() const;
/**
* Given a path, invokes fopen on that path and wrap the result in a
* StdioStream instance.
*/
static StdioStream *makeFromPath(const Common::String &path, bool writeMode);
StdioStream(void *handle);
virtual ~StdioStream();
bool err() const;
void clearErr();
bool eos() const;
uint32 pos() const;
void seek(int32 delta, int dir);
virtual uint32 write(const void *dataPtr, uint32 dataSize);
virtual bool flush();
virtual int32 pos() const;
virtual int32 size() const;
bool seek(int32 offs, int whence = SEEK_SET);
uint32 read(void *dataPtr, uint32 dataSize);
};
class FileChunk : public BaseChunk {
private:
BaseScummFile *_data;
bool _deleteData;
uint32 _offset;
FileChunk(BaseScummFile *data, int offset);
public:
FileChunk(const Common::String &name, int offset = 0);
virtual ~FileChunk();
Chunk *subBlock();
void reseek();
uint32 read(void *buffer, uint32 size);
};
class MemoryChunk : public BaseChunk {
private:
byte *_data;
public:
MemoryChunk(byte *data);
Chunk *subBlock();
void reseek();
uint32 read(void *buffer, uint32 size);
};
} // End of namespace Scumm
#endif

View file

@ -26,8 +26,6 @@
#include "backends/fs/symbian/symbian-fs-factory.h"
#include "backends/fs/symbian/symbian-fs.cpp"
DECLARE_SINGLETON(SymbianFilesystemFactory);
AbstractFilesystemNode *SymbianFilesystemFactory::makeRootFileNode() const {
return new SymbianFilesystemNode(true);
}
@ -38,7 +36,7 @@ AbstractFilesystemNode *SymbianFilesystemFactory::makeCurrentDirectoryFileNode()
return new SymbianFilesystemNode(path);
}
AbstractFilesystemNode *SymbianFilesystemFactory::makeFileNodePath(const String &path) const {
AbstractFilesystemNode *SymbianFilesystemFactory::makeFileNodePath(const Common::String &path) const {
return new SymbianFilesystemNode(path);
}
#endif

View file

@ -25,7 +25,6 @@
#ifndef SYMBIAN_FILESYSTEM_FACTORY_H
#define SYMBIAN_FILESYSTEM_FACTORY_H
#include "common/singleton.h"
#include "backends/fs/fs-factory.h"
/**
@ -33,19 +32,11 @@
*
* Parts of this class are documented in the base interface class, FilesystemFactory.
*/
class SymbianFilesystemFactory : public FilesystemFactory, public Common::Singleton<SymbianFilesystemFactory> {
class SymbianFilesystemFactory : public FilesystemFactory {
public:
typedef Common::String String;
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
protected:
SymbianFilesystemFactory() {};
private:
friend class Common::Singleton<SingletonBaseType>;
virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
};
#endif /*SYMBIAN_FILESYSTEM_FACTORY_H*/

View file

@ -24,12 +24,16 @@
#if defined (__SYMBIAN32__)
#include "backends/fs/abstract-fs.h"
#include "backends/fs/symbian/symbianstream.h"
#include "backends/platform/symbian/src/symbianos.h"
#include <dirent.h>
#include <eikenv.h>
#include <f32file.h>
#include <bautils.h>
#define KDriveLabelSize 30
/**
* Implementation of the ScummVM file system API based on POSIX.
*
@ -37,12 +41,11 @@
*/
class SymbianFilesystemNode : public AbstractFilesystemNode {
protected:
String _displayName;
String _path;
bool _isDirectory;
bool _isValid;
bool _isPseudoRoot;
Common::String _displayName;
Common::String _path;
TBool _isDirectory;
TBool _isValid;
TBool _isPseudoRoot;
public:
/**
* Creates a SymbianFilesystemNode with the root node as path.
@ -54,57 +57,36 @@ public:
/**
* Creates a SymbianFilesystemNode for a given path.
*
* @param path String with the path the new node should point to.
* @param path Common::String with the path the new node should point to.
*/
SymbianFilesystemNode(const String &path);
SymbianFilesystemNode(const Common::String &path);
virtual bool exists() const {
TFileName fname;
TPtrC8 ptr((const unsigned char*)_path.c_str(),_path.size());
TPtrC8 ptr((const unsigned char*) _path.c_str(), _path.size());
fname.Copy(ptr);
TBool fileExists = BaflUtils::FileExists(CEikonEnv::Static()->FsSession(), fname);
TBool fileExists = BaflUtils::FileExists(static_cast<OSystem_SDL_Symbian*> (g_system)->FsSession(), fname);
return fileExists;
}
virtual String getDisplayName() const { return _displayName; }
virtual String getName() const { return _displayName; }
virtual String getPath() const { return _path; }
virtual Common::String getDisplayName() const { return _displayName; }
virtual Common::String getName() const { return _displayName; }
virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return access(_path.c_str(), R_OK) == 0; } //FIXME: this is just a stub
virtual bool isWritable() const { return access(_path.c_str(), W_OK) == 0; } //FIXME: this is just a stub
virtual AbstractFilesystemNode *getChild(const String &n) const;
virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
virtual Common::SeekableReadStream *openForReading();
virtual Common::WriteStream *openForWriting();
};
/**
* Returns the last component of a given path.
*
* Examples:
* c:\foo\bar.txt would return "\bar.txt"
* c:\foo\bar\ would return "\bar\"
*
* @param str Path to obtain the last component from.
* @return Pointer to the first char of the last component inside str.
*/
const char *lastPathComponent(const Common::String &str) {
if(str.empty())
return "";
const char *start = str.c_str();
const char *cur = start + str.size() - 2;
while (cur >= start && *cur != '\\') {
--cur;
}
return cur + 1;
}
/**
* Fixes the path by changing all slashes to backslashes.
*
* @param path String with the path to be fixed.
* @param path Common::String with the path to be fixed.
*/
static void fixFilePath(Common::String& aPath){
TInt len = aPath.size();
@ -118,54 +100,47 @@ static void fixFilePath(Common::String& aPath){
SymbianFilesystemNode::SymbianFilesystemNode(bool aIsRoot) {
_path = "";
_isValid = true;
_isDirectory = true;
_isValid = ETrue;
_isDirectory = ETrue;
_isPseudoRoot = aIsRoot;
_displayName = "Root";
}
SymbianFilesystemNode::SymbianFilesystemNode(const String &path) {
SymbianFilesystemNode::SymbianFilesystemNode(const Common::String &path) {
if (path.size() == 0)
_isPseudoRoot = true;
_isPseudoRoot = ETrue;
else
_isPseudoRoot = false;
_isPseudoRoot = EFalse;
_path = path;
fixFilePath(_path);
_displayName = lastPathComponent(_path);
_displayName = lastPathComponent(_path, '\\');
TEntry fileAttribs;
TFileName fname;
TPtrC8 ptr((const unsigned char*)_path.c_str(),_path.size());
fname.Copy(ptr);
if (CEikonEnv::Static()->FsSession().Entry(fname, fileAttribs) == KErrNone) {
_isValid = true;
if (static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession().Entry(fname, fileAttribs) == KErrNone) {
_isValid = ETrue;
_isDirectory = fileAttribs.IsDir();
} else {
_isValid = false;
_isDirectory = false;
_isValid = ETrue;
_isDirectory = EFalse;
}
}
AbstractFilesystemNode *SymbianFilesystemNode::getChild(const String &n) const {
AbstractFilesystemNode *SymbianFilesystemNode::getChild(const Common::String &n) const {
assert(_isDirectory);
String newPath(_path);
Common::String newPath(_path);
if (_path.lastChar() != '\\')
newPath += '\\';
newPath += n;
TPtrC8 ptr((const unsigned char*) newPath.c_str(), newPath.size());
TFileName fname;
fname.Copy(ptr);
TBool isFolder = EFalse;
BaflUtils::IsFolder(CEikonEnv::Static()->FsSession(), fname, isFolder);
if (!isFolder)
return 0;
newPath += n;
return new SymbianFilesystemNode(newPath);
}
@ -177,19 +152,19 @@ bool SymbianFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, b
if (_isPseudoRoot) {
// Drives enumeration
RFs fs = CEikonEnv::Static()->FsSession();
RFs& fs = static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession();
TInt driveNumber;
TChar driveLetter;
TUint driveLetterValue;
TVolumeInfo volumeInfo;
TBuf8<30> driveLabel8;
TBuf8<30> driveString8;
TBuf8<KDriveLabelSize> driveLabel8;
TBuf8<KDriveLabelSize> driveString8;
for (driveNumber=EDriveA; driveNumber<=EDriveZ; driveNumber++) {
TInt err = fs.Volume(volumeInfo, driveNumber);
if (err != KErrNone)
continue;
if (fs.DriveToChar(driveNumber,driveLetter) != KErrNone)
if (fs.DriveToChar(driveNumber, driveLetter) != KErrNone)
continue;
driveLetterValue = driveLetter;
@ -205,40 +180,46 @@ bool SymbianFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, b
sprintf(path,"%c:\\", driveNumber+'A');
SymbianFilesystemNode entry(false);
entry._displayName = (char*)driveString8.PtrZ(); // drive_name
entry._isDirectory = true;
entry._isValid = true;
entry._isPseudoRoot = false;
entry._displayName = (char*) driveString8.PtrZ(); // drive_name
entry._isDirectory = ETrue;
entry._isValid = ETrue;
entry._isPseudoRoot = EFalse;
entry._path = path;
myList.push_back(new SymbianFilesystemNode(entry));
}
} else {
TPtrC8 ptr((const unsigned char*)_path.c_str(),_path.size());
TPtrC8 ptr((const unsigned char*) _path.c_str(), _path.size());
TFileName fname;
fname.Copy(ptr);
TBuf8<256>nameBuf;
CDir* dirPtr;
if (CEikonEnv::Static()->FsSession().GetDir(fname,KEntryAttNormal|KEntryAttDir,0,dirPtr)==KErrNone) {
fname.Copy(ptr);
if (_path.lastChar() != '\\')
fname.Append('\\');
if (static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession().GetDir(fname, KEntryAttNormal|KEntryAttDir, 0, dirPtr) == KErrNone) {
CleanupStack::PushL(dirPtr);
TInt cnt=dirPtr->Count();
for (TInt loop=0;loop<cnt;loop++) {
TEntry fileentry=(*dirPtr)[loop];
nameBuf.Copy(fileentry.iName);
SymbianFilesystemNode entry(false);
entry._isPseudoRoot = false;
SymbianFilesystemNode entry(EFalse);
entry._isPseudoRoot = EFalse;
entry._displayName =(char*)nameBuf.PtrZ();
entry._displayName =(char*) nameBuf.PtrZ();
entry._path = _path;
entry._path +=(char*)nameBuf.PtrZ();
if (entry._path.lastChar() != '\\')
entry._path+= '\\';
entry._path +=(char*) nameBuf.PtrZ();
entry._isDirectory = fileentry.IsDir();
// Honor the chosen mode
if ((mode == FilesystemNode::kListFilesOnly && entry._isDirectory) ||
(mode == FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
if ((mode == Common::FilesystemNode::kListFilesOnly && entry._isDirectory) ||
(mode == Common::FilesystemNode::kListDirectoriesOnly && !entry._isDirectory))
continue;
if (entry._isDirectory)
entry._path += "\\";
myList.push_back(new SymbianFilesystemNode(entry));
}
CleanupStack::PopAndDestroy(dirPtr);
@ -254,21 +235,30 @@ AbstractFilesystemNode *SymbianFilesystemNode::getParent() const {
// Root node is its own parent. Still we can't just return this
// as the GUI code will call delete on the old node.
if (!_isPseudoRoot && _path.size() > 3) {
p = new SymbianFilesystemNode(false);
p = new SymbianFilesystemNode(EFalse);
const char *start = _path.c_str();
const char *end = lastPathComponent(_path);
const char *end = lastPathComponent(_path, '\\');
p->_path = String(start, end - start);
p->_isValid = true;
p->_isDirectory = true;
p->_displayName = lastPathComponent(p->_path);
p->_path = Common::String(start, end - start);
p->_isValid = ETrue;
p->_isDirectory = ETrue;
p->_displayName = lastPathComponent(p->_path, '\\');
}
else
{
p = new SymbianFilesystemNode(true);
p = new SymbianFilesystemNode(ETrue);
}
return p;
}
Common::SeekableReadStream *SymbianFilesystemNode::openForReading() {
return SymbianStdioStream::makeFromPath(getPath().c_str(), false);
}
Common::WriteStream *SymbianFilesystemNode::openForWriting() {
return SymbianStdioStream::makeFromPath(getPath().c_str(), true);
}
#endif //#if defined (__SYMBIAN32__)

View file

@ -0,0 +1,274 @@
/* 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$
* $Id$
*
*/
#include "common/scummsys.h"
#include "backends/fs/symbian/symbianstream.h"
#include "common/system.h"
#include "backends/platform/symbian/src/symbianos.h"
#include <f32file.h>
#define KInputBufferLength 128
// Symbian libc file functionality in order to provide shared file handles
class TSymbianFileEntry {
public:
RFile _fileHandle;
char _inputBuffer[KInputBufferLength];
TInt _inputBufferLen;
TInt _inputPos;
TInt _lastError;
TBool _eofReached;
};
TSymbianFileEntry* CreateSymbianFileEntry(const char* name, const char* mode) {
TSymbianFileEntry* fileEntry = new TSymbianFileEntry;
fileEntry->_inputPos = KErrNotFound;
fileEntry->_lastError = 0;
fileEntry->_eofReached = EFalse;
if (fileEntry != NULL) {
TInt modeLen = strlen(mode);
TPtrC8 namePtr((unsigned char*) name, strlen(name));
TFileName tempFileName;
tempFileName.Copy(namePtr);
TInt fileMode = EFileRead;
if (mode[0] == 'a')
fileMode = EFileWrite;
if (!((modeLen > 1 && mode[1] == 'b') || (modeLen > 2 && mode[2] == 'b'))) {
fileMode |= EFileStreamText;
}
if ((modeLen > 1 && mode[1] == '+') || (modeLen > 2 && mode[2] == '+')) {
fileMode = fileMode| EFileWrite;
}
fileMode = fileMode| EFileShareAny;
switch(mode[0]) {
case 'a':
if (fileEntry->_fileHandle.Open(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) {
if (fileEntry->_fileHandle.Create(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) {
delete fileEntry;
fileEntry = NULL;
}
}
break;
case 'r':
if (fileEntry->_fileHandle.Open(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) {
delete fileEntry;
fileEntry = NULL;
}
break;
case 'w':
if (fileEntry->_fileHandle.Replace(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), tempFileName, fileMode) != KErrNone) {
delete fileEntry;
fileEntry = NULL;
}
break;
}
}
return fileEntry;
}
size_t ReadData(const void* ptr, size_t size, size_t numItems, TSymbianFileEntry* handle) {
TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle));
TUint32 totsize = size*numItems;
TPtr8 pointer ( (unsigned char*) ptr, totsize);
// Nothing cached and we want to load at least KInputBufferLength bytes
if (totsize >= KInputBufferLength) {
TUint32 totLength = 0;
if (entry->_inputPos != KErrNotFound) {
TPtr8 cacheBuffer( (unsigned char*) entry->_inputBuffer+entry->_inputPos, entry->_inputBufferLen - entry->_inputPos, KInputBufferLength);
pointer.Append(cacheBuffer);
entry->_inputPos = KErrNotFound;
totLength+=pointer.Length();
pointer.Set(totLength+(unsigned char*) ptr, 0, totsize-totLength);
}
entry->_lastError = entry->_fileHandle.Read(pointer);
totLength+=pointer.Length();
pointer.Set((unsigned char*) ptr, totLength, totsize);
} else {
// Nothing in buffer
if (entry->_inputPos == KErrNotFound) {
TPtr8 cacheBuffer( (unsigned char*) entry->_inputBuffer, KInputBufferLength);
entry->_lastError = entry->_fileHandle.Read(cacheBuffer);
if (cacheBuffer.Length() >= totsize) {
pointer.Copy(cacheBuffer.Left(totsize));
entry->_inputPos = totsize;
entry->_inputBufferLen = cacheBuffer.Length();
} else {
pointer.Copy(cacheBuffer);
entry->_inputPos = KErrNotFound;
}
} else {
TPtr8 cacheBuffer( (unsigned char*) entry->_inputBuffer, entry->_inputBufferLen, KInputBufferLength);
if (entry->_inputPos+totsize < entry->_inputBufferLen) {
pointer.Copy(cacheBuffer.Mid(entry->_inputPos, totsize));
entry->_inputPos+=totsize;
} else {
pointer.Copy(cacheBuffer.Mid(entry->_inputPos, entry->_inputBufferLen-entry->_inputPos));
cacheBuffer.SetLength(0);
entry->_lastError = entry->_fileHandle.Read(cacheBuffer);
if (cacheBuffer.Length() >= totsize-pointer.Length()) {
TUint32 restSize = totsize-pointer.Length();
pointer.Append(cacheBuffer.Left(restSize));
entry->_inputPos = restSize;
entry->_inputBufferLen = cacheBuffer.Length();
} else {
pointer.Append(cacheBuffer);
entry->_inputPos = KErrNotFound;
}
}
}
}
if((numItems * size) != pointer.Length() && entry->_lastError == KErrNone) {
entry->_eofReached = ETrue;
}
return pointer.Length() / size;
}
SymbianStdioStream::SymbianStdioStream(void *handle) : _handle(handle) {
assert(handle);
}
SymbianStdioStream::~SymbianStdioStream() {
((TSymbianFileEntry*)(_handle))->_fileHandle.Close();
delete (TSymbianFileEntry*)(_handle);
}
bool SymbianStdioStream::err() const {
return ((TSymbianFileEntry*)(_handle))->_lastError != 0;
}
void SymbianStdioStream::clearErr() {
((TSymbianFileEntry*)(_handle))->_lastError = 0;
((TSymbianFileEntry*)(_handle))->_eofReached = 0;
}
bool SymbianStdioStream::eos() const {
TSymbianFileEntry* entry = ((TSymbianFileEntry*)(_handle));
return entry->_eofReached != 0;
}
int32 SymbianStdioStream::pos() const {
TInt pos = 0;
TSymbianFileEntry* entry = ((TSymbianFileEntry*)(_handle));
entry->_lastError = entry->_fileHandle.Seek(ESeekCurrent, pos);
if (entry->_lastError == KErrNone && entry->_inputPos != KErrNotFound) {
pos += (entry->_inputPos - entry->_inputBufferLen);
}
return pos;
}
int32 SymbianStdioStream::size() const {
TInt length = 0;
((TSymbianFileEntry*)(_handle))->_fileHandle.Size(length);
return length;
}
bool SymbianStdioStream::seek(int32 offs, int whence) {
assert(_handle);
TSeek seekMode = ESeekStart;
TInt pos = offs;
TSymbianFileEntry* entry = ((TSymbianFileEntry*)(_handle));
switch (whence) {
case SEEK_SET:
seekMode = ESeekStart;
break;
case SEEK_CUR:
seekMode = ESeekCurrent;
if (entry->_inputPos != KErrNotFound) {
pos += (entry->_inputPos - entry->_inputBufferLen);
}
break;
case SEEK_END:
seekMode = ESeekEnd;
break;
}
entry->_inputPos = KErrNotFound;
entry->_eofReached = EFalse;
entry->_fileHandle.Seek(seekMode, pos);
return true; // FIXME: Probably should return a value based on what _fileHandle.Seek returns
}
uint32 SymbianStdioStream::read(void *ptr, uint32 len) {
return (uint32)ReadData((byte *)ptr, 1, len, (TSymbianFileEntry *)_handle);
}
uint32 SymbianStdioStream::write(const void *ptr, uint32 len) {
TPtrC8 pointer( (unsigned char*) ptr, len);
((TSymbianFileEntry*)(_handle))->_inputPos = KErrNotFound;
((TSymbianFileEntry*)(_handle))->_lastError = ((TSymbianFileEntry*)(_handle))->_fileHandle.Write(pointer);
((TSymbianFileEntry*)(_handle))->_eofReached = EFalse;
if (((TSymbianFileEntry*)(_handle))->_lastError == KErrNone) {
return len;
}
return 0;
}
bool SymbianStdioStream::flush() {
((TSymbianFileEntry*)(_handle))->_fileHandle.Flush();
return true;
}
SymbianStdioStream *SymbianStdioStream::makeFromPath(const Common::String &path, bool writeMode) {
void *handle = CreateSymbianFileEntry(path.c_str(), writeMode ? "wb" : "rb");
if (handle)
return new SymbianStdioStream(handle);
return 0;
}

View file

@ -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.
*
* $URL: $
* $Id: $
*
*/
#ifndef BACKENDS_FS_SYMBIANSTDIOSTREAM_H
#define BACKENDS_FS_SYMBIANSTDIOSTREAM_H
#include "common/scummsys.h"
#include "common/noncopyable.h"
#include "common/stream.h"
#include "common/str.h"
class SymbianStdioStream : public Common::SeekableReadStream, public Common::WriteStream, public Common::NonCopyable {
protected:
/** File handle to the actual file. */
void *_handle;
public:
/**
* Given a path, invokes fopen on that path and wrap the result in a
* StdioStream instance.
*/
static SymbianStdioStream *makeFromPath(const Common::String &path, bool writeMode);
SymbianStdioStream(void *handle);
virtual ~SymbianStdioStream();
bool err() const;
void clearErr();
bool eos() const;
virtual uint32 write(const void *dataPtr, uint32 dataSize);
virtual bool flush();
virtual int32 pos() const;
virtual int32 size() const;
bool seek(int32 offs, int whence = SEEK_SET);
uint32 read(void *dataPtr, uint32 dataSize);
};
#endif

View file

@ -42,7 +42,7 @@ AbstractFilesystemNode *WiiFilesystemFactory::makeCurrentDirectoryFileNode() con
return new WiiFilesystemNode();
}
AbstractFilesystemNode *WiiFilesystemFactory::makeFileNodePath(const String &path) const {
AbstractFilesystemNode *WiiFilesystemFactory::makeFileNodePath(const Common::String &path) const {
return new WiiFilesystemNode(path, true);
}
#endif

View file

@ -33,11 +33,9 @@
*/
class WiiFilesystemFactory : public FilesystemFactory, public Common::Singleton<WiiFilesystemFactory> {
public:
typedef Common::String String;
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
protected:
WiiFilesystemFactory() {};

View file

@ -23,6 +23,7 @@
#if defined(__WII__)
#include "backends/fs/abstract-fs.h"
#include "backends/fs/stdiostream.h"
#include <sys/dir.h>
@ -37,8 +38,8 @@
*/
class WiiFilesystemNode : public AbstractFilesystemNode {
protected:
String _displayName;
String _path;
Common::String _displayName;
Common::String _path;
bool _isDirectory, _isReadable, _isWritable;
public:
@ -50,51 +51,30 @@ public:
/**
* Creates a WiiFilesystemNode for a given path.
*
* @param path String with the path the new node should point to.
* @param path Common::String with the path the new node should point to.
* @param verify true if the isValid and isDirectory flags should be verified during the construction.
*/
WiiFilesystemNode(const String &path, bool verify);
WiiFilesystemNode(const Common::String &path, bool verify);
virtual bool exists() const;
virtual String getDisplayName() const { return _displayName; }
virtual String getName() const { return _displayName; }
virtual String getPath() const { return _path; }
virtual Common::String getDisplayName() const { return _displayName; }
virtual Common::String getName() const { return _displayName; }
virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return _isReadable; }
virtual bool isWritable() const { return _isWritable; }
virtual AbstractFilesystemNode *getChild(const String &n) const;
virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
virtual Common::SeekableReadStream *openForReading();
virtual Common::WriteStream *openForWriting();
private:
virtual void setFlags();
};
/**
* Returns the last component of a given path.
*
* Examples:
* /foo/bar.txt would return /bar.txt
* /foo/bar/ would return /bar/
*
* @param str String containing the path.
* @return Pointer to the first char of the last component inside str.
*/
const char *lastPathComponent(const Common::String &str) {
if(str.empty())
return "";
const char *start = str.c_str();
const char *cur = start + str.size() - 2;
while (cur >= start && *cur != '/') {
--cur;
}
return cur + 1;
}
void WiiFilesystemNode::setFlags() {
struct stat st;
@ -118,12 +98,12 @@ WiiFilesystemNode::WiiFilesystemNode() {
setFlags();
}
WiiFilesystemNode::WiiFilesystemNode(const String &p, bool verify) {
WiiFilesystemNode::WiiFilesystemNode(const Common::String &p, bool verify) {
assert(p.size() > 0);
_path = p;
_displayName = lastPathComponent(_path);
_displayName = lastPathComponent(_path, '/');
if (verify)
setFlags();
@ -134,10 +114,10 @@ bool WiiFilesystemNode::exists() const {
return stat(_path.c_str (), &st) == 0;
}
AbstractFilesystemNode *WiiFilesystemNode::getChild(const String &n) const {
AbstractFilesystemNode *WiiFilesystemNode::getChild(const Common::String &n) const {
assert(_isDirectory);
String newPath(_path);
Common::String newPath(_path);
if (newPath.lastChar() != '/')
newPath += '/';
newPath += n;
@ -160,15 +140,15 @@ bool WiiFilesystemNode::getChildren(AbstractFSList &myList, ListMode mode, bool
if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0)
continue;
String newPath(_path);
Common::String newPath(_path);
if (newPath.lastChar() != '/')
newPath += '/';
newPath += filename;
bool isDir = S_ISDIR(st.st_mode);
if ((mode == FilesystemNode::kListFilesOnly && isDir) ||
(mode == FilesystemNode::kListDirectoriesOnly && !isDir))
if ((mode == Common::FilesystemNode::kListFilesOnly && isDir) ||
(mode == Common::FilesystemNode::kListDirectoriesOnly && !isDir))
continue;
if (isDir)
@ -187,9 +167,17 @@ AbstractFilesystemNode *WiiFilesystemNode::getParent() const {
return 0;
const char *start = _path.c_str();
const char *end = lastPathComponent(_path);
const char *end = lastPathComponent(_path, '/');
return new WiiFilesystemNode(String(start, end - start), true);
return new WiiFilesystemNode(Common::String(start, end - start), true);
}
Common::SeekableReadStream *WiiFilesystemNode::openForReading() {
return StdioStream::makeFromPath(getPath().c_str(), false);
}
Common::WriteStream *WiiFilesystemNode::openForWriting() {
return StdioStream::makeFromPath(getPath().c_str(), true);
}
#endif //#if defined(__WII__)

View file

@ -26,8 +26,6 @@
#include "backends/fs/windows/windows-fs-factory.h"
#include "backends/fs/windows/windows-fs.cpp"
DECLARE_SINGLETON(WindowsFilesystemFactory);
AbstractFilesystemNode *WindowsFilesystemFactory::makeRootFileNode() const {
return new WindowsFilesystemNode();
}
@ -36,7 +34,7 @@ AbstractFilesystemNode *WindowsFilesystemFactory::makeCurrentDirectoryFileNode()
return new WindowsFilesystemNode("", true);
}
AbstractFilesystemNode *WindowsFilesystemFactory::makeFileNodePath(const String &path) const {
AbstractFilesystemNode *WindowsFilesystemFactory::makeFileNodePath(const Common::String &path) const {
return new WindowsFilesystemNode(path, false);
}
#endif

View file

@ -25,7 +25,6 @@
#ifndef WINDOWS_FILESYSTEM_FACTORY_H
#define WINDOWS_FILESYSTEM_FACTORY_H
#include "common/singleton.h"
#include "backends/fs/fs-factory.h"
/**
@ -33,19 +32,11 @@
*
* Parts of this class are documented in the base interface class, FilesystemFactory.
*/
class WindowsFilesystemFactory : public FilesystemFactory, public Common::Singleton<WindowsFilesystemFactory> {
class WindowsFilesystemFactory : public FilesystemFactory {
public:
typedef Common::String String;
virtual AbstractFilesystemNode *makeRootFileNode() const;
virtual AbstractFilesystemNode *makeCurrentDirectoryFileNode() const;
virtual AbstractFilesystemNode *makeFileNodePath(const String &path) const;
protected:
WindowsFilesystemFactory() {};
private:
friend class Common::Singleton<SingletonBaseType>;
virtual AbstractFilesystemNode *makeFileNodePath(const Common::String &path) const;
};
#endif /*WINDOWS_FILESYSTEM_FACTORY_H*/

View file

@ -24,24 +24,17 @@
#ifdef WIN32
#ifdef ARRAYSIZE
#undef ARRAYSIZE
#endif
#ifdef _WIN32_WCE
#include <windows.h>
// winnt.h defines ARRAYSIZE, but we want our own one...
#undef ARRAYSIZE
#ifdef _WIN32_WCE
#undef GetCurrentDirectory
#endif
#include "backends/fs/abstract-fs.h"
#include "backends/fs/stdiostream.h"
#include <io.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef _WIN32_WCE
#include <windows.h>
// winnt.h defines ARRAYSIZE, but we want our own one...
#undef ARRAYSIZE
#endif
#include <tchar.h>
// F_OK, R_OK and W_OK are not defined under MSVC, so we define them here
@ -66,8 +59,8 @@
*/
class WindowsFilesystemNode : public AbstractFilesystemNode {
protected:
String _displayName;
String _path;
Common::String _displayName;
Common::String _path;
bool _isDirectory;
bool _isPseudoRoot;
bool _isValid;
@ -89,23 +82,26 @@ public:
* path=c:\foo\bar.txt, currentDir=true -> current directory
* path=NULL, currentDir=true -> current directory
*
* @param path String with the path the new node should point to.
* @param path Common::String with the path the new node should point to.
* @param currentDir if true, the path parameter will be ignored and the resulting node will point to the current directory.
*/
WindowsFilesystemNode(const String &path, const bool currentDir);
WindowsFilesystemNode(const Common::String &path, const bool currentDir);
virtual bool exists() const { return _access(_path.c_str(), F_OK) == 0; }
virtual String getDisplayName() const { return _displayName; }
virtual String getName() const { return _displayName; }
virtual String getPath() const { return _path; }
virtual Common::String getDisplayName() const { return _displayName; }
virtual Common::String getName() const { return _displayName; }
virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return _isDirectory; }
virtual bool isReadable() const { return _access(_path.c_str(), R_OK) == 0; }
virtual bool isWritable() const { return _access(_path.c_str(), W_OK) == 0; }
virtual AbstractFilesystemNode *getChild(const String &n) const;
virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual AbstractFilesystemNode *getParent() const;
virtual Common::SeekableReadStream *openForReading();
virtual Common::WriteStream *openForWriting();
private:
/**
* Adds a single WindowsFilesystemNode to a given list.
@ -113,7 +109,7 @@ private:
*
* @param list List to put the file entry node in.
* @param mode Mode to use while adding the file entry to the list.
* @param base String with the directory being listed.
* @param base Common::String with the directory being listed.
* @param find_data Describes a file that the FindFirstFile, FindFirstFileEx, or FindNextFile functions find.
*/
static void addFile(AbstractFSList &list, ListMode mode, const char *base, WIN32_FIND_DATA* find_data);
@ -121,7 +117,7 @@ private:
/**
* Converts a Unicode string to Ascii format.
*
* @param str String to convert from Unicode to Ascii.
* @param str Common::String to convert from Unicode to Ascii.
* @return str in Ascii format.
*/
static char *toAscii(TCHAR *str);
@ -129,36 +125,12 @@ private:
/**
* Converts an Ascii string to Unicode format.
*
* @param str String to convert from Ascii to Unicode.
* @param str Common::String to convert from Ascii to Unicode.
* @return str in Unicode format.
*/
static const TCHAR* toUnicode(const char *str);
};
/**
* Returns the last component of a given path.
*
* Examples:
* c:\foo\bar.txt would return "\bar.txt"
* c:\foo\bar\ would return "\bar\"
*
* @param str Path to obtain the last component from.
* @return Pointer to the first char of the last component inside str.
*/
const char *lastPathComponent(const Common::String &str) {
if(str.empty())
return "";
const char *start = str.c_str();
const char *cur = start + str.size() - 2;
while (cur >= start && *cur != '\\') {
--cur;
}
return cur + 1;
}
void WindowsFilesystemNode::addFile(AbstractFSList &list, ListMode mode, const char *base, WIN32_FIND_DATA* find_data) {
WindowsFilesystemNode entry;
char *asciiName = toAscii(find_data->cFileName);
@ -170,8 +142,8 @@ void WindowsFilesystemNode::addFile(AbstractFSList &list, ListMode mode, const c
isDirectory = (find_data->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? true : false);
if ((!isDirectory && mode == FilesystemNode::kListDirectoriesOnly) ||
(isDirectory && mode == FilesystemNode::kListFilesOnly))
if ((!isDirectory && mode == Common::FilesystemNode::kListDirectoriesOnly) ||
(isDirectory && mode == Common::FilesystemNode::kListFilesOnly))
return;
entry._isDirectory = isDirectory;
@ -222,18 +194,17 @@ WindowsFilesystemNode::WindowsFilesystemNode() {
#endif
}
WindowsFilesystemNode::WindowsFilesystemNode(const String &p, const bool currentDir) {
WindowsFilesystemNode::WindowsFilesystemNode(const Common::String &p, const bool currentDir) {
if (currentDir) {
char path[MAX_PATH];
GetCurrentDirectory(MAX_PATH, path);
_path = path;
}
else {
} else {
assert(p.size() > 0);
_path = p;
}
_displayName = lastPathComponent(_path);
_displayName = lastPathComponent(_path, '\\');
// Check whether it is a directory, and whether the file actually exists
DWORD fileAttribs = GetFileAttributes(toUnicode(_path.c_str()));
@ -252,19 +223,14 @@ WindowsFilesystemNode::WindowsFilesystemNode(const String &p, const bool current
_isPseudoRoot = false;
}
AbstractFilesystemNode *WindowsFilesystemNode::getChild(const String &n) const {
AbstractFilesystemNode *WindowsFilesystemNode::getChild(const Common::String &n) const {
assert(_isDirectory);
String newPath(_path);
Common::String newPath(_path);
if (_path.lastChar() != '\\')
newPath += '\\';
newPath += n;
// Check whether the directory actually exists
DWORD fileAttribs = GetFileAttributes(toUnicode(newPath.c_str()));
if (fileAttribs == INVALID_FILE_ATTRIBUTES)
return 0;
return new WindowsFilesystemNode(newPath, false);
}
@ -328,17 +294,25 @@ AbstractFilesystemNode *WindowsFilesystemNode::getParent() const {
WindowsFilesystemNode *p = new WindowsFilesystemNode();
if (_path.size() > 3) {
const char *start = _path.c_str();
const char *end = lastPathComponent(_path);
const char *end = lastPathComponent(_path, '\\');
p = new WindowsFilesystemNode();
p->_path = String(start, end - start);
p->_path = Common::String(start, end - start);
p->_isValid = true;
p->_isDirectory = true;
p->_displayName = lastPathComponent(p->_path);
p->_displayName = lastPathComponent(p->_path, '\\');
p->_isPseudoRoot = false;
}
return p;
}
Common::SeekableReadStream *WindowsFilesystemNode::openForReading() {
return StdioStream::makeFromPath(getPath().c_str(), false);
}
Common::WriteStream *WindowsFilesystemNode::openForWriting() {
return StdioStream::makeFromPath(getPath().c_str(), true);
}
#endif //#ifdef WIN32

View file

@ -79,20 +79,18 @@ MidiDriver_ALSA::MidiDriver_ALSA()
}
int MidiDriver_ALSA::open() {
const char *var;
const char *var = NULL;
if (_isOpen)
return MERR_ALREADY_OPEN;
_isOpen = true;
if (!(var = getenv("SCUMMVM_PORT"))) {
// use config option if no var specified
var = getenv("SCUMMVM_PORT");
if (!var && ConfMan.hasKey("alsa_port")) {
var = ConfMan.get("alsa_port").c_str();
if (parse_addr(var, &seq_client, &seq_port) < 0) {
error("Invalid port %s", var);
return -1;
}
} else {
}
if (var) {
if (parse_addr(var, &seq_client, &seq_port) < 0) {
error("Invalid port %s", var);
return -1;
@ -120,14 +118,32 @@ int MidiDriver_ALSA::open() {
return -1;
}
if (seq_client != SND_SEQ_ADDRESS_SUBSCRIBERS) {
/* subscribe to MIDI port */
if (snd_seq_connect_to(seq_handle, my_port, seq_client, seq_port) < 0) {
error("Can't subscribe to MIDI port (%d:%d) see README for help", seq_client, seq_port);
if (var) {
if (seq_client != SND_SEQ_ADDRESS_SUBSCRIBERS) {
// subscribe to MIDI port
if (snd_seq_connect_to(seq_handle, my_port, seq_client, seq_port) < 0) {
error("Can't subscribe to MIDI port (%d:%d) see README for help", seq_client, seq_port);
}
}
else printf("Connected to Alsa sequencer client [%d:%d]\n", seq_client, seq_port);
} else {
int defaultPorts[] = {
65, 0,
17, 0
};
int i;
for (i = 0; i < ARRAYSIZE(defaultPorts); i += 2) {
seq_client = defaultPorts[i];
seq_port = defaultPorts[i + 1];
if (snd_seq_connect_to(seq_handle, my_port, seq_client, seq_port) >= 0)
break;
}
if (i >= ARRAYSIZE(defaultPorts))
error("Can't subscribe to MIDI port (65:0) or (17:0)");
}
printf("Connected to Alsa sequencer client [%d:%d]\n", seq_client, seq_port);
printf("ALSA client initialised [%d:0]\n", my_client);
return 0;

View file

@ -28,7 +28,7 @@
* both the QuickTime support and (vkeybd http://www.alsa-project.org/~iwai/alsa.html)
*/
#if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__)
#if defined(UNIX) && !defined(__BEOS__) && !defined(__MAEMO__) && !defined(__MINT__)
#include "common/util.h"
#include "sound/musicplugin.h"

155
backends/midi/stmidi.cpp Normal file
View file

@ -0,0 +1,155 @@
/* ScummVM - Scumm Interpreter
* Copyright (C) 2001 Ludvig Strigeus
* Copyright (C) 2001-2006 The ScummVM project
*
* 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.
*/
/*
* Raw MIDI output for the Atari ST line of computers.
* Based on the ScummVM SEQ & CoreMIDI drivers.
* Atari code by Keith Scroggins
* We, unfortunately, could not use the SEQ driver because the /dev/midi under
* FreeMiNT (and hence in libc) is considered to be a serial port for machine
* access. So, we just use OS calls then to send the data to the MIDI ports
* directly. The current implementation is sending 1 byte at a time because
* in most cases we are only sending up to 3 bytes, I believe this saves a few
* cycles. I might change so sysex messages are sent the other way later.
*/
#if defined __MINT__
#include <osbind.h>
#include "sound/mpu401.h"
#include "common/util.h"
#include "sound/musicplugin.h"
class MidiDriver_STMIDI : public MidiDriver_MPU401 {
public:
MidiDriver_STMIDI() : _isOpen (false) { }
int open();
void close();
void send(uint32 b);
void sysEx(const byte *msg, uint16 length);
private:
bool _isOpen;
};
int MidiDriver_STMIDI::open() {
if ((_isOpen) && (!Bcostat(4)))
return MERR_ALREADY_OPEN;
warning("ST Midi Port Open");
_isOpen = true;
return 0;
}
void MidiDriver_STMIDI::close() {
MidiDriver_MPU401::close();
_isOpen = false;
}
void MidiDriver_STMIDI::send(uint32 b) {
byte status_byte = (b & 0x000000FF);
byte first_byte = (b & 0x0000FF00) >> 8;
byte second_byte = (b & 0x00FF0000) >> 16;
// warning("ST MIDI Packet sent");
switch (b & 0xF0) {
case 0x80: // Note Off
case 0x90: // Note On
case 0xA0: // Polyphonic Key Pressure
case 0xB0: // Controller
case 0xE0: // Pitch Bend
Bconout(3, status_byte);
Bconout(3, first_byte);
Bconout(3, second_byte);
break;
case 0xC0: // Program Change
case 0xD0: // Aftertouch
Bconout(3, status_byte);
Bconout(3, first_byte);
break;
default:
fprintf(stderr, "Unknown : %08x\n", (int)b);
break;
}
}
void MidiDriver_STMIDI::sysEx (const byte *msg, uint16 length) {
if (length > 254) {
warning ("Cannot send SysEx block - data too large");
return;
}
const byte *chr = msg;
warning("Sending SysEx Message");
Bconout(3, '0xF0');
for (; length; --length, ++chr) {
Bconout(3,((unsigned char) *chr & 0x7F));
}
Bconout(3, '0xF7');
}
// Plugin interface
class StMidiMusicPlugin : public MusicPluginObject {
public:
const char *getName() const {
return "STMIDI";
}
const char *getId() const {
return "stmidi";
}
MusicDevices getDevices() const;
PluginError createInstance(Audio::Mixer *mixer, MidiDriver **mididriver)
const;
};
MusicDevices StMidiMusicPlugin::getDevices() const {
MusicDevices devices;
// TODO: Return a different music type depending on the configuration
// TODO: List the available devices
devices.push_back(MusicDevice(this, "", MT_GM));
return devices;
}
PluginError StMidiMusicPlugin::createInstance(Audio::Mixer *mixer, MidiDriver **mididriver) const {
*mididriver = new MidiDriver_STMIDI();
return kNoError;
}
MidiDriver *MidiDriver_STMIDI_create(Audio::Mixer *mixer) {
MidiDriver *mididriver;
StMidiMusicPlugin p;
p.createInstance(mixer, &mididriver);
return mididriver;
}
//#if PLUGIN_ENABLED_DYNAMIC(STMIDI)
//REGISTER_PLUGIN_DYNAMIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
//#else
REGISTER_PLUGIN_STATIC(STMIDI, PLUGIN_TYPE_MUSIC, StMidiMusicPlugin);
//#endif
#endif

View file

@ -1,6 +1,8 @@
MODULE := backends
MODULE_OBJS := \
fs/abstract-fs.o \
fs/stdiostream.o \
fs/amigaos4/amigaos4-fs-factory.o \
fs/ds/ds-fs-factory.o \
fs/palmos/palmos-fs-factory.o \
@ -17,6 +19,7 @@ MODULE_OBJS := \
midi/coremidi.o \
midi/quicktime.o \
midi/seq.o \
midi/stmidi.o \
midi/timidity.o \
midi/dmedia.o \
midi/windows.o \

View file

@ -30,6 +30,9 @@
#include "backends/timer/default/default-timer.h"
#include "sound/mixer.h"
#define DEFAULT_SAVE_PATH "/PALM/Programs/ScummVM/Saved"
OSystem_PalmBase::OSystem_PalmBase() {
_overlayVisible = false;
@ -100,7 +103,7 @@ void OSystem_PalmBase::initBackend() {
// Create the savefile manager, if none exists yet (we check for this to
// allow subclasses to provide their own).
if (_saveMgr == 0) {
_saveMgr = new DefaultSaveFileManager();
_saveMgr = new DefaultSaveFileManager(DEFAULT_SAVE_PATH);
}
// Create and hook up the mixer, if none exists yet (we check for this to

View file

@ -24,6 +24,7 @@
#include "dc.h"
#include "backends/fs/abstract-fs.h"
#include "backends/fs/stdiostream.h"
#include <ronin/cdfs.h>
#include <stdio.h>
@ -34,75 +35,52 @@
*
* Parts of this class are documented in the base interface class, AbstractFilesystemNode.
*/
/* A file */
class RoninCDFileNode : public AbstractFilesystemNode {
protected:
String _path;
static const char *lastPathComponent(const Common::String &str);
Common::String _path;
public:
RoninCDFileNode(const String &path) : _path(path) {};
RoninCDFileNode(const Common::String &path) : _path(path) {};
virtual bool exists() const { return true; }
virtual String getName() const { return lastPathComponent(_path); }
virtual String getPath() const { return _path; }
virtual Common::String getName() const { return lastPathComponent(_path, '/'); }
virtual Common::String getPath() const { return _path; }
virtual bool isDirectory() const { return false; }
virtual bool isReadable() const { return true; }
virtual bool isWritable() const { return false; }
virtual AbstractFilesystemNode *getChild(const String &n) const { return NULL; }
virtual AbstractFilesystemNode *getChild(const Common::String &n) const { return NULL; }
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const { return false; }
virtual AbstractFilesystemNode *getParent() const;
virtual Common::SeekableReadStream *openForReading();
virtual Common::WriteStream *openForWriting() { return 0; }
static AbstractFilesystemNode *makeFileNodePath(const Common::String &path);
};
/* A directory */
class RoninCDDirectoryNode : public RoninCDFileNode {
public:
RoninCDDirectoryNode(const String &path) : RoninCDFileNode(path) {};
RoninCDDirectoryNode(const Common::String &path) : RoninCDFileNode(path) {};
virtual bool isDirectory() const { return true; }
virtual AbstractFilesystemNode *getChild(const String &n) const;
virtual AbstractFilesystemNode *getChild(const Common::String &n) const;
virtual bool getChildren(AbstractFSList &list, ListMode mode, bool hidden) const;
virtual Common::SeekableReadStream *openForReading() { return 0; }
};
/* A file/directory which does not exist */
class RoninCDNonexistingNode : public RoninCDFileNode {
public:
RoninCDNonexistingNode(const String &path) : RoninCDFileNode(path) {};
RoninCDNonexistingNode(const Common::String &path) : RoninCDFileNode(path) {};
virtual bool exists() const { return false; }
virtual bool isReadable() const { return false; }
virtual Common::SeekableReadStream *openForReading() { return 0; }
};
/**
* Returns the last component of a given path.
*
* Examples:
* /foo/bar.txt would return /bar.txt
* /foo/bar/ would return /bar/
*
* @param str String containing the path.
* @return Pointer to the first char of the last component inside str.
*/
const char *RoninCDFileNode::lastPathComponent(const Common::String &str) {
if(str.empty())
return "";
const char *start = str.c_str();
const char *cur = start + str.size() - 2;
while (cur >= start && *cur != '/') {
--cur;
}
return cur + 1;
}
AbstractFilesystemNode *RoninCDFileNode::makeFileNodePath(const Common::String &path)
{
AbstractFilesystemNode *RoninCDFileNode::makeFileNodePath(const Common::String &path) {
assert(path.size() > 0);
int fd;
@ -110,18 +88,16 @@ AbstractFilesystemNode *RoninCDFileNode::makeFileNodePath(const Common::String &
if ((fd = open(path.c_str(), O_RDONLY)) >= 0) {
close(fd);
return new RoninCDFileNode(path);
}
else if ((fd = open(path.c_str(), O_DIR|O_RDONLY)) >= 0) {
} else if ((fd = open(path.c_str(), O_DIR|O_RDONLY)) >= 0) {
close(fd);
return new RoninCDDirectoryNode(path);
}
else {
} else {
return NULL;
}
}
AbstractFilesystemNode *RoninCDDirectoryNode::getChild(const String &n) const {
String newPath(_path);
AbstractFilesystemNode *RoninCDDirectoryNode::getChild(const Common::String &n) const {
Common::String newPath(_path);
if (_path.lastChar() != '/')
newPath += '/';
newPath += n;
@ -139,20 +115,20 @@ bool RoninCDDirectoryNode::getChildren(AbstractFSList &myList, ListMode mode, bo
// ... loop over dir entries using readdir
while ((dp = readdir(dirp)) != NULL) {
String newPath(_path);
Common::String newPath(_path);
if (newPath.lastChar() != '/')
newPath += '/';
newPath += dp->d_name;
if (dp->d_size < 0) {
// Honor the chosen mode
if (mode == FilesystemNode::kListFilesOnly)
if (mode == Common::FilesystemNode::kListFilesOnly)
continue;
myList.push_back(new RoninCDDirectoryNode(newPath+"/"));
} else {
// Honor the chosen mode
if (mode == FilesystemNode::kListDirectoriesOnly)
if (mode == Common::FilesystemNode::kListDirectoriesOnly)
continue;
myList.push_back(new RoninCDFileNode(newPath));
@ -168,9 +144,14 @@ AbstractFilesystemNode *RoninCDFileNode::getParent() const {
return 0;
const char *start = _path.c_str();
const char *end = lastPathComponent(_path);
const char *end = lastPathComponent(_path, '/');
return new RoninCDDirectoryNode(String(start, end - start));
return new RoninCDDirectoryNode(Common::String(start, end - start));
}
Common::SeekableReadStream *RoninCDFileNode::openForReading() {
return StdioStream::makeFromPath(getPath().c_str(), false);
}
AbstractFilesystemNode *OSystem_Dreamcast::makeRootFileNode() const {

View file

@ -26,8 +26,8 @@
#include <common/scummsys.h>
#include <engines/engine.h>
#include <engines/metaengine.h>
#include <engines/game.h>
#include <base/plugins.h>
#include <base/game.h>
#include <common/fs.h>
#include <common/events.h>
#include "dc.h"
@ -146,12 +146,12 @@ struct Dir
{
char name[252];
char deficon[256];
FilesystemNode node;
Common::FilesystemNode node;
};
static Game the_game;
static bool isIcon(const FilesystemNode &entry)
static bool isIcon(const Common::FilesystemNode &entry)
{
int l = entry.getDisplayName().size();
if (l>4 && !strcasecmp(entry.getDisplayName().c_str()+l-4, ".ICO"))
@ -198,14 +198,14 @@ static int findGames(Game *games, int max)
{
Dir *dirs = new Dir[MAX_DIR];
int curr_game = 0, curr_dir = 0, num_dirs = 1;
dirs[0].node = FilesystemNode("");
dirs[0].node = Common::FilesystemNode("");
while (curr_game < max && curr_dir < num_dirs) {
strncpy(dirs[curr_dir].name, dirs[curr_dir].node.getPath().c_str(), 252);
dirs[curr_dir].name[251] = '\0';
dirs[curr_dir].deficon[0] = '\0';
FSList files, fslist;
dirs[curr_dir++].node.getChildren(fslist, FilesystemNode::kListAll);
for (FSList::const_iterator entry = fslist.begin(); entry != fslist.end();
Common::FSList files, fslist;
dirs[curr_dir++].node.getChildren(fslist, Common::FilesystemNode::kListAll);
for (Common::FSList::const_iterator entry = fslist.begin(); entry != fslist.end();
++entry) {
if (entry->isDirectory()) {
if (num_dirs < MAX_DIR && strcasecmp(entry->getDisplayName().c_str(),

View file

@ -269,14 +269,15 @@ class InVMSave : public Common::InSaveFile {
private:
char *buffer;
int _pos, _size;
bool _eos;
uint32 read(void *buf, uint32 cnt);
void skip(uint32 offset);
void seek(int32 offs, int whence);
bool skip(uint32 offset);
bool seek(int32 offs, int whence);
public:
InVMSave()
: _pos(0), buffer(NULL)
: _pos(0), buffer(NULL), _eos(false)
{ }
~InVMSave()
@ -285,9 +286,10 @@ public:
delete[] buffer;
}
bool eos() const { return _pos >= _size; }
uint32 pos() const { return _pos; }
uint32 size() const { return _size; }
bool eos() const { return _eos; }
void clearErr() { _eos = false; }
int32 pos() const { return _pos; }
int32 size() const { return _size; }
bool readSaveGame(const char *filename)
{ return ::readSaveGame(buffer, _size, filename); }
@ -312,8 +314,8 @@ public:
~OutVMSave();
bool ioFailed() const { return iofailed; }
void clearIOFailed() { iofailed = false; }
bool err() const { return iofailed; }
void clearErr() { iofailed = false; }
void finalize();
};
@ -370,6 +372,7 @@ uint32 InVMSave::read(void *buf, uint32 cnt)
int nbyt = cnt;
if (_pos + nbyt > _size) {
cnt = (_size - _pos);
_eos = true;
nbyt = cnt;
}
if (nbyt)
@ -378,15 +381,16 @@ uint32 InVMSave::read(void *buf, uint32 cnt)
return cnt;
}
void InVMSave::skip(uint32 offset)
bool InVMSave::skip(uint32 offset)
{
int nbyt = offset;
if (_pos + nbyt > _size)
nbyt = (_size - _pos);
_pos += nbyt;
return true;
}
void InVMSave::seek(int32 offs, int whence)
bool InVMSave::seek(int32 offs, int whence)
{
switch(whence) {
case SEEK_SET:
@ -403,6 +407,8 @@ void InVMSave::seek(int32 offs, int whence)
_pos = 0;
else if (_pos > _size)
_pos = _size;
_eos = false;
return true;
}
uint32 OutVMSave::write(const void *buf, uint32 cnt)

View file

@ -107,7 +107,7 @@ MAPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.map)))
export OFILES := $(MAPFILES:.map=.o) $(RAWFILES:.raw=.o) $(PALFILES:.pal=.o) $(BINFILES:.bin=.o) $(PCXFILES:.pcx=.o)\
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) -I- -I$(CURDIR)/../commoninclude\
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) -Iquote -I$(CURDIR)/../commoninclude\
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
$(foreach dir,$(LIBDIRS),-I$(dir)/include/nds)\
-I$(CURDIR)/$(BUILD) -I$(CURDIR)/source/libcartreset

View file

@ -233,7 +233,7 @@ void DummyHandler() {
REG_IF = REG_IF;
}
uint16 powerManagerWrite(uint32 command, u32 data, bool enable) {
void powerManagerWrite(uint32 command, u32 data, bool enable) {
uint16 result;
SerialWaitBusy();
@ -261,9 +261,6 @@ uint16 powerManagerWrite(uint32 command, u32 data, bool enable) {
REG_SPICNT = SPI_ENABLE | SPI_BAUD_1MHz;
REG_SPIDATA = enable? (result | data): (result & ~data);
SerialWaitBusy();
// FIXME: This function should either return something, or have a comment
// explaining why it is valid for it to not return something. :-)
}
/*

View file

@ -0,0 +1,840 @@
The official port of ScummVM
to the Nintendo DS handheld console
by Neil Millstone (agentq)
http://scummvm.drunkencoders.com
------------------------------------------------------------------------
Visit the main ScummVM website <http://www.scummvm.org>
Contents
------------------------------------------------------------------------
* What's New?
* What is ScummVM DS?
* Features
* Screenshots
* How to Get ScummVM DS Onto Your DS - Simple Explanation
o Using a CF/SD/Mini SD/Micro SD card reader and a DLDI driver
o Instructions for specific card readers
* What to do if saving doesn't work or your card gets corruped -
force SRAM saves
* How to use ScummVM DS
* Game Specific Controls
* DS Options Screen
* Which games are compatible with ScummVM DS
* Predictive dictionary for Sierra AGI games
* Converting your CD audio
* Converting speech to MP3 format
* Frequently Asked Questions
* Downloads
* Contributors
* Donations and Getting Help
* Building from Sources
What's New?
------------------------------------------------------------------------
ScummVM DS 0.12.0
* New games supported: Lure of the Temptress, Nippon Safes, Lost in Time.
* New laptop-style trackpad input method. Uses relative movement when you
drag on the touch screen.
* New option which allows you to drag to hover, tap the touch screen to
click, and double tap the screen to right click.
* Reorganised DS Options screen into three tabs for clearer navigation
* New top screen scaling options let you choose the scaling factor used
on startup.
* The usual round of bug fixes.
ScummVM DS 0.11.1
* Bugfix release - No new DS port features
ScummVM DS 0.11.0
* New games supported: Elvira 1 and 2, Waxworks (Amiga version)
* Software scaler for improved image quality. Turn it on using the DS options
screen (press select during the game). Thanks to Tramboi and Robin Watts for
this feature!
* Function keys added to virtual keyboard (used in AGI games)
* Plenty of bug fixes
What is ScummVM DS?
------------------------------------------------------------------------
ScummVM DS is a part of the ScummVM project. The ScummVM project is an
attempt to re-engineer many classic point and click adventure games of the
80s and 90s to run on modern computer hardware. Technology has changed a
lot since these games were written, and so ScummVM attempts to replicate the
gameplay of the original games in exacting details, without any of the original
code that the game ran on. ScummVM needs a copy of the original game, in order
to take the graphics, sound, and scripts that made the game work.
ScummVM is written in such a way that it can be 'ported' from one type of
machine to another, and ScummVM DS is a port of ScummVM to the Nintendo DS
handheld games console.
Features
------------------------------------------------------------------------
* Runs nearly all of Lucasarts' SCUMM games up to and including Sam
& Max Hit the Road
* Runs many non-Lucasarts point-and-click adventures too
* Supports sound
* Provides a GUI to change settings and choose games
* Supports using the DS touch screen for controls
* Suports saving games to compatible flash cards
* All games run at pretty much full speed
How to Get ScummVM DS Onto Your DS - Simple Explanation
------------------------------------------------------------------------
Nintendo don't want you to run ScummVM on your DS. They control
which companies can make games on the DS, and there is an expensive
process to go through in order to be licenced. Having to pay for
this would prevent me from giving away ScummVM for free.
So, the result is that to run ScummVM on your DS you'll need an
unofficial card reader. There are many of these, and all are different.
Popular models at the time of writing are the R4DS and the M3DS Real,
but many different models work. You need to buy one of these, and at
MicroSD card to go with it.
There are also slot-2 card readers which fit into the bottom slot on
your DS, usually used for Game Boy Advance games. These are less common
these days, and although they have certain advantages, the details of
these are beyond the scope of this website. Information on these is
quite easy to find by searching.
Once you have your card reader and a MicroSD card, you will also need
a copy of the game you want to run. ScummVM can run a large variety
of games, but you must own a real boxed copy of the game. These games
are still under copyright, and it is illegal to copy them from a friend
or download them from the Internet without paying. The exception to
this are the three Revolution Software games. These are 'Beneath a
Steel Sky', 'Lure of the Temptress' and 'Flight of the Amazon Queen'.
Revolution have kindly allowed us to give these games away for free.
You can download them from the main ScummVM site at
<http://www.scummvm.org/downloads.php>
NOTE: Previous version of ScummVM DS supported a method which used a
zip file to run games on unsupported flash card readers. This method
is no longer supported.
How to Get ScummVM DS Onto Your DS - Using a CF/SD/Mini SD/Micro
SD card reader and a DLDI driver
------------------------------------------------------------------------
ScummVM DS needs something called a DLDI driver to run on each make
and model of card reader. Many modern card readers (R4DS, M3 DS Real)
handle this autmatically and for those, you don't have to do anything.
Just running ScummVM on the card will handle this step for you.
For others, you will need to follow the steps in this section before
ScummVM DS will work.
All DS card readers are different in the way that they work. In order to
support many different card readers, ScummVM DS uses a DLDI driver installed
into the ScummVM DS code. This is done using a program called DLDITool
which you can download and run on your computer. Each DLDI driver is
designed to tell ScummVM DS how to use a specific type of card reader.
These drivers can be used with any homebrew program which supports the
DLDI interface.
While each card reader should work with these instructions, there are
some exceptions. Please read the card reader notes
section to see if there is any specific information about your card reader.
Here is what you need to do:
* Visit the DLDI page <http://dldi.drunkencoders.com/> and
download the executable for DLDITool for your operating system
(versions are available for Windows, Linux, and MacOS)
* Download the DLDI for your card reader. This is the big table at
the top of the page. The first column marked DLDI is the one you
want. You should get a single file with a .dldi extension.
* Extract DLDITool into a folder, and put the DLDI of your choice in
the same folder.
* If you're using the command line version of DLDITool enter the
following at a command prompt:
dlditool <dldiname> <scummvm nds name>
If you're using the Windows GUI version, double click on
dlditool32.exe, select your card reader from the box, drag your
ScummVM binaries (either the .nds, or the .ds.gba version
depending on your card reader. I think only Supercards use the
.ds.gba files) into the lower box, then click patch.
Either way, you should see 'Patched Successfully'. If you don't,
you're doing something wrong.
You need to patch one of the builds labeled A - F depending on
which game you want to run. See the table on the ScummVM DS
website to see which games are supported by which build.
* Put the patched .nds or .ds.gba files on your flash card. If
you're using the Supercard, you will need to use the .ds.gba
files, but rename them to .nds.
* Put your game data in any folder on the card. Do NOT use a zip file.
* Boot up your DS and run ScummVM.
* Click 'Add Game', browse to the folder with your game data, click
'Choose', then 'OK'. Click 'Start' to run the game.
If your copy of ScummVM DS has been successfully patched, you will get a
message on the top screen that looks like this:
DLDI Device:
GBA Movie Player (Compact Flash)
The message should show the name of your card reader. If it is wrong,
you have used the wrong DLDI file.
If you haven't patched your .nds file, you will get the following message
DLDI Driver not patched!
DLDI Initialise failed.
In this case, you've made a mistake following the above instructions, or
have patched the wrong file.
You may also see the following message:
DLDI Device:
GBA Movie Player (Compact Flash)
DLDI Initialise failed.
In this case, the driver did not start up correctly. The driver is
probably broken, or you've used the wrong one for your card reader.
In the case of the Supercard, M3 Lite and DS Link, there are several
drivers available. You might want to try one of the others.
This version of ScummVM DS will run on any card reader that has a DLDI
driver available. If yours doesn't, you need to pressure your card
reader manufacturer to release one.
DO NOT EMAIL ME TO ASK ME TO CREATE A DRIVER FOR YOUR CARD READER, I
CANNOT DO THIS.
How to Get ScummVM DS Onto Your DS - Instructions for specific
card readers
------------------------------------------------------------------------
* *GBAMP CF:* You need to upload replacement firmware to your card
reader before it will work. You can download the firmware program
here <http://chishm.drunkencoders.com/NDSMP/index.html>. Name your
.nds file _BOOT_MP.nds.
* *M3 CF/SD:* Copy the .nds file to your card with the M3 Game
Manager in order to avoid an annoying message when you boot your
M3. Use the default options to copy the file. Be sure to press 'A'
in the M3 browser to start the .nds file, and not 'Start', or it
won't work.
* *M3 CF/SD:* Copy the .nds file to your card with the M3 Game
Manager in order to avoid an annoying message when you boot your
M3. Use the default options to copy the file. Be sure to press 'A'
in the M3 browser to start the .nds file, and not 'Start', or it
won't work.
* *Supercard CF/SD (slot-2):* Use the .ds.gba files to run ScummVM
on the Supercard. Other than that, just follow the instructions as
normal.
* *Supercard Lite (slot-2):* It has been reported that only the
standard Supercard driver and the Moonshell version work with
ScummVM DS.
* *Datel Max Media Dock: * If you haven't already, upgrade your
firmware to the latest version. The firmware that came with my Max
Media Dock was unable to run ScummVM DS at all. Click here to
visit Datel's support page and download the latest firmware
<http://us.codejunkies.com/mpds/support.htm>
* *NinjaDS*: There are firmware upgrades for this device, but for
me, ScummVM DS ran straight out of the box. Visit this page
<http://www.ninjads.com/news.html> to download the latest firmware
if you want. If you have installed FlashMe on your DS, it will
make your DS crash on boot when the NinjaDS is inserted. You can
hold the 'select' button during boot to disable FlashMe, which
will allow the NinjaDS to work. Due to this, it is not recommended
to install FlashMe if you use a NinjaDS.
* *EZ-Flash*: This card reader uses .ds.gba files from the ScummVM
archive. Rename them to .nds before patching them with the DLDI
patcher.
* *R4DS*: If you upgrade the firmware for your R4DS to version 1.10
or later, the card will autmatically DLDI patch the game, meaning
you don't have to use dlditool to patch the .NDS file. This makes
things a lot easier!
* *M3DS Real*: This card autmatically DLDI patches the game, meaning
that you do not need to do this yourself.
Which games are compatible with ScummVM DS?
------------------------------------------------------------------------
I'm glad you asked. Here is a list of the compatible games in version
0.12.0. Demo versions of the games listed should work too.
Flight of the Amazon Queen, Beneath a Steel Sky, and Lure of the
Temptress have generously been released as freeware by the original
authors, Revolution Software <http://www.revolution.co.uk/>. This is a
great thing and we should support Revolution for being so kind to us.
You can download the game data from the official ScummVM download page
<http://www.scummvm.org/downloads.php>.
The other games on this list are commercial, and still under copyright,
which means downloading them without paying for it is illegal. You can
probably find a second-hand copy on eBay. Please don't email me to ask
for a copy, as I am unable to send it to you.
Game Build Notes
Manic Mansion A
Zak McKracken and the Alien Mindbenders A
Indiana Jones and the Last Crusade A
Loom A
Passport to Adventure A
The Secret of Monkey Island A
Monkey Island 2: LeChuck's Revenge A
Indiana Jones and the Fate of Atlantis A
Day of the Tentacle A
Sam & Max Hit the Road A Some slowdown in a few scenes
when MP3 audio is enabled
Bear Stormin' (DOS) A
Fatty Bear's Birthday Surprise (DOS) A
Fatty Bear's Fun Pack (DOS) A
Putt-Putt's Fun Pack (DOS) A
Putt-Putt Goes to the Moon (DOS) A
Putt-Putt Joins the Parade (DOS) A Can sometimes crash due to low memory
Beneath a Steel Sky B
Flight of the Amazon Queen B
Simon the Sorcerer 1 C Zoomed view does not follow the
speaking character
Simon the Sorcerer 2 C Zoomed view does not follow the
speaking character
Elvira 1 C
Elvira 2 C
Waxworks (Amiga version) C
Gobliiins D
Gobliins 2 D
Goblins 3 D
Ween: The Prophecy D
Bargon Attack D
Lost in Time D
Future Wars D
All Sierra AGI games.
For a complete list, see this page
<http://wiki.scummvm.org/index.php/AGI> D
Inherit the Earth E
The Legend of Kyrandia F Zoomed view does not follow the
speaking character
Lure of the Temptress G
Nippon Safes G
There is no support for Full Throttle, The Dig, or The Curse of Monkey
Island because of memory issues. There simply is not enough RAM on the
DS to run these games. Sorry. Also there is no support for Windows Humongous
Entertainment games. The extra code required to make this work uses up
too much RAM.
What to do when saving doesn't work or your card gets corrupted -
forcing SRAM Saves
------------------------------------------------------------------------
This method only works for cards which use the Game Boy Advance slot on the
bottom of your DS.
If ScummVM DS cannot save games to your SD card, or it causes corruption
when it does, you can force it to use GBA SRAM to save the game. This
uses your flash cart reader's GBA features to save the game to a .sav or
.dat file (depending on the reader). Only slot-2 devices can use SRAM saves,
and only ones with support for GBA games.
If you want to use SRAM save, just create a text file called scummvm.ini
(or scummvmb.ini, scummvmc.ini for builds B or C) in the root of your
card which contains the following:
[ds]
forcesramsave=true
When you boot your game, ScummVM DS will not save games to your SD card
directly, instead it will save to GBA SRAM. On most cards, you need to
transfer the data to your SD card by rebooting and using your card
reader's boot-up menu. Using this method, around four saves can me made.
One disadvantage of forcing SRAM saves is that your settings won't be
saved. You can add games manually to the ini file so that you don't have
to select them on each boot. Just add a section like the following on
for each game on your card.
[monkey2]
description=Monkey Island 2: LeChuck's Revenge (English/DOS)
path=mp:/MONKEY2
How to Use ScummVM
------------------------------------------------------------------------
Once you've booted up ScummVM, you'll see the start up screen.
1. Tap the 'Add' button with the pen, then browse to the folder
containing your game data. Once you have clicked on your folder, you will
not see any files inside. This is normal, as the folder selector only shows
folders!
2. Click the 'Choose' button.
3. You will get some options for the game. You can usually just click 'Ok' to
this.
4. Now click on the name of the game you want to play from the list and
click 'Start'. Your game will start!
You can use the B button to skip cutscenes, and the select button to
show an options menu which will let you tweak the DS contols, including
switch between scaled and unscaled video modes. The text is clearer in
the unscaled mode, but the whole game doesn't fit on the screen. To
scroll around, hold either shoulder button and use the D-pad or drag the
screen around with the stylus. Even in scaled mode, a small amount is
missing from the top and bottom of the screen. You can scroll around to
see those areas. The top screen shows a zoomed-in view. This scrolls
around to focus on the character who's speaking, and also follows where
the pen touches the screen. You can change the zoom level by holding one
of the shoulder buttons and pressing B to zoom in and A to zoom out.
Press the start button for the in-game menu where you can load or save
your game (this works in Lucasarts games, other games vary). Saves will
write directly to your flash card. You can choose the folder where they
are stored using the GUI that appears when you boot up. If you're using
a GBA Flash Cartridge, or an unsupported flash card adaptor, you will be
using GBA SRAM to save your game. Four or five save game will fit in
save RAM. If you save more games than will fit, a warning will appear on
the top screen. When you turn your DS off, the new save will be lost,
and only the first ones you saved will be present.
Many of the games use both mouse buttons. Usually the right button often
performs the default action on any object you click on. To simulate this
with the DS pen, you can switch the input into one of three modes. Press
left on the D-pad to enable the left mouse button. Press right on the
D-pad to enable the right mouse button. Press up on the D-pad to enable
hover mode. In this mode, you won't click on anything, just hover the
mouse cursor over it. This lets you pick out active objects in the scene.
An icon on the top screen will show you which mode you're in.
In hover mode, there are some additional controls. While holding the pen
on the screen, tapping D-pad left or D-pad right (or A/Y in left handed
mode) will click the left or right mouse button.
There is an alternative method of control which doesn't require you to
change modes with the D-pad. Press 'Select' to bring up the DS options,
and choose 'Tap for left click, double tap for right click'. In this
mode, you can quickly tap the screen to left click the mouse, and tap twice
to right click the mouse.
Here is a complete list of controls in right-handed mode (the default
setting):
Key Usage
Pad Left Left mouse button
Pad Right Right mouse button
Pad Up Hover mouse (no mouse button)
Pad Down Skip dialogue line (for some Lucasarts games), Show inventory
(for Beneath a Steel Sky), Show active objects (for Simon the Sorceror)
Start Pause/game menu (works in some games)
Select DS Options
B Skip cutscenes
A Swap main screen and zoomed screen
Y Show/Hide debug console
X Show/Hide on-screen keyboard
L + D-pad or L + Pen Scroll touch screen view
L + B Zoom in
L + A Zoom out
And here's left-handed mode:
Key Usage
Y Left mouse button
A Right mouse button
X Hover mouse (no mouse button)
B Skip dialogue line (for some Lucasarts games), Show inventory (for
Beneath a Steel Sky), Show active objects (for Simon the Sorceror)
Start Pause/game menu (works in some games)
Select DS Options
D-pad down Skip cutscenes
D-pad up Swap main screen and zoomed screen
D-pad left Show/Hide debug console
D-pad right Show/Hide on-screen keyboard
R + D-pad or R + Pen Scroll touch screen view
R + D-pad down Zoom in
R + d-pad right Zoom out
Game-specific controls
------------------------------------------------------------------------
* Sam and Max Hit the Road: The current cursor mode is displayed on
the top screen. Use d-pad right to switch mode.
* Indiana Jones games: If you get into a fight, press Select, and
check the box marked 'Use Indy Fighting Controls'.
Return to the game, then use the following controls to fight:
D-pad left: move left
D-pad right: move right
D-pad up: guard up
D-pad down: guard down
Y: guard middle
X: Punch high
A: Punch middle
B: Punch low
Left shoulder: Fight towards the left
Right shoulder: Fight towards the right
The icon on the top screen shows which way you're currently
facing. Remember to turn the option off when the fight ends, or
the normal controls won't work!
* Beneath a Steel Sky: Press D-pad down to show your inventory.
* Simon the Sorcerer 1/2: Press D-pad down to show active objects.
* AGI games: Press Start to show the menu bar.
* Bargon Attack: Press Start to hit F1 when you need to start the
game. Use the on-screen keyboard (hit X) to press other function keys.
DS Options Screen
------------------------------------------------------------------------
Pressing the 'select' button during any game to show the DS options
screen. This screen shows options specific to the Nintendo DS version
of ScummVM.
Controls tab
Indy Fight Controls - Enable fighting controls for the Indiana Jones
games. See 'Game Specific Controls' for more information.
Left handed Mode - Switch the controls on the D-pad with the controls
on the A/B/X/Y buttons.
Show mouse cursor - Shows the game's mouse cursor on the bottom screen.
Snap to edges - makes it easier for the mouse controls to reach the edges
of the screen. Useful for Beneath a Steel Sky and Goblins 3.
Touch X offset - if your screen doesn't perform properly, this setting
allows you to adjust when the cursor appears left or right relative to
the screen's measured touch position.
Touch Y offset - if your screen doesn't perform properly, this setting
allows you to adjust when the cursor appears higher or lower relative to
the screen's measured touch position.
Use Laptop Trackpad-style cursor control - In this mode, use the lower
screen to drag the cursor around, a bit like using a trackpad on a laptop.
When this option is enabled, the following option is also enabled.
Tap for left click, double tap for right click - In this mode, you can
quickly tap on the screen to left click the mouse, or quickly
double tap on the screen to right click the mouse. If you find clicking
or double-clicking difficult, try and make a firmer touch on the screen,
and keep the pen down for longer.
Sensitivity - this bar adjusts the speed of cursor movement when laptop
trackpad-style cursor control is enabled (see above).
Graphics Tab
Scaling options:
Three scaling options are available for the main screen.
Harware Scale - Scales using the DS hardware scaler using a flicker method.
Produces lower quality graphics but doesn't slow the game down.
Software Scale - Scales using the CPU. A much higher quality image is
produced, but at the expense of speed in some games.
Unscaled - Allows you to see the graphics as originaly displayed. This
doesn't fit on the DS screen, but you can scroll the screen around by holding
the left shoulder button and using the D-pad or touch screen.
Top screen zoom - These three options control the zoom level of the top
screen when ScummVM is started up. Changing this option will set the zoom
to the specified level immediately.
Initial top screen scale:
This option controls the scaling level of the zoomed screen. In ScummVM
DS, one screen shows a zoomed-in view of the action, and this option controls
how zoomed in it is. You can also adjust this in the game by holding L and
pressing A/B.
General Tab
High Quality Audio - Enhance the sound quality, at the expense of some
slowdown during some games.
Disable power off - ScummVM DS turns the power off when the game quits.
This option disables that feature.
Auto completion dictionary for Sierra AGI games
------------------------------------------------------------------------
If you are playing a Sierra AGI game, you will be using the on-screen
keyboard quite a lot (press X to show it). To reduce the amount you have
to type, the game can automatically complete long words for you. To use
this feature, simply copy the PRED.DIC file from the ScummVM DS archive
into your game folder on your card. Now, when you use the keyboard,
possible words will be shown underneith it. To type one of those words,
simply double click on it with your stylus.
Converting your CD audio
------------------------------------------------------------------------
ScummVM supports playing CD audio for specific games which came with
music stored as standard music CD tracks. To use this music in ScummVM
DS, they need to be ripped from the CD and stored in a specific format.
This can only be done for the CD versions of certain games, such as
Monkey Island 1, Loom, and Gobliiins. All the floppy games and CD games
that didn't have CD audio tracks for music don't require any conversion,
and will work unmodified on ScummVM DS. MP3 audio files for CD music are
not supported.
Cdex can do the conversion very well and I recommend using it to convert
your audio files, although any CD ripping software can be used, so feel
free to use your favourite program. The format you need to use is
IMA-ADPCM 4-bit Mono. You may use any sample rate. All other formats
will be rejected, including uncompressed WAV files.
Now I will to describe how to rip your CD tracks with Cdex, which can be
found here: Cdex Homepage <http://sourceforge.net/projects/cdexos/>.
Other software can be used to create IMA ADPCM files under Linux or
MacOS.
To set this up in Cdex, select Settings from the Options menu. On the
Encoder tab, select 'WAV Output Encoder'. Under 'Encoder Options',
choose the following:
Format: WAV
Compression: IMA ADPCM
Samplerate: 22050 Hz
Channels: Mono
On the fly encoding: On
Next, go to the 'Filenames' tab and select the folder you want to save
your Wav files to. Under 'Filename format', enter 'track%3'. This should
name your WAV files in the correct way. Click OK.
Now select all the tracks on your CD, and click 'Extract CD tracks to a
compressed audio file'. Cdex should rip all the audio off your CD.
Now all you have to do is copy the newly created WAV files into the same
directory that your other game data is stored on your CompactFlash card.
Next time your run ScummVM DS, it should play with music!
*Important Note:* Do not select 'Extract CD tracks to a WAV file'. This
creates uncompressed WAVs only. You want 'Extract CD tracks to a
compressed audio file'.
Converting Speech files to MP3 format
------------------------------------------------------------------------
ScummVM supports playing back speech for talkie games in MP3 format.
Unfortunately, the DS CPU is not quite up to the task, and MP3 audio
will sometimes cause slowdown in your game. However, if your flash card
isn't big enough to fit the audio files on, you will have no choice!
To convert your audio you will need a copy of the ScummVM Tools package
<http://sourceforge.net/project/showfiles.php?group_id=37116&package_id=67433>.
You will also need a copy of the LAME MP3 encoder
<http://www.free-codecs.com/Lame_Encoder_download.htm>.
Once this is all installed and set up, the process to encode your audio
varies from game to game, but the Lucasarts games can all be compressed
using the following command line:
compress_scumm_sou --mp3 monster.sou
This produces a monster.so3 file which you can copy to your flash card
and replaces the original monster.sou. Ogg format (monster.sog) and flac
format files are not currently supported by ScummVM DS, and it is
unlikely they will ever be supported. There is no way to convert .sog or
.so3 files back to .sou files. Just dig out your original CD and copy
the file from that.
Frequently Asked Questions
------------------------------------------------------------------------
I get a lot of email about ScummVM DS. Nearly all of them are exactly
the same. Here I'm going to try and answer the questions that everybody
asks me in the hope that I will spend less time answering questions that
are clearly in the documentation and more time helping people who have a
real problem or have discovered a real bug.
*Q:* I can't see the bottom line of inventory items in Day of the
Tentacle, Monkey Island 2, or a few other games! What do I do?
*A:* Hold down the left shoulder button and use D-pad (or the touch
screen) to scroll the screen around.
*Q:* I dont see a menu when I press Start in Flight of the Amazon Queen
or Simon the Sorcerer. Is ScummVM broken?
*A:* No. To save in Simon the Sorcerer, click 'use', then click on the
postcard in your inventory. In Flight of the Amazon Queen, click 'use',
then click on the journal in your inventory.
*Q:* Why does ScummVM crash when I play Monkey Island 1?
*A:* This happens when MP3 audio tracks are present from the PC version
of ScummVM. Delete the MP3 tracks and reencode them to ADPCM WAV files
as described in the CD audio section.
*Q:* When will you support my Mini/Micro SD card reader? I want it!
Pretty please?
*A:* ScummVM uses DLDI drivers. If your card reader manufacturer doesn't
provide a driver, there is nothing I can do about it. The people to ask
are the card reader manufacturers themselves.
*Q:* Can't you use the extra RAM in the M3/Supercard or the official
Opera Expansion Pack to support more games like The Dig and Full
Throttle? DS Linux has done it, so why can't you?
*A:* Not at the moment. The extra RAM has certain differences to the
build in RAM which makes it difficult to use for general programs. As
ScummVM DS is an official port, the changes to the ScummVM code base
must be minimal to avoid making the code difficult to read for other
users. I do have plans to work on this some time in the future, but
don't nag me about when it'll be done. If and when there's progress with
this, I will post on the ScummVM forums about it.
*Q:* ScummVM DS turns off my DS when I hit 'Quit' in the game or quit
from the frontend. Why doesn't it return to the menu?
*A:* Due to bugs in the ScummVM codebase, many of the ScummVM games
cannot quit cleanly leaving the machine in the same state as when it
started. You will notice that no other versions of ScummVM can quit back
to the menu either. This will be fixed at some time in the future.
Contributors
------------------------------------------------------------------------
ScummVM DS uses chishm's GBA Movie Player FAT driver.
The CPU scaler is by Tramboi and Robin Watts
The ARM code was optimised by Robin Watts
Thanks to highpass for the ScummVM DS icons.
Thanks to zhevon for the Sam & Max cursor code.
Thanks to theNinjaBunny for the M3 Adaptor guide on this site.
Thanks also to everyone on the GBADev Forums.
This program was brought to you by caffiene, sugar, and late nights.
Donations and Getting Help
------------------------------------------------------------------------
If you have problems getting ScummVM to work on your hardware, please
read the FAQ first. /Please/ don't ask me questions which are
answered in the FAQ, I get many emails about this program each day, and
I can't help the people who really need help if I'm answering the same
question all the time which is already answered on this page. Other than
that, feel free to post on the ScummVM DS forum <http://forums.scummvm.org>
for help. Please do your research first though. There is no way of
running this on an out-of-the box DS without extra hardware. Most of
these things are fairly inexpensive though.
If you want to contact me, please email me on scummvm at millstone dot
demon dot co dot uk.
If you want to help with the development of ScummVM DS, great! Download
the source code and get building. There are plenty of things left to do.
You can also help by making a donation if you've particularly enjoyed
ScummVM DS. This uses Paypal, and is completely secure. There's no
pressure though, ScummVM DS is completely free. This is just for those
who would like to make a contribution to further development.
Building from Sources
------------------------------------------------------------------------
ScummVM is an open source project. This means that anyone is free to
take the source code to the project and make their own additions and fixes,
contributing them back to the authors for consideration for the next version.
To build ScummVM DS from source, it's probably better to checkout the
latest version of the code from the ScummVM SVN repository. The ScummVM
Sourceforge.net homepage <http://sourceforge.net/projects/scummvm> has
all the information about how to do this.
By default, ScummVM DS expects to find libmad, an MP3 compressor library
targeted for the ARM platform. If you don't have this, you must disable
libmad support by opening 'backends/platform/ds/arm9/makefile' and
commenting out the line which says USE_MAD = 1.
Then, enter the 'backends/platform/ds' folder and type:
make SCUMM_BUILD=a
The executable nds file will build inside 'backends/platform/ds/arm9/SCUMMVM-A'.
For other builds, substitute the letters b - g in the above line.

View file

@ -8,25 +8,29 @@ libndsdir = $(DEVKITPRO)/libnds
# Select the build by setting SCUMM_BUILD to a,b,c,d,e,f or g.
# Anything else gets build a.
ifeq ($(SCUMM_BUILD),g)
DS_BUILD_G = 1
else
ifeq ($(SCUMM_BUILD),f)
DS_BUILD_F = 1
ifeq ($(SCUMM_BUILD),h)
DS_BUILD_H = 1
else
ifeq ($(SCUMM_BUILD),e)
DS_BUILD_E = 1
ifeq ($(SCUMM_BUILD),g)
DS_BUILD_G = 1
else
ifeq ($(SCUMM_BUILD),d)
DS_BUILD_D = 1
ifeq ($(SCUMM_BUILD),f)
DS_BUILD_F = 1
else
ifeq ($(SCUMM_BUILD),e)
DS_BUILD_E = 1
else
ifeq ($(SCUMM_BUILD),c)
DS_BUILD_C = 1
ifeq ($(SCUMM_BUILD),d)
DS_BUILD_D = 1
else
ifeq ($(SCUMM_BUILD),b)
DS_BUILD_B = 1
ifeq ($(SCUMM_BUILD),c)
DS_BUILD_C = 1
else
ifeq ($(SCUMM_BUILD),b)
DS_BUILD_B = 1
else
DS_BUILD_A = 1
endif
endif
endif
endif
@ -67,7 +71,12 @@ endif
# NOTE: The header and libs for the debugger is assumed to be in the libnds
# folder.
VPATH = $(srcdir)
vpath %.h $(srcdir)
vpath %.cpp $(srcdir)
vpath %.c $(srcdir)
vpath %.m $(srcdir)
vpath %.asm $(srcdir)
vpath %.s $(srcdir)
# Command to build libmad is:
# ./configure --host=arm-elf --enable-speed --enable-sso -enable-fpm=arm CFLAGS='-specs=ds_arm9.specs -mthumb-interwork'
@ -75,8 +84,8 @@ VPATH = $(srcdir)
# I actually had to use
# ./configure --host=arm-elf --enable-speed --enable-sso -enable-fpm=arm CFLAGS='-specs=ds_arm9.specs -mthumb-interwork' LDFLAGS='C:/Progra~1/devkitpro/libnds/lib/libnds9.a' --disable-shared --disable-debugging
USE_ARM_SOUND_ASM = 1
ARM = 1
USE_ARM_SOUND_ASM = 1
USE_ARM_COSTUME_ASM = 1
ifdef DS_BUILD_A
@ -135,6 +144,13 @@ ifdef DS_BUILD_G
BUILD=scummvm-G
endif
ifdef DS_BUILD_H
DEFINES = -DDS_NON_SCUMM_BUILD -DDS_BUILD_H
LOGO = logog.bmp
ENABLE_PARALLACTION = STATIC_PLUGIN
BUILD=scummvm-H
endif
ARM7BIN := -7 $(CURDIR)/../../arm7/arm7.bin
ICON := -b ../../../logo.bmp "ScummVM;By Neil Millstone;"
@ -147,6 +163,7 @@ CFLAGS = -Wno-multichar -Wall\
-mcpu=arm9tdmi -mtune=arm9tdmi -fomit-frame-pointer\
-mthumb-interwork -DUSE_ARM_COSTUME_ASM=1
# -ffast-math
ifdef USE_DEBUGGER
@ -160,7 +177,7 @@ ifdef USE_PROFILER
endif
CXXFLAGS= $(CFLAGS) -Wno-non-virtual-dtor -Wno-unknown-pragmas -Wno-reorder \
-fno-exceptions -fno-rtti -mthumb-interwork
-fno-exceptions -fno-rtti -mthumb-interwork -ffunction-sections -fdata-sections
# -mthumb
@ -180,12 +197,12 @@ ifdef USE_MAD
endif
LDFLAGS = -specs=ds_arm9.specs -mthumb-interwork -Wl,--wrap,time -mno-fpu -Wl,-Map,map.txt
LDFLAGS = -specs=ds_arm9.specs -mthumb-interwork -Wl,--wrap,time -mno-fpu -Wl,-Map,map.txt -Wl,--gc-sections
INCLUDES= -I./ -I$(portdir)/$(BUILD) -I$(srcdir) -I$(srcdir)/common -I$(portdir)/source \
-I$(portdir)/data -I$(libndsdir)/include -I$(portdir)/../commoninclude\
-I$(libndsdir)/include -I$(libndsdir)/include/nds -I$(srcdir)/engines -I$(portdir)/source/mad\
-I$(portdir)/source/libcartreset -include $(srcdir)/common/scummsys.h
INCLUDES= -I$(portdir)/$(BUILD) -I$(srcdir) -I$(srcdir)/engines \
-I$(portdir)/data -I$(portdir)/../commoninclude \
-I$(portdir)/source -I$(portdir)/source/mad -I$(portdir)/source/libcartreset \
-I$(libndsdir)/include -include $(srcdir)/common/scummsys.h
LIBS = -lm -L$(libndsdir)/lib -L$(portdir)/lib -lnds9
@ -232,7 +249,8 @@ endif
DATA_OBJS := $(portdir)/data/icons.o $(portdir)/data/keyboard.o $(portdir)/data/keyboard_pal.o $(portdir)/data/default_font.o $(portdir)/data/8x8font_tga.o
COMPRESSOR_OBJS := $(portdir)/source/compressor/lz.o
COMPRESSOR_OBJS :=
#$(portdir)/source/compressor/lz.o
FAT_OBJS := $(portdir)/source/fat/disc_io.o $(portdir)/source/fat/gba_nds_fat.o\
$(portdir)/source/fat/io_fcsr.o $(portdir)/source/fat/io_m3cf.o\
@ -252,14 +270,15 @@ FAT_OBJS := $(portdir)/source/fat/disc_io.o $(portdir)/source/fat/gba_nds_fat.o
# $(portdir)/source/fat/io_sd_common.o $(portdir)/source/fat/io_scsd_s.o \
# $(portdir)/source/fat/io_sc_common.o $(portdir)/source/fat/io_sd_common.o
LIBCARTRESET_OBJS := $(portdir)/source/libcartreset/cartreset.o
LIBCARTRESET_OBJS :=
#$(portdir)/source/libcartreset/cartreset.o
# Files in this list will be optimisied for speed, otherwise they will be optimised for space
OPTLIST := actor.cpp ds_main.cpp osystem_ds.cpp blitters.cpp fmopl.cpp rate.cpp mixer.cpp isomap.cpp image.cpp gfx.cpp sprite.cpp actor_path.cpp actor_walk.cpp
#OPTLIST :=
# Compiler options for files which should be optimised for speed
OPT_SPEED := -O2
OPT_SPEED := -O3
# Compiler options for files which should be optimised for space
OPT_SIZE := -Os
@ -281,7 +300,7 @@ ndsall:
include $(srcdir)/Makefile.common
semiclean:
$(RM) $(portdir)/source/dsoptions.o $(portdir)/source/dsmain.o $(FAT_OBJS) $(DATA_OBJS) $(portdir)/source/wordcompletion.o
$(RM) $(portdir)/source/dsoptions.o $(portdir)/source/dsmain.o $(FAT_OBJS) $(DATA_OBJS) $(portdir)/source/wordcompletion.o $(portdir)/source/dsoptions.o
clean:
$(RM) $(OBJS) $(EXECUTABLE)
@ -333,36 +352,17 @@ endef
##############
# Replacement rule for the one in makefile.common
##############
ifndef HAVE_GCC3
# If you use GCC, disable the above and enable this for intelligent
# dependency tracking.
#.cpp.o:
%.o:%.cpp
$(MKDIR) $(*D)/$(DEPDIR)
$(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d2" $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
# $(ECHO) "$(*D)/" > $(*D)/$(DEPDIR)/$(*F).d
$(CAT) "$(*D)/$(DEPDIR)/$(*F).d2" >> "$(*D)/$(DEPDIR)/$(*F).d"
$(RM) "$(*D)/$(DEPDIR)/$(*F).d2"
else
# If you even have GCC 3.x, you can use this build rule, which is safer; the above
# rule can get you into a bad state if you Ctrl-C at the wrong moment.
# Also, with this GCC inserts additional dummy rules for the involved headers,
# which ensures a smooth compilation even if said headers become obsolete.
#.cpp.o:
%.o:%.cpp
%.o: %.cpp
# echo !!!!!!!!!!!! $(notdir $<)
# ifeq ( $(notdir $<), $(findstring $(notdir $<), $(OPTLIST)) )
# OPTFLAG=-O3
# else
# OPTFLAG=-Os
# endif
# export OPTFLAG = ;
# echo !!!!!!!! $(OPTFLAG)
$(MKDIR) $(*D)/$(DEPDIR)
$(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(if $(findstring $(notdir $<), $(OPTLIST)), $(OPT_SPEED), $(OPT_SIZE)) $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o
endif
#---------------------------------------------------------------------------------
@ -412,6 +412,7 @@ endif
padbin 16 $(basename $@).ds.gba
#---------------------------------------------------------------------------------
# FIXME: The following rule hardcodes the input & output filename -- shouldn't it use $< and $@ instead?
%.bin: %.elf
$(OBJCOPY) -S scummvm.elf scummvm-stripped.elf
$(OBJCOPY) -O binary scummvm-stripped.elf scummvm.bin
@ -419,4 +420,3 @@ endif
#%.o: %.s
# $(MKDIR) $(*D)/$(DEPDIR)
# $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o

View file

@ -20,149 +20,12 @@
@
@ @author Robin Watts (robin@wss.co.uk)
.global asmDrawStripToScreen
.global asmCopy8Col
.global Rescale_320x256xPAL8_To_256x256x1555
.global Rescale_320x256x1555_To_256x256x1555
.section .itcm,"ax", %progbits
.align 2
.code 32
@ ARM implementation of asmDrawStripToScreen.
@
@ C prototype would be:
@
@ extern "C" void asmDrawStripToScreen(int height,
@ int width,
@ byte const *text,
@ byte const *src,
@ byte *dst,
@ int vsPitch,
@ int vsScreenWidth,
@ int textSurfacePitch);
@
@ In addition, we assume that text, src and dst are all word (4 byte)
@ aligned. This is the same assumption that the old 'inline' version
@ made.
asmDrawStripToScreen:
@ r0 = height
@ r1 = width
@ r2 = text
@ r3 = src
MOV r12,r13
STMFD r13!,{r4-r7,r9-r11,R14}
LDMIA r12,{r4,r5,r6,r7}
@ r4 = dst
@ r5 = vsPitch
@ r6 = vmScreenWidth
@ r7 = textSurfacePitch
CMP r0,#0 @ If height<=0
MOVLE r0,#1 @ height=1
CMP r1,#4 @ If width<4
BLT end @ return
@ Width &= ~4 ? What's that about then? Width &= ~3 I could have
@ understood...
BIC r1,r1,#4
SUB r5,r5,r1 @ vsPitch -= width
SUB r6,r6,r1 @ vmScreenWidth -= width
SUB r7,r7,r1 @ textSurfacePitch -= width
MOV r10,#253
ORR r10,r10,r10,LSL #8
ORR r10,r10,r10,LSL #16 @ r10 = mask
yLoop:
MOV r14,r1 @ r14 = width
xLoop:
LDR r12,[r2],#4 @ r12 = [text]
LDR r11,[r3],#4 @ r11 = [src]
CMP r12,r10
BNE singleByteCompare
SUBS r14,r14,#4
STR r11,[r4], #4 @ r4 = [dst]
BGT xLoop
ADD r2,r2,r7 @ text += textSurfacePitch
ADD r3,r3,r5 @ src += vsPitch
ADD r4,r4,r6 @ dst += vmScreenWidth
SUBS r0,r0,#1
BGT yLoop
LDMFD r13!,{r4-r7,r9-r11,PC}
singleByteCompare:
MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
CMP r9,r10,LSR #24 @ if (r9 == mask)
MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
CMP r9,r10,LSR #24 @ if (r9 == mask)
MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
CMP r9,r10,LSR #24 @ if (r9 == mask)
MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
MOV r9,r12,LSR #24 @ r9 = 1st byte of [text]
CMP r9,r10,LSR #24 @ if (r9 == mask)
MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src]
ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12
STR r12,[r4],#4
SUBS r14,r14,#4
BGT xLoop
ADD r2,r2,r7 @ text += textSurfacePitch
ADD r3,r3,r5 @ src += vsPitch
ADD r4,r4,r6 @ dst += vmScreenWidth
SUBS r0,r0,#1
BGT yLoop
end:
LDMFD r13!,{r4-r7,r9-r11,PC}
@ ARM implementation of asmCopy8Col
@
@ C prototype would be:
@
@ extern "C" void asmCopy8Col(byte *dst,
@ int dstPitch,
@ const byte *src,
@ int height);
@
@ In addition, we assume that src and dst are both word (4 byte)
@ aligned. This is the same assumption that the old 'inline' version
@ made.
asmCopy8Col:
@ r0 = dst
@ r1 = dstPitch
@ r2 = src
@ r3 = height
STMFD r13!,{r14}
SUB r1,r1,#4
TST r3,#1
ADDNE r3,r3,#1
BNE roll2
yLoop2:
LDR r12,[r2],#4
LDR r14,[r2],r1
STR r12,[r0],#4
STR r14,[r0],r1
roll2:
LDR r12,[r2],#4
LDR r14,[r2],r1
SUBS r3,r3,#2
STR r12,[r0],#4
STR r14,[r0],r1
BNE yLoop2
LDMFD r13!,{PC}
@ ARM implementation of Rescale_320x256x1555_To_256x256x1555
@
@ C prototype would be:

View file

@ -20,7 +20,7 @@
*
*/
#ifndef _CDAUDIO_H_
#ifndef _CDAUDIO_H_
#define _CDAUDIO_H_
namespace DS {

File diff suppressed because it is too large Load diff

View file

@ -38,7 +38,8 @@ enum controlType {
CONT_SIMON,
CONT_FUTURE_WARS,
CONT_AGI,
CONT_GOBLINS
CONT_GOBLINS,
CONT_NIPPON,
};
struct gameListType {
@ -56,6 +57,7 @@ int getPenX();
int getPenY();
GLvector getPenPos();
void consumePenEvents();
controlType getControlType();
// Pad reading
int getKeysHeld();
@ -64,6 +66,8 @@ int getKeysDown();
int getKeysReleased();
void consumeKeys();
int leftHandedSwap(int keys);
void setGameScreenSwap(bool enable);
void setSensitivity(int sensitivity);
// Video
void displayMode8Bit(); // Switch to 8-bit mode5
@ -81,6 +85,7 @@ u16* getScalerBuffer();
void setTalkPos(int x, int y);
void setTopScreenTarget(int x, int y);
void set200PercentFixedScale(bool on);
void setTopScreenZoom(int percentage);
// Timers
void setTimerCallback(OSystem_DS::TimerProc proc, int interval); // Setup a callback function at a regular interval
@ -88,7 +93,9 @@ int getMillis(); // Return the current runtime in milliseconds
void doTimerCallback(); // Call callback function if required
// Sound
void doSoundCallback(); // Call function if sound buffers need more data
void doSoundCallback();
void startSound(int freq, int buffer); // Start sound hardware
// Call function if sound buffers need more data
void playSound(const void* data, u32 length, bool loop, bool adpcm = false, int rate = 22050); // Start a sound
void stopSound(int channel);
int getSoundFrequency();
@ -131,6 +138,8 @@ void setIndyFightState(bool st);
bool getIndyFightState();
bool isCpuScalerEnabled();
void setCpuScalerEnable(bool enable);
void setTrackPadStyleEnable(bool enable);
void setTapScreenClicksEnable(bool enable);
// Display
bool getIsDisplayMode8Bit();

View file

@ -25,6 +25,7 @@
#include "gui/dialog.h"
#include "gui/newgui.h"
#include "gui/ListWidget.h"
#include "gui/TabWidget.h"
#include "osystem_ds.h"
#include "engines/scumm/scumm.h"
#include "touchkeyboard.h"
@ -41,8 +42,67 @@ namespace Scumm {
namespace DS {
DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(5, 0, 320 - 5, 230 - 20) {
addButton(this, 10, 175, "Close", GUI::kCloseCmd, 'C');
DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(0, 0, 320 - 10, 230 - 40) {
addButton(this, 10, 170, "Close", GUI::kCloseCmd, 'C');
_tab = new GUI::TabWidget(this, 5, 5, 300, 230 - 20 - 40 - 10);
_tab->addTab("Controls");
_leftHandedCheckbox = new GUI::CheckboxWidget(_tab, 5, 5, 130, 20, "Left handed mode", 0, 'L');
_indyFightCheckbox = new GUI::CheckboxWidget(_tab, 5, 20, 140, 20, "Indy fight controls", 0, 'I');
_showCursorCheckbox = new GUI::CheckboxWidget(_tab, 150, 5, 130, 20, "Show mouse cursor", 0, 'T');
_snapToBorderCheckbox = new GUI::CheckboxWidget(_tab, 150, 20, 130, 20, "Snap to edges", 0, 'T');
new GUI::StaticTextWidget(_tab, 20, 35, 100, 15, "Touch X Offset", GUI::kTextAlignLeft);
_touchX = new GUI::SliderWidget(_tab, 130, 35, 130, 12, 1);
_touchX->setMinValue(-8);
_touchX->setMaxValue(+8);
_touchX->setValue(0);
_touchX->setFlags(GUI::WIDGET_CLEARBG);
new GUI::StaticTextWidget(_tab, 20, 50, 100, 15, "Touch Y Offset", GUI::kTextAlignLeft);
_touchY = new GUI::SliderWidget(_tab, 130, 50, 130, 12, 2);
_touchY->setMinValue(-8);
_touchY->setMaxValue(+8);
_touchY->setValue(0);
_touchY->setFlags(GUI::WIDGET_CLEARBG);
new GUI::StaticTextWidget(_tab, 130 + 65 - 10, 65, 20, 15, "0", GUI::kTextAlignCenter);
new GUI::StaticTextWidget(_tab, 130 + 130 - 10, 65, 20, 15, "8", GUI::kTextAlignCenter);
new GUI::StaticTextWidget(_tab, 130 - 20, 65, 20, 15, "-8", GUI::kTextAlignCenter);
_touchPadStyle = new GUI::CheckboxWidget(_tab, 5, 80, 270, 20, "Use laptop trackpad-style cursor control", 0x20000001, 'T');
_screenTaps = new GUI::CheckboxWidget(_tab, 5, 95, 285, 20, "Tap for left click, double tap right click", 0x20000002, 'T');
_sensitivityLabel = new GUI::StaticTextWidget(_tab, 20, 110, 110, 15, "Sensitivity", GUI::kTextAlignLeft);
_sensitivity = new GUI::SliderWidget(_tab, 130, 110, 130, 12, 1);
_sensitivity->setMinValue(4);
_sensitivity->setMaxValue(16);
_sensitivity->setValue(8);
_sensitivity->setFlags(GUI::WIDGET_CLEARBG);
_tab->addTab("Graphics");
new GUI::StaticTextWidget(_tab, 5, 70, 180, 15, "Initial top screen scale:", GUI::kTextAlignLeft);
_100PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 85, 230, 20, "100%", 0x30000001, 'T');
_150PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 100, 230, 20, "150%", 0x30000002, 'T');
_200PercentCheckbox = new GUI::CheckboxWidget(_tab, 5, 115, 230, 20, "200%", 0x30000003, 'T');
new GUI::StaticTextWidget(_tab, 5, 5, 180, 15, "Main screen scaling:", GUI::kTextAlignLeft);
_hardScaler = new GUI::CheckboxWidget(_tab, 5, 20, 270, 20, "Hardware scale (fast, but low quality)", 0x10000001, 'T');
_cpuScaler = new GUI::CheckboxWidget(_tab, 5, 35, 270, 20, "Software scale (good quality, but slower)", 0x10000002, 'S');
_unscaledCheckbox = new GUI::CheckboxWidget(_tab, 5, 50, 270, 20, "Unscaled (you must scroll left and right)", 0x10000003, 'S');
_tab->addTab("General");
_highQualityAudioCheckbox = new GUI::CheckboxWidget(_tab, 5, 5, 250, 20, "High quality audio (slower) (reboot)", 0, 'T');
_disablePowerOff = new GUI::CheckboxWidget(_tab, 5, 20, 200, 20, "Disable power off", 0, 'T');
_tab->setActiveTab(0);
_radioButtonMode = false;
@ -52,46 +112,17 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(5, 0, 320 - 5, 230 - 20) {
}
#endif
new GUI::StaticTextWidget(this, 90, 10, 130, 15, "ScummVM DS Options", GUI::kTextAlignCenter);
// new GUI::StaticTextWidget(this, 90, 10, 130, 15, "ScummVM DS Options", GUI::kTextAlignCenter);
_leftHandedCheckbox = new GUI::CheckboxWidget(this, 5, 70, 130, 20, "Left handed mode", 0, 'L');
_indyFightCheckbox = new GUI::CheckboxWidget(this, 5, 40, 200, 20, "Indy fighting controls", 0, 'I');
_twoHundredPercentCheckbox = new GUI::CheckboxWidget(this, 5, 55, 230, 20, "Zoomed screen at fixed 200% zoom", 0, 'T');
_highQualityAudioCheckbox = new GUI::CheckboxWidget(this, 5, 25, 250, 20, "High quality audio (slower) (reboot)", 0, 'T');
_disablePowerOff = new GUI::CheckboxWidget(this, 5, 85, 130, 20, "Disable power off", 0, 'T');
_showCursorCheckbox = new GUI::CheckboxWidget(this, 5, 100, 130, 20, "Show mouse cursor", 0, 'T');
//#ifdef ALLOW_CPU_SCALER
// _cpuScaler = new GUI::CheckboxWidget(this, 160, 115, 90, 20, "CPU scaler", 0, 'T');
//#endif
new GUI::StaticTextWidget(this, 180, 70, 130, 15, "Main screen:", GUI::kTextAlignLeft);
_hardScaler = new GUI::CheckboxWidget(this, 140, 85, 170, 20, "Hardware scale (fast)", 0x10000001, 'T');
_cpuScaler = new GUI::CheckboxWidget(this, 140, 100, 170, 20, "Software scale (quality)", 0x10000002, 'S');
_unscaledCheckbox = new GUI::CheckboxWidget(this, 140, 115, 170, 20, "Unscaled", 0x10000003, 'S');
_snapToBorderCheckbox = new GUI::CheckboxWidget(this, 5, 115, 120, 20, "Snap to border", 0, 'T');
new GUI::StaticTextWidget(this, 20, 145, 110, 15, "Touch X Offset", GUI::kTextAlignLeft);
_touchX = new GUI::SliderWidget(this, 130, 145, 130, 12, 1);
_touchX->setMinValue(-8);
_touchX->setMaxValue(+8);
_touchX->setValue(0);
_touchX->setFlags(GUI::WIDGET_CLEARBG);
new GUI::StaticTextWidget(this, 20, 160, 110, 15, "Touch Y Offset", GUI::kTextAlignLeft);
_touchY = new GUI::SliderWidget(this, 130, 160, 130, 12, 2);
_touchY->setMinValue(-8);
_touchY->setMaxValue(+8);
_touchY->setValue(0);
_touchY->setFlags(GUI::WIDGET_CLEARBG);
new GUI::StaticTextWidget(this, 130 + 65 - 10, 175, 20, 15, "0", GUI::kTextAlignCenter);
new GUI::StaticTextWidget(this, 130 + 130 - 10, 175, 20, 15, "8", GUI::kTextAlignCenter);
new GUI::StaticTextWidget(this, 130 - 10, 175, 20, 15, "-8", GUI::kTextAlignCenter);
#ifdef DS_SCUMM_BUILD
_delDialog = new Scumm::SaveLoadChooser("Delete game:", "Delete", false, Scumm::g_scumm);
@ -125,10 +156,36 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(5, 0, 320 - 5, 230 - 20) {
_unscaledCheckbox->setState(false);
}
if (ConfMan.hasKey("twohundredpercent", "ds")) {
_twoHundredPercentCheckbox->setState(ConfMan.getBool("twohundredpercent", "ds"));
if (ConfMan.hasKey("topscreenzoom", "ds")) {
_100PercentCheckbox->setState(false);
_150PercentCheckbox->setState(false);
_200PercentCheckbox->setState(false);
switch (ConfMan.getInt("topscreenzoom", "ds"))
{
case 100: {
_100PercentCheckbox->setState(true);
break;
}
case 150: {
_150PercentCheckbox->setState(true);
break;
}
case 200: {
_200PercentCheckbox->setState(true);
break;
}
}
} else if (ConfMan.hasKey("twohundredpercent", "ds")) {
_200PercentCheckbox->setState(ConfMan.getBool("twohundredpercent", "ds"));
} else {
_twoHundredPercentCheckbox->setState(false);
// No setting
_150PercentCheckbox->setState(true);
}
if (ConfMan.hasKey("22khzaudio", "ds")) {
@ -165,6 +222,29 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(5, 0, 320 - 5, 230 - 20) {
_touchY->setValue(0);
}
if (ConfMan.hasKey("sensitivity", "ds")) {
_sensitivity->setValue(ConfMan.getInt("sensitivity", "ds"));
} else {
_sensitivity->setValue(8);
}
if (ConfMan.hasKey("touchpad", "ds")) {
_touchPadStyle->setState(ConfMan.getBool("touchpad", "ds"));
} else {
_touchPadStyle->setState(0);
}
if (ConfMan.hasKey("screentaps", "ds")) {
_screenTaps->setState(ConfMan.getBool("screentaps", "ds"));
} else {
_screenTaps->setState(0);
}
_screenTaps->setEnabled(!_touchPadStyle->getState());
_sensitivity->setEnabled(_touchPadStyle->getState());
_sensitivityLabel->setEnabled(_touchPadStyle->getState());
_sensitivityLabel->draw();
if (!_cpuScaler->getState() && !_unscaledCheckbox->getState()) {
_hardScaler->setState(true);
}
@ -180,7 +260,7 @@ DSOptionsDialog::~DSOptionsDialog() {
void DSOptionsDialog::updateConfigManager() {
ConfMan.setBool("lefthanded", _leftHandedCheckbox->getState(), "ds");
ConfMan.setBool("unscaled", _unscaledCheckbox->getState(), "ds");
ConfMan.setBool("twohundredpercent", _twoHundredPercentCheckbox->getState(), "ds");
// ConfMan.setBool("twohundredpercent", _twoHundredPercentCheckbox->getState(), "ds");
ConfMan.setBool("22khzaudio", _highQualityAudioCheckbox->getState(), "ds");
ConfMan.setBool("disablepoweroff", _disablePowerOff->getState(), "ds");
#ifdef ALLOW_CPU_SCALER
@ -190,6 +270,24 @@ void DSOptionsDialog::updateConfigManager() {
ConfMan.setInt("yoffset", _touchY->getValue(), "ds");
ConfMan.setBool("showcursor", _showCursorCheckbox->getState(), "ds");
ConfMan.setBool("snaptoborder", _snapToBorderCheckbox->getState(), "ds");
ConfMan.setBool("touchpad", _touchPadStyle->getState(), "ds");
ConfMan.setBool("screentaps", _screenTaps->getState(), "ds");
ConfMan.setInt("sensitivity", _sensitivity->getValue(), "ds");
u32 zoomLevel = 150;
if (_100PercentCheckbox->getState()) {
zoomLevel = 100;
} else if (_150PercentCheckbox->getState()) {
zoomLevel = 150;
} else if (_200PercentCheckbox->getState()) {
zoomLevel = 200;
}
consolePrintf("Saved zoom: %d\n", zoomLevel);
ConfMan.setInt("topscreenzoom", zoomLevel, "ds");
DS::setOptions();
}
@ -227,6 +325,70 @@ void DSOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint
}
if ((!guard) && (_radioButtonMode))
{
guard = true;
if ((sender == _touchPadStyle) && (cmd == 0x20000001)) {
if (_touchPadStyle->getState()) {
// Swap screens when turning on trackpad style, it feels
// much more natural!
DS::setGameScreenSwap(true);
_screenTaps->setState(true);
_screenTaps->setEnabled(false);
_screenTaps->draw();
_sensitivity->setEnabled(true);
_sensitivityLabel->setEnabled(true);
_sensitivityLabel->draw();
_sensitivity->draw();
} else {
DS::setGameScreenSwap(false);
_screenTaps->setEnabled(true);
_screenTaps->setState(false);
_screenTaps->draw();
_sensitivity->setEnabled(false);
_sensitivityLabel->setEnabled(false);
_sensitivityLabel->draw();
_sensitivity->draw();
}
}
guard = false;
}
if ((!guard) && (_radioButtonMode)) {
guard = true;
if (cmd == 0x30000001) {
_100PercentCheckbox->setState(true);
_150PercentCheckbox->setState(false);
_200PercentCheckbox->setState(false);
DS::setTopScreenZoom(100);
}
if (cmd == 0x30000002) {
_100PercentCheckbox->setState(false);
_150PercentCheckbox->setState(true);
_200PercentCheckbox->setState(false);
DS::setTopScreenZoom(150);
}
if (cmd == 0x30000003) {
_100PercentCheckbox->setState(false);
_150PercentCheckbox->setState(false);
_200PercentCheckbox->setState(true);
DS::setTopScreenZoom(200);
}
guard = false;
}
if (cmd == GUI::kCloseCmd) {
updateConfigManager();
close();
@ -297,6 +459,8 @@ void showOptionsDialog() {
}
void setOptions() {
static bool firstLoad = true;
ConfMan.addGameDomain("ds");
if (ConfMan.hasKey("lefthanded", "ds")) {
@ -327,10 +491,16 @@ void setOptions() {
DS::setUnscaledMode(false);
}
if (ConfMan.hasKey("twohundredpercent", "ds")) {
DS::set200PercentFixedScale(ConfMan.getBool("twohundredpercent", "ds"));
} else {
DS::set200PercentFixedScale(false);
if (firstLoad) {
if (ConfMan.hasKey("topscreenzoom", "ds")) {
DS::setTopScreenZoom(ConfMan.getInt("topscreenzoom", "ds"));
} else {
if (ConfMan.hasKey("twohundredpercent", "ds")) {
DS::setTopScreenZoom(200);
} else {
DS::setTopScreenZoom(150);
}
}
}
if (ConfMan.hasKey("xoffset", "ds")) {
@ -345,6 +515,12 @@ void setOptions() {
DS::setTouchXOffset(0);
}
if (ConfMan.hasKey("sensitivity", "ds")) {
DS::setSensitivity(ConfMan.getInt("sensitivity", "ds"));
} else {
DS::setSensitivity(8);
}
#ifdef ALLOW_CPU_SCALER
if (ConfMan.hasKey("cpu_scaler", "ds")) {
DS::setCpuScalerEnable(ConfMan.getBool("cpu_scaler", "ds"));
@ -353,6 +529,33 @@ void setOptions() {
}
#endif
if (ConfMan.hasKey("screentaps", "ds")) {
DS::setTapScreenClicksEnable(ConfMan.getBool("screentaps", "ds"));
} else {
DS::setTapScreenClicksEnable(false);
}
if (ConfMan.hasKey("touchpad", "ds")) {
bool enable = ConfMan.getBool("touchpad", "ds");
DS::setTrackPadStyleEnable(enable);
if ((enable) and (firstLoad)) {
// If we've just booted up, want to swap screens when trackpad mode is in use
// but not every time we enter the options dialog.
DS::setGameScreenSwap(true);
}
if (enable) {
DS::setTapScreenClicksEnable(true);
}
} else {
DS::setTrackPadStyleEnable(false);
}
firstLoad = false;
}
}

View file

@ -30,6 +30,7 @@
#include "gui/object.h"
#include "gui/widget.h"
#include "gui/dialog.h"
#include "gui/TabWidget.h"
#include "scumm/dialogs.h"
namespace DS {
@ -45,11 +46,18 @@ protected:
void togglePause();
void updateConfigManager();
GUI::TabWidget* _tab;
GUI::StaticTextWidget* _sensitivityLabel;
GUI::SliderWidget* _touchX;
GUI::SliderWidget* _touchY;
GUI::SliderWidget* _sensitivity;
GUI::CheckboxWidget* _leftHandedCheckbox;
GUI::CheckboxWidget* _unscaledCheckbox;
GUI::CheckboxWidget* _twoHundredPercentCheckbox;
GUI::CheckboxWidget* _100PercentCheckbox;
GUI::CheckboxWidget* _150PercentCheckbox;
GUI::CheckboxWidget* _200PercentCheckbox;
GUI::CheckboxWidget* _indyFightCheckbox;
GUI::CheckboxWidget* _highQualityAudioCheckbox;
GUI::CheckboxWidget* _disablePowerOff;
@ -59,6 +67,9 @@ protected:
GUI::CheckboxWidget* _hardScaler;
GUI::CheckboxWidget* _cpuScaler;
GUI::CheckboxWidget* _touchPadStyle;
GUI::CheckboxWidget* _screenTaps;
#ifdef DS_SCUMM_BUILD
Scumm::SaveLoadChooser* _delDialog;
#endif

View file

@ -54,8 +54,8 @@ bool GBAMPSaveFile::eos() const {
return DS::std_feof(handle);
}
void GBAMPSaveFile::skip(uint32 bytes) {
DS::std_fseek(handle, bytes, SEEK_CUR);
bool GBAMPSaveFile::skip(uint32 bytes) {
return DS::std_fseek(handle, bytes, SEEK_CUR) == 0;
}
void GBAMPSaveFile::flushSaveBuffer() {
@ -67,11 +67,11 @@ void GBAMPSaveFile::flushSaveBuffer() {
}
}
uint32 GBAMPSaveFile::pos() const {
int32 GBAMPSaveFile::pos() const {
return DS::std_ftell(handle);
}
uint32 GBAMPSaveFile::size() const {
int32 GBAMPSaveFile::size() const {
int position = pos();
DS::std_fseek(handle, 0, SEEK_END);
int size = DS::std_ftell(handle);
@ -79,8 +79,8 @@ uint32 GBAMPSaveFile::size() const {
return size;
}
void GBAMPSaveFile::seek(int32 pos, int whence) {
DS::std_fseek(handle, pos, whence);
bool GBAMPSaveFile::seek(int32 pos, int whence) {
return DS::std_fseek(handle, pos, whence) == 0;
}
@ -155,11 +155,13 @@ GBAMPSaveFile* GBAMPSaveFileManager::openSavefile(char const* name, bool saveOrL
sprintf(fileSpec, "%s/%s", getSavePath(), name);
}
// consolePrintf(fileSpec);
// consolePrintf("Opening the file: %s\n", fileSpec);
GBAMPSaveFile* sf = new GBAMPSaveFile(fileSpec, saveOrLoad);
if (sf->isOpen()) {
// consolePrintf("Ok");
return sf;
} else {
// consolePrintf("Fail");
delete sf;
return NULL;
}
@ -192,8 +194,29 @@ Common::StringList GBAMPSaveFileManager::listSavefiles(const char *pattern) {
enum { TYPE_NO_MORE = 0, TYPE_FILE = 1, TYPE_DIR = 2 };
char name[256];
DS::std_cwd((char*)getSavePath()); //TODO : Check this suspicious const-cast
// consolePrintf("Save path: '%s', pattern: '%s'\n", getSavePath(),pattern);
{
char dir[128];
strcpy(dir, getSavePath());
char *realName = dir;
if ((strlen(dir) >= 4) && (dir[0] == 'm') && (dir[1] == 'p') && (dir[2] == ':') && (dir[3] == '/')) {
realName += 4;
}
// consolePrintf("Real cwd:%d\n", realName);
char* p = realName;
while (*p) {
if (*p == '\\') *p = '/';
p++;
}
// consolePrintf("Real cwd:%d\n", realName);
FAT_chdir(realName);
}
// consolePrintf("Save path: '%s', pattern: '%s'\n", getSavePath(), pattern);
int fileType = FAT_FindFirstFileLFN(name);
@ -206,7 +229,7 @@ Common::StringList GBAMPSaveFileManager::listSavefiles(const char *pattern) {
FAT_GetLongFilename(name);
for (int r = 0; r < strlen(name); r++) {
for (int r = 0; name[r] != 0; r++) {
name[r] = tolower(name[r]);
}

View file

@ -43,11 +43,11 @@ public:
virtual uint32 write(const void *buf, uint32 size);
virtual bool eos() const;
virtual void skip(uint32 bytes);
virtual bool skip(uint32 bytes);
virtual uint32 pos() const;
virtual uint32 size() const;
virtual void seek(int32 pos, int whence);
virtual int32 pos() const;
virtual int32 size() const;
virtual bool seek(int32 pos, int whence);
void flushSaveBuffer();

View file

@ -41,7 +41,8 @@
OSystem_DS* OSystem_DS::_instance = NULL;
OSystem_DS::OSystem_DS()
: eventNum(0), lastPenFrame(0), queuePos(0), _mixer(NULL), _timer(NULL), _frameBufferExists(false)
: eventNum(0), lastPenFrame(0), queuePos(0), _mixer(NULL), _timer(NULL), _frameBufferExists(false),
_disableCursorPalette(true), _graphicsEnable(true)
{
// eventNum = 0;
// lastPenFrame = 0;
@ -71,7 +72,13 @@ void OSystem_DS::initBackend() {
_timer = new DSTimerManager();
DS::setTimerCallback(&OSystem_DS::timerHandler, 10);
_mixer->setOutputRate(11025 /*DS::getSoundFrequency()*/);
if (ConfMan.hasKey("22khzaudio", "ds") && ConfMan.getBool("22khzaudio", "ds")) {
DS::startSound(22050, 8192);
} else {
DS::startSound(11025, 4096);
}
_mixer->setOutputRate(DS::getSoundFrequency());
_mixer->setReady(true);
OSystem::initBackend();
@ -79,7 +86,7 @@ void OSystem_DS::initBackend() {
bool OSystem_DS::hasFeature(Feature f) {
// consolePrintf("hasfeature\n");
return (f == kFeatureVirtualKeyboard);
return (f == kFeatureVirtualKeyboard) || (f == kFeatureCursorHasPalette);
}
void OSystem_DS::setFeatureState(Feature f, bool enable) {
@ -107,7 +114,7 @@ bool OSystem_DS::setGraphicsMode(int mode) {
}
bool OSystem_DS::setGraphicsMode(const char *name) {
// consolePrintf("Set gfx mode %s\n", name);
consolePrintf("Set gfx mode %s\n", name);
return true;
}
@ -116,8 +123,15 @@ int OSystem_DS::getGraphicsMode() const {
}
void OSystem_DS::initSize(uint width, uint height) {
// consolePrintf("Set gfx mode %d x %d\n", width, height);
DS::setGameSize(width, height);
// For Lost in Time, the title screen is displayed in 640x400.
// In order to support this game, the screen mode is set, but
// all draw calls are ignored until the game switches to 320x200.
if ((width == 640) && (height == 400)) {
_graphicsEnable = false;
} else {
_graphicsEnable = true;
DS::setGameSize(width, height);
}
}
int16 OSystem_DS::getHeight() {
@ -129,9 +143,8 @@ int16 OSystem_DS::getWidth() {
}
void OSystem_DS::setPalette(const byte *colors, uint start, uint num) {
// consolePrintf("Set palette %d, %d colours\n", start, num);
//return;
if (!DS::getIsDisplayMode8Bit()) return;
// consolePrintf("Setpal %d, %d\n", start, num);
for (unsigned int r = start; r < start + num; r++) {
int red = *colors;
int green = *(colors + 1);
@ -141,19 +154,46 @@ void OSystem_DS::setPalette(const byte *colors, uint start, uint num) {
green >>= 3;
blue >>= 3;
if (r != 255)
// if (r != 255)
{
BG_PALETTE[r] = red | (green << 5) | (blue << 10);
if (!DS::getKeyboardEnable()) {
BG_PALETTE_SUB[r] = red | (green << 5) | (blue << 10);
u16 paletteValue = red | (green << 5) | (blue << 10);
if (DS::getIsDisplayMode8Bit()) {
BG_PALETTE[r] = paletteValue;
if (!DS::getKeyboardEnable()) {
BG_PALETTE_SUB[r] = paletteValue;
}
}
_palette[r] = paletteValue;
}
// if (num == 16) consolePrintf("pal:%d r:%d g:%d b:%d\n", r, red, green, blue);
// if (num == 255) consolePrintf("pal:%d r:%d g:%d b:%d\n", r, red, green, blue);
colors += 4;
}
}
void OSystem_DS::setCursorPalette(const byte *colors, uint start, uint num) {
// consolePrintf("Cursor palette set: start: %d, cols: %d\n", start, num);
for (unsigned int r = start; r < start + num; r++) {
int red = *colors;
int green = *(colors + 1);
int blue = *(colors + 2);
red >>= 3;
green >>= 3;
blue >>= 3;
u16 paletteValue = red | (green << 5) | (blue << 10);
_cursorPalette[r] = paletteValue;
colors += 4;
}
_disableCursorPalette = false;
}
bool OSystem_DS::grabRawScreen(Graphics::Surface* surf) {
surf->create(DS::getGameWidth(), DS::getGameHeight(), 1);
@ -184,9 +224,11 @@ void OSystem_DS::grabPalette(unsigned char *colors, uint start, uint num) {
}
#define MISALIGNED16(ptr) (((u32) (ptr) & 1) != 0)
void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) {
// consolePrintf("Copy rect %d, %d %d, %d ", x, y, w, h);
//consolePrintf("Copy rect %d, %d %d, %d ", x, y, w, h);
if (!_graphicsEnable) return;
if (w <= 1) return;
if (h < 0) return;
if (!DS::getIsDisplayMode8Bit()) return;
@ -195,6 +237,9 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
s32 stride;
u16* bgSub = (u16 *) BG_GFX_SUB;
// The DS video RAM doesn't support 8-bit writes because Nintendo wanted
// to save a few pennies/euro cents on the hardware.
if (_frameBufferExists) {
bg = (u16 *) _framebuffer.pixels;
stride = _framebuffer.pitch;
@ -203,46 +248,117 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int
stride = DS::get8BitBackBufferStride();
}
u16* src = (u16 *) buf;
if (DS::getKeyboardEnable()) {
if (((pitch & 1) != 0) || ((w & 1) != 0) || (((int) (buf) & 1) != 0)) {
// Something is misaligned, so we have to use the slow but sure method
int by = 0;
for (int dy = y; dy < y + h; dy++) {
u16* dest = bg + (dy * (stride >> 1)) + (x >> 1);
DC_FlushRange(src, w << 1);
DC_FlushRange(dest, w << 1);
dmaCopyHalfWords(3, src, dest, w);
src += pitch >> 1;
}
} else {
for (int dy = y; dy < y + h; dy++) {
u16* dest1 = bg + (dy * (stride >> 1)) + (x >> 1);
u16* dest2 = bgSub + (dy << 8) + (x >> 1);
u8* dest = ((u8 *) (bg)) + (dy * stride) + x;
u8* destSub = ((u8 *) (bgSub)) + (dy * 512) + x;
u8* src = (u8 *) buf + (pitch * by);
DC_FlushRange(src, w << 1);
DC_FlushRange(dest1, w << 1);
DC_FlushRange(dest2, w << 1);
dmaCopyHalfWords(3, src, dest1, w);
dmaCopyHalfWords(3, src, dest2, w);
src += pitch >> 1;
u32 dx;
u32 pixelsLeft = w;
if (MISALIGNED16(dest)) {
// Read modify write
dest--;
u16 mix = *((u16 *) dest);
mix = (mix & 0x00FF) | (*src++ << 8);
*dest = mix;
*destSub = mix;
dest += 2;
destSub += 2;
pixelsLeft--;
}
// We can now assume dest is aligned
u16* dest16 = (u16 *) dest;
u16* destSub16 = (u16 *) destSub;
for (dx = 0; dx < pixelsLeft; dx+=2) {
u16 mix;
mix = *src + (*(src + 1) << 8);
*dest16++ = mix;
*destSub16++ = mix;
src += 2;
}
pixelsLeft -= dx;
// At the end we may have one pixel left over
if (pixelsLeft != 0) {
u16 mix = *dest16;
mix = (mix & 0x00FF) | ((*src++) << 8);
*dest16 = mix;
*destSub16 = mix;
}
by++;
}
// consolePrintf("Slow method used!\n");
} else {
// Stuff is aligned to 16-bit boundaries, so it's safe to do DMA.
u16* src = (u16 *) buf;
if (DS::getKeyboardEnable()) {
for (int dy = y; dy < y + h; dy++) {
u16* dest = bg + (dy * (stride >> 1)) + (x >> 1);
DC_FlushRange(src, w << 1);
DC_FlushRange(dest, w << 1);
dmaCopyHalfWords(3, src, dest, w);
while (dmaBusy(3));
src += pitch >> 1;
}
} else {
for (int dy = y; dy < y + h; dy++) {
u16* dest1 = bg + (dy * (stride >> 1)) + (x >> 1);
u16* dest2 = bgSub + (dy << 8) + (x >> 1);
DC_FlushRange(src, w << 1);
DC_FlushRange(dest1, w << 1);
DC_FlushRange(dest2, w << 1);
dmaCopyHalfWords(3, src, dest1, w);
if ((!_frameBufferExists) || (buf == _framebuffer.pixels)) {
dmaCopyHalfWords(2, src, dest2, w);
}
while (dmaBusy(2) || dmaBusy(3));
src += pitch >> 1;
}
}
}
// consolePrintf("Done\n");
}
void OSystem_DS::updateScreen() {
if ((_frameBufferExists) && (DS::getIsDisplayMode8Bit()))
{
if ((_frameBufferExists) && (DS::getIsDisplayMode8Bit())) {
_frameBufferExists = false;
// Copy temp framebuffer back to screen
@ -253,6 +369,12 @@ void OSystem_DS::updateScreen() {
DS::doSoundCallback();
// DS::doTimerCallback();
DS::addEventsToQueue();
// Force back buffer usage for Nippon Safes, as it doesn't double buffer it's output
if (DS::getControlType() == DS::CONT_NIPPON) {
OSystem_DS::instance()->lockScreen();
OSystem_DS::instance()->unlockScreen();
}
}
void OSystem_DS::setShakePos(int shakeOffset) {
@ -334,7 +456,21 @@ void OSystem_DS::warpMouse(int x, int y) {
}
void OSystem_DS::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor, int targetCursorScale) {
DS::setCursorIcon(buf, w, h, keycolor, hotspotX, hotspotY);
if ((w > 0) && (w < 64) && (h > 0) && (h < 64))
{
memcpy(_cursorImage, buf, w * h);
_cursorW = w;
_cursorH = h;
_cursorHotX = hotspotX;
_cursorHotY = hotspotY;
_cursorKey = keycolor;
_cursorScale = targetCursorScale;
refreshCursor();
}
}
void OSystem_DS::refreshCursor() {
DS::setCursorIcon(_cursorImage, _cursorW, _cursorH, _cursorKey, _cursorHotX, _cursorHotY);
}
void OSystem_DS::addEvent(Common::Event& e) {
@ -489,7 +625,11 @@ Common::SaveFileManager* OSystem_DS::getSavefileManager() {
if (DS::isGBAMPAvailable() && (!forceSram)) {
return &mpSaveManager;
} else {
#ifdef GBA_SRAM_SAVE
return &saveManager;
#else
return NULL;
#endif
}
}

View file

@ -52,17 +52,32 @@ protected:
Common::Event eventQueue[96];
int queuePos;
#ifdef GBA_SRAM_SAVE
DSSaveFileManager saveManager;
#endif
GBAMPSaveFileManager mpSaveManager;
DSAudioMixer* _mixer;
DSTimerManager* _timer;
Graphics::Surface _framebuffer;
bool _frameBufferExists;
bool _graphicsEnable;
static OSystem_DS* _instance;
u16 _palette[256];
u16 _cursorPalette[256];
u8 _cursorImage[64 * 64];
uint _cursorW;
uint _cursorH;
int _cursorHotX;
int _cursorHotY;
byte _cursorKey;
int _cursorScale;
Graphics::Surface* createTempFrameBuffer();
bool _disableCursorPalette;
public:
typedef void (*SoundProc)(byte *buf, int len);
@ -159,7 +174,16 @@ public:
virtual void clearAutoComplete();
virtual void setCharactersEntered(int count);
u16 getDSPaletteEntry(u32 entry) { return _palette[entry]; }
u16 getDSCursorPaletteEntry(u32 entry) { return !_disableCursorPalette? _cursorPalette[entry]: _palette[entry]; }
virtual void setCursorPalette(const byte *colors, uint start, uint num);
virtual void disableCursorPalette(bool dis) { _disableCursorPalette = dis; refreshCursor(); }
FilesystemFactory *getFilesystemFactory();
void refreshCursor();
};
static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {

View file

@ -81,7 +81,10 @@ void consolePrintf(const char* s, ...);
#define ITCM_DATA __attribute__((section(".itcm")))
// Since I can't change the engine at the moment (post lockdown) this define can go here.
// This define changes the mouse-relative motion which doesn't make sense on a touch screen to
// a more conventional form of input where the menus can be clicked on.
#define LURE_CLICKABLE_MENUS
//#include "common/array.h"
//#include "common/str.h"

View file

@ -19,7 +19,9 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
// Save in order 1,2,3,4,larger 2,5
#ifdef GBA_SRAM_SAVE
#include "ramsave.h"
#include "nds.h"
#include "compressor/lz.h"
@ -64,6 +66,7 @@ DSSaveFile::DSSaveFile(SCUMMSave* s, bool compressed, u8* data) {
}
isTempFile = false;
eosReached = false;
}
DSSaveFile::~DSSaveFile() {
@ -167,11 +170,13 @@ int DSSaveFile::saveToSaveRAM(vu8* address) {
void DSSaveFile::reset() {
ptr = 0;
eosReached = false;
}
uint32 DSSaveFile::read(void *buf, uint32 size) {
if (ptr + size > save.size) {
size = save.size - ptr;
eosReached = true;
if (size < 0) size = 0;
}
memcpy(buf, saveData + ptr, size);
@ -181,15 +186,15 @@ uint32 DSSaveFile::read(void *buf, uint32 size) {
return size;
}
uint32 DSSaveFile::pos() const {
int32 DSSaveFile::pos() const {
return ptr;
}
uint32 DSSaveFile::size() const {
int32 DSSaveFile::size() const {
return save.size;
}
void DSSaveFile::seek(int32 pos, int whence) {
bool DSSaveFile::seek(int32 pos, int whence) {
switch (whence) {
case SEEK_SET: {
ptr = pos;
@ -204,15 +209,22 @@ void DSSaveFile::seek(int32 pos, int whence) {
break;
}
}
eosReached = false;
return true;
}
bool DSSaveFile::eos() const {
return ptr >= (int) save.size;
return eosReached;
}
void DSSaveFile::skip(uint32 bytes) {
void DSSaveFile::clearErr() {
eosReached = false;
}
bool DSSaveFile::skip(uint32 bytes) {
ptr = ptr + bytes;
if (ptr > (int) save.size) ptr = save.size;
return true;
}
uint32 DSSaveFile::write(const void *buf, uint32 size) {
@ -227,7 +239,7 @@ uint32 DSSaveFile::write(const void *buf, uint32 size) {
return size;
}
bool DSSaveFile::matches(char* prefix, int num) {
bool DSSaveFile::matches(const char *prefix, int num) {
char str[16];
if (isValid()) {
sprintf(str, "%s%02d", prefix, num);
@ -241,7 +253,7 @@ bool DSSaveFile::matches(char* prefix, int num) {
}
}
bool DSSaveFile::matches(char* filename) {
bool DSSaveFile::matches(const char *filename) {
if (isValid()) {
return !strcmp(save.name, filename);
} else {
@ -522,3 +534,5 @@ int DSSaveFileManager::getExtraData() {
return 0;
}
}
#endif

View file

@ -52,6 +52,7 @@ class DSSaveFile : public Common::InSaveFile, public Common::OutSaveFile {
SCUMMSave* origHeader;
bool isOpenFlag;
bool isTempFile;
bool eosReached;
public:
DSSaveFile();
@ -62,11 +63,12 @@ public:
bool isOpen() const { return isOpenFlag; }
virtual bool eos() const;
virtual void skip(uint32 size);
virtual void clearErr();
virtual bool skip(uint32 size);
virtual uint32 pos() const;
virtual uint32 size() const;
virtual void seek(int32 pos, int whence);
virtual int32 pos() const;
virtual int32 size() const;
virtual bool seek(int32 pos, int whence);
uint32 read(void *buf, uint32 size);
uint32 write(const void *buf, uint32 size);
@ -76,8 +78,8 @@ public:
bool isValid() { return save.isValid; }
bool isTemp() { return isTempFile; }
bool matches(char* prefix, int num);
bool matches(char* filename);
bool matches(const char *prefix, int num);
bool matches(const char *filename);
void clearData();
void compress();

View file

@ -402,6 +402,23 @@ void createKeyEvent(int keyNum, Common::Event& event)
}
}
void releaseAllKeys() {
for (int r = 0; r < DS_NUM_KEYS; r++) {
if (keys[r].pressed) {
DS::setKeyHighlight(r, false);
OSystem_DS* system = OSystem_DS::instance();
Common::Event event;
createKeyEvent(r, event);
event.type = Common::EVENT_KEYUP;
system->addEvent(event);
keys[r].pressed = false;
}
}
}
void addKeyboardEvents() {
bool resetShift = false;
@ -446,7 +463,7 @@ void addKeyboardEvents() {
// consolePrintf("Key: %d\n", r);
if ((keys[r].character == Common::KEYCODE_INVALID)) {
// Close button
DS::closed = true;
//DS::closed = true;
} else {
createKeyEvent(r, event);
}
@ -492,9 +509,14 @@ void addKeyboardEvents() {
OSystem_DS* system = OSystem_DS::instance();
Common::Event event;
createKeyEvent(r, event);
event.type = Common::EVENT_KEYUP;
system->addEvent(event);
if ((keys[r].character == Common::KEYCODE_INVALID)) {
// Close button
DS::closed = true;
} else {
createKeyEvent(r, event);
event.type = Common::EVENT_KEYUP;
system->addEvent(event);
}
keys[r].pressed = false;

View file

@ -40,6 +40,7 @@ bool getKeyboardClosed();
void addAutoComplete(char* word);
void clearAutoComplete();
void setCharactersEntered(int count);
void releaseAllKeys();
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 630 B

View file

@ -36,3 +36,23 @@ allbuilds:
make all SCUMM_BUILD=f
make semiclean
make all SCUMM_BUILD=g
make semiclean
make all SCUMM_BUILD=h
allbuildssafe:
make clean SCUMM_BUILD=a
make all SCUMM_BUILD=a
make clean SCUMM_BUILD=b
make all SCUMM_BUILD=b
make clean SCUMM_BUILD=c
make all SCUMM_BUILD=c
make clean SCUMM_BUILD=d
make all SCUMM_BUILD=d
make clean SCUMM_BUILD=e
make all SCUMM_BUILD=e
make clean SCUMM_BUILD=f
make all SCUMM_BUILD=f
make clean SCUMM_BUILD=g
make all SCUMM_BUILD=g
make clean SCUMM_BUILD=h
make all SCUMM_BUILD=h

View file

@ -219,7 +219,7 @@ void OSystem_GP2X::initBackend() {
// Create the savefile manager, if none exists yet (we check for this to
// allow subclasses to provide their own).
if (_savefile == 0) {
_savefile = new DefaultSaveFileManager();
_savefile = new DefaultSaveFileManager(savePath);
}
// Create and hook up the mixer, if none exists yet (we check for this to

View file

@ -54,8 +54,7 @@
@implementation SoftKeyboard
- (id)initWithFrame:(CGRect)frame {
//self = [super initWithFrame:frame];
self = [super initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, 0.0f)];
self = [super initWithFrame:frame];
inputDelegate = nil;
inputView = [[TextInputHandler alloc] initWithKeyboard:self];
return self;

View file

@ -79,10 +79,7 @@ int main(int argc, char** argv) {
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// hide the status bar
[UIHardware _setStatusBarHeight:0.0f];
//[self setStatusBarMode:2 orientation:0 duration:0.0f fenceID:0];
//[self setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:NO];
[self setStatusBarHidden:YES animated:YES];
[self setStatusBarHidden:YES animated:NO];
_window = [[UIWindow alloc] initWithContentRect: [UIHardware fullScreenApplicationContentRect]];
[_window retain];
@ -103,9 +100,13 @@ int main(int argc, char** argv) {
- (void)applicationResume:(GSEventRef)event {
[self removeApplicationBadge];
[UIHardware _setStatusBarHeight:0.0f];
[self setStatusBarHidden:YES animated:YES];
[_view applicationResume];
// Workaround, need to "hide" and unhide the statusbar to properly remove it,
// since the Springboard has put it back without apparently flagging our application.
[self setStatusBarHidden:NO animated:NO]; // hide status bar
[UIHardware _setStatusBarHeight:0.0f];
[self setStatusBarHidden:YES animated:NO]; // hide status bar
}
- (void)deviceOrientationChanged:(GSEvent *)event {

View file

@ -169,10 +169,6 @@ bool getLocalMouseCoords(CGPoint *point) {
nil
];
if (_screenSurface != nil) {
//[[sharedInstance _layer] removeSublayer: screenLayer];
}
//("Allocating surface: %d\n", allocSize);
_screenSurface = CoreSurfaceBufferCreate((CFDictionaryRef)dict);
//printf("Surface created.\n");
@ -205,10 +201,13 @@ bool getLocalMouseCoords(CGPoint *point) {
[screenLayer setFrame: _screenRect];
} else {
float ratio = (float)_height / (float)_width;
_screenRect = CGRectMake(0, 0, _fullWidth, _fullWidth * ratio);
int height = _fullWidth * ratio;
//printf("Making rect (%u, %u)\n", _fullWidth, height);
_screenRect = CGRectMake(0, 0, _fullWidth - 1, height - 1);
[screenLayer setFrame: _screenRect];
CGRect keyFrame = CGRectMake(0.0f, _screenRect.size.height, _fullWidth, _fullHeight - _screenRect.size.height);
//CGRect keyFrame = CGRectMake(0.0f, _screenRect.size.height, _fullWidth, _fullHeight - _screenRect.size.height);
CGRect keyFrame = CGRectMake(0.0f, 0.0f, 0.0f, 0.0f);
if (_keyboardView == nil) {
_keyboardView = [[SoftKeyboard alloc] initWithFrame:keyFrame];
[_keyboardView setInputDelegate:self];
@ -250,9 +249,6 @@ bool getLocalMouseCoords(CGPoint *point) {
[self lock];
id event = [_events objectAtIndex: 0];
if (event == nil) {
return nil;
}
[_events removeObjectAtIndex: 0];
[self unlock];

View file

@ -56,24 +56,27 @@ const OSystem::GraphicsMode OSystem_IPHONE::s_supportedGraphicsModes[] = {
AQCallbackStruct OSystem_IPHONE::s_AudioQueue;
SoundProc OSystem_IPHONE::s_soundCallback = NULL;
void *OSystem_IPHONE::s_soundParam = NULL;
bool OSystem_IPHONE::s_is113OrHigher = false;
OSystem_IPHONE::OSystem_IPHONE() :
_savefile(NULL), _mixer(NULL), _timer(NULL), _offscreen(NULL),
_overlayVisible(false), _overlayBuffer(NULL), _fullscreen(NULL),
_mouseHeight(0), _mouseWidth(0), _mouseBuf(NULL), _lastMouseTap(0),
_secondaryTapped(false), _lastSecondaryTap(0), _screenOrientation(kScreenOrientationFlippedLandscape),
_needEventRestPeriod(false), _mouseClickAndDragEnabled(false),
_needEventRestPeriod(false), _mouseClickAndDragEnabled(false), _touchpadModeEnabled(false),
_gestureStartX(-1), _gestureStartY(-1), _fullScreenIsDirty(false),
_mouseDirty(false), _timeSuspended(0)
_mouseDirty(false), _timeSuspended(0), _lastDragPosX(-1), _lastDragPosY(-1)
{
_queuedInputEvent.type = (Common::EventType)0;
_lastDrawnMouseRect = Common::Rect(0, 0, 0, 0);
_fsFactory = new POSIXFilesystemFactory();
}
OSystem_IPHONE::~OSystem_IPHONE() {
AudioQueueDispose(s_AudioQueue.queue, true);
delete _fsFactory;
delete _savefile;
delete _mixer;
delete _timer;
@ -88,7 +91,7 @@ int OSystem_IPHONE::timerHandler(int t) {
}
void OSystem_IPHONE::initBackend() {
_savefile = new DefaultSaveFileManager();
_savefile = new DefaultSaveFileManager(SCUMMVM_SAVE_PATH);
_timer = new DefaultTimerManager();
gettimeofday(&_startTime, NULL);
@ -665,8 +668,8 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) {
float xUnit, yUnit;
if (iPhone_fetchEvent(&eventType, &xUnit, &yUnit)) {
int x;
int y;
int x = 0;
int y = 0;
switch (_screenOrientation) {
case kScreenOrientationPortrait:
x = (int)(xUnit * _screenWidth);
@ -684,326 +687,50 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) {
switch ((InputEvent)eventType) {
case kInputMouseDown:
//printf("Mouse down at (%u, %u)\n", x, y);
// Workaround: kInputMouseSecondToggled isn't always sent when the
// secondary finger is lifted. Need to make sure we get out of that mode.
_secondaryTapped = false;
warpMouse(x, y);
// event.type = Common::EVENT_MOUSEMOVE;
// event.mouse.x = _mouseX;
// event.mouse.y = _mouseY;
if (_mouseClickAndDragEnabled) {
event.type = Common::EVENT_LBUTTONDOWN;
event.mouse.x = _mouseX;
event.mouse.y = _mouseY;
return true;
} else {
_lastMouseDown = curTime;
}
return false;
if (!handleEvent_mouseDown(event, x, y))
return false;
break;
case kInputMouseUp:
//printf("Mouse up at (%u, %u)\n", x, y);
if (_mouseClickAndDragEnabled) {
event.type = Common::EVENT_LBUTTONUP;
event.mouse.x = _mouseX;
event.mouse.y = _mouseY;
} else {
if (curTime - _lastMouseDown < 250) {
event.type = Common::EVENT_LBUTTONDOWN;
event.mouse.x = _mouseX;
event.mouse.y = _mouseY;
_queuedInputEvent.type = Common::EVENT_LBUTTONUP;
_queuedInputEvent.mouse.x = _mouseX;
_queuedInputEvent.mouse.y = _mouseY;
_lastMouseTap = curTime;
_needEventRestPeriod = true;
} else
return false;
}
if (!handleEvent_mouseUp(event, x, y))
return false;
break;
case kInputMouseDragged:
//printf("Mouse dragged at (%u, %u)\n", x, y);
if (_secondaryTapped) {
if (_gestureStartX == -1 || _gestureStartY == -1) {
return false;
}
int vecX = (x - _gestureStartX);
int vecY = (y - _gestureStartY);
int lengthSq = vecX * vecX + vecY * vecY;
//printf("Lengthsq: %u\n", lengthSq);
if (lengthSq > 15000) { // Long enough gesture to react upon.
_gestureStartX = -1;
_gestureStartY = -1;
float vecLength = sqrt(lengthSq);
float vecXNorm = vecX / vecLength;
float vecYNorm = vecY / vecLength;
//printf("Swipe vector: (%.2f, %.2f)\n", vecXNorm, vecYNorm);
if (vecXNorm > -0.50 && vecXNorm < 0.50 && vecYNorm > 0.75) {
// Swipe down
event.type = Common::EVENT_KEYDOWN;
_queuedInputEvent.type = Common::EVENT_KEYUP;
event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_F5;
event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_F5;
_needEventRestPeriod = true;
} else if (vecXNorm > -0.50 && vecXNorm < 0.50 && vecYNorm < -0.75) {
// Swipe up
_mouseClickAndDragEnabled = !_mouseClickAndDragEnabled;
const char *dialogMsg;
if (_mouseClickAndDragEnabled)
dialogMsg = "Mouse-click-and-drag mode enabled.";
else
dialogMsg = "Mouse-click-and-drag mode disabled.";
GUI::TimedMessageDialog dialog(dialogMsg, 1500);
dialog.runModal();
return false;
} else if (vecXNorm > 0.75 && vecYNorm > -0.5 && vecYNorm < 0.5) {
// Swipe right
// _secondaryTapped = !_secondaryTapped;
// _gestureStartX = x;
// _gestureStartY = y;
//
// GUI::TimedMessageDialog dialog("Forcing toggle of pressed state.", 1500);
// dialog.runModal();
return false;
} else if (vecXNorm < -0.75 && vecYNorm > -0.5 && vecYNorm < 0.5) {
// Swipe left
return false;
} else
return false;
} else
return false;
} else {
event.type = Common::EVENT_MOUSEMOVE;
event.mouse.x = x;
event.mouse.y = y;
warpMouse(x, y);
}
if (!handleEvent_mouseDragged(event, x, y))
return false;
break;
case kInputMouseSecondToggled:
_secondaryTapped = !_secondaryTapped;
//printf("Mouse second at (%u, %u). State now %s.\n", x, y, _secondaryTapped ? "on" : "off");
if (_secondaryTapped) {
_lastSecondaryDown = curTime;
_gestureStartX = x;
_gestureStartY = y;
if (_mouseClickAndDragEnabled) {
event.type = Common::EVENT_LBUTTONUP;
event.mouse.x = _mouseX;
event.mouse.y = _mouseY;
_queuedInputEvent.type = Common::EVENT_RBUTTONDOWN;
_queuedInputEvent.mouse.x = _mouseX;
_queuedInputEvent.mouse.y = _mouseY;
}
else
if (!handleEvent_secondMouseDown(event, x, y))
return false;
} else {
if (curTime - _lastSecondaryDown < 250 ) {
if (curTime - _lastSecondaryTap < 250 && !_overlayVisible) {
event.type = Common::EVENT_KEYDOWN;
_queuedInputEvent.type = Common::EVENT_KEYUP;
event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_ESCAPE;
event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_ESCAPE;
_needEventRestPeriod = true;
_lastSecondaryTap = 0;
} else if (!_mouseClickAndDragEnabled) {
event.type = Common::EVENT_RBUTTONDOWN;
event.mouse.x = _mouseX;
event.mouse.y = _mouseY;
_queuedInputEvent.type = Common::EVENT_RBUTTONUP;
_queuedInputEvent.mouse.x = _mouseX;
_queuedInputEvent.mouse.y = _mouseY;
_lastSecondaryTap = curTime;
_needEventRestPeriod = true;
}
}
if (_mouseClickAndDragEnabled) {
event.type = Common::EVENT_RBUTTONUP;
event.mouse.x = _mouseX;
event.mouse.y = _mouseY;
}
}
break;
case kInputOrientationChanged:
//printf("Orientation: %i", (int)xUnit);
ScreenOrientation newOrientation;
switch ((int)xUnit) {
case 1:
newOrientation = kScreenOrientationPortrait;
break;
case 3:
newOrientation = kScreenOrientationLandscape;
break;
case 4:
newOrientation = kScreenOrientationFlippedLandscape;
break;
default:
if (!handleEvent_secondMouseUp(event, x, y))
return false;
}
break;
if (_screenOrientation != newOrientation) {
_screenOrientation = newOrientation;
if (_screenOrientation != kScreenOrientationPortrait)
iPhone_initSurface(_screenHeight, _screenWidth, true);
else
iPhone_initSurface(_screenWidth, _screenHeight, false);
dirtyFullScreen();
updateScreen();
}
case kInputOrientationChanged:
handleEvent_orientationChanged((int)xUnit);
return false;
break;
case kInputApplicationSuspended:
suspendLoop();
return false;
break;
case kInputKeyPressed: {
int keyPressed = (int)xUnit;
int ascii = keyPressed;
//printf("key: %i\n", keyPressed);
// We remap some of the iPhone keyboard keys.
// The first ten here are the row of symbols below the numeric keys.
switch (keyPressed) {
case 45:
keyPressed = Common::KEYCODE_F1;
ascii = Common::ASCII_F1;
break;
case 47:
keyPressed = Common::KEYCODE_F2;
ascii = Common::ASCII_F2;
break;
case 58:
keyPressed = Common::KEYCODE_F3;
ascii = Common::ASCII_F3;
break;
case 59:
keyPressed = Common::KEYCODE_F4;
ascii = Common::ASCII_F4;
break;
case 40:
keyPressed = Common::KEYCODE_F5;
ascii = Common::ASCII_F5;
break;
case 41:
keyPressed = Common::KEYCODE_F6;
ascii = Common::ASCII_F6;
break;
case 36:
keyPressed = Common::KEYCODE_F7;
ascii = Common::ASCII_F7;
break;
case 38:
keyPressed = Common::KEYCODE_F8;
ascii = Common::ASCII_F8;
break;
case 64:
keyPressed = Common::KEYCODE_F9;
ascii = Common::ASCII_F9;
break;
case 34:
keyPressed = Common::KEYCODE_F10;
ascii = Common::ASCII_F10;
break;
case 10:
keyPressed = Common::KEYCODE_RETURN;
ascii = Common::ASCII_RETURN;
break;
}
event.type = Common::EVENT_KEYDOWN;
_queuedInputEvent.type = Common::EVENT_KEYUP;
event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
event.kbd.keycode = _queuedInputEvent.kbd.keycode = (Common::KeyCode)keyPressed;
event.kbd.ascii = _queuedInputEvent.kbd.ascii = ascii;
_needEventRestPeriod = true;
case kInputKeyPressed:
handleEvent_keyPressed(event, (int)xUnit);
break;
}
case kInputSwipe: {
Common::KeyCode keycode = Common::KEYCODE_INVALID;
switch (_screenOrientation) {
case kScreenOrientationPortrait:
switch ((UIViewSwipeDirection)xUnit) {
case kUIViewSwipeUp:
keycode = Common::KEYCODE_UP;
break;
case kUIViewSwipeDown:
keycode = Common::KEYCODE_DOWN;
break;
case kUIViewSwipeLeft:
keycode = Common::KEYCODE_LEFT;
break;
case kUIViewSwipeRight:
keycode = Common::KEYCODE_RIGHT;
break;
default:
return false;
}
break;
case kScreenOrientationLandscape:
switch ((UIViewSwipeDirection)xUnit) {
case kUIViewSwipeUp:
keycode = Common::KEYCODE_LEFT;
break;
case kUIViewSwipeDown:
keycode = Common::KEYCODE_RIGHT;
break;
case kUIViewSwipeLeft:
keycode = Common::KEYCODE_DOWN;
break;
case kUIViewSwipeRight:
keycode = Common::KEYCODE_UP;
break;
default:
return false;
}
break;
case kScreenOrientationFlippedLandscape:
switch ((UIViewSwipeDirection)xUnit) {
case kUIViewSwipeUp:
keycode = Common::KEYCODE_RIGHT;
break;
case kUIViewSwipeDown:
keycode = Common::KEYCODE_LEFT;
break;
case kUIViewSwipeLeft:
keycode = Common::KEYCODE_UP;
break;
case kUIViewSwipeRight:
keycode = Common::KEYCODE_DOWN;
break;
default:
return false;
}
break;
}
event.kbd.keycode = _queuedInputEvent.kbd.keycode = keycode;
event.kbd.ascii = _queuedInputEvent.kbd.ascii = 0;
event.type = Common::EVENT_KEYDOWN;
_queuedInputEvent.type = Common::EVENT_KEYUP;
event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
_needEventRestPeriod = true;
case kInputSwipe:
if (!handleEvent_swipe(event, (int)xUnit))
return false;
break;
}
default:
break;
@ -1014,22 +741,401 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) {
return false;
}
bool OSystem_IPHONE::handleEvent_mouseDown(Common::Event &event, int x, int y) {
printf("Mouse down at (%u, %u)\n", x, y);
// Workaround: kInputMouseSecondToggled isn't always sent when the
// secondary finger is lifted. Need to make sure we get out of that mode.
_secondaryTapped = false;
if (_touchpadModeEnabled) {
_lastPadX = x;
_lastPadY = y;
} else
warpMouse(x, y);
if (_mouseClickAndDragEnabled) {
event.type = Common::EVENT_LBUTTONDOWN;
event.mouse.x = _mouseX;
event.mouse.y = _mouseY;
return true;
} else {
_lastMouseDown = getMillis();
}
return false;
}
bool OSystem_IPHONE::handleEvent_mouseUp(Common::Event &event, int x, int y) {
//printf("Mouse up at (%u, %u)\n", x, y);
if (_secondaryTapped) {
_secondaryTapped = false;
if (!handleEvent_secondMouseUp(event, x, y))
return false;
}
else if (_mouseClickAndDragEnabled) {
event.type = Common::EVENT_LBUTTONUP;
event.mouse.x = _mouseX;
event.mouse.y = _mouseY;
} else {
if (getMillis() - _lastMouseDown < 250) {
event.type = Common::EVENT_LBUTTONDOWN;
event.mouse.x = _mouseX;
event.mouse.y = _mouseY;
_queuedInputEvent.type = Common::EVENT_LBUTTONUP;
_queuedInputEvent.mouse.x = _mouseX;
_queuedInputEvent.mouse.y = _mouseY;
_lastMouseTap = getMillis();
_needEventRestPeriod = true;
} else
return false;
}
return true;
}
bool OSystem_IPHONE::handleEvent_secondMouseDown(Common::Event &event, int x, int y) {
_lastSecondaryDown = getMillis();
_gestureStartX = x;
_gestureStartY = y;
if (_mouseClickAndDragEnabled) {
event.type = Common::EVENT_LBUTTONUP;
event.mouse.x = _mouseX;
event.mouse.y = _mouseY;
_queuedInputEvent.type = Common::EVENT_RBUTTONDOWN;
_queuedInputEvent.mouse.x = _mouseX;
_queuedInputEvent.mouse.y = _mouseY;
}
else
return false;
return true;
}
bool OSystem_IPHONE::handleEvent_secondMouseUp(Common::Event &event, int x, int y) {
int curTime = getMillis();
if (curTime - _lastSecondaryDown < 400 ) {
//printf("Right tap!\n");
if (curTime - _lastSecondaryTap < 400 && !_overlayVisible) {
//printf("Right escape!\n");
event.type = Common::EVENT_KEYDOWN;
_queuedInputEvent.type = Common::EVENT_KEYUP;
event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_ESCAPE;
event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_ESCAPE;
_needEventRestPeriod = true;
_lastSecondaryTap = 0;
} else if (!_mouseClickAndDragEnabled) {
//printf("Rightclick!\n");
event.type = Common::EVENT_RBUTTONDOWN;
event.mouse.x = _mouseX;
event.mouse.y = _mouseY;
_queuedInputEvent.type = Common::EVENT_RBUTTONUP;
_queuedInputEvent.mouse.x = _mouseX;
_queuedInputEvent.mouse.y = _mouseY;
_lastSecondaryTap = curTime;
_needEventRestPeriod = true;
} else {
//printf("Right nothing!\n");
return false;
}
}
if (_mouseClickAndDragEnabled) {
event.type = Common::EVENT_RBUTTONUP;
event.mouse.x = _mouseX;
event.mouse.y = _mouseY;
}
return true;
}
bool OSystem_IPHONE::handleEvent_mouseDragged(Common::Event &event, int x, int y) {
if (_lastDragPosX == x && _lastDragPosY == y)
return false;
_lastDragPosX = x;
_lastDragPosY = y;
//printf("Mouse dragged at (%u, %u)\n", x, y);
if (_secondaryTapped) {
if (_gestureStartX == -1 || _gestureStartY == -1) {
return false;
}
int vecX = (x - _gestureStartX);
int vecY = (y - _gestureStartY);
int lengthSq = vecX * vecX + vecY * vecY;
//printf("Lengthsq: %u\n", lengthSq);
if (lengthSq > 15000) { // Long enough gesture to react upon.
_gestureStartX = -1;
_gestureStartY = -1;
float vecLength = sqrt(lengthSq);
float vecXNorm = vecX / vecLength;
float vecYNorm = vecY / vecLength;
//printf("Swipe vector: (%.2f, %.2f)\n", vecXNorm, vecYNorm);
if (vecXNorm > -0.50 && vecXNorm < 0.50 && vecYNorm > 0.75) {
// Swipe down
event.type = Common::EVENT_KEYDOWN;
_queuedInputEvent.type = Common::EVENT_KEYUP;
event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
event.kbd.keycode = _queuedInputEvent.kbd.keycode = Common::KEYCODE_F5;
event.kbd.ascii = _queuedInputEvent.kbd.ascii = Common::ASCII_F5;
_needEventRestPeriod = true;
} else if (vecXNorm > -0.50 && vecXNorm < 0.50 && vecYNorm < -0.75) {
// Swipe up
_mouseClickAndDragEnabled = !_mouseClickAndDragEnabled;
const char *dialogMsg;
if (_mouseClickAndDragEnabled)
dialogMsg = "Mouse-click-and-drag mode enabled.";
else
dialogMsg = "Mouse-click-and-drag mode disabled.";
GUI::TimedMessageDialog dialog(dialogMsg, 1500);
dialog.runModal();
return false;
} else if (vecXNorm > 0.75 && vecYNorm > -0.5 && vecYNorm < 0.5) {
// Swipe right
_touchpadModeEnabled = !_touchpadModeEnabled;
const char *dialogMsg;
if (_touchpadModeEnabled)
dialogMsg = "Touchpad mode enabled.";
else
dialogMsg = "Touchpad mode disabled.";
GUI::TimedMessageDialog dialog(dialogMsg, 1500);
dialog.runModal();
return false;
} else if (vecXNorm < -0.75 && vecYNorm > -0.5 && vecYNorm < 0.5) {
// Swipe left
return false;
} else
return false;
} else
return false;
} else {
int mouseNewPosX;
int mouseNewPosY;
if (_touchpadModeEnabled ) {
int deltaX = _lastPadX - x;
int deltaY = _lastPadY - y;
_lastPadX = x;
_lastPadY = y;
mouseNewPosX = (int)(_mouseX - deltaX / 0.5f);
mouseNewPosY = (int)(_mouseY - deltaY / 0.5f);
if (mouseNewPosX < 0)
mouseNewPosX = 0;
else if (mouseNewPosX > _screenWidth)
mouseNewPosX = _screenWidth;
if (mouseNewPosY < 0)
mouseNewPosY = 0;
else if (mouseNewPosY > _screenHeight)
mouseNewPosY = _screenHeight;
} else {
mouseNewPosX = x;
mouseNewPosY = y;
}
event.type = Common::EVENT_MOUSEMOVE;
event.mouse.x = mouseNewPosX;
event.mouse.y = mouseNewPosY;
warpMouse(mouseNewPosX, mouseNewPosY);
}
return true;
}
void OSystem_IPHONE::handleEvent_orientationChanged(int orientation) {
//printf("Orientation: %i\n", orientation);
ScreenOrientation newOrientation;
switch (orientation) {
case 1:
newOrientation = kScreenOrientationPortrait;
break;
case 3:
newOrientation = kScreenOrientationLandscape;
break;
case 4:
newOrientation = kScreenOrientationFlippedLandscape;
break;
default:
return;
}
if (_screenOrientation != newOrientation) {
_screenOrientation = newOrientation;
if (_screenOrientation != kScreenOrientationPortrait)
iPhone_initSurface(_screenHeight, _screenWidth, true);
else
iPhone_initSurface(_screenWidth, _screenHeight, false);
dirtyFullScreen();
updateScreen();
}
}
void OSystem_IPHONE::handleEvent_keyPressed(Common::Event &event, int keyPressed) {
int ascii = keyPressed;
//printf("key: %i\n", keyPressed);
// We remap some of the iPhone keyboard keys.
// The first ten here are the row of symbols below the numeric keys.
switch (keyPressed) {
case 45:
keyPressed = Common::KEYCODE_F1;
ascii = Common::ASCII_F1;
break;
case 47:
keyPressed = Common::KEYCODE_F2;
ascii = Common::ASCII_F2;
break;
case 58:
keyPressed = Common::KEYCODE_F3;
ascii = Common::ASCII_F3;
break;
case 59:
keyPressed = Common::KEYCODE_F4;
ascii = Common::ASCII_F4;
break;
case 40:
keyPressed = Common::KEYCODE_F5;
ascii = Common::ASCII_F5;
break;
case 41:
keyPressed = Common::KEYCODE_F6;
ascii = Common::ASCII_F6;
break;
case 36:
keyPressed = Common::KEYCODE_F7;
ascii = Common::ASCII_F7;
break;
case 38:
keyPressed = Common::KEYCODE_F8;
ascii = Common::ASCII_F8;
break;
case 64:
keyPressed = Common::KEYCODE_F9;
ascii = Common::ASCII_F9;
break;
case 34:
keyPressed = Common::KEYCODE_F10;
ascii = Common::ASCII_F10;
break;
case 10:
keyPressed = Common::KEYCODE_RETURN;
ascii = Common::ASCII_RETURN;
break;
}
event.type = Common::EVENT_KEYDOWN;
_queuedInputEvent.type = Common::EVENT_KEYUP;
event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
event.kbd.keycode = _queuedInputEvent.kbd.keycode = (Common::KeyCode)keyPressed;
event.kbd.ascii = _queuedInputEvent.kbd.ascii = ascii;
_needEventRestPeriod = true;
}
bool OSystem_IPHONE::handleEvent_swipe(Common::Event &event, int direction) {
Common::KeyCode keycode = Common::KEYCODE_INVALID;
switch (_screenOrientation) {
case kScreenOrientationPortrait:
switch ((UIViewSwipeDirection)direction) {
case kUIViewSwipeUp:
keycode = Common::KEYCODE_UP;
break;
case kUIViewSwipeDown:
keycode = Common::KEYCODE_DOWN;
break;
case kUIViewSwipeLeft:
keycode = Common::KEYCODE_LEFT;
break;
case kUIViewSwipeRight:
keycode = Common::KEYCODE_RIGHT;
break;
default:
return false;
}
break;
case kScreenOrientationLandscape:
switch ((UIViewSwipeDirection)direction) {
case kUIViewSwipeUp:
keycode = Common::KEYCODE_LEFT;
break;
case kUIViewSwipeDown:
keycode = Common::KEYCODE_RIGHT;
break;
case kUIViewSwipeLeft:
keycode = Common::KEYCODE_DOWN;
break;
case kUIViewSwipeRight:
keycode = Common::KEYCODE_UP;
break;
default:
return false;
}
break;
case kScreenOrientationFlippedLandscape:
switch ((UIViewSwipeDirection)direction) {
case kUIViewSwipeUp:
keycode = Common::KEYCODE_RIGHT;
break;
case kUIViewSwipeDown:
keycode = Common::KEYCODE_LEFT;
break;
case kUIViewSwipeLeft:
keycode = Common::KEYCODE_UP;
break;
case kUIViewSwipeRight:
keycode = Common::KEYCODE_DOWN;
break;
default:
return false;
}
break;
}
event.kbd.keycode = _queuedInputEvent.kbd.keycode = keycode;
event.kbd.ascii = _queuedInputEvent.kbd.ascii = 0;
event.type = Common::EVENT_KEYDOWN;
_queuedInputEvent.type = Common::EVENT_KEYUP;
event.kbd.flags = _queuedInputEvent.kbd.flags = 0;
_needEventRestPeriod = true;
return true;
}
void OSystem_IPHONE::suspendLoop() {
bool done = false;
int eventType;
float xUnit, yUnit;
uint32 startTime = getMillis();
AudioQueueStop(s_AudioQueue.queue, true);
stopSoundsystem();
while (!done) {
if (iPhone_fetchEvent(&eventType, &xUnit, &yUnit))
if ((InputEvent)eventType == kInputApplicationResumed)
done = true;
usleep(100000);
}
startSoundsystem();
AudioQueueStart(s_AudioQueue.queue, NULL);
_timeSuspended += getMillis() - startTime;
}
@ -1107,7 +1213,10 @@ void OSystem_IPHONE::setupMixer() {
s_soundCallback = mixCallback;
s_soundParam = this;
startSoundsystem();
}
void OSystem_IPHONE::startSoundsystem() {
s_AudioQueue.dataFormat.mSampleRate = AUDIO_SAMPLE_RATE;
s_AudioQueue.dataFormat.mFormatID = kAudioFormatLinearPCM;
s_AudioQueue.dataFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
@ -1147,6 +1256,17 @@ void OSystem_IPHONE::setupMixer() {
_mixer->setReady(true);
}
void OSystem_IPHONE::stopSoundsystem() {
AudioQueueStop(s_AudioQueue.queue, true);
for (int i = 0; i < AUDIO_BUFFERS; i++) {
AudioQueueFreeBuffer(s_AudioQueue.queue, s_AudioQueue.buffers[i]);
}
AudioQueueDispose(s_AudioQueue.queue, true);
_mixer->setReady(false);
}
int OSystem_IPHONE::getOutputSampleRate() const {
return AUDIO_SAMPLE_RATE;
}
@ -1196,33 +1316,6 @@ const char* OSystem_IPHONE::getConfigPath() {
return SCUMMVM_PREFS_PATH;
}
const char* OSystem_IPHONE::getSavePath() {
return SCUMMVM_SAVE_PATH;
}
void OSystem_IPHONE::migrateApp() {
// Migrate to the new 1.1.3 directory structure, if needed.
FilesystemNode file("/var/mobile");
if (file.exists() && file.isDirectory()) {
// We have 1.1.3 or above.
s_is113OrHigher = true;
file = FilesystemNode(SCUMMVM_ROOT_PATH);
if (!file.exists()) {
system("mkdir " SCUMMVM_ROOT_PATH);
system("mkdir " SCUMMVM_SAVE_PATH);
// Copy over the prefs file
system("cp " SCUMMVM_OLD_PREFS_PATH " " SCUMMVM_PREFS_PATH);
file = FilesystemNode(SCUMMVM_OLD_SAVE_PATH);
// Copy over old savegames to the new directory.
if (file.exists() && file.isDirectory())
system("cp " SCUMMVM_OLD_SAVE_PATH "/* " SCUMMVM_SAVE_PATH "/");
}
}
}
void iphone_main(int argc, char *argv[]) {
//OSystem_IPHONE::migrateApp();
@ -1243,6 +1336,8 @@ void iphone_main(int argc, char *argv[]) {
system("mkdir " SCUMMVM_ROOT_PATH);
system("mkdir " SCUMMVM_SAVE_PATH);
chdir("/var/mobile/");
g_system = OSystem_IPHONE_create();
assert(g_system);

View file

@ -35,14 +35,12 @@
#include <AudioToolbox/AudioQueue.h>
#define AUDIO_BUFFERS 3
#define WAVE_BUFFER_SIZE 8192
#define WAVE_BUFFER_SIZE 2048
#define AUDIO_SAMPLE_RATE 44100
#define SCUMMVM_ROOT_PATH "/var/mobile/Library/ScummVM"
#define SCUMMVM_SAVE_PATH SCUMMVM_ROOT_PATH "/Savegames"
#define SCUMMVM_OLD_SAVE_PATH "/var/root/.scummvm"
#define SCUMMVM_PREFS_PATH SCUMMVM_ROOT_PATH "/Preferences"
#define SCUMMVM_OLD_PREFS_PATH "/var/root/.scummvmrc"
typedef void (*SoundProc)(void *param, byte *buf, int len);
typedef int (*TimerProc)(int interval);
@ -61,7 +59,6 @@ protected:
static AQCallbackStruct s_AudioQueue;
static SoundProc s_soundCallback;
static void *s_soundParam;
static bool s_is113OrHigher;
Common::SaveFileManager *_savefile;
Audio::MixerImpl *_mixer;
@ -97,6 +94,11 @@ protected:
long _lastSecondaryTap;
int _gestureStartX, _gestureStartY;
bool _mouseClickAndDragEnabled;
bool _touchpadModeEnabled;
int _lastPadX;
int _lastPadY;
int _lastDragPosX;
int _lastDragPosY;
int _timerCallbackNext;
int _timerCallbackTimer;
@ -106,6 +108,8 @@ protected:
ScreenOrientation _screenOrientation;
bool _fullScreenIsDirty;
FilesystemFactory *_fsFactory;
public:
OSystem_IPHONE();
@ -161,7 +165,7 @@ public:
virtual void quit();
FilesystemFactory *getFilesystemFactory() { return &POSIXFilesystemFactory::instance(); }
FilesystemFactory *getFilesystemFactory() { return _fsFactory; }
virtual void getTimeAndDate(struct tm &t) const;
virtual void setWindowCaption(const char *caption);
@ -170,9 +174,10 @@ public:
virtual Audio::Mixer *getMixer();
virtual Common::TimerManager *getTimerManager();
static void migrateApp();
void startSoundsystem();
void stopSoundsystem();
static const char* getConfigPath();
static const char* getSavePath();
protected:
inline void addDirtyRect(int16 x1, int16 y1, int16 w, int16 h);
@ -183,6 +188,18 @@ protected:
void suspendLoop();
static void AQBufferCallback(void *in, AudioQueueRef inQ, AudioQueueBufferRef outQB);
static int timerHandler(int t);
bool handleEvent_swipe(Common::Event &event, int direction);
void handleEvent_keyPressed(Common::Event &event, int keyPressed);
void handleEvent_orientationChanged(int orientation);
bool handleEvent_mouseDown(Common::Event &event, int x, int y);
bool handleEvent_mouseUp(Common::Event &event, int x, int y);
bool handleEvent_secondMouseDown(Common::Event &event, int x, int y);
bool handleEvent_secondMouseUp(Common::Event &event, int x, int y);
bool handleEvent_mouseDragged(Common::Event &event, int x, int y);
};
#endif

View file

@ -50,13 +50,12 @@
#include "backends/fs/windows/windows-fs-factory.h"
#endif
class OSystem_NULL : public OSystem {
protected:
Common::SaveFileManager *_savefile;
Audio::MixerImpl *_mixer;
Common::TimerManager *_timer;
FilesystemFactory *_fsFactory;
timeval _startTime;
public:
@ -133,12 +132,23 @@ OSystem_NULL::OSystem_NULL() {
_savefile = 0;
_mixer = 0;
_timer = 0;
#if defined(__amigaos4__)
_fsFactory = new AmigaOSFilesystemFactory();
#elif defined(UNIX)
_fsFactory = new POSIXFilesystemFactory();
#elif defined(WIN32)
_fsFactory = new WindowsFilesystemFactory();
#else
#error Unknown and unsupported FS backend
#endif
}
OSystem_NULL::~OSystem_NULL() {
delete _savefile;
delete _mixer;
delete _timer;
delete _fsFactory;
}
void OSystem_NULL::initBackend() {
@ -194,11 +204,11 @@ void OSystem_NULL::initSize(uint width, uint height) {
}
int16 OSystem_NULL::getHeight() {
return 320;
return 200;
}
int16 OSystem_NULL::getWidth() {
return 200;
return 320;
}
void OSystem_NULL::setPalette(const byte *colors, uint start, uint num) {
@ -327,18 +337,9 @@ void OSystem_NULL::getTimeAndDate(struct tm &t) const {
}
FilesystemFactory *OSystem_NULL::getFilesystemFactory() {
#if defined(__amigaos4__)
return &AmigaOSFilesystemFactory::instance();
#elif defined(UNIX)
return &POSIXFilesystemFactory::instance();
#elif defined(WIN32)
return &WindowsFilesystemFactory::instance();
#else
#error Unknown and unsupported backend in OSystem_NULL::getFilesystemFactory
#endif
return _fsFactory;
}
OSystem *OSystem_NULL_create() {
return new OSystem_NULL();
}

View file

@ -31,6 +31,7 @@ RawReadFile::RawReadFile(McAccess *mcAccess) {
_size = -1;
_pos = 0;
_buf = NULL;
_eof = false;
}
RawReadFile::~RawReadFile(void) {
@ -79,12 +80,16 @@ int RawReadFile::bufSeek(int ofs, int whence) {
_pos = 0;
else if (_pos > _size)
_pos = _size;
_eof = false;
return _pos;
}
int RawReadFile::bufRead(void *dest, int size) {
if (_pos + size > _size)
if (_pos + size > _size) {
size = _size - _pos;
_eof = true;
}
memcpy(dest, _buf + _pos, size);
_pos += size;
return size;
@ -94,7 +99,13 @@ int RawReadFile::bufSize(void) const {
return _size;
}
bool RawReadFile::bufEof(void) const {
return _eof;
}
void RawReadFile::bufClearErr(void) const {
_eof = false;
}
RawWriteFile::RawWriteFile(McAccess *mcAccess) {
_mcAccess = mcAccess;

View file

@ -40,11 +40,14 @@ public:
int bufTell(void) const;
int bufSeek(int ofs, int whence);
int bufSize(void) const;
bool bufEof(void) const;
void bufClearErr(void);
protected:
McAccess *_mcAccess;
int _size;
uint8 *_buf;
int _pos;
bool _eof;
};
class RawWriteFile {

View file

@ -71,7 +71,7 @@ uint32 AutoSaveFile::write(const void *ptr, uint32 size) {
UclInSaveFile::UclInSaveFile(const char *filename, Gs2dScreen *screen, McAccess *mcAccess) : RawReadFile(mcAccess) {
_screen = screen;
_ioFailed = true;
_err = true;
if (bufOpen(filename)) {
if ((_size > 8) && (*(uint32 *)_buf == UCL_MAGIC)) {
@ -82,13 +82,13 @@ UclInSaveFile::UclInSaveFile(const char *filename, Gs2dScreen *screen, McAccess
free(_buf);
_buf = decBuf;
_size = resSize;
_ioFailed = false;
_err = false;
_pos = 0;
} else
free(decBuf);
}
}
if (_ioFailed) {
if (_err) {
if (_buf)
free(_buf);
_buf = NULL;
@ -100,36 +100,39 @@ UclInSaveFile::~UclInSaveFile(void) {
_screen->wantAnim(false);
}
bool UclInSaveFile::ioFailed(void) const {
return _ioFailed;
bool UclInSaveFile::err(void) const {
return _err;
}
void UclInSaveFile::clearIOFailed(void) {
_ioFailed = false;
void UclInSaveFile::clearErr(void) {
_err = false;
bufClearErr();
}
bool UclInSaveFile::eos(void) const {
return bufTell() == bufSize();
return bufEof();
}
uint32 UclInSaveFile::pos(void) const {
int32 UclInSaveFile::pos(void) const {
return bufTell();
}
uint32 UclInSaveFile::size(void) const {
int32 UclInSaveFile::size(void) const {
return bufSize();
}
void UclInSaveFile::seek(int pos, int whence) {
bool UclInSaveFile::seek(int pos, int whence) {
bufSeek(pos, whence);
return true;
}
uint32 UclInSaveFile::read(void *ptr, uint32 size) {
return (uint32)bufRead(ptr, (int)size);
}
void UclInSaveFile::skip(uint32 offset) {
bool UclInSaveFile::skip(uint32 offset) {
bufSeek(offset, SEEK_CUR);
return true;
}
UclOutSaveFile::UclOutSaveFile(const char *filename, OSystem_PS2 *system, Gs2dScreen *screen, McAccess *mc) : RawWriteFile(mc) {
@ -137,7 +140,7 @@ UclOutSaveFile::UclOutSaveFile(const char *filename, OSystem_PS2 *system, Gs2dSc
_system = system;
strcpy(_fileName, filename);
_ioFailed = !bufOpen(filename);
_err = !bufOpen(filename);
_wasFlushed = false;
}
@ -146,7 +149,7 @@ UclOutSaveFile::~UclOutSaveFile(void) {
if (_pos != 0) {
printf("Engine didn't call SaveFile::flush()\n");
flush();
if (ioFailed()) {
if (err()) {
// unable to save to memory card and it's too late to return an error code to the engine
_system->msgPrintf(5000, "!WARNING!\nCan't write to memory card.\nGame was NOT saved.");
printf("~UclOutSaveFile: Flush failed!\n");
@ -160,20 +163,20 @@ uint32 UclOutSaveFile::write(const void *ptr, uint32 size) {
return size;
}
bool UclOutSaveFile::ioFailed(void) const {
return _ioFailed;
bool UclOutSaveFile::err(void) const {
return _err;
}
void UclOutSaveFile::clearIOFailed(void) {
_ioFailed = false;
void UclOutSaveFile::clearErr(void) {
_err = false;
}
void UclOutSaveFile::flush(void) {
bool UclOutSaveFile::flush(void) {
if (_pos != 0) {
if (_wasFlushed) {
printf("Multiple calls to UclOutSaveFile::flush!\n");
_ioFailed = true;
return;
_err = true;
return false;
}
uint32 compSize = _pos * 2;
uint8 *compBuf = (uint8*)memalign(64, compSize + 8);
@ -188,11 +191,12 @@ void UclOutSaveFile::flush(void) {
_pos = compSize + 8;
if (!bufFlush()) {
printf("UclOutSaveFile::flush failed!\n");
_ioFailed = true;
_err = true;
removeFile();
}
_wasFlushed = true;
}
return true;
}
/* ----------------------------------------- Glue Classes for POSIX Memory Card Access ----------------------------------------- */
@ -216,11 +220,11 @@ uint32 Ps2McReadFile::write(const void *src, uint32 len) {
return 0;
}
uint32 Ps2McReadFile::tell(void) {
int32 Ps2McReadFile::tell(void) {
return bufTell();
}
uint32 Ps2McReadFile::size(void) {
int32 Ps2McReadFile::size(void) {
return bufSize();
}
@ -253,11 +257,11 @@ uint32 Ps2McWriteFile::write(const void *src, uint32 len) {
return len;
}
uint32 Ps2McWriteFile::tell(void) {
int32 Ps2McWriteFile::tell(void) {
return bufTell();
}
uint32 Ps2McWriteFile::size(void) {
int32 Ps2McWriteFile::size(void) {
return bufTell();
}
@ -267,6 +271,3 @@ int Ps2McWriteFile::seek(int32 offset, int origin) {
return 0;
}
bool Ps2McWriteFile::eof(void) {
return true;
}

View file

@ -41,14 +41,14 @@ public:
UclOutSaveFile(const char *filename, OSystem_PS2 *system, Gs2dScreen *screen, McAccess *mc);
virtual ~UclOutSaveFile(void);
virtual uint32 write(const void *ptr, uint32 size);
virtual void flush(void);
virtual bool ioFailed(void) const;
virtual void clearIOFailed(void);
virtual bool flush(void);
virtual bool err(void) const;
virtual void clearErr(void);
private:
OSystem_PS2 *_system;
Gs2dScreen *_screen;
bool _ioFailed, _wasFlushed;
bool _err, _wasFlushed;
char _fileName[128];
};
@ -58,16 +58,16 @@ public:
virtual ~UclInSaveFile(void);
virtual bool eos(void) const;
virtual uint32 read(void *ptr, uint32 size);
virtual bool ioFailed(void) const;
virtual void clearIOFailed(void);
virtual void skip(uint32 offset);
virtual bool err(void) const;
virtual void clearErr(void);
virtual bool skip(uint32 offset);
virtual uint32 pos(void) const;
virtual uint32 size(void) const;
virtual void seek(int pos, int whence = SEEK_SET);
virtual int32 pos(void) const;
virtual int32 size(void) const;
virtual bool seek(int pos, int whence = SEEK_SET);
private:
Gs2dScreen *_screen;
bool _ioFailed;
bool _err;
};
class AutoSaveFile : public Common::OutSaveFile {
@ -75,9 +75,9 @@ public:
AutoSaveFile(Ps2SaveFileManager *saveMan, const char *filename);
~AutoSaveFile(void);
virtual uint32 write(const void *ptr, uint32 size);
virtual void flush(void) {}
virtual bool ioFailed(void) { return false; };
virtual void clearIOFailed(void) {}
virtual bool flush(void) {}
virtual bool err(void) const { return false; }
virtual void clearErr(void) {}
private:
Ps2SaveFileManager *_saveMan;
char _fileName[256];
@ -95,8 +95,8 @@ public:
virtual bool open(const char *name);
virtual uint32 read(void *dest, uint32 len);
virtual uint32 write(const void *src, uint32 len);
virtual uint32 tell(void);
virtual uint32 size(void);
virtual int32 tell(void);
virtual int32 size(void);
virtual int seek(int32 offset, int origin);
virtual bool eof(void);
};
@ -108,10 +108,9 @@ public:
virtual bool open(const char *name);
virtual uint32 read(void *dest, uint32 len);
virtual uint32 write(const void *src, uint32 len);
virtual uint32 tell(void);
virtual uint32 size(void);
virtual int32 tell(void);
virtual int32 size(void);
virtual int seek(int32 offset, int origin);
virtual bool eof(void);
};
#endif // __PS2_SAVEFILE__

View file

@ -98,7 +98,20 @@ OSystem_PSP::~OSystem_PSP() {
void OSystem_PSP::initBackend() {
_savefile = new DefaultSaveFileManager();
_savefile = new DefaultSaveFileManager("ms0:/scummvm_savegames");
const char *savePath = _savefile->getSavePath().c_str();
//check if the save directory exists
SceUID fd = sceIoDopen(savePath);
if (fd < 0) {
//No? then let's create it.
sceIoMkdir(savePath, 0777);
} else {
//it exists, so close it again.
sceIoDclose(fd);
}
_timer = new DefaultTimerManager();
setTimerCallback(&timer_handler, 10);

View file

@ -94,19 +94,23 @@ OSystem_PSP_GU::OSystem_PSP_GU() {
//decompress keyboard data
uLongf kbdSize = KBD_DATA_SIZE;
keyboard_letters = (unsigned char *)memalign(16, KBD_DATA_SIZE);
assert(Z_OK == uncompress((Bytef *)keyboard_letters, &kbdSize, (const Bytef *)keyboard_letters_compressed, size_keyboard_letters_compressed));
if (!uncompress((Bytef *)keyboard_letters, &kbdSize, (const Bytef *)keyboard_letters_compressed, size_keyboard_letters_compressed))
error("OSystem_PSP_GU: uncompressing keyboard_letters failed");
kbdSize = KBD_DATA_SIZE;
keyboard_letters_shift = (unsigned char *)memalign(16, KBD_DATA_SIZE);
assert(Z_OK == uncompress((Bytef *)keyboard_letters_shift, &kbdSize, (const Bytef *)keyboard_letters_shift_compressed, size_keyboard_letters_shift_compressed));
if (!uncompress((Bytef *)keyboard_letters_shift, &kbdSize, (const Bytef *)keyboard_letters_shift_compressed, size_keyboard_letters_shift_compressed))
error("OSystem_PSP_GU: uncompressing keyboard_letters_shift failed");
kbdSize = KBD_DATA_SIZE;
keyboard_symbols = (unsigned char *)memalign(16, KBD_DATA_SIZE);
assert(Z_OK == uncompress((Bytef *)keyboard_symbols, &kbdSize, (const Bytef *)keyboard_symbols_compressed, size_keyboard_symbols_compressed));
if (!uncompress((Bytef *)keyboard_symbols, &kbdSize, (const Bytef *)keyboard_symbols_compressed, size_keyboard_symbols_compressed))
error("OSystem_PSP_GU: uncompressing keyboard_symbols failed");
kbdSize = KBD_DATA_SIZE;
keyboard_symbols_shift = (unsigned char *)memalign(16, KBD_DATA_SIZE);
assert(Z_OK == uncompress((Bytef *)keyboard_symbols_shift, &kbdSize, (const Bytef *)keyboard_symbols_shift_compressed, size_keyboard_symbols_shift_compressed));
if (!uncompress((Bytef *)keyboard_symbols_shift, &kbdSize, (const Bytef *)keyboard_symbols_shift_compressed, size_keyboard_symbols_shift_compressed))
error("OSystem_PSP_GU: uncompressing keyboard_symbols_shift failed");
_keyboardVisible = false;
_clut = (unsigned short*)(((unsigned int)clut256)|0x40000000);

View file

@ -43,7 +43,6 @@
#include "trace.h"
#define SCUMMVM_SAVEPATH "ms0:/scummvm_savegames"
#define BREAKPOINT asm("break\n")

View file

@ -122,16 +122,6 @@ int main(void)
{
SetupCallbacks();
//check if the save directory exists
SceUID fd = sceIoDopen(SCUMMVM_SAVEPATH);
if (fd < 0) {
//No? then let's create it.
sceIoMkdir(SCUMMVM_SAVEPATH, 0777);
} else {
//it exists, so close it again.
sceIoDclose(fd);
}
static char *argv[] = { "scummvm", NULL };
static int argc = sizeof(argv)/sizeof(char *)-1;

View file

@ -196,7 +196,9 @@ bool OSystem_SDL::pollEvent(Common::Event &event) {
// Alt-Return and Alt-Enter toggle full screen mode
if (b == Common::KBD_ALT && (ev.key.keysym.sym == SDLK_RETURN
|| ev.key.keysym.sym == SDLK_KP_ENTER)) {
beginGFXTransaction();
setFullscreenMode(!_fullscreen);
endGFXTransaction();
#ifdef USE_OSD
if (_fullscreen)
displayMessageOnOSD("Fullscreen mode");

View file

@ -691,20 +691,14 @@ bool OSystem_SDL::saveScreenshot(const char *filename) {
void OSystem_SDL::setFullscreenMode(bool enable) {
Common::StackLock lock(_graphicsMutex);
if (_fullscreen == enable)
return;
if (_fullscreen != enable || _transactionMode == kTransactionCommit) {
if (_transactionMode == kTransactionCommit) {
assert(_hwscreen != 0);
_fullscreen = enable;
if (_transactionMode == kTransactionActive) {
_transactionDetails.fs = enable;
_transactionDetails.fsChanged = true;
_transactionDetails.needHotswap = true;
return;
}
// Switch between fullscreen and windowed mode by invoking hotswapGFXMode().
// We used to use SDL_WM_ToggleFullScreen() in the past, but this caused various
// problems. E.g. on OS X, it was implemented incorrectly for a long time; on
@ -713,6 +707,11 @@ void OSystem_SDL::setFullscreenMode(bool enable) {
// So, we just do it "manually" now. There shouldn't be any drawbacks to that
// anyway.
hotswapGFXMode();
} else if (_transactionMode == kTransactionActive) {
_transactionDetails.fs = enable;
_transactionDetails.fsChanged = true;
_transactionDetails.needHotswap = true;
}
}

View file

@ -23,7 +23,16 @@
*
*/
#if defined(WIN32)
#include <windows.h>
#if defined(ARRAYSIZE)
// winnt.h defines ARRAYSIZE, but we want our own one... - this is needed before including util.h
#undef ARRAYSIZE
#endif
#endif
#include "backends/platform/sdl/sdl.h"
#include "common/archive.h"
#include "common/config-manager.h"
#include "common/events.h"
#include "common/util.h"
@ -40,6 +49,7 @@
#define SAMPLES_PER_SEC 22050
//#define SAMPLES_PER_SEC 44100
/*
* Include header files needed for the getFilesystemFactory() method.
*/
@ -52,6 +62,21 @@
#endif
#if defined(UNIX)
#ifdef MACOSX
#define DEFAULT_CONFIG_FILE "Library/Preferences/ScummVM Preferences"
#else
#define DEFAULT_CONFIG_FILE ".scummvmrc"
#endif
#else
#define DEFAULT_CONFIG_FILE "scummvm.ini"
#endif
#if defined(MACOSX) || defined(IPHONE)
#include "CoreFoundation/CoreFoundation.h"
#endif
static Uint32 timer_handler(Uint32 interval, void *param) {
((DefaultTimerManager *)param)->handler();
return interval;
@ -179,6 +204,7 @@ OSystem_SDL::OSystem_SDL()
_soundMutex(0), _soundCond(0), _soundThread(0),
_soundThreadIsRunning(false), _soundThreadShouldQuit(false),
#endif
_fsFactory(0),
_savefile(0),
_mixer(0),
_timer(0),
@ -196,6 +222,19 @@ OSystem_SDL::OSystem_SDL()
memset(&_mouseCurState, 0, sizeof(_mouseCurState));
_inited = false;
#if defined(__amigaos4__)
_fsFactory = new AmigaOSFilesystemFactory();
#elif defined(UNIX)
_fsFactory = new POSIXFilesystemFactory();
#elif defined(WIN32)
_fsFactory = new WindowsFilesystemFactory();
#elif defined(__SYMBIAN32__)
// Do nothing since its handled by the Symbian SDL inheritance
#else
#error Unknown and unsupported FS backend
#endif
}
OSystem_SDL::~OSystem_SDL() {
@ -237,17 +276,115 @@ Common::SaveFileManager *OSystem_SDL::getSavefileManager() {
}
FilesystemFactory *OSystem_SDL::getFilesystemFactory() {
#if defined(__amigaos4__)
return &AmigaOSFilesystemFactory::instance();
#elif defined(UNIX)
return &POSIXFilesystemFactory::instance();
#elif defined(WIN32)
return &WindowsFilesystemFactory::instance();
#elif defined(__SYMBIAN32__)
// Do nothing since its handled by the Symbian SDL inheritance
#else
#error Unknown and unsupported backend in OSystem_SDL::getFilesystemFactory
#endif
assert(_fsFactory);
return _fsFactory;
}
void OSystem_SDL::addSysArchivesToSearchSet(Common::SearchSet &s, uint priority) {
#ifdef DATA_PATH
// Add the global DATA_PATH to the directory search list
// FIXME: We use depth = 4 for now, to match the old code. May want to change that
Common::FilesystemNode dataNode(DATA_PATH);
if (dataNode.exists() && dataNode.isDirectory()) {
Common::ArchivePtr dataArchive(new Common::FSDirectory(dataNode, 4));
s.add(DATA_PATH, dataArchive, priority);
}
#endif
#if defined(MACOSX) || defined(IPHONE)
// Get URL of the Resource directory of the .app bundle
CFURLRef fileUrl = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle());
if (fileUrl) {
// Try to convert the URL to an absolute path
UInt8 buf[MAXPATHLEN];
if (CFURLGetFileSystemRepresentation(fileUrl, true, buf, sizeof(buf))) {
// Success: Add it to the search path
Common::String bundlePath((const char *)buf);
Common::ArchivePtr bundleArchive(new Common::FSDirectory(bundlePath));
s.add("__OSX_BUNDLE__", bundleArchive, priority);
}
CFRelease(fileUrl);
}
#endif
}
static Common::String getDefaultConfigFileName() {
char configFile[MAXPATHLEN];
#if defined (WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__)
OSVERSIONINFO win32OsVersion;
ZeroMemory(&win32OsVersion, sizeof(OSVERSIONINFO));
win32OsVersion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx(&win32OsVersion);
// Check for non-9X version of Windows.
if (win32OsVersion.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS) {
// Use the Application Data directory of the user profile.
if (win32OsVersion.dwMajorVersion >= 5) {
if (!GetEnvironmentVariable("APPDATA", configFile, sizeof(configFile)))
error("Unable to access application data directory");
} else {
if (!GetEnvironmentVariable("USERPROFILE", configFile, sizeof(configFile)))
error("Unable to access user profile directory");
strcat(configFile, "\\Application Data");
CreateDirectory(configFile, NULL);
}
strcat(configFile, "\\ScummVM");
CreateDirectory(configFile, NULL);
strcat(configFile, "\\" DEFAULT_CONFIG_FILE);
FILE *tmp = NULL;
if ((tmp = fopen(configFile, "r")) == NULL) {
// Check windows directory
char oldConfigFile[MAXPATHLEN];
GetWindowsDirectory(oldConfigFile, MAXPATHLEN);
strcat(oldConfigFile, "\\" DEFAULT_CONFIG_FILE);
if ((tmp = fopen(oldConfigFile, "r"))) {
strcpy(configFile, oldConfigFile);
fclose(tmp);
}
} else {
fclose(tmp);
}
} else {
// Check windows directory
GetWindowsDirectory(configFile, MAXPATHLEN);
strcat(configFile, "\\" DEFAULT_CONFIG_FILE);
}
#elif defined(UNIX)
// On UNIX type systems, by default we store the config file inside
// to the HOME directory of the user.
//
// GP2X is Linux based but Home dir can be read only so do not use
// it and put the config in the executable dir.
//
// On the iPhone, the home dir of the user when you launch the app
// from the Springboard, is /. Which we don't want.
const char *home = getenv("HOME");
if (home != NULL && strlen(home) < MAXPATHLEN)
snprintf(configFile, MAXPATHLEN, "%s/%s", home, DEFAULT_CONFIG_FILE);
else
strcpy(configFile, DEFAULT_CONFIG_FILE);
#else
strcpy(configFile, DEFAULT_CONFIG_FILE);
#endif
return configFile;
}
Common::SeekableReadStream *OSystem_SDL::openConfigFileForReading() {
Common::FilesystemNode file(getDefaultConfigFileName());
return file.openForReading();
}
Common::WriteStream *OSystem_SDL::openConfigFileForWriting() {
Common::FilesystemNode file(getDefaultConfigFileName());
return file.openForWriting();
}
void OSystem_SDL::setWindowCaption(const char *caption) {
@ -332,15 +469,21 @@ void OSystem_SDL::quit() {
}
void OSystem_SDL::setupIcon() {
int w, h, ncols, nbytes, i;
unsigned int rgba[256], icon[32 * 32];
unsigned char mask[32][4];
int x, y, w, h, ncols, nbytes, i;
unsigned int rgba[256];
unsigned int *icon;
sscanf(scummvm_icon[0], "%d %d %d %d", &w, &h, &ncols, &nbytes);
if ((w != 32) || (h != 32) || (ncols > 255) || (nbytes > 1)) {
warning("Could not load the icon (%d %d %d %d)", w, h, ncols, nbytes);
if ((w > 512) || (h > 512) || (ncols > 255) || (nbytes > 1)) {
warning("Could not load the built-in icon (%d %d %d %d)", w, h, ncols, nbytes);
return;
}
icon = (unsigned int*)malloc(w*h*sizeof(unsigned int));
if (!icon) {
warning("Could not allocate temp storage for the built-in icon");
return;
}
for (i = 0; i < ncols; i++) {
unsigned char code;
char color[32];
@ -354,26 +497,27 @@ void OSystem_SDL::setupIcon() {
sscanf(color + 1, "%06x", &col);
col |= 0xFF000000;
} else {
warning("Could not load the icon (%d %s - %s) ", code, color, scummvm_icon[1 + i]);
warning("Could not load the built-in icon (%d %s - %s) ", code, color, scummvm_icon[1 + i]);
free(icon);
return;
}
rgba[code] = col;
}
memset(mask, 0, sizeof(mask));
for (h = 0; h < 32; h++) {
const char *line = scummvm_icon[1 + ncols + h];
for (w = 0; w < 32; w++) {
icon[w + 32 * h] = rgba[(int)line[w]];
if (rgba[(int)line[w]] & 0xFF000000) {
mask[h][w >> 3] |= 1 << (7 - (w & 0x07));
}
for (y = 0; y < h; y++) {
const char *line = scummvm_icon[1 + ncols + y];
for (x = 0; x < w; x++) {
icon[x + w * y] = rgba[(int)line[x]];
}
}
SDL_Surface *sdl_surf = SDL_CreateRGBSurfaceFrom(icon, 32, 32, 32, 32 * 4, 0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000);
SDL_WM_SetIcon(sdl_surf, (unsigned char *) mask);
SDL_Surface *sdl_surf = SDL_CreateRGBSurfaceFrom(icon, w, h, 32, w * 4, 0xFF0000, 0x00FF00, 0x0000FF, 0xFF000000);
if (!sdl_surf) {
warning("SDL_CreateRGBSurfaceFrom(icon) failed");
}
SDL_WM_SetIcon(sdl_surf, NULL);
SDL_FreeSurface(sdl_surf);
free(icon);
}
OSystem::MutexRef OSystem_SDL::createMutex(void) {
@ -412,7 +556,7 @@ void OSystem_SDL::mixerProducerThread() {
// Generate samples and put them into the next buffer
nextSoundBuffer = _activeSoundBuf ^ 1;
_mixer->mixCallback(_soundBuffers[nextSoundBuffer], _soundBufSize);
// Swap buffers
_activeSoundBuf = nextSoundBuffer;
}
@ -456,7 +600,7 @@ void OSystem_SDL::deinitThreadedMixer() {
SDL_CondBroadcast(_soundCond);
SDL_WaitThread(_soundThread, NULL);
// Kill the mutex & cond variables.
// Kill the mutex & cond variables.
// Attention: AT this point, the mixer callback must not be running
// anymore, else we will crash!
SDL_DestroyMutex(_soundMutex);
@ -479,10 +623,10 @@ void OSystem_SDL::mixCallback(void *arg, byte *samples, int len) {
// Lock mutex, to ensure our data is not overwritten by the producer thread
SDL_LockMutex(this_->_soundMutex);
// Copy data from the current sound buffer
memcpy(samples, this_->_soundBuffers[this_->_activeSoundBuf], len);
// Unlock mutex and wake up the produced thread
SDL_UnlockMutex(this_->_soundMutex);
SDL_CondSignal(this_->_soundCond);
@ -542,7 +686,7 @@ void OSystem_SDL::setupMixer() {
// even if it didn't. Probably only happens for "weird" rates, though.
_samplesPerSec = obtained.freq;
debug(1, "Output sample rate: %d Hz", _samplesPerSec);
// Tell the mixer that we are ready and start the sound processing
_mixer->setOutputRate(_samplesPerSec);
_mixer->setReady(true);

View file

@ -212,6 +212,10 @@ public:
virtual Common::SaveFileManager *getSavefileManager();
virtual FilesystemFactory *getFilesystemFactory();
virtual void addSysArchivesToSearchSet(Common::SearchSet &s, uint priority = 0);
virtual Common::SeekableReadStream *openConfigFileForReading();
virtual Common::WriteStream *openConfigFileForWriting();
protected:
bool _inited;
@ -400,14 +404,13 @@ protected:
void deinitThreadedMixer();
#endif
FilesystemFactory *_fsFactory;
Common::SaveFileManager *_savefile;
Audio::MixerImpl *_mixer;
SDL_TimerID _timerID;
Common::TimerManager *_timer;
protected:
void addDirtyRgnAuto(const byte *buf);
void makeChecksums(const byte *buf);

View file

@ -27,7 +27,7 @@ chdir("../../../");
"mmp/scummvm_sword1.mmp",
"mmp/scummvm_sword2.mmp",
"mmp/scummvm_touche.mmp",
"mmp/scummvm_tinsel.mmp",
# Target Platform Project Files
"S60/ScummVM_S60.mmp",
@ -83,6 +83,9 @@ my @excludes_graphics = (
"iff.cpp"
);
my @excludes_gui = (
);
# the USE_ARM_* defines not parsed correctly, exclude manually:
my @excludes_scumm = (
".*ARM.*", # the *ARM.s files are added in .mpp files based on WINS/ARM build!
@ -95,7 +98,7 @@ my @excludes_scumm = (
#arseModule(mmpStr, dirStr, ifdefArray, [exclusionsArray])
ParseModule("_base", "base", \@section_empty); # now in ./TRG/ScummVM_TRG.mmp, these never change anyways...
ParseModule("_base", "common", \@section_empty);
ParseModule("_base", "gui", \@section_empty);
ParseModule("_base", "gui", \@section_empty, \@excludes_gui);
ParseModule("_base", "graphics", \@section_empty, \@excludes_graphics);
ParseModule("_base", "sound", \@section_empty, \@excludes_snd);
@ -103,22 +106,23 @@ chdir("engines/");
ParseModule("_scumm", "scumm", \@sections_scumm, \@excludes_scumm );
ParseModule("_queen", "queen", \@section_empty);
ParseModule("_agos", "agos", \@section_empty);
ParseModule("_sky", "sky", \@section_empty);
ParseModule("_gob", "gob", \@section_empty);
ParseModule("_sky", "sky", \@section_empty);
ParseModule("_gob", "gob", \@section_empty);
ParseModule("_saga", "saga", \@section_empty);
ParseModule("_kyra", "kyra", \@section_empty);
ParseModule("_sword1", "sword1", \@section_empty);
ParseModule("_sword2", "sword2", \@section_empty);
ParseModule("_lure", "lure", \@section_empty);
ParseModule("_cine", "cine", \@section_empty);
ParseModule("_agi", "agi", \@section_empty);
ParseModule("_agi", "agi", \@section_empty);
ParseModule("_touche", "touche", \@section_empty);
ParseModule("_parallaction","parallaction",\@section_empty);
ParseModule("_cruise", "cruise", \@section_empty);
ParseModule("_drascula","drascula", \@section_empty);
ParseModule("_igor", "igor", \@section_empty);
ParseModule("_made", "made", \@section_empty);
ParseModule("_m4", "m4", \@section_empty);
ParseModule("_m4", "m4", \@section_empty);
ParseModule("_tinsel", "tinsel", \@section_empty);
print "
=======================================================================================
Done. Enjoy :P

View file

@ -443,6 +443,10 @@ my $header = "
PrintMessage("Cleaning for $Target") if (!$ReallyQuiet);
system("bldmake bldfiles > NUL 2> NUL");
PrintErrorMessage("'bldmake bldfiles' exited with value " . ($? >> 8)) if ($? >> 8);
system("abld MAKEFILE $TargetName > NUL 2> NUL");
PrintErrorMessage("'abld MAKEFILE $TargetName' exited with value " . ($? >> 8)) if ($? >> 8);
system("abld CLEAN $TargetName UREL > NUL 2> NUL");
PrintErrorMessage("'abld CLEAN $TargetName urel' exited with value " . ($? >> 8)) if ($? >> 8);
# remove file so we are sure that after .lib generation we have a fresh copy!
@ -455,10 +459,10 @@ my $header = "
my $OldSize = (-s $build_log_err);
$Redirection = ($RedirectSTDERR ? "2>> $build_log_err" : "");
system("abld BUILD $TargetName UREL $Redirection >> $build_log_out");
system("abld TARGET $TargetName UREL $Redirection >> $build_log_out");
$OK = 0 if ($? >> 8);
# print " STDERR: ".((-s $build_log_err)-$OldSize)." bytes output written to $build_log_err\n+--------------------------------------------------------------------------------------\n" if ($OldSize != (-s $build_log_err));
PrintErrorMessage("'abld BUILD $TargetName UREL' exited with value " . ($? >> 8)) if ($? >> 8);
PrintErrorMessage("'abld TARGET $TargetName UREL' exited with value " . ($? >> 8)) if ($? >> 8);
return 0 if (!$OK); # ABLD always returns ok :( grr
PrintMessage("Done.") if (!$ReallyQuiet);
@ -475,7 +479,7 @@ my $header = "
}
else
{
PrintErrorMessage("'abld BUILD $TargetName UREL' apparently failed.");
PrintErrorMessage("'abld TARGET $TargetName UREL' apparently failed.");
if ($HaltOnError)
{
PrintErrorMessage("Halting on error as requested!");

View file

@ -2,16 +2,16 @@
##################################################################################################################
@WorkingEngines = qw(
scumm agos sky queen gob saga
kyra lure agi
scumm agos sky queen gob saga drascula
kyra lure agi touche parallaction cine
cruise igor made m4 tinsel sword1 sword2
);
@TestingEngines = qw(
cine cruise touche parallaction
drascula igor made m4
);
@BrokenEngines = qw(
sword1
sword2
@BrokenEngines = qw(
);
@EnablableEngines = (@WorkingEngines, @TestingEngines);
@ -29,21 +29,8 @@
);
# these are normally enabled for each variation
$DefaultFeatures = qw(zlib mad tremor);
#$DefaultFeatures = qw(zlib mad tremor);
# you can use these below for speed & clarity or override with custom settings
$DefaultTopMacros = "
MACRO USE_ZLIB // LIB:zlib.lib
//MACRO USE_MAD // LIB:libmad.lib
MACRO USE_TREMOR // LIB:libtremor.lib
";
$DefaultBottomMacros = "
MACRO DISABLE_SWORD1 // LIB:scummvm_sword1.lib
MACRO DISABLE_SWORD2 // LIB:scummvm_sword2.lib
";
#$DefaultFeatures = qw(zlib,mad);
$DefaultFeatures = qw(zlib,mad,tremor);
##################################################################################################################
##
@ -186,6 +173,44 @@
# now you can add $VariationSets only built on this PC below this line :)
}
elsif ($ENV{'COMPUTERNAME'} eq "EMBEDDEV-LAPE") #################################################################
{
$Producer = "AnotherGuest";
$RedirectSTDERR = 1;
$HaltOnError = 0;
$SkipExistingPackages = 1;
$ReallyQuiet = 1;
#$FTP_Host = "host.com";
#$FTP_User = "ag@host.com";
#$FTP_Pass = "password";
#$FTP_Dir = "cvsbuilds";
#$SDK_RootDirs{'UIQ2'}= "D:\\UIQ2";
$SDK_RootDirs{'UIQ3'}= "G:\\UIQ3";
#$SDK_RootDirs{'S60v1'}= "D:\\S60v1";
#$SDK_RootDirs{'S60v2'}= "D:\\S60v2";
$SDK_RootDirs{'S60v3'}= "G:\\S60_3rd_FP1";
#$SDK_RootDirs{'S80'}= "D:\\S80";
#$SDK_RootDirs{'S90'}= "D:\\S90";
$ECompXL_BinDir= "D:\\ECompXL\\";
if (0) # so we can turn them on/off easily
{
# $SDK_LibraryDirs{'ALL'}{'zlib.lib'} = "C:\\S\\zlib-1.2.2\\epoc";
# $SDK_LibraryDirs{'ALL'}{'libmad.lib'} = "C:\\S\\libmad-0.15.1b\\group";
# $SDK_LibraryDirs{'ALL'}{'libtremor.lib'}= "C:\\tremor\\epoc";
$SDK_LibraryDirs{'UIQ2'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\UIQ";
$SDK_LibraryDirs{'S60v1'}{'esdl.lib'} = $SDK_LibraryDirs{'S60v2'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S60";
$SDK_LibraryDirs{'S80'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S80";
$SDK_LibraryDirs{'S90'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S90";
$SDK_LibraryDirs{'S60v3'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\S60\\S60V3";
$SDK_LibraryDirs{'UIQ3'}{'esdl.lib'} = "E:\\WICKED\\ESDL\\epoc\\UIQ\\UIQ3";
#$SDK_LibraryDirs{'ALL'}{'libmpeg2.lib'} = "C:\\S\\mpeg2dec-0.4.0\\epoc";
}
# now you can add $VariationSets only built on this PC below this line :)
}
else #########################################################################################################
{
@ -246,15 +271,11 @@
}
# below here you could specify weird & experimental combinations, non-ready engines
# a small version of the saga engine, because it is so big (no tremor,mad,zlib)
#$VariationSets{'ALL'}{'saga_mini'} = "saga";
# Separate version for the broken sword engines (1&2)
$VariationSets{'ALL'}{'brokensword'} = "$DefaultFeatures sword1 sword2";
# a smaller version of scumm without support for v7, v8 and HE games
#$VariationSets{'ALL'}{'scumm_no78he'} = "$DefaultFeatures scumm";
# maybe you feel lucky and want to test the sword engines? :P
#$VariationSets{'S60v2'}{'test_sword'} = "$DefaultFeatures mpeg2 sword1 sword2";
#$VariationSets{'UIQ2'}{'test_sword'} = "$DefaultFeatures mpeg2 sword1 sword2";
# Separate version for Scumm games (COMI) since memory usage might be high
$VariationSets{'ALL'}{'scumm'} = "$DefaultFeatures scumm scumm_7_8 he";
# for mega-fast-testing only plz! Warning: contains to engines!
#$VariationSets{'ALL'}{'fast_empty'} = "";

View file

@ -1,33 +1,45 @@
ScummVM - ScummVM ported to EPOC/SymbianOS
Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson
Copyright (C) 2007 Lars 'AnotherGuest' Persson
Copyright (C) 2007 Jurgen 'SumthinWicked' Braam
Copyright (C) 2007 ScummVM Team
Copyright (C) 2008 ScummVM Team
Copyright (C) 2003-2008 Lars 'AnotherGuest' Persson
Copyright (C) 2002008 Jurgen 'SumthinWicked' Braam
Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson
$Id$
Using parts of snprintf.c by
Mark Martinec <mark.martinec@ijs.si>, April 1999, June 2000
Copyright © 1999,2000,2001,2002 Mark Martinec. All rights reserved.
under these conditions:
"Terms and conditions ...
This program is free software; it is dual licensed, the terms of the "Frontier Artistic License" or
the "GNU General Public License" can be chosen at your discretion.
The chosen license then applies solely and in its entirety.
Both licenses come with this Kit."
About ScummVM
--------------
The original ports (uptil 0.7.1) were made by Andreas Karlsson and Lars Persson.
The main transition to 0.8.0CVS and all relevant changes were done by Jurgen Braam.
Jurgen and Lars have successfully transfered all needed changes into CVS, with additional helpful tools for Symbian OS
Jurgen and Lars have successfully transfered all needed changes into CVS/SVN, with additional helpful tools for Symbian OS
Release version: 0.10.0
Release version: 0.12.0
* This version is only supported on Symbian OS 9 devices due to compiler constraints for older devices. (That means UIQ3 and S60V3 devices)
* Updated to SDL version 1.2.11 (previous version used was 1.2.8)
* Updated to SDL version 1.2.13 (previous version used was 1.2.2)
* Information about S60 devices can be found here http://wiki.scummvm.org/index.php/SymbianOS_S60
* Information about UIQ devices can be found here http://wiki.scummvm.org/index.php/SymbianOS_UIQ
* Best source of general information is the ScummVM forum, http://forums.scummvm.org
* SVN builds (not frequently updated) can be found at http://anotherguest.k0.se
* SVN builds (not frequently updated) can be found at http://www.anotherguest.se
Games supported
---------------
The Symbian port of ScummVM supports all but Sword1 & 2 games. Some games might not run properly due to screenresolution or memory constraints.
Minimum free memory requirement is about 12MB to be able to start and run ScummVM, this is enough for most older games, but newer more resource hungry games, might require more.
Building ScummVM
---------------------
@ -38,7 +50,7 @@ Building ScummVM
Lets just say the framework needs quite some time to set up and takes a while
to get used to. If you choose to continue you will need the following items:
- UIQ 3.0 SDK (To build for UIQ3 devices)
- UIQ 3.x SDK (To build for UIQ3 devices)(Build scripts in SDK need tweaking in order to build scummvm since Symbian OS GCCE never builds as large projects as ScummVM before)
- UIQ 2.1 SDK (To build for UIQ2 devices);
http://www.symbian.com/developer/sdks_uiq.asp
@ -72,8 +84,7 @@ Building ScummVM
http://flac.sourceforge.net/
- libmpeg2, a free MPEG-2 video stream decoder
http://libmpeg2.sourceforge.net/
http://libmpeg2.sourceforge.net
Compiling ScummVM
-----------------
@ -89,7 +100,7 @@ Building ScummVM
PETRAN.EXE will be the executable that is started.
SDL: the latest version of SDL at this point in time is 1.2.12. This version
SDL: the latest version of SDL at this point in time is 1.2.13. This version
works great for compiling on other platforms.
zlib: the zlib-x.x.x.tar.gz does not come with UIQ .mpp build files, that's why

View file

@ -93,6 +93,7 @@ SOURCE backends\platform\symbian\src\ScummApp.cpp
SOURCE gui\Key.cpp
SOURCE gui\KeysDialog.cpp
SOURCE gui\Actions.cpp
SOURCE gui\Dialog.cpp
// Special for graphics
source graphics\iff.cpp

View file

@ -16,7 +16,7 @@
; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
;
; $URL:$
; $Id:$
; $Id$
;
;
@ -28,7 +28,7 @@
;&EN
; UID is the app's UID
#{"ScummVM S60v1"},(0x101f9b57),0,120,0
#{"ScummVM S60v1"},(0x101f9b57),0,130,0
; Platform type
(0x101F6F88), 0, 0, 0, {"Series60ProductID"}

View file

@ -27,7 +27,7 @@
;&EN
; UID is the app's UID
#{"ScummVM S60v2"},(0x101f9b57),0,120,0
#{"ScummVM S60v2"},(0x101f9b57),0,130,0
; Platform type
(0x101F6F88), 0, 0, 0, {"Series60ProductID"}
@ -52,6 +52,7 @@
"..\..\..\..\dists\engine-data\sky.cpt"-"!:\system\apps\scummvm\sky.cpt"
"..\..\..\..\dists\engine-data\igor.tbl"-"!:\system\apps\scummvm\igor.tbl"
"..\..\..\..\dists\engine-data\lure.dat"-"!:\system\apps\scummvm\lure.dat"
"..\..\..\..\dists\engine-data\drascula.dat"-"!:\system\apps\scummvm\drascula.dat"
; Config/log files: 'empty' will automagically be removed on uninstall
""-"!:\system\apps\ScummVM\scummvm.ini",FILENULL

View file

@ -50,7 +50,7 @@ LANG SC
END
EPOCSTACKSIZE 80000
EPOCHEAPSIZE 3000000 64000000
EPOCHEAPSIZE 5000000 64000000
START BITMAP ScummVM.mbm
TARGETPATH \Resource\Apps
@ -116,6 +116,7 @@ SOURCE backends\platform\symbian\src\ScummApp.cpp
SOURCE gui\Key.cpp
SOURCE gui\KeysDialog.cpp
SOURCE gui\Actions.cpp
SOURCE gui\Dialog.cpp
// Special for graphics
source graphics\iff.cpp

View file

@ -16,7 +16,7 @@
; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
;
; $URL:$
; $Id:$
; $Id$
;
;
@ -34,7 +34,7 @@
:"ScummVM"
; UID is the app's UID
#{"ScummVM S60v3"},(0xA0000657),0,120,0
#{"ScummVM S60v3"},(0xA0000657),0,13,0
;Supports Series 60 v 3.0
[0x101F7961], 0, 0, 0, {"Series60ProductID"}
@ -63,6 +63,7 @@
"..\..\..\..\dists\engine-data\sky.cpt"-"c:\data\scummvm\sky.cpt"
"..\..\..\..\dists\engine-data\igor.tbl"-"c:\data\scummvm\igor.tbl"
"..\..\..\..\dists\engine-data\lure.dat"-"c:\data\scummvm\lure.dat"
"..\..\..\..\dists\engine-data\drascula.dat"-"c:\data\scummvm\drascula.dat"
; Config/log files: 'empty' will automagically be removed on uninstall
""-"c:\data\scummvm\scummvm.ini",FILENULL

View file

@ -91,6 +91,7 @@ SOURCE backends\platform\symbian\src\ScummApp.cpp
SOURCE gui\Key.cpp
SOURCE gui\KeysDialog.cpp
SOURCE gui\Actions.cpp
SOURCE gui\Dialog.cpp
// Special for graphics
source graphics\iff.cpp

View file

@ -28,7 +28,7 @@
;&EN
; UID is the app's UID
#{"ScummVM S80"},(0x101f9b57),0,120,0
#{"ScummVM S80"},(0x101f9b57),0,130,0
; Platform type -- disabled: seems to be causing trouble
;(0x101F8ED2), 0, 0, 0, {"Series80ProductID"}
@ -53,6 +53,7 @@
"..\..\..\..\dists\engine-data\sky.cpt"-"!:\system\apps\scummvm\sky.cpt"
"..\..\..\..\dists\engine-data\igor.tbl"-"!:\system\apps\scummvm\igor.tbl"
"..\..\..\..\dists\engine-data\lure.dat"-"!:\system\apps\scummvm\lure.dat"
"..\..\..\..\dists\engine-data\drascula.dat"-"!:\system\apps\scummvm\drascula.dat"
; Config/log files: 'empty' will automagically be removed on uninstall
""-"!:\system\apps\ScummVM\scummvm.ini",FILENULL

Some files were not shown because too many files have changed in this diff Show more