diff options
Diffstat (limited to 'backends/platform')
87 files changed, 4148 insertions, 1662 deletions
diff --git a/backends/platform/PalmOS/Src/be_base.cpp b/backends/platform/PalmOS/Src/be_base.cpp index afb3f15bae..32e68bde9f 100644 --- a/backends/platform/PalmOS/Src/be_base.cpp +++ b/backends/platform/PalmOS/Src/be_base.cpp @@ -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 diff --git a/backends/platform/dc/dc-fs.cpp b/backends/platform/dc/dc-fs.cpp index f4dc4037df..4baba5b7dc 100644 --- a/backends/platform/dc/dc-fs.cpp +++ b/backends/platform/dc/dc-fs.cpp @@ -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(Common::String(start, end - start)); +} + - return new RoninCDDirectoryNode(String(start, end - start)); +Common::SeekableReadStream *RoninCDFileNode::openForReading() { + return StdioStream::makeFromPath(getPath().c_str(), false); } AbstractFilesystemNode *OSystem_Dreamcast::makeRootFileNode() const { diff --git a/backends/platform/dc/selector.cpp b/backends/platform/dc/selector.cpp index 91c851506f..883787781a 100644 --- a/backends/platform/dc/selector.cpp +++ b/backends/platform/dc/selector.cpp @@ -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(), diff --git a/backends/platform/dc/vmsave.cpp b/backends/platform/dc/vmsave.cpp index 6ab8fc4558..d17e1f6213 100644 --- a/backends/platform/dc/vmsave.cpp +++ b/backends/platform/dc/vmsave.cpp @@ -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) diff --git a/backends/platform/ds/arm7/Makefile b/backends/platform/ds/arm7/Makefile index 55db7f8cad..82637845db 100644 --- a/backends/platform/ds/arm7/Makefile +++ b/backends/platform/ds/arm7/Makefile @@ -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 diff --git a/backends/platform/ds/arm7/source/main.cpp b/backends/platform/ds/arm7/source/main.cpp index bee39f1efe..d252ed44de 100644 --- a/backends/platform/ds/arm7/source/main.cpp +++ b/backends/platform/ds/arm7/source/main.cpp @@ -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. :-) } /* diff --git a/backends/platform/ds/arm9/dist/readme_ds.txt b/backends/platform/ds/arm9/dist/readme_ds.txt new file mode 100644 index 0000000000..f77da418c9 --- /dev/null +++ b/backends/platform/ds/arm9/dist/readme_ds.txt @@ -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. + + + diff --git a/backends/platform/ds/arm9/makefile b/backends/platform/ds/arm9/makefile index 7472a32218..e74bcf28da 100644 --- a/backends/platform/ds/arm9/makefile +++ b/backends/platform/ds/arm9/makefile @@ -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) +ifeq ($(SCUMM_BUILD),h) + DS_BUILD_H = 1 + else + ifeq ($(SCUMM_BUILD),g) DS_BUILD_G = 1 -else - ifeq ($(SCUMM_BUILD),f) + else + ifeq ($(SCUMM_BUILD),f) DS_BUILD_F = 1 - else - ifeq ($(SCUMM_BUILD),e) - DS_BUILD_E = 1 else - ifeq ($(SCUMM_BUILD),d) - DS_BUILD_D = 1 + 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 - diff --git a/backends/platform/ds/arm9/source/blitters_arm.s b/backends/platform/ds/arm9/source/blitters_arm.s index 5f7df298b4..48ec316675 100644 --- a/backends/platform/ds/arm9/source/blitters_arm.s +++ b/backends/platform/ds/arm9/source/blitters_arm.s @@ -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: diff --git a/backends/platform/ds/arm9/source/cdaudio.h b/backends/platform/ds/arm9/source/cdaudio.h index d237569bb7..d1897d3e5d 100644 --- a/backends/platform/ds/arm9/source/cdaudio.h +++ b/backends/platform/ds/arm9/source/cdaudio.h @@ -20,7 +20,7 @@ * */ - #ifndef _CDAUDIO_H_ +#ifndef _CDAUDIO_H_ #define _CDAUDIO_H_ namespace DS { diff --git a/backends/platform/ds/arm9/source/dsmain.cpp b/backends/platform/ds/arm9/source/dsmain.cpp index f4706807f7..872a196e9b 100644 --- a/backends/platform/ds/arm9/source/dsmain.cpp +++ b/backends/platform/ds/arm9/source/dsmain.cpp @@ -65,6 +65,8 @@ //#define USE_LIBCARTRESET #include <nds.h> +#include <nds/registers_alt.h> +#include <nds/arm9/exceptions.h> //#include <ARM9/console.h> //basic print funcionality @@ -75,13 +77,10 @@ #include "icons_raw.h" #include "fat/gba_nds_fat.h" #include "fat/disc_io.h" -#include "common/config-manager.h" -#include "engines/scumm/scumm.h" #include "keyboard_raw.h" #include "keyboard_pal_raw.h" #define V16(a, b) ((a << 12) | b) #include "touchkeyboard.h" -#include "registers_alt.h" //#include "compact_flash.h" #include "dsoptions.h" #ifdef USE_DEBUGGER @@ -96,6 +95,26 @@ #endif #include "backends/fs/ds/ds-fs.h" +extern "C" u32 getExceptionAddress( u32 opcodeAddress, u32 thumbState); +extern const char __itcm_start[]; +static const char *registerNames[] = + { "r0","r1","r2","r3","r4","r5","r6","r7", + "r8 ","r9 ","r10","r11","r12","sp ","lr ","pc " }; + +/* +extern "C" void* __real_malloc(size_t size); + +extern "C" void* __wrap_malloc(size_t size) { + void* res = __real_malloc(size); + if (res) { + return res; + } else { + consolePrintf("Failed alloc %d\n", size); + return NULL; + } +} +*/ + namespace DS { // From console.c in NDSLib @@ -168,7 +187,7 @@ bool displayModeIs8Bit = false; u8 gameID; bool snapToBorder = false; -bool consoleEnable = true; +bool consoleEnable = false; bool gameScreenSwap = false; bool isCpuScalerEnabled(); //#define HEAVY_LOGGING @@ -197,6 +216,13 @@ int mouseHotspotX, mouseHotspotY; bool cursorEnable = false; bool mouseCursorVisible = true; bool rightButtonDown = false; +bool touchPadStyle = false; +int touchPadSensitivity = 8; +bool tapScreenClicks = true; + +int tapCount = 0; +int tapTimeout = 0; +int tapComplete = 0; // Dragging int dragStartX, dragStartY; @@ -213,7 +239,14 @@ int gameHeight = 200; // Scale bool twoHundredPercentFixedScale = false; bool cpuScalerEnable = false; -#define NUM_SUPPORTED_GAMES 20 + + // 100 256 + // 150 192 + // 200 128 + + // (256 << 8) / scale + + #ifdef USE_PROFILER int hBlankCount = 0; @@ -221,6 +254,7 @@ int hBlankCount = 0; u8* scalerBackBuffer = NULL; +#define NUM_SUPPORTED_GAMES 21 gameListType gameList[NUM_SUPPORTED_GAMES] = { // Unknown game - use normal SCUMM controls @@ -248,6 +282,7 @@ gameListType gameList[NUM_SUPPORTED_GAMES] = { {"elvira2", CONT_SIMON}, {"elvira1", CONT_SIMON}, {"waxworks", CONT_SIMON}, + {"parallaction", CONT_NIPPON}, }; gameListType* currentGame = NULL; @@ -260,6 +295,7 @@ bool penHeld; bool penReleased; bool penDownLastFrame; s32 penX, penY; +s32 penDownX, penDownY; int keysDownSaved; int keysReleasedSaved; int keysChangedSaved; @@ -299,9 +335,41 @@ void setCpuScalerEnable(bool enable) { cpuScalerEnable = enable; } +void setTrackPadStyleEnable(bool enable) { + touchPadStyle = enable; +} + +void setTapScreenClicksEnable(bool enable) { + tapScreenClicks = enable; +} + +void setGameScreenSwap(bool enable) { + gameScreenSwap = enable; +} + +void setSensitivity(int sensitivity) { + touchPadSensitivity = sensitivity; +} + +void setTopScreenZoom(int percentage) { + // 100 256 + // 150 192 + // 200 128 + + // (256 << 8) / scale + + s32 scale = (percentage << 8) / 100; + subScreenScale = (256 * 256) / scale; + +// consolePrintf("Scale is %d %%\n", percentage); +} // return (ConfMan.hasKey("cpu_scaler", "ds") && ConfMan.getBool("cpu_scaler", "ds")); +controlType getControlType() { + return currentGame->control; +} + //plays an 8 bit mono sample at 11025Hz void playSound(const void* data, u32 length, bool loop, bool adpcm, int rate) @@ -429,14 +497,14 @@ void initGame() { consolePrintf("initing game..."); #endif - static bool firstTime = true; +// static bool firstTime = true; setOptions(); //strcpy(gameName, ConfMan.getActiveDomain().c_str()); strcpy(gameName, ConfMan.get("gameid").c_str()); - consolePrintf("\n\n\n\nCurrent game: '%s' %d\n", gameName, gameName[0]); +// consolePrintf("\n\n\n\nCurrent game: '%s' %d\n", gameName, gameName[0]); currentGame = &gameList[0]; // Default game @@ -447,16 +515,12 @@ void initGame() { } } - if (firstTime) { +/* if (firstTime) { firstTime = false; - if (ConfMan.hasKey("22khzaudio", "ds") && ConfMan.getBool("22khzaudio", "ds")) { - startSound(22050, 8192); - } else { - startSound(11025, 4096); - } } +*/ #ifdef HEAVY_LOGGING consolePrintf("done\n"); #endif @@ -631,7 +695,7 @@ void checkSleepMode() { void setShowCursor(bool enable) { - if (currentGame->control == CONT_SCUMM_SAMNMAX) + if ((currentGame) && (currentGame->control == CONT_SCUMM_SAMNMAX)) { if (cursorEnable) { sprites[1].attribute[0] = ATTR0_BMP | 150; @@ -654,23 +718,28 @@ void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor, int hotspotX, mouseHotspotX = hotspotX; mouseHotspotY = hotspotY; + //consolePrintf("Set cursor icon %d, %d\n", w, h); + { int off = 128*64; memset(SPRITE_GFX + off, 0, 32 * 32 * 2); memset(SPRITE_GFX_SUB + off, 0, 32 * 32 * 2); + for (uint y=0; y<h; y++) { for (uint x=0; x<w; x++) { int color = icon[y*w+x]; + + //consolePrintf("%d:%d ", color, OSystem_DS::instance()->getDSPaletteEntry(color)); if (color == keycolor) { SPRITE_GFX[off+(y)*32+x] = 0x0000; // black background SPRITE_GFX_SUB[off+(y)*32+x] = 0x0000; // black background } else { - SPRITE_GFX[off+(y)*32+x] = BG_PALETTE[color] | 0x8000; - SPRITE_GFX_SUB[off+(y)*32+x] = BG_PALETTE[color] | 0x8000; + SPRITE_GFX[off+(y)*32+x] = OSystem_DS::instance()->getDSCursorPaletteEntry(color) | 0x8000; + SPRITE_GFX_SUB[off+(y)*32+x] = OSystem_DS::instance()->getDSCursorPaletteEntry(color) | 0x8000; } } } @@ -733,6 +802,7 @@ void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor, int hotspotX, sprites[1].attribute[1] = ATTR1_SIZE_64 | pos; sprites[1].attribute[2] = ATTR2_ALPHA(1) | 176; } + } @@ -745,6 +815,7 @@ void displayMode16Bit() { u16 buffer[32 * 32 * 2]; + releaseAllKeys(); if (displayModeIs8Bit) { // static int test = 0; @@ -1109,7 +1180,7 @@ void setKeyboardEnable(bool en) { } else { - + DS::releaseAllKeys(); // Restore the palette that the keyboard has used for (int r = 0; r < 256; r++) { BG_PALETTE_SUB[r] = BG_PALETTE[r]; @@ -1157,6 +1228,194 @@ bool getIsDisplayMode8Bit() { return displayModeIs8Bit; } +void doScreenTapMode(OSystem_DS* system) +{ + Common::Event event; + static bool left = false, right = false; + + if (left) { + event.type = Common::EVENT_LBUTTONUP; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + left = false; + } + + if (right) { + event.type = Common::EVENT_RBUTTONUP; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + right = false; + } + + + if (tapComplete == 1) { + event.type = Common::EVENT_LBUTTONDOWN; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + tapComplete = 0; + left = true; + } else if (tapComplete == 2) { + event.type = Common::EVENT_RBUTTONDOWN; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + tapComplete = 0; + right = true; + } + + + if (getKeysDown() & KEY_LEFT) { + event.type = Common::EVENT_LBUTTONDOWN; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + } + + if (getKeysReleased() & KEY_LEFT) { + event.type = Common::EVENT_LBUTTONUP; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + } + + + if (getKeysDown() & KEY_RIGHT) { + event.type = Common::EVENT_RBUTTONDOWN; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + } + + if (getKeysReleased() & KEY_RIGHT) { + event.type = Common::EVENT_RBUTTONUP; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + } + + event.type = Common::EVENT_MOUSEMOVE; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); +} + +void doButtonSelectMode(OSystem_DS* system) +{ + Common::Event event; + + + if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { + event.type = Common::EVENT_MOUSEMOVE; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + //consolePrintf("x=%d y=%d \n", getPenX(), getPenY()); + } + + static bool leftButtonDown = false; + static bool rightButtonDown = false; + + if (getPenReleased() && (leftButtonDown || rightButtonDown)) { + if (leftButtonDown) { + event.type = Common::EVENT_LBUTTONUP; + } else { + event.type = Common::EVENT_RBUTTONUP; + } + + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + } + + + if ((mouseMode != MOUSE_HOVER) || (!displayModeIs8Bit)) { + if (getPenDown() && (!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { + if ((mouseMode == MOUSE_LEFT) || (!displayModeIs8Bit)) { + event.type = Common::EVENT_LBUTTONDOWN; + leftButtonDown = true; + } else { + event.type = Common::EVENT_RBUTTONDOWN; + rightButtonDown = true; + } + + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + } + + } else { + // In hover mode, D-pad left and right click the mouse when the pen is on the screen + + if (getPenHeld()) { + if (getKeysDown() & KEY_LEFT) { + event.type = Common::EVENT_LBUTTONDOWN; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + } + if (getKeysReleased() & KEY_LEFT) { + event.type = Common::EVENT_LBUTTONUP; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + } + + + if (getKeysDown() & KEY_RIGHT) { + event.type = Common::EVENT_RBUTTONDOWN; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + } + if (getKeysReleased() & KEY_RIGHT) { + event.type = Common::EVENT_RBUTTONUP; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + } + } + } + + if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (!getIndyFightState()) && (!getKeyboardEnable())) { + + if (!getPenHeld() || (mouseMode != MOUSE_HOVER)) { + if (getKeysDown() & KEY_LEFT) { + mouseMode = MOUSE_LEFT; + } + + if (rightButtonDown) + { + Common::Event event; + event.mouse = Common::Point(getPenX(), getPenY()); + event.type = Common::EVENT_RBUTTONUP; + system->addEvent(event); + rightButtonDown = false; + } + + + if (getKeysDown() & KEY_RIGHT) { + if ((currentGame->control != CONT_SCUMM_SAMNMAX) && (currentGame->control != CONT_FUTURE_WARS) && (currentGame->control != CONT_GOBLINS)) { + mouseMode = MOUSE_RIGHT; + } else { + // If we're playing sam and max, click and release the right mouse + // button to change verb + Common::Event event; + + if (currentGame->control == CONT_FUTURE_WARS) { + event.mouse = Common::Point(320 - 128, 200 - 128); + event.type = Common::EVENT_MOUSEMOVE; + system->addEvent(event); + } else { + event.mouse = Common::Point(getPenX(), getPenY()); + } + + rightButtonDown = true; + + + event.type = Common::EVENT_RBUTTONDOWN; + system->addEvent(event); + + //event.type = Common::EVENT_RBUTTONUP; + //system->addEvent(event); + } + } + + + + if (getKeysDown() & KEY_UP) { + mouseMode = MOUSE_HOVER; + } + } + } +} + void addEventsToQueue() { #ifdef HEAVY_LOGGING consolePrintf("addEventsToQueue\n"); @@ -1286,54 +1545,6 @@ void addEventsToQueue() { } - if (!getPenHeld() || (mouseMode != MOUSE_HOVER)) { - if (getKeysDown() & KEY_LEFT) { - mouseMode = MOUSE_LEFT; - } - - if (rightButtonDown) - { - Common::Event event; - event.mouse = Common::Point(getPenX(), getPenY()); - event.type = Common::EVENT_RBUTTONUP; - system->addEvent(event); - rightButtonDown = false; - } - - - if (getKeysDown() & KEY_RIGHT) { - if ((currentGame->control != CONT_SCUMM_SAMNMAX) && (currentGame->control != CONT_FUTURE_WARS) && (currentGame->control != CONT_GOBLINS)) { - mouseMode = MOUSE_RIGHT; - } else { - // If we're playing sam and max, click and release the right mouse - // button to change verb - Common::Event event; - - if (currentGame->control == CONT_FUTURE_WARS) { - event.mouse = Common::Point(320 - 128, 200 - 128); - event.type = Common::EVENT_MOUSEMOVE; - system->addEvent(event); - } else { - event.mouse = Common::Point(getPenX(), getPenY()); - } - - rightButtonDown = true; - - - event.type = Common::EVENT_RBUTTONDOWN; - system->addEvent(event); - - //event.type = Common::EVENT_RBUTTONUP; - //system->addEvent(event); - } - } - - - - if (getKeysDown() & KEY_UP) { - mouseMode = MOUSE_HOVER; - } - } @@ -1359,52 +1570,13 @@ void addEventsToQueue() { if (!keyboardEnable) { - if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { - event.type = Common::EVENT_MOUSEMOVE; - event.mouse = Common::Point(getPenX(), getPenY()); - system->addEvent(event); - //consolePrintf("x=%d y=%d \n", getPenX(), getPenY()); + if ((tapScreenClicks) && (getIsDisplayMode8Bit())) + { + doScreenTapMode(system); } - - if ((mouseMode != MOUSE_HOVER) || (!displayModeIs8Bit)) { - if (getPenDown() && (!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { - event.type = ((mouseMode == MOUSE_LEFT) || (!displayModeIs8Bit))? Common::EVENT_LBUTTONDOWN: Common::EVENT_RBUTTONDOWN; - event.mouse = Common::Point(getPenX(), getPenY()); - system->addEvent(event); - } - - if (getPenReleased()) { - event.type = mouseMode == MOUSE_LEFT? Common::EVENT_LBUTTONUP: Common::EVENT_RBUTTONUP; - event.mouse = Common::Point(getPenX(), getPenY()); - system->addEvent(event); - } - } else { - // In hover mode, D-pad left and right click the mouse when the pen is on the screen - - if (getPenHeld()) { - if (getKeysDown() & KEY_LEFT) { - event.type = Common::EVENT_LBUTTONDOWN; - event.mouse = Common::Point(getPenX(), getPenY()); - system->addEvent(event); - } - if (getKeysReleased() & KEY_LEFT) { - event.type = Common::EVENT_LBUTTONUP; - event.mouse = Common::Point(getPenX(), getPenY()); - system->addEvent(event); - } - - - if (getKeysDown() & KEY_RIGHT) { - event.type = Common::EVENT_RBUTTONDOWN; - event.mouse = Common::Point(getPenX(), getPenY()); - system->addEvent(event); - } - if (getKeysReleased() & KEY_RIGHT) { - event.type = Common::EVENT_RBUTTONUP; - event.mouse = Common::Point(getPenX(), getPenY()); - system->addEvent(event); - } - } + else + { + doButtonSelectMode(system); } if (((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R)) || (indyFightState)) && (displayModeIs8Bit)) { @@ -1537,8 +1709,8 @@ void triggerIcon(int imageNum) { void setIcon(int num, int x, int y, int imageNum, int flags, bool enable) { - sprites[num].attribute[0] = ATTR0_BMP | (enable? y: 192) | (!enable? ATTR0_DISABLED: 0); - sprites[num].attribute[1] = ATTR1_SIZE_32 | x | flags; + sprites[num].attribute[0] = ATTR0_BMP | (enable? (y & 0xFF): 192) | (!enable? ATTR0_DISABLED: 0); + sprites[num].attribute[1] = ATTR1_SIZE_32 | (x & 0x1FF) | flags; sprites[num].attribute[2] = ATTR2_ALPHA(1)| (imageNum * 16); } @@ -1552,28 +1724,30 @@ void updateStatus() { int offs; if (displayModeIs8Bit) { - switch (mouseMode) { - case MOUSE_LEFT: { - offs = 1; - break; - } - case MOUSE_RIGHT: { - offs = 2; - break; - } - case MOUSE_HOVER: { - offs = 0; - break; - } - default: { - // Nothing! - offs = 0; - break; + if (!tapScreenClicks) { + switch (mouseMode) { + case MOUSE_LEFT: { + offs = 1; + break; + } + case MOUSE_RIGHT: { + offs = 2; + break; + } + case MOUSE_HOVER: { + offs = 0; + break; + } + default: { + // Nothing! + offs = 0; + break; + } } + + setIcon(0, 208, 150, offs, 0, true); } - setIcon(0, 208, 150, offs, 0, true); - if (indyFightState) { setIcon(1, (190 - 32), 150, 3, (indyFightRight? 0: ATTR1_FLIP_X), true); // consolePrintf("%d\n", indyFightRight); @@ -1631,7 +1805,7 @@ void setMainScreenScroll(int x, int y) { BG3_CX = x + (((frameCount & 1) == 0)? 64: 0); BG3_CY = y; - if (!gameScreenSwap) { + if ((!gameScreenSwap) || (touchPadStyle)) { touchX = x >> 8; touchY = y >> 8; } @@ -1660,7 +1834,7 @@ void setMainScreenScale(int x, int y) { BG3_YDY = y; } - if (!gameScreenSwap) { + if ((!gameScreenSwap) || (touchPadStyle)) { touchScX = x; touchScY = y; } @@ -1676,7 +1850,7 @@ void setZoomedScreenScroll(int x, int y, bool shake) { touchY = y >> 8; } else */{ - if (gameScreenSwap) { + if ((gameScreenSwap) && (!touchPadStyle)) { touchX = x >> 8; touchY = y >> 8; } @@ -1696,7 +1870,7 @@ void setZoomedScreenScale(int x, int y) { } else */{ - if (gameScreenSwap) { + if ((gameScreenSwap) && (!touchPadStyle)) { touchScX = x; touchScY = y; } @@ -1757,18 +1931,22 @@ void VBlankHandler(void) { frameCount++; - if ((cursorEnable) && (mouseCursorVisible)) - { + if ((cursorEnable) && (mouseCursorVisible)) { if (!keyboardEnable) { storedMouseX = penX; storedMouseY = penY; } - setIconMain(3, storedMouseX - mouseHotspotX, storedMouseY - mouseHotspotY, 8, 0, true); - } - else - { + if (gameScreenSwap) { + setIcon(3, storedMouseX - mouseHotspotX, storedMouseY - mouseHotspotY, 8, 0, true); + setIconMain(3, 0, 0, 0, 0, false); + } else { + setIconMain(3, storedMouseX - mouseHotspotX, storedMouseY - mouseHotspotY, 8, 0, true); + setIcon(3, 0, 0, 0, 0, false); + } + } else { setIconMain(3, 0, 0, 0, 0, false); + setIcon(3, 0, 0, 0, 0, false); } @@ -1826,7 +2004,7 @@ void VBlankHandler(void) { SUB_BG3_YDX = 0; SUB_BG3_YDY = (int) (subScreenHeight / 192.0f * 256);*/ - static int ratio = ( 320 << 8) / SCUMM_GAME_WIDTH; + static int ratio = (320 << 8) / SCUMM_GAME_WIDTH; bool zooming = false; @@ -1851,8 +2029,12 @@ void VBlankHandler(void) { subScreenWidth = 256 >> 1; subScreenHeight = 192 >> 1; } else { - subScreenWidth = (((SCUMM_GAME_HEIGHT * 256) / 192) * subScreenScale) >> 8; - subScreenHeight = SCUMM_GAME_HEIGHT * subScreenScale >> 8; +// subScreenWidth = (((SCUMM_GAME_HEIGHT * 256) / 192) * subScreenScale) >> 8; +// subScreenHeight = SCUMM_GAME_HEIGHT * subScreenScale >> 8; + + + subScreenWidth = (256 * subScreenScale) >> 8; + subScreenHeight = (192 * subScreenScale) >> 8; if ( ((subScreenWidth) > 256 - 8) && ((subScreenWidth) < 256 + 8) ) { subScreenWidth = 256; @@ -2215,43 +2397,141 @@ void penUpdate() { // if (getKeysHeld() & KEY_L) consolePrintf("%d, %d penX=%d, penY=%d tz=%d\n", IPC->touchXpx, IPC->touchYpx, penX, penY, IPC->touchZ1); - if ((penDownFrames > 1)) { // Is this right? Dunno, but it works for me. + bool penDownThisFrame = (IPC->touchZ1 > 0) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0); + bool firstFrame = penDownFrames == 2; + static bool moved = false; - if ((penHeld)) { - penHeld = true; - penDown = false; + if ((tapScreenClicks) && (!getKeyboardEnable()) && (getIsDisplayMode8Bit())) { - if ((IPC->touchZ1 > 0) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0)) { - penX = IPC->touchXpx + touchXOffset; - penY = IPC->touchYpx + touchYOffset; + if ((tapTimeout >= 0)) { + tapTimeout++; + + if (((tapTimeout > 15) || (tapCount == 2)) && (tapCount > 0)) { + tapComplete = tapCount; + tapCount = 0; +// consolePrintf("Taps: %d\n", tapComplete); } + } - } else { - penDown = true; - penHeld = true; - penDownSaved = true; + - //if ( (ABS(penX - IPC->touchXpx) < 10) && (ABS(penY - IPC->touchYpx) < 10) ) { - if ((IPC->touchZ1 > 0) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0)) { - penX = IPC->touchXpx; - penY = IPC->touchYpx; + if ((penHeld) && (!penDownThisFrame)) { + if ((touchPadStyle) || (moved) || (tapCount == 1)) { + if ((penDownFrames > 0) && (penDownFrames < 6) && ((tapTimeout == -1) || (tapTimeout > 2))) { + tapCount++; + tapTimeout = 0; +// consolePrintf("Tap! %d\n", penDownFrames); + moved = false; + } } - //} } + } - } else { - if (penHeld) { - penReleased = true; - penReleasedSaved = true; + + + if ((touchPadStyle) && (getIsDisplayMode8Bit())) { + + if ((penDownFrames > 0)) { + + + if ((penHeld)) { + + if (penDownThisFrame) + { + if (penDownFrames >= 2) { + int diffX = IPC->touchXpx - penDownX; + int diffY = IPC->touchYpx - penDownY; + + int speed = ABS(diffX) + ABS(diffY); + + if ((ABS(diffX) < 35) && (ABS(diffY) < 35)) + { + + if (speed >= 8) + { + diffX *= ((speed >> 3) * touchPadSensitivity) >> 3; + diffY *= ((speed >> 3) * touchPadSensitivity) >> 3; + } + + penX += diffX; + penY += diffY; + if (penX > 255) penX = 255; + if (penX < 0) penX = 0; + if (penY > 191) penY = 191; + if (penY < 0) penY = 0; + } + +// consolePrintf("x: %d y: %d\n", IPC->touchYpx - penDownY, IPC->touchYpx - penDownY); + penDownX = IPC->touchXpx; + penDownY = IPC->touchYpx; + + } + } + else + { + } + + + } else { + penDown = true; + penHeld = true; + penDownSaved = true; + + // First frame, so save pen positions + if (penDownThisFrame) { + penDownX = IPC->touchXpx; + penDownY = IPC->touchYpx; + } + } + } else { - penReleased = false; + if (penHeld) { + penReleased = true; + penReleasedSaved = true; + } else { + penReleased = false; + } + + penDown = false; + penHeld = false; } + } else { + if ((penDownFrames > 1)) { // Is this right? Dunno, but it works for me. + + if ((penHeld)) { + penHeld = true; + penDown = false; + } else { + penDown = true; + penHeld = true; + penDownSaved = true; + } + + if ((IPC->touchZ1 > 0) && (IPC->touchXpx > 0) && (IPC->touchYpx > 0)) { + penX = IPC->touchXpx + touchXOffset; + penY = IPC->touchYpx + touchYOffset; + moved = true; + } + - penDown = false; - penHeld = false; + + } else { + if (penHeld) { + penReleased = true; + penReleasedSaved = true; + } else { + penReleased = false; + } + + penDown = false; + penHeld = false; + } + + } + if ((IPC->touchZ1 > 0) || ((penDownFrames == 2)) ) { penDownLastFrame = true; penDownFrames++; @@ -2259,7 +2539,6 @@ void penUpdate() { penDownLastFrame = false; penDownFrames = 0; } - } int leftHandedSwap(int keys) { @@ -2346,8 +2625,7 @@ int getPenX() { int x = ((penX * touchScX) >> 8) + touchX; x = x < 0? 0: (x > gameWidth - 1? gameWidth - 1: x); - if (snapToBorder) - { + if (snapToBorder) { if (x < 8) x = 0; if (x > gameWidth - 8) x = gameWidth - 1; } @@ -2359,8 +2637,7 @@ int getPenY() { int y = ((penY * touchScY) >> 8) + touchY; y = y < 0? 0: (y > gameHeight - 1? gameHeight - 1: y); - if (snapToBorder) - { + if (snapToBorder) { if (y < 8) y = 0; if (y > gameHeight - 8) y = gameHeight - 1; } @@ -2377,6 +2654,8 @@ GLvector getPenPos() { return v; } +#ifdef GBA_SRAM_SAVE + void formatSramOption() { consolePrintf("The following files are present in save RAM:\n"); DSSaveFileManager::instance()->listFiles(); @@ -2398,7 +2677,7 @@ void formatSramOption() { } } } - +#endif void setIndyFightState(bool st) { indyFightState = st; @@ -2496,8 +2775,6 @@ struct cardTranslate { char dldiId[5]; }; -#define NUM_CARD_READERS 7 - cardTranslate cardReaderTable[] = { {DEVICE_TYPE_M3SD, DEVICE_M3SD, "M3SD"}, {DEVICE_TYPE_M3CF, DEVICE_M3CF, "M3CF"}, @@ -2519,13 +2796,13 @@ void reboot() { consolePrintf("DLDI Device ID: %s\n", id); - for (int r = 0; r < NUM_CARD_READERS; r++) { + for (int r = 0; r < ARRAYSIZE(cardReaderTable); r++) { if (!stricmp(id, cardReaderTable[r].dldiId)) { deviceType = cardReaderTable[r].cartResetId; } } } else { - for (int r = 0; r < NUM_CARD_READERS; r++) { + for (int r = 0; r < ARRAYSIZE(cardReaderTable); r++) { if (disc_getDeviceId() == cardReaderTable[r].svmId) { deviceType = cardReaderTable[r].cartResetId; } @@ -2573,13 +2850,66 @@ void powerOff() { ///////////////// -int main(void) -{ + +void dsExceptionHandler() { + consolePrintf("Blue screen of death"); + setExceptionHandler(NULL); + + + u32 currentMode = getCPSR() & 0x1f; + u32 thumbState = ((*(u32*)0x027FFD90) & 0x20); + + u32 codeAddress, exceptionAddress = 0; + + int offset = 8; + + if ( currentMode == 0x17 ) { + consolePrintf("\x1b[10Cdata abort!\n\n"); + codeAddress = exceptionRegisters[15] - offset; + if ( (codeAddress > 0x02000000 && codeAddress < 0x02400000) || + (codeAddress > (u32)__itcm_start && codeAddress < (u32)(__itcm_start + 32768)) ) + exceptionAddress = getExceptionAddress( codeAddress, thumbState); + else + exceptionAddress = codeAddress; + + } else { + if (thumbState) + offset = 2; + else + offset = 4; + consolePrintf("\x1b[5Cundefined instruction!\n\n"); + codeAddress = exceptionRegisters[15] - offset; + exceptionAddress = codeAddress; + } + + consolePrintf(" pc: %08X addr: %08X\n\n",codeAddress,exceptionAddress); + + int i; + for ( i=0; i < 8; i++ ) { + consolePrintf( " %s: %08X %s: %08X\n", + registerNames[i], exceptionRegisters[i], + registerNames[i+8],exceptionRegisters[i+8]); + } +// u32 *stack = (u32 *)exceptionRegisters[13]; +// for ( i=0; i<10; i++ ) { +// consolePrintf( "\x1b[%d;2H%08X: %08X %08X", i + 14, (u32)&stack[i*2],stack[i*2], stack[(i*2)+1] ); +// } + + memoryReport(); + + while(1); +} + + + + +int main(void) { soundCallback = NULL; initHardware(); + setExceptionHandler(dsExceptionHandler); #ifdef USE_DEBUGGER for (int r = 0; r < 150; r++) { @@ -2663,36 +2993,33 @@ int main(void) consolePrintf("-------------------------------\n"); consolePrintf("ScummVM DS\n"); consolePrintf("Ported by Neil Millstone\n"); - consolePrintf("Version 0.11.1 beta2"); + consolePrintf("Version 0.13.0 SVN "); #if defined(DS_BUILD_A) consolePrintf("build A\n"); consolePrintf("Lucasarts SCUMM games (SCUMM)\n"); - consolePrintf("-------------------------------\n"); #elif defined(DS_BUILD_B) consolePrintf("build B\n"); consolePrintf("BASS, QUEEN\n"); - consolePrintf("-------------------------------\n"); #elif defined(DS_BUILD_C) consolePrintf("build C\n"); consolePrintf("Simon/Elvira/Waxworks (AGOS)\n"); - consolePrintf("-------------------------------\n"); #elif defined(DS_BUILD_D) consolePrintf("build D\n"); consolePrintf("AGI, CINE, GOB\n"); - consolePrintf("-------------------------------\n"); #elif defined(DS_BUILD_E) consolePrintf("build E\n"); consolePrintf("Inherit the Earth (SAGA)\n"); - consolePrintf("-------------------------------\n"); #elif defined(DS_BUILD_F) consolePrintf("build F\n"); consolePrintf("The Legend of Kyrandia (KYRA)\n"); - consolePrintf("-------------------------------\n"); #elif defined(DS_BUILD_G) - consolePrintf("build F\n"); - consolePrintf("Lure of the Temptress (LURE)\n"); - consolePrintf("-------------------------------\n"); + consolePrintf("build G\n"); + consolePrintf("Lure of the Tempress (LURE)\n"); +#elif defined(DS_BUILD_H) + consolePrintf("build H\n"); + consolePrintf("Nippon Safes (PARALLATION)\n"); #endif + consolePrintf("-------------------------------\n"); consolePrintf("L/R + D-pad/pen: Scroll view\n"); consolePrintf("D-pad left: Left mouse button\n"); consolePrintf("D-pad right: Right mouse button\n"); @@ -2808,9 +3135,11 @@ int main(void) g_system = new OSystem_DS(); assert(g_system); +#ifdef GBA_SRAM_SAVE if ((keysHeld() & KEY_L) && (keysHeld() & KEY_R)) { formatSramOption(); } +#endif IPC->adpcm.semaphore = false; @@ -2831,6 +3160,8 @@ int main(void) const char *argv[] = {"/scummvmds", "--config=scummvmf.ini"}; #elif defined(DS_BUILD_G) const char *argv[] = {"/scummvmds", "--config=scummvmg.ini"}; +#elif defined(DS_BUILD_H) + const char *argv[] = {"/scummvmds", "--config=scummvmh.ini"}; #endif while (1) { diff --git a/backends/platform/ds/arm9/source/dsmain.h b/backends/platform/ds/arm9/source/dsmain.h index 43258b5c5d..ab74554917 100644 --- a/backends/platform/ds/arm9/source/dsmain.h +++ b/backends/platform/ds/arm9/source/dsmain.h @@ -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(); diff --git a/backends/platform/ds/arm9/source/dsoptions.cpp b/backends/platform/ds/arm9/source/dsoptions.cpp index edb9c70580..2dbc4b842b 100644 --- a/backends/platform/ds/arm9/source/dsoptions.cpp +++ b/backends/platform/ds/arm9/source/dsoptions.cpp @@ -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; } } diff --git a/backends/platform/ds/arm9/source/dsoptions.h b/backends/platform/ds/arm9/source/dsoptions.h index 9cfa785ca8..e3ab2f55e0 100644 --- a/backends/platform/ds/arm9/source/dsoptions.h +++ b/backends/platform/ds/arm9/source/dsoptions.h @@ -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 diff --git a/backends/platform/ds/arm9/source/gbampsave.cpp b/backends/platform/ds/arm9/source/gbampsave.cpp index 9c8af81a6e..a53ab9739d 100644 --- a/backends/platform/ds/arm9/source/gbampsave.cpp +++ b/backends/platform/ds/arm9/source/gbampsave.cpp @@ -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]); } diff --git a/backends/platform/ds/arm9/source/gbampsave.h b/backends/platform/ds/arm9/source/gbampsave.h index d0cbc68bfd..6ddc4fd964 100644 --- a/backends/platform/ds/arm9/source/gbampsave.h +++ b/backends/platform/ds/arm9/source/gbampsave.h @@ -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(); diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp index 79b0c5390b..5ddcb50b15 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.cpp +++ b/backends/platform/ds/arm9/source/osystem_ds.cpp @@ -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,17 +154,44 @@ 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) { @@ -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; + u8* dest = ((u8 *) (bg)) + (dy * stride) + x; + u8* destSub = ((u8 *) (bgSub)) + (dy * 512) + x; + u8* src = (u8 *) buf + (pitch * by); + + 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 { - for (int dy = y; dy < y + h; dy++) { - u16* dest1 = bg + (dy * (stride >> 1)) + (x >> 1); - u16* dest2 = bgSub + (dy << 8) + (x >> 1); + + // 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(dest1, w << 1); - DC_FlushRange(dest2, w << 1); - - dmaCopyHalfWords(3, src, dest1, w); - dmaCopyHalfWords(3, src, dest2, w); - - src += pitch >> 1; - } - } + DC_FlushRange(src, w << 1); + DC_FlushRange(dest, w << 1); + dmaCopyHalfWords(3, src, dest, w); -// consolePrintf("Done\n"); + 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 } } diff --git a/backends/platform/ds/arm9/source/osystem_ds.h b/backends/platform/ds/arm9/source/osystem_ds.h index 8c8d661ad8..16c8f41491 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.h +++ b/backends/platform/ds/arm9/source/osystem_ds.h @@ -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[] = { diff --git a/backends/platform/ds/arm9/source/portdefs.h b/backends/platform/ds/arm9/source/portdefs.h index de7a5795f5..16f3d8cc9b 100644 --- a/backends/platform/ds/arm9/source/portdefs.h +++ b/backends/platform/ds/arm9/source/portdefs.h @@ -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" diff --git a/backends/platform/ds/arm9/source/ramsave.cpp b/backends/platform/ds/arm9/source/ramsave.cpp index be355ce76f..a9f4e3d2fc 100644 --- a/backends/platform/ds/arm9/source/ramsave.cpp +++ b/backends/platform/ds/arm9/source/ramsave.cpp @@ -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 diff --git a/backends/platform/ds/arm9/source/ramsave.h b/backends/platform/ds/arm9/source/ramsave.h index f919da18db..034e957b7f 100644 --- a/backends/platform/ds/arm9/source/ramsave.h +++ b/backends/platform/ds/arm9/source/ramsave.h @@ -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(); diff --git a/backends/platform/ds/arm9/source/touchkeyboard.cpp b/backends/platform/ds/arm9/source/touchkeyboard.cpp index 11832f4e3a..85f80fac92 100644 --- a/backends/platform/ds/arm9/source/touchkeyboard.cpp +++ b/backends/platform/ds/arm9/source/touchkeyboard.cpp @@ -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; diff --git a/backends/platform/ds/arm9/source/touchkeyboard.h b/backends/platform/ds/arm9/source/touchkeyboard.h index 8a5fc728ce..91efbc1e9a 100644 --- a/backends/platform/ds/arm9/source/touchkeyboard.h +++ b/backends/platform/ds/arm9/source/touchkeyboard.h @@ -40,6 +40,7 @@ bool getKeyboardClosed(); void addAutoComplete(char* word); void clearAutoComplete(); void setCharactersEntered(int count); +void releaseAllKeys(); } diff --git a/backends/platform/ds/logog.bmp b/backends/platform/ds/logog.bmp Binary files differnew file mode 100644 index 0000000000..9c194d3f82 --- /dev/null +++ b/backends/platform/ds/logog.bmp diff --git a/backends/platform/ds/makefile b/backends/platform/ds/makefile index 3fb19e939c..a9fbb13637 100644 --- a/backends/platform/ds/makefile +++ b/backends/platform/ds/makefile @@ -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 diff --git a/backends/platform/gp2x/gp2x.cpp b/backends/platform/gp2x/gp2x.cpp index c138f6c54d..e5f062ed35 100644 --- a/backends/platform/gp2x/gp2x.cpp +++ b/backends/platform/gp2x/gp2x.cpp @@ -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 diff --git a/backends/platform/iphone/iphone_keyboard.m b/backends/platform/iphone/iphone_keyboard.m index bd4948e30a..fda481933d 100644 --- a/backends/platform/iphone/iphone_keyboard.m +++ b/backends/platform/iphone/iphone_keyboard.m @@ -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; diff --git a/backends/platform/iphone/iphone_main.m b/backends/platform/iphone/iphone_main.m index b01e9f3f34..6b709b0803 100644 --- a/backends/platform/iphone/iphone_main.m +++ b/backends/platform/iphone/iphone_main.m @@ -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 { diff --git a/backends/platform/iphone/iphone_video.m b/backends/platform/iphone/iphone_video.m index 89f159c1d9..910f14ab58 100644 --- a/backends/platform/iphone/iphone_video.m +++ b/backends/platform/iphone/iphone_video.m @@ -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]; diff --git a/backends/platform/iphone/osys_iphone.cpp b/backends/platform/iphone/osys_iphone.cpp index fdef911d0a..521e91a87e 100644 --- a/backends/platform/iphone/osys_iphone.cpp +++ b/backends/platform/iphone/osys_iphone.cpp @@ -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,334 +687,436 @@ 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; - } + case kInputMouseUp: + 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; + case kInputKeyPressed: + handleEvent_keyPressed(event, (int)xUnit); + break; - 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 kInputSwipe: + if (!handleEvent_swipe(event, (int)xUnit)) + return false; 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; - } + default: + break; + } + + return true; + } + 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); - event.kbd.keycode = _queuedInputEvent.kbd.keycode = keycode; - event.kbd.ascii = _queuedInputEvent.kbd.ascii = 0; + 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; - break; - } + } 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; - default: - break; + } 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; +} - 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; } - return false; + + + 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() { @@ -1020,16 +1125,17 @@ void OSystem_IPHONE::suspendLoop() { 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); diff --git a/backends/platform/iphone/osys_iphone.h b/backends/platform/iphone/osys_iphone.h index af883a62c9..a9a3ddad65 100644 --- a/backends/platform/iphone/osys_iphone.h +++ b/backends/platform/iphone/osys_iphone.h @@ -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 diff --git a/backends/platform/null/null.cpp b/backends/platform/null/null.cpp index 463e9d7b2d..610f1d3a42 100644 --- a/backends/platform/null/null.cpp +++ b/backends/platform/null/null.cpp @@ -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(); } diff --git a/backends/platform/ps2/rawsavefile.cpp b/backends/platform/ps2/rawsavefile.cpp index 03270ea9ce..aa3cc57fe7 100644 --- a/backends/platform/ps2/rawsavefile.cpp +++ b/backends/platform/ps2/rawsavefile.cpp @@ -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; diff --git a/backends/platform/ps2/rawsavefile.h b/backends/platform/ps2/rawsavefile.h index b638d106ab..8e0dba4ab9 100644 --- a/backends/platform/ps2/rawsavefile.h +++ b/backends/platform/ps2/rawsavefile.h @@ -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 { diff --git a/backends/platform/ps2/savefile.cpp b/backends/platform/ps2/savefile.cpp index 5ee724cd3f..bfcaf0f57f 100644 --- a/backends/platform/ps2/savefile.cpp +++ b/backends/platform/ps2/savefile.cpp @@ -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; -} diff --git a/backends/platform/ps2/savefile.h b/backends/platform/ps2/savefile.h index 4832b8c3fe..0c0cf922f4 100644 --- a/backends/platform/ps2/savefile.h +++ b/backends/platform/ps2/savefile.h @@ -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__ diff --git a/backends/platform/psp/osys_psp.cpp b/backends/platform/psp/osys_psp.cpp index 6e9b5980d4..69be0abcb2 100644 --- a/backends/platform/psp/osys_psp.cpp +++ b/backends/platform/psp/osys_psp.cpp @@ -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); diff --git a/backends/platform/psp/osys_psp_gu.cpp b/backends/platform/psp/osys_psp_gu.cpp index 7e36fe6db0..1aa3bcd438 100644 --- a/backends/platform/psp/osys_psp_gu.cpp +++ b/backends/platform/psp/osys_psp_gu.cpp @@ -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); diff --git a/backends/platform/psp/portdefs.h b/backends/platform/psp/portdefs.h index af772230d7..1708a70c74 100644 --- a/backends/platform/psp/portdefs.h +++ b/backends/platform/psp/portdefs.h @@ -43,7 +43,6 @@ #include "trace.h" -#define SCUMMVM_SAVEPATH "ms0:/scummvm_savegames" #define BREAKPOINT asm("break\n") diff --git a/backends/platform/psp/psp_main.cpp b/backends/platform/psp/psp_main.cpp index d2ed59efbe..94ef63488d 100644 --- a/backends/platform/psp/psp_main.cpp +++ b/backends/platform/psp/psp_main.cpp @@ -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; diff --git a/backends/platform/sdl/events.cpp b/backends/platform/sdl/events.cpp index a4863d833b..c2edcf78fb 100644 --- a/backends/platform/sdl/events.cpp +++ b/backends/platform/sdl/events.cpp @@ -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"); diff --git a/backends/platform/sdl/graphics.cpp b/backends/platform/sdl/graphics.cpp index 4a5c143712..96b74ecba7 100644 --- a/backends/platform/sdl/graphics.cpp +++ b/backends/platform/sdl/graphics.cpp @@ -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; } } diff --git a/backends/platform/sdl/sdl.cpp b/backends/platform/sdl/sdl.cpp index a8655ef5fd..fdc1ba97f6 100644 --- a/backends/platform/sdl/sdl.cpp +++ b/backends/platform/sdl/sdl.cpp @@ -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); diff --git a/backends/platform/sdl/sdl.h b/backends/platform/sdl/sdl.h index 3fbfa8ba0d..3639d61c3a 100644 --- a/backends/platform/sdl/sdl.h +++ b/backends/platform/sdl/sdl.h @@ -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); diff --git a/backends/platform/symbian/AdaptAllMMPs.pl b/backends/platform/symbian/AdaptAllMMPs.pl index b576bb3993..d7b5642f1c 100644 --- a/backends/platform/symbian/AdaptAllMMPs.pl +++ b/backends/platform/symbian/AdaptAllMMPs.pl @@ -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 diff --git a/backends/platform/symbian/BuildPackageUpload_AllVersions.pl b/backends/platform/symbian/BuildPackageUpload_AllVersions.pl index 94edbf4fcf..ba8afe5084 100644 --- a/backends/platform/symbian/BuildPackageUpload_AllVersions.pl +++ b/backends/platform/symbian/BuildPackageUpload_AllVersions.pl @@ -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!"); diff --git a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl index 22846f45dd..8ba743674d 100644 --- a/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl +++ b/backends/platform/symbian/BuildPackageUpload_LocalSettings.pl @@ -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); ################################################################################################################## ## @@ -187,6 +174,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 ######################################################################################################### { print "ERROR: Computer name ".$ENV{'COMPUTERNAME'}." not recognized! Plz edit _LocalSettings.pl!"; @@ -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'} = ""; diff --git a/backends/platform/symbian/README b/backends/platform/symbian/README index 8ab729a4d0..1e011ec4a1 100644 --- a/backends/platform/symbian/README +++ b/backends/platform/symbian/README @@ -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 diff --git a/backends/platform/symbian/S60/ScummVM_S60.mmp.in b/backends/platform/symbian/S60/ScummVM_S60.mmp.in index 099b33ed95..35632d9c95 100644 --- a/backends/platform/symbian/S60/ScummVM_S60.mmp.in +++ b/backends/platform/symbian/S60/ScummVM_S60.mmp.in @@ -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 diff --git a/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v1.pkg b/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v1.pkg index bf3c69ae08..91649727df 100644 --- a/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v1.pkg +++ b/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v1.pkg @@ -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"} diff --git a/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v2.pkg b/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v2.pkg index 3afb7a094c..4547af0597 100644 --- a/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v2.pkg +++ b/backends/platform/symbian/S60/scummvm-CVS-SymbianS60v2.pkg @@ -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 diff --git a/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in b/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in index 3fea916e43..fae74a425a 100644 --- a/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in +++ b/backends/platform/symbian/S60v3/ScummVM_S60v3.mmp.in @@ -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 diff --git a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg index a7126db4c8..1898ac1b58 100644 --- a/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg +++ b/backends/platform/symbian/S60v3/scummvm-CVS-SymbianS60v3.pkg @@ -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 diff --git a/backends/platform/symbian/S80/ScummVM_S80.mmp.in b/backends/platform/symbian/S80/ScummVM_S80.mmp.in index 95879dd2af..1c8076fdc3 100644 --- a/backends/platform/symbian/S80/ScummVM_S80.mmp.in +++ b/backends/platform/symbian/S80/ScummVM_S80.mmp.in @@ -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 diff --git a/backends/platform/symbian/S80/scummvm-CVS-SymbianS80.pkg b/backends/platform/symbian/S80/scummvm-CVS-SymbianS80.pkg index 94d457b93a..c6b3e6f82f 100644 --- a/backends/platform/symbian/S80/scummvm-CVS-SymbianS80.pkg +++ b/backends/platform/symbian/S80/scummvm-CVS-SymbianS80.pkg @@ -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 diff --git a/backends/platform/symbian/S90/Scummvm_S90.mmp.in b/backends/platform/symbian/S90/Scummvm_S90.mmp.in index 47a3d9a1d4..8ace71b190 100644 --- a/backends/platform/symbian/S90/Scummvm_S90.mmp.in +++ b/backends/platform/symbian/S90/Scummvm_S90.mmp.in @@ -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 diff --git a/backends/platform/symbian/S90/scummvm-CVS-SymbianS90.pkg b/backends/platform/symbian/S90/scummvm-CVS-SymbianS90.pkg index ca7f08d85f..b578019979 100644 --- a/backends/platform/symbian/S90/scummvm-CVS-SymbianS90.pkg +++ b/backends/platform/symbian/S90/scummvm-CVS-SymbianS90.pkg @@ -28,7 +28,7 @@ ;&EN ; UID is the app's UID -#{"ScummVM S90"},(0x101f9b57),0,120,0 +#{"ScummVM S90"},(0x101f9b57),0,130,0 ; Platform type -- disabled: seems to be causing trouble ;(0x101FBE04), 0, 0, 0, {"Series90ProductID"} @@ -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 diff --git a/backends/platform/symbian/UIQ2/ScummVM_UIQ2.mmp.in b/backends/platform/symbian/UIQ2/ScummVM_UIQ2.mmp.in index e9dff7b94f..9fab248799 100644 --- a/backends/platform/symbian/UIQ2/ScummVM_UIQ2.mmp.in +++ b/backends/platform/symbian/UIQ2/ScummVM_UIQ2.mmp.in @@ -89,6 +89,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 diff --git a/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2.pkg b/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2.pkg index aca927eadd..a8b02d4099 100644 --- a/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2.pkg +++ b/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2.pkg @@ -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 UIQ2"},(0x101f9b57),0,100,0 +#{"ScummVM UIQ2"},(0x101f9b57),0,130,0 ; Platform type (0x101F617B), 2, 0, 0, {"UIQ20ProductID"} diff --git a/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2_SE.pkg b/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2_SE.pkg index ecca51bd26..2d08bd01b2 100644 --- a/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2_SE.pkg +++ b/backends/platform/symbian/UIQ2/scummvm-CVS-SymbianUIQ2_SE.pkg @@ -6,7 +6,7 @@ ;&EN ; UID is the app's UID -#{"ScummVM SE"},(0x101f9b57),0,110,0 +#{"ScummVM SE"},(0x101f9b57),0,130,0 ; Platform type (0x101F617B), 2, 0, 0, {"UIQ20ProductID"} diff --git a/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in b/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in index 0013d061ca..6053a72182 100644 --- a/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in +++ b/backends/platform/symbian/UIQ3/ScummVM_UIQ3.mmp.in @@ -51,7 +51,7 @@ LANG SC END EPOCSTACKSIZE 80000 -EPOCHEAPSIZE 3000000 64000000 +EPOCHEAPSIZE 5000000 64000000 START BITMAP ScummVM.mbm TARGETPATH \Resource\Apps @@ -117,6 +117,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 diff --git a/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg b/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg index 5d6ce01525..cdeb83f192 100644 --- a/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg +++ b/backends/platform/symbian/UIQ3/scummvm-CVS-SymbianUIQ3.pkg @@ -16,7 +16,7 @@ ; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ; ; $URL:$ -; $Id:$ +; $Id$ ; ; @@ -32,7 +32,7 @@ :"ScummVM" ; UID is the app's UID -#{"ScummVM UIQ3"},(0xA0000657),0,120,0 +#{"ScummVM UIQ3"},(0xA0000657),0,13,0 ; ProductID for UIQ 3.0 ; Product/platform version UID, Major, Minor, Build, Product ID @@ -61,6 +61,7 @@ "..\..\..\..\dists\engine-data\sky.cpt"-"c:\shared\scummvm\sky.cpt" "..\..\..\..\dists\engine-data\igor.tbl"-"c:\shared\scummvm\igor.tbl" "..\..\..\..\dists\engine-data\lure.dat"-"c:\shared\scummvm\lure.dat" +"..\..\..\..\dists\engine-data\drascula.dat"-"c:\shared\scummvm\drascula.dat" ; Config/log files: 'empty' will automagically be removed on uninstall ""-"c:\shared\scummvm\scummvm.ini",FILENULL diff --git a/backends/platform/symbian/mmp/scummvm_base.mmp.in b/backends/platform/symbian/mmp/scummvm_base.mmp.in index d1c8878d4b..3277e34ba3 100644 --- a/backends/platform/symbian/mmp/scummvm_base.mmp.in +++ b/backends/platform/symbian/mmp/scummvm_base.mmp.in @@ -85,7 +85,6 @@ SOURCEPATH ..\..\..\..\gui //SOURCE KeysDialog.cpp //SOURCE Actions.cpp - SOURCEPATH ..\..\..\..\sound //START_AUTO_OBJECTS_SOUND_// @@ -108,7 +107,8 @@ SOURCE backends\saves\savefile.cpp SOURCE backends\saves\default\default-saves.cpp SOURCE backends\saves\compressed\compressed-saves.cpp SOURCE engines\engine.cpp - - -// backend specific includes +SOURCE engines\dialogs.cpp +SOURCE backends\fs\abstract-fs.cpp +SOURCE backends\fs\symbian\symbianstream.cpp // backend specific includes + diff --git a/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in b/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in new file mode 100644 index 0000000000..3f68ec086e --- /dev/null +++ b/backends/platform/symbian/mmp/scummvm_tinsel.mmp.in @@ -0,0 +1,56 @@ +/* ScummVM - Scumm Interpreter + * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL + * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System + * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer + * Copyright (C) 2005-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. + * + */ + +// +// EPOC MMP makefile project for ScummVM +// + +// *** Definitions + +TARGET scummvm_tinsel.lib +TARGETTYPE lib +OPTION MSVC /QIfist /Ob1 /Oy /GF // /QIfist disables use of __ftol2 to avoid linker probs with MS libc: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vcrefQIfistSuppress_ftol.asp +OPTION GCC -Wno-multichar -Wno-reorder // don't optimize for ARM, platform way too sensitive for that :( just turn off some common warnings +OPTION GCCE -Wno-multichar -Wno-reorder -Wno-unused -Wno-format -fsigned-char +ALWAYS_BUILD_AS_ARM + +//START_AUTO_MACROS_SLAVE// + +// empty base file, will be updated by Perl build scripts + +//STOP_AUTO_MACROS_SLAVE// + +// *** SOURCE files + +SOURCEPATH ..\..\..\..\engines\tinsel + +//START_AUTO_OBJECTS_TINSEL_// + + // empty base file, will be updated by Perl build scripts + +//STOP_AUTO_OBJECTS_TINSEL_// + +// *** Include paths + +USERINCLUDE ..\..\..\..\engines +USERINCLUDE ..\..\..\.. ..\..\..\..\common ..\..\..\..\gui ..\..\..\..\sound ..\src +SYSTEMINCLUDE \epoc32\include \epoc32\include\libc ..\src diff --git a/backends/platform/symbian/src/SymbianActions.cpp b/backends/platform/symbian/src/SymbianActions.cpp index 8fc35e9f8d..e71b242329 100644 --- a/backends/platform/symbian/src/SymbianActions.cpp +++ b/backends/platform/symbian/src/SymbianActions.cpp @@ -129,17 +129,20 @@ void SymbianActions::initInstanceGame() { bool is_simon = (strncmp(gameid.c_str(), "simon", 5) == 0); bool is_sword1 = (gameid == "sword1"); bool is_sword2 = (strcmp(gameid.c_str(), "sword2") == 0); - bool is_sky = (strncmp(gameid.c_str(), "sky", 3) == 0); - bool is_saga = (gameid == "saga"); + bool is_queen = (gameid == "queen"); + bool is_sky = (gameid == "sky"); bool is_comi = (strncmp(gameid.c_str(), "comi", 4) == 0); - bool is_queen = (strncmp(gameid.c_str(), "queen", 5) == 0); bool is_gob = (strncmp(gameid.c_str(), "gob", 3) == 0); - bool is_kyra = (gameid == "kyra1"); + bool is_saga = (gameid == "saga"); + bool is_kyra = (strncmp(gameid.c_str(), "kyra",4) == 0); bool is_samnmax = (gameid == "samnmax"); bool is_cine = (gameid == "cine"); bool is_touche = (gameid == "touche"); bool is_agi = (gameid == "agi"); bool is_parallaction = (gameid == "parallaction"); + bool is_lure = (gameid == "lure"); + bool is_feeble = (gameid == "feeble"); + bool is_drascula = (strncmp(gameid.c_str(), "drascula",8) == 0); Actions::initInstanceGame(); @@ -150,16 +153,16 @@ void SymbianActions::initInstanceGame() { // Save - if (is_simon || is_sword2 || is_gob || is_kyra || is_touche) + if (is_simon || is_sword2 || is_gob || is_kyra || is_feeble) _action_enabled[ACTION_SAVE] = false; else { _action_enabled[ACTION_SAVE] = true; if (is_queen) { - _key_action[ACTION_SAVE].setKey(Common::ASCII_F5, Common::KEYCODE_F5); // F1 key for FOTAQ + _key_action[ACTION_SAVE].setKey(Common::ASCII_F1, Common::KEYCODE_F1); // F1 key for FOTAQ } else if (is_sky) { _key_action[ACTION_SAVE].setKey(Common::ASCII_F5, Common::KEYCODE_F5); - } else if (is_cine) { + } else if (is_cine || is_drascula) { _key_action[ACTION_SAVE].setKey(Common::ASCII_F10, Common::KEYCODE_F10); // F10 } else if (is_agi) { _key_action[ACTION_SAVE].setKey(Common::ASCII_ESCAPE, Common::KEYCODE_ESCAPE); @@ -175,7 +178,8 @@ void SymbianActions::initInstanceGame() { // Skip text if (!is_cine && !is_parallaction) _action_enabled[ACTION_SKIP_TEXT] = true; - if (is_simon || is_sky || is_sword2 || is_queen || is_sword1 || is_gob || is_saga || is_kyra || is_touche) + if (is_simon || is_sky || is_sword2 || is_queen || is_sword1 || is_gob || + is_saga || is_kyra || is_touche || is_lure || is_feeble || is_drascula) _key_action[ACTION_SKIP_TEXT].setKey(Common::KEYCODE_ESCAPE, Common::KEYCODE_ESCAPE); // Escape key else { _key_action[ACTION_SKIP_TEXT].setKey(SDLK_PERIOD); diff --git a/backends/platform/symbian/src/SymbianOS.cpp b/backends/platform/symbian/src/SymbianOS.cpp index e3a4027d79..23876c5ec1 100644 --- a/backends/platform/symbian/src/SymbianOS.cpp +++ b/backends/platform/symbian/src/SymbianOS.cpp @@ -24,12 +24,15 @@ #include <eikenv.h> // for CEikonEnv::Static() @ Symbian::FatalError() #include <sdlapp.h> // for CSDLApp::GetExecutablePathCStr() @ Symbian::GetExecutablePath() +#include <bautils.h> #include "backends/fs/symbian/symbian-fs-factory.h" #include "backends/platform/symbian/src/SymbianOS.h" #include "backends/platform/symbian/src/SymbianActions.h" +#include "backends/saves/default/default-saves.h" #include "common/config-manager.h" #include "common/events.h" +#include "common/file.h" #include "gui/Actions.h" #include "gui/Key.h" #include "gui/message.h" @@ -42,14 +45,9 @@ #define SAMPLES_PER_SEC 16000 #endif -#define KInputBufferLength 128 -// Symbian libc file functionality in order to provide shared file handles -struct TSymbianFileEntry { - RFile iFileHandle; - char iInputBuffer[KInputBufferLength]; - TInt iInputBufferLen; - TInt iInputPos; -}; + +#define DEFAULT_CONFIG_FILE "scummvm.ini" +#define DEFAULT_SAVE_PATH "Savegames" #define FILE void @@ -118,8 +116,21 @@ void OSystem_SDL_Symbian::setFeatureState(Feature f, bool enable) { } } -FilesystemFactory *OSystem_SDL_Symbian::getFilesystemFactory() { - return &SymbianFilesystemFactory::instance(); +static Common::String getDefaultConfigFileName() { + char configFile[MAXPATHLEN]; + strcpy(configFile, Symbian::GetExecutablePath()); + strcat(configFile, DEFAULT_CONFIG_FILE); + return configFile; +} + +Common::SeekableReadStream *OSystem_SDL_Symbian::openConfigFileForReading() { + Common::FilesystemNode file(getDefaultConfigFileName()); + return file.openForReading(); +} + +Common::WriteStream *OSystem_SDL_Symbian::openConfigFileForWriting() { + Common::FilesystemNode file(getDefaultConfigFileName()); + return file.openForWriting(); } OSystem_SDL_Symbian::zoneDesc OSystem_SDL_Symbian::_zones[TOTAL_ZONES] = { @@ -128,10 +139,33 @@ OSystem_SDL_Symbian::zoneDesc OSystem_SDL_Symbian::_zones[TOTAL_ZONES] = { { 150, 145, 170, 55 } }; OSystem_SDL_Symbian::OSystem_SDL_Symbian() :_channels(0),_stereo_mix_buffer(0) { + _RFs = &CEikonEnv::Static()->FsSession(); + _fsFactory = new SymbianFilesystemFactory(); } void OSystem_SDL_Symbian::initBackend() { + // First set the extrapath (for installed dat files etc) ConfMan.set("extrapath", Symbian::GetExecutablePath()); + + // Calculate the default savepath + Common::String savePath; + savePath = Symbian::GetExecutablePath(); + savePath += DEFAULT_SAVE_PATH "\\"; + _savefile = new DefaultSaveFileManager(savePath); + + // If savepath has not already been set then set it + if (!ConfMan.hasKey("savepath")) { + ConfMan.set("savepath", savePath); + + } + + // Ensure that the current set path (might have been altered by the user) exists + Common::String currentPath = ConfMan.get("savepath"); + TFileName fname; + TPtrC8 ptr((const unsigned char*)currentPath.c_str(),currentPath.size()); + fname.Copy(ptr); + BaflUtils::EnsurePathExistsL(static_cast<OSystem_SDL_Symbian*>(g_system)->FsSession(), fname); + ConfMan.setBool("FM_high_quality", false); #if !defined(S60) || defined(S60V3) // S60 has low quality as default ConfMan.setBool("FM_medium_quality", true); @@ -455,223 +489,60 @@ void OSystem_SDL_Symbian::initZones() { } } -FILE* symbian_fopen(const char* name, const char* mode) { - TSymbianFileEntry* fileEntry = new TSymbianFileEntry; - fileEntry->iInputPos = KErrNotFound; - - 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->iFileHandle.Open(CEikonEnv::Static()->FsSession(), tempFileName, fileMode) != KErrNone) { - if (fileEntry->iFileHandle.Create(CEikonEnv::Static()->FsSession(), tempFileName, fileMode) != KErrNone) { - delete fileEntry; - fileEntry = NULL; - } - } - break; - case 'r': - if (fileEntry->iFileHandle.Open(CEikonEnv::Static()->FsSession(), tempFileName, fileMode) != KErrNone) { - delete fileEntry; - fileEntry = NULL; - } - break; - - case 'w': - if (fileEntry->iFileHandle.Replace(CEikonEnv::Static()->FsSession(), tempFileName, fileMode) != KErrNone) { - delete fileEntry; - fileEntry = NULL; - } - break; - } - } - return (FILE*) fileEntry; -} - -void symbian_fclose(FILE* handle) { - ((TSymbianFileEntry*)(handle))->iFileHandle.Close(); - - delete (TSymbianFileEntry*)(handle); +RFs& OSystem_SDL_Symbian::FsSession() { + return *_RFs; } -size_t symbian_fread(const void* ptr, size_t size, size_t numItems, FILE* 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->iInputPos != KErrNotFound) - { - TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer+entry->iInputPos, entry->iInputBufferLen - entry->iInputPos, KInputBufferLength); - pointer.Append(cacheBuffer); - entry->iInputPos = KErrNotFound; - totLength+=pointer.Length(); - pointer.Set(totLength+(unsigned char*) ptr, 0, totsize-totLength); - } - - entry->iFileHandle.Read(pointer); - totLength+=pointer.Length(); - - pointer.Set((unsigned char*) ptr, totLength, totsize); - +// Symbian bsearch implementation is flawed +void* scumm_bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) { + // Perform binary search + size_t lo = 0; + size_t hi = nmemb; + while (lo < hi) { + size_t mid = (lo + hi) / 2; + const void *p = ((const char *)base) + mid * size; + int tmp = (*compar)(key, p); + if (tmp < 0) + hi = mid; + else if (tmp > 0) + lo = mid + 1; + else + return (void *)p; } - else { - // Nothing in buffer - if(entry->iInputPos == KErrNotFound) { - TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer, KInputBufferLength); - entry->iFileHandle.Read(cacheBuffer); - - if(cacheBuffer.Length() >= totsize) { - pointer.Copy(cacheBuffer.Left(totsize)); - entry->iInputPos = totsize; - entry->iInputBufferLen = cacheBuffer.Length(); - } - else { - pointer.Copy(cacheBuffer); - entry->iInputPos = KErrNotFound; - } - - } - else { - TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer, entry->iInputBufferLen, KInputBufferLength); - if(entry->iInputPos+totsize < entry->iInputBufferLen) { - pointer.Copy(cacheBuffer.Mid(entry->iInputPos, totsize)); - entry->iInputPos+=totsize; - } - else { - - pointer.Copy(cacheBuffer.Mid(entry->iInputPos, entry->iInputBufferLen-entry->iInputPos)); - cacheBuffer.SetLength(0); - entry->iFileHandle.Read(cacheBuffer); - - if(cacheBuffer.Length() >= totsize-pointer.Length()) { - TUint32 restSize = totsize-pointer.Length(); - pointer.Append(cacheBuffer.Left(restSize)); - entry->iInputPos = restSize; - entry->iInputBufferLen = cacheBuffer.Length(); - } - else { - pointer.Append(cacheBuffer); - entry->iInputPos = KErrNotFound; - } - } - } - } - - return pointer.Length()/size; -} - -size_t symbian_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) { - TPtrC8 pointer( (unsigned char*) ptr, size*numItems); - - ((TSymbianFileEntry*)(handle))->iInputPos = KErrNotFound; - if (((TSymbianFileEntry*)(handle))->iFileHandle.Write(pointer) == KErrNone) { - return numItems; - } - - return 0; + return NULL; } -bool symbian_feof(FILE* handle) { - TInt pos = 0; - TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle)); - - if (entry->iFileHandle.Seek(ESeekCurrent, pos) == KErrNone) { - - TInt size = 0; - if (entry->iFileHandle.Size(size) == KErrNone) { - if(entry->iInputPos == KErrNotFound && pos == size) - return true; - - if(entry->iInputPos != KErrNotFound && pos == size && entry->iInputPos == entry->iInputBufferLen) - return true; - - return false; - } - } - return true; -} - -long int symbian_ftell(FILE* handle) { - TInt pos = 0; - TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle)); - - entry->iFileHandle.Seek(ESeekCurrent, pos); - if(entry->iInputPos != KErrNotFound) - { - pos+=(entry->iInputPos - entry->iInputBufferLen); - } - return pos; -} - -int symbian_fseek(FILE* handle, long int offset, int whence) { - - TSeek seekMode = ESeekStart; - TInt pos = offset; - TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle)); - - switch(whence) { - case SEEK_SET: - seekMode = ESeekStart; - break; - case SEEK_CUR: - seekMode = ESeekCurrent; - if(entry->iInputPos != KErrNotFound) { - pos+=(entry->iInputPos - entry->iInputBufferLen); - } - break; - case SEEK_END: - seekMode = ESeekEnd; - break; - - } - - entry->iInputPos = KErrNotFound; - - return entry->iFileHandle.Seek(seekMode, pos); -} - -void symbian_clearerr(FILE* /*handle*/) { +extern "C" +{ +// Include the snprintf and vsnprintf implementations as 'C' code +#include "vsnprintf.h" } /** Vibration support */ #ifdef USE_VIBRA_SE_PXXX void OSystem_SDL_Symbian::initializeVibration() { - _vibrationApi = SonyEricsson::CVibration::NewL(); +#ifdef UIQ3 +#else +#endif } void OSystem_SDL_Symbian::vibrationOn(int vibraLength) { - // initialize? +#ifdef UIQ3 + // initialize? if (!_vibrationApi) _vibrationApi = SonyEricsson::CVibration::NewL(); // do it! _vibrationApi->VibrationOn(1, 1, vibraLength); +#else + +#endif } void OSystem_SDL_Symbian::vibrationOff() { +#ifdef UIQ3 +#else _vibrationApi->VibrationOff(); +#endif } #endif // USE_SE_PXX_VIBRA diff --git a/backends/platform/symbian/src/SymbianOS.h b/backends/platform/symbian/src/SymbianOS.h index 71d24f6286..03d7fb972c 100644 --- a/backends/platform/symbian/src/SymbianOS.h +++ b/backends/platform/symbian/src/SymbianOS.h @@ -27,12 +27,8 @@ #include "backends/platform/sdl/sdl.h" -/** Vibration support */ -#ifdef USE_VIBRA_SE_PXXX -#include <vibration.h> -#endif - #define TOTAL_ZONES 3 +class RFs; class OSystem_SDL_Symbian : public OSystem_SDL { public: @@ -62,6 +58,9 @@ public: // Overloaded from SDL_Commmon void quit(); + + // Returns reference to File session + RFs& FsSession(); protected: // // The mixer callback function, passed on to OSystem::setSoundCallback(). @@ -70,7 +69,9 @@ protected: // static void symbianMixCallback(void *s, byte *samples, int len); - virtual FilesystemFactory *getFilesystemFactory(); + + virtual Common::SeekableReadStream *openConfigFileForReading(); + virtual Common::WriteStream *openConfigFileForWriting(); public: // vibration support #ifdef USE_VIBRA_SE_PXXX @@ -131,6 +132,7 @@ protected: } zoneDesc; static zoneDesc _zones[TOTAL_ZONES]; + RFs* _RFs; }; #endif diff --git a/backends/platform/symbian/src/main_features.inl b/backends/platform/symbian/src/main_features.inl deleted file mode 100644 index f572ddb3dd..0000000000 --- a/backends/platform/symbian/src/main_features.inl +++ /dev/null @@ -1,93 +0,0 @@ -/* ScummVM - Scumm Interpreter - * Copyright (C) 2003-2005 Andreas 'Sprawl' Karlsson - Original EPOC port, ESDL - * Copyright (C) 2003-2005 Lars 'AnotherGuest' Persson - Original EPOC port, Audio System - * Copyright (C) 2005 Jurgen 'SumthinWicked' Braam - EPOC/CVS maintainer - * Copyright (C) 2005-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. - * - */ - -#ifdef USE_VIBRA_SE_PXXX - "Vibra " -#endif - "\n" - -// we want a list of supported engines visible in the program, -// because we also release special builds with only one engine -#ifndef DISABLE_SCUMM - "SCUMM " -#endif -#ifndef DISABLE_AGOS - "AGOS " -#endif -#ifndef DISABLE_SKY - "Sky " -#endif -#ifndef DISABLE_QUEEN - "Queen " -#endif -#ifndef DISABLE_GOB - "Gob " -#endif -#ifndef DISABLE_SAGA - "Saga " -#endif -#ifndef DISABLE_KYRA - "Kyra " -#endif -#ifndef DISABLE_SWORD1 - "Sword1 " -#endif -#ifndef DISABLE_SWORD2 - "Sword2 " -#endif -#ifndef DISABLE_CINE - "Cine " -#endif -#ifndef DISABLE_LURE - "Lure " -#endif -#ifndef DISABLE_AGI - "AGI " -#endif -#ifndef DISABLE_TOUCHE - "Touche " -#endif -#ifndef DISABLE_DRASCULA - "Drascula " -#endif -#ifndef DISABLE_IGOR - "Igor " -#endif -#ifndef DISABLE_PARALLACTION - "Parallaction " -#endif -#ifndef DISABLE_CRUISE - "Cruise " -#endif -#ifndef DISABLE_MADE - "MADE " -#endif - -#ifndef DISABLE_M4 - "M4 " -#endif - - - - - - diff --git a/backends/platform/symbian/src/portdefs.h b/backends/platform/symbian/src/portdefs.h index 06a4cf374c..ab8333c986 100644 --- a/backends/platform/symbian/src/portdefs.h +++ b/backends/platform/symbian/src/portdefs.h @@ -35,9 +35,6 @@ #include <e32std.h> #include <math.h> -//#define DISABLE_SCALERS // we only need 1x -//#define DISABLE_HQ_SCALERS - #if defined(USE_TREMOR) && !defined(USE_VORBIS) #define USE_VORBIS // make sure this one is defined together with USE_TREMOR! #endif @@ -107,51 +104,31 @@ */ #elif defined (__WINS__) // WINS + extern "C" int symbian_snprintf(char *text, size_t maxlen, const char *fmt, ...); + extern "C" int symbian_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap); + #define snprintf(buf,len,args...) symbian_snprintf(buf,len,args) + #define vsnprintf(buf,len,format,valist) symbian_vsnprintf(buf,len,format,valist) - // let's just blatantly ignore this for now and just get it to work :P but does n't work from the debug function - int inline scumm_snprintf (char *str, unsigned long /*n*/, char const *fmt, ...) { - va_list args; - va_start(args, fmt); - vsprintf(str, fmt, args); - va_end(args); - return strlen(str); - } - - int inline scumm_vsnprintf (char *str, unsigned long /*n*/, char const *fmt, va_list valist) { - vsprintf(str, fmt, valist); - return strlen(str); - } - - #define snprintf scumm_snprintf - #define vsnprintf scumm_vsnprintf void* symbian_malloc (size_t _size); #define malloc symbian_malloc #else // GCCE and the rest - #define snprintf(buf,len,args...) sprintf(buf,args) - #define vsnprintf(buf,len,format,valist) vsprintf(buf,format,valist) + extern "C" int symbian_snprintf(char *text, size_t maxlen, const char *fmt, ...); + extern "C" int symbian_vsnprintf(char *text, size_t maxlen, const char *fmt, va_list ap); + #define snprintf(buf,len,args...) symbian_snprintf(buf,len,args) + #define vsnprintf(buf,len,format,valist) symbian_vsnprintf(buf,len,format,valist) #endif #ifndef __WINS__ #define USE_ARM_GFX_ASM -#define ARM_USE_GFX_ASM #define USE_ARM_SMUSH_ASM #define USE_ARM_COSTUME_ASM #define USE_ARM_SOUND_ASM #endif -// somehow nobody has this function... -#define hypot(a, b) sqrt((a)*(a) + (b)*(b)) // Symbian bsearch implementation is flawed -void inline *scumm_bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)) { - size_t i; - - for (i=0; i < nmemb; i++) - if (compar(key, (void *)((size_t)base + size * i)) == 0) - return (void *)((size_t)base + size * i); - return NULL; -} -#define bsearch scumm_bsearch +void *scumm_bsearch(const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); +#define bsearch scumm_bsearch // we cannot include SymbianOS.h everywhere, but this works too (functions code is in SymbianOS.cpp) namespace Symbian { diff --git a/backends/platform/symbian/src/vsnprintf.h b/backends/platform/symbian/src/vsnprintf.h new file mode 100644 index 0000000000..5ed04b1980 --- /dev/null +++ b/backends/platform/symbian/src/vsnprintf.h @@ -0,0 +1,668 @@ +/* + * This is the vsnprintf for scummvm/symbian implementation from the original snprintf.c, + * all support functions has been removed and vsnprintf renamed to symbian_vsnprintf + * snprintf.c - a portable implementation of snprintf + * According to the homepage this function could be licensed as either Frontier Aritistic or GPL. + * + * AUTHOR + * Mark Martinec <mark.martinec@ijs.si>, April 1999. + * + * Copyright 1999, Mark Martinec. All rights reserved. + * + * TERMS AND CONDITIONS + * This program is free software; you can redistribute it and/or modify + * it under the terms of the "Frontier Artistic License" which comes + * with this Kit. + * + * 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 Frontier Artistic License for more details. + * + * You should have received a copy of the Frontier Artistic License + * with this Kit in the file named LICENSE.txt . + * If not, I'll be glad to provide one. + * + * FEATURES + * - careful adherence to specs regarding flags, field width and precision; + * - good performance for large string handling (large format, large + * argument or large paddings). Performance is similar to system's sprintf + * and in several cases significantly better (make sure you compile with + * optimizations turned on, tell the compiler the code is strict ANSI + * if necessary to give it more freedom for optimizations); + * - return value semantics per ISO/IEC 9899:1999 ("ISO C99"); + * - written in standard ISO/ANSI C - requires an ANSI C compiler. + * + * SUPPORTED CONVERSION SPECIFIERS AND DATA TYPES + * + * This snprintf only supports the following conversion specifiers: + * s, c, d, u, o, x, X, p (and synonyms: i, D, U, O - see below) + * with flags: '-', '+', ' ', '0' and '#'. + * An asterisk is supported for field width as well as precision. + * + * Length modifiers 'h' (short int), 'l' (long int), + * and 'll' (long long int) are supported. + * NOTE: + * If macro SNPRINTF_LONGLONG_SUPPORT is not defined (default) the + * length modifier 'll' is recognized but treated the same as 'l', + * which may cause argument value truncation! Defining + * SNPRINTF_LONGLONG_SUPPORT requires that your system's sprintf also + * handles length modifier 'll'. long long int is a language extension + * which may not be portable. + * + * Conversion of numeric data (conversion specifiers d, u, o, x, X, p) + * with length modifiers (none or h, l, ll) is left to the system routine + * sprintf, but all handling of flags, field width and precision as well as + * c and s conversions is done very carefully by this portable routine. + * If a string precision (truncation) is specified (e.g. %.8s) it is + * guaranteed the string beyond the specified precision will not be referenced. + * + * Length modifiers h, l and ll are ignored for c and s conversions (data + * types wint_t and wchar_t are not supported). + * + * The following common synonyms for conversion characters are supported: + * - i is a synonym for d + * - D is a synonym for ld, explicit length modifiers are ignored + * - U is a synonym for lu, explicit length modifiers are ignored + * - O is a synonym for lo, explicit length modifiers are ignored + * The D, O and U conversion characters are nonstandard, they are supported + * for backward compatibility only, and should not be used for new code. + * + * The following is specifically NOT supported: + * - flag ' (thousands' grouping character) is recognized but ignored + * - numeric conversion specifiers: f, e, E, g, G and synonym F, + * as well as the new a and A conversion specifiers + * - length modifier 'L' (long double) and 'q' (quad - use 'll' instead) + * - wide character/string conversions: lc, ls, and nonstandard + * synonyms C and S + * - writeback of converted string length: conversion character n + * - the n$ specification for direct reference to n-th argument + * - locales + * + * It is permitted for str_m to be zero, and it is permitted to specify NULL + * pointer for resulting string argument if str_m is zero (as per ISO C99). + * + * The return value is the number of characters which would be generated + * for the given input, excluding the trailing null. If this value + * is greater or equal to str_m, not all characters from the result + * have been stored in str, output bytes beyond the (str_m-1) -th character + * are discarded. If str_m is greater than zero it is guaranteed + * the resulting string will be null-terminated. + * + * NOTE that this matches the ISO C99, OpenBSD, and GNU C library 2.1, + * but is different from some older and vendor implementations, + * and is also different from XPG, XSH5, SUSv2 specifications. + * For historical discussion on changes in the semantics and standards + * of snprintf see printf(3) man page in the Linux programmers manual. + * + * Routines asprintf and vasprintf return a pointer (in the ptr argument) + * to a buffer sufficiently large to hold the resulting string. This pointer + * should be passed to free(3) to release the allocated storage when it is + * no longer needed. If sufficient space cannot be allocated, these functions + * will return -1 and set ptr to be a NULL pointer. These two routines are a + * GNU C library extensions (glibc). + * + * Routines asnprintf and vasnprintf are similar to asprintf and vasprintf, + * yet, like snprintf and vsnprintf counterparts, will write at most str_m-1 + * characters into the allocated output string, the last character in the + * allocated buffer then gets the terminating null. If the formatted string + * length (the return value) is greater than or equal to the str_m argument, + * the resulting string was truncated and some of the formatted characters + * were discarded. These routines present a handy way to limit the amount + * of allocated memory to some sane value. + * + * AVAILABILITY + * http://www.ijs.si/software/snprintf/ + * + * REVISION HISTORY + * 1999-04 V0.9 Mark Martinec + * - initial version, some modifications after comparing printf + * man pages for Digital Unix 4.0, Solaris 2.6 and HPUX 10, + * and checking how Perl handles sprintf (differently!); + * 1999-04-09 V1.0 Mark Martinec <mark.martinec@ijs.si> + * - added main test program, fixed remaining inconsistencies, + * added optional (long long int) support; + * 1999-04-12 V1.1 Mark Martinec <mark.martinec@ijs.si> + * - support the 'p' conversion (pointer to void); + * - if a string precision is specified + * make sure the string beyond the specified precision + * will not be referenced (e.g. by strlen); + * 1999-04-13 V1.2 Mark Martinec <mark.martinec@ijs.si> + * - support synonyms %D=%ld, %U=%lu, %O=%lo; + * - speed up the case of long format string with few conversions; + * 1999-06-30 V1.3 Mark Martinec <mark.martinec@ijs.si> + * - fixed runaway loop (eventually crashing when str_l wraps + * beyond 2^31) while copying format string without + * conversion specifiers to a buffer that is too short + * (thanks to Edwin Young <edwiny@autonomy.com> for + * spotting the problem); + * - added macros PORTABLE_SNPRINTF_VERSION_(MAJOR|MINOR) + * to snprintf.h + * 2000-02-14 V2.0 (never released) Mark Martinec <mark.martinec@ijs.si> + * - relaxed license terms: The Artistic License now applies. + * You may still apply the GNU GENERAL PUBLIC LICENSE + * as was distributed with previous versions, if you prefer; + * - changed REVISION HISTORY dates to use ISO 8601 date format; + * - added vsnprintf (patch also independently proposed by + * Caolan McNamara 2000-05-04, and Keith M Willenson 2000-06-01) + * 2000-06-27 V2.1 Mark Martinec <mark.martinec@ijs.si> + * - removed POSIX check for str_m<1; value 0 for str_m is + * allowed by ISO C99 (and GNU C library 2.1) - (pointed out + * on 2000-05-04 by Caolan McNamara, caolan@ csn dot ul dot ie). + * Besides relaxed license this change in standards adherence + * is the main reason to bump up the major version number; + * - added nonstandard routines asnprintf, vasnprintf, asprintf, + * vasprintf that dynamically allocate storage for the + * resulting string; these routines are not compiled by default, + * see comments where NEED_V?ASN?PRINTF macros are defined; + * - autoconf contributed by Caolan McNamara + * 2000-10-06 V2.2 Mark Martinec <mark.martinec@ijs.si> + * - BUG FIX: the %c conversion used a temporary variable + * that was no longer in scope when referenced, + * possibly causing incorrect resulting character; + * - BUG FIX: make precision and minimal field width unsigned + * to handle huge values (2^31 <= n < 2^32) correctly; + * also be more careful in the use of signed/unsigned/size_t + * internal variables - probably more careful than many + * vendor implementations, but there may still be a case + * where huge values of str_m, precision or minimal field + * could cause incorrect behaviour; + * - use separate variables for signed/unsigned arguments, + * and for short/int, long, and long long argument lengths + * to avoid possible incompatibilities on certain + * computer architectures. Also use separate variable + * arg_sign to hold sign of a numeric argument, + * to make code more transparent; + * - some fiddling with zero padding and "0x" to make it + * Linux compatible; + * - systematically use macros fast_memcpy and fast_memset + * instead of case-by-case hand optimization; determine some + * breakeven string lengths for different architectures; + * - terminology change: 'format' -> 'conversion specifier', + * 'C9x' -> 'ISO/IEC 9899:1999 ("ISO C99")', + * 'alternative form' -> 'alternate form', + * 'data type modifier' -> 'length modifier'; + * - several comments rephrased and new ones added; + * - make compiler not complain about 'credits' defined but + * not used; + */ +/* ============================================= */ +/* NO USER SERVICABLE PARTS FOLLOWING THIS POINT */ +/* ============================================= */ + +#define PORTABLE_SNPRINTF_VERSION_MAJOR 2 +#define PORTABLE_SNPRINTF_VERSION_MINOR 2 +#include <sys/types.h> +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <errno.h> +#ifdef isdigit +#undef isdigit +#endif +#define isdigit(c) ((c) >= '0' && (c) <= '9') + +#ifndef breakeven_point +# define breakeven_point 6 /* some reasonable one-size-fits-all value */ +#endif + +#define fast_memcpy(d,s,n) \ +{ register size_t nn = (size_t)(n); \ + if (nn >= breakeven_point) memcpy((d), (s), nn); \ + else if (nn > 0) { /* proc call overhead is worth only for large strings*/\ + register char *dd; register const char *ss; \ +for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } } + +#define fast_memset(d,c,n) \ +{ register size_t nn = (size_t)(n); \ + if (nn >= breakeven_point) memset((d), (int)(c), nn); \ + else if (nn > 0) { /* proc call overhead is worth only for large strings*/\ + register char *dd; register const int cc=(int)(c); \ +for (dd=(d); nn>0; nn--) *dd++ = cc; } } + + +/* declarations */ + +static char credits[] = "\n\ +@(#)snprintf.c, v2.2: Mark Martinec, <mark.martinec@ijs.si>\n\ +@(#)snprintf.c, v2.2: Copyright 1999, Mark Martinec. Frontier Artistic License applies.\n\ +@(#)snprintf.c, v2.2: http://www.ijs.si/software/snprintf/\n"; +int symbian_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) { + + size_t str_l = 0; + const char *p = fmt; + + /* In contrast with POSIX, the ISO C99 now says + * that str can be NULL and str_m can be 0. + * This is more useful than the old: if (str_m < 1) return -1; */ + + if (!p) p = ""; + while (*p) { + if (*p != '%') { + /* if (str_l < str_m) str[str_l++] = *p++; -- this would be sufficient */ + /* but the following code achieves better performance for cases + * where format string is long and contains few conversions */ + const char *q = strchr(p+1,'%'); + size_t n = !q ? strlen(p) : (q-p); + if (str_l < str_m) { + size_t avail = str_m-str_l; + fast_memcpy(str+str_l, p, (n>avail?avail:n)); + } + p += n; str_l += n; + } else { + const char *starting_p; + size_t min_field_width = 0, precision = 0; + int zero_padding = 0, precision_specified = 0, justify_left = 0; + int alternate_form = 0, force_sign = 0; + int space_for_positive = 1; /* If both the ' ' and '+' flags appear, + the ' ' flag should be ignored. */ + char length_modifier = '\0'; /* allowed values: \0, h, l, L */ + char tmp[32];/* temporary buffer for simple numeric->string conversion */ + + const char *str_arg; /* string address in case of string argument */ + size_t str_arg_l; /* natural field width of arg without padding + and sign */ + unsigned char uchar_arg; + /* unsigned char argument value - only defined for c conversion. + N.B. standard explicitly states the char argument for + the c conversion is unsigned */ + + size_t number_of_zeros_to_pad = 0; + /* number of zeros to be inserted for numeric conversions + as required by the precision or minimal field width */ + + size_t zero_padding_insertion_ind = 0; + /* index into tmp where zero padding is to be inserted */ + + char fmt_spec = '\0'; + /* current conversion specifier character */ + + str_arg = credits;/* just to make compiler happy (defined but not used)*/ + str_arg = NULL; + starting_p = p; p++; /* skip '%' */ + /* parse flags */ + while (*p == '0' || *p == '-' || *p == '+' || + *p == ' ' || *p == '#' || *p == '\'') { + switch (*p) { + case '0': zero_padding = 1; break; + case '-': justify_left = 1; break; + case '+': force_sign = 1; space_for_positive = 0; break; + case ' ': force_sign = 1; + /* If both the ' ' and '+' flags appear, the ' ' flag should be ignored */ + break; + case '#': alternate_form = 1; break; + case '\'': break; + } + p++; + } + /* If the '0' and '-' flags both appear, the '0' flag should be ignored. */ + + /* parse field width */ + if (*p == '*') { + int j; + p++; j = va_arg(ap, int); + if (j >= 0) min_field_width = j; + else { min_field_width = -j; justify_left = 1; } + } else if (isdigit((int)(*p))) { + /* size_t could be wider than unsigned int; + make sure we treat argument like common implementations do */ + unsigned int uj = *p++ - '0'; + while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0'); + min_field_width = uj; + } + /* parse precision */ + if (*p == '.') { + p++; precision_specified = 1; + if (*p == '*') { + int j = va_arg(ap, int); + p++; + if (j >= 0) precision = j; + else { + precision_specified = 0; precision = 0; + /* NOTE: + * Solaris 2.6 man page claims that in this case the precision + * should be set to 0. Digital Unix 4.0, HPUX 10 and BSD man page + * claim that this case should be treated as unspecified precision, + * which is what we do here. + */ + } + } else if (isdigit((int)(*p))) { + /* size_t could be wider than unsigned int; + make sure we treat argument like common implementations do */ + unsigned int uj = *p++ - '0'; + while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0'); + precision = uj; + } + } + /* parse 'h', 'l' and 'll' length modifiers */ + if (*p == 'h' || *p == 'l') { + length_modifier = *p; p++; + if (length_modifier == 'l' && *p == 'l') { /* double l = long long */ +#ifdef SNPRINTF_LONGLONG_SUPPORT + length_modifier = '2'; /* double l encoded as '2' */ +#else + length_modifier = 'l'; /* treat it as a single 'l' */ +#endif + p++; + } + } + fmt_spec = *p; + /* common synonyms: */ + switch (fmt_spec) { + case 'i': fmt_spec = 'd'; break; + case 'D': fmt_spec = 'd'; length_modifier = 'l'; break; + case 'U': fmt_spec = 'u'; length_modifier = 'l'; break; + case 'O': fmt_spec = 'o'; length_modifier = 'l'; break; + default: break; + } + /* get parameter value, do initial processing */ + switch (fmt_spec) { + case '%': /* % behaves similar to 's' regarding flags and field widths */ + case 'c': /* c behaves similar to 's' regarding flags and field widths */ + case 's': + length_modifier = '\0'; /* wint_t and wchar_t not supported */ + /* the result of zero padding flag with non-numeric conversion specifier*/ + /* is undefined. Solaris and HPUX 10 does zero padding in this case, */ + /* Digital Unix and Linux does not. */ + zero_padding = 0; /* turn zero padding off for string conversions */ + str_arg_l = 1; + switch (fmt_spec) { + case '%': + str_arg = p; break; + case 'c': { + int j = va_arg(ap, int); + uchar_arg = (unsigned char) j; /* standard demands unsigned char */ + str_arg = (const char *) &uchar_arg; + break; + } + case 's': + str_arg = va_arg(ap, const char *); + if (!str_arg) str_arg_l = 0; + /* make sure not to address string beyond the specified precision !!! */ + else if (!precision_specified) str_arg_l = strlen(str_arg); + /* truncate string if necessary as requested by precision */ + else if (precision == 0) str_arg_l = 0; + else { + /* memchr on HP does not like n > 2^31 !!! */ + const char *q = (const char*) memchr(str_arg, '\0', + precision <= 0x7fffffff ? precision : 0x7fffffff); + str_arg_l = !q ? precision : (q-str_arg); + } + break; + default: break; + } + break; + case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': { + /* NOTE: the u, o, x, X and p conversion specifiers imply + the value is unsigned; d implies a signed value */ + + int arg_sign = 0; + /* 0 if numeric argument is zero (or if pointer is NULL for 'p'), + +1 if greater than zero (or nonzero for unsigned arguments), + -1 if negative (unsigned argument is never negative) */ + + int int_arg = 0; unsigned int uint_arg = 0; + /* only defined for length modifier h, or for no length modifiers */ + + long int long_arg = 0; unsigned long int ulong_arg = 0; + /* only defined for length modifier l */ + + void *ptr_arg = NULL; + /* pointer argument value -only defined for p conversion */ + +#ifdef SNPRINTF_LONGLONG_SUPPORT + long long int long_long_arg = 0; + unsigned long long int ulong_long_arg = 0; + /* only defined for length modifier ll */ +#endif + if (fmt_spec == 'p') { + /* HPUX 10: An l, h, ll or L before any other conversion character + * (other than d, i, u, o, x, or X) is ignored. + * Digital Unix: + * not specified, but seems to behave as HPUX does. + * Solaris: If an h, l, or L appears before any other conversion + * specifier (other than d, i, u, o, x, or X), the behavior + * is undefined. (Actually %hp converts only 16-bits of address + * and %llp treats address as 64-bit data which is incompatible + * with (void *) argument on a 32-bit system). + */ + length_modifier = '\0'; + ptr_arg = va_arg(ap, void *); + if (ptr_arg != NULL) arg_sign = 1; + } else if (fmt_spec == 'd') { /* signed */ + switch (length_modifier) { + case '\0': + case 'h': + /* It is non-portable to specify a second argument of char or short + * to va_arg, because arguments seen by the called function + * are not char or short. C converts char and short arguments + * to int before passing them to a function. + */ + int_arg = va_arg(ap, int); + if (int_arg > 0) arg_sign = 1; + else if (int_arg < 0) arg_sign = -1; + break; + case 'l': + long_arg = va_arg(ap, long int); + if (long_arg > 0) arg_sign = 1; + else if (long_arg < 0) arg_sign = -1; + break; +#ifdef SNPRINTF_LONGLONG_SUPPORT + case '2': + long_long_arg = va_arg(ap, long long int); + if (long_long_arg > 0) arg_sign = 1; + else if (long_long_arg < 0) arg_sign = -1; + break; +#endif + } + } else { /* unsigned */ + switch (length_modifier) { + case '\0': + case 'h': + uint_arg = va_arg(ap, unsigned int); + if (uint_arg) arg_sign = 1; + break; + case 'l': + ulong_arg = va_arg(ap, unsigned long int); + if (ulong_arg) arg_sign = 1; + break; +#ifdef SNPRINTF_LONGLONG_SUPPORT + case '2': + ulong_long_arg = va_arg(ap, unsigned long long int); + if (ulong_long_arg) arg_sign = 1; + break; +#endif + } + } + str_arg = tmp; str_arg_l = 0; + /* NOTE: + * For d, i, u, o, x, and X conversions, if precision is specified, + * the '0' flag should be ignored. This is so with Solaris 2.6, + * Digital UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl. + */ + if (precision_specified) zero_padding = 0; + if (fmt_spec == 'd') { + if (force_sign && arg_sign >= 0) + tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; + /* leave negative numbers for sprintf to handle, + to avoid handling tricky cases like (short int)(-32768) */ + } else if (alternate_form) { + if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X') ) + { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; } + /* alternate form should have no effect for p conversion, but ... */ + } + zero_padding_insertion_ind = str_arg_l; + if (!precision_specified) precision = 1; /* default precision is 1 */ + if (precision == 0 && arg_sign == 0 + ) { + /* converted to null string */ + /* When zero value is formatted with an explicit precision 0, + the resulting formatted string is empty (d, i, u, o, x, X, p). */ + } else { + char f[5]; int f_l = 0; + f[f_l++] = '%'; /* construct a simple format string for sprintf */ + if (!length_modifier) { } + else if (length_modifier=='2') { f[f_l++] = 'l'; f[f_l++] = 'l'; } + else f[f_l++] = length_modifier; + f[f_l++] = fmt_spec; f[f_l++] = '\0'; + if (fmt_spec == 'p') str_arg_l += sprintf(tmp+str_arg_l, f, ptr_arg); + else if (fmt_spec == 'd') { /* signed */ + switch (length_modifier) { + case '\0': + case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, int_arg); break; + case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, long_arg); break; +#ifdef SNPRINTF_LONGLONG_SUPPORT + case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,long_long_arg); break; +#endif + } + } else { /* unsigned */ + switch (length_modifier) { + case '\0': + case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, uint_arg); break; + case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, ulong_arg); break; +#ifdef SNPRINTF_LONGLONG_SUPPORT + case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,ulong_long_arg);break; +#endif + } + } + /* include the optional minus sign and possible "0x" + in the region before the zero padding insertion point */ + if (zero_padding_insertion_ind < str_arg_l && + tmp[zero_padding_insertion_ind] == '-') { + zero_padding_insertion_ind++; + } + if (zero_padding_insertion_ind+1 < str_arg_l && + tmp[zero_padding_insertion_ind] == '0' && + (tmp[zero_padding_insertion_ind+1] == 'x' || + tmp[zero_padding_insertion_ind+1] == 'X') ) { + zero_padding_insertion_ind += 2; + } + } + { size_t num_of_digits = str_arg_l - zero_padding_insertion_ind; + if (alternate_form && fmt_spec == 'o' + /* unless zero is already the first character */ + && !(zero_padding_insertion_ind < str_arg_l + && tmp[zero_padding_insertion_ind] == '0') + ) { /* assure leading zero for alternate-form octal numbers */ + if (!precision_specified || precision < num_of_digits+1) { + /* precision is increased to force the first character to be zero, + except if a zero value is formatted with an explicit precision + of zero */ + precision = num_of_digits+1; precision_specified = 1; + } + } + /* zero padding to specified precision? */ + if (num_of_digits < precision) + number_of_zeros_to_pad = precision - num_of_digits; + } + /* zero padding to specified minimal field width? */ + if (!justify_left && zero_padding) { + int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); + if (n > 0) number_of_zeros_to_pad += n; + } + break; + } + default: /* unrecognized conversion specifier, keep format string as-is*/ + zero_padding = 0; /* turn zero padding off for non-numeric convers. */ + justify_left = 1; min_field_width = 0; /* reset flags */ + /* discard the unrecognized conversion, just keep * + * the unrecognized conversion character */ + str_arg = p; str_arg_l = 0; + if (*p) str_arg_l++; /* include invalid conversion specifier unchanged + if not at end-of-string */ + break; + } + if (*p) p++; /* step over the just processed conversion specifier */ + /* insert padding to the left as requested by min_field_width; + this does not include the zero padding in case of numerical conversions*/ + if (!justify_left) { /* left padding with blank or zero */ + int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m-str_l; + fast_memset(str+str_l, (zero_padding?'0':' '), (n>avail?avail:n)); + } + str_l += n; + } + } + /* zero padding as requested by the precision or by the minimal field width + * for numeric conversions required? */ + if (number_of_zeros_to_pad <= 0) { + /* will not copy first part of numeric right now, * + * force it to be copied later in its entirety */ + zero_padding_insertion_ind = 0; + } else { + /* insert first part of numerics (sign or '0x') before zero padding */ + int n = zero_padding_insertion_ind; + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m-str_l; + fast_memcpy(str+str_l, str_arg, (n>avail?avail:n)); + } + str_l += n; + } + /* insert zero padding as requested by the precision or min field width */ + n = number_of_zeros_to_pad; + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m-str_l; + fast_memset(str+str_l, '0', (n>avail?avail:n)); + } + str_l += n; + } + } + /* insert formatted string + * (or as-is conversion specifier for unknown conversions) */ + { int n = str_arg_l - zero_padding_insertion_ind; + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m-str_l; + fast_memcpy(str+str_l, str_arg+zero_padding_insertion_ind, + (n>avail?avail:n)); + } + str_l += n; + } + } + /* insert right padding */ + if (justify_left) { /* right blank padding to the field width */ + int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m-str_l; + fast_memset(str+str_l, ' ', (n>avail?avail:n)); + } + str_l += n; + } + } + } + } + if (str_m > 0) { /* make sure the string is null-terminated + even at the expense of overwriting the last character + (shouldn't happen, but just in case) */ + str[str_l <= str_m-1 ? str_l : str_m-1] = '\0'; + } + /* Return the number of characters formatted (excluding trailing null + * character), that is, the number of characters that would have been + * written to the buffer if it were large enough. + * + * The value of str_l should be returned, but str_l is of unsigned type + * size_t, and snprintf is int, possibly leading to an undetected + * integer overflow, resulting in a negative return value, which is illegal. + * Both XSH5 and ISO C99 (at least the draft) are silent on this issue. + * Should errno be set to EOVERFLOW and EOF returned in this case??? + */ + return (int) str_l; +} + +int symbian_snprintf(char *text, size_t maxlen, const char *fmt, ...) { + va_list ap; + int retval; + + va_start(ap, fmt); + retval = symbian_vsnprintf(text, maxlen, fmt, ap); + va_end(ap); + + return retval; +} diff --git a/backends/platform/wii/Makefile b/backends/platform/wii/Makefile index a52ceb1774..90ebcccb66 100644 --- a/backends/platform/wii/Makefile +++ b/backends/platform/wii/Makefile @@ -1,26 +1,32 @@ +# this enables port specific debug messages and redirects stdout/err over +# usbgecko in memcard slot b DEBUG_WII = 1 -ENABLE_SCUMM = 1 -ENABLE_SCUMM_7_8 = 1 -ENABLE_HE = 1 -# ENABLE_AGI = 1 -ENABLE_AGOS = 1 -ENABLE_CINE = 1 -ENABLE_CRUISE = 1 -ENABLE_DRASCULA = 1 -ENABLE_GOB = 1 -ENABLE_IGOR = 1 -ENABLE_KYRA = 1 -ENABLE_LURE = 1 -ENABLE_M4 = 1 -ENABLE_MADE = 1 -ENABLE_PARALLACTION = 1 -ENABLE_QUEEN = 1 -ENABLE_SAGA = 1 -ENABLE_SKY = 1 -ENABLE_SWORD1 = 1 -ENABLE_SWORD2 = 1 -ENABLE_TOUCHE = 1 +# builds a gamecube version. cleanup object files before flipping this +GAMECUBE = 0 + +ENABLE_SCUMM = STATIC_PLUGIN +ENABLE_SCUMM_7_8 = STATIC_PLUGIN +ENABLE_HE = STATIC_PLUGIN +# ENABLE_AGI = STATIC_PLUGIN +ENABLE_AGOS = STATIC_PLUGIN +ENABLE_CINE = STATIC_PLUGIN +ENABLE_CRUISE = STATIC_PLUGIN +ENABLE_DRASCULA = STATIC_PLUGIN +ENABLE_GOB = STATIC_PLUGIN +ENABLE_IGOR = STATIC_PLUGIN +ENABLE_KYRA = STATIC_PLUGIN +ENABLE_LURE = STATIC_PLUGIN +ENABLE_M4 = STATIC_PLUGIN +ENABLE_MADE = STATIC_PLUGIN +ENABLE_PARALLACTION = STATIC_PLUGIN +ENABLE_QUEEN = STATIC_PLUGIN +ENABLE_SAGA = STATIC_PLUGIN +ENABLE_SKY = STATIC_PLUGIN +ENABLE_SWORD1 = STATIC_PLUGIN +ENABLE_SWORD2 = STATIC_PLUGIN +ENABLE_TINSEL = STATIC_PLUGIN +ENABLE_TOUCHE = STATIC_PLUGIN DISABLE_HQ_SCALERS = 1 DISABLE_SCALERS = 1 @@ -30,7 +36,11 @@ USE_MAD = 1 USE_TREMOR = 1 USE_FLAC = 1 USE_MPEG2 = 1 +ifeq ($(GAMECUBE),1) +USE_MT32EMU = 0 +else USE_MT32EMU = 1 +endif srcdir = ../../.. VPATH = $(srcdir) @@ -54,21 +64,28 @@ MKDIR = mkdir -p RM = rm -f CP = cp -f +ifeq ($(GAMECUBE),1) +TARGET = scummvm-gc +MACHDEP = -DGEKKO -DGAMECUBE -mogc -mcpu=750 -meabi -mhard-float \ + -ffunction-sections -fdata-sections -fmodulo-sched +LIBDIR = $(DEVKITPRO)/libogc/lib/cube +LIBS = -lstdc++ -lfat -logc -lm +else TARGET = scummvm-wii - MACHDEP = -DGEKKO -mrvl -mcpu=750 -meabi -mhard-float \ -ffunction-sections -fdata-sections -fmodulo-sched +LIBDIR = $(DEVKITPRO)/libogc/lib/wii +LIBS = -lstdc++ -lfat -lwiiuse -lbte -logc -lm +endif INCDIR = $(srcdir) . $(srcdir)/engines/ $(DEVKITPRO)/libogc/include -LIBDIR = $(DEVKITPRO)/libogc/lib/wii CXXFLAGS = -g -Os -Wall $(MACHDEP) -D__WII__ -Wno-multichar -Wno-long-long \ - -Wno-unknown-pragmas -Wno-reorder -fno-exceptions -fno-rtti + -Wno-unknown-pragmas -Wno-reorder -fno-exceptions -fno-rtti CXXFLAGS += $(addprefix -I,$(INCDIR)) LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(TARGET).elf.map LDFLAGS += $(addprefix -L,$(LIBDIR)) -LIBS = -lstdc++ -lfat -lwiiuse -lbte -logc -lm CXXFLAGS += -I$(DEVKITPRO)/3rd/wii/include LDFLAGS += -L$(DEVKITPRO)/3rd/wii/lib @@ -138,19 +155,27 @@ distclean-wii: @-$(RM) dist upload: +ifeq ($(GAMECUBE),1) + $(DEVKITPPC)/bin/geckoupload $(TARGET).dol +else $(DEVKITPPC)/bin/wiiload $(TARGET).dol +endif dist: - $(MKDIR) dist/apps/scummvm - $(CP) $(TARGET).dol dist/apps/scummvm/boot.dol - $(CP) $(DISTPATH)/meta.xml dist/apps/scummvm/ - $(CP) $(DISTPATH)/icon.png dist/apps/scummvm/ - $(CP) $(DISTPATH)/READMII dist/apps/scummvm/ - $(CP) $(srcdir)/AUTHORS dist/apps/scummvm/ - $(CP) $(srcdir)/COPYING dist/apps/scummvm/ - $(CP) $(srcdir)/COPYRIGHT dist/apps/scummvm/ - $(CP) $(srcdir)/NEWS dist/apps/scummvm/ - $(CP) $(srcdir)/README dist/apps/scummvm/ - $(CP) $(DIST_FILES_THEMES) dist/apps/scummvm/ - $(CP) $(DIST_FILES_ENGINEDATA) dist/apps/scummvm/ + $(MKDIR) dist/scummvm +ifeq ($(GAMECUBE),1) + $(CP) $(TARGET).dol dist/scummvm/ +else + $(CP) $(TARGET).dol dist/scummvm/boot.dol + $(CP) $(DISTPATH)/meta.xml dist/scummvm/ + $(CP) $(DISTPATH)/icon.png dist/scummvm/ +endif + $(CP) $(DISTPATH)/READMII dist/scummvm/ + $(CP) $(srcdir)/AUTHORS dist/scummvm/ + $(CP) $(srcdir)/COPYING dist/scummvm/ + $(CP) $(srcdir)/COPYRIGHT dist/scummvm/ + $(CP) $(srcdir)/NEWS dist/scummvm/ + $(CP) $(srcdir)/README dist/scummvm/ + $(CP) $(DIST_FILES_THEMES) dist/scummvm/ + $(CP) $(DIST_FILES_ENGINEDATA) dist/scummvm/ diff --git a/backends/platform/wii/gx_supp.cpp b/backends/platform/wii/gx_supp.cpp index 4c7b8ed58a..436deddbb8 100644 --- a/backends/platform/wii/gx_supp.cpp +++ b/backends/platform/wii/gx_supp.cpp @@ -1,6 +1,7 @@ /**************************************************************************** * Generic GX Support for Emulators * softdev 2007 +* dhewg 2008 * * 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 @@ -21,12 +22,13 @@ * These are pretty standard functions to setup and use GX scaling. ****************************************************************************/ -#include <gccore.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <malloc.h> +#include "gx_supp.h" + #define DEFAULT_FIFO_SIZE (256 * 1024) #define HASPECT 320 @@ -39,18 +41,19 @@ extern "C" { /*** 2D ***/ static u32 whichfb; static u32 *xfb[2]; -static GXRModeObj *vmode; +GXRModeObj *vmode = NULL; /*** 3D GX ***/ static u8 *gp_fifo; /*** Texture memory ***/ -static u8 *texturemem; +static u8 *texturemem = NULL; static u32 texturesize; -GXTexObj texobj; +static GXTexObj texobj; static Mtx view; static u16 vwidth, vheight, oldvwidth, oldvheight; +static float tex_xT = 0.0f, tex_yT = 0.0f; /* New texture based scaler */ typedef struct tagcamera { @@ -74,6 +77,10 @@ static camera cam = { void GX_InitVideo() { vmode = VIDEO_GetPreferredMode(NULL); + + vmode->viWidth = 678; + vmode->viXOrigin = (VI_MAX_WIDTH_PAL - 678) / 2; + VIDEO_Configure(vmode); xfb[0] = (u32 *) MEM_K0_TO_K1 (SYS_AllocateFramebuffer(vmode)); @@ -93,6 +100,15 @@ void GX_InitVideo() { VIDEO_WaitVSync(); } +void GX_SetTexTrans(float xT, float yT) { + tex_xT = xT; + tex_yT = yT; +} + +void GX_SetCamPosZ(float f) { + cam.pos.z = f; +} + /**************************************************************************** * Scaler Support Functions ****************************************************************************/ @@ -128,7 +144,7 @@ static void draw_square(Mtx v) { Mtx mv; guMtxIdentity(m); - guMtxTransApply(m, m, 0, 0, -100); + guMtxTransApply(m, m, tex_xT, tex_yT, -100); guMtxConcat(v, m, mv); GX_LoadPosMtxImm(mv, GX_PNMTX0); @@ -144,9 +160,9 @@ static void draw_square(Mtx v) { * StartGX ****************************************************************************/ void GX_Start(u16 width, u16 height, s16 haspect, s16 vaspect) { + static bool inited = false; Mtx p; - - GX_AbortFrame(); + GXColor gxbackground = { 0, 0, 0, 0xff }; /*** Set new aspect ***/ square[0] = square[9] = -haspect; @@ -156,9 +172,20 @@ void GX_Start(u16 width, u16 height, s16 haspect, s16 vaspect) { /*** Allocate 32byte aligned texture memory ***/ texturesize = (width * height) * 2; + + if (texturemem) + free(texturemem); + texturemem = (u8 *) memalign(32, texturesize); + memset(texturemem, 0, texturesize); - GXColor gxbackground = { 0, 0, 0, 0xff }; + /*** Setup for first call to scaler ***/ + oldvwidth = oldvheight = -1; + + if (inited) + return; + + inited = true; /*** Clear out FIFO area ***/ memset(gp_fifo, 0, DEFAULT_FIFO_SIZE); @@ -184,12 +211,8 @@ void GX_Start(u16 width, u16 height, s16 haspect, s16 vaspect) { guPerspective(p, 60, 1.33f, 10.0f, 1000.0f); GX_LoadProjectionMtx(p, GX_PERSPECTIVE); - memset(texturemem, 0, texturesize); GX_Flush(); - - /*** Setup for first call to scaler ***/ - vwidth = vheight = -1; } /**************************************************************************** diff --git a/backends/platform/wii/gx_supp.h b/backends/platform/wii/gx_supp.h index 9393e93a26..108a94f0e7 100644 --- a/backends/platform/wii/gx_supp.h +++ b/backends/platform/wii/gx_supp.h @@ -1,6 +1,7 @@ /**************************************************************************** * Generic GX Scaler * softdev 2007 +* dhewg 2008 * * 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 @@ -23,11 +24,17 @@ #ifndef _WII_GX_SUPP_H_ #define _WII_GX_SUPP_H_ +#include <gccore.h> + #ifdef __cplusplus extern "C" { #endif +extern GXRModeObj *vmode; + void GX_InitVideo(); +void GX_SetTexTrans(float xT, float yT); +void GX_SetCamPosZ(float f); void GX_Start(u16 width, u16 height, s16 haspect, s16 vaspect); void GX_Render(u16 width, u16 height, u8 *buffer, u16 pitch); diff --git a/backends/platform/wii/main.cpp b/backends/platform/wii/main.cpp index 5753ecefe4..8bb1bff904 100644 --- a/backends/platform/wii/main.cpp +++ b/backends/platform/wii/main.cpp @@ -62,7 +62,9 @@ int main(int argc, char *argv[]) { printf("startup\n"); SYS_SetResetCallback(reset_cb); +#ifndef GAMECUBE SYS_SetPowerCallback(power_cb); +#endif if (!fatInitDefault()) { printf("fatInitDefault failed\n"); @@ -75,7 +77,7 @@ int main(int argc, char *argv[]) { if (!strcmp(buf, "fat:/")) chdir("/apps/scummvm"); - //fatEnableReadAhead(PI_DEFAULT, 32, 128); + fatEnableReadAhead(PI_DEFAULT, 32, 128); } g_system = new OSystem_Wii(); diff --git a/backends/platform/wii/osystem.cpp b/backends/platform/wii/osystem.cpp index 9e708345c5..505f93c820 100644 --- a/backends/platform/wii/osystem.cpp +++ b/backends/platform/wii/osystem.cpp @@ -19,8 +19,10 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "osystem.h" #include "backends/fs/wii/wii-fs-factory.h" +#include "common/config-manager.h" + +#include "osystem.h" #include <unistd.h> @@ -51,7 +53,9 @@ OSystem_Wii::OSystem_Wii() : _currentHeight(0), _supportedGraphicsModes(NULL), - _activeGraphicsMode(-1), + _activeGraphicsMode(0), + + _fullscreen(false), _mouseVisible(false), _mouseX(0), @@ -89,11 +93,17 @@ OSystem_Wii::~OSystem_Wii() { void OSystem_Wii::initBackend() { _startup_time = gettime(); + + char buf[MAXPATHLEN]; + if (!getcwd(buf, MAXPATHLEN)) + strcpy(buf, "/"); - _savefile = new DefaultSaveFileManager(); + _savefile = new DefaultSaveFileManager(buf); _mixer = new Audio::MixerImpl(this); _timer = new DefaultTimerManager(); + _fullscreen = ConfMan.getBool("fullscreen"); + initGfx(); initSfx(); initEvents(); @@ -108,14 +118,28 @@ void OSystem_Wii::quit() { } bool OSystem_Wii::hasFeature(Feature f) { - return f == kFeatureCursorHasPalette; + return (f == kFeatureFullscreenMode) || + (f == kFeatureCursorHasPalette); } void OSystem_Wii::setFeatureState(Feature f, bool enable) { + switch (f) { + case kFeatureFullscreenMode: + _fullscreen = enable; + setGraphicsMode(_activeGraphicsMode); + break; + default: + break; + } } bool OSystem_Wii::getFeatureState(Feature f) { - return false; + switch (f) { + case kFeatureFullscreenMode: + return _fullscreen; + default: + return false; + } } uint32 OSystem_Wii::getMillis() { diff --git a/backends/platform/wii/osystem.h b/backends/platform/wii/osystem.h index 7fbc560b1a..94c0fa76b3 100644 --- a/backends/platform/wii/osystem.h +++ b/backends/platform/wii/osystem.h @@ -22,9 +22,9 @@ #ifndef _WII_OSYSTEM_H_ #define _WII_OSYSTEM_H_ -#include "common/system.h" #include "base/main.h" - +#include "common/system.h" +#include "common/fs.h" #include "common/rect.h" #include "common/events.h" @@ -73,6 +73,8 @@ private: OSystem::GraphicsMode *_supportedGraphicsModes; s32 _activeGraphicsMode; + bool _fullscreen; + bool _mouseVisible; s32 _mouseX, _mouseY; u32 _mouseWidth, _mouseHeight; @@ -110,7 +112,6 @@ public: virtual bool getFeatureState(Feature f); virtual const GraphicsMode *getSupportedGraphicsModes() const; virtual int getDefaultGraphicsMode() const; - bool setGraphicsMode(const char *name); virtual bool setGraphicsMode(int mode); virtual int getGraphicsMode() const; virtual void initSize(uint width, uint height); diff --git a/backends/platform/wii/osystem_gfx.cpp b/backends/platform/wii/osystem_gfx.cpp index 1e54233c93..faad41d5f0 100644 --- a/backends/platform/wii/osystem_gfx.cpp +++ b/backends/platform/wii/osystem_gfx.cpp @@ -27,7 +27,12 @@ #define MAX_FPS 30 enum GraphicModeID { - GM_DEFAULT + GM_DEFAULT = 0, + GM_OVERSCAN1, + GM_OVERSCAN2, + GM_OVERSCAN3, + GM_OVERSCAN4, + GM_OVERSCAN5 }; void OSystem_Wii::initGfx() { @@ -42,6 +47,11 @@ void OSystem_Wii::initGfx() { _overlayWidth = 640; _overlayHeight = 480; +#ifndef GAMECUBE + if (CONF_GetAspectRatio() && _fullscreen) + _overlayHeight = 360; +#endif + _overlaySize = _overlayWidth * _overlayHeight * 2; _overlayPixels = (OverlayColor *) memalign(32, _overlaySize); @@ -51,17 +61,32 @@ void OSystem_Wii::initGfx() { _cursorPalette = (u16 *) memalign(32, 256 * 2); memset(_cursorPalette, 0, 256 * 2); - _supportedGraphicsModes = new OSystem::GraphicsMode[2]; - _supportedGraphicsModes[0].name = strdup("gx"); - _supportedGraphicsModes[0].description = strdup("wii hardware scaler"); + _supportedGraphicsModes = new OSystem::GraphicsMode[7]; + _supportedGraphicsModes[0].name = strdup("standard"); + _supportedGraphicsModes[0].description = strdup("standard"); _supportedGraphicsModes[0].id = GM_DEFAULT; - _supportedGraphicsModes[1].name = 0; - _supportedGraphicsModes[1].description = 0; - _supportedGraphicsModes[1].id = 0; - - _texture = (u16 *) memalign(32, _overlaySize); - - GX_Start(_overlayWidth, _overlayHeight, 320, 240); + _supportedGraphicsModes[1].name = strdup("overscan1"); + _supportedGraphicsModes[1].description = strdup("overscan 1"); + _supportedGraphicsModes[1].id = GM_OVERSCAN1; + _supportedGraphicsModes[2].name = strdup("overscan2"); + _supportedGraphicsModes[2].description = strdup("overscan 2"); + _supportedGraphicsModes[2].id = GM_OVERSCAN2; + _supportedGraphicsModes[3].name = strdup("overscan3"); + _supportedGraphicsModes[3].description = strdup("overscan 3"); + _supportedGraphicsModes[3].id = GM_OVERSCAN3; + _supportedGraphicsModes[4].name = strdup("overscan4"); + _supportedGraphicsModes[4].description = strdup("overscan 4"); + _supportedGraphicsModes[4].id = GM_OVERSCAN4; + _supportedGraphicsModes[5].name = strdup("overscan5"); + _supportedGraphicsModes[5].description = strdup("overscan 5"); + _supportedGraphicsModes[5].id = GM_OVERSCAN5; + _supportedGraphicsModes[6].name = 0; + _supportedGraphicsModes[6].description = 0; + _supportedGraphicsModes[6].id = 0; + + _texture = (u16 *) memalign(32, 640 * 480 * 2); + + setGraphicsMode(_activeGraphicsMode); } void OSystem_Wii::deinitGfx() { @@ -111,13 +136,24 @@ int OSystem_Wii::getDefaultGraphicsMode() const { return GM_DEFAULT; } -bool OSystem_Wii::setGraphicsMode(const char *mode) { - setGraphicsMode(GM_DEFAULT); +bool OSystem_Wii::setGraphicsMode(int mode) { + s16 xar, yar; - return true; -} + printf("setGraphicsMode %d\n", mode); + + xar = vmode->viWidth / 2; + yar = vmode->xfbHeight / 2; + +#ifndef GAMECUBE + if (CONF_GetAspectRatio() && !_fullscreen) + xar /= 1.33f; +#endif + + GX_SetCamPosZ(400 - mode * 10); + GX_Start(640, 480, xar, yar); + + _activeGraphicsMode = mode; -bool OSystem_Wii::setGraphicsMode(int mode) { return true; } @@ -129,6 +165,8 @@ void OSystem_Wii::initSize(uint width, uint height) { if (_gameWidth != width || _gameHeight != height) { printf("initSize %u %u\n", width, height); + assert((width <= 640) && (height <= 480)); + _gameWidth = width; _gameHeight = height; @@ -136,12 +174,15 @@ void OSystem_Wii::initSize(uint width, uint height) { free(_gamePixels); _gamePixels = (u8 *) memalign(32, _gameWidth * _gameHeight); + memset(_gamePixels, 0, _gameWidth * _gameHeight); if (!_overlayVisible) { _currentWidth = _gameWidth; _currentHeight = _gameHeight; updateEventScreenResolution(); } + + setGraphicsMode(_activeGraphicsMode); } } @@ -320,6 +361,8 @@ void OSystem_Wii::unlockScreen() { } void OSystem_Wii::setShakePos(int shakeOffset) { + GX_SetTexTrans(0, (float) -shakeOffset * ((float) vmode->efbHeight / + (float) _currentHeight)); } void OSystem_Wii::showOverlay() { diff --git a/backends/platform/wince/CEActionsPocket.cpp b/backends/platform/wince/CEActionsPocket.cpp index 45310dba88..7f78517762 100644 --- a/backends/platform/wince/CEActionsPocket.cpp +++ b/backends/platform/wince/CEActionsPocket.cpp @@ -121,7 +121,7 @@ void CEActionsPocket::initInstanceGame() { bool is_comi = (strncmp(gameid.c_str(), "comi", 4) == 0); bool is_gob = (strncmp(gameid.c_str(), "gob", 3) == 0); bool is_saga = (gameid == "saga"); - bool is_kyra = (gameid == "kyra1"); + bool is_kyra = (strncmp(gameid.c_str(), "kyra",4) == 0); bool is_samnmax = (gameid == "samnmax"); bool is_cine = (gameid == "cine"); bool is_touche = (gameid == "touche"); @@ -129,11 +129,13 @@ void CEActionsPocket::initInstanceGame() { bool is_parallaction = (gameid == "parallaction"); bool is_lure = (gameid == "lure"); bool is_feeble = (gameid == "feeble"); + bool is_drascula = (strncmp(gameid.c_str(), "drascula",8) == 0); GUI_Actions::initInstanceGame(); // See if a right click mapping could be needed - if (is_sword1 || is_sword2 || is_sky || is_queen || is_comi || is_gob || is_samnmax || is_cine || is_touche || is_parallaction) + if (is_sword1 || is_sword2 || is_sky || is_queen || is_comi || is_gob || + is_samnmax || is_cine || is_touche || is_parallaction || is_drascula) _right_click_needed = true; // See if a "hide toolbar" mapping could be needed @@ -145,7 +147,7 @@ void CEActionsPocket::initInstanceGame() { _key_action[POCKET_ACTION_PAUSE].setKey(VK_SPACE); _action_enabled[POCKET_ACTION_PAUSE] = true; // Save - if (is_simon || is_sword2 || is_gob || is_kyra || is_touche || is_feeble) + if (is_simon || is_sword2 || is_gob || is_kyra || is_feeble) _action_enabled[POCKET_ACTION_SAVE] = false; else if (is_queen) { _action_enabled[POCKET_ACTION_SAVE] = true; @@ -153,7 +155,7 @@ void CEActionsPocket::initInstanceGame() { } else if (is_sky) { _action_enabled[POCKET_ACTION_SAVE] = true; _key_action[POCKET_ACTION_SAVE].setKey(Common::ASCII_F5, SDLK_F5); - } else if (is_cine) { + } else if (is_cine || is_drascula) { _action_enabled[POCKET_ACTION_SAVE] = true; _key_action[POCKET_ACTION_SAVE].setKey(Common::ASCII_F10, SDLK_F10); // F10 } else if (is_agi) { @@ -171,7 +173,8 @@ void CEActionsPocket::initInstanceGame() { // Skip if (!is_cine && !is_parallaction) _action_enabled[POCKET_ACTION_SKIP] = true; - if (is_simon || is_sky || is_sword2 || is_queen || is_sword1 || is_gob || is_saga || is_kyra || is_touche || is_lure || is_feeble) + if (is_simon || is_sky || is_sword2 || is_queen || is_sword1 || is_gob || + is_saga || is_kyra || is_touche || is_lure || is_feeble || is_drascula) _key_action[POCKET_ACTION_SKIP].setKey(VK_ESCAPE); else _key_action[POCKET_ACTION_SKIP].setKey(KEY_ALL_SKIP); @@ -212,7 +215,7 @@ CEActionsPocket::~CEActionsPocket() { } bool CEActionsPocket::perform(GUI::ActionType action, bool pushed) { - static bool keydialogrunning = false; + static bool keydialogrunning = false, quitdialog = false; if (!pushed) { switch(action) { @@ -289,12 +292,14 @@ bool CEActionsPocket::perform(GUI::ActionType action, bool pushed) { _CESystem->move_cursor_right(); return true; case POCKET_ACTION_QUIT: - { + if (!quitdialog) { + quitdialog = true; GUI::MessageDialog alert(" Are you sure you want to quit ? ", "Yes", "No"); if (alert.runModal() == GUI::kMessageOK) _mainSystem->quit(); - return true; + quitdialog = false; } + return true; case POCKET_ACTION_BINDKEYS: if (!keydialogrunning) { keydialogrunning = true; diff --git a/backends/platform/wince/CEActionsSmartphone.cpp b/backends/platform/wince/CEActionsSmartphone.cpp index 97d780d534..0c4113cc0c 100644 --- a/backends/platform/wince/CEActionsSmartphone.cpp +++ b/backends/platform/wince/CEActionsSmartphone.cpp @@ -111,7 +111,7 @@ void CEActionsSmartphone::initInstanceGame() { bool is_comi = (strncmp(gameid.c_str(), "comi", 4) == 0); bool is_gob = (strncmp(gameid.c_str(), "gob", 3) == 0); bool is_saga = (gameid == "saga"); - bool is_kyra = (gameid == "kyra1"); + bool is_kyra = (strncmp(gameid.c_str(), "kyra",4) == 0); bool is_samnmax = (gameid == "samnmax"); bool is_cine = (gameid == "cine"); bool is_touche = (gameid == "touche"); @@ -119,16 +119,18 @@ void CEActionsSmartphone::initInstanceGame() { bool is_parallaction = (gameid == "parallaction"); bool is_lure = (gameid == "lure"); bool is_feeble = (gameid == "feeble"); + bool is_drascula = (strncmp(gameid.c_str(), "drascula",8) == 0); GUI_Actions::initInstanceGame(); // See if a right click mapping could be needed - if (is_sword1 || is_sword2 || is_sky || is_queen || is_comi || is_gob || is_samnmax || is_cine || is_touche || is_parallaction) + if (is_sword1 || is_sword2 || is_sky || is_queen || is_comi || is_gob || + is_samnmax || is_cine || is_touche || is_parallaction || is_drascula) _right_click_needed = true; // Initialize keys for different actions // Save - if (is_simon || is_sword2 || is_gob || is_kyra || is_touche || is_feeble) + if (is_simon || is_sword2 || is_gob || is_kyra || is_feeble) _action_enabled[SMARTPHONE_ACTION_SAVE] = false; else if (is_queen) { _action_enabled[SMARTPHONE_ACTION_SAVE] = true; @@ -136,7 +138,7 @@ void CEActionsSmartphone::initInstanceGame() { } else if (is_sky) { _action_enabled[SMARTPHONE_ACTION_SAVE] = true; _key_action[SMARTPHONE_ACTION_SAVE].setKey(Common::ASCII_F5, SDLK_F5); - } else if (is_cine) { + } else if (is_cine || is_drascula) { _action_enabled[SMARTPHONE_ACTION_SAVE] = true; _key_action[SMARTPHONE_ACTION_SAVE].setKey(Common::ASCII_F10, SDLK_F10); //F10 } else if (is_agi) { @@ -151,7 +153,8 @@ void CEActionsSmartphone::initInstanceGame() { } // Skip _action_enabled[SMARTPHONE_ACTION_SKIP] = true; - if (is_simon || is_sky || is_sword2 || is_queen || is_sword1 || is_gob || is_saga || is_kyra || is_touche || is_lure || is_feeble) + if (is_simon || is_sky || is_sword2 || is_queen || is_sword1 || is_gob || + is_saga || is_kyra || is_touche || is_lure || is_feeble || is_drascula) _key_action[SMARTPHONE_ACTION_SKIP].setKey(VK_ESCAPE); else _key_action[SMARTPHONE_ACTION_SKIP].setKey(KEY_ALL_SKIP); @@ -176,7 +179,7 @@ CEActionsSmartphone::~CEActionsSmartphone() { } bool CEActionsSmartphone::perform(GUI::ActionType action, bool pushed) { - static bool keydialogrunning = false; + static bool keydialogrunning = false, quitdialog = false; if (!pushed) { switch (action) { @@ -247,12 +250,14 @@ bool CEActionsSmartphone::perform(GUI::ActionType action, bool pushed) { _CESystem->smartphone_rotate_display(); return true; case SMARTPHONE_ACTION_QUIT: - { + if (!quitdialog) { + quitdialog = true; GUI::MessageDialog alert(" Are you sure you want to quit ? ", "Yes", "No"); if (alert.runModal() == GUI::kMessageOK) _mainSystem->quit(); - return true; + quitdialog = false; } + return true; } return false; diff --git a/backends/platform/wince/CELauncherDialog.cpp b/backends/platform/wince/CELauncherDialog.cpp index edfdad84b3..7e306be114 100644 --- a/backends/platform/wince/CELauncherDialog.cpp +++ b/backends/platform/wince/CELauncherDialog.cpp @@ -72,10 +72,10 @@ void CELauncherDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 d } } -void CELauncherDialog::automaticScanDirectory(const FilesystemNode &node) { +void CELauncherDialog::automaticScanDirectory(const Common::FilesystemNode &node) { // First check if we have a recognized game in the current directory - FSList files; - node.getChildren(files, FilesystemNode::kListFilesOnly); + Common::FSList files; + node.getChildren(files, Common::FilesystemNode::kListFilesOnly); // detect GameList candidates(EngineMan.detectGames(files)); // insert @@ -85,9 +85,9 @@ void CELauncherDialog::automaticScanDirectory(const FilesystemNode &node) { addGameToConf(result); } // Then recurse on the subdirectories - FSList dirs; - node.getChildren(dirs, FilesystemNode::kListDirectoriesOnly); - for (FSList::const_iterator currentDir = dirs.begin(); currentDir != dirs.end(); ++currentDir) + Common::FSList dirs; + node.getChildren(dirs, Common::FilesystemNode::kListDirectoriesOnly); + for (Common::FSList::const_iterator currentDir = dirs.begin(); currentDir != dirs.end(); ++currentDir) automaticScanDirectory(*currentDir); } diff --git a/backends/platform/wince/CELauncherDialog.h b/backends/platform/wince/CELauncherDialog.h index 55d177bcb8..a5f3fd0d43 100644 --- a/backends/platform/wince/CELauncherDialog.h +++ b/backends/platform/wince/CELauncherDialog.h @@ -36,7 +36,7 @@ public: virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data); protected: void addGame(); - void automaticScanDirectory(const FilesystemNode &node); + void automaticScanDirectory(const Common::FilesystemNode &node); }; typedef GUI::LauncherDialog GUILauncherDialog; diff --git a/backends/platform/wince/CEkeys/EventsBuffer.cpp b/backends/platform/wince/CEkeys/EventsBuffer.cpp index 92a21ab7ad..f31a77570f 100644 --- a/backends/platform/wince/CEkeys/EventsBuffer.cpp +++ b/backends/platform/wince/CEkeys/EventsBuffer.cpp @@ -36,9 +36,8 @@ namespace CEKEYS { key->setKey(key->keycode()); ev.type = (pushed ? SDL_KEYDOWN : SDL_KEYUP); - ev.key.keysym.mod = (SDLMod)key->flags(); + ev.key.keysym.unicode = (SDLMod)key->flags(); // HACK: put the flags into the unused unicode field ev.key.keysym.sym = (SDLKey)key->keycode(); - ev.key.keysym.unicode = key->keycode(); ev.key.keysym.mod = KMOD_RESERVED; return (SDL_PushEvent(&ev) == 0); } diff --git a/backends/platform/wince/Makefile b/backends/platform/wince/Makefile index 176971067e..9f040bbed1 100644 --- a/backends/platform/wince/Makefile +++ b/backends/platform/wince/Makefile @@ -34,17 +34,19 @@ ENABLE_SWORD1 = STATIC_PLUGIN ENABLE_SWORD2 = STATIC_PLUGIN ENABLE_TOUCHE = STATIC_PLUGIN ENABLE_PARALLACTION = STATIC_PLUGIN +ENABLE_DRASCULA = STATIC_PLUGIN #ENABLE_CRUISE = STATIC_PLUGIN -#ENABLE_DRASCULA = STATIC_PLUGIN #ENABLE_IGOR = STATIC_PLUGIN +#ENABLE_M4 = STATIC_PLUGIN +#ENABLE_MADE = STATIC_PLUGIN ######################################################################## ## Pick which libraries you want to use here USE_MAD = 1 USE_MPEG2 = 1 -USE_TREMOR = 1 -#USE_TREMOLO = 1 +#USE_TREMOR = 1 +USE_TREMOLO = 1 USE_FLAC = 1 USE_ZLIB = 1 @@ -137,7 +139,7 @@ LIBS += -ltremorce endif ifdef USE_TREMOLO -DEFINES += -DUSE_TREMOR -DUSE_VORBIS +DEFINES += -DUSE_TREMOR -DUSE_VORBIS -DUSE_TREMOLO INCLUDES += -Ilibs/include/tremolo LIBS += -llibTremolo endif diff --git a/backends/platform/wince/README-WinCE.txt b/backends/platform/wince/README-WinCE.txt index f4cb00dcfa..86c627d764 100644 --- a/backends/platform/wince/README-WinCE.txt +++ b/backends/platform/wince/README-WinCE.txt @@ -1,29 +1,28 @@ ScummVM Windows CE FAQ Last updated: $Date$ -Release version: 0.11.0 +Release version: 0.12.0 ------------------------------------------------------------------------ New in this version ------------------- -0.11.0 -- Redesigned 'Free Look' action (Pocket PCs) -In order to accommodate for the requirements of the lure engine, the -usage characteristics of the 'Free Look' action have been improved. The -new behavior is available for use in all engines, but is is *strongly* -recommended for at least when playing 'Lure of the Temptress'. By using -the new scheme, when in 'Free Look' mode, it is now possible to enter -left clicks by clicking a second time near the current location of the -mouse pointer. Left and Right clicks at the current point location -are also available by using the respective actions' bound key. +0.12.0: +- Improved SMUSH support (deprecated 'Smush_force_redraw' option) +No skipped frames in Full Throttle action sequences. The 'Smush_force_redraw' +option is not needed/honored anymore. -- Reduced optimization build -The ScummVM executable has grown quite large, prohibiting some devices -from running memory demanding games (or any games at all). Code -optimization level has been reduced to offset the growth of the executable. -Games run slightly slower. This will be addressed before next release. +- Fixed MultiFuntion key in Full Throttle -- Several bugfixes +- Improved sound output +Fixed a long standing bug which led to distorted sound output in all games. + +- Switched to faster ogg vorbis library +Robin Watts' libTremolo is used for ogg vorbis (tremor) replay. Info patch +by Lostech. + +- New right click through double tap inhibiting option +Check out the 'no_doubletap_rightclick' option if double-tapping as a right +click input method annoys you. Patch by spookypeanut. ------------------------------------------------------------------------ @@ -109,10 +108,10 @@ and report your success ... How do I install ScummVM for Windows CE ? ----------------------------------------- -Simple! Unpack the release package on your desktop pc, then copy all its contents -to a folder on your device. Typically, you should at least have scummvm.exe, -modern.ini and modern.zip in the same directory. Finally, upload your beloved games -and fire it up :-) +Simple! Unpack the release package on your desktop pc, then copy all its +contents to a folder on your device. Typically, you should at least have +scummvm.exe, modern.ini and modern.zip in the same directory. Finally, upload +your beloved games and fire it up :-) Some devices (like Pocket PC 2000) require GAPI to be present. @@ -184,18 +183,19 @@ The following actions are available : * Right click : acts as a right mouse button click * Cursor : hide or display the mouse cursor * Free look : go in or out of free-look mode. In this mode, you can tap - the screen to look for interesting locations without walking. - Cling a second time near the pointer's location equals to left click. + the screen to look for interesting locations without + walking. Click a second time near the pointer's location + equals to a left click. * Zoom up : magnify the upper part of the screen for 640x480 games rendered on a QVGA device. * Zoom down : magnify the lower part of the screen for 640x480 games rendered on a QVGA device. - * Multi Function : this key performs a different function depending on the game - : Full Throttle -> win an action sequence (cheat) - : Fate of Atlantis -> sucker punch (cheat) - : Bargon -> F1 (start the game) - : All AGI games -> bring up the predictive input dialog - * Bind keys : map a key action to a device button + * Multi Function : performs a different function depending on the game : + Full Throttle -> win an action sequence (cheat) + Fate of Atlantis -> sucker punch (cheat) + Bargon -> F1 (start the game) + All AGI games -> bring up the predictive input dialog + * Bind keys map a key action to a device button * Up,Down,Left : Right, : emulate mouse/stylus behavior Left Click : @@ -245,11 +245,11 @@ the list of available actions for Smartphones: * Skip : skip a non interactive sequence, the current dialog or behaves like the ESC key on a regular keyboard * Zone : switch between the 3 different mouse zones - * Multi Function : this key performs a different function depending on the game - : Full Throttle -> win an action sequence (cheat) - : Fate of Atlantis -> sucker punch (cheat) - : Bargon -> F1 (start the game) - : All AGI games -> bring up the predictive input dialog + * Multi Function : performs a different function depending on the game + Full Throttle -> win an action sequence (cheat) + Fate of Atlantis -> sucker punch (cheat) + Bargon -> F1 (start the game) + All AGI games -> bring up the predictive input dialog * Bind keys : map a key action to a device button * Keyboard : hide or display the virtual keyboard * Rotate : rotate the screen (also rotates dpad keys) @@ -287,32 +287,34 @@ Some parameters are specific to this port : Game specific sections (f.e. [monkey2]) - performance options - * high_sample_rate bool Desktop quality (22 kHz) sound output if set. - 11 kHz otherwise. The default is 11 kHz. - If you have a fast device, you can set this to - true to enjoy better sound effects and music. + * high_sample_rate bool Desktop quality (22 kHz) sound output if + set. The default is 11 kHz. + If you have a fast device, you can set this + to true to enjoy better sound effects and + music. * FM_high_quality bool Desktop quality FM synthesis if set. Lower - quality otherwise. The default is low quality. - You can change this if you have a fast device. - * sound_thread_priority int Set the priority of the sound thread (0, 1, 2). - Depending on the release, this is set to 1 - internally (above normal). If you get sound - stuttering try setting this to a higher value. + quality otherwise. The default is low + quality. You can change this if you have a + fast device. + * sound_thread_priority int Set the priority of the sound thread (0, 1, + 2). Depending on the release, this is set + to 1 internally (above normal). + If you get sound stuttering try setting + this to a higher value. Set to 0 if your device is fast enough or if - you prefer better audio/video synchronization. - * Smush_force_redraw int Force a Smush frame redraw every X missed - frames. Mainly used for Full Throttle action - sequences. Setting it lower gives more - priority to screen redraws. Setting it higher - gives more priority to stylus/keyboard input. - The default is 30. + you prefer better audio/video sync. Game specific sections (f.e. [monkey2]) - game options - * landscape int 0: Portrait, 1: Landscape, 2: Inverse Landscape - You can also use this in the [scummvm] section - in QVGA Pocket PCs to display the launcher in - landscape, for example, at startup. + * landscape int 0: Portrait, 1: Landscape, + 2: Inverse Landscape. + You can also use this in the [scummvm] + section to display the launcher in landscape + for example, at startup. + * no_doubletap_rightclick int 1: Turn off the default behavior of + simulating a right-click when the screen is + double-tapped. + [scummvm] section - keys definition @@ -335,18 +337,18 @@ You can tweak these parameters to customize how the cursor is handled. consider being repeated. * repeatX int Number of key repeat events before changing horizontal cursor behaviour. - * stepX1 int Horizontal cursor offset value when the key is - not repeated. - * stepX2 int Horizontal cursor offset value when the key is - repeated less than repeatX. - * stepX3 int Horizontal cursor offset value when the key is - repeated more than repeatX. + * stepX1 int Horizontal cursor offset value when the key + is not repeated. + * stepX2 int Horizontal cursor offset value when the key + is repeated less than repeatX. + * stepX3 int Horizontal cursor offset value when the key + is repeated more than repeatX. * repeatY int Number of key repeat events before changing - vertical cursor behaviour. + vertical cursor behavior. * stepY1 int Vertical cursor offset value when the key is not repeated. - * stepY2 int Horizontal cursor offset value when the key is - repeated less than repeatY. + * stepY2 int Horizontal cursor offset value when the key + is repeated less than repeatY. * stepY3 int Vertical cursor offset value when the key is repeated more than repeatY. @@ -361,8 +363,8 @@ Game specific questions I need to press a special key ----------------------------- -Bring up the virtual keyboard. On Smartphones take a look at the Keyboard action above. -On Pocket PCs it's easier to double-tap at the top of the screen. +Bring up the virtual keyboard. On Smartphones take a look at the Keyboard +action above. On Pocket PCs it's easier to double-tap at the top of the screen. The panel is obscuring the playfield area ----------------------------------------- @@ -383,17 +385,18 @@ Bind and use the quit action to quit. I cannot rotate the screen to landscape/inverse landscape --------------------------------------------------------- -Depending on the video driver, ScummVM may opt to not provide such functionality. -In general, when ScummVM starts in normal "portrait" orientation, the device driver -reports better display characteristics and you should consider launching from portrait. +Depending on the video driver, ScummVM may opt to not provide such +functionality. In general, when ScummVM starts in normal "portrait" +orientation, the device driver reports better display characteristics and you +should consider launching from portrait. I'm having problems. Is there diagnostic output available ? ----------------------------------------------------------- Insert a line in the [scummvm] section of scummvm.ini with the following: debuglevel=1 -Run ScummVM. When it closes scummvm_stdout.txt and scummvm_stderr.txt files will be -available at the program directory (see section above). +Run ScummVM. When it closes scummvm_stdout.txt and scummvm_stderr.txt files +will be available at the program directory (see section above). ScummVM crashes and returns to desktop -------------------------------------- @@ -548,18 +551,19 @@ Use the Multi Function action. -- AGI engine games -- ---------------------- -Do you expect me to play these games on keyboard less devices ? +Do you expect me to play these games on keyboard-less devices ? --------------------------------------------------------------- Sure we do :-) -If you want to get some mileage on your stylus you can use the virtual keyboard. -There is a very useful alternative though, the AGI engine's predictive input dialog. -It requires a dictionary to be present. Just tap on the command line or use the -Multi Function action to bring it up. On Smartphones, when the dialog is shown -all key mapping is disabled temporarily (including mouse emulation). Input is -performed either by pressing the phone's numeric keypad keys and dpad enter to -close the dialog, or by navigating the buttons using the dpad arrows and pressing -with dpad enter. Check the main Readme file for more information on this. +If you want to get some mileage on your stylus you can use the virtual +keyboard. There is a very useful alternative though, the AGI engine's +predictive input dialog. It requires a dictionary to be present. Just tap on +the command line or use the Multi Function action to bring it up. On +Smartphones, when the dialog is shown all key mapping is disabled temporarily +(including mouse emulation). Input is performed either by pressing the phone's +numeric keypad keys and dpad enter to close the dialog, or by navigating the +buttons using the dpad arrows and pressing with dpad enter. Check the main +Readme file for more information on this. --------------------------- -- Lure of the Temptress -- @@ -595,8 +599,9 @@ I think I found a bug, ScummVM crashes in ... See the "Reporting Bugs" section in ScummVM readme. -If you have a Pocket PC or Handheld PC, be sure to include its resolution (obtained -on the second dialog displayed on the "About" menu) in your bug report. +If you have a Pocket PC or Handheld PC, be sure to include its resolution +(obtained on the second dialog displayed on the "About" menu) in your bug +report. If you cannot reproduce this bug on another ScummVM version, you can cross post your bug report on ScummVM forums. @@ -619,6 +624,26 @@ http://www.scummvm.org/ Old news follow ... ------------------------------------------------------------------------ +0.11.0: +- Redesigned 'Free Look' action (Pocket PCs) +In order to accommodate for the requirements of the lure engine, the +usage characteristics of the 'Free Look' action have been improved. The +new behavior is available for use in all engines, but is is *strongly* +recommended for at least when playing 'Lure of the Temptress'. By using +the new scheme, when in 'Free Look' mode, it is now possible to enter +left clicks by clicking a second time near the current location of the +mouse pointer. Left and Right clicks at the current point location +are also available by using the respective actions' bound key. + +- Reduced optimization build +The ScummVM executable has grown quite large, prohibiting some devices +from running memory demanding games (or any games at all). Code +optimization level has been reduced to offset the growth of the executable. +Games run slightly slower. This will be addressed before next release. + +- Several bugfixes + + 0.10.0: Major improvements have taken place in this version, mostly for behind- the-scenes stuff. First, we have migrated to GCC for building the Windows diff --git a/backends/platform/wince/missing/missing.cpp b/backends/platform/wince/missing/missing.cpp index c760b1f7df..f03f00bb9a 100644 --- a/backends/platform/wince/missing/missing.cpp +++ b/backends/platform/wince/missing/missing.cpp @@ -171,7 +171,7 @@ int _access(const char *path, int mode) { MultiByteToWideChar(CP_ACP, 0, path, -1, fname, sizeof(fname)/sizeof(TCHAR)); WIN32_FIND_DATA ffd; - HANDLE h=FindFirstFile(fname, &ffd); + HANDLE h = FindFirstFile(fname, &ffd); FindClose(h); if (h == INVALID_HANDLE_VALUE) @@ -179,9 +179,14 @@ int _access(const char *path, int mode) { if (ffd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) { // WORKAROUND: WinCE (or the emulator) sometimes returns bogus direcotry - // hits for files that don't exist. Checking for the same fname twice + // hits for files that don't exist. TRIPLE checking for the same fname // seems to weed out those false positives. - HANDLE h=FindFirstFile(fname, &ffd); + // Exhibited in kyra engine. + HANDLE h = FindFirstFile(fname, &ffd); + FindClose(h); + if (h == INVALID_HANDLE_VALUE) + return -1; //Can't find file + h = FindFirstFile(fname, &ffd); FindClose(h); if (h == INVALID_HANDLE_VALUE) return -1; //Can't find file diff --git a/backends/platform/wince/wince-sdl.cpp b/backends/platform/wince/wince-sdl.cpp index 3f16b4fdd1..f09a483086 100644 --- a/backends/platform/wince/wince-sdl.cpp +++ b/backends/platform/wince/wince-sdl.cpp @@ -461,7 +461,7 @@ OSystem_WINCE3::OSystem_WINCE3() : OSystem_SDL(), _orientationLandscape(0), _newOrientation(0), _panelInitialized(false), _panelVisible(true), _panelStateForced(false), _forceHideMouse(false), _unfilteredkeys(false), _freeLook(false), _forcePanelInvisible(false), _toolbarHighDrawn(false), _zoomUp(false), _zoomDown(false), - _scalersChanged(false), _lastKeyPressed(0), _tapTime(0), _closeClick(false), + _scalersChanged(false), _lastKeyPressed(0), _tapTime(0), _closeClick(false), _noDoubleTapRMB(false), _saveToolbarState(false), _saveActiveToolbar(NAME_MAIN_PANEL), _rbutton(false), _hasfocus(true), _usesEmulatedMouse(false), _mouseBackupOld(NULL), _mouseBackupToolbar(NULL), _mouseBackupDim(0) { @@ -805,8 +805,16 @@ void OSystem_WINCE3::setupMixer() { debug(1, "Sound opened OK, mixing at %d Hz", _sampleRate); // Re-create mixer to match the output rate + int vol1 = _mixer->getVolumeForSoundType(Audio::Mixer::kPlainSoundType); + int vol2 = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType); + int vol3 = _mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType); + int vol4 = _mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType); delete(_mixer); _mixer = new Audio::MixerImpl(this); + _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, vol1); + _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol2); + _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, vol3); + _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, vol4); _mixer->setOutputRate(_sampleRate); _mixer->setReady(true); SDL_PauseAudio(0); @@ -1051,14 +1059,11 @@ void OSystem_WINCE3::update_game_settings() { panel->setVisible(false); _saveToolbarState = true; - - // Set Smush Force Redraw rate for Full Throttle - if (!ConfMan.hasKey("Smush_force_redraw")) { - ConfMan.setInt("Smush_force_redraw", 30); - ConfMan.flushToDisk(); - } } + if (ConfMan.hasKey("no_doubletap_rightclick")) + _noDoubleTapRMB = ConfMan.getBool("no_doubletap_rightclick"); + compute_sample_rate(); } @@ -2254,15 +2259,18 @@ bool OSystem_WINCE3::pollEvent(Common::Event &event) { _lastKeyPressed = 0; event.type = Common::EVENT_PREDICTIVE_DIALOG; return true; - } - - event.type = Common::EVENT_KEYDOWN; + } event.type = Common::EVENT_KEYDOWN; if (!_unfilteredkeys) event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; else event.kbd.keycode = (Common::KeyCode)mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys); event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys); + if (ev.key.keysym.mod == KMOD_RESERVED && ev.key.keysym.unicode == KMOD_SHIFT) { + event.kbd.ascii ^= 0x20; + event.kbd.flags = Common::KBD_SHIFT; + } + return true; case SDL_KEYUP: @@ -2290,6 +2298,11 @@ bool OSystem_WINCE3::pollEvent(Common::Event &event) { event.kbd.keycode = (Common::KeyCode)mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys); event.kbd.ascii = mapKeyCE(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode, _unfilteredkeys); + if (ev.key.keysym.mod == KMOD_RESERVED && ev.key.keysym.unicode == KMOD_SHIFT) { + event.kbd.ascii ^= 0x20; + event.kbd.flags = Common::KBD_SHIFT; + } + return true; case SDL_MOUSEMOTION: @@ -2324,7 +2337,7 @@ bool OSystem_WINCE3::pollEvent(Common::Event &event) { if (_closeClick && (GetTickCount() - _tapTime < 1000)) { if (event.mouse.y <= 20 && _panelInitialized) { // top of screen (show panel) swap_panel_visibility(); - } else { // right click + } else if (!_noDoubleTapRMB) { // right click event.type = Common::EVENT_RBUTTONDOWN; _rbutton = true; } diff --git a/backends/platform/wince/wince-sdl.h b/backends/platform/wince/wince-sdl.h index 8853c156d8..ece8c9b7b1 100644 --- a/backends/platform/wince/wince-sdl.h +++ b/backends/platform/wince/wince-sdl.h @@ -200,6 +200,7 @@ private: bool _zoomUp; // zooming up mode bool _zoomDown; // zooming down mode + bool _noDoubleTapRMB; // disable double tap -> rmb click bool _rbutton; // double tap -> right button simulation bool _closeClick; // flag when taps are spatially close together |