mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
ALL: Sync with ScummVM - rev. 823c2f899b
This commit is contained in:
+11
-2
@@ -9,6 +9,7 @@ lib*.a
|
||||
/config.log
|
||||
/residualvm
|
||||
/residualvm-static
|
||||
/ResidualVMDockTilePlugin*
|
||||
/config.h
|
||||
/config.mk
|
||||
/.gdb_history
|
||||
@@ -19,6 +20,7 @@ lib*.a
|
||||
/MT32_CONTROL.ROM
|
||||
/MT32_PCM.ROM
|
||||
/ResidualVM.app
|
||||
/residualvm.docktileplugin
|
||||
/residualvm-ps3.pkg
|
||||
/*.ipk
|
||||
/*.dmg
|
||||
@@ -29,6 +31,7 @@ lib*.a
|
||||
/Icon.*
|
||||
/*.m4b
|
||||
/*.lab
|
||||
/*.dat
|
||||
|
||||
/build
|
||||
/staging
|
||||
@@ -79,6 +82,7 @@ project.xcworkspace
|
||||
/test/*.dSYM
|
||||
|
||||
/devtools/create_project/create_project
|
||||
/devtools/create_translations/create_translations
|
||||
|
||||
#ignore thumbnails created by windows
|
||||
Thumbs.db
|
||||
@@ -113,10 +117,15 @@ ipch/
|
||||
*.vcxproj*
|
||||
*.bat
|
||||
*.tss
|
||||
*.VC.db
|
||||
|
||||
#Ignore default Visual Studio build folders
|
||||
[Dd]ebug*/
|
||||
[Rr]elease*/
|
||||
[Dd]ebug/
|
||||
[Rr]elease/
|
||||
[Dd]ebug32/
|
||||
[Rr]elease32/
|
||||
[Dd]ebug64/
|
||||
[Rr]elease64/
|
||||
LLVM32/
|
||||
LLVM64/
|
||||
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
language:
|
||||
- cpp
|
||||
|
||||
sudo: false
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++ make
|
||||
- libsdl1.2-dev
|
||||
- libjpeg62-turbo-dev
|
||||
- libmpeg2-4-dev
|
||||
- libogg-dev
|
||||
- libvorbis-dev
|
||||
- libflac-dev
|
||||
- libmad0-dev
|
||||
- libpng-dev
|
||||
- libglew-dev
|
||||
- libtheora-dev
|
||||
- libfaad-dev
|
||||
- libfluidsynth-dev
|
||||
- libfreetype6-dev
|
||||
- zlib1g-dev
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
||||
os:
|
||||
- linux
|
||||
|
||||
script:
|
||||
- ./configure --enable-all-engines --disable-eventrecorder
|
||||
- make -j 2
|
||||
- make test
|
||||
- make devtools
|
||||
@@ -59,214 +59,404 @@ Copyright (C) 2001-2016 by the following:
|
||||
If you have contributed to this project then you deserve to be on this
|
||||
list. Contact us (see: AUTHORS) and we'll add you.
|
||||
|
||||
Tore Anderson
|
||||
Manuel Alfayate
|
||||
Torbjorn Andersson
|
||||
Tore Anderson
|
||||
Matteo Angelino
|
||||
Chris Apers
|
||||
Adrian Astley
|
||||
Bertrand Augereau
|
||||
Ori Avtalion
|
||||
Nicolas Bacca
|
||||
Dobo Balazs
|
||||
Daniel Balsom
|
||||
Yotam Barnoy
|
||||
Fabio Battaglia
|
||||
Vincent Benony
|
||||
Alex Bevilacqua
|
||||
Laurent Blume
|
||||
Bastien Bouclet
|
||||
Arnaud Boutonne
|
||||
Francois-R Boyer
|
||||
Peter Bozso
|
||||
Jurgen Braam
|
||||
Ralph Brorsen
|
||||
James Brown
|
||||
Henry Bush
|
||||
Stuart Caie
|
||||
Rainer Canavan
|
||||
Ben Castricum
|
||||
Xiaojun Chen
|
||||
Jamieson Christian
|
||||
Ryan Clark
|
||||
William Claydon
|
||||
Fabien Coeurjoly
|
||||
Marcus Comstedt
|
||||
David Corrales-Lopez
|
||||
Paolo Costabel
|
||||
Robert Crossfield
|
||||
Thierry Crozat
|
||||
Vyacheslav Dikonov
|
||||
Paul David Doherty
|
||||
Martin Doucha
|
||||
Ivan Dubrov
|
||||
Frantisek Dufka
|
||||
Sylvain Dupont
|
||||
Joachim Eberhard
|
||||
Thomas Edvalson
|
||||
Oystein Eftevaag
|
||||
Kovacs Endre Janos
|
||||
David Eriksson
|
||||
Thomas Fach-Pedersen
|
||||
Yaroslav Fedevych
|
||||
Jerome Fisher
|
||||
Hampus Flink
|
||||
Hans-Joerg Frieden
|
||||
Greg Frieger
|
||||
Tom Frost
|
||||
Stuart George
|
||||
Paul Gilbert
|
||||
Jean Marc Gimenez
|
||||
Robert Goeffringmann
|
||||
Victor Gonzalez
|
||||
GrajPoPolsku.pl Team
|
||||
Chris Gray
|
||||
Jonathan Gray
|
||||
Tobias Gunkel
|
||||
Benjamin Haisch
|
||||
Vincent Hamm
|
||||
Ruediger Hanke
|
||||
Matt Hargett
|
||||
Andre Heider
|
||||
Sven Hesse
|
||||
Jochen Hoenicke
|
||||
Matthew Hoops
|
||||
Max Horn
|
||||
Travis Howell
|
||||
Janne Huttunen
|
||||
Ravi I.
|
||||
Felix Jakschitsch
|
||||
Kovacs Endre Janos
|
||||
Jeroen Janssen
|
||||
Emmanuel Jeandel
|
||||
Dmitry Jemerov
|
||||
David Jensen
|
||||
Florian Kagerer
|
||||
Keith Kaisershot
|
||||
Filippos Karapetis
|
||||
Andreas Karlsson
|
||||
Denis Kasak
|
||||
Chris Kehler
|
||||
Robert Kelsen
|
||||
Ismail Khatib
|
||||
Oliver Kiehl
|
||||
Martin Kiewitz
|
||||
Pawel Kolodziejski
|
||||
George Kormendi
|
||||
Mutwin Kraus
|
||||
Stefan Kristiansson
|
||||
Andrew Kurushin
|
||||
Daniel ter Laan
|
||||
Hugo Labrande
|
||||
Christopher T. Lansdown
|
||||
Sergey Lapin
|
||||
Angus Lees
|
||||
Rickard Lind
|
||||
Max Lingua
|
||||
Lubomyr Lisen
|
||||
Ivan Lukyanov
|
||||
Tomas Maidagan
|
||||
Hubert Maier
|
||||
Johannes Manhave
|
||||
Lothar Serra Mari
|
||||
Vicent Marti
|
||||
Claudio Matsuoka
|
||||
Thomas Mayer
|
||||
Robert Megone
|
||||
Vladimir Menshakov
|
||||
Alyssa Milburn
|
||||
Neil Millstone
|
||||
Dark Minister
|
||||
Gregory Montoir
|
||||
Peter Moraliyski
|
||||
Carl Muckenhoupt
|
||||
Alejandro Gomez de la Munoza
|
||||
Sean Murray
|
||||
Kostas Nakos
|
||||
Mikesch Nepomuk
|
||||
Jeremy Newman
|
||||
Anders Baden Nielsen
|
||||
Juha Niemimaki
|
||||
Walter van Niftrik
|
||||
Nicolas Noble
|
||||
Steffen Nyeland
|
||||
Rune Orsval
|
||||
Chris Page
|
||||
Willem Jan Palenstijn
|
||||
Stefan Parviainen
|
||||
Solomon Peachy
|
||||
Lars Persson
|
||||
Joost Peters
|
||||
Tim Phillips
|
||||
Robey Pointer
|
||||
Jordi Vilalta Prat
|
||||
Magnus Reftel
|
||||
Christoph Reichenbach
|
||||
George Reid
|
||||
Klaus Reimer
|
||||
Andreas Roever
|
||||
Edward Rudd
|
||||
Toni Saarela
|
||||
Kari Salminen
|
||||
Eugene Sandulenko
|
||||
Santiago G. Sanz
|
||||
Simon Sawatzki
|
||||
Daniel Schepler
|
||||
Dominik Scherer
|
||||
Johannes Schickel
|
||||
Luc Schrijvers
|
||||
Zbynik Schwarz
|
||||
Keith Scroggins
|
||||
Dan Serban
|
||||
Lars Skovlund
|
||||
Paul Smedley
|
||||
Colin Snover
|
||||
Tarek Soliman
|
||||
Einar Johan T. Somaaen
|
||||
Andre Souza
|
||||
Robert Spalek
|
||||
Rink Springer
|
||||
Won Star
|
||||
Markus Strangl
|
||||
Ludvig Strigeus
|
||||
Fedor Strizhniou
|
||||
David Symonds
|
||||
Jordi Vilalta
|
||||
Rainer De Temple
|
||||
Julien Templier
|
||||
Sean Terrell
|
||||
Tobia Tesan
|
||||
Scott Thomas
|
||||
David Turner
|
||||
Lionel Ulmer
|
||||
Mikel Iturbe Urretxa
|
||||
Hugues Valois
|
||||
Petr Vyhnak
|
||||
Chris Warren-Smith
|
||||
Robin Watts
|
||||
Lukasz Watka
|
||||
David Weinehall
|
||||
Fredrik Wendel
|
||||
John Willis
|
||||
Anton Yarcev
|
||||
Bas Zoetekouw
|
||||
Jezar
|
||||
n0p
|
||||
peres
|
||||
Quietust
|
||||
ScummBR Team
|
||||
Raina
|
||||
|
||||
|
||||
Patches contributed by:
|
||||
|
||||
Laura Abbott "sageofminerva"
|
||||
Vikram Aggarwal "youngelf"
|
||||
the rara avis "theraraavis"
|
||||
Norbert Bajko
|
||||
Giovanni Bajo
|
||||
Matan Bareket
|
||||
Dieter Baron "dillo"
|
||||
Kevin Becker
|
||||
Alban Bedel "albeu"
|
||||
Bodo Bellut "bellut"
|
||||
Bramvandijk "bramvandijk"
|
||||
Nagy Bendeguz
|
||||
Andreas Bierfert "awjb"
|
||||
Kaustav Biswas
|
||||
Elio Blanca "eblanca76"
|
||||
Martin Bohm
|
||||
David Breakey "dbreakey"
|
||||
Michael du Breuil "WickedShell"
|
||||
Michael Brown
|
||||
Robert Buchholz "prendi"
|
||||
Rainer Canavan "canavan"
|
||||
Sander Buskens
|
||||
Giulio Camuffo
|
||||
Kevin Carnes
|
||||
Mathieu Carot "yokna"
|
||||
Stefano Ceccherini "jackburton"
|
||||
Travis S Coady "theealien"
|
||||
Josh Coalson "jcoalson"
|
||||
Curt Coder
|
||||
Thomas Combeleran "hibernatus"
|
||||
Patrick Combet
|
||||
Kees Cook "keescook"
|
||||
Carlos Corbacho "cathectic"
|
||||
Andrea Corna
|
||||
Roberto Costa "fiix76"
|
||||
dc france "erwan2004"
|
||||
dewt "mncl"
|
||||
Martin Doucha "next_ghost"
|
||||
Eric Culp
|
||||
Alexander Dergunov
|
||||
Alexandre Detiste
|
||||
Roman Donchenko
|
||||
Heather Douglass
|
||||
Michael Drueing "doc_wagon"
|
||||
Michael du Breuil "WickedShell"
|
||||
dubsdj
|
||||
Matthew Duggan "stauff1"
|
||||
Barry Duncan
|
||||
Olivier Duverne "richiefs"
|
||||
Andrei Dziahel "develop7"
|
||||
John Eckerdal "johneck"
|
||||
Thomas Fach-Pedersen "madm00se"
|
||||
Florent "flobo"
|
||||
Florob "florob"
|
||||
Abdeselam El-Haman
|
||||
Henrik Engqvist
|
||||
Mike Frysinger "vapier"
|
||||
Bence Gazder
|
||||
Chris Gelatt "kreeblah"
|
||||
Jens Georg "phako"
|
||||
Nicolas George "cigaes"
|
||||
Martin Gerhardy
|
||||
Jonathan Gevaryahu "lord_nightmare"
|
||||
Boris Gnezdilov
|
||||
Tobias Gruetzmacher "tobig"
|
||||
Damien Guard "damienguard"
|
||||
Tobias Gunkel "tobigun"
|
||||
Matti Hamalainen "ccrtnsp"
|
||||
Matt Hargett "matt_hargett"
|
||||
Lauri Harsila
|
||||
Stefan Haubenthal "polluks"
|
||||
Gavin Hayler
|
||||
Alexander Holler "holler"
|
||||
Enrico Horn
|
||||
Falk Hueffner "mellum"
|
||||
Casey Hutchinson "nnooiissee"
|
||||
j0tt
|
||||
Tomas Jakobsson
|
||||
Gregor Jasny "gjasny"
|
||||
Jellby "jellby"
|
||||
Joerg "macdrega"
|
||||
Matt Johnson "mattjon"
|
||||
Nicolas Joly "njoly"
|
||||
KeithS "keithscr"
|
||||
Yusuke Kamiyamane
|
||||
Martin Kennedy
|
||||
Stephen Kennedy
|
||||
Sam Kenny "sam_k"
|
||||
Koen Kooi "koenkooi"
|
||||
Christoph Korn
|
||||
Christian Krause
|
||||
Till Kresslein
|
||||
Zygmunt Krynicki "zygoon"
|
||||
Janne Kujanpaa "jukuja"
|
||||
Neeraj Kumar
|
||||
Oleksiy Kurochko
|
||||
Jay Lanagan "r0ni"
|
||||
Norbert Lange "nolange"
|
||||
Manuel Lauss "mlau2"
|
||||
Rolf Leggewie "leggewie"
|
||||
Jim Leiterman
|
||||
Matt Lewandowsky
|
||||
Chenbo Li
|
||||
Rob Loach
|
||||
Duncan Lock "dflock"
|
||||
Mark Lodato "itsr0y"
|
||||
Fridvin Logi "phillip_j_fry"
|
||||
Lostech "lostech"
|
||||
Michael Lojkovic
|
||||
Borja Lorente Escobar
|
||||
Georg Lukas "ge0rg"
|
||||
Artem Lukoyanov
|
||||
Michael Madsen "pidgeot"
|
||||
Matthias Mailander
|
||||
Narek Mailian
|
||||
Christoph Mallon
|
||||
Engin Manap
|
||||
Dmitry Marakasov "amdmi3"
|
||||
Alejandro Marzini "vgvgf"
|
||||
Connor McLeod "mcleod2032"
|
||||
Mickey McMurray "metafox"
|
||||
Vladimir Menshakov "megath"
|
||||
Adam Metcalf "gamblore"
|
||||
Nicola Mettifogo
|
||||
Frank Meyering "frank_m24"
|
||||
Gael Le Migno "kilobug"
|
||||
Etienne Millon
|
||||
Andy Molloy "maloi"
|
||||
Sean Murrau "lightcast"
|
||||
Omer Mor
|
||||
Armin Mueller "arm_in"
|
||||
Sean Murrau "lightcast"
|
||||
Andrea Musuruane "musuruan"
|
||||
KO Myung-Hun "lvzuufx"
|
||||
Markus Napp "meist3r"
|
||||
Peter Naulls "pnaulls"
|
||||
Christian Neumair "mannythegnome"
|
||||
Nicos "anarxia"
|
||||
Juha Niemimaki "capehill"
|
||||
Hannes Niederhausen
|
||||
Markus Niemisto "niemisto"
|
||||
ole
|
||||
Bastien Nocera
|
||||
Jody Northup
|
||||
Julian Ospald
|
||||
Christopher Page
|
||||
Chris Paras "paras_rasmatazz"
|
||||
Aubin Paul "outlyer"
|
||||
Michael Pearce
|
||||
Vincent Pelletier "subdino"
|
||||
phi1
|
||||
Pix2 "pix2"
|
||||
Jussi Pitkanen
|
||||
Carsten Pohl "carstenpohl"
|
||||
Tony Puccinelli
|
||||
Markus Pyykko "mankeli"
|
||||
Richard "trinity78"
|
||||
Felix Riemann "kirschsaft"
|
||||
Rodrigo Rebello
|
||||
Alexander Reim
|
||||
Thomas Richter "thorfdbg"
|
||||
Felix Riemann "kirschsaft"
|
||||
Timo Roehling "t1m0"
|
||||
Andreas Roever "roever"
|
||||
Jonathan Rogers "jonner"
|
||||
Enrico Rolfi
|
||||
Doron Rosenberg
|
||||
Marek Roth "logicdeluxe"
|
||||
David Russo
|
||||
Uwe Ryssel "uweryssel"
|
||||
Simon Sawatzki "simsaw"
|
||||
Scarlatti "escarlate"
|
||||
Daniel Schepler "dschepler"
|
||||
Florian Schmitt "fatpenguin"
|
||||
Mark Schreiber "mark7"
|
||||
Ben Shadwick "benshadwick"
|
||||
Rodrigo Silva
|
||||
Jean-Yves Simon "lethalwp"
|
||||
Andrej Sinicyn "andrej4000"
|
||||
Andre Souza "luke_br"
|
||||
spookypeanut "spookypeanut"
|
||||
Dmitry Smirnov
|
||||
Steve Stavropoulos "isnothere"
|
||||
Daniel Steinberger "amorphousshape"
|
||||
Sven Strothoff "dataslayer"
|
||||
Andrea Suatoni "mrhandler"
|
||||
tbcarey
|
||||
Tim "tipabu"
|
||||
Max Tabachenko
|
||||
DOSBox Team
|
||||
Sarien Team
|
||||
Joel Teichroeb
|
||||
Jimmi Thogersen
|
||||
Alexander Tkachov
|
||||
Pino Toscano
|
||||
Luigi Toscano "ltosky"
|
||||
Xavier Trochu "xtrochu"
|
||||
Vasyl Tsvirkunov
|
||||
Michal Tulacek "tutchek"
|
||||
Michael Udaltsov "cccp99"
|
||||
Joni Vahamaki
|
||||
Kristof Vansant "lupusbe"
|
||||
Aaryaman Vasishta
|
||||
Tim Walters "realmz"
|
||||
David Weinehall "weine"
|
||||
Eric A. Welsh "eweish42"
|
||||
Yudhi Widyatama "yudhi97"
|
||||
Jakub Wilk
|
||||
Kieron Wilkinson
|
||||
Robert Wohlrab "moshroum"
|
||||
Xanathar "xanathar"
|
||||
James Woodcock
|
||||
Grant Yeager "glo_kidd"
|
||||
Benjamin W. Zale "junior_aepi"
|
||||
Yotam Barnoy "bluddy"
|
||||
Tom Frost "TomFrost"
|
||||
Kamil Zbrog
|
||||
Michal Ziabkowski
|
||||
Bramvandijk "bramvandijk"
|
||||
Canadacow
|
||||
countingpine
|
||||
Damien
|
||||
dc france "erwan2004"
|
||||
dewt "mncl"
|
||||
dubsdj
|
||||
Florent "flobo"
|
||||
Florob "florob"
|
||||
j0tt
|
||||
Jellby "jellby"
|
||||
Joerg "macdrega"
|
||||
Lostech "lostech"
|
||||
Nicos "anarxia"
|
||||
ole
|
||||
phi1
|
||||
Pix2 "pix2"
|
||||
Richard "trinity78"
|
||||
Scarlatti "escarlate"
|
||||
the rara avis "theraraavis"
|
||||
Tim "tipabu"
|
||||
vandalo
|
||||
Xanathar "xanathar"
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "audio/softsynth/emumidi.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/error.h"
|
||||
#include "common/scummsys.h"
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include "common/util.h"
|
||||
|
||||
#include "audio/decoders/3do.h"
|
||||
#include "audio/decoders/raw.h"
|
||||
#include "audio/decoders/adpcm_intern.h"
|
||||
|
||||
namespace Audio {
|
||||
|
||||
@@ -31,19 +31,12 @@
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/types.h"
|
||||
#include "common/substream.h"
|
||||
#include "common/stream.h"
|
||||
|
||||
#include "audio/audiostream.h"
|
||||
#include "audio/decoders/raw.h"
|
||||
|
||||
namespace Common {
|
||||
class SeekableReadStream;
|
||||
}
|
||||
|
||||
namespace Audio {
|
||||
|
||||
class SeekableAudioStream;
|
||||
|
||||
// amount of bytes to be used within the decoder classes as buffers
|
||||
#define AUDIO_3DO_CACHE_SIZE 1024
|
||||
|
||||
|
||||
@@ -320,10 +320,11 @@ int MS_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {
|
||||
_decodedSamples[_decodedSampleCount++] = decodeMS(&_status.ch[0], (data >> 4) & 0x0f);
|
||||
_decodedSamples[_decodedSampleCount++] = decodeMS(&_status.ch[_channels - 1], data & 0x0f);
|
||||
}
|
||||
_decodedSampleIndex = 0;
|
||||
}
|
||||
|
||||
// (1 - (count - 1)) ensures that _decodedSamples acts as a FIFO of depth 2
|
||||
buffer[samples] = _decodedSamples[1 - (_decodedSampleCount - 1)];
|
||||
// _decodedSamples acts as a FIFO of depth 2 or 4;
|
||||
buffer[samples] = _decodedSamples[_decodedSampleIndex++];
|
||||
_decodedSampleCount--;
|
||||
}
|
||||
|
||||
@@ -433,7 +434,7 @@ int16 Ima_ADPCMStream::decodeIMA(byte code, int channel) {
|
||||
return samp;
|
||||
}
|
||||
|
||||
RewindableAudioStream *makeADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, ADPCMType type, int rate, int channels, uint32 blockAlign) {
|
||||
SeekableAudioStream *makeADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, ADPCMType type, int rate, int channels, uint32 blockAlign) {
|
||||
// If size is 0, report the entire size of the stream
|
||||
if (!size)
|
||||
size = stream->size();
|
||||
|
||||
@@ -45,7 +45,7 @@ class SeekableReadStream;
|
||||
namespace Audio {
|
||||
|
||||
class PacketizedAudioStream;
|
||||
class RewindableAudioStream;
|
||||
class SeekableAudioStream;
|
||||
|
||||
// There are several types of ADPCM encoding, only some are supported here
|
||||
// For all the different encodings, refer to:
|
||||
@@ -74,7 +74,7 @@ enum ADPCMType {
|
||||
* @param blockAlign block alignment ???
|
||||
* @return a new RewindableAudioStream, or NULL, if an error occurred
|
||||
*/
|
||||
RewindableAudioStream *makeADPCMStream(
|
||||
SeekableAudioStream *makeADPCMStream(
|
||||
Common::SeekableReadStream *stream,
|
||||
DisposeAfterUse::Flag disposeAfterUse,
|
||||
uint32 size, ADPCMType type,
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
namespace Audio {
|
||||
|
||||
class ADPCMStream : public RewindableAudioStream {
|
||||
class ADPCMStream : public SeekableAudioStream {
|
||||
protected:
|
||||
Common::DisposablePtr<Common::SeekableReadStream> _stream;
|
||||
int32 _startpos;
|
||||
@@ -67,6 +67,8 @@ public:
|
||||
virtual int getRate() const { return _rate; }
|
||||
|
||||
virtual bool rewind();
|
||||
virtual bool seek(const Timestamp &where) { return false; }
|
||||
virtual Timestamp getLength() const { return -1; }
|
||||
|
||||
/**
|
||||
* This table is used by some ADPCM variants (IMA and OKI) to adjust the
|
||||
@@ -207,6 +209,7 @@ public:
|
||||
error("MS_ADPCMStream(): blockAlign isn't specified for MS ADPCM");
|
||||
memset(&_status, 0, sizeof(_status));
|
||||
_decodedSampleCount = 0;
|
||||
_decodedSampleIndex = 0;
|
||||
}
|
||||
|
||||
virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos) && (_decodedSampleCount == 0); }
|
||||
@@ -218,6 +221,7 @@ protected:
|
||||
|
||||
private:
|
||||
uint8 _decodedSampleCount;
|
||||
uint8 _decodedSampleIndex;
|
||||
int16 _decodedSamples[4];
|
||||
};
|
||||
|
||||
|
||||
@@ -129,6 +129,8 @@ RewindableAudioStream *makeAIFFStream(Common::SeekableReadStream *stream, Dispos
|
||||
foundSSND = true;
|
||||
/* uint32 offset = */ stream->readUint32BE();
|
||||
/* uint32 blockAlign = */ stream->readUint32BE();
|
||||
if (dataStream)
|
||||
delete dataStream;
|
||||
dataStream = new Common::SeekableSubReadStream(stream, stream->pos(), stream->pos() + length - 8, disposeAfterUse);
|
||||
break;
|
||||
case MKTAG('F', 'V', 'E', 'R'):
|
||||
@@ -154,7 +156,7 @@ RewindableAudioStream *makeAIFFStream(Common::SeekableReadStream *stream, Dispos
|
||||
return 0;
|
||||
default:
|
||||
debug(1, "Skipping AIFF '%s' chunk", tag2str(tag));
|
||||
break;
|
||||
break;
|
||||
}
|
||||
|
||||
stream->seek(pos + length + (length & 1)); // ensure we're also word-aligned
|
||||
@@ -203,7 +205,7 @@ RewindableAudioStream *makeAIFFStream(Common::SeekableReadStream *stream, Dispos
|
||||
if (codec == MKTAG('s', 'o', 'w', 't'))
|
||||
rawFlags |= Audio::FLAG_LITTLE_ENDIAN;
|
||||
|
||||
return makeRawStream(dataStream, rate, rawFlags);
|
||||
return makeRawStream(dataStream, rate, rawFlags);
|
||||
}
|
||||
case MKTAG('i', 'm', 'a', '4'):
|
||||
// TODO: Use QT IMA ADPCM
|
||||
@@ -212,7 +214,7 @@ RewindableAudioStream *makeAIFFStream(Common::SeekableReadStream *stream, Dispos
|
||||
case MKTAG('Q', 'D', 'M', '2'):
|
||||
// TODO: Need to figure out how to integrate this
|
||||
// (But hopefully never needed)
|
||||
warning("Unhandled AIFF-C QDM2 compression");
|
||||
warning("Unhandled AIFF-C QDM2 compression");
|
||||
break;
|
||||
case MKTAG('A', 'D', 'P', '4'):
|
||||
// ADP4 on 3DO
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
* - sword25
|
||||
* - touche
|
||||
* - tucker
|
||||
* - wintermute
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_VORBIS_H
|
||||
|
||||
@@ -158,7 +158,7 @@ bool loadWAVFromStream(Common::SeekableReadStream &stream, int &size, int &rate,
|
||||
return true;
|
||||
}
|
||||
|
||||
RewindableAudioStream *makeWAVStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse) {
|
||||
SeekableAudioStream *makeWAVStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse) {
|
||||
int size, rate;
|
||||
byte flags;
|
||||
uint16 type;
|
||||
|
||||
@@ -56,7 +56,7 @@ class SeekableReadStream;
|
||||
|
||||
namespace Audio {
|
||||
|
||||
class RewindableAudioStream;
|
||||
class SeekableAudioStream;
|
||||
|
||||
/**
|
||||
* Try to load a WAVE from the given seekable stream. Returns true if
|
||||
@@ -82,9 +82,9 @@ extern bool loadWAVFromStream(
|
||||
*
|
||||
* @param stream the SeekableReadStream from which to read the WAVE data
|
||||
* @param disposeAfterUse whether to delete the stream after use
|
||||
* @return a new RewindableAudioStream, or NULL, if an error occurred
|
||||
* @return a new SeekableAudioStream, or NULL, if an error occurred
|
||||
*/
|
||||
RewindableAudioStream *makeWAVStream(
|
||||
SeekableAudioStream *makeWAVStream(
|
||||
Common::SeekableReadStream *stream,
|
||||
DisposeAfterUse::Flag disposeAfterUse);
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#include "common/textconsole.h"
|
||||
|
||||
#include "audio/fmopl.h"
|
||||
#include "audio/softsynth/emumidi.h"
|
||||
|
||||
namespace Audio {
|
||||
|
||||
|
||||
@@ -140,10 +140,7 @@ MidiDriver_MT32::MidiDriver_MT32(Audio::Mixer *mixer) : MidiDriver_Emulated(mixe
|
||||
}
|
||||
_reportHandler = NULL;
|
||||
_synth = NULL;
|
||||
// Unfortunately bugs in the emulator cause inaccurate tuning
|
||||
// at rates other than 32KHz, thus we produce data at 32KHz and
|
||||
// rely on Mixer to convert.
|
||||
_outputRate = 32000; //_mixer->getOutputRate();
|
||||
_outputRate = 0;
|
||||
_initializing = false;
|
||||
|
||||
// Initialized in open()
|
||||
@@ -180,7 +177,6 @@ int MidiDriver_MT32::open() {
|
||||
if (_isOpen)
|
||||
return MERR_ALREADY_OPEN;
|
||||
|
||||
MidiDriver_Emulated::open();
|
||||
_reportHandler = new MT32Emu::ReportHandlerScummVM();
|
||||
_synth = new MT32Emu::Synth(_reportHandler);
|
||||
|
||||
@@ -212,6 +208,18 @@ int MidiDriver_MT32::open() {
|
||||
double gain = (double)ConfMan.getInt("midi_gain") / 100.0;
|
||||
_synth->setOutputGain(1.0f * gain);
|
||||
_synth->setReverbOutputGain(0.68f * gain);
|
||||
// We let the synthesizer play MIDI messages immediately. Our MIDI
|
||||
// handling is synchronous to sample generation. This makes delaying MIDI
|
||||
// events result in odd sound output in some cases. For example, the
|
||||
// shattering window in the Indiana Jones and the Fate of Atlantis intro
|
||||
// will sound like a bell if we use any delay here.
|
||||
// Bug #6242 "AUDIO: Built-In MT-32 MUNT Produces Wrong Sounds".
|
||||
_synth->setMIDIDelayMode(MT32Emu::MIDIDelayMode_IMMEDIATE);
|
||||
|
||||
// We need to report the sample rate MUNT renders at as sample rate of our
|
||||
// AudioStream.
|
||||
_outputRate = _synth->getStereoOutputSampleRate();
|
||||
MidiDriver_Emulated::open();
|
||||
|
||||
_initializing = false;
|
||||
|
||||
|
||||
@@ -0,0 +1,199 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Original license header:
|
||||
*
|
||||
* Cabal - Legacy Game Implementations
|
||||
*
|
||||
* Cabal is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "backends/audiocd/audiocd-stream.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
AudioCDStream::AudioCDStream() : _buffer(), _frame(0), _bufferPos(0), _bufferFrame(0), _forceStop(false) {
|
||||
}
|
||||
|
||||
AudioCDStream::~AudioCDStream() {
|
||||
// Stop the timer; the subclass needs to do this,
|
||||
// so this is just a last resort.
|
||||
stopTimer();
|
||||
|
||||
// Clear any buffered frames
|
||||
emptyQueue();
|
||||
}
|
||||
|
||||
int AudioCDStream::readBuffer(int16 *buffer, const int numSamples) {
|
||||
int samples = 0;
|
||||
|
||||
// See if any data is left first
|
||||
while (_bufferPos < kSamplesPerFrame && samples < numSamples)
|
||||
buffer[samples++] = _buffer[_bufferPos++];
|
||||
|
||||
// Bail out if done
|
||||
if (endOfData())
|
||||
return samples;
|
||||
|
||||
while (samples < numSamples && !endOfData()) {
|
||||
if (!readNextFrame())
|
||||
return samples;
|
||||
|
||||
// Copy the samples over
|
||||
for (_bufferPos = 0; _bufferPos < kSamplesPerFrame && samples < numSamples;)
|
||||
buffer[samples++] = _buffer[_bufferPos++];
|
||||
}
|
||||
|
||||
return samples;
|
||||
}
|
||||
|
||||
bool AudioCDStream::readNextFrame() {
|
||||
// Fetch a frame from the queue
|
||||
int16 *buffer;
|
||||
|
||||
{
|
||||
Common::StackLock lock(_mutex);
|
||||
|
||||
// Nothing we can do if it's empty
|
||||
if (_bufferQueue.empty())
|
||||
return false;
|
||||
|
||||
buffer = _bufferQueue.pop();
|
||||
}
|
||||
|
||||
memcpy(_buffer, buffer, kSamplesPerFrame * 2);
|
||||
delete[] buffer;
|
||||
_frame++;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AudioCDStream::endOfData() const {
|
||||
return !shouldForceStop() && getStartFrame() + _frame >= getEndFrame() && _bufferPos == kSamplesPerFrame;
|
||||
}
|
||||
|
||||
bool AudioCDStream::seek(const Audio::Timestamp &where) {
|
||||
// Stop the timer
|
||||
stopTimer();
|
||||
|
||||
// Clear anything out of the queue
|
||||
emptyQueue();
|
||||
|
||||
// Convert to the frame number
|
||||
// Really not much else needed
|
||||
_bufferPos = kSamplesPerFrame;
|
||||
_frame = where.convertToFramerate(kFramesPerSecond).totalNumberOfFrames();
|
||||
_bufferFrame = _frame;
|
||||
|
||||
// Start the timer again
|
||||
startTimer();
|
||||
return true;
|
||||
}
|
||||
|
||||
Audio::Timestamp AudioCDStream::getLength() const {
|
||||
return Audio::Timestamp(0, getEndFrame() - getStartFrame(), kFramesPerSecond);
|
||||
}
|
||||
|
||||
void AudioCDStream::timerProc(void *refCon) {
|
||||
static_cast<AudioCDStream *>(refCon)->onTimer();
|
||||
}
|
||||
|
||||
void AudioCDStream::onTimer() {
|
||||
// The goal here is to do as much work in this timer instead
|
||||
// of doing it in the readBuffer() call, which is the mixer.
|
||||
|
||||
// If we're done, bail.
|
||||
if (shouldForceStop() || getStartFrame() + _bufferFrame >= getEndFrame())
|
||||
return;
|
||||
|
||||
// Get a quick count of the number of items in the queue
|
||||
// We don't care that much; we only need a quick estimate
|
||||
_mutex.lock();
|
||||
uint32 queueCount = _bufferQueue.size();
|
||||
_mutex.unlock();
|
||||
|
||||
// If we have enough audio buffered, bail out
|
||||
if (queueCount >= kBufferThreshold)
|
||||
return;
|
||||
|
||||
while (!shouldForceStop() && queueCount < kBufferThreshold && getStartFrame() + _bufferFrame < getEndFrame()) {
|
||||
int16 *buffer = new int16[kSamplesPerFrame];
|
||||
|
||||
// Figure out the MSF of the frame we're looking for
|
||||
int frame = _bufferFrame + getStartFrame();
|
||||
|
||||
// Request to read that frame
|
||||
if (!readFrame(frame, buffer)) {
|
||||
warning("Failed to read CD audio");
|
||||
forceStop();
|
||||
return;
|
||||
}
|
||||
|
||||
_bufferFrame++;
|
||||
|
||||
// Now push the buffer onto the queue
|
||||
Common::StackLock lock(_mutex);
|
||||
_bufferQueue.push(buffer);
|
||||
queueCount = _bufferQueue.size();
|
||||
}
|
||||
}
|
||||
|
||||
void AudioCDStream::startTimer(bool fillBuffer) {
|
||||
_forceStop = false;
|
||||
if (fillBuffer) {
|
||||
onTimer();
|
||||
}
|
||||
g_system->getTimerManager()->installTimerProc(timerProc, 10 * 1000, this, "AudioCDStream");
|
||||
}
|
||||
|
||||
void AudioCDStream::stopTimer() {
|
||||
forceStop();
|
||||
g_system->getTimerManager()->removeTimerProc(timerProc);
|
||||
}
|
||||
|
||||
void AudioCDStream::emptyQueue() {
|
||||
while (!_bufferQueue.empty())
|
||||
delete[] _bufferQueue.pop();
|
||||
}
|
||||
|
||||
bool AudioCDStream::shouldForceStop() const {
|
||||
Common::StackLock lock(_forceStopMutex);
|
||||
return _forceStop;
|
||||
}
|
||||
|
||||
void AudioCDStream::forceStop() {
|
||||
Common::StackLock lock(_forceStopMutex);
|
||||
_forceStop = true;
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Original license header:
|
||||
*
|
||||
* Cabal - Legacy Game Implementations
|
||||
*
|
||||
* Cabal is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_AUDIOCD_AUDIOCD_STREAM_H
|
||||
#define BACKENDS_AUDIOCD_AUDIOCD_STREAM_H
|
||||
|
||||
#include "audio/audiostream.h"
|
||||
#include "common/mutex.h"
|
||||
#include "common/queue.h"
|
||||
#include "common/timer.h"
|
||||
|
||||
class AudioCDStream : public Audio::SeekableAudioStream {
|
||||
public:
|
||||
AudioCDStream();
|
||||
~AudioCDStream();
|
||||
|
||||
int readBuffer(int16 *buffer, const int numSamples);
|
||||
bool isStereo() const { return true; }
|
||||
int getRate() const { return 44100; }
|
||||
bool endOfData() const;
|
||||
bool seek(const Audio::Timestamp &where);
|
||||
Audio::Timestamp getLength() const;
|
||||
|
||||
protected:
|
||||
virtual uint getStartFrame() const = 0;
|
||||
virtual uint getEndFrame() const = 0;
|
||||
virtual bool readFrame(int frame, int16 *buffer) = 0;
|
||||
|
||||
void startTimer(bool fillBuffer = false);
|
||||
void stopTimer();
|
||||
|
||||
enum {
|
||||
kBytesPerFrame = 2352,
|
||||
kSamplesPerFrame = kBytesPerFrame / 2
|
||||
};
|
||||
|
||||
enum {
|
||||
kSecondsPerMinute = 60,
|
||||
kFramesPerSecond = 75
|
||||
};
|
||||
|
||||
enum {
|
||||
// Keep about a second's worth of audio in the buffer
|
||||
kBufferThreshold = kFramesPerSecond
|
||||
};
|
||||
|
||||
private:
|
||||
int16 _buffer[kSamplesPerFrame];
|
||||
int _frame;
|
||||
uint _bufferPos;
|
||||
|
||||
Common::Queue<int16 *> _bufferQueue;
|
||||
int _bufferFrame;
|
||||
Common::Mutex _mutex;
|
||||
|
||||
bool _forceStop;
|
||||
bool shouldForceStop() const;
|
||||
void forceStop();
|
||||
Common::Mutex _forceStopMutex;
|
||||
|
||||
bool readNextFrame();
|
||||
static void timerProc(void *refCon);
|
||||
void onTimer();
|
||||
void emptyQueue();
|
||||
};
|
||||
|
||||
#endif
|
||||
+19
-58
@@ -48,26 +48,31 @@ public:
|
||||
};
|
||||
|
||||
/**
|
||||
* @name Emulated playback functions
|
||||
* Engines should call these functions. Not all platforms
|
||||
* support cd playback, and these functions should try to
|
||||
* emulate it.
|
||||
* Initialize the specified CD drive for audio playback.
|
||||
* @return true if the CD drive was inited successfully
|
||||
*/
|
||||
//@{
|
||||
virtual bool open() = 0;
|
||||
|
||||
/**
|
||||
* Close the currently open CD drive
|
||||
*/
|
||||
virtual void close() = 0;
|
||||
|
||||
/**
|
||||
* Start audio CD playback
|
||||
* @param track the track to play.
|
||||
* @param numLoops how often playback should be repeated (-1 = infinitely often).
|
||||
* @param startFrame the frame at which playback should start (75 frames = 1 second).
|
||||
* @param duration the number of frames to play.
|
||||
* @param only_emulate determines if the track should be emulated only
|
||||
* @param track the track to play.
|
||||
* @param numLoops how often playback should be repeated (<=0 means infinitely often).
|
||||
* @param startFrame the frame at which playback should start (75 frames = 1 second).
|
||||
* @param duration the number of frames to play.
|
||||
* @param onlyEmulate determines if the track should be emulated only
|
||||
* @note The @c onlyEmulate parameter is deprecated.
|
||||
* @return @c true if the track started playing, @c false otherwise
|
||||
*/
|
||||
virtual void play(int track, int numLoops, int startFrame, int duration, bool only_emulate = false) = 0;
|
||||
virtual bool play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate = false) = 0;
|
||||
|
||||
/**
|
||||
* Get if audio is being played.
|
||||
* @return true if CD or emulated audio is playing
|
||||
* @return true if CD audio is playing
|
||||
*/
|
||||
virtual bool isPlaying() const = 0;
|
||||
|
||||
@@ -82,12 +87,12 @@ public:
|
||||
virtual void setBalance(int8 balance) = 0;
|
||||
|
||||
/**
|
||||
* Stop CD or emulated audio playback.
|
||||
* Stop audio playback.
|
||||
*/
|
||||
virtual void stop() = 0;
|
||||
|
||||
/**
|
||||
* Update CD or emulated audio status.
|
||||
* Update audio status.
|
||||
*/
|
||||
virtual void update() = 0;
|
||||
|
||||
@@ -96,50 +101,6 @@ public:
|
||||
* @return a Status struct with playback data.
|
||||
*/
|
||||
virtual Status getStatus() const = 0;
|
||||
|
||||
//@}
|
||||
|
||||
|
||||
/**
|
||||
* @name Real CD audio methods
|
||||
* These functions should be called from the emulated
|
||||
* ones if they can't emulate the audio playback.
|
||||
*/
|
||||
//@{
|
||||
|
||||
/**
|
||||
* Initialize the specified CD drive for audio playback.
|
||||
* @param drive the drive id
|
||||
* @return true if the CD drive was inited successfully
|
||||
*/
|
||||
virtual bool openCD(int drive) = 0;
|
||||
|
||||
/**
|
||||
* Poll CD status.
|
||||
* @return true if CD audio is playing
|
||||
*/
|
||||
virtual bool pollCD() const = 0;
|
||||
|
||||
/**
|
||||
* Start CD audio playback.
|
||||
* @param track the track to play.
|
||||
* @param num_loops how often playback should be repeated (-1 = infinitely often).
|
||||
* @param start_frame the frame at which playback should start (75 frames = 1 second).
|
||||
* @param duration the number of frames to play.
|
||||
*/
|
||||
virtual void playCD(int track, int num_loops, int start_frame, int duration) = 0;
|
||||
|
||||
/**
|
||||
* Stop CD audio playback.
|
||||
*/
|
||||
virtual void stopCD() = 0;
|
||||
|
||||
/**
|
||||
* Update CD audio status.
|
||||
*/
|
||||
virtual void updateCD() = 0;
|
||||
|
||||
//@}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include "backends/audiocd/default/default-audiocd.h"
|
||||
#include "audio/audiostream.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/system.h"
|
||||
|
||||
DefaultAudioCDManager::DefaultAudioCDManager() {
|
||||
@@ -37,7 +38,25 @@ DefaultAudioCDManager::DefaultAudioCDManager() {
|
||||
assert(_mixer);
|
||||
}
|
||||
|
||||
void DefaultAudioCDManager::play(int track, int numLoops, int startFrame, int duration, bool only_emulate) {
|
||||
DefaultAudioCDManager::~DefaultAudioCDManager() {
|
||||
// Subclasses should call close as well
|
||||
close();
|
||||
}
|
||||
|
||||
bool DefaultAudioCDManager::open() {
|
||||
// For emulation, opening is always valid
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
|
||||
void DefaultAudioCDManager::close() {
|
||||
// Only need to stop for emulation
|
||||
stop();
|
||||
}
|
||||
|
||||
bool DefaultAudioCDManager::play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate) {
|
||||
stop();
|
||||
|
||||
if (numLoops != 0 || startFrame != 0) {
|
||||
_cd.track = track;
|
||||
_cd.numLoops = numLoops;
|
||||
@@ -55,9 +74,6 @@ void DefaultAudioCDManager::play(int track, int numLoops, int startFrame, int du
|
||||
for (int i = 0; !stream && i < 2; ++i)
|
||||
stream = Audio::SeekableAudioStream::openStreamFile(trackName[i]);
|
||||
|
||||
// Stop any currently playing emulated track
|
||||
_mixer->stopHandle(_handle);
|
||||
|
||||
if (stream != 0) {
|
||||
Audio::Timestamp start = Audio::Timestamp(0, startFrame, 75);
|
||||
Audio::Timestamp end = duration ? Audio::Timestamp(0, startFrame + duration, 75) : stream->getLength();
|
||||
@@ -70,12 +86,11 @@ void DefaultAudioCDManager::play(int track, int numLoops, int startFrame, int du
|
||||
_emulating = true;
|
||||
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_handle,
|
||||
Audio::makeLoopingAudioStream(stream, start, end, (numLoops < 1) ? numLoops + 1 : numLoops), -1, _cd.volume, _cd.balance);
|
||||
} else {
|
||||
_emulating = false;
|
||||
if (!only_emulate)
|
||||
playCD(track, numLoops, startFrame, duration);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void DefaultAudioCDManager::stop() {
|
||||
@@ -83,52 +98,32 @@ void DefaultAudioCDManager::stop() {
|
||||
// Audio CD emulation
|
||||
_mixer->stopHandle(_handle);
|
||||
_emulating = false;
|
||||
} else {
|
||||
// Real Audio CD
|
||||
stopCD();
|
||||
}
|
||||
}
|
||||
|
||||
bool DefaultAudioCDManager::isPlaying() const {
|
||||
if (_emulating) {
|
||||
// Audio CD emulation
|
||||
// Audio CD emulation
|
||||
if (_emulating)
|
||||
return _mixer->isSoundHandleActive(_handle);
|
||||
} else {
|
||||
// Real Audio CD
|
||||
return pollCD();
|
||||
}
|
||||
|
||||
// The default class only handles emulation
|
||||
return false;
|
||||
}
|
||||
|
||||
void DefaultAudioCDManager::setVolume(byte volume) {
|
||||
_cd.volume = volume;
|
||||
if (_emulating) {
|
||||
// Audio CD emulation
|
||||
if (_mixer->isSoundHandleActive(_handle))
|
||||
_mixer->setChannelVolume(_handle, _cd.volume);
|
||||
} else {
|
||||
// Real Audio CD
|
||||
|
||||
// Unfortunately I can't implement this atm
|
||||
// since SDL doesn't seem to offer an interface method for this.
|
||||
|
||||
// g_system->setVolumeCD(_cd.volume);
|
||||
}
|
||||
// Audio CD emulation
|
||||
if (_emulating && isPlaying())
|
||||
_mixer->setChannelVolume(_handle, _cd.volume);
|
||||
}
|
||||
|
||||
void DefaultAudioCDManager::setBalance(int8 balance) {
|
||||
_cd.balance = balance;
|
||||
if (_emulating) {
|
||||
// Audio CD emulation
|
||||
if (isPlaying())
|
||||
_mixer->setChannelBalance(_handle, _cd.balance);
|
||||
} else {
|
||||
// Real Audio CD
|
||||
|
||||
// Unfortunately I can't implement this atm
|
||||
// since SDL doesn't seem to offer an interface method for this.
|
||||
|
||||
// g_system->setBalanceCD(_cd.balance);
|
||||
}
|
||||
// Audio CD emulation
|
||||
if (_emulating && isPlaying())
|
||||
_mixer->setChannelBalance(_handle, _cd.balance);
|
||||
}
|
||||
|
||||
void DefaultAudioCDManager::update() {
|
||||
@@ -142,8 +137,6 @@ void DefaultAudioCDManager::update() {
|
||||
// or not.
|
||||
_emulating = false;
|
||||
}
|
||||
} else {
|
||||
updateCD();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,3 +145,21 @@ DefaultAudioCDManager::Status DefaultAudioCDManager::getStatus() const {
|
||||
info.playing = isPlaying();
|
||||
return info;
|
||||
}
|
||||
|
||||
bool DefaultAudioCDManager::openRealCD() {
|
||||
Common::String cdrom = ConfMan.get("cdrom");
|
||||
|
||||
// Try to parse it as an int
|
||||
char *endPos;
|
||||
int drive = strtol(cdrom.c_str(), &endPos, 0);
|
||||
|
||||
// If not an integer, treat as a drive path
|
||||
if (endPos == cdrom.c_str())
|
||||
return openCD(cdrom);
|
||||
|
||||
if (drive < 0)
|
||||
return false;
|
||||
|
||||
return openCD(drive);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,29 +26,48 @@
|
||||
#include "backends/audiocd/audiocd.h"
|
||||
#include "audio/mixer.h"
|
||||
|
||||
namespace Common {
|
||||
class String;
|
||||
} // End of namespace Common
|
||||
|
||||
/**
|
||||
* The default audio cd manager. Implements emulation of audio cd playback.
|
||||
*/
|
||||
class DefaultAudioCDManager : public AudioCDManager {
|
||||
public:
|
||||
DefaultAudioCDManager();
|
||||
virtual ~DefaultAudioCDManager() {}
|
||||
virtual ~DefaultAudioCDManager();
|
||||
|
||||
void play(int track, int numLoops, int startFrame, int duration, bool only_emulate = false);
|
||||
void stop();
|
||||
bool isPlaying() const;
|
||||
void setVolume(byte volume);
|
||||
void setBalance(int8 balance);
|
||||
void update();
|
||||
virtual bool open();
|
||||
virtual void close();
|
||||
virtual bool play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate = false);
|
||||
virtual void stop();
|
||||
virtual bool isPlaying() const;
|
||||
virtual void setVolume(byte volume);
|
||||
virtual void setBalance(int8 balance);
|
||||
virtual void update();
|
||||
virtual Status getStatus() const; // Subclasses should override for better status results
|
||||
|
||||
virtual bool openCD(int drive) { return false; }
|
||||
virtual void updateCD() {}
|
||||
virtual bool pollCD() const { return false; }
|
||||
virtual void playCD(int track, int num_loops, int start_frame, int duration) {}
|
||||
virtual void stopCD() {}
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Open a CD using the cdrom config variable
|
||||
*/
|
||||
bool openRealCD();
|
||||
|
||||
/**
|
||||
* Open a CD using the specified drive index
|
||||
* @param drive The index of the drive
|
||||
* @note The index is implementation-defined, but 0 is always the best choice
|
||||
*/
|
||||
virtual bool openCD(int drive) { return false; }
|
||||
|
||||
/**
|
||||
* Open a CD from a specific drive
|
||||
* @param drive The name of the drive/path
|
||||
* @note The drive parameter is platform-specific
|
||||
*/
|
||||
virtual bool openCD(const Common::String &drive) { return false; }
|
||||
|
||||
Audio::SoundHandle _handle;
|
||||
bool _emulating;
|
||||
|
||||
|
||||
@@ -0,0 +1,471 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Original license header:
|
||||
*
|
||||
* Cabal - Legacy Game Implementations
|
||||
*
|
||||
* Cabal is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
// Enable all forbidden symbols to allow us to include and use necessary APIs.
|
||||
#define FORBIDDEN_SYMBOL_ALLOW_ALL
|
||||
|
||||
#include "backends/audiocd/linux/linux-audiocd.h"
|
||||
|
||||
#ifdef USE_LINUXCD
|
||||
|
||||
#include "backends/audiocd/audiocd-stream.h"
|
||||
#include "backends/audiocd/default/default-audiocd.h"
|
||||
#include "common/array.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/str.h"
|
||||
#include "common/debug.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <linux/cdrom.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
enum {
|
||||
kLeadoutTrack = 0xAA
|
||||
};
|
||||
|
||||
enum {
|
||||
kBytesPerFrame = 2352,
|
||||
kSamplesPerFrame = kBytesPerFrame / 2
|
||||
};
|
||||
|
||||
enum {
|
||||
kSecondsPerMinute = 60,
|
||||
kFramesPerSecond = 75
|
||||
};
|
||||
|
||||
enum {
|
||||
// Keep about a second's worth of audio in the buffer
|
||||
kBufferThreshold = kFramesPerSecond
|
||||
};
|
||||
|
||||
static int getFrameCount(const cdrom_msf0 &msf) {
|
||||
int time = msf.minute;
|
||||
time *= kSecondsPerMinute;
|
||||
time += msf.second;
|
||||
time *= kFramesPerSecond;
|
||||
time += msf.frame;
|
||||
return time;
|
||||
}
|
||||
|
||||
// Helper function to convert an error code into a human-readable message
|
||||
static Common::String getErrorMessage(int errorCode) {
|
||||
char buf[256];
|
||||
buf[0] = 0;
|
||||
|
||||
#ifdef _GNU_SOURCE
|
||||
// glibc sucks
|
||||
return Common::String(strerror_r(errorCode, buf, sizeof(buf)));
|
||||
#else
|
||||
strerror_r(errorCode, buf, sizeof(buf));
|
||||
return Common::String(buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
class LinuxAudioCDStream : public AudioCDStream {
|
||||
public:
|
||||
LinuxAudioCDStream(int fd, const cdrom_tocentry &startEntry, const cdrom_tocentry &endEntry);
|
||||
~LinuxAudioCDStream();
|
||||
|
||||
protected:
|
||||
uint getStartFrame() const;
|
||||
uint getEndFrame() const;
|
||||
bool readFrame(int frame, int16 *buffer);
|
||||
|
||||
private:
|
||||
int _fd;
|
||||
const cdrom_tocentry &_startEntry, &_endEntry;
|
||||
};
|
||||
|
||||
LinuxAudioCDStream::LinuxAudioCDStream(int fd, const cdrom_tocentry &startEntry, const cdrom_tocentry &endEntry) :
|
||||
_fd(fd), _startEntry(startEntry), _endEntry(endEntry) {
|
||||
// We fill the buffer here already to prevent any out of sync issues due
|
||||
// to the CD not yet having spun up.
|
||||
startTimer(true);
|
||||
}
|
||||
|
||||
LinuxAudioCDStream::~LinuxAudioCDStream() {
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
bool LinuxAudioCDStream::readFrame(int frame, int16 *buffer) {
|
||||
// Create the argument
|
||||
union {
|
||||
cdrom_msf msf;
|
||||
char buffer[kBytesPerFrame];
|
||||
} arg;
|
||||
|
||||
int seconds = frame / kFramesPerSecond;
|
||||
frame %= kFramesPerSecond;
|
||||
int minutes = seconds / kSecondsPerMinute;
|
||||
seconds %= kSecondsPerMinute;
|
||||
|
||||
// Request to read that frame
|
||||
// We don't use CDROMREADAUDIO, as it seems to cause kernel
|
||||
// panics on ejecting discs. Probably bad to eject the disc
|
||||
// while playing, but at least let's try to prevent that case.
|
||||
arg.msf.cdmsf_min0 = minutes;
|
||||
arg.msf.cdmsf_sec0 = seconds;
|
||||
arg.msf.cdmsf_frame0 = frame;
|
||||
// The "end" part is irrelevant (why isn't cdrom_msf0 the type
|
||||
// instead?)
|
||||
|
||||
if (ioctl(_fd, CDROMREADRAW, &arg) < 0) {
|
||||
warning("Failed to CD read audio: %s", getErrorMessage(errno).c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(buffer, arg.buffer, kBytesPerFrame);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint LinuxAudioCDStream::getStartFrame() const {
|
||||
return getFrameCount(_startEntry.cdte_addr.msf);
|
||||
}
|
||||
|
||||
uint LinuxAudioCDStream::getEndFrame() const {
|
||||
return getFrameCount(_endEntry.cdte_addr.msf);
|
||||
}
|
||||
|
||||
|
||||
class LinuxAudioCDManager : public DefaultAudioCDManager {
|
||||
public:
|
||||
LinuxAudioCDManager();
|
||||
~LinuxAudioCDManager();
|
||||
|
||||
bool open();
|
||||
void close();
|
||||
bool play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate = false);
|
||||
|
||||
protected:
|
||||
bool openCD(int drive);
|
||||
bool openCD(const Common::String &drive);
|
||||
|
||||
private:
|
||||
struct Device {
|
||||
Device(const Common::String &n, dev_t d) : name(n), device(d) {}
|
||||
Common::String name;
|
||||
dev_t device;
|
||||
};
|
||||
|
||||
typedef Common::Array<Device> DeviceList;
|
||||
DeviceList scanDevices();
|
||||
bool tryAddDrive(DeviceList &devices, const Common::String &drive);
|
||||
bool tryAddDrive(DeviceList &devices, const Common::String &drive, dev_t device);
|
||||
bool tryAddDrive(DeviceList &devices, dev_t device);
|
||||
bool tryAddPath(DeviceList &devices, const Common::String &path);
|
||||
bool tryAddGamePath(DeviceList &devices);
|
||||
bool loadTOC();
|
||||
static bool hasDevice(const DeviceList &devices, dev_t device);
|
||||
|
||||
int _fd;
|
||||
cdrom_tochdr _tocHeader;
|
||||
Common::Array<cdrom_tocentry> _tocEntries;
|
||||
};
|
||||
|
||||
static bool isTrayEmpty(int errorNumber) {
|
||||
switch (errorNumber) {
|
||||
case EIO:
|
||||
case ENOENT:
|
||||
case EINVAL:
|
||||
#ifdef ENOMEDIUM
|
||||
case ENOMEDIUM:
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
LinuxAudioCDManager::LinuxAudioCDManager() {
|
||||
_fd = -1;
|
||||
memset(&_tocHeader, 0, sizeof(_tocHeader));
|
||||
}
|
||||
|
||||
LinuxAudioCDManager::~LinuxAudioCDManager() {
|
||||
close();
|
||||
}
|
||||
|
||||
bool LinuxAudioCDManager::open() {
|
||||
close();
|
||||
|
||||
if (openRealCD())
|
||||
return true;
|
||||
|
||||
return DefaultAudioCDManager::open();
|
||||
}
|
||||
|
||||
void LinuxAudioCDManager::close() {
|
||||
DefaultAudioCDManager::close();
|
||||
|
||||
if (_fd < 0)
|
||||
return;
|
||||
|
||||
::close(_fd);
|
||||
memset(&_tocHeader, 0, sizeof(_tocHeader));
|
||||
_tocEntries.clear();
|
||||
}
|
||||
|
||||
bool LinuxAudioCDManager::openCD(int drive) {
|
||||
DeviceList devices = scanDevices();
|
||||
if (drive >= (int)devices.size())
|
||||
return false;
|
||||
|
||||
_fd = ::open(devices[drive].name.c_str(), O_RDONLY | O_NONBLOCK, 0);
|
||||
if (_fd < 0)
|
||||
return false;
|
||||
|
||||
if (!loadTOC()) {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LinuxAudioCDManager::openCD(const Common::String &drive) {
|
||||
DeviceList devices;
|
||||
if (!tryAddDrive(devices, drive) && !tryAddPath(devices, drive))
|
||||
return false;
|
||||
|
||||
_fd = ::open(devices[0].name.c_str(), O_RDONLY | O_NONBLOCK, 0);
|
||||
if (_fd < 0)
|
||||
return false;
|
||||
|
||||
if (!loadTOC()) {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LinuxAudioCDManager::play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate) {
|
||||
// Prefer emulation
|
||||
if (DefaultAudioCDManager::play(track, numLoops, startFrame, duration, onlyEmulate))
|
||||
return true;
|
||||
|
||||
// If we're set to only emulate, or have no CD drive, return here
|
||||
if (onlyEmulate || _fd < 0)
|
||||
return false;
|
||||
|
||||
// HACK: For now, just assume that track number is right
|
||||
// That only works because ScummVM uses the wrong track number anyway
|
||||
|
||||
if (track >= (int)_tocEntries.size() - 1) {
|
||||
warning("No such track %d", track);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bail if the track isn't an audio track
|
||||
if ((_tocEntries[track].cdte_ctrl & 0x04) != 0) {
|
||||
warning("Track %d is not audio", track);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the AudioStream and play it
|
||||
debug(1, "Playing CD track %d", track);
|
||||
|
||||
Audio::SeekableAudioStream *audioStream = new LinuxAudioCDStream(_fd, _tocEntries[track], _tocEntries[track + 1]);
|
||||
|
||||
Audio::Timestamp start = Audio::Timestamp(0, startFrame, 75);
|
||||
Audio::Timestamp end = (duration == 0) ? audioStream->getLength() : Audio::Timestamp(0, startFrame + duration, 75);
|
||||
|
||||
// Fake emulation since we're really playing an AudioStream
|
||||
_emulating = true;
|
||||
|
||||
_mixer->playStream(
|
||||
Audio::Mixer::kMusicSoundType,
|
||||
&_handle,
|
||||
Audio::makeLoopingAudioStream(audioStream, start, end, (numLoops < 1) ? numLoops + 1 : numLoops),
|
||||
-1,
|
||||
_cd.volume,
|
||||
_cd.balance,
|
||||
DisposeAfterUse::YES,
|
||||
true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
LinuxAudioCDManager::DeviceList LinuxAudioCDManager::scanDevices() {
|
||||
DeviceList devices;
|
||||
|
||||
// Try to use the game's path first as the device
|
||||
tryAddGamePath(devices);
|
||||
|
||||
// Try adding the default CD-ROM
|
||||
tryAddDrive(devices, "/dev/cdrom");
|
||||
|
||||
// TODO: Try others?
|
||||
|
||||
return devices;
|
||||
}
|
||||
|
||||
bool LinuxAudioCDManager::tryAddDrive(DeviceList &devices, const Common::String &drive) {
|
||||
struct stat stbuf;
|
||||
if (stat(drive.c_str(), &stbuf) < 0)
|
||||
return false;
|
||||
|
||||
// Must be a character or block device
|
||||
if (!S_ISCHR(stbuf.st_mode) && !S_ISBLK(stbuf.st_mode))
|
||||
return false;
|
||||
|
||||
return tryAddDrive(devices, drive, stbuf.st_rdev);
|
||||
}
|
||||
|
||||
bool LinuxAudioCDManager::tryAddDrive(DeviceList &devices, const Common::String &drive, dev_t device) {
|
||||
if (hasDevice(devices, device))
|
||||
return true;
|
||||
|
||||
// Try opening the device and seeing if it is a CD-ROM drve
|
||||
int fd = ::open(drive.c_str(), O_RDONLY | O_NONBLOCK, 0);
|
||||
if (fd >= 0) {
|
||||
cdrom_subchnl info;
|
||||
info.cdsc_format = CDROM_MSF;
|
||||
|
||||
bool isCD = ioctl(fd, CDROMSUBCHNL, &info) == 0 || isTrayEmpty(errno);
|
||||
::close(fd);
|
||||
if (isCD) {
|
||||
devices.push_back(Device(drive, device));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LinuxAudioCDManager::tryAddDrive(DeviceList &devices, dev_t device) {
|
||||
// Construct the block name
|
||||
// TODO: libblkid's blkid_devno_to_devname is exactly what we look for.
|
||||
// This requires an external dependency though.
|
||||
Common::String name = Common::String::format("/dev/block/%d:%d", major(device), minor(device));
|
||||
|
||||
return tryAddDrive(devices, name, device);
|
||||
}
|
||||
|
||||
bool LinuxAudioCDManager::tryAddPath(DeviceList &devices, const Common::String &path) {
|
||||
struct stat stbuf;
|
||||
if (stat(path.c_str(), &stbuf) < 0)
|
||||
return false;
|
||||
|
||||
return tryAddDrive(devices, stbuf.st_dev);
|
||||
}
|
||||
|
||||
bool LinuxAudioCDManager::tryAddGamePath(DeviceList &devices) {
|
||||
if (!ConfMan.hasKey("path"))
|
||||
return false;
|
||||
|
||||
return tryAddPath(devices, ConfMan.get("path"));
|
||||
}
|
||||
|
||||
bool LinuxAudioCDManager::loadTOC() {
|
||||
if (_fd < 0)
|
||||
return false;
|
||||
|
||||
if (ioctl(_fd, CDROMREADTOCHDR, &_tocHeader) < 0)
|
||||
return false;
|
||||
|
||||
debug(4, "CD: Start Track: %d, End Track %d", _tocHeader.cdth_trk0, _tocHeader.cdth_trk1);
|
||||
|
||||
for (int i = _tocHeader.cdth_trk0; i <= _tocHeader.cdth_trk1; i++) {
|
||||
cdrom_tocentry entry;
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
entry.cdte_track = i;
|
||||
entry.cdte_format = CDROM_MSF;
|
||||
|
||||
if (ioctl(_fd, CDROMREADTOCENTRY, &entry) < 0)
|
||||
return false;
|
||||
|
||||
#if 0
|
||||
debug("Entry:");
|
||||
debug("\tTrack: %d", entry.cdte_track);
|
||||
debug("\tAdr: %d", entry.cdte_adr);
|
||||
debug("\tCtrl: %d", entry.cdte_ctrl);
|
||||
debug("\tFormat: %d", entry.cdte_format);
|
||||
debug("\tMSF: %d:%d:%d", entry.cdte_addr.msf.minute, entry.cdte_addr.msf.second, entry.cdte_addr.msf.frame);
|
||||
debug("\tMode: %d\n", entry.cdte_datamode);
|
||||
#endif
|
||||
|
||||
_tocEntries.push_back(entry);
|
||||
}
|
||||
|
||||
// Fetch the leadout so we can get the length of the last frame
|
||||
cdrom_tocentry entry;
|
||||
memset(&entry, 0, sizeof(entry));
|
||||
entry.cdte_track = kLeadoutTrack;
|
||||
entry.cdte_format = CDROM_MSF;
|
||||
|
||||
if (ioctl(_fd, CDROMREADTOCENTRY, &entry) < 0)
|
||||
return false;
|
||||
|
||||
#if 0
|
||||
debug("Lead out:");
|
||||
debug("\tTrack: %d", entry.cdte_track);
|
||||
debug("\tAdr: %d", entry.cdte_adr);
|
||||
debug("\tCtrl: %d", entry.cdte_ctrl);
|
||||
debug("\tFormat: %d", entry.cdte_format);
|
||||
debug("\tMSF: %d:%d:%d", entry.cdte_addr.msf.minute, entry.cdte_addr.msf.second, entry.cdte_addr.msf.frame);
|
||||
debug("\tMode: %d\n", entry.cdte_datamode);
|
||||
#endif
|
||||
|
||||
_tocEntries.push_back(entry);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LinuxAudioCDManager::hasDevice(const DeviceList &devices, dev_t device) {
|
||||
for (DeviceList::const_iterator it = devices.begin(); it != devices.end(); it++)
|
||||
if (it->device == device)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
AudioCDManager *createLinuxAudioCDManager() {
|
||||
return new LinuxAudioCDManager();
|
||||
}
|
||||
|
||||
#endif // USE_LINUXCD
|
||||
@@ -0,0 +1,62 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Original license header:
|
||||
*
|
||||
* Cabal - Legacy Game Implementations
|
||||
*
|
||||
* Cabal is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_AUDIOCD_LINUX_H
|
||||
#define BACKENDS_AUDIOCD_LINUX_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#ifdef USE_LINUXCD
|
||||
|
||||
class AudioCDManager;
|
||||
|
||||
/**
|
||||
* Create an audio CD manager using the Linux CDROM API
|
||||
*/
|
||||
AudioCDManager *createLinuxAudioCDManager();
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,306 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Original license header:
|
||||
*
|
||||
* Cabal - Legacy Game Implementations
|
||||
*
|
||||
* Cabal is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef MACOSX
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mount.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#include "audio/audiostream.h"
|
||||
#include "audio/decoders/aiff.h"
|
||||
#include "audio/timestamp.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/fs.h"
|
||||
#include "common/hashmap.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "backends/audiocd/default/default-audiocd.h"
|
||||
#include "backends/audiocd/macosx/macosx-audiocd.h"
|
||||
#include "backends/fs/stdiostream.h"
|
||||
|
||||
// Partially based on SDL's code
|
||||
|
||||
/**
|
||||
* The Mac OS X audio cd manager. Implements real audio cd playback.
|
||||
*/
|
||||
class MacOSXAudioCDManager : public DefaultAudioCDManager {
|
||||
public:
|
||||
MacOSXAudioCDManager() {}
|
||||
~MacOSXAudioCDManager();
|
||||
|
||||
bool open();
|
||||
void close();
|
||||
bool play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate = false);
|
||||
|
||||
protected:
|
||||
bool openCD(int drive);
|
||||
bool openCD(const Common::String &drive);
|
||||
|
||||
private:
|
||||
struct Drive {
|
||||
Drive(const Common::String &m, const Common::String &d, const Common::String &f) :
|
||||
mountPoint(m), deviceName(d), fsType(f) {}
|
||||
|
||||
Common::String mountPoint;
|
||||
Common::String deviceName;
|
||||
Common::String fsType;
|
||||
};
|
||||
|
||||
typedef Common::Array<Drive> DriveList;
|
||||
DriveList detectAllDrives();
|
||||
DriveList detectCDDADrives();
|
||||
|
||||
bool findTrackNames(const Common::String &drivePath);
|
||||
|
||||
Common::HashMap<uint, Common::String> _trackMap;
|
||||
};
|
||||
|
||||
MacOSXAudioCDManager::~MacOSXAudioCDManager() {
|
||||
close();
|
||||
}
|
||||
|
||||
bool MacOSXAudioCDManager::open() {
|
||||
close();
|
||||
|
||||
if (openRealCD())
|
||||
return true;
|
||||
|
||||
return DefaultAudioCDManager::open();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the base disk number of device name.
|
||||
* Returns -1 if mount point is not /dev/disk*
|
||||
*/
|
||||
static int findBaseDiskNumber(const Common::String &diskName) {
|
||||
if (!diskName.hasPrefix("/dev/disk"))
|
||||
return -1;
|
||||
|
||||
const char *startPtr = diskName.c_str() + 9;
|
||||
char *endPtr;
|
||||
int baseDiskNumber = strtol(startPtr, &endPtr, 10);
|
||||
if (startPtr == endPtr)
|
||||
return -1;
|
||||
|
||||
return baseDiskNumber;
|
||||
}
|
||||
|
||||
bool MacOSXAudioCDManager::openCD(int drive) {
|
||||
DriveList allDrives = detectAllDrives();
|
||||
if (allDrives.empty())
|
||||
return false;
|
||||
|
||||
DriveList cddaDrives;
|
||||
|
||||
// Try to get the volume related to the game's path
|
||||
if (ConfMan.hasKey("path")) {
|
||||
Common::String gamePath = ConfMan.get("path");
|
||||
struct statfs gamePathStat;
|
||||
if (statfs(gamePath.c_str(), &gamePathStat) == 0) {
|
||||
int baseDiskNumber = findBaseDiskNumber(gamePathStat.f_mntfromname);
|
||||
if (baseDiskNumber >= 0) {
|
||||
// Look for a CDDA drive with the same base disk number
|
||||
for (uint32 i = 0; i < allDrives.size(); i++) {
|
||||
if (allDrives[i].fsType == "cddafs" && findBaseDiskNumber(allDrives[i].deviceName) == baseDiskNumber) {
|
||||
debug(1, "Preferring drive '%s'", allDrives[i].mountPoint.c_str());
|
||||
cddaDrives.push_back(allDrives[i]);
|
||||
allDrives.remove_at(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the remaining CDDA drives to the CDDA list
|
||||
for (uint32 i = 0; i < allDrives.size(); i++)
|
||||
if (allDrives[i].fsType == "cddafs")
|
||||
cddaDrives.push_back(allDrives[i]);
|
||||
|
||||
if (drive >= (int)cddaDrives.size())
|
||||
return false;
|
||||
|
||||
debug(1, "Using '%s' as the CD drive", cddaDrives[drive].mountPoint.c_str());
|
||||
|
||||
return findTrackNames(cddaDrives[drive].mountPoint);
|
||||
}
|
||||
|
||||
bool MacOSXAudioCDManager::openCD(const Common::String &drive) {
|
||||
DriveList drives = detectAllDrives();
|
||||
|
||||
for (uint32 i = 0; i < drives.size(); i++) {
|
||||
if (drives[i].fsType != "cddafs")
|
||||
continue;
|
||||
|
||||
if (drives[i].mountPoint == drive || drives[i].deviceName == drive) {
|
||||
debug(1, "Using '%s' as the CD drive", drives[i].mountPoint.c_str());
|
||||
return findTrackNames(drives[i].mountPoint);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void MacOSXAudioCDManager::close() {
|
||||
DefaultAudioCDManager::close();
|
||||
_trackMap.clear();
|
||||
}
|
||||
|
||||
enum {
|
||||
// Some crazy high number that we'll never actually hit
|
||||
kMaxDriveCount = 256
|
||||
};
|
||||
|
||||
MacOSXAudioCDManager::DriveList MacOSXAudioCDManager::detectAllDrives() {
|
||||
// Fetch the lists of drives
|
||||
struct statfs driveStats[kMaxDriveCount];
|
||||
int foundDrives = getfsstat(driveStats, sizeof(driveStats), MNT_WAIT);
|
||||
if (foundDrives <= 0)
|
||||
return DriveList();
|
||||
|
||||
DriveList drives;
|
||||
for (int i = 0; i < foundDrives; i++)
|
||||
drives.push_back(Drive(driveStats[i].f_mntonname, driveStats[i].f_mntfromname, driveStats[i].f_fstypename));
|
||||
|
||||
return drives;
|
||||
}
|
||||
|
||||
bool MacOSXAudioCDManager::play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate) {
|
||||
// Prefer emulation
|
||||
if (DefaultAudioCDManager::play(track, numLoops, startFrame, duration, onlyEmulate))
|
||||
return true;
|
||||
|
||||
// If we're set to only emulate, or have no CD drive, return here
|
||||
if (onlyEmulate || !_trackMap.contains(track))
|
||||
return false;
|
||||
|
||||
if (!numLoops && !startFrame)
|
||||
return false;
|
||||
|
||||
// Now load the AIFF track from the name
|
||||
Common::String fileName = _trackMap[track];
|
||||
Common::SeekableReadStream *stream = StdioStream::makeFromPath(fileName.c_str(), false);
|
||||
|
||||
if (!stream) {
|
||||
warning("Failed to open track '%s'", fileName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
Audio::AudioStream *audioStream = Audio::makeAIFFStream(stream, DisposeAfterUse::YES);
|
||||
if (!audioStream) {
|
||||
warning("Track '%s' is not an AIFF track", fileName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
Audio::SeekableAudioStream *seekStream = dynamic_cast<Audio::SeekableAudioStream *>(audioStream);
|
||||
if (!seekStream) {
|
||||
warning("Track '%s' is not seekable", fileName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
Audio::Timestamp start = Audio::Timestamp(0, startFrame, 75);
|
||||
Audio::Timestamp end = duration ? Audio::Timestamp(0, startFrame + duration, 75) : seekStream->getLength();
|
||||
|
||||
// Fake emulation since we're really playing an AIFF file
|
||||
_emulating = true;
|
||||
|
||||
_mixer->playStream(Audio::Mixer::kMusicSoundType, &_handle,
|
||||
Audio::makeLoopingAudioStream(seekStream, start, end, (numLoops < 1) ? numLoops + 1 : numLoops), -1, _cd.volume, _cd.balance);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacOSXAudioCDManager::findTrackNames(const Common::String &drivePath) {
|
||||
Common::FSNode directory(drivePath);
|
||||
|
||||
if (!directory.exists()) {
|
||||
warning("Directory '%s' does not exist", drivePath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!directory.isDirectory()) {
|
||||
warning("'%s' is not a directory", drivePath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
Common::FSList children;
|
||||
if (!directory.getChildren(children, Common::FSNode::kListFilesOnly)) {
|
||||
warning("Failed to find children for '%s'", drivePath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < children.size(); i++) {
|
||||
if (!children[i].isDirectory()) {
|
||||
Common::String fileName = children[i].getName();
|
||||
|
||||
if (fileName.hasSuffix(".aiff") || fileName.hasSuffix(".cdda")) {
|
||||
uint j = 0;
|
||||
|
||||
// Search for the track ID in the file name.
|
||||
for (; j < fileName.size() && !Common::isDigit(fileName[j]); j++)
|
||||
;
|
||||
|
||||
const char *trackIDString = fileName.c_str() + j;
|
||||
char *endPtr = nullptr;
|
||||
long trackID = strtol(trackIDString, &endPtr, 10);
|
||||
|
||||
if (trackIDString != endPtr && trackID > 0 && trackID < UINT_MAX) {
|
||||
_trackMap[trackID - 1] = drivePath + '/' + fileName;
|
||||
} else {
|
||||
warning("Invalid track file name: '%s'", fileName.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
AudioCDManager *createMacOSXAudioCDManager() {
|
||||
return new MacOSXAudioCDManager();
|
||||
}
|
||||
|
||||
#endif // MACOSX
|
||||
@@ -0,0 +1,61 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Original license header:
|
||||
*
|
||||
* Cabal - Legacy Game Implementations
|
||||
*
|
||||
* Cabal is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_AUDIOCD_MACOSX_H
|
||||
#define BACKENDS_AUDIOCD_MACOSX_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#ifdef MACOSX
|
||||
|
||||
class AudioCDManager;
|
||||
|
||||
/**
|
||||
* Create an audio CD manager for Mac OS X
|
||||
*/
|
||||
AudioCDManager *createMacOSXAudioCDManager();
|
||||
|
||||
#endif
|
||||
|
||||
#endif //
|
||||
@@ -43,10 +43,16 @@ SdlAudioCDManager::SdlAudioCDManager()
|
||||
}
|
||||
|
||||
SdlAudioCDManager::~SdlAudioCDManager() {
|
||||
if (_cdrom) {
|
||||
SDL_CDStop(_cdrom);
|
||||
SDL_CDClose(_cdrom);
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
||||
bool SdlAudioCDManager::open() {
|
||||
close();
|
||||
|
||||
if (openRealCD())
|
||||
return true;
|
||||
|
||||
return DefaultAudioCDManager::open();
|
||||
}
|
||||
|
||||
bool SdlAudioCDManager::openCD(int drive) {
|
||||
@@ -67,44 +73,69 @@ bool SdlAudioCDManager::openCD(int drive) {
|
||||
return (_cdrom != NULL);
|
||||
}
|
||||
|
||||
void SdlAudioCDManager::stopCD() {
|
||||
void SdlAudioCDManager::close() {
|
||||
DefaultAudioCDManager::close();
|
||||
|
||||
if (_cdrom) {
|
||||
SDL_CDStop(_cdrom);
|
||||
SDL_CDClose(_cdrom);
|
||||
_cdrom = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SdlAudioCDManager::stop() {
|
||||
DefaultAudioCDManager::stop();
|
||||
|
||||
// Stop CD Audio in 1/10th of a second
|
||||
_cdStopTime = SDL_GetTicks() + 100;
|
||||
_cdNumLoops = 0;
|
||||
}
|
||||
|
||||
void SdlAudioCDManager::playCD(int track, int num_loops, int start_frame, int duration) {
|
||||
if (!num_loops && !start_frame)
|
||||
return;
|
||||
bool SdlAudioCDManager::play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate) {
|
||||
// Prefer emulation
|
||||
if (DefaultAudioCDManager::play(track, numLoops, startFrame, duration, onlyEmulate))
|
||||
return true;
|
||||
|
||||
if (!_cdrom)
|
||||
return;
|
||||
// If we're set to only emulate, or have no CD, return here
|
||||
if (onlyEmulate || !_cdrom)
|
||||
return false;
|
||||
|
||||
if (!numLoops && !startFrame)
|
||||
return false;
|
||||
|
||||
// FIXME: Explain this.
|
||||
if (duration > 0)
|
||||
duration += 5;
|
||||
|
||||
_cdTrack = track;
|
||||
_cdNumLoops = num_loops;
|
||||
_cdStartFrame = start_frame;
|
||||
_cdNumLoops = numLoops;
|
||||
_cdStartFrame = startFrame;
|
||||
|
||||
SDL_CDStatus(_cdrom);
|
||||
if (start_frame == 0 && duration == 0)
|
||||
if (startFrame == 0 && duration == 0)
|
||||
SDL_CDPlayTracks(_cdrom, track, 0, 1, 0);
|
||||
else
|
||||
SDL_CDPlayTracks(_cdrom, track, start_frame, 0, duration);
|
||||
SDL_CDPlayTracks(_cdrom, track, startFrame, 0, duration);
|
||||
_cdDuration = duration;
|
||||
_cdStopTime = 0;
|
||||
_cdEndTime = SDL_GetTicks() + _cdrom->track[track].length * 1000 / CD_FPS;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SdlAudioCDManager::pollCD() const {
|
||||
bool SdlAudioCDManager::isPlaying() const {
|
||||
if (DefaultAudioCDManager::isPlaying())
|
||||
return true;
|
||||
|
||||
if (!_cdrom)
|
||||
return false;
|
||||
|
||||
return (_cdNumLoops != 0 && (SDL_GetTicks() < _cdEndTime || SDL_CDStatus(_cdrom) == CD_PLAYING));
|
||||
}
|
||||
|
||||
void SdlAudioCDManager::updateCD() {
|
||||
void SdlAudioCDManager::update() {
|
||||
DefaultAudioCDManager::update();
|
||||
|
||||
if (!_cdrom)
|
||||
return;
|
||||
|
||||
|
||||
@@ -37,12 +37,15 @@ public:
|
||||
SdlAudioCDManager();
|
||||
virtual ~SdlAudioCDManager();
|
||||
|
||||
virtual bool open();
|
||||
virtual void close();
|
||||
virtual bool play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate = false);
|
||||
virtual void stop();
|
||||
virtual bool isPlaying() const;
|
||||
virtual void update();
|
||||
|
||||
protected:
|
||||
virtual bool openCD(int drive);
|
||||
virtual void updateCD();
|
||||
virtual bool pollCD() const;
|
||||
virtual void playCD(int track, int num_loops, int start_frame, int duration);
|
||||
virtual void stopCD();
|
||||
|
||||
SDL_CD *_cdrom;
|
||||
int _cdTrack, _cdNumLoops, _cdStartFrame, _cdDuration;
|
||||
|
||||
@@ -0,0 +1,362 @@
|
||||
/**
|
||||
* @file ntddcdrm.h
|
||||
* Copyright 2012, 2013 MinGW.org project
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/* Created by Casper S. Hornstrup <chorns@users.sourceforge.net> */
|
||||
#ifndef __NTDDCDRM_H
|
||||
#define __NTDDCDRM_H
|
||||
#if 0 // Added to make MSVC happy.
|
||||
#pragma GCC system_header
|
||||
#include <_mingw.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* CDROM IOCTL interface.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if 0 // Added to make MSVC happy.
|
||||
#include "ntddk.h"
|
||||
#include "ntddstor.h"
|
||||
#endif
|
||||
|
||||
#define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM
|
||||
|
||||
#define IOCTL_CDROM_CHECK_VERIFY \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0200, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_FIND_NEW_DEVICES \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0206, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_GET_CONTROL \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x000D, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_GET_DRIVE_GEOMETRY \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0013, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_GET_LAST_SESSION \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x000E, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_GET_VOLUME \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0005, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_PAUSE_AUDIO \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0003, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_PLAY_AUDIO_MSF \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0006, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_RAW_READ \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x000F, METHOD_OUT_DIRECT, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_READ_Q_CHANNEL \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x000B, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_READ_TOC \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_READ_TOC_EX \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0015, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_RESUME_AUDIO \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0004, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_SEEK_AUDIO_MSF \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0001, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_SET_VOLUME \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x000A, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_SIMBAD \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x1003, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_CDROM_STOP_AUDIO \
|
||||
CTL_CODE(IOCTL_CDROM_BASE, 0x0002, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
|
||||
#define MAXIMUM_NUMBER_TRACKS 100
|
||||
#define MAXIMUM_CDROM_SIZE 804
|
||||
#define MINIMUM_CDROM_READ_TOC_EX_SIZE 2
|
||||
|
||||
typedef struct _TRACK_DATA {
|
||||
UCHAR Reserved;
|
||||
UCHAR Control : 4;
|
||||
UCHAR Adr : 4;
|
||||
UCHAR TrackNumber;
|
||||
UCHAR Reserved1;
|
||||
UCHAR Address[4];
|
||||
} TRACK_DATA, *PTRACK_DATA;
|
||||
|
||||
/* CDROM_DISK_DATA.DiskData flags */
|
||||
#define CDROM_DISK_AUDIO_TRACK 0x00000001
|
||||
#define CDROM_DISK_DATA_TRACK 0x00000002
|
||||
|
||||
typedef struct _CDROM_DISK_DATA {
|
||||
ULONG DiskData;
|
||||
} CDROM_DISK_DATA, *PCDROM_DISK_DATA;
|
||||
|
||||
typedef struct _CDROM_PLAY_AUDIO_MSF {
|
||||
UCHAR StartingM;
|
||||
UCHAR StartingS;
|
||||
UCHAR StartingF;
|
||||
UCHAR EndingM;
|
||||
UCHAR EndingS;
|
||||
UCHAR EndingF;
|
||||
} CDROM_PLAY_AUDIO_MSF, *PCDROM_PLAY_AUDIO_MSF;
|
||||
|
||||
/* CDROM_READ_TOC_EX.Format constants */
|
||||
#define CDROM_READ_TOC_EX_FORMAT_TOC 0x00
|
||||
#define CDROM_READ_TOC_EX_FORMAT_SESSION 0x01
|
||||
#define CDROM_READ_TOC_EX_FORMAT_FULL_TOC 0x02
|
||||
#define CDROM_READ_TOC_EX_FORMAT_PMA 0x03
|
||||
#define CDROM_READ_TOC_EX_FORMAT_ATIP 0x04
|
||||
#define CDROM_READ_TOC_EX_FORMAT_CDTEXT 0x05
|
||||
|
||||
typedef struct _CDROM_READ_TOC_EX {
|
||||
UCHAR Format : 4;
|
||||
UCHAR Reserved1 : 3;
|
||||
UCHAR Msf : 1;
|
||||
UCHAR SessionTrack;
|
||||
UCHAR Reserved2;
|
||||
UCHAR Reserved3;
|
||||
} CDROM_READ_TOC_EX, *PCDROM_READ_TOC_EX;
|
||||
|
||||
typedef struct _CDROM_SEEK_AUDIO_MSF {
|
||||
UCHAR M;
|
||||
UCHAR S;
|
||||
UCHAR F;
|
||||
} CDROM_SEEK_AUDIO_MSF, *PCDROM_SEEK_AUDIO_MSF;
|
||||
|
||||
/* CDROM_SUB_Q_DATA_FORMAT.Format constants */
|
||||
#define IOCTL_CDROM_SUB_Q_CHANNEL 0x00
|
||||
#define IOCTL_CDROM_CURRENT_POSITION 0x01
|
||||
#define IOCTL_CDROM_MEDIA_CATALOG 0x02
|
||||
#define IOCTL_CDROM_TRACK_ISRC 0x03
|
||||
|
||||
typedef struct _CDROM_SUB_Q_DATA_FORMAT {
|
||||
UCHAR Format;
|
||||
UCHAR Track;
|
||||
} CDROM_SUB_Q_DATA_FORMAT, *PCDROM_SUB_Q_DATA_FORMAT;
|
||||
|
||||
typedef struct _CDROM_TOC {
|
||||
UCHAR Length[2];
|
||||
UCHAR FirstTrack;
|
||||
UCHAR LastTrack;
|
||||
TRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS];
|
||||
} CDROM_TOC, *PCDROM_TOC;
|
||||
|
||||
#define CDROM_TOC_SIZE sizeof(CDROM_TOC)
|
||||
|
||||
typedef struct _CDROM_TOC_ATIP_DATA_BLOCK {
|
||||
UCHAR CdrwReferenceSpeed : 3;
|
||||
UCHAR Reserved3 : 1;
|
||||
UCHAR WritePower : 3;
|
||||
UCHAR True1 : 1;
|
||||
UCHAR Reserved4 : 6;
|
||||
UCHAR UnrestrictedUse : 1;
|
||||
UCHAR Reserved5 : 1;
|
||||
UCHAR A3Valid : 1;
|
||||
UCHAR A2Valid : 1;
|
||||
UCHAR A1Valid : 1;
|
||||
UCHAR Reserved6 : 3;
|
||||
UCHAR IsCdrw : 1;
|
||||
UCHAR True2 : 1;
|
||||
UCHAR Reserved7;
|
||||
UCHAR LeadInMsf[3];
|
||||
UCHAR Reserved8;
|
||||
UCHAR LeadOutMsf[3];
|
||||
UCHAR Reserved9;
|
||||
UCHAR A1Values[3];
|
||||
UCHAR Reserved10;
|
||||
UCHAR A2Values[3];
|
||||
UCHAR Reserved11;
|
||||
UCHAR A3Values[3];
|
||||
UCHAR Reserved12;
|
||||
} CDROM_TOC_ATIP_DATA_BLOCK, *PCDROM_TOC_ATIP_DATA_BLOCK;
|
||||
|
||||
#if 0 // Added to make MSVC happy.
|
||||
typedef struct _CDROM_TOC_ATIP_DATA {
|
||||
UCHAR Length[2];
|
||||
UCHAR Reserved1;
|
||||
UCHAR Reserved2;
|
||||
CDROM_TOC_ATIP_DATA_BLOCK Descriptors[0];
|
||||
CDROM_TOC_ATIP_DATA_BLOCK Descriptors[1];
|
||||
} CDROM_TOC_ATIP_DATA, *PCDROM_TOC_ATIP_DATA;
|
||||
#endif
|
||||
|
||||
/* CDROM_TOC_CD_TEXT_DATA_BLOCK.PackType constants */
|
||||
#define CDROM_CD_TEXT_PACK_ALBUM_NAME 0x80
|
||||
#define CDROM_CD_TEXT_PACK_PERFORMER 0x81
|
||||
#define CDROM_CD_TEXT_PACK_SONGWRITER 0x82
|
||||
#define CDROM_CD_TEXT_PACK_COMPOSER 0x83
|
||||
#define CDROM_CD_TEXT_PACK_ARRANGER 0x84
|
||||
#define CDROM_CD_TEXT_PACK_MESSAGES 0x85
|
||||
#define CDROM_CD_TEXT_PACK_DISC_ID 0x86
|
||||
#define CDROM_CD_TEXT_PACK_GENRE 0x87
|
||||
#define CDROM_CD_TEXT_PACK_TOC_INFO 0x88
|
||||
#define CDROM_CD_TEXT_PACK_TOC_INFO2 0x89
|
||||
#define CDROM_CD_TEXT_PACK_UPC_EAN 0x8e
|
||||
#define CDROM_CD_TEXT_PACK_SIZE_INFO 0x8f
|
||||
|
||||
#if 0 // Added to make MSVC happy.
|
||||
typedef struct _CDROM_TOC_CD_TEXT_DATA_BLOCK {
|
||||
UCHAR PackType;
|
||||
UCHAR TrackNumber : 7;
|
||||
UCHAR ExtensionFlag : 1;
|
||||
UCHAR SequenceNumber;
|
||||
UCHAR CharacterPosition : 4;
|
||||
UCHAR BlockNumber : 3;
|
||||
UCHAR Unicode : 1;
|
||||
_ANONYMOUS_UNION union {
|
||||
UCHAR Text[12];
|
||||
WCHAR WText[6];
|
||||
} DUMMYUNIONNAME;
|
||||
UCHAR CRC[2];
|
||||
} CDROM_TOC_CD_TEXT_DATA_BLOCK, *PCDROM_TOC_CD_TEXT_DATA_BLOCK;
|
||||
|
||||
typedef struct _CDROM_TOC_CD_TEXT_DATA {
|
||||
UCHAR Length[2];
|
||||
UCHAR Reserved1;
|
||||
UCHAR Reserved2;
|
||||
CDROM_TOC_CD_TEXT_DATA_BLOCK Descriptors[0];
|
||||
} CDROM_TOC_CD_TEXT_DATA, *PCDROM_TOC_CD_TEXT_DATA;
|
||||
#endif
|
||||
|
||||
/* CDROM_TOC_FULL_TOC_DATA_BLOCK.Adr constants */
|
||||
#define ADR_NO_MODE_INFORMATION 0x0
|
||||
#define ADR_ENCODES_CURRENT_POSITION 0x1
|
||||
#define ADR_ENCODES_MEDIA_CATALOG 0x2
|
||||
#define ADR_ENCODES_ISRC 0x3
|
||||
|
||||
typedef struct _CDROM_TOC_FULL_TOC_DATA_BLOCK {
|
||||
UCHAR SessionNumber;
|
||||
UCHAR Control : 4;
|
||||
UCHAR Adr : 4;
|
||||
UCHAR Reserved1;
|
||||
UCHAR Point;
|
||||
UCHAR MsfExtra[3];
|
||||
UCHAR Zero;
|
||||
UCHAR Msf[3];
|
||||
} CDROM_TOC_FULL_TOC_DATA_BLOCK, *PCDROM_TOC_FULL_TOC_DATA_BLOCK;
|
||||
|
||||
#if 0 // Added to make MSVC happy.
|
||||
typedef struct _CDROM_TOC_FULL_TOC_DATA {
|
||||
UCHAR Length[2];
|
||||
UCHAR FirstCompleteSession;
|
||||
UCHAR LastCompleteSession;
|
||||
CDROM_TOC_FULL_TOC_DATA_BLOCK Descriptors[0];
|
||||
} CDROM_TOC_FULL_TOC_DATA, *PCDROM_TOC_FULL_TOC_DATA;
|
||||
|
||||
typedef struct _CDROM_TOC_PMA_DATA {
|
||||
UCHAR Length[2];
|
||||
UCHAR Reserved1;
|
||||
UCHAR Reserved2;
|
||||
CDROM_TOC_FULL_TOC_DATA_BLOCK Descriptors[0];
|
||||
} CDROM_TOC_PMA_DATA, *PCDROM_TOC_PMA_DATA;
|
||||
#endif
|
||||
|
||||
/* SUB_Q_HEADER.AudioStatus constants */
|
||||
#define AUDIO_STATUS_NOT_SUPPORTED 0x00
|
||||
#define AUDIO_STATUS_IN_PROGRESS 0x11
|
||||
#define AUDIO_STATUS_PAUSED 0x12
|
||||
#define AUDIO_STATUS_PLAY_COMPLETE 0x13
|
||||
#define AUDIO_STATUS_PLAY_ERROR 0x14
|
||||
#define AUDIO_STATUS_NO_STATUS 0x15
|
||||
|
||||
typedef struct _SUB_Q_HEADER {
|
||||
UCHAR Reserved;
|
||||
UCHAR AudioStatus;
|
||||
UCHAR DataLength[2];
|
||||
} SUB_Q_HEADER, *PSUB_Q_HEADER;
|
||||
|
||||
typedef struct _SUB_Q_MEDIA_CATALOG_NUMBER {
|
||||
SUB_Q_HEADER Header;
|
||||
UCHAR FormatCode;
|
||||
UCHAR Reserved[3];
|
||||
UCHAR Reserved1 : 7;
|
||||
UCHAR Mcval :1;
|
||||
UCHAR MediaCatalog[15];
|
||||
} SUB_Q_MEDIA_CATALOG_NUMBER, *PSUB_Q_MEDIA_CATALOG_NUMBER;
|
||||
|
||||
typedef struct _SUB_Q_TRACK_ISRC {
|
||||
SUB_Q_HEADER Header;
|
||||
UCHAR FormatCode;
|
||||
UCHAR Reserved0;
|
||||
UCHAR Track;
|
||||
UCHAR Reserved1;
|
||||
UCHAR Reserved2 : 7;
|
||||
UCHAR Tcval : 1;
|
||||
UCHAR TrackIsrc[15];
|
||||
} SUB_Q_TRACK_ISRC, *PSUB_Q_TRACK_ISRC;
|
||||
|
||||
typedef struct _SUB_Q_CURRENT_POSITION {
|
||||
SUB_Q_HEADER Header;
|
||||
UCHAR FormatCode;
|
||||
UCHAR Control : 4;
|
||||
UCHAR ADR : 4;
|
||||
UCHAR TrackNumber;
|
||||
UCHAR IndexNumber;
|
||||
UCHAR AbsoluteAddress[4];
|
||||
UCHAR TrackRelativeAddress[4];
|
||||
} SUB_Q_CURRENT_POSITION, *PSUB_Q_CURRENT_POSITION;
|
||||
|
||||
typedef union _SUB_Q_CHANNEL_DATA {
|
||||
SUB_Q_CURRENT_POSITION CurrentPosition;
|
||||
SUB_Q_MEDIA_CATALOG_NUMBER MediaCatalog;
|
||||
SUB_Q_TRACK_ISRC TrackIsrc;
|
||||
} SUB_Q_CHANNEL_DATA, *PSUB_Q_CHANNEL_DATA;
|
||||
|
||||
/* CDROM_AUDIO_CONTROL.LbaFormat constants */
|
||||
#define AUDIO_WITH_PREEMPHASIS 0x1
|
||||
#define DIGITAL_COPY_PERMITTED 0x2
|
||||
#define AUDIO_DATA_TRACK 0x4
|
||||
#define TWO_FOUR_CHANNEL_AUDIO 0x8
|
||||
|
||||
typedef struct _CDROM_AUDIO_CONTROL {
|
||||
UCHAR LbaFormat;
|
||||
USHORT LogicalBlocksPerSecond;
|
||||
} CDROM_AUDIO_CONTROL, *PCDROM_AUDIO_CONTROL;
|
||||
|
||||
typedef struct _VOLUME_CONTROL {
|
||||
UCHAR PortVolume[4];
|
||||
} VOLUME_CONTROL, *PVOLUME_CONTROL;
|
||||
|
||||
typedef enum _TRACK_MODE_TYPE {
|
||||
YellowMode2,
|
||||
XAForm2,
|
||||
CDDA
|
||||
} TRACK_MODE_TYPE, *PTRACK_MODE_TYPE;
|
||||
|
||||
typedef struct __RAW_READ_INFO {
|
||||
LARGE_INTEGER DiskOffset;
|
||||
ULONG SectorCount;
|
||||
TRACK_MODE_TYPE TrackMode;
|
||||
} RAW_READ_INFO, *PRAW_READ_INFO;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __NTDDCDRM_H */
|
||||
@@ -0,0 +1,388 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Original license header:
|
||||
*
|
||||
* Cabal - Legacy Game Implementations
|
||||
*
|
||||
* Cabal is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#undef ARRAYSIZE // winnt.h defines ARRAYSIZE, but we want our own one...
|
||||
|
||||
#include "backends/audiocd/win32/win32-audiocd.h"
|
||||
|
||||
#include "audio/audiostream.h"
|
||||
#include "backends/audiocd/audiocd-stream.h"
|
||||
#include "backends/audiocd/default/default-audiocd.h"
|
||||
#include "common/array.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/mutex.h"
|
||||
#include "common/queue.h"
|
||||
#include "common/str.h"
|
||||
#include "common/timer.h"
|
||||
|
||||
#include <winioctl.h>
|
||||
#if _MSC_VER < 1900
|
||||
// WORKAROUND: Older versions of MSVC might not supply DDK headers by default.
|
||||
// Visual Studio 2015 contains the required headers. We use a compatability
|
||||
// header from MinGW's w32api for all older versions.
|
||||
// TODO: Limit this to the Visual Studio versions which actually require this.
|
||||
#include "msvc/ntddcdrm.h"
|
||||
#elif defined(__MINGW32__) && !defined(__MINGW64__)
|
||||
// Classic MinGW uses non standard paths for DDK headers.
|
||||
#include <ddk/ntddcdrm.h>
|
||||
#else
|
||||
#include <ntddcdrm.h>
|
||||
#endif
|
||||
|
||||
class Win32AudioCDStream : public AudioCDStream {
|
||||
public:
|
||||
Win32AudioCDStream(HANDLE handle, const TRACK_DATA &startEntry, const TRACK_DATA &endEntry);
|
||||
~Win32AudioCDStream();
|
||||
|
||||
protected:
|
||||
uint getStartFrame() const;
|
||||
uint getEndFrame() const;
|
||||
bool readFrame(int frame, int16 *buffer);
|
||||
|
||||
private:
|
||||
HANDLE _driveHandle;
|
||||
const TRACK_DATA &_startEntry, &_endEntry;
|
||||
|
||||
enum {
|
||||
// The CD-ROM pre-gap is 2s
|
||||
kPreGapFrames = kFramesPerSecond * 2
|
||||
};
|
||||
|
||||
static int getFrameCount(const TRACK_DATA &data) {
|
||||
int time = data.Address[1];
|
||||
time *= kSecondsPerMinute;
|
||||
time += data.Address[2];
|
||||
time *= kFramesPerSecond;
|
||||
time += data.Address[3];
|
||||
return time;
|
||||
}
|
||||
};
|
||||
|
||||
Win32AudioCDStream::Win32AudioCDStream(HANDLE handle, const TRACK_DATA &startEntry, const TRACK_DATA &endEntry) :
|
||||
_driveHandle(handle), _startEntry(startEntry), _endEntry(endEntry) {
|
||||
// We fill the buffer here already to prevent any out of sync issues due
|
||||
// to the CD not yet having spun up.
|
||||
startTimer(true);
|
||||
}
|
||||
|
||||
Win32AudioCDStream::~Win32AudioCDStream() {
|
||||
stopTimer();
|
||||
}
|
||||
|
||||
uint Win32AudioCDStream::getStartFrame() const {
|
||||
return getFrameCount(_startEntry);
|
||||
}
|
||||
|
||||
uint Win32AudioCDStream::getEndFrame() const {
|
||||
return getFrameCount(_endEntry);
|
||||
}
|
||||
|
||||
bool Win32AudioCDStream::readFrame(int frame, int16 *buffer) {
|
||||
// Request to read that frame
|
||||
RAW_READ_INFO readAudio;
|
||||
memset(&readAudio, 0, sizeof(readAudio));
|
||||
readAudio.DiskOffset.QuadPart = (frame - kPreGapFrames) * 2048;
|
||||
readAudio.SectorCount = 1;
|
||||
readAudio.TrackMode = CDDA;
|
||||
|
||||
DWORD bytesReturned;
|
||||
return DeviceIoControl(
|
||||
_driveHandle,
|
||||
IOCTL_CDROM_RAW_READ,
|
||||
&readAudio,
|
||||
sizeof(readAudio),
|
||||
buffer,
|
||||
kBytesPerFrame,
|
||||
&bytesReturned,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
class Win32AudioCDManager : public DefaultAudioCDManager {
|
||||
public:
|
||||
Win32AudioCDManager();
|
||||
~Win32AudioCDManager();
|
||||
|
||||
bool open();
|
||||
void close();
|
||||
bool play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate = false);
|
||||
|
||||
protected:
|
||||
bool openCD(int drive);
|
||||
bool openCD(const Common::String &drive);
|
||||
|
||||
private:
|
||||
bool loadTOC();
|
||||
|
||||
typedef Common::Array<char> DriveList;
|
||||
DriveList detectDrives();
|
||||
bool tryAddDrive(char drive, DriveList &drives);
|
||||
|
||||
HANDLE _driveHandle;
|
||||
int _firstTrack, _lastTrack;
|
||||
Common::Array<TRACK_DATA> _tocEntries;
|
||||
};
|
||||
|
||||
Win32AudioCDManager::Win32AudioCDManager() {
|
||||
_driveHandle = INVALID_HANDLE_VALUE;
|
||||
_firstTrack = _lastTrack = 0;
|
||||
}
|
||||
|
||||
Win32AudioCDManager::~Win32AudioCDManager() {
|
||||
close();
|
||||
}
|
||||
|
||||
bool Win32AudioCDManager::open() {
|
||||
close();
|
||||
|
||||
if (openRealCD())
|
||||
return true;
|
||||
|
||||
return DefaultAudioCDManager::open();
|
||||
}
|
||||
|
||||
bool Win32AudioCDManager::openCD(int drive) {
|
||||
// Fetch the drive list
|
||||
DriveList drives = detectDrives();
|
||||
if (drive >= (int)drives.size())
|
||||
return false;
|
||||
|
||||
debug(1, "Opening CD drive %c:\\", drives[drive]);
|
||||
|
||||
// Construct the drive path and try to open it
|
||||
Common::String drivePath = Common::String::format("\\\\.\\%c:", drives[drive]);
|
||||
_driveHandle = CreateFileA(drivePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (_driveHandle == INVALID_HANDLE_VALUE) {
|
||||
warning("Failed to open drive %c:\\, error %d", drives[drive], (int)GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!loadTOC()) {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Win32AudioCDManager::openCD(const Common::String &drive) {
|
||||
// Just some bounds checking
|
||||
if (drive.empty() || drive.size() > 3)
|
||||
return false;
|
||||
|
||||
if (!Common::isAlpha(drive[0]) || drive[1] != ':')
|
||||
return false;
|
||||
|
||||
if (drive[2] != 0 && drive[2] != '\\')
|
||||
return false;
|
||||
|
||||
DriveList drives;
|
||||
if (!tryAddDrive(toupper(drive[0]), drives))
|
||||
return false;
|
||||
|
||||
// Construct the drive path and try to open it
|
||||
Common::String drivePath = Common::String::format("\\\\.\\%c:", drives[0]);
|
||||
_driveHandle = CreateFileA(drivePath.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
if (_driveHandle == INVALID_HANDLE_VALUE) {
|
||||
warning("Failed to open drive %c:\\, error %d", drives[0], (int)GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!loadTOC()) {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Win32AudioCDManager::close() {
|
||||
DefaultAudioCDManager::close();
|
||||
|
||||
if (_driveHandle != INVALID_HANDLE_VALUE) {
|
||||
CloseHandle(_driveHandle);
|
||||
_driveHandle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
_firstTrack = _lastTrack = 0;
|
||||
_tocEntries.clear();
|
||||
}
|
||||
|
||||
bool Win32AudioCDManager::play(int track, int numLoops, int startFrame, int duration, bool onlyEmulate) {
|
||||
// Prefer emulation
|
||||
if (DefaultAudioCDManager::play(track, numLoops, startFrame, duration, onlyEmulate))
|
||||
return true;
|
||||
|
||||
// If we're set to only emulate, or have no CD drive, return here
|
||||
if (onlyEmulate || _driveHandle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
|
||||
// HACK: For now, just assume that track number is right
|
||||
// That only works because ScummVM uses the wrong track number anyway
|
||||
|
||||
if (track >= (int)_tocEntries.size() - 1) {
|
||||
warning("No such track %d", track);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Bail if the track isn't an audio track
|
||||
if ((_tocEntries[track].Control & 0x04) != 0) {
|
||||
warning("Track %d is not audio", track);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create the AudioStream and play it
|
||||
debug(1, "Playing CD track %d", track);
|
||||
|
||||
Audio::SeekableAudioStream *audioStream = new Win32AudioCDStream(_driveHandle, _tocEntries[track], _tocEntries[track + 1]);
|
||||
|
||||
Audio::Timestamp start = Audio::Timestamp(0, startFrame, 75);
|
||||
Audio::Timestamp end = (duration == 0) ? audioStream->getLength() : Audio::Timestamp(0, startFrame + duration, 75);
|
||||
|
||||
// Fake emulation since we're really playing an AudioStream
|
||||
_emulating = true;
|
||||
|
||||
_mixer->playStream(
|
||||
Audio::Mixer::kMusicSoundType,
|
||||
&_handle,
|
||||
Audio::makeLoopingAudioStream(audioStream, start, end, (numLoops < 1) ? numLoops + 1 : numLoops),
|
||||
-1,
|
||||
_cd.volume,
|
||||
_cd.balance,
|
||||
DisposeAfterUse::YES,
|
||||
true);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Win32AudioCDManager::loadTOC() {
|
||||
CDROM_READ_TOC_EX tocRequest;
|
||||
memset(&tocRequest, 0, sizeof(tocRequest));
|
||||
tocRequest.Format = CDROM_READ_TOC_EX_FORMAT_TOC;
|
||||
tocRequest.Msf = 1;
|
||||
tocRequest.SessionTrack = 0;
|
||||
|
||||
DWORD bytesReturned;
|
||||
CDROM_TOC tocData;
|
||||
bool result = DeviceIoControl(
|
||||
_driveHandle,
|
||||
IOCTL_CDROM_READ_TOC_EX,
|
||||
&tocRequest,
|
||||
sizeof(tocRequest),
|
||||
&tocData,
|
||||
sizeof(tocData),
|
||||
&bytesReturned,
|
||||
NULL);
|
||||
if (!result) {
|
||||
debug("Failed to query the CD TOC: %d", (int)GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
_firstTrack = tocData.FirstTrack;
|
||||
_lastTrack = tocData.LastTrack;
|
||||
#if 0
|
||||
debug("First Track: %d", tocData.FirstTrack);
|
||||
debug("Last Track: %d", tocData.LastTrack);
|
||||
#endif
|
||||
|
||||
for (uint32 i = 0; i < (bytesReturned - 4) / sizeof(TRACK_DATA); i++)
|
||||
_tocEntries.push_back(tocData.TrackData[i]);
|
||||
|
||||
#if 0
|
||||
for (uint32 i = 0; i < _tocEntries.size(); i++) {
|
||||
const TRACK_DATA &entry = _tocEntries[i];
|
||||
debug("Entry:");
|
||||
debug("\tTrack: %d", entry.TrackNumber);
|
||||
debug("\tAdr: %d", entry.Adr);
|
||||
debug("\tCtrl: %d", entry.Control);
|
||||
debug("\tMSF: %d:%d:%d\n", entry.Address[1], entry.Address[2], entry.Address[3]);
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Win32AudioCDManager::DriveList Win32AudioCDManager::detectDrives() {
|
||||
DriveList drives;
|
||||
|
||||
// Try to get the game path's drive
|
||||
char gameDrive = 0;
|
||||
if (ConfMan.hasKey("path")) {
|
||||
Common::String gamePath = ConfMan.get("path");
|
||||
char fullPath[MAX_PATH];
|
||||
DWORD result = GetFullPathNameA(gamePath.c_str(), sizeof(fullPath), fullPath, 0);
|
||||
|
||||
if (result > 0 && result < sizeof(fullPath) && Common::isAlpha(fullPath[0]) && fullPath[1] == ':' && tryAddDrive(toupper(fullPath[0]), drives))
|
||||
gameDrive = drives[0];
|
||||
}
|
||||
|
||||
// Try adding the rest of the drives
|
||||
for (char drive = 'A'; drive <= 'Z'; drive++)
|
||||
if (drive != gameDrive)
|
||||
tryAddDrive(drive, drives);
|
||||
|
||||
return drives;
|
||||
}
|
||||
|
||||
bool Win32AudioCDManager::tryAddDrive(char drive, DriveList &drives) {
|
||||
Common::String drivePath = Common::String::format("%c:\\", drive);
|
||||
|
||||
// Ensure it's an actual CD drive
|
||||
if (GetDriveTypeA(drivePath.c_str()) != DRIVE_CDROM)
|
||||
return false;
|
||||
|
||||
debug(2, "Detected drive %c:\\ as a CD drive", drive);
|
||||
drives.push_back(drive);
|
||||
return true;
|
||||
}
|
||||
|
||||
AudioCDManager *createWin32AudioCDManager() {
|
||||
return new Win32AudioCDManager();
|
||||
}
|
||||
|
||||
#endif // WIN32
|
||||
@@ -0,0 +1,60 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Original license header:
|
||||
*
|
||||
* Cabal - Legacy Game Implementations
|
||||
*
|
||||
* Cabal is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_AUDIOCD_WIN32_H
|
||||
#define BACKENDS_AUDIOCD_WIN32_H
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
class AudioCDManager;
|
||||
|
||||
/**
|
||||
* Create an AudioCDManager using the Win32 API
|
||||
*/
|
||||
AudioCDManager *createWin32AudioCDManager();
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -121,7 +121,7 @@ int SdlEventSource::mapKey(SDLKey sdlKey, SDLMod mod, Uint16 unicode) {
|
||||
Common::KeyCode key = SDLToOSystemKeycode(sdlKey);
|
||||
|
||||
if (key >= Common::KEYCODE_F1 && key <= Common::KEYCODE_F9) {
|
||||
return key - SDLK_F1 + Common::ASCII_F1;
|
||||
return key - Common::KEYCODE_F1 + Common::ASCII_F1;
|
||||
} else if (key >= Common::KEYCODE_KP0 && key <= Common::KEYCODE_KP9) {
|
||||
return key - Common::KEYCODE_KP0 + '0';
|
||||
} else if (key >= Common::KEYCODE_UP && key <= Common::KEYCODE_PAGEDOWN) {
|
||||
@@ -531,15 +531,17 @@ bool SdlEventSource::handleKeyDown(SDL_Event &ev, Common::Event &event) {
|
||||
|
||||
SDLModToOSystemKeyFlags(SDL_GetModState(), event);
|
||||
|
||||
SDLKey sdlKeycode = obtainKeycode(ev.key.keysym);
|
||||
|
||||
// Handle scroll lock as a key modifier
|
||||
if (ev.key.keysym.sym == SDLK_SCROLLOCK)
|
||||
if (sdlKeycode == SDLK_SCROLLOCK)
|
||||
_scrollLock = !_scrollLock;
|
||||
|
||||
if (_scrollLock)
|
||||
event.kbd.flags |= Common::KBD_SCRL;
|
||||
|
||||
// Ctrl-m toggles mouse capture
|
||||
if (event.kbd.hasFlags(Common::KBD_CTRL) && ev.key.keysym.sym == 'm') {
|
||||
if (event.kbd.hasFlags(Common::KBD_CTRL) && sdlKeycode == 'm') {
|
||||
if (_graphicsManager) {
|
||||
_graphicsManager->getWindow()->toggleMouseGrab();
|
||||
}
|
||||
@@ -548,26 +550,26 @@ bool SdlEventSource::handleKeyDown(SDL_Event &ev, Common::Event &event) {
|
||||
|
||||
#if defined(MACOSX)
|
||||
// On Macintosh, Cmd-Q quits
|
||||
if ((ev.key.keysym.mod & KMOD_META) && ev.key.keysym.sym == 'q') {
|
||||
if ((ev.key.keysym.mod & KMOD_META) && sdlKeycode == 'q') {
|
||||
event.type = Common::EVENT_QUIT;
|
||||
return true;
|
||||
}
|
||||
#elif defined(POSIX)
|
||||
// On other *nix systems, Control-Q quits
|
||||
if ((ev.key.keysym.mod & KMOD_CTRL) && ev.key.keysym.sym == 'q') {
|
||||
if ((ev.key.keysym.mod & KMOD_CTRL) && sdlKeycode == 'q') {
|
||||
event.type = Common::EVENT_QUIT;
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
// Ctrl-z and Alt-X quit
|
||||
if ((event.kbd.hasFlags(Common::KBD_CTRL) && ev.key.keysym.sym == 'z') || (event.kbd.hasFlags(Common::KBD_ALT) && ev.key.keysym.sym == 'x')) {
|
||||
// Ctrl-z quits
|
||||
if ((event.kbd.hasFlags(Common::KBD_CTRL) && sdlKeycode == 'z')) {
|
||||
event.type = Common::EVENT_QUIT;
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
// On Windows, also use the default Alt-F4 quit combination
|
||||
if ((ev.key.keysym.mod & KMOD_ALT) && ev.key.keysym.sym == SDLK_F4) {
|
||||
if ((ev.key.keysym.mod & KMOD_ALT) && sdlKeycode == SDLK_F4) {
|
||||
event.type = Common::EVENT_QUIT;
|
||||
return true;
|
||||
}
|
||||
@@ -575,7 +577,7 @@ bool SdlEventSource::handleKeyDown(SDL_Event &ev, Common::Event &event) {
|
||||
#endif
|
||||
|
||||
// Ctrl-u toggles mute
|
||||
if ((ev.key.keysym.mod & KMOD_CTRL) && ev.key.keysym.sym == 'u') {
|
||||
if ((ev.key.keysym.mod & KMOD_CTRL) && sdlKeycode == 'u') {
|
||||
event.type = Common::EVENT_MUTE;
|
||||
return true;
|
||||
}
|
||||
@@ -584,8 +586,8 @@ bool SdlEventSource::handleKeyDown(SDL_Event &ev, Common::Event &event) {
|
||||
return true;
|
||||
|
||||
event.type = Common::EVENT_KEYDOWN;
|
||||
event.kbd.keycode = SDLToOSystemKeycode(ev.key.keysym.sym);
|
||||
event.kbd.ascii = mapKey(ev.key.keysym.sym, (SDLMod)ev.key.keysym.mod, obtainUnicode(ev.key.keysym));
|
||||
event.kbd.keycode = SDLToOSystemKeycode(sdlKeycode);
|
||||
event.kbd.ascii = mapKey(sdlKeycode, (SDLMod)ev.key.keysym.mod, obtainUnicode(ev.key.keysym));
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -594,6 +596,7 @@ bool SdlEventSource::handleKeyUp(SDL_Event &ev, Common::Event &event) {
|
||||
if (remapKey(ev, event))
|
||||
return true;
|
||||
|
||||
SDLKey sdlKeycode = obtainKeycode(ev.key.keysym);
|
||||
SDLMod mod = SDL_GetModState();
|
||||
|
||||
// Check if this is an event handled by handleKeyDown(), and stop if it is
|
||||
@@ -601,35 +604,30 @@ bool SdlEventSource::handleKeyUp(SDL_Event &ev, Common::Event &event) {
|
||||
// Check if the Ctrl key is down, so that we can trap cases where the
|
||||
// user has the Ctrl key down, and has just released a special key
|
||||
if (mod & KMOD_CTRL) {
|
||||
if (ev.key.keysym.sym == 'm' || // Ctrl-m toggles mouse capture
|
||||
if (sdlKeycode == 'm' || // Ctrl-m toggles mouse capture
|
||||
#if defined(MACOSX)
|
||||
// Meta - Q, handled below
|
||||
#elif defined(POSIX)
|
||||
ev.key.keysym.sym == 'q' || // On other *nix systems, Control-Q quits
|
||||
sdlKeycode == 'q' || // On other *nix systems, Control-Q quits
|
||||
#else
|
||||
ev.key.keysym.sym == 'z' || // Ctrl-z quit
|
||||
sdlKeycode == 'z' || // Ctrl-z quit
|
||||
#endif
|
||||
ev.key.keysym.sym == 'u') // Ctrl-u toggles mute
|
||||
sdlKeycode == 'u') // Ctrl-u toggles mute
|
||||
return false;
|
||||
}
|
||||
|
||||
// Same for other keys (Meta and Alt)
|
||||
#if defined(MACOSX)
|
||||
if ((mod & KMOD_META) && ev.key.keysym.sym == 'q')
|
||||
if ((mod & KMOD_META) && sdlKeycode == 'q')
|
||||
return false; // On Macintosh, Cmd-Q quits
|
||||
#elif defined(POSIX)
|
||||
// Control Q has already been handled above
|
||||
#else
|
||||
if ((mod & KMOD_ALT) && ev.key.keysym.sym == 'x')
|
||||
return false; // Alt-x quit
|
||||
#endif
|
||||
|
||||
// If we reached here, this isn't an event handled by handleKeyDown(), thus
|
||||
// continue normally
|
||||
|
||||
event.type = Common::EVENT_KEYUP;
|
||||
event.kbd.keycode = SDLToOSystemKeycode(ev.key.keysym.sym);
|
||||
event.kbd.ascii = mapKey(ev.key.keysym.sym, (SDLMod)ev.key.keysym.mod, 0);
|
||||
event.kbd.keycode = SDLToOSystemKeycode(sdlKeycode);
|
||||
event.kbd.ascii = mapKey(sdlKeycode, (SDLMod)ev.key.keysym.mod, 0);
|
||||
|
||||
// Ctrl-Alt-<key> will change the GFX mode
|
||||
SDLModToOSystemKeyFlags(mod, event);
|
||||
@@ -887,10 +885,63 @@ bool SdlEventSource::handleResizeEvent(Common::Event &event, int w, int h) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SDLKey SdlEventSource::obtainKeycode(const SDL_keysym keySym) {
|
||||
#if !SDL_VERSION_ATLEAST(2, 0, 0) && defined(WIN32) && !defined(_WIN32_WCE)
|
||||
// WORKAROUND: SDL 1.2 on Windows does not use the user configured keyboard layout,
|
||||
// resulting in "keySym.sym" values to always be those expected for an US keyboard.
|
||||
// For example, SDL returns SDLK_Q when pressing the 'A' key on an AZERTY keyboard.
|
||||
// This defeats the purpose of keycodes which is to be able to refer to a key without
|
||||
// knowing where it is physically located.
|
||||
// We work around this issue by querying the currently active Windows keyboard layout
|
||||
// using the scancode provided by SDL.
|
||||
|
||||
if (keySym.sym >= SDLK_0 && keySym.sym <= SDLK_9) {
|
||||
// The keycode returned by SDL is kept for the number keys.
|
||||
// Querying the keyboard layout for those would return the base key values
|
||||
// for AZERTY keyboards, which are not numbers. For example, SDLK_1 would
|
||||
// map to SDLK_AMPERSAND. This is theoretically correct but practically unhelpful,
|
||||
// because it makes it impossible to handle key combinations such as "ctrl-1".
|
||||
return keySym.sym;
|
||||
}
|
||||
|
||||
int vk = MapVirtualKey(keySym.scancode, MAPVK_VSC_TO_VK);
|
||||
if (vk) {
|
||||
int ch = (MapVirtualKey(vk, MAPVK_VK_TO_CHAR) & 0x7FFF);
|
||||
// The top bit of the result of MapVirtualKey with MAPVK_VSC_TO_VK signals
|
||||
// a dead key was pressed. In that case we keep the value of the accent alone.
|
||||
if (ch) {
|
||||
if (ch >= 'A' && ch <= 'Z') {
|
||||
// Windows returns uppercase ASCII whereas SDL expects lowercase
|
||||
return (SDLKey)(SDLK_a + (ch - 'A'));
|
||||
} else {
|
||||
return (SDLKey)ch;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return keySym.sym;
|
||||
}
|
||||
|
||||
uint32 SdlEventSource::obtainUnicode(const SDL_keysym keySym) {
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
SDL_Event events[2];
|
||||
|
||||
// Update the event queue here to give SDL a chance to insert TEXTINPUT
|
||||
// events for KEYDOWN events. Otherwise we have a high chance that on
|
||||
// Windows the TEXTINPUT event is not in the event queue at this point.
|
||||
// In this case we will get two events with ascii values due to mapKey
|
||||
// and dispatchSDLEvent. This results in nasty double input of characters
|
||||
// in the GUI.
|
||||
//
|
||||
// FIXME: This is all a bit fragile because in mapKey we derive the ascii
|
||||
// value from the key code if no unicode value is given. This is legacy
|
||||
// behavior and should be removed anyway. If that is removed, we might not
|
||||
// even need to do this peeking here but instead can rely on the
|
||||
// SDL_TEXTINPUT case in dispatchSDLEvent to introduce keydown/keyup with
|
||||
// proper ASCII values (but with KEYCODE_INVALID as keycode).
|
||||
SDL_PumpEvents();
|
||||
|
||||
// In SDL2, the unicode field has been removed from the keysym struct.
|
||||
// Instead a SDL_TEXTINPUT event is generated on key combinations that
|
||||
// generates unicode.
|
||||
|
||||
@@ -150,6 +150,11 @@ protected:
|
||||
*/
|
||||
uint32 obtainUnicode(const SDL_keysym keySym);
|
||||
|
||||
/**
|
||||
* Extracts the keycode for the specified key sym.
|
||||
*/
|
||||
SDLKey obtainKeycode(const SDL_keysym keySym);
|
||||
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
/**
|
||||
* Whether _fakeKeyUp contains an event we need to send.
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef __OS2__
|
||||
#define INCL_DOS
|
||||
@@ -251,4 +252,67 @@ Common::WriteStream *POSIXFilesystemNode::createWriteStream() {
|
||||
return StdioStream::makeFromPath(getPath(), true);
|
||||
}
|
||||
|
||||
namespace Posix {
|
||||
|
||||
bool assureDirectoryExists(const Common::String &dir, const char *prefix) {
|
||||
struct stat sb;
|
||||
|
||||
// Check whether the prefix exists if one is supplied.
|
||||
if (prefix) {
|
||||
if (stat(prefix, &sb) != 0) {
|
||||
return false;
|
||||
} else if (!S_ISDIR(sb.st_mode)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Obtain absolute path.
|
||||
Common::String path;
|
||||
if (prefix) {
|
||||
path = prefix;
|
||||
path += '/';
|
||||
path += dir;
|
||||
} else {
|
||||
path = dir;
|
||||
}
|
||||
|
||||
path = Common::normalizePath(path, '/');
|
||||
|
||||
const Common::String::iterator end = path.end();
|
||||
Common::String::iterator cur = path.begin();
|
||||
if (*cur == '/')
|
||||
++cur;
|
||||
|
||||
do {
|
||||
if (cur + 1 != end) {
|
||||
if (*cur != '/') {
|
||||
continue;
|
||||
}
|
||||
|
||||
// It is kind of ugly and against the purpose of Common::String to
|
||||
// insert 0s inside, but this is just for a local string and
|
||||
// simplifies the code a lot.
|
||||
*cur = '\0';
|
||||
}
|
||||
|
||||
if (mkdir(path.c_str(), 0755) != 0) {
|
||||
if (errno == EEXIST) {
|
||||
if (stat(path.c_str(), &sb) != 0) {
|
||||
return false;
|
||||
} else if (!S_ISDIR(sb.st_mode)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*cur = '/';
|
||||
} while (cur++ != end);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Posix
|
||||
|
||||
#endif //#if defined(POSIX)
|
||||
|
||||
@@ -81,4 +81,18 @@ private:
|
||||
virtual void setFlags();
|
||||
};
|
||||
|
||||
namespace Posix {
|
||||
|
||||
/**
|
||||
* Assure that a directory path exists.
|
||||
*
|
||||
* @param dir The path which is required to exist.
|
||||
* @param prefix An (optional) prefix which should not be created if non existent.
|
||||
* prefix is prepended to dir if supplied.
|
||||
* @return true in case the directoy exists (or was created), false otherwise.
|
||||
*/
|
||||
bool assureDirectoryExists(const Common::String &dir, const char *prefix = nullptr);
|
||||
|
||||
} // End of namespace Posix
|
||||
|
||||
#endif
|
||||
|
||||
@@ -185,6 +185,9 @@ MusicDevices WindowsMusicPlugin::getDevices() const {
|
||||
deviceNames.push_back(tmp.szPname);
|
||||
}
|
||||
|
||||
// Limit us to the number of actually retrieved devices.
|
||||
numDevs = deviceNames.size();
|
||||
|
||||
// Check for non-unique device names. This may happen if someone has devices with identical
|
||||
// names (e. g. more than one USB device of the exact same hardware type). It seems that this
|
||||
// does happen in reality sometimes. We generate index numbers for these devices.
|
||||
|
||||
@@ -3,6 +3,7 @@ MODULE := backends
|
||||
MODULE_OBJS := \
|
||||
base-backend.o \
|
||||
modular-backend.o \
|
||||
audiocd/audiocd-stream.o \
|
||||
audiocd/default/default-audiocd.o \
|
||||
events/default/default-events.o \
|
||||
fs/abstract-fs.o \
|
||||
@@ -90,6 +91,7 @@ endif
|
||||
|
||||
ifdef MACOSX
|
||||
MODULE_OBJS += \
|
||||
audiocd/macosx/macosx-audiocd.o \
|
||||
midi/coreaudio.o \
|
||||
midi/coremidi.o \
|
||||
updates/macosx/macosx-updates.o \
|
||||
@@ -98,11 +100,13 @@ endif
|
||||
|
||||
ifdef WIN32
|
||||
MODULE_OBJS += \
|
||||
audiocd/win32/win32-audiocd.o \
|
||||
fs/windows/windows-fs.o \
|
||||
fs/windows/windows-fs-factory.o \
|
||||
midi/windows.o \
|
||||
plugins/win32/win32-provider.o \
|
||||
saves/windows/windows-saves.o \
|
||||
updates/win32/win32-updates.o \
|
||||
taskbar/win32/win32-taskbar.o
|
||||
endif
|
||||
|
||||
@@ -121,6 +125,11 @@ MODULE_OBJS += \
|
||||
events/ps3sdl/ps3sdl-events.o
|
||||
endif
|
||||
|
||||
ifdef USE_LINUXCD
|
||||
MODULE_OBJS += \
|
||||
audiocd/linux/linux-audiocd.o
|
||||
endif
|
||||
|
||||
ifeq ($(BACKEND),tizen)
|
||||
MODULE_OBJS += \
|
||||
timer/tizen/timer.o
|
||||
|
||||
@@ -24,13 +24,44 @@
|
||||
|
||||
#if defined(__amigaos4__)
|
||||
|
||||
#include "backends/fs/amigaos4/amigaos4-fs.h"
|
||||
#include "backends/platform/sdl/amigaos/amigaos.h"
|
||||
#include "backends/plugins/sdl/sdl-provider.h"
|
||||
#include "base/main.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
// Set up a stack cookie to avoid crashes due to too few stack set by users
|
||||
// The following will gather the application name and add the install path
|
||||
// to a variable in AmigaOS4's ENV(ARC) system. It will be placed in AppPaths
|
||||
// so that ScummVM can become AmiUpdate aware
|
||||
const char *const appname = "ResidualVM";
|
||||
|
||||
BPTR lock;
|
||||
APTR oldwin;
|
||||
|
||||
// Obtain a lock to the home directory
|
||||
if ((lock = IDOS->GetProgramDir())) {
|
||||
TEXT progpath[2048];
|
||||
TEXT apppath[1024] = "AppPaths";
|
||||
|
||||
if (IDOS->DevNameFromLock(lock,
|
||||
progpath,
|
||||
sizeof(progpath),
|
||||
DN_FULLPATH)) {
|
||||
|
||||
// Stop any "Insert volume..." type requesters
|
||||
oldwin = IDOS->SetProcWindow((APTR)-1);
|
||||
|
||||
// Finally, set the variable to the path the executable was run from
|
||||
IDOS->AddPart( apppath, appname, 1024);
|
||||
IDOS->SetVar( apppath, progpath, -1, GVF_GLOBAL_ONLY|GVF_SAVE_VAR );
|
||||
|
||||
// Turn system requesters back on
|
||||
IDOS->SetProcWindow( oldwin );
|
||||
}
|
||||
}
|
||||
|
||||
// Set up a stack cookie to avoid crashes from a stack set too low
|
||||
static const char *stack_cookie __attribute__((used)) = "$STACK: 600000";
|
||||
|
||||
// Create our OSystem instance
|
||||
@@ -44,7 +75,7 @@ int main(int argc, char *argv[]) {
|
||||
PluginManager::instance().addPluginProvider(new SDLPluginProvider());
|
||||
#endif
|
||||
|
||||
// Invoke the actual ScummVM main entry point:
|
||||
// Invoke the actual ScummVM main entry point
|
||||
int res = scummvm_main(argc, argv);
|
||||
|
||||
// Free OSystem
|
||||
|
||||
@@ -10,6 +10,17 @@ amigaosdist: $(EXECUTABLE)
|
||||
ifdef DIST_FILES_ENGINEDATA
|
||||
cp $(DIST_FILES_ENGINEDATA) $(AMIGAOSPATH)/extras/
|
||||
endif
|
||||
cat ${srcdir}/README | sed -f ${srcdir}/dists/amiga/convertRM.sed > README.conv
|
||||
# AmigaOS's shell is not happy with indented comments, thus don't do it.
|
||||
# AREXX seems to have problems when ${srcdir} is '.'. It will break with a
|
||||
# "Program not found" error. Therefore we copy the script to the cwd and
|
||||
# remove it again, once it has finished.
|
||||
cp ${srcdir}/dists/amiga/RM2AG.rx .
|
||||
rx RM2AG.rx README.conv
|
||||
cp README.guide $(AMIGAOSPATH)
|
||||
rm RM2AG.rx
|
||||
rm README.conv
|
||||
rm README.guide
|
||||
cp $(DIST_FILES_DOCS) $(AMIGAOSPATH)
|
||||
|
||||
# Special target to cross create an AmigaOS snapshot installation
|
||||
|
||||
@@ -27,9 +27,10 @@
|
||||
|
||||
#ifdef MACOSX
|
||||
|
||||
#include "backends/platform/sdl/macosx/macosx.h"
|
||||
#include "backends/audiocd/macosx/macosx-audiocd.h"
|
||||
#include "backends/mixer/doublebuffersdl/doublebuffersdl-mixer.h"
|
||||
#include "backends/platform/sdl/macosx/appmenu_osx.h"
|
||||
#include "backends/platform/sdl/macosx/macosx.h"
|
||||
#include "backends/updates/macosx/macosx-updates.h"
|
||||
#include "backends/taskbar/macosx/macosx-taskbar.h"
|
||||
|
||||
@@ -170,4 +171,8 @@ Common::String OSystem_MacOSX::getSystemLanguage() const {
|
||||
#endif // USE_DETECTLANG
|
||||
}
|
||||
|
||||
AudioCDManager *OSystem_MacOSX::createAudioCDManager() {
|
||||
return createMacOSXAudioCDManager();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -38,6 +38,11 @@ public:
|
||||
virtual void init();
|
||||
virtual void initBackend();
|
||||
virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);
|
||||
|
||||
protected:
|
||||
// Override createAudioCDManager() to get our Mac-specific
|
||||
// version.
|
||||
virtual AudioCDManager *createAudioCDManager();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#if defined(POSIX) && !defined(MACOSX) && !defined(SAMSUNGTV) && !defined(MAEMO) && !defined(WEBOS) && !defined(LINUXMOTO) && !defined(GPH_DEVICE) && !defined(GP2X) && !defined(DINGUX) && !defined(OPENPANDORA) && !defined(PLAYSTATION3)
|
||||
#if defined(POSIX) && !defined(MACOSX) && !defined(SAMSUNGTV) && !defined(MAEMO) && !defined(WEBOS) && !defined(LINUXMOTO) && !defined(GPH_DEVICE) && !defined(GP2X) && !defined(DINGUX) && !defined(OPENPANDORA) && !defined(PLAYSTATION3) && !defined(ANDROIDSDL)
|
||||
|
||||
#include "backends/platform/sdl/posix/posix.h"
|
||||
#include "backends/plugins/sdl/sdl-provider.h"
|
||||
|
||||
@@ -33,14 +33,18 @@
|
||||
#include "backends/platform/sdl/posix/posix.h"
|
||||
#include "backends/saves/posix/posix-saves.h"
|
||||
#include "backends/fs/posix/posix-fs-factory.h"
|
||||
#include "backends/fs/posix/posix-fs.h"
|
||||
#include "backends/taskbar/unity/unity-taskbar.h"
|
||||
|
||||
#ifdef USE_LINUXCD
|
||||
#include "backends/audiocd/linux/linux-audiocd.h"
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
OSystem_POSIX::OSystem_POSIX(Common::String baseConfigName)
|
||||
:
|
||||
_baseConfigName(baseConfigName) {
|
||||
@@ -82,11 +86,54 @@ bool OSystem_POSIX::hasFeature(Feature f) {
|
||||
Common::String OSystem_POSIX::getDefaultConfigFileName() {
|
||||
Common::String configFile;
|
||||
|
||||
// On POSIX type systems, by default we store the config file inside
|
||||
// to the HOME directory of the user.
|
||||
const char *home = getenv("HOME");
|
||||
if (home != NULL && (strlen(home) + 1 + _baseConfigName.size()) < MAXPATHLEN) {
|
||||
configFile = Common::String::format("%s/%s", home, _baseConfigName.c_str());
|
||||
Common::String prefix;
|
||||
#ifdef MACOSX
|
||||
prefix = getenv("HOME");
|
||||
#elif !defined(SAMSUNGTV)
|
||||
const char *envVar;
|
||||
// Our old configuration file path for POSIX systems was ~/.residualvmrc.
|
||||
// If that file exists, we still use it.
|
||||
envVar = getenv("HOME");
|
||||
if (envVar && *envVar) {
|
||||
configFile = envVar;
|
||||
configFile += '/';
|
||||
configFile += ".residualvmrc";
|
||||
|
||||
if (configFile.size() < MAXPATHLEN) {
|
||||
struct stat sb;
|
||||
if (stat(configFile.c_str(), &sb) == 0) {
|
||||
return configFile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// On POSIX systems we follow the XDG Base Directory Specification for
|
||||
// where to store files. The version we based our code upon can be found
|
||||
// over here: http://standards.freedesktop.org/basedir-spec/basedir-spec-0.8.html
|
||||
envVar = getenv("XDG_CONFIG_HOME");
|
||||
if (!envVar || !*envVar) {
|
||||
envVar = getenv("HOME");
|
||||
if (!envVar) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (Posix::assureDirectoryExists(".config", envVar)) {
|
||||
prefix = envVar;
|
||||
prefix += "/.config";
|
||||
}
|
||||
} else {
|
||||
prefix = envVar;
|
||||
}
|
||||
|
||||
if (!prefix.empty() && Posix::assureDirectoryExists("residualvm", prefix.c_str())) {
|
||||
prefix += "/residualvm";
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!prefix.empty() && (prefix.size() + 1 + _baseConfigName.size()) < MAXPATHLEN) {
|
||||
configFile = prefix;
|
||||
configFile += '/';
|
||||
configFile += _baseConfigName;
|
||||
} else {
|
||||
configFile = _baseConfigName;
|
||||
}
|
||||
@@ -99,58 +146,43 @@ Common::WriteStream *OSystem_POSIX::createLogFile() {
|
||||
// of a failure, we know that no log file is open.
|
||||
_logFilePath.clear();
|
||||
|
||||
const char *home = getenv("HOME");
|
||||
if (home == NULL)
|
||||
return 0;
|
||||
|
||||
Common::String logFile(home);
|
||||
const char *prefix = nullptr;
|
||||
Common::String logFile;
|
||||
#ifdef MACOSX
|
||||
logFile += "/Library";
|
||||
#else
|
||||
logFile += "/.residualvm";
|
||||
#endif
|
||||
#ifdef SAMSUNGTV
|
||||
logFile = "/mtd_ram";
|
||||
#endif
|
||||
|
||||
struct stat sb;
|
||||
|
||||
// Check whether the dir exists
|
||||
if (stat(logFile.c_str(), &sb) == -1) {
|
||||
// The dir does not exist, or stat failed for some other reason.
|
||||
if (errno != ENOENT)
|
||||
return 0;
|
||||
|
||||
// If the problem was that the path pointed to nothing, try
|
||||
// to create the dir.
|
||||
if (mkdir(logFile.c_str(), 0755) != 0)
|
||||
return 0;
|
||||
} else if (!S_ISDIR(sb.st_mode)) {
|
||||
// Path is no directory. Oops
|
||||
prefix = getenv("HOME");
|
||||
if (prefix == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef MACOSX
|
||||
logFile += "/Logs";
|
||||
logFile = "Library/Logs";
|
||||
#elif SAMSUNGTV
|
||||
prefix = nullptr;
|
||||
logFile = "/mtd_ram";
|
||||
#else
|
||||
logFile += "/logs";
|
||||
// On POSIX systems we follow the XDG Base Directory Specification for
|
||||
// where to store files. The version we based our code upon can be found
|
||||
// over here: http://standards.freedesktop.org/basedir-spec/basedir-spec-0.8.html
|
||||
prefix = getenv("XDG_CACHE_HOME");
|
||||
if (prefix == nullptr || !*prefix) {
|
||||
prefix = getenv("HOME");
|
||||
if (prefix == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
logFile = ".cache/";
|
||||
}
|
||||
|
||||
logFile += "residualvm/logs";
|
||||
#endif
|
||||
|
||||
// Check whether the dir exists
|
||||
if (stat(logFile.c_str(), &sb) == -1) {
|
||||
// The dir does not exist, or stat failed for some other reason.
|
||||
if (errno != ENOENT)
|
||||
return 0;
|
||||
|
||||
// If the problem was that the path pointed to nothing, try
|
||||
// to create the dir.
|
||||
if (mkdir(logFile.c_str(), 0755) != 0)
|
||||
return 0;
|
||||
} else if (!S_ISDIR(sb.st_mode)) {
|
||||
// Path is no directory. Oops
|
||||
if (!Posix::assureDirectoryExists(logFile, prefix)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (prefix) {
|
||||
logFile = Common::String::format("%s/%s", prefix, logFile.c_str());
|
||||
}
|
||||
|
||||
logFile += "/residualvm.log";
|
||||
|
||||
Common::FSNode file(logFile);
|
||||
@@ -212,4 +244,12 @@ bool OSystem_POSIX::displayLogFile() {
|
||||
}
|
||||
|
||||
|
||||
AudioCDManager *OSystem_POSIX::createAudioCDManager() {
|
||||
#ifdef USE_LINUXCD
|
||||
return createLinuxAudioCDManager();
|
||||
#else
|
||||
return OSystem_SDL::createAudioCDManager();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
class OSystem_POSIX : public OSystem_SDL {
|
||||
public:
|
||||
// Let the subclasses be able to change _baseConfigName in the constructor
|
||||
OSystem_POSIX(Common::String baseConfigName = ".residualvmrc");
|
||||
OSystem_POSIX(Common::String baseConfigName = "residualvm.ini");
|
||||
virtual ~OSystem_POSIX() {}
|
||||
|
||||
virtual bool hasFeature(Feature f);
|
||||
@@ -59,6 +59,8 @@ protected:
|
||||
virtual Common::String getDefaultConfigFileName();
|
||||
|
||||
virtual Common::WriteStream *createLogFile();
|
||||
|
||||
virtual AudioCDManager *createAudioCDManager();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -52,6 +52,21 @@ typedef struct { int FAKE; } FAKE_FILE;
|
||||
#define strncasecmp FAKE_strncasecmp
|
||||
#endif
|
||||
|
||||
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_exit)
|
||||
#undef exit
|
||||
#define exit FAKE_exit
|
||||
#endif
|
||||
|
||||
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_abort)
|
||||
#undef abort
|
||||
#define abort FAKE_abort
|
||||
#endif
|
||||
|
||||
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_system)
|
||||
#undef system
|
||||
#define system FAKE_system
|
||||
#endif
|
||||
|
||||
// HACK: SDL might include windows.h which defines its own ARRAYSIZE.
|
||||
// However, we want to use the version from common/util.h. Thus, we make sure
|
||||
// that we actually have this definition after including the SDL headers.
|
||||
@@ -129,7 +144,7 @@ typedef struct { int FAKE; } FAKE_FILE;
|
||||
#endif
|
||||
|
||||
// In a moment of brilliance Xlib.h included by SDL_syswm.h #defines the
|
||||
// following names. In a moment of mental breakdown, which occured upon
|
||||
// following names. In a moment of mental breakdown, which occurred upon
|
||||
// gazing at Xlib.h, LordHoto decided to undefine them to prevent havoc.
|
||||
#ifdef Status
|
||||
#undef Status
|
||||
@@ -163,6 +178,21 @@ typedef struct { int FAKE; } FAKE_FILE;
|
||||
#define strncasecmp FORBIDDEN_SYMBOL_REPLACEMENT
|
||||
#endif
|
||||
|
||||
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_exit)
|
||||
#undef exit
|
||||
#define exit(a) FORBIDDEN_SYMBOL_REPLACEMENT
|
||||
#endif
|
||||
|
||||
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_abort)
|
||||
#undef abort
|
||||
#define abort() FORBIDDEN_SYMBOL_REPLACEMENT
|
||||
#endif
|
||||
|
||||
#if !defined(FORBIDDEN_SYMBOL_ALLOW_ALL) && !defined(FORBIDDEN_SYMBOL_EXCEPTION_system)
|
||||
#undef system
|
||||
#define system(a) FORBIDDEN_SYMBOL_REPLACEMENT
|
||||
#endif
|
||||
|
||||
// SDL 2 has major API changes. We redefine constants which got renamed to
|
||||
// ease the transition. This is sometimes dangerous because the values changed
|
||||
// too!
|
||||
|
||||
@@ -49,9 +49,10 @@
|
||||
#include "backends/timer/sdl/sdl-timer.h"
|
||||
#include "backends/graphics/surfacesdl/surfacesdl-graphics.h"
|
||||
|
||||
#ifdef USE_OPENGL
|
||||
#ifdef USE_OPENGL
|
||||
#include "backends/graphics/openglsdl/openglsdl-graphics.h"
|
||||
#include "graphics/opengl/context.h"
|
||||
//#include "graphics/cursorman.h" // ResidualVM
|
||||
#include "graphics/opengl/context.h" // ResidualVM specific
|
||||
#endif
|
||||
|
||||
#include <time.h> // for getTimeAndDate()
|
||||
@@ -169,10 +170,12 @@ void OSystem_SDL::initBackend() {
|
||||
// is not active by this point.
|
||||
debug(1, "Using SDL Video Driver \"%s\"", sdlDriverName);
|
||||
|
||||
// ResidualVM specific code start
|
||||
detectDesktopResolution();
|
||||
#ifdef USE_OPENGL
|
||||
detectFramebufferSupport();
|
||||
#endif
|
||||
// ResidualVM specific code end
|
||||
|
||||
// Create the default event source, in case a custom backend
|
||||
// manager didn't provide one yet.
|
||||
@@ -203,15 +206,7 @@ void OSystem_SDL::initBackend() {
|
||||
_timerManager = new SdlTimerManager();
|
||||
#endif
|
||||
|
||||
if (_audiocdManager == 0) {
|
||||
// Audio CD support was removed with SDL 2.0
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
_audiocdManager = new DefaultAudioCDManager();
|
||||
#else
|
||||
_audiocdManager = new SdlAudioCDManager();
|
||||
#endif
|
||||
|
||||
}
|
||||
_audiocdManager = createAudioCDManager();
|
||||
|
||||
// Setup a custom program icon.
|
||||
_window->setupIcon();
|
||||
@@ -345,6 +340,7 @@ void OSystem_SDL::setWindowCaption(const char *caption) {
|
||||
_window->setWindowCaption(cap);
|
||||
}
|
||||
|
||||
// ResidualVM specific code
|
||||
void OSystem_SDL::setupScreen(uint screenW, uint screenH, bool fullscreen, bool accel3d) {
|
||||
#ifdef USE_OPENGL
|
||||
bool switchedManager = false;
|
||||
@@ -374,6 +370,7 @@ void OSystem_SDL::setupScreen(uint screenW, uint screenH, bool fullscreen, bool
|
||||
void OSystem_SDL::launcherInitSize(uint w, uint h) {
|
||||
setupScreen(w, h, false, false);
|
||||
}
|
||||
// End of ResidualVM specific code
|
||||
|
||||
void OSystem_SDL::quit() {
|
||||
delete this;
|
||||
@@ -531,6 +528,15 @@ Common::TimerManager *OSystem_SDL::getTimerManager() {
|
||||
#endif
|
||||
}
|
||||
|
||||
AudioCDManager *OSystem_SDL::createAudioCDManager() {
|
||||
// Audio CD support was removed with SDL 2.0
|
||||
#if SDL_VERSION_ATLEAST(2, 0, 0)
|
||||
return new DefaultAudioCDManager();
|
||||
#else
|
||||
return new SdlAudioCDManager();
|
||||
#endif
|
||||
}
|
||||
|
||||
// ResidualVM specific code
|
||||
bool OSystem_SDL::hasFeature(Feature f) {
|
||||
if (f == kFeatureSideTextures)
|
||||
|
||||
@@ -83,6 +83,7 @@ public:
|
||||
|
||||
// ResidualVM specific code
|
||||
virtual void setupScreen(uint screenW, uint screenH, bool fullscreen, bool accel3d) override;
|
||||
// ResidualVM specific code
|
||||
virtual void launcherInitSize(uint w, uint h) override;
|
||||
|
||||
protected:
|
||||
@@ -119,6 +120,11 @@ protected:
|
||||
*/
|
||||
virtual void initSDL();
|
||||
|
||||
/**
|
||||
* Create the audio CD manager
|
||||
*/
|
||||
virtual AudioCDManager *createAudioCDManager();
|
||||
|
||||
// Logging
|
||||
virtual Common::WriteStream *createLogFile() { return 0; }
|
||||
Backends::Log::Log *_logger;
|
||||
|
||||
@@ -44,7 +44,12 @@ int __stdcall WinMain(HINSTANCE /*hInst*/, HINSTANCE /*hPrevInst*/, LPSTR /*lpC
|
||||
SDL_SetModuleHandle(GetModuleHandle(NULL));
|
||||
#endif
|
||||
// HACK: __argc, __argv are broken and return zero when using mingwrt 4.0+ on MinGW
|
||||
#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64__)
|
||||
// HACK: MinGW-w64 based toolchains neither feature _argc nor _argv. The 32 bit
|
||||
// incarnation only defines __MINGW32__. This leads to build breakage due to
|
||||
// missing declarations. Luckily MinGW-w64 based toolchains define
|
||||
// __MINGW64_VERSION_foo macros inside _mingw.h, which is included from all
|
||||
// system headers. Thus we abuse that to detect them.
|
||||
#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
|
||||
return main(_argc, _argv);
|
||||
#else
|
||||
return main(__argc, __argv);
|
||||
|
||||
@@ -35,11 +35,13 @@
|
||||
#include "common/error.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
#include "backends/audiocd/win32/win32-audiocd.h"
|
||||
#include "backends/platform/sdl/win32/win32.h"
|
||||
#include "backends/platform/sdl/win32/win32-window.h"
|
||||
#include "backends/saves/windows/windows-saves.h"
|
||||
#include "backends/fs/windows/windows-fs-factory.h"
|
||||
#include "backends/taskbar/win32/win32-taskbar.h"
|
||||
#include "backends/updates/win32/win32-updates.h"
|
||||
|
||||
#include "common/memstream.h"
|
||||
|
||||
@@ -81,6 +83,11 @@ void OSystem_Win32::initBackend() {
|
||||
if (_savefileManager == 0)
|
||||
_savefileManager = new WindowsSaveFileManager();
|
||||
|
||||
#if defined(USE_SPARKLE)
|
||||
// Initialize updates manager
|
||||
_updateManager = new Win32UpdateManager();
|
||||
#endif
|
||||
|
||||
// Invoke parent implementation of this method
|
||||
OSystem_SDL::initBackend();
|
||||
}
|
||||
@@ -318,4 +325,8 @@ void OSystem_Win32::addSysArchivesToSearchSet(Common::SearchSet &s, int priority
|
||||
OSystem_SDL::addSysArchivesToSearchSet(s, priority);
|
||||
}
|
||||
|
||||
AudioCDManager *OSystem_Win32::createAudioCDManager() {
|
||||
return createWin32AudioCDManager();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -49,6 +49,10 @@ protected:
|
||||
|
||||
virtual Common::String getDefaultConfigFileName();
|
||||
virtual Common::WriteStream *createLogFile();
|
||||
|
||||
// Override createAudioCDManager() to get our Mac-specific
|
||||
// version.
|
||||
virtual AudioCDManager *createAudioCDManager();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
debug("Failed loading plugin '%s' (error code %d)", _filename.c_str(), (int32) GetLastError());
|
||||
return false;
|
||||
} else {
|
||||
debug(1, "Success loading plugin '%s', handle %08X", _filename.c_str(), (uint32) _dlHandle);
|
||||
debug(1, "Success loading plugin '%s', handle %p", _filename.c_str(), _dlHandle);
|
||||
}
|
||||
|
||||
return DynamicPlugin::loadPlugin();
|
||||
|
||||
@@ -60,22 +60,15 @@ void DefaultSaveFileManager::checkPath(const Common::FSNode &dir) {
|
||||
}
|
||||
|
||||
Common::StringArray DefaultSaveFileManager::listSavefiles(const Common::String &pattern) {
|
||||
Common::String savePathName = getSavePath();
|
||||
checkPath(Common::FSNode(savePathName));
|
||||
// Assure the savefile name cache is up-to-date.
|
||||
assureCached(getSavePath());
|
||||
if (getError().getCode() != Common::kNoError)
|
||||
return Common::StringArray();
|
||||
|
||||
// recreate FSNode since checkPath may have changed/created the directory
|
||||
Common::FSNode savePath(savePathName);
|
||||
|
||||
Common::FSDirectory dir(savePath);
|
||||
Common::ArchiveMemberList savefiles;
|
||||
Common::StringArray results;
|
||||
Common::String search(pattern);
|
||||
|
||||
if (dir.listMatchingMembers(savefiles, search) > 0) {
|
||||
for (Common::ArchiveMemberList::const_iterator file = savefiles.begin(); file != savefiles.end(); ++file) {
|
||||
results.push_back((*file)->getName());
|
||||
for (SaveFileCache::const_iterator file = _saveFileCache.begin(), end = _saveFileCache.end(); file != end; ++file) {
|
||||
if (file->_key.matchString(pattern, true)) {
|
||||
results.push_back(file->_key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,68 +76,81 @@ Common::StringArray DefaultSaveFileManager::listSavefiles(const Common::String &
|
||||
}
|
||||
|
||||
Common::InSaveFile *DefaultSaveFileManager::openForLoading(const Common::String &filename) {
|
||||
// Ensure that the savepath is valid. If not, generate an appropriate error.
|
||||
Common::String savePathName = getSavePath();
|
||||
checkPath(Common::FSNode(savePathName));
|
||||
// Assure the savefile name cache is up-to-date.
|
||||
assureCached(getSavePath());
|
||||
if (getError().getCode() != Common::kNoError)
|
||||
return 0;
|
||||
return nullptr;
|
||||
|
||||
// recreate FSNode since checkPath may have changed/created the directory
|
||||
Common::FSNode savePath(savePathName);
|
||||
|
||||
Common::FSNode file = savePath.getChild(filename);
|
||||
if (!file.exists())
|
||||
return 0;
|
||||
|
||||
// Open the file for reading
|
||||
Common::SeekableReadStream *sf = file.createReadStream();
|
||||
|
||||
return Common::wrapCompressedReadStream(sf);
|
||||
SaveFileCache::const_iterator file = _saveFileCache.find(filename);
|
||||
if (file == _saveFileCache.end()) {
|
||||
return nullptr;
|
||||
} else {
|
||||
// Open the file for loading.
|
||||
Common::SeekableReadStream *sf = file->_value.createReadStream();
|
||||
return Common::wrapCompressedReadStream(sf);
|
||||
}
|
||||
}
|
||||
|
||||
Common::OutSaveFile *DefaultSaveFileManager::openForSaving(const Common::String &filename, bool compress) {
|
||||
// Ensure that the savepath is valid. If not, generate an appropriate error.
|
||||
Common::String savePathName = getSavePath();
|
||||
checkPath(Common::FSNode(savePathName));
|
||||
// Assure the savefile name cache is up-to-date.
|
||||
const Common::String savePathName = getSavePath();
|
||||
assureCached(savePathName);
|
||||
if (getError().getCode() != Common::kNoError)
|
||||
return 0;
|
||||
return nullptr;
|
||||
|
||||
// recreate FSNode since checkPath may have changed/created the directory
|
||||
Common::FSNode savePath(savePathName);
|
||||
// Obtain node.
|
||||
SaveFileCache::const_iterator file = _saveFileCache.find(filename);
|
||||
Common::FSNode fileNode;
|
||||
|
||||
Common::FSNode file = savePath.getChild(filename);
|
||||
// If the file did not exist before, we add it to the cache.
|
||||
if (file == _saveFileCache.end()) {
|
||||
const Common::FSNode savePath(savePathName);
|
||||
fileNode = savePath.getChild(filename);
|
||||
} else {
|
||||
fileNode = file->_value;
|
||||
}
|
||||
|
||||
// Open the file for saving
|
||||
Common::WriteStream *sf = file.createWriteStream();
|
||||
// Open the file for saving.
|
||||
Common::WriteStream *const sf = fileNode.createWriteStream();
|
||||
Common::OutSaveFile *const result = compress ? Common::wrapCompressedWriteStream(sf) : sf;
|
||||
|
||||
return compress ? Common::wrapCompressedWriteStream(sf) : sf;
|
||||
// Add file to cache now that it exists.
|
||||
_saveFileCache[filename] = Common::FSNode(fileNode.getPath());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool DefaultSaveFileManager::removeSavefile(const Common::String &filename) {
|
||||
Common::String savePathName = getSavePath();
|
||||
checkPath(Common::FSNode(savePathName));
|
||||
// Assure the savefile name cache is up-to-date.
|
||||
assureCached(getSavePath());
|
||||
if (getError().getCode() != Common::kNoError)
|
||||
return false;
|
||||
|
||||
// recreate FSNode since checkPath may have changed/created the directory
|
||||
Common::FSNode savePath(savePathName);
|
||||
|
||||
Common::FSNode file = savePath.getChild(filename);
|
||||
|
||||
// FIXME: remove does not exist on all systems. If your port fails to
|
||||
// compile because of this, please let us know (scummvm-devel or Fingolfin).
|
||||
// There is a nicely portable workaround, too: Make this method overloadable.
|
||||
if (remove(file.getPath().c_str()) != 0) {
|
||||
#ifndef _WIN32_WCE
|
||||
if (errno == EACCES)
|
||||
setError(Common::kWritePermissionDenied, "Search or write permission denied: "+file.getName());
|
||||
|
||||
if (errno == ENOENT)
|
||||
setError(Common::kPathDoesNotExist, "removeSavefile: '"+file.getName()+"' does not exist or path is invalid");
|
||||
#endif
|
||||
// Obtain node if exists.
|
||||
SaveFileCache::const_iterator file = _saveFileCache.find(filename);
|
||||
if (file == _saveFileCache.end()) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
const Common::FSNode fileNode = file->_value;
|
||||
// Remove from cache, this invalidates the 'file' iterator.
|
||||
_saveFileCache.erase(file);
|
||||
file = _saveFileCache.end();
|
||||
|
||||
// FIXME: remove does not exist on all systems. If your port fails to
|
||||
// compile because of this, please let us know (scummvm-devel).
|
||||
// There is a nicely portable workaround, too: Make this method overloadable.
|
||||
if (remove(fileNode.getPath().c_str()) != 0) {
|
||||
#ifndef _WIN32_WCE
|
||||
if (errno == EACCES)
|
||||
setError(Common::kWritePermissionDenied, "Search or write permission denied: "+fileNode.getName());
|
||||
|
||||
if (errno == ENOENT)
|
||||
setError(Common::kPathDoesNotExist, "removeSavefile: '"+fileNode.getName()+"' does not exist or path is invalid");
|
||||
#endif
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,4 +177,43 @@ Common::String DefaultSaveFileManager::getSavePath() const {
|
||||
return dir;
|
||||
}
|
||||
|
||||
void DefaultSaveFileManager::assureCached(const Common::String &savePathName) {
|
||||
// Check that path exists and is usable.
|
||||
checkPath(Common::FSNode(savePathName));
|
||||
|
||||
if (_cachedDirectory == savePathName) {
|
||||
return;
|
||||
}
|
||||
|
||||
_saveFileCache.clear();
|
||||
_cachedDirectory.clear();
|
||||
|
||||
if (getError().getCode() != Common::kNoError) {
|
||||
warning("DefaultSaveFileManager::assureCached: Can not cache path '%s': '%s'", savePathName.c_str(), getErrorDesc().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// FSNode can cache its members, thus create it after checkPath to reflect
|
||||
// actual file system state.
|
||||
const Common::FSNode savePath(savePathName);
|
||||
|
||||
Common::FSList children;
|
||||
if (!savePath.getChildren(children, Common::FSNode::kListFilesOnly)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Build the savefile name cache.
|
||||
for (Common::FSList::const_iterator file = children.begin(), end = children.end(); file != end; ++file) {
|
||||
if (_saveFileCache.contains(file->getName())) {
|
||||
warning("DefaultSaveFileManager::assureCached: Name clash when building cache, ignoring file '%s'", file->getName().c_str());
|
||||
} else {
|
||||
_saveFileCache[file->getName()] = *file;
|
||||
}
|
||||
}
|
||||
|
||||
// Only now store that we cached 'savePathName' to indicate we successfully
|
||||
// cached the directory.
|
||||
_cachedDirectory = savePathName;
|
||||
}
|
||||
|
||||
#endif // !defined(DISABLE_DEFAULT_SAVEFILEMANAGER)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "common/savefile.h"
|
||||
#include "common/str.h"
|
||||
#include "common/fs.h"
|
||||
#include "common/hashmap.h"
|
||||
|
||||
/**
|
||||
* Provides a default savefile manager implementation for common platforms.
|
||||
@@ -54,6 +55,30 @@ protected:
|
||||
* Sets the internal error and error message accordingly.
|
||||
*/
|
||||
virtual void checkPath(const Common::FSNode &dir);
|
||||
|
||||
/**
|
||||
* Assure that the given save path is cached.
|
||||
*
|
||||
* @param savePathName String representation of save path to cache.
|
||||
*/
|
||||
void assureCached(const Common::String &savePathName);
|
||||
|
||||
typedef Common::HashMap<Common::String, Common::FSNode, Common::IgnoreCase_Hash, Common::IgnoreCase_EqualTo> SaveFileCache;
|
||||
|
||||
/**
|
||||
* Cache of all the save files in the currently cached directory.
|
||||
*
|
||||
* Modify with caution because we only re-cache when the save path changed!
|
||||
* This needs to be updated inside at least openForSaving and
|
||||
* removeSavefile.
|
||||
*/
|
||||
SaveFileCache _saveFileCache;
|
||||
|
||||
private:
|
||||
/**
|
||||
* The currently cached directory.
|
||||
*/
|
||||
Common::String _cachedDirectory;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,16 +21,19 @@
|
||||
*/
|
||||
|
||||
|
||||
// Enable getenv, mkdir and time.h stuff
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_getenv
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir
|
||||
// Re-enable some forbidden symbols to avoid clashes with stat.h and unistd.h.
|
||||
// Also with clock() in sys/time.h in some Mac OS X SDKs.
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_time_h //On IRIX, sys/stat.h includes sys/time.h
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_unistd_h
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_mkdir
|
||||
#define FORBIDDEN_SYMBOL_EXCEPTION_getenv
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#if defined(POSIX) && !defined(DISABLE_DEFAULT_SAVEFILEMANAGER)
|
||||
|
||||
#include "backends/saves/posix/posix-saves.h"
|
||||
#include "backends/fs/posix/posix-fs.h"
|
||||
|
||||
#include "common/config-manager.h"
|
||||
#include "common/savefile.h"
|
||||
@@ -41,26 +44,70 @@
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
#ifdef MACOSX
|
||||
#define DEFAULT_SAVE_PATH "Documents/ResidualVM Savegames"
|
||||
#else
|
||||
#define DEFAULT_SAVE_PATH ".residualvm"
|
||||
#endif
|
||||
|
||||
POSIXSaveFileManager::POSIXSaveFileManager() {
|
||||
// Register default savepath based on HOME
|
||||
// Register default savepath.
|
||||
#if defined(SAMSUNGTV)
|
||||
ConfMan.registerDefault("savepath", "/mtd_wiselink/residualvm savegames");
|
||||
#else
|
||||
Common::String savePath;
|
||||
|
||||
#if defined(MACOSX)
|
||||
const char *home = getenv("HOME");
|
||||
if (home && *home && strlen(home) < MAXPATHLEN) {
|
||||
savePath = home;
|
||||
savePath += "/" DEFAULT_SAVE_PATH;
|
||||
savePath += "/Documents/ResidualVM Savegames";
|
||||
|
||||
ConfMan.registerDefault("savepath", savePath);
|
||||
}
|
||||
|
||||
#else
|
||||
const char *envVar;
|
||||
|
||||
// Previously we placed our default savepath in HOME. If the directory
|
||||
// still exists, we will use it for backwards compatability.
|
||||
envVar = getenv("HOME");
|
||||
if (envVar && *envVar) {
|
||||
savePath = envVar;
|
||||
savePath += "/.residualvm";
|
||||
|
||||
struct stat sb;
|
||||
if (stat(savePath.c_str(), &sb) != 0 || !S_ISDIR(sb.st_mode)) {
|
||||
savePath.clear();
|
||||
}
|
||||
}
|
||||
|
||||
if (savePath.empty()) {
|
||||
Common::String prefix;
|
||||
|
||||
// On POSIX systems we follow the XDG Base Directory Specification for
|
||||
// where to store files. The version we based our code upon can be found
|
||||
// over here: http://standards.freedesktop.org/basedir-spec/basedir-spec-0.8.html
|
||||
envVar = getenv("XDG_DATA_HOME");
|
||||
if (!envVar || !*envVar) {
|
||||
envVar = getenv("HOME");
|
||||
if (envVar && *envVar) {
|
||||
prefix = envVar;
|
||||
savePath = ".local/share/";
|
||||
}
|
||||
} else {
|
||||
prefix = envVar;
|
||||
}
|
||||
|
||||
// Our default save path is '$XDG_DATA_HOME/residualvm/saves'
|
||||
savePath += "residualvm/saves";
|
||||
|
||||
if (!Posix::assureDirectoryExists(savePath, prefix.c_str())) {
|
||||
savePath.clear();
|
||||
} else {
|
||||
savePath = prefix + '/' + savePath;
|
||||
}
|
||||
}
|
||||
|
||||
if (!savePath.empty() && savePath.size() < MAXPATHLEN) {
|
||||
ConfMan.registerDefault("savepath", savePath);
|
||||
}
|
||||
#endif
|
||||
|
||||
// The user can override the savepath with the SCUMMVM_SAVEPATH
|
||||
// environment variable. This is weaker than a --savepath on the
|
||||
// command line, but overrides the default savepath.
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
|
||||
@interface ScummVMDockTilePlugIn : NSObject <NSDockTilePlugIn> {
|
||||
NSMenu *recentGamesMenu;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface StartGameMenuItem : NSMenuItem {
|
||||
NSString *game;
|
||||
}
|
||||
- (IBAction) startGame;
|
||||
- (NSMenuItem*)initWithGame:(NSString *)gameId description:(NSString*)desc icon:(NSString*)iconFile;
|
||||
@end
|
||||
|
||||
@implementation ScummVMDockTilePlugIn
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
recentGamesMenu = nil;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[recentGamesMenu release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
- (void)setDockTile:(NSDockTile *)dockTile {
|
||||
}
|
||||
|
||||
- (NSMenu*)dockMenu {
|
||||
// Get the list or recent games
|
||||
CFPreferencesAppSynchronize(CFSTR("org.residualvm.residaulvm"));
|
||||
NSArray *array = CFPreferencesCopyAppValue(CFSTR("recentGames"), CFSTR("org.residualvm.residualvm"));
|
||||
if (array == nil)
|
||||
return nil;
|
||||
|
||||
// Create the menu
|
||||
if (recentGamesMenu == nil)
|
||||
recentGamesMenu = [[NSMenu alloc] init];
|
||||
else
|
||||
[recentGamesMenu removeAllItems];
|
||||
|
||||
NSEnumerator *enumerator = [array objectEnumerator];
|
||||
NSDictionary *recentGame;
|
||||
while (recentGame = [enumerator nextObject]) {
|
||||
NSString *gameId = [recentGame valueForKey:@"game"];
|
||||
NSString *desc = [recentGame valueForKey:@"description"];
|
||||
NSString *iconFile = [recentGame valueForKey:@"icon"];
|
||||
|
||||
StartGameMenuItem *menuItem = [[StartGameMenuItem alloc] initWithGame:gameId description:desc icon:iconFile];
|
||||
[recentGamesMenu addItem:menuItem];
|
||||
[menuItem release];
|
||||
}
|
||||
|
||||
return recentGamesMenu;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation StartGameMenuItem
|
||||
|
||||
- (NSMenuItem*)initWithGame:(NSString *)gameId description:(NSString*)desc icon:(NSString*)iconFile {
|
||||
self = [super initWithTitle:(desc == nil ? gameId : desc) action:@selector(startGame) keyEquivalent:@""];
|
||||
[self setTarget:self];
|
||||
|
||||
if (iconFile != nil) {
|
||||
NSImage *image = [[NSImage alloc] initWithContentsOfFile:iconFile];
|
||||
[self setImage:image];
|
||||
[image release];
|
||||
}
|
||||
|
||||
game = gameId;
|
||||
[game retain];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[game release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (IBAction) startGame {
|
||||
NSLog(@"Starting Game %@...", game);
|
||||
|
||||
NSString *scummVMPath = [[NSWorkspace sharedWorkspace] absolutePathForAppBundleWithIdentifier:@"org.residualvm.residualvm"];
|
||||
if (scummVMPath == nil) {
|
||||
NSLog(@"Cannot find ResidualVM.app!");
|
||||
return;
|
||||
}
|
||||
// Start ScummVM.app with the game ID as argument
|
||||
NSURL *url = [NSURL fileURLWithPath:scummVMPath];
|
||||
NSMutableDictionary *args = [[NSMutableDictionary alloc] init];
|
||||
[args setObject:[NSArray arrayWithObject:game] forKey:NSWorkspaceLaunchConfigurationArguments];
|
||||
[[NSWorkspace sharedWorkspace] launchApplicationAtURL:url options:NSWorkspaceLaunchDefault configuration:args error:nil];
|
||||
[args release];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -37,6 +37,7 @@ public:
|
||||
virtual void setProgressValue(int completed, int total);
|
||||
virtual void setProgressState(TaskbarProgressState state);
|
||||
virtual void setCount(int count);
|
||||
virtual void addRecent(const Common::String &name, const Common::String &description);
|
||||
virtual void notifyError();
|
||||
virtual void clearError();
|
||||
|
||||
|
||||
@@ -29,9 +29,6 @@
|
||||
// NSDockTile was introduced with Mac OS X 10.5.
|
||||
// Try provide backward compatibility by avoiding NSDockTile symbols.
|
||||
|
||||
// TODO: Implement recent list, maybe as a custom menu on dock tile when app is not running
|
||||
// See Dock Tile plug-in at https://developer.apple.com/library/mac/documentation/Carbon/Conceptual/customizing_docktile/CreatingaDockTilePlug-in/CreatingaDockTilePlug-in.html
|
||||
|
||||
#include "backends/taskbar/macosx/macosx-taskbar.h"
|
||||
#include "common/config-manager.h"
|
||||
#include "common/file.h"
|
||||
@@ -39,6 +36,9 @@
|
||||
#include <AppKit/NSApplication.h>
|
||||
#include <AppKit/NSImage.h>
|
||||
#include <Foundation/NSString.h>
|
||||
#include <Foundation/NSDictionary.h>
|
||||
#include <Foundation/NSArray.h>
|
||||
#include <Foundation/NSUserDefaults.h>
|
||||
#include <AppKit/NSImageView.h>
|
||||
#include <AppKit/NSColor.h>
|
||||
#include <AppKit/NSBezierPath.h>
|
||||
@@ -120,7 +120,7 @@ void MacOSXTaskbarManager::setOverlayIcon(const Common::String &name, const Comm
|
||||
initOverlayIconView();
|
||||
|
||||
CFStringRef imageFile = CFStringCreateWithCString(0, path.c_str(), kCFStringEncodingASCII);
|
||||
NSImage* image = [[NSImage alloc] initWithContentsOfFile:(NSString *)imageFile];
|
||||
NSImage *image = [[NSImage alloc] initWithContentsOfFile:(NSString *)imageFile];
|
||||
[_overlayIconView setImage:image];
|
||||
[image release];
|
||||
CFRelease(imageFile);
|
||||
@@ -234,5 +234,64 @@ return (path); \
|
||||
return "";
|
||||
}
|
||||
|
||||
void MacOSXTaskbarManager::addRecent(const Common::String &name, const Common::String &description) {
|
||||
//warning("[MacOSXTaskbarManager::addRecent] Adding recent list entry: %s (%s)", name.c_str(), description.c_str());
|
||||
|
||||
if (_dockTile == nil)
|
||||
return;
|
||||
|
||||
// Store the game, description and icon in user preferences.
|
||||
// The NSDockTilePlugin will retrieve them there to list them in the dock tile menu.
|
||||
|
||||
CFStringRef gameName = CFStringCreateWithCString(0, name.c_str(), kCFStringEncodingASCII);
|
||||
CFStringRef desc = CFStringCreateWithCString(0, description.c_str(), kCFStringEncodingASCII);
|
||||
|
||||
// First build the dictionary for this game.
|
||||
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
|
||||
[dict setObject:(NSString *)gameName forKey:@"game"];
|
||||
[dict setObject:(NSString *)desc forKey:@"description"];
|
||||
|
||||
// Icon
|
||||
Common::String iconPath = getIconPath(name);
|
||||
if (!iconPath.empty()) {
|
||||
CFStringRef icon = CFStringCreateWithCString(0, iconPath.c_str(), kCFStringEncodingASCII);
|
||||
[dict setObject:(NSString *)icon forKey:@"icon"];
|
||||
CFRelease(icon);
|
||||
}
|
||||
|
||||
// Retrieve the current list of recent items and update it.
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSArray *oldArray = [defaults arrayForKey:@"recentGames"];
|
||||
if (oldArray == nil) {
|
||||
[defaults setObject:[NSArray arrayWithObject:dict] forKey:@"recentGames"];
|
||||
} else {
|
||||
NSMutableArray *newArray = [[NSMutableArray alloc] initWithArray:oldArray];
|
||||
// Insert the new game at the start
|
||||
[newArray insertObject:dict atIndex:0];
|
||||
// If the game was already present in the array, remove it
|
||||
for (unsigned int i = 1 ; i < [newArray count] ; ++i) {
|
||||
NSDictionary *oldDict = [newArray objectAtIndex:i];
|
||||
if (oldDict == nil)
|
||||
continue;
|
||||
NSString *oldGame = [oldDict valueForKey:@"game"];
|
||||
if (oldGame != nil && [oldGame isEqualToString:(NSString*)gameName]) {
|
||||
[newArray removeObjectAtIndex:i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
// And make sure we limit the size of the array to 5 games
|
||||
if ([newArray count] > 5)
|
||||
[newArray removeLastObject];
|
||||
[defaults setObject:newArray forKey:@"recentGames"];
|
||||
[newArray release];
|
||||
}
|
||||
|
||||
// Finally release the dictionary
|
||||
[dict release];
|
||||
CFRelease(gameName);
|
||||
CFRelease(desc);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,8 +28,22 @@
|
||||
|
||||
#if defined(WIN32) && defined(USE_TASKBAR)
|
||||
|
||||
// HACK: To get __MINGW64_VERSION_foo defines we need to manually include
|
||||
// _mingw.h in this file because we do not include any system headers at this
|
||||
// point on purpose. The defines are required to detect whether this is a
|
||||
// classic MinGW toolchain or a MinGW-w64 based one.
|
||||
#if defined(__MINGW32__)
|
||||
#include <_mingw.h>
|
||||
#endif
|
||||
|
||||
// Needed for taskbar functions
|
||||
#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64__)
|
||||
// HACK: MinGW-w64 based toolchains include the symbols we require in their
|
||||
// headers. The 32 bit incarnation only defines __MINGW32__. This leads to
|
||||
// build breakage due to clashes with our compat header. Luckily MinGW-w64
|
||||
// based toolchains define __MINGW64_VERSION_foo macros inside _mingw.h,
|
||||
// which is included from all system headers. Thus we abuse that to detect
|
||||
// them.
|
||||
#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
|
||||
#include "backends/taskbar/win32/mingw-compat.h"
|
||||
#else
|
||||
// We use functionality introduced with Win7 in this file.
|
||||
@@ -71,7 +85,7 @@ const PROPERTYKEY PKEY_Title = { /* fmtid = */ { 0xF29F85E0, 0x4FF9, 0x1068, { 0
|
||||
|
||||
Win32TaskbarManager::Win32TaskbarManager(SdlWindow *window) : _window(window), _taskbar(NULL), _count(0), _icon(NULL) {
|
||||
// Do nothing if not running on Windows 7 or later
|
||||
if (!isWin7OrLater())
|
||||
if (!confirmWindowsVersion(10, 0) && !confirmWindowsVersion(6, 1))
|
||||
return;
|
||||
|
||||
CoInitialize(NULL);
|
||||
@@ -386,14 +400,14 @@ BOOL VerifyVersionInfoFunc(LPOSVERSIONINFOEXA lpVersionInformation, DWORD dwType
|
||||
return verifyVersionInfo(lpVersionInformation, dwTypeMask, dwlConditionMask);
|
||||
}
|
||||
|
||||
bool Win32TaskbarManager::isWin7OrLater() {
|
||||
bool Win32TaskbarManager::confirmWindowsVersion(uint majorVersion, uint minorVersion) {
|
||||
OSVERSIONINFOEX versionInfo;
|
||||
DWORDLONG conditionMask = 0;
|
||||
|
||||
ZeroMemory(&versionInfo, sizeof(OSVERSIONINFOEX));
|
||||
versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
|
||||
versionInfo.dwMajorVersion = 6;
|
||||
versionInfo.dwMinorVersion = 1;
|
||||
versionInfo.dwMajorVersion = majorVersion;
|
||||
versionInfo.dwMinorVersion = minorVersion;
|
||||
|
||||
conditionMask = VerSetConditionMaskFunc(conditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL);
|
||||
conditionMask = VerSetConditionMaskFunc(conditionMask, VER_MINORVERSION, VER_GREATER_EQUAL);
|
||||
|
||||
@@ -64,7 +64,7 @@ private:
|
||||
Common::String getIconPath(Common::String target);
|
||||
|
||||
// Helper functions
|
||||
bool isWin7OrLater();
|
||||
bool confirmWindowsVersion(uint majorVersion, uint minorVersion);
|
||||
LPWSTR ansiToUnicode(const char *s);
|
||||
HWND getHwnd();
|
||||
};
|
||||
|
||||
@@ -39,8 +39,10 @@ public:
|
||||
virtual void setAutomaticallyChecksForUpdates(UpdateState state);
|
||||
virtual UpdateState getAutomaticallyChecksForUpdates();
|
||||
|
||||
virtual void setUpdateCheckInterval(UpdateInterval interval);
|
||||
virtual UpdateInterval getUpdateCheckInterval();
|
||||
virtual void setUpdateCheckInterval(int interval);
|
||||
virtual int getUpdateCheckInterval();
|
||||
|
||||
virtual bool getLastUpdateCheckTimeAndDate(TimeDate &t);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -23,14 +23,18 @@
|
||||
// Disable symbol overrides so that we can use system headers.
|
||||
#define FORBIDDEN_SYMBOL_ALLOW_ALL
|
||||
|
||||
#include "common/system.h"
|
||||
#include "backends/updates/macosx/macosx-updates.h"
|
||||
|
||||
#ifdef USE_SPARKLE
|
||||
#include "common/translation.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include <Sparkle/Sparkle.h>
|
||||
|
||||
#include <AvailabilityMacros.h>
|
||||
|
||||
SUUpdater *sparkleUpdater;
|
||||
|
||||
/**
|
||||
@@ -45,14 +49,22 @@ SUUpdater *sparkleUpdater;
|
||||
*
|
||||
*/
|
||||
MacOSXUpdateManager::MacOSXUpdateManager() {
|
||||
NSBundle* mainBundle = [NSBundle mainBundle];
|
||||
|
||||
NSString *version = [mainBundle objectForInfoDictionaryKey:(__bridge NSString *)kCFBundleVersionKey];
|
||||
if (!version || [version isEqualToString:@""]) {
|
||||
warning("Running not in bundle, skipping Sparkle initialization");
|
||||
|
||||
sparkleUpdater = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
NSMenuItem *menuItem = [[NSApp mainMenu] itemAtIndex:0];
|
||||
NSMenu *applicationMenu = [menuItem submenu];
|
||||
|
||||
// Init Sparkle
|
||||
sparkleUpdater = [SUUpdater sharedUpdater];
|
||||
|
||||
NSBundle* mainBundle = [NSBundle mainBundle];
|
||||
|
||||
NSString* feedbackURL = [mainBundle objectForInfoDictionaryKey:@"SUFeedURL"];
|
||||
|
||||
// Set appcast URL
|
||||
@@ -74,11 +86,13 @@ MacOSXUpdateManager::MacOSXUpdateManager() {
|
||||
// Finally give up our references to the objects
|
||||
[menuItem release];
|
||||
|
||||
// Enable automatic update checking once a day (alternatively use
|
||||
// checkForUpdates() here to check for updates on every startup)
|
||||
// TODO: Should be removed when an update settings gui is implemented
|
||||
setAutomaticallyChecksForUpdates(kUpdateStateEnabled);
|
||||
setUpdateCheckInterval(kUpdateIntervalOneDay);
|
||||
if (!ConfMan.hasKey("updates_check")
|
||||
|| ConfMan.getInt("updates_check") == Common::UpdateManager::kUpdateIntervalNotSupported) {
|
||||
setAutomaticallyChecksForUpdates(kUpdateStateDisabled);
|
||||
} else {
|
||||
setAutomaticallyChecksForUpdates(kUpdateStateEnabled);
|
||||
setUpdateCheckInterval(normalizeInterval(ConfMan.getInt("updates_check")));
|
||||
}
|
||||
}
|
||||
|
||||
MacOSXUpdateManager::~MacOSXUpdateManager() {
|
||||
@@ -86,6 +100,9 @@ MacOSXUpdateManager::~MacOSXUpdateManager() {
|
||||
}
|
||||
|
||||
void MacOSXUpdateManager::checkForUpdates() {
|
||||
if (sparkleUpdater == nullptr)
|
||||
return;
|
||||
|
||||
[sparkleUpdater checkForUpdatesInBackground];
|
||||
}
|
||||
|
||||
@@ -93,24 +110,38 @@ void MacOSXUpdateManager::setAutomaticallyChecksForUpdates(UpdateManager::Update
|
||||
if (state == kUpdateStateNotSupported)
|
||||
return;
|
||||
|
||||
if (sparkleUpdater == nullptr)
|
||||
return;
|
||||
|
||||
[sparkleUpdater setAutomaticallyChecksForUpdates:(state == kUpdateStateEnabled ? YES : NO)];
|
||||
}
|
||||
|
||||
Common::UpdateManager::UpdateState MacOSXUpdateManager::getAutomaticallyChecksForUpdates() {
|
||||
if (sparkleUpdater == nullptr)
|
||||
return kUpdateStateDisabled;
|
||||
|
||||
if ([sparkleUpdater automaticallyChecksForUpdates])
|
||||
return kUpdateStateEnabled;
|
||||
else
|
||||
return kUpdateStateDisabled;
|
||||
}
|
||||
|
||||
void MacOSXUpdateManager::setUpdateCheckInterval(UpdateInterval interval) {
|
||||
void MacOSXUpdateManager::setUpdateCheckInterval(int interval) {
|
||||
if (sparkleUpdater == nullptr)
|
||||
return;
|
||||
|
||||
if (interval == kUpdateIntervalNotSupported)
|
||||
return;
|
||||
|
||||
interval = normalizeInterval(interval);
|
||||
|
||||
[sparkleUpdater setUpdateCheckInterval:(NSTimeInterval)interval];
|
||||
}
|
||||
|
||||
Common::UpdateManager::UpdateInterval MacOSXUpdateManager::getUpdateCheckInterval() {
|
||||
int MacOSXUpdateManager::getUpdateCheckInterval() {
|
||||
if (sparkleUpdater == nullptr)
|
||||
return kUpdateIntervalOneDay;
|
||||
|
||||
// This is kind of a hack but necessary, as the value stored by Sparkle
|
||||
// might have been changed outside of ScummVM (in which case we return the
|
||||
// default interval of one day)
|
||||
@@ -128,4 +159,30 @@ Common::UpdateManager::UpdateInterval MacOSXUpdateManager::getUpdateCheckInterva
|
||||
}
|
||||
}
|
||||
|
||||
bool MacOSXUpdateManager::getLastUpdateCheckTimeAndDate(TimeDate &t) {
|
||||
if (sparkleUpdater == nullptr)
|
||||
return false;
|
||||
|
||||
NSDate *date = [sparkleUpdater lastUpdateCheckDate];
|
||||
#ifdef MAC_OS_X_VERSION_10_10
|
||||
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
|
||||
NSDateComponents *components = [gregorian components:(NSCalendarUnitDay | NSCalendarUnitWeekday) fromDate:date];
|
||||
#else
|
||||
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
|
||||
NSDateComponents *components = [gregorian components:(NSDayCalendarUnit | NSWeekdayCalendarUnit) fromDate:date];
|
||||
#endif
|
||||
|
||||
t.tm_wday = [components weekday];
|
||||
t.tm_year = [components year];
|
||||
t.tm_mon = [components month];
|
||||
t.tm_mday = [components day];
|
||||
t.tm_hour = [components hour];
|
||||
t.tm_min = [components minute];
|
||||
t.tm_sec = [components second];
|
||||
|
||||
[gregorian release];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
// Disable symbol overrides so that we can use system headers.
|
||||
#define FORBIDDEN_SYMBOL_ALLOW_ALL
|
||||
|
||||
#include "common/system.h"
|
||||
#include "backends/updates/win32/win32-updates.h"
|
||||
|
||||
#ifdef USE_SPARKLE
|
||||
#include "common/translation.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <winsparkle.h>
|
||||
|
||||
/**
|
||||
* Sparkle is a software update framework for Mac OS X which uses appcasts for
|
||||
* release information. Appcasts are RSS-like XML feeds which contain information
|
||||
* about the most current version at the time. If a new version is available, the
|
||||
* user is presented the release-notes/changes/fixes and is asked if he wants to
|
||||
* update, and if yes the Sparkle framework downloads a signed update package
|
||||
* from the server and automatically installs and restarts the software.
|
||||
* More detailed information is available at the following address:
|
||||
* http://sparkle.andymatuschak.org/
|
||||
*
|
||||
* WinSparkle is a heavily (to the point of being its almost-port) inspired by the
|
||||
* Sparkle framework originally by Andy Matuschak that became the de facto standard
|
||||
* for software updates on OS X.
|
||||
* More detailed information is available at the following address:
|
||||
* https://winsparkle.org/
|
||||
*
|
||||
*/
|
||||
Win32UpdateManager::Win32UpdateManager() {
|
||||
const char *appcastUrl = "https://www.residualvm.org/appcasts/macosx/release.xml";
|
||||
|
||||
win_sparkle_set_appcast_url(appcastUrl);
|
||||
win_sparkle_init();
|
||||
|
||||
if (!ConfMan.hasKey("updates_check")
|
||||
|| ConfMan.getInt("updates_check") == Common::UpdateManager::kUpdateIntervalNotSupported) {
|
||||
setAutomaticallyChecksForUpdates(kUpdateStateDisabled);
|
||||
} else {
|
||||
setAutomaticallyChecksForUpdates(kUpdateStateEnabled);
|
||||
setUpdateCheckInterval(normalizeInterval(ConfMan.getInt("updates_check")));
|
||||
}
|
||||
}
|
||||
|
||||
Win32UpdateManager::~Win32UpdateManager() {
|
||||
win_sparkle_cleanup();
|
||||
}
|
||||
|
||||
void Win32UpdateManager::checkForUpdates() {
|
||||
win_sparkle_check_update_with_ui();
|
||||
}
|
||||
|
||||
void Win32UpdateManager::setAutomaticallyChecksForUpdates(UpdateManager::UpdateState state) {
|
||||
if (state == kUpdateStateNotSupported)
|
||||
return;
|
||||
|
||||
win_sparkle_set_automatic_check_for_updates(state == kUpdateStateEnabled ? 1 : 0);
|
||||
}
|
||||
|
||||
Common::UpdateManager::UpdateState Win32UpdateManager::getAutomaticallyChecksForUpdates() {
|
||||
if (win_sparkle_get_automatic_check_for_updates() == 1)
|
||||
return kUpdateStateEnabled;
|
||||
else
|
||||
return kUpdateStateDisabled;
|
||||
}
|
||||
|
||||
void Win32UpdateManager::setUpdateCheckInterval(int interval) {
|
||||
if (interval == kUpdateIntervalNotSupported)
|
||||
return;
|
||||
|
||||
interval = normalizeInterval(interval);
|
||||
|
||||
win_sparkle_set_update_check_interval(interval);
|
||||
}
|
||||
|
||||
int Win32UpdateManager::getUpdateCheckInterval() {
|
||||
// This is kind of a hack but necessary, as the value stored by Sparkle
|
||||
// might have been changed outside of ScummVM (in which case we return the
|
||||
// default interval of one day)
|
||||
|
||||
int updateInterval = win_sparkle_get_update_check_interval();
|
||||
switch (updateInterval) {
|
||||
case kUpdateIntervalOneDay:
|
||||
case kUpdateIntervalOneWeek:
|
||||
case kUpdateIntervalOneMonth:
|
||||
return updateInterval;
|
||||
|
||||
default:
|
||||
// Return the default value (one day)
|
||||
return kUpdateIntervalOneDay;
|
||||
}
|
||||
}
|
||||
|
||||
bool Win32UpdateManager::getLastUpdateCheckTimeAndDate(TimeDate &t) {
|
||||
time_t updateTime = win_sparkle_get_last_check_time();
|
||||
tm *ut = localtime(&updateTime);
|
||||
|
||||
t.tm_wday = ut->tm_wday;
|
||||
t.tm_year = ut->tm_year;
|
||||
t.tm_mon = ut->tm_mon;
|
||||
t.tm_mday = ut->tm_mday;
|
||||
t.tm_hour = ut->tm_hour;
|
||||
t.tm_min = ut->tm_min;
|
||||
t.tm_sec = ut->tm_sec;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_UPDATES_WIN32_H
|
||||
#define BACKENDS_UPDATES_WIN32_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
#if defined(WIN32) && defined(USE_SPARKLE)
|
||||
|
||||
#include "common/updates.h"
|
||||
|
||||
class Win32UpdateManager : public Common::UpdateManager {
|
||||
public:
|
||||
Win32UpdateManager();
|
||||
virtual ~Win32UpdateManager();
|
||||
|
||||
virtual void checkForUpdates();
|
||||
|
||||
virtual void setAutomaticallyChecksForUpdates(UpdateState state);
|
||||
virtual UpdateState getAutomaticallyChecksForUpdates();
|
||||
|
||||
virtual void setUpdateCheckInterval(int interval);
|
||||
virtual int getUpdateCheckInterval();
|
||||
|
||||
virtual bool getLastUpdateCheckTimeAndDate(TimeDate &t);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif // BACKENDS_UPDATES_WIN32_H
|
||||
+13
-5
@@ -42,7 +42,7 @@
|
||||
|
||||
#include "audio/musicplugin.h"
|
||||
|
||||
#include "graphics/renderer.h"
|
||||
#include "graphics/renderer.h" // ResidualVM
|
||||
|
||||
#define DETECTOR_TESTING_HACK
|
||||
#define UPGRADE_ALL_TARGETS_HACK
|
||||
@@ -59,7 +59,7 @@ static const char USAGE_STRING[] =
|
||||
;
|
||||
|
||||
// DONT FIXME: DO NOT ORDER ALPHABETICALLY, THIS IS ORDERED BY IMPORTANCE/CATEGORY! :)
|
||||
#if defined(__SYMBIAN32__) || defined(__GP32__) || defined(ANDROID) || defined(__DS__)
|
||||
#if defined(__SYMBIAN32__) || defined(__GP32__) || defined(ANDROID) || defined(__DS__) || defined(__3DS__)
|
||||
static const char HELP_STRING[] = "NoUsageString"; // save more data segment space
|
||||
#else
|
||||
static const char HELP_STRING[] =
|
||||
@@ -99,8 +99,9 @@ static const char HELP_STRING[] =
|
||||
" -u, --dump-scripts Enable script dumping if a directory called 'dumps'\n"
|
||||
" exists in the current directory\n"
|
||||
"\n"
|
||||
" --cdrom=NUM CD drive to play CD audio from (default: 0 = first\n"
|
||||
" drive)\n"
|
||||
" --cdrom=DRIVE CD drive to play CD audio from; can either be a\n"
|
||||
" drive, path, or numeric index (default: 0 = best\n"
|
||||
" choice drive)\n"
|
||||
" --joystick[=NUM] Enable joystick input (default: 0 = first joystick)\n"
|
||||
" --platform=WORD Specify platform of game (allowed values: 2gs, 3do,\n"
|
||||
" acorn, amiga, atari, c64, fmtowns, nes, mac, pc, pc98,\n"
|
||||
@@ -339,6 +340,12 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
|
||||
// We defer checking whether this is a valid target to a later point.
|
||||
return s;
|
||||
} else {
|
||||
// On MacOS X prior to 10.9 the OS is sometimes adding a -psn_X_XXXXXX argument (where X are digits)
|
||||
// to pass the process serial number. We need to ignore it to avoid an error.
|
||||
#ifdef MACOSX
|
||||
if (strncmp(s, "-psn_", 5) == 0)
|
||||
continue;
|
||||
#endif
|
||||
|
||||
bool isLongCmd = (s[0] == '-' && s[1] == '-');
|
||||
|
||||
@@ -489,7 +496,7 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
|
||||
|
||||
DO_LONG_OPTION("gamma")
|
||||
END_OPTION
|
||||
|
||||
// ResidualVM specific start
|
||||
DO_LONG_OPTION("renderer")
|
||||
Graphics::RendererType renderer = Graphics::parseRendererTypeCode(option);
|
||||
if (renderer == Graphics::kRendererTypeDefault)
|
||||
@@ -497,6 +504,7 @@ Common::String parseCommandLine(Common::StringMap &settings, int argc, const cha
|
||||
END_OPTION
|
||||
|
||||
DO_LONG_OPTION_BOOL("show-fps")
|
||||
// ResidualVM specific end
|
||||
END_OPTION
|
||||
|
||||
DO_LONG_OPTION("savepath")
|
||||
|
||||
+30
-2
@@ -75,6 +75,9 @@
|
||||
#include "gui/launcher.h"
|
||||
#endif
|
||||
|
||||
#ifdef USE_UPDATES
|
||||
#include "gui/updates-dialog.h"
|
||||
#endif
|
||||
|
||||
static bool launcherDialog() {
|
||||
|
||||
@@ -134,9 +137,26 @@ static Common::Error runGame(const EnginePlugin *plugin, OSystem &system, const
|
||||
Common::Error err = Common::kNoError;
|
||||
Engine *engine = 0;
|
||||
|
||||
// Disabled in ResidualVM:
|
||||
#if 0//defined(SDL_BACKEND) && defined(USE_OPENGL) && defined(USE_RGB_COLOR)
|
||||
// HACK: We set up the requested graphics mode setting here to allow the
|
||||
// backend to switch from Surface SDL to OpenGL if necessary. This is
|
||||
// needed because otherwise the g_system->getSupportedFormats might return
|
||||
// bad values.
|
||||
g_system->beginGFXTransaction();
|
||||
g_system->setGraphicsMode(ConfMan.get("gfx_mode").c_str());
|
||||
if (g_system->endGFXTransaction() != OSystem::kTransactionSuccess) {
|
||||
warning("Switching graphics mode to '%s' failed", ConfMan.get("gfx_mode").c_str());
|
||||
return Common::kUnknownError;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Verify that the game path refers to an actual directory
|
||||
if (!(dir.exists() && dir.isDirectory()))
|
||||
if (!dir.exists()) {
|
||||
err = Common::kPathDoesNotExist;
|
||||
} else if (!dir.isDirectory()) {
|
||||
err = Common::kPathNotDirectory;
|
||||
}
|
||||
|
||||
// Create the game engine
|
||||
if (err.getCode() == Common::kNoError) {
|
||||
@@ -370,7 +390,8 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
|
||||
if (settings.contains("debugflags")) {
|
||||
specialDebug = settings["debugflags"];
|
||||
settings.erase("debugflags");
|
||||
}
|
||||
} else if (ConfMan.hasKey("debugflags"))
|
||||
specialDebug = ConfMan.get("debugflags");
|
||||
|
||||
PluginManager::instance().init();
|
||||
PluginManager::instance().loadAllPlugins(); // load plugins for cached plugin manager
|
||||
@@ -446,6 +467,13 @@ extern "C" int scummvm_main(int argc, const char * const argv[]) {
|
||||
// Now as the event manager is created, setup the keymapper
|
||||
setupKeymapper(system);
|
||||
|
||||
#ifdef USE_UPDATES
|
||||
if (!ConfMan.hasKey("updates_check")) {
|
||||
GUI::UpdatesDialog dlg;
|
||||
dlg.runModal();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Unless a game was specified, show the launcher dialog
|
||||
if (0 == ConfMan.getActiveDomain())
|
||||
launcherDialog();
|
||||
|
||||
@@ -141,9 +141,6 @@ public:
|
||||
#if defined(USE_TIMIDITY)
|
||||
LINK_PLUGIN(TIMIDITY)
|
||||
#endif
|
||||
#if PLUGIN_ENABLED_STATIC(STARK)
|
||||
LINK_PLUGIN(STARK)
|
||||
#endif
|
||||
|
||||
return pl;
|
||||
}
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@
|
||||
* header file, analog to internal_version.h, maybe called svn_rev.h or so.)
|
||||
*
|
||||
* Drawback: This only works on systems which can run suitable scripts as part
|
||||
* of the build proces (so I guess Visual C++ would be out of the game here?
|
||||
* of the build process (so I guess Visual C++ would be out of the game here?
|
||||
* I don't know VC enough to be sure). And of course it must be robust enough
|
||||
* to properly work in exports (i.e. release tar balls etc.).
|
||||
*/
|
||||
|
||||
@@ -270,5 +270,26 @@ T gcd(T a, T b) {
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Replacement algorithm for iterables.
|
||||
*
|
||||
* Replaces all occurrences of "original" in [begin, end) with occurrences of "replaced".
|
||||
*
|
||||
* @param[in, out] begin: First element to be examined.
|
||||
* @param[in] end: Last element in the seubsection. Not examined.
|
||||
* @param[in] original: Elements to be replaced.
|
||||
* @param[in] replaced: Element to replace occurrences of "original".
|
||||
*
|
||||
* @note Usage examples and unit tests may be found in "test/common/algorithm.h"
|
||||
*/
|
||||
template<class It, class Dat>
|
||||
void replace(It begin, It end, const Dat &original, const Dat &replaced) {
|
||||
for (; begin != end; ++begin) {
|
||||
if (*begin == original) {
|
||||
*begin = replaced;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Common
|
||||
#endif
|
||||
|
||||
+14
-15
@@ -48,7 +48,7 @@ int Archive::listMatchingMembers(ArchiveMemberList &list, const String &pattern)
|
||||
int matches = 0;
|
||||
|
||||
ArchiveMemberList::const_iterator it = allNames.begin();
|
||||
for ( ; it != allNames.end(); ++it) {
|
||||
for (; it != allNames.end(); ++it) {
|
||||
// TODO: We match case-insenstivie for now, our API does not define whether that's ok or not though...
|
||||
// For our use case case-insensitive is probably what we want to have though.
|
||||
if ((*it)->getName().matchString(pattern, true, true)) {
|
||||
@@ -64,7 +64,7 @@ int Archive::listMatchingMembers(ArchiveMemberList &list, const String &pattern)
|
||||
|
||||
SearchSet::ArchiveNodeList::iterator SearchSet::find(const String &name) {
|
||||
ArchiveNodeList::iterator it = _list.begin();
|
||||
for ( ; it != _list.end(); ++it) {
|
||||
for (; it != _list.end(); ++it) {
|
||||
if (it->_name == name)
|
||||
break;
|
||||
}
|
||||
@@ -73,7 +73,7 @@ SearchSet::ArchiveNodeList::iterator SearchSet::find(const String &name) {
|
||||
|
||||
SearchSet::ArchiveNodeList::const_iterator SearchSet::find(const String &name) const {
|
||||
ArchiveNodeList::const_iterator it = _list.begin();
|
||||
for ( ; it != _list.end(); ++it) {
|
||||
for (; it != _list.end(); ++it) {
|
||||
if (it->_name == name)
|
||||
break;
|
||||
}
|
||||
@@ -81,13 +81,13 @@ SearchSet::ArchiveNodeList::const_iterator SearchSet::find(const String &name) c
|
||||
}
|
||||
|
||||
/*
|
||||
Keep the nodes sorted according to descending priorities.
|
||||
In case two or node nodes have the same priority, insertion
|
||||
order prevails.
|
||||
Keep the nodes sorted according to descending priorities.
|
||||
In case two or node nodes have the same priority, insertion
|
||||
order prevails.
|
||||
*/
|
||||
void SearchSet::insert(const Node &node) {
|
||||
ArchiveNodeList::iterator it = _list.begin();
|
||||
for ( ; it != _list.end(); ++it) {
|
||||
for (; it != _list.end(); ++it) {
|
||||
if (it->_priority < node._priority)
|
||||
break;
|
||||
}
|
||||
@@ -131,8 +131,7 @@ void SearchSet::addSubDirectoriesMatching(const FSNode &directory, String origPa
|
||||
++sep;
|
||||
if (sep != origPattern.end())
|
||||
nextPattern = String(sep, origPattern.end());
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
pattern = origPattern;
|
||||
}
|
||||
|
||||
@@ -211,7 +210,7 @@ bool SearchSet::hasFile(const String &name) const {
|
||||
return false;
|
||||
|
||||
ArchiveNodeList::const_iterator it = _list.begin();
|
||||
for ( ; it != _list.end(); ++it) {
|
||||
for (; it != _list.end(); ++it) {
|
||||
if (it->_arc->hasFile(name))
|
||||
return true;
|
||||
}
|
||||
@@ -223,7 +222,7 @@ int SearchSet::listMatchingMembers(ArchiveMemberList &list, const String &patter
|
||||
int matches = 0;
|
||||
|
||||
ArchiveNodeList::const_iterator it = _list.begin();
|
||||
for ( ; it != _list.end(); ++it)
|
||||
for (; it != _list.end(); ++it)
|
||||
matches += it->_arc->listMatchingMembers(list, pattern);
|
||||
|
||||
return matches;
|
||||
@@ -233,7 +232,7 @@ int SearchSet::listMembers(ArchiveMemberList &list) const {
|
||||
int matches = 0;
|
||||
|
||||
ArchiveNodeList::const_iterator it = _list.begin();
|
||||
for ( ; it != _list.end(); ++it)
|
||||
for (; it != _list.end(); ++it)
|
||||
matches += it->_arc->listMembers(list);
|
||||
|
||||
return matches;
|
||||
@@ -244,7 +243,7 @@ const ArchiveMemberPtr SearchSet::getMember(const String &name) const {
|
||||
return ArchiveMemberPtr();
|
||||
|
||||
ArchiveNodeList::const_iterator it = _list.begin();
|
||||
for ( ; it != _list.end(); ++it) {
|
||||
for (; it != _list.end(); ++it) {
|
||||
if (it->_arc->hasFile(name))
|
||||
return it->_arc->getMember(name);
|
||||
}
|
||||
@@ -257,7 +256,7 @@ SeekableReadStream *SearchSet::createReadStreamForMember(const String &name) con
|
||||
return 0;
|
||||
|
||||
ArchiveNodeList::const_iterator it = _list.begin();
|
||||
for ( ; it != _list.end(); ++it) {
|
||||
for (; it != _list.end(); ++it) {
|
||||
SeekableReadStream *stream = it->_arc->createReadStreamForMember(name);
|
||||
if (stream)
|
||||
return stream;
|
||||
@@ -268,7 +267,7 @@ SeekableReadStream *SearchSet::createReadStreamForMember(const String &name) con
|
||||
|
||||
|
||||
SearchManager::SearchManager() {
|
||||
clear(); // Force a reset
|
||||
clear(); // Force a reset
|
||||
}
|
||||
|
||||
void SearchManager::clear() {
|
||||
|
||||
@@ -141,6 +141,12 @@ public:
|
||||
insert_aux(_storage + idx, array.begin(), array.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts element before pos.
|
||||
*/
|
||||
void insert(iterator pos, const T &element) {
|
||||
insert_aux(pos, &element, &element + 1);
|
||||
}
|
||||
|
||||
T remove_at(size_type idx) {
|
||||
assert(idx < _size);
|
||||
@@ -187,6 +193,14 @@ public:
|
||||
_capacity = 0;
|
||||
}
|
||||
|
||||
iterator erase(iterator pos) {
|
||||
copy(pos + 1, _storage + _size, pos);
|
||||
_size--;
|
||||
// We also need to destroy the last object properly here.
|
||||
_storage[_size].~T();
|
||||
return pos;
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return (_size == 0);
|
||||
}
|
||||
@@ -347,6 +361,87 @@ protected:
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Double linked list with sorted nodes.
|
||||
*/
|
||||
template<class T>
|
||||
class SortedArray : public Array<T> {
|
||||
public:
|
||||
typedef T *iterator;
|
||||
typedef uint size_type;
|
||||
|
||||
SortedArray(int (*comparator)(const void *, const void *)) {
|
||||
_comparator = comparator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts element at the sorted position.
|
||||
*/
|
||||
void insert(const T &element) {
|
||||
if (!this->_size) {
|
||||
this->insert_aux(this->_storage, &element, &element + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
T *where = bsearchMin(element);
|
||||
|
||||
if (where > this->_storage + this->_size)
|
||||
Array<T>::push_back(element);
|
||||
else
|
||||
Array<T>::insert(where, element);
|
||||
}
|
||||
|
||||
T &operator[](size_type idx) {
|
||||
error("Operation []= not allowed with SortedArray");
|
||||
}
|
||||
|
||||
void insert_at(size_type idx, const T &element) {
|
||||
error("Operation insert_at(idx, element) not allowed with SortedArray");
|
||||
}
|
||||
|
||||
void insert_at(size_type idx, const Array<T> &array) {
|
||||
error("Operation insert_at(idx, array) not allowed with SortedArray");
|
||||
}
|
||||
|
||||
void insert(iterator pos, const T &element) {
|
||||
error("Operation insert(pos, elemnet) not allowed with SortedArray");
|
||||
}
|
||||
|
||||
void push_back(const T &element) {
|
||||
error("Operation push_back(element) not allowed with SortedArray");
|
||||
}
|
||||
|
||||
void push_back(const Array<T> &array) {
|
||||
error("Operation push_back(array) not allowed with SortedArray");
|
||||
}
|
||||
|
||||
private:
|
||||
// Based on code Copyright (C) 2008-2009 Ksplice, Inc.
|
||||
// Author: Tim Abbott <tabbott@ksplice.com>
|
||||
// Licensed under GPLv2+
|
||||
T *bsearchMin(void *key) {
|
||||
uint start_ = 0, end_ = this->_size;
|
||||
int result;
|
||||
|
||||
while (start_ < end_) {
|
||||
uint mid = start_ + (end_ - start_) / 2;
|
||||
|
||||
result = this->_comparator(key, this->_storage[mid]);
|
||||
if (result < 0)
|
||||
end_ = mid;
|
||||
else if (result > 0)
|
||||
start_ = mid + 1;
|
||||
else
|
||||
return &this->_storage[mid];
|
||||
}
|
||||
|
||||
return &this->_storage[start_];
|
||||
}
|
||||
|
||||
private:
|
||||
int (*_comparator)(const void *, const void *);
|
||||
};
|
||||
|
||||
} // End of namespace Common
|
||||
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -470,7 +470,7 @@ bool decompressDCL(ReadStream *src, byte *dest, uint32 packedSize, uint32 unpack
|
||||
// Read source into memory
|
||||
src->read(sourceBufferPtr, packedSize);
|
||||
|
||||
Common::MemoryReadStream *sourceStream = new MemoryReadStream(sourceBufferPtr, packedSize, DisposeAfterUse::NO);
|
||||
Common::MemoryReadStream *sourceStream = new MemoryReadStream(sourceBufferPtr, packedSize, DisposeAfterUse::YES);
|
||||
Common::MemoryWriteStream *targetStream = new MemoryWriteStream(dest, unpackedSize);
|
||||
|
||||
success = dcl.unpack(sourceStream, targetStream, unpackedSize, true);
|
||||
|
||||
@@ -64,6 +64,7 @@ const struct GameOpt {
|
||||
{ GUIO_RENDERPC9801, "pc9801" },
|
||||
{ GUIO_RENDERAPPLE2GS, "2gs" },
|
||||
{ GUIO_RENDERATARIST, "atari" },
|
||||
{ GUIO_RENDERMACINTOSH, "macintosh" },
|
||||
|
||||
{ GUIO_GAMEOPTIONS1, "gameOption1" },
|
||||
{ GUIO_GAMEOPTIONS2, "gameOption2" },
|
||||
@@ -73,6 +74,7 @@ const struct GameOpt {
|
||||
{ GUIO_GAMEOPTIONS6, "gameOption6" },
|
||||
{ GUIO_GAMEOPTIONS7, "gameOption7" },
|
||||
{ GUIO_GAMEOPTIONS8, "gameOption8" },
|
||||
{ GUIO_GAMEOPTIONS9, "gameOption9" },
|
||||
|
||||
{ GUIO_NONE, 0 }
|
||||
};
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#define GUIO_RENDERPC9801 "\040"
|
||||
#define GUIO_RENDERAPPLE2GS "\041"
|
||||
#define GUIO_RENDERATARIST "\042"
|
||||
#define GUIO_RENDERMACINTOSH "\043"
|
||||
|
||||
// Special GUIO flags for the AdvancedDetector's caching of game specific
|
||||
// options.
|
||||
@@ -67,6 +68,7 @@
|
||||
#define GUIO_GAMEOPTIONS6 "\055"
|
||||
#define GUIO_GAMEOPTIONS7 "\056"
|
||||
#define GUIO_GAMEOPTIONS8 "\057"
|
||||
#define GUIO_GAMEOPTIONS9 "\058"
|
||||
|
||||
#define GUIO0() (GUIO_NONE)
|
||||
#define GUIO1(a) (a)
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "common/md5.h"
|
||||
#include "common/substream.h"
|
||||
#include "common/textconsole.h"
|
||||
#include "common/archive.h"
|
||||
|
||||
#ifdef MACOSX
|
||||
#include "common/config-manager.h"
|
||||
@@ -261,6 +262,76 @@ bool MacResManager::exists(const String &fileName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void MacResManager::listFiles(StringArray &files, const String &pattern) {
|
||||
// Base names discovered so far.
|
||||
typedef HashMap<String, bool, IgnoreCase_Hash, IgnoreCase_EqualTo> BaseNameSet;
|
||||
BaseNameSet baseNames;
|
||||
|
||||
// List files itself.
|
||||
ArchiveMemberList memberList;
|
||||
SearchMan.listMatchingMembers(memberList, pattern);
|
||||
SearchMan.listMatchingMembers(memberList, pattern + ".rsrc");
|
||||
SearchMan.listMatchingMembers(memberList, pattern + ".bin");
|
||||
SearchMan.listMatchingMembers(memberList, constructAppleDoubleName(pattern));
|
||||
|
||||
for (ArchiveMemberList::const_iterator i = memberList.begin(), end = memberList.end(); i != end; ++i) {
|
||||
String filename = (*i)->getName();
|
||||
|
||||
// For raw resource forks and MacBinary files we strip the extension
|
||||
// here to obtain a valid base name.
|
||||
int lastDotPos = filename.size() - 1;
|
||||
for (; lastDotPos >= 0; --lastDotPos) {
|
||||
if (filename[lastDotPos] == '.') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastDotPos != -1) {
|
||||
const char *extension = filename.c_str() + lastDotPos + 1;
|
||||
bool removeExtension = false;
|
||||
|
||||
// TODO: Should we really keep filenames suggesting raw resource
|
||||
// forks or MacBinary files but not being such around? This might
|
||||
// depend on the pattern the client requests...
|
||||
if (!scumm_stricmp(extension, "rsrc")) {
|
||||
SeekableReadStream *stream = (*i)->createReadStream();
|
||||
removeExtension = stream && isRawFork(*stream);
|
||||
delete stream;
|
||||
} else if (!scumm_stricmp(extension, "bin")) {
|
||||
SeekableReadStream *stream = (*i)->createReadStream();
|
||||
removeExtension = stream && isMacBinary(*stream);
|
||||
delete stream;
|
||||
}
|
||||
|
||||
if (removeExtension) {
|
||||
filename.erase(lastDotPos);
|
||||
}
|
||||
}
|
||||
|
||||
// Strip AppleDouble '._' prefix if applicable.
|
||||
bool isAppleDoubleName = false;
|
||||
const String filenameAppleDoubleStripped = disassembleAppleDoubleName(filename, &isAppleDoubleName);
|
||||
|
||||
if (isAppleDoubleName) {
|
||||
SeekableReadStream *stream = (*i)->createReadStream();
|
||||
if (stream->readUint32BE() == 0x00051607) {
|
||||
filename = filenameAppleDoubleStripped;
|
||||
}
|
||||
// TODO: Should we really keep filenames suggesting AppleDouble
|
||||
// but not being AppleDouble around? This might depend on the
|
||||
// pattern the client requests...
|
||||
delete stream;
|
||||
}
|
||||
|
||||
baseNames[filename] = true;
|
||||
}
|
||||
|
||||
// Append resulting base names to list to indicate found files.
|
||||
for (BaseNameSet::const_iterator i = baseNames.begin(), end = baseNames.end(); i != end; ++i) {
|
||||
files.push_back(i->_key);
|
||||
}
|
||||
}
|
||||
|
||||
bool MacResManager::loadFromAppleDouble(SeekableReadStream &stream) {
|
||||
if (stream.readUint32BE() != 0x00051607) // tag
|
||||
return false;
|
||||
@@ -314,6 +385,18 @@ bool MacResManager::isMacBinary(SeekableReadStream &stream) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacResManager::isRawFork(SeekableReadStream &stream) {
|
||||
// TODO: Is there a better way to detect whether this is a raw fork?
|
||||
const uint32 dataOffset = stream.readUint32BE();
|
||||
const uint32 mapOffset = stream.readUint32BE();
|
||||
const uint32 dataLength = stream.readUint32BE();
|
||||
const uint32 mapLength = stream.readUint32BE();
|
||||
|
||||
return !stream.eos() && !stream.err()
|
||||
&& dataOffset < (uint32)stream.size() && dataOffset + dataLength <= (uint32)stream.size()
|
||||
&& mapOffset < (uint32)stream.size() && mapOffset + mapLength <= (uint32)stream.size();
|
||||
}
|
||||
|
||||
bool MacResManager::loadFromMacBinary(SeekableReadStream &stream) {
|
||||
byte infoHeader[MBI_INFOHDR];
|
||||
stream.read(infoHeader, MBI_INFOHDR);
|
||||
@@ -592,4 +675,32 @@ String MacResManager::constructAppleDoubleName(String name) {
|
||||
return name;
|
||||
}
|
||||
|
||||
String MacResManager::disassembleAppleDoubleName(String name, bool *isAppleDouble) {
|
||||
if (isAppleDouble) {
|
||||
*isAppleDouble = false;
|
||||
}
|
||||
|
||||
// Remove "._" before the last portion of a path name.
|
||||
for (int i = name.size() - 1; i >= 0; --i) {
|
||||
if (i == 0) {
|
||||
if (name.size() > 2 && name[0] == '.' && name[1] == '_') {
|
||||
name.erase(0, 2);
|
||||
if (isAppleDouble) {
|
||||
*isAppleDouble = true;
|
||||
}
|
||||
}
|
||||
} else if (name[i] == '/') {
|
||||
if ((uint)(i + 2) < name.size() && name[i + 1] == '.' && name[i + 2] == '_') {
|
||||
name.erase(i + 1, 2);
|
||||
if (isAppleDouble) {
|
||||
*isAppleDouble = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
} // End of namespace Common
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
#include "common/array.h"
|
||||
#include "common/fs.h"
|
||||
#include "common/str.h"
|
||||
#include "common/str-array.h"
|
||||
|
||||
#ifndef COMMON_MACRESMAN_H
|
||||
#define COMMON_MACRESMAN_H
|
||||
@@ -81,6 +82,16 @@ public:
|
||||
*/
|
||||
static bool exists(const String &fileName);
|
||||
|
||||
/**
|
||||
* List all filenames matching pattern for opening with open().
|
||||
*
|
||||
* @param files Array containing all matching filenames discovered. Only
|
||||
* adds to the list.
|
||||
* @param pattern Pattern to match against. Taking String::matchPattern's
|
||||
* format.
|
||||
*/
|
||||
static void listFiles(StringArray &files, const String &pattern);
|
||||
|
||||
/**
|
||||
* Close the Mac data/resource fork pair.
|
||||
*/
|
||||
@@ -176,6 +187,7 @@ private:
|
||||
bool loadFromAppleDouble(SeekableReadStream &stream);
|
||||
|
||||
static String constructAppleDoubleName(String name);
|
||||
static String disassembleAppleDoubleName(String name, bool *isAppleDouble);
|
||||
|
||||
/**
|
||||
* Check if the given stream is in the MacBinary format.
|
||||
@@ -183,6 +195,13 @@ private:
|
||||
*/
|
||||
static bool isMacBinary(SeekableReadStream &stream);
|
||||
|
||||
/**
|
||||
* Do a sanity check whether the given stream is a raw resource fork.
|
||||
*
|
||||
* @param stream Stream object to check. Will not preserve its position.
|
||||
*/
|
||||
static bool isRawFork(SeekableReadStream &stream);
|
||||
|
||||
enum {
|
||||
kResForkNone = 0,
|
||||
kResForkRaw,
|
||||
|
||||
+3
-2
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "common/stream.h"
|
||||
#include "common/types.h"
|
||||
#include "common/util.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
@@ -156,7 +157,7 @@ public:
|
||||
* that grows as it's written to.
|
||||
*/
|
||||
class MemoryWriteStreamDynamic : public WriteStream {
|
||||
private:
|
||||
protected:
|
||||
uint32 _capacity;
|
||||
uint32 _size;
|
||||
byte *_ptr;
|
||||
@@ -170,7 +171,7 @@ private:
|
||||
|
||||
byte *old_data = _data;
|
||||
|
||||
_capacity = new_len + 32;
|
||||
_capacity = MAX(new_len + 32, _capacity * 2);
|
||||
_data = (byte *)malloc(_capacity);
|
||||
_ptr = _data + _pos;
|
||||
|
||||
|
||||
@@ -59,10 +59,16 @@ MODULE_OBJS += \
|
||||
recorderfile.o
|
||||
endif
|
||||
|
||||
# ResidualVM specific
|
||||
ifdef USE_ICONV
|
||||
MODULE_OBJS += \
|
||||
iconv.o
|
||||
endif
|
||||
|
||||
ifdef USE_UPDATES
|
||||
MODULE_OBJS += \
|
||||
updates.o
|
||||
endif
|
||||
|
||||
# Include common rules
|
||||
include $(srcdir)/rules.mk
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace Common {
|
||||
|
||||
const PlatformDescription g_platforms[] = {
|
||||
{ "2gs", "2gs", "2gs", "Apple IIgs", kPlatformApple2GS },
|
||||
{ "apple2", "apple2", "apple2", "Apple II", kPlatformApple2 },
|
||||
{ "3do", "3do", "3do", "3DO", kPlatform3DO },
|
||||
{ "acorn", "acorn", "acorn", "Acorn", kPlatformAcorn },
|
||||
{ "amiga", "ami", "amiga", "Amiga", kPlatformAmiga },
|
||||
|
||||
@@ -50,6 +50,7 @@ enum Platform {
|
||||
kPlatformSegaCD,
|
||||
kPlatform3DO,
|
||||
kPlatformPCEngine,
|
||||
kPlatformApple2,
|
||||
kPlatformApple2GS,
|
||||
kPlatformPC98,
|
||||
kPlatformWii,
|
||||
|
||||
@@ -84,6 +84,8 @@ public:
|
||||
int getNumerator() const { return _num; }
|
||||
int getDenominator() const { return _denom; }
|
||||
|
||||
bool isOne() const { return _num == _denom; }
|
||||
|
||||
void debugPrint(int debuglevel = 0, const char *caption = "Rational:") const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
#include "graphics/surface.h"
|
||||
#include "graphics/scaler.h"
|
||||
|
||||
#ifdef ENABLE_EVENTRECORDER
|
||||
|
||||
#define RECORD_VERSION 1
|
||||
|
||||
namespace Common {
|
||||
@@ -714,3 +716,5 @@ void PlaybackFile::checkRecordedMD5() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // ENABLE_EVENTRECORDER
|
||||
|
||||
+2
-1
@@ -163,7 +163,8 @@ struct Rect {
|
||||
*
|
||||
* @param r the rectangle to check
|
||||
*
|
||||
* @return true if the given rectangle is inside the rectangle, false otherwise
|
||||
* @return true if the given rectangle has a non-empty intersection with
|
||||
* this rectangle, false otherwise
|
||||
*/
|
||||
bool intersects(const Rect &r) const {
|
||||
return (left < r.right) && (r.left < right) && (top < r.bottom) && (r.top < bottom);
|
||||
|
||||
@@ -43,6 +43,7 @@ const RenderModeDescription g_renderModes[] = {
|
||||
{ "pc9801", _s("PC-9801 (16 Colors)"), kRenderPC9801 },
|
||||
{ "2gs", "Apple IIgs", kRenderApple2GS },
|
||||
{ "atari", "Atari ST", kRenderAtariST },
|
||||
{ "macintosh", "Macintosh", kRenderMacintosh },
|
||||
{0, 0, kRenderDefault}
|
||||
};
|
||||
|
||||
@@ -65,7 +66,8 @@ static const RenderGUIOMapping s_renderGUIOMapping[] = {
|
||||
{ kRenderPC9821, GUIO_RENDERPC9821 },
|
||||
{ kRenderPC9801, GUIO_RENDERPC9801 },
|
||||
{ kRenderApple2GS, GUIO_RENDERAPPLE2GS },
|
||||
{ kRenderAtariST, GUIO_RENDERATARIST }
|
||||
{ kRenderAtariST, GUIO_RENDERATARIST },
|
||||
{ kRenderMacintosh, GUIO_RENDERMACINTOSH }
|
||||
};
|
||||
|
||||
DECLARE_TRANSLATION_ADDITIONAL_CONTEXT("Hercules Green", "lowres")
|
||||
|
||||
+2
-1
@@ -47,7 +47,8 @@ enum RenderMode {
|
||||
kRenderPC9821 = 8,
|
||||
kRenderPC9801 = 9,
|
||||
kRenderApple2GS = 10,
|
||||
kRenderAtariST = 11
|
||||
kRenderAtariST = 11,
|
||||
kRenderMacintosh = 12
|
||||
};
|
||||
|
||||
struct RenderModeDescription {
|
||||
|
||||
+29
-16
@@ -56,6 +56,12 @@ typedef WriteStream OutSaveFile;
|
||||
* i.e. typically save states, but also configuration files and similar
|
||||
* things.
|
||||
*
|
||||
* Savefile names represent SaveFiles. These names are case insensitive, that
|
||||
* means a name of "Kq1.000" represents the same savefile as "kq1.000". In
|
||||
* addition, SaveFileManager does not allow for names which contain path
|
||||
* separators like '/' or '\'. This is because we do not support directories
|
||||
* in SaveFileManager.
|
||||
*
|
||||
* While not declared as a singleton, it is effectively used as such,
|
||||
* with OSystem::getSavefileManager returning a pointer to the single
|
||||
* SaveFileManager instances to be used.
|
||||
@@ -115,49 +121,56 @@ public:
|
||||
* exports from the Quest for Glory series. QfG5 is a 3D game and won't be
|
||||
* supported by ScummVM.
|
||||
*
|
||||
* @param name the name of the savefile
|
||||
* @param compress toggles whether to compress the resulting save file
|
||||
* (default) or not.
|
||||
* @return pointer to an OutSaveFile, or NULL if an error occurred.
|
||||
* @param name The name of the savefile.
|
||||
* @param compress Toggles whether to compress the resulting save file
|
||||
* (default) or not.
|
||||
* @return Pointer to an OutSaveFile, or NULL if an error occurred.
|
||||
*/
|
||||
virtual OutSaveFile *openForSaving(const String &name, bool compress = true) = 0;
|
||||
|
||||
/**
|
||||
* Open the file with the specified name in the given directory for loading.
|
||||
* @param name the name of the savefile
|
||||
* @return pointer to an InSaveFile, or NULL if an error occurred.
|
||||
*
|
||||
* @param name The name of the savefile.
|
||||
* @return Pointer to an InSaveFile, or NULL if an error occurred.
|
||||
*/
|
||||
virtual InSaveFile *openForLoading(const String &name) = 0;
|
||||
|
||||
/**
|
||||
* Removes the given savefile from the system.
|
||||
* @param name the name of the savefile to be removed.
|
||||
*
|
||||
* @param name The name of the savefile to be removed.
|
||||
* @return true if no error occurred, false otherwise.
|
||||
*/
|
||||
virtual bool removeSavefile(const String &name) = 0;
|
||||
|
||||
/**
|
||||
* Renames the given savefile.
|
||||
* @param oldName Old name.
|
||||
* @param newName New name.
|
||||
*
|
||||
* @param oldName Old name.
|
||||
* @param newName New name.
|
||||
* @return true if no error occurred. false otherwise.
|
||||
*/
|
||||
virtual bool renameSavefile(const String &oldName, const String &newName);
|
||||
|
||||
/**
|
||||
* Copy the given savefile.
|
||||
* @param oldName Old name.
|
||||
* @param newName New name.
|
||||
*
|
||||
* @param oldName Old name.
|
||||
* @param newName New name.
|
||||
* @return true if no error occurred. false otherwise.
|
||||
*/
|
||||
virtual bool copySavefile(const String &oldName, const String &newName);
|
||||
|
||||
/**
|
||||
* Request a list of available savegames with a given DOS-style pattern,
|
||||
* also known as "glob" in the POSIX world. Refer to the Common::matchString()
|
||||
* function to learn about the precise pattern format.
|
||||
* @param pattern Pattern to match. Wildcards like * or ? are available.
|
||||
* @return list of strings for all present file names.
|
||||
* List available savegames matching a given pattern.
|
||||
*
|
||||
* Our pattern format is based on DOS paterns, also known as "glob" in the
|
||||
* POSIX world. Please refer to the Common::matchString() function to learn
|
||||
* about the precise pattern format.
|
||||
*
|
||||
* @param pattern Pattern to match. Wildcards like * or ? are available.
|
||||
* @return List of strings for all present file names.
|
||||
* @see Common::matchString()
|
||||
*/
|
||||
virtual StringArray listSavefiles(const String &pattern) = 0;
|
||||
|
||||
+6
-1
@@ -215,6 +215,10 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
// Now we need to adjust some settings when running tests
|
||||
#ifdef COMPILING_TESTS
|
||||
#undef ENABLE_EVENTRECORDER
|
||||
#endif
|
||||
|
||||
// In the following we configure various targets, in particular those
|
||||
// which can't use our "configure" tool and hence don't use config.h.
|
||||
@@ -251,6 +255,7 @@
|
||||
|
||||
#if defined(__DC__) || \
|
||||
defined(__DS__) || \
|
||||
defined(__3DS__) || \
|
||||
defined(__GP32__) || \
|
||||
defined(IPHONE) || \
|
||||
defined(__PLAYSTATION2__) || \
|
||||
@@ -367,7 +372,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef STRINGBUFLEN
|
||||
#if defined(__N64__) || defined(__DS__)
|
||||
#if defined(__N64__) || defined(__DS__) || defined(__3DS__)
|
||||
#define STRINGBUFLEN 256
|
||||
#else
|
||||
#define STRINGBUFLEN 1024
|
||||
|
||||
+65
-18
@@ -75,7 +75,7 @@ void String::initWithCStr(const char *str, uint32 len) {
|
||||
}
|
||||
|
||||
String::String(const String &str)
|
||||
: _size(str._size) {
|
||||
: _size(str._size) {
|
||||
if (str.isStorageIntern()) {
|
||||
// String in internal storage: just copy it
|
||||
memcpy(_storage, str._storage, _builtinCapacity);
|
||||
@@ -91,7 +91,7 @@ String::String(const String &str)
|
||||
}
|
||||
|
||||
String::String(char c)
|
||||
: _size(0), _str(_storage) {
|
||||
: _size(0), _str(_storage) {
|
||||
|
||||
_storage[0] = c;
|
||||
_storage[1] = 0;
|
||||
@@ -132,24 +132,19 @@ void String::ensureCapacity(uint32 new_size, bool keep_old) {
|
||||
if (!isShared && new_size < curCapacity)
|
||||
return;
|
||||
|
||||
if (isShared && new_size < _builtinCapacity) {
|
||||
// We share the storage, but there is enough internal storage: Use that.
|
||||
newStorage = _storage;
|
||||
newCapacity = _builtinCapacity;
|
||||
} else {
|
||||
// We need to allocate storage on the heap!
|
||||
// We need to allocate storage on the heap!
|
||||
|
||||
// Compute a suitable new capacity limit
|
||||
// If the current capacity is sufficient we use the same capacity
|
||||
if (new_size < curCapacity)
|
||||
newCapacity = curCapacity;
|
||||
else
|
||||
newCapacity = MAX(curCapacity * 2, computeCapacity(new_size+1));
|
||||
// Compute a suitable new capacity limit
|
||||
// If the current capacity is sufficient we use the same capacity
|
||||
if (new_size < curCapacity)
|
||||
newCapacity = curCapacity;
|
||||
else
|
||||
newCapacity = MAX(curCapacity * 2, computeCapacity(new_size+1));
|
||||
|
||||
// Allocate new storage
|
||||
newStorage = new char[newCapacity];
|
||||
assert(newStorage);
|
||||
|
||||
// Allocate new storage
|
||||
newStorage = new char[newCapacity];
|
||||
assert(newStorage);
|
||||
}
|
||||
|
||||
// Copy old data if needed, elsewise reset the new storage.
|
||||
if (keep_old) {
|
||||
@@ -444,6 +439,58 @@ uint String::hash() const {
|
||||
return hashit(c_str());
|
||||
}
|
||||
|
||||
void String::replace(uint32 pos, uint32 count, const String &str) {
|
||||
replace(pos, count, str, 0, str._size);
|
||||
}
|
||||
|
||||
void String::replace(uint32 pos, uint32 count, const char *str) {
|
||||
replace(pos, count, str, 0, strlen(str));
|
||||
}
|
||||
|
||||
void String::replace(iterator begin_, iterator end_, const String &str) {
|
||||
replace(begin_ - _str, end_ - begin_, str._str, 0, str._size);
|
||||
}
|
||||
|
||||
void String::replace(iterator begin_, iterator end_, const char *str) {
|
||||
replace(begin_ - _str, end_ - begin_, str, 0, strlen(str));
|
||||
}
|
||||
|
||||
void String::replace(uint32 posOri, uint32 countOri, const String &str,
|
||||
uint32 posDest, uint32 countDest) {
|
||||
replace(posOri, countOri, str._str, posDest, countDest);
|
||||
}
|
||||
|
||||
void String::replace(uint32 posOri, uint32 countOri, const char *str,
|
||||
uint32 posDest, uint32 countDest) {
|
||||
|
||||
ensureCapacity(_size + countDest - countOri, true);
|
||||
|
||||
// Prepare string for the replaced text.
|
||||
if (countOri < countDest) {
|
||||
uint32 offset = countDest - countOri; ///< Offset to copy the characters
|
||||
uint32 newSize = _size + offset;
|
||||
_size = newSize;
|
||||
|
||||
// Push the old characters to the end of the string
|
||||
for (uint32 i = _size; i >= posOri + countDest; i--)
|
||||
_str[i] = _str[i - offset];
|
||||
|
||||
} else if (countOri > countDest){
|
||||
uint32 offset = countOri - countDest; ///< Number of positions that we have to pull back
|
||||
|
||||
// Pull the remainder string back
|
||||
for (uint32 i = posOri + countDest; i < _size; i++)
|
||||
_str[i] = _str[i + offset];
|
||||
|
||||
_size -= offset;
|
||||
}
|
||||
|
||||
// Copy the replaced part of the string
|
||||
for (uint32 i = 0; i < countDest; i++)
|
||||
_str[posOri + i] = str[posDest + i];
|
||||
|
||||
}
|
||||
|
||||
// static
|
||||
String String::format(const char *fmt, ...) {
|
||||
String output;
|
||||
|
||||
+43
-9
@@ -46,6 +46,17 @@ namespace Common {
|
||||
class String {
|
||||
public:
|
||||
static const uint32 npos = 0xFFFFFFFF;
|
||||
|
||||
typedef char value_type;
|
||||
/**
|
||||
* Unsigned version of the underlying type. This can be used to cast
|
||||
* individual string characters to bigger integer types without sign
|
||||
* extension happening.
|
||||
*/
|
||||
typedef unsigned char unsigned_type;
|
||||
typedef char * iterator;
|
||||
typedef const char * const_iterator;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* The size of the internal storage. Increasing this means less heap
|
||||
@@ -222,6 +233,38 @@ public:
|
||||
void trim();
|
||||
|
||||
uint hash() const;
|
||||
|
||||
/**@{
|
||||
* Functions to replace some amount of chars with chars from some other string.
|
||||
*
|
||||
* @note The implementation follows that of the STL's std::string:
|
||||
* http://www.cplusplus.com/reference/string/string/replace/
|
||||
*
|
||||
* @param pos Starting position for the replace in the original string.
|
||||
* @param count Number of chars to replace from the original string.
|
||||
* @param str Source of the new chars.
|
||||
* @param posOri Same as pos
|
||||
* @param countOri Same as count
|
||||
* @param posDest Initial position to read str from.
|
||||
* @param countDest Number of chars to read from str. npos by default.
|
||||
*/
|
||||
// Replace 'count' bytes, starting from 'pos' with str.
|
||||
void replace(uint32 pos, uint32 count, const String &str);
|
||||
// The same as above, but accepts a C-like array of characters.
|
||||
void replace(uint32 pos, uint32 count, const char *str);
|
||||
// Replace the characters in [begin, end) with str._str.
|
||||
void replace(iterator begin, iterator end, const String &str);
|
||||
// Replace the characters in [begin, end) with str.
|
||||
void replace(iterator begin, iterator end, const char *str);
|
||||
// Replace _str[posOri, posOri + countOri) with
|
||||
// str._str[posDest, posDest + countDest)
|
||||
void replace(uint32 posOri, uint32 countOri, const String &str,
|
||||
uint32 posDest, uint32 countDest);
|
||||
// Replace _str[posOri, posOri + countOri) with
|
||||
// str[posDest, posDest + countDest)
|
||||
void replace(uint32 posOri, uint32 countOri, const char *str,
|
||||
uint32 posDest, uint32 countDest);
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* Print formatted data into a String object. Similar to sprintf,
|
||||
@@ -238,15 +281,6 @@ public:
|
||||
static String vformat(const char *fmt, va_list args);
|
||||
|
||||
public:
|
||||
typedef char value_type;
|
||||
/**
|
||||
* Unsigned version of the underlying type. This can be used to cast
|
||||
* individual string characters to bigger integer types without sign
|
||||
* extension happening.
|
||||
*/
|
||||
typedef unsigned char unsigned_type;
|
||||
typedef char * iterator;
|
||||
typedef const char * const_iterator;
|
||||
|
||||
iterator begin() {
|
||||
// Since the user could potentially
|
||||
|
||||
@@ -672,6 +672,7 @@ public:
|
||||
* Return a Graphics::PixelBuffer representing the framebuffer.
|
||||
* The caller can then perform arbitrary graphics transformations
|
||||
* on the framebuffer (blitting, scrolling, etc.).
|
||||
* !!! ResidualVM specific method: !!!
|
||||
*/
|
||||
virtual Graphics::PixelBuffer getScreenPixelBuffer() = 0;
|
||||
|
||||
|
||||
+1
-1
@@ -123,7 +123,7 @@ public:
|
||||
virtual void addRecent(const String &name, const String &description) {}
|
||||
|
||||
/**
|
||||
* Notifies the user an error occured through the taskbar icon
|
||||
* Notifies the user an error occurred through the taskbar icon
|
||||
*
|
||||
* This will for example show the taskbar icon as red (using progress of 100% and an error state)
|
||||
* on Windows, and set the launcher icon in the urgent state on Unity
|
||||
|
||||
@@ -41,7 +41,7 @@ void setErrorHandler(ErrorHandler handler) {
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace Common
|
||||
} // End of namespace Common
|
||||
|
||||
|
||||
#ifndef DISABLE_TEXT_CONSOLE
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/system.h"
|
||||
#include "common/updates.h"
|
||||
#include "common/translation.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
static const int updateIntervals[] = {
|
||||
UpdateManager::kUpdateIntervalNotSupported,
|
||||
UpdateManager::kUpdateIntervalOneDay,
|
||||
UpdateManager::kUpdateIntervalOneWeek,
|
||||
UpdateManager::kUpdateIntervalOneMonth,
|
||||
-1
|
||||
};
|
||||
|
||||
const int *UpdateManager::getUpdateIntervals() {
|
||||
return updateIntervals;
|
||||
}
|
||||
|
||||
int UpdateManager::normalizeInterval(int interval) {
|
||||
const int *val = updateIntervals;
|
||||
|
||||
while (*val != -1) {
|
||||
if (*val >= interval)
|
||||
return *val;
|
||||
val++;
|
||||
}
|
||||
|
||||
return val[-1]; // Return maximal acceptable value
|
||||
}
|
||||
|
||||
const char *UpdateManager::updateIntervalToString(int interval) {
|
||||
switch (interval) {
|
||||
case kUpdateIntervalNotSupported:
|
||||
return _("Never");
|
||||
case kUpdateIntervalOneDay:
|
||||
return _("Daily");
|
||||
case kUpdateIntervalOneWeek:
|
||||
return _("Weekly");
|
||||
case kUpdateIntervalOneMonth:
|
||||
return _("Monthly");
|
||||
default:
|
||||
return _("<Bad value>");
|
||||
}
|
||||
}
|
||||
|
||||
} // End of namespace Common
|
||||
+37
-5
@@ -20,8 +20,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BACKENDS_UPDATES_ABSTRACT_H
|
||||
#define BACKENDS_UPDATES_ABSTRACT_H
|
||||
#ifndef COMMON_UPDATES_H
|
||||
#define COMMON_UPDATES_H
|
||||
|
||||
#if defined(USE_UPDATES)
|
||||
|
||||
@@ -85,18 +85,50 @@ public:
|
||||
*
|
||||
* @param interval The interval.
|
||||
*/
|
||||
virtual void setUpdateCheckInterval(UpdateInterval interval) {}
|
||||
virtual void setUpdateCheckInterval(int interval) {}
|
||||
|
||||
/**
|
||||
* Gets the update check interval.
|
||||
*
|
||||
* @return the update check interval.
|
||||
*/
|
||||
virtual UpdateInterval getUpdateCheckInterval() { return kUpdateIntervalNotSupported; }
|
||||
virtual int getUpdateCheckInterval() { return kUpdateIntervalNotSupported; }
|
||||
|
||||
/**
|
||||
* Gets last update check time
|
||||
*
|
||||
* @param t TimeDate struct to fill out
|
||||
* @return flag indicating success
|
||||
*/
|
||||
virtual bool getLastUpdateCheckTimeAndDate(TimeDate &t) { return false; }
|
||||
|
||||
/**
|
||||
* Returns list of supported uptate intervals.
|
||||
* Ending with '-1' which is not acceptable value.
|
||||
*
|
||||
* @return list of integer values representing update intervals in seconds.
|
||||
*/
|
||||
static const int *getUpdateIntervals();
|
||||
|
||||
/**
|
||||
* Returns string representation of a given interval.
|
||||
*
|
||||
* @param interval The interval.
|
||||
* @return pointer to localized string of given interval.
|
||||
*/
|
||||
static const char *updateIntervalToString(int interval);
|
||||
|
||||
/**
|
||||
* Rounds up the given interval to acceptable value.
|
||||
*
|
||||
* @param interval The interval.
|
||||
* @return rounded up interval
|
||||
*/
|
||||
static int normalizeInterval(int interval);
|
||||
};
|
||||
|
||||
} // End of namespace Common
|
||||
|
||||
#endif
|
||||
|
||||
#endif // BACKENDS_UPDATES_ABSTRACT_H
|
||||
#endif // COMMON_UPDATES_H
|
||||
|
||||
Vendored
+88
-55
@@ -1,8 +1,8 @@
|
||||
#! /bin/sh
|
||||
# Attempt to guess a canonical system name.
|
||||
# Copyright 1992-2014 Free Software Foundation, Inc.
|
||||
# Copyright 1992-2016 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2014-11-04'
|
||||
timestamp='2016-04-02'
|
||||
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
@@ -27,7 +27,7 @@ timestamp='2014-11-04'
|
||||
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
|
||||
#
|
||||
# You can get the latest version of this script from:
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
|
||||
#
|
||||
# Please send patches to <config-patches@gnu.org>.
|
||||
|
||||
@@ -50,7 +50,7 @@ version="\
|
||||
GNU config.guess ($timestamp)
|
||||
|
||||
Originally written by Per Bothner.
|
||||
Copyright 1992-2014 Free Software Foundation, Inc.
|
||||
Copyright 1992-2016 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@@ -168,20 +168,27 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
# Note: NetBSD doesn't particularly care about the vendor
|
||||
# portion of the name. We always set it to "unknown".
|
||||
sysctl="sysctl -n hw.machine_arch"
|
||||
UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
|
||||
/usr/sbin/$sysctl 2>/dev/null || echo unknown)`
|
||||
UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
|
||||
/sbin/$sysctl 2>/dev/null || \
|
||||
/usr/sbin/$sysctl 2>/dev/null || \
|
||||
echo unknown)`
|
||||
case "${UNAME_MACHINE_ARCH}" in
|
||||
armeb) machine=armeb-unknown ;;
|
||||
arm*) machine=arm-unknown ;;
|
||||
sh3el) machine=shl-unknown ;;
|
||||
sh3eb) machine=sh-unknown ;;
|
||||
sh5el) machine=sh5le-unknown ;;
|
||||
earmv*)
|
||||
arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
|
||||
endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
|
||||
machine=${arch}${endian}-unknown
|
||||
;;
|
||||
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
|
||||
esac
|
||||
# The Operating System including object format, if it has switched
|
||||
# to ELF recently, or will in the future.
|
||||
case "${UNAME_MACHINE_ARCH}" in
|
||||
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
|
||||
arm*|earm*|i386|m68k|ns32k|sh3*|sparc|vax)
|
||||
eval $set_cc_for_build
|
||||
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
|
||||
| grep -q __ELF__
|
||||
@@ -197,6 +204,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
os=netbsd
|
||||
;;
|
||||
esac
|
||||
# Determine ABI tags.
|
||||
case "${UNAME_MACHINE_ARCH}" in
|
||||
earm*)
|
||||
expr='s/^earmv[0-9]/-eabi/;s/eb$//'
|
||||
abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
|
||||
;;
|
||||
esac
|
||||
# The OS release
|
||||
# Debian GNU/NetBSD machines have a different userland, and
|
||||
# thus, need a distinct triplet. However, they do not need
|
||||
@@ -207,13 +221,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
release='-gnu'
|
||||
;;
|
||||
*)
|
||||
release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
||||
release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
|
||||
;;
|
||||
esac
|
||||
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
|
||||
# contains redundant information, the shorter form:
|
||||
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
|
||||
echo "${machine}-${os}${release}"
|
||||
echo "${machine}-${os}${release}${abi}"
|
||||
exit ;;
|
||||
*:Bitrig:*:*)
|
||||
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
|
||||
@@ -223,6 +237,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
|
||||
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:LibertyBSD:*:*)
|
||||
UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
|
||||
echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:ekkoBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
|
||||
exit ;;
|
||||
@@ -235,6 +253,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
*:MirBSD:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
|
||||
exit ;;
|
||||
*:Sortix:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-sortix
|
||||
exit ;;
|
||||
alpha:OSF1:*:*)
|
||||
case $UNAME_RELEASE in
|
||||
*4.0)
|
||||
@@ -251,42 +272,42 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
|
||||
case "$ALPHA_CPU_TYPE" in
|
||||
"EV4 (21064)")
|
||||
UNAME_MACHINE="alpha" ;;
|
||||
UNAME_MACHINE=alpha ;;
|
||||
"EV4.5 (21064)")
|
||||
UNAME_MACHINE="alpha" ;;
|
||||
UNAME_MACHINE=alpha ;;
|
||||
"LCA4 (21066/21068)")
|
||||
UNAME_MACHINE="alpha" ;;
|
||||
UNAME_MACHINE=alpha ;;
|
||||
"EV5 (21164)")
|
||||
UNAME_MACHINE="alphaev5" ;;
|
||||
UNAME_MACHINE=alphaev5 ;;
|
||||
"EV5.6 (21164A)")
|
||||
UNAME_MACHINE="alphaev56" ;;
|
||||
UNAME_MACHINE=alphaev56 ;;
|
||||
"EV5.6 (21164PC)")
|
||||
UNAME_MACHINE="alphapca56" ;;
|
||||
UNAME_MACHINE=alphapca56 ;;
|
||||
"EV5.7 (21164PC)")
|
||||
UNAME_MACHINE="alphapca57" ;;
|
||||
UNAME_MACHINE=alphapca57 ;;
|
||||
"EV6 (21264)")
|
||||
UNAME_MACHINE="alphaev6" ;;
|
||||
UNAME_MACHINE=alphaev6 ;;
|
||||
"EV6.7 (21264A)")
|
||||
UNAME_MACHINE="alphaev67" ;;
|
||||
UNAME_MACHINE=alphaev67 ;;
|
||||
"EV6.8CB (21264C)")
|
||||
UNAME_MACHINE="alphaev68" ;;
|
||||
UNAME_MACHINE=alphaev68 ;;
|
||||
"EV6.8AL (21264B)")
|
||||
UNAME_MACHINE="alphaev68" ;;
|
||||
UNAME_MACHINE=alphaev68 ;;
|
||||
"EV6.8CX (21264D)")
|
||||
UNAME_MACHINE="alphaev68" ;;
|
||||
UNAME_MACHINE=alphaev68 ;;
|
||||
"EV6.9A (21264/EV69A)")
|
||||
UNAME_MACHINE="alphaev69" ;;
|
||||
UNAME_MACHINE=alphaev69 ;;
|
||||
"EV7 (21364)")
|
||||
UNAME_MACHINE="alphaev7" ;;
|
||||
UNAME_MACHINE=alphaev7 ;;
|
||||
"EV7.9 (21364A)")
|
||||
UNAME_MACHINE="alphaev79" ;;
|
||||
UNAME_MACHINE=alphaev79 ;;
|
||||
esac
|
||||
# A Pn.n version is a patched version.
|
||||
# A Vn.n version is a released version.
|
||||
# A Tn.n version is a released field test version.
|
||||
# A Xn.n version is an unreleased experimental baselevel.
|
||||
# 1.2 uses "1.2" for uname -r.
|
||||
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
||||
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
|
||||
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
|
||||
exitcode=$?
|
||||
trap '' 0
|
||||
@@ -359,16 +380,16 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
exit ;;
|
||||
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
|
||||
eval $set_cc_for_build
|
||||
SUN_ARCH="i386"
|
||||
SUN_ARCH=i386
|
||||
# If there is a compiler, see if it is configured for 64-bit objects.
|
||||
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
|
||||
# This test works for both compilers.
|
||||
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
|
||||
if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
|
||||
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_64BIT_ARCH >/dev/null
|
||||
then
|
||||
SUN_ARCH="x86_64"
|
||||
SUN_ARCH=x86_64
|
||||
fi
|
||||
fi
|
||||
echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
|
||||
@@ -393,7 +414,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
||||
exit ;;
|
||||
sun*:*:4.2BSD:*)
|
||||
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
|
||||
test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
|
||||
test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3
|
||||
case "`/bin/arch`" in
|
||||
sun3)
|
||||
echo m68k-sun-sunos${UNAME_RELEASE}
|
||||
@@ -618,13 +639,13 @@ EOF
|
||||
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
|
||||
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
|
||||
case "${sc_cpu_version}" in
|
||||
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
|
||||
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
|
||||
523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
|
||||
528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
|
||||
532) # CPU_PA_RISC2_0
|
||||
case "${sc_kernel_bits}" in
|
||||
32) HP_ARCH="hppa2.0n" ;;
|
||||
64) HP_ARCH="hppa2.0w" ;;
|
||||
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
|
||||
32) HP_ARCH=hppa2.0n ;;
|
||||
64) HP_ARCH=hppa2.0w ;;
|
||||
'') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
|
||||
esac ;;
|
||||
esac
|
||||
fi
|
||||
@@ -663,11 +684,11 @@ EOF
|
||||
exit (0);
|
||||
}
|
||||
EOF
|
||||
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
|
||||
(CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
|
||||
test -z "$HP_ARCH" && HP_ARCH=hppa
|
||||
fi ;;
|
||||
esac
|
||||
if [ ${HP_ARCH} = "hppa2.0w" ]
|
||||
if [ ${HP_ARCH} = hppa2.0w ]
|
||||
then
|
||||
eval $set_cc_for_build
|
||||
|
||||
@@ -680,12 +701,12 @@ EOF
|
||||
# $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
|
||||
# => hppa64-hp-hpux11.23
|
||||
|
||||
if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
|
||||
if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
|
||||
grep -q __LP64__
|
||||
then
|
||||
HP_ARCH="hppa2.0w"
|
||||
HP_ARCH=hppa2.0w
|
||||
else
|
||||
HP_ARCH="hppa64"
|
||||
HP_ARCH=hppa64
|
||||
fi
|
||||
fi
|
||||
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
|
||||
@@ -790,14 +811,14 @@ EOF
|
||||
echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
|
||||
exit ;;
|
||||
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
|
||||
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
|
||||
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
|
||||
FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
|
||||
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
|
||||
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||
exit ;;
|
||||
5000:UNIX_System_V:4.*:*)
|
||||
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
|
||||
FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
|
||||
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
|
||||
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
|
||||
exit ;;
|
||||
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
|
||||
@@ -879,7 +900,7 @@ EOF
|
||||
exit ;;
|
||||
*:GNU/*:*:*)
|
||||
# other systems with GNU libc and userland
|
||||
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
|
||||
echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
|
||||
exit ;;
|
||||
i*86:Minix:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-minix
|
||||
@@ -902,7 +923,7 @@ EOF
|
||||
EV68*) UNAME_MACHINE=alphaev68 ;;
|
||||
esac
|
||||
objdump --private-headers /bin/sh | grep -q ld.so.1
|
||||
if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
|
||||
if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
arc:Linux:*:* | arceb:Linux:*:*)
|
||||
@@ -933,6 +954,9 @@ EOF
|
||||
crisv32:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
|
||||
exit ;;
|
||||
e2k:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
frv:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
@@ -945,6 +969,9 @@ EOF
|
||||
ia64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
k1om:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
m32r*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
exit ;;
|
||||
@@ -1021,7 +1048,7 @@ EOF
|
||||
echo ${UNAME_MACHINE}-dec-linux-${LIBC}
|
||||
exit ;;
|
||||
x86_64:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
echo ${UNAME_MACHINE}-pc-linux-${LIBC}
|
||||
exit ;;
|
||||
xtensa*:Linux:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||
@@ -1100,7 +1127,7 @@ EOF
|
||||
# uname -m prints for DJGPP always 'pc', but it prints nothing about
|
||||
# the processor, so we play safe by assuming i586.
|
||||
# Note: whatever this is, it MUST be the same as what config.sub
|
||||
# prints for the "djgpp" host, or else GDB configury will decide that
|
||||
# prints for the "djgpp" host, or else GDB configure will decide that
|
||||
# this is a cross-build.
|
||||
echo i586-pc-msdosdjgpp
|
||||
exit ;;
|
||||
@@ -1249,6 +1276,9 @@ EOF
|
||||
SX-8R:SUPER-UX:*:*)
|
||||
echo sx8r-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
SX-ACE:SUPER-UX:*:*)
|
||||
echo sxace-nec-superux${UNAME_RELEASE}
|
||||
exit ;;
|
||||
Power*:Rhapsody:*:*)
|
||||
echo powerpc-apple-rhapsody${UNAME_RELEASE}
|
||||
exit ;;
|
||||
@@ -1262,9 +1292,9 @@ EOF
|
||||
UNAME_PROCESSOR=powerpc
|
||||
fi
|
||||
if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
|
||||
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
|
||||
if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
|
||||
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
|
||||
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
|
||||
grep IS_64BIT_ARCH >/dev/null
|
||||
then
|
||||
case $UNAME_PROCESSOR in
|
||||
@@ -1286,7 +1316,7 @@ EOF
|
||||
exit ;;
|
||||
*:procnto*:*:* | *:QNX:[0123456789]*:*)
|
||||
UNAME_PROCESSOR=`uname -p`
|
||||
if test "$UNAME_PROCESSOR" = "x86"; then
|
||||
if test "$UNAME_PROCESSOR" = x86; then
|
||||
UNAME_PROCESSOR=i386
|
||||
UNAME_MACHINE=pc
|
||||
fi
|
||||
@@ -1317,7 +1347,7 @@ EOF
|
||||
# "uname -m" is not consistent, so use $cputype instead. 386
|
||||
# is converted to i386 for consistency with other x86
|
||||
# operating systems.
|
||||
if test "$cputype" = "386"; then
|
||||
if test "$cputype" = 386; then
|
||||
UNAME_MACHINE=i386
|
||||
else
|
||||
UNAME_MACHINE="$cputype"
|
||||
@@ -1359,7 +1389,7 @@ EOF
|
||||
echo i386-pc-xenix
|
||||
exit ;;
|
||||
i*86:skyos:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
|
||||
echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'`
|
||||
exit ;;
|
||||
i*86:rdos:*:*)
|
||||
echo ${UNAME_MACHINE}-pc-rdos
|
||||
@@ -1370,6 +1400,9 @@ EOF
|
||||
x86_64:VMkernel:*:*)
|
||||
echo ${UNAME_MACHINE}-unknown-esx
|
||||
exit ;;
|
||||
amd64:Isilon\ OneFS:*:*)
|
||||
echo x86_64-unknown-onefs
|
||||
exit ;;
|
||||
esac
|
||||
|
||||
cat >&2 <<EOF
|
||||
@@ -1379,9 +1412,9 @@ This script, last modified $timestamp, has failed to recognize
|
||||
the operating system you are using. It is advised that you
|
||||
download the most up to date version of the config scripts from
|
||||
|
||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
|
||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
|
||||
and
|
||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
|
||||
http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
|
||||
|
||||
If the version you run ($0) is already up to date, please
|
||||
send the following data and any information you think might be
|
||||
|
||||
Vendored
+23
-15
@@ -1,8 +1,8 @@
|
||||
#! /bin/sh
|
||||
# Configuration validation subroutine script.
|
||||
# Copyright 1992-2014 Free Software Foundation, Inc.
|
||||
# Copyright 1992-2016 Free Software Foundation, Inc.
|
||||
|
||||
timestamp='2014-12-03'
|
||||
timestamp='2016-03-30'
|
||||
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
@@ -33,7 +33,7 @@ timestamp='2014-12-03'
|
||||
# Otherwise, we print the canonical config type on stdout and succeed.
|
||||
|
||||
# You can get the latest version of this script from:
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
|
||||
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
|
||||
|
||||
# This file is supposed to be the same for all GNU packages
|
||||
# and recognize all the CPU types, system types and aliases
|
||||
@@ -53,8 +53,7 @@ timestamp='2014-12-03'
|
||||
me=`echo "$0" | sed -e 's,.*/,,'`
|
||||
|
||||
usage="\
|
||||
Usage: $0 [OPTION] CPU-MFR-OPSYS
|
||||
$0 [OPTION] ALIAS
|
||||
Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
|
||||
|
||||
Canonicalize a configuration name.
|
||||
|
||||
@@ -68,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>."
|
||||
version="\
|
||||
GNU config.sub ($timestamp)
|
||||
|
||||
Copyright 1992-2014 Free Software Foundation, Inc.
|
||||
Copyright 1992-2016 Free Software Foundation, Inc.
|
||||
|
||||
This is free software; see the source for copying conditions. There is NO
|
||||
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
|
||||
@@ -117,7 +116,7 @@ maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
|
||||
case $maybe_os in
|
||||
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
|
||||
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
|
||||
knetbsd*-gnu* | netbsd*-gnu* | \
|
||||
knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
|
||||
kopensolaris*-gnu* | \
|
||||
storm-chaos* | os2-emx* | rtmk-nova*)
|
||||
os=-$maybe_os
|
||||
@@ -255,12 +254,13 @@ case $basic_machine in
|
||||
| arc | arceb \
|
||||
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
|
||||
| avr | avr32 \
|
||||
| ba \
|
||||
| be32 | be64 \
|
||||
| bfin \
|
||||
| c4x | c8051 | clipper \
|
||||
| d10v | d30v | dlx | dsp16xx \
|
||||
| epiphany \
|
||||
| fido | fr30 | frv \
|
||||
| e2k | epiphany \
|
||||
| fido | fr30 | frv | ft32 \
|
||||
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
|
||||
| hexagon \
|
||||
| i370 | i860 | i960 | ia64 \
|
||||
@@ -305,7 +305,7 @@ case $basic_machine in
|
||||
| riscv32 | riscv64 \
|
||||
| rl78 | rx \
|
||||
| score \
|
||||
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
|
||||
| sh64 | sh64le \
|
||||
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
|
||||
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
|
||||
@@ -376,12 +376,13 @@ case $basic_machine in
|
||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
|
||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||
| avr-* | avr32-* \
|
||||
| ba-* \
|
||||
| be32-* | be64-* \
|
||||
| bfin-* | bs2000-* \
|
||||
| c[123]* | c30-* | [cjt]90-* | c4x-* \
|
||||
| c8051-* | clipper-* | craynv-* | cydra-* \
|
||||
| d10v-* | d30v-* | dlx-* \
|
||||
| elxsi-* \
|
||||
| e2k-* | elxsi-* \
|
||||
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
|
||||
| h8300-* | h8500-* \
|
||||
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
|
||||
@@ -428,12 +429,13 @@ case $basic_machine in
|
||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
|
||||
| pyramid-* \
|
||||
| riscv32-* | riscv64-* \
|
||||
| rl78-* | romp-* | rs6000-* | rx-* \
|
||||
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
||||
| sparclite-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
|
||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
|
||||
| tahoe-* \
|
||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||
| tile*-* \
|
||||
@@ -518,6 +520,9 @@ case $basic_machine in
|
||||
basic_machine=i386-pc
|
||||
os=-aros
|
||||
;;
|
||||
asmjs)
|
||||
basic_machine=asmjs-unknown
|
||||
;;
|
||||
aux)
|
||||
basic_machine=m68k-apple
|
||||
os=-aux
|
||||
@@ -1373,11 +1378,11 @@ case $os in
|
||||
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
|
||||
| -sym* | -kopensolaris* | -plan9* \
|
||||
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
|
||||
| -aos* | -aros* \
|
||||
| -aos* | -aros* | -cloudabi* | -sortix* \
|
||||
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
|
||||
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
|
||||
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
|
||||
| -bitrig* | -openbsd* | -solidbsd* \
|
||||
| -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
|
||||
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
|
||||
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
|
||||
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
|
||||
@@ -1393,7 +1398,8 @@ case $os in
|
||||
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
|
||||
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
|
||||
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
|
||||
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
|
||||
| -onefs* | -tirtos*)
|
||||
# Remember, each alternative MUST END IN *, to match a version number.
|
||||
;;
|
||||
-qnx*)
|
||||
@@ -1525,6 +1531,8 @@ case $os in
|
||||
;;
|
||||
-nacl*)
|
||||
;;
|
||||
-ios)
|
||||
;;
|
||||
-none)
|
||||
;;
|
||||
*)
|
||||
|
||||
@@ -132,6 +132,7 @@ _timidity=no
|
||||
_zlib=auto
|
||||
_mpeg2=auto
|
||||
_sparkle=auto
|
||||
_osxdockplugin=auto
|
||||
_jpeg=auto
|
||||
_png=auto
|
||||
_theoradec=auto
|
||||
@@ -165,10 +166,12 @@ _bink=yes
|
||||
_vkeybd=no
|
||||
_keymapper=no
|
||||
_eventrec=no
|
||||
# GUI translation options
|
||||
_translation=yes
|
||||
# Default platform settings
|
||||
_backend=sdl
|
||||
_16bit=auto
|
||||
_highres=auto
|
||||
_savegame_timestamp=auto
|
||||
_dynamic_modules=no
|
||||
_elf_loader=no
|
||||
@@ -188,6 +191,8 @@ _stagingpath="staging"
|
||||
_win32path="C:/residualvm"
|
||||
_amigaospath="Games:ResidualVM"
|
||||
_staticlibpath=
|
||||
_xcodetoolspath=
|
||||
_sparklepath=
|
||||
_sdlconfig=sdl-config
|
||||
_freetypeconfig=freetype-config
|
||||
_sdlpath="$PATH"
|
||||
@@ -208,6 +213,7 @@ add_feature 16bit "16bit color" "_16bit"
|
||||
add_feature faad "libfaad" "_faad"
|
||||
add_feature flac "FLAC" "_flac"
|
||||
add_feature freetype2 "FreeType2" "_freetype2"
|
||||
add_feature highres "high resolution" "_highres"
|
||||
add_feature mad "MAD" "_mad"
|
||||
add_feature jpeg "JPEG" "_jpeg"
|
||||
add_feature png "PNG" "_png"
|
||||
@@ -443,7 +449,7 @@ get_system_exe_extension() {
|
||||
arm-riscos)
|
||||
_exeext=",ff8"
|
||||
;;
|
||||
dreamcast | ds | gamecube | n64 | ps2 | psp | wii)
|
||||
3ds | dreamcast | ds | gamecube | n64 | ps2 | psp | wii)
|
||||
_exeext=".elf"
|
||||
;;
|
||||
gph-linux)
|
||||
@@ -600,7 +606,7 @@ engine_enable() {
|
||||
parent=`get_subengine_parent ${engine}`
|
||||
if test `get_engine_build ${parent}` = "no" ; then
|
||||
set_var _engine_${parent}_build "yes"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$opt" = "static" -o "$opt" = "dynamic" -o "$opt" = "yes" ; then
|
||||
@@ -811,12 +817,6 @@ get_subengines_build_string() {
|
||||
echo "$subengine_string"
|
||||
}
|
||||
|
||||
#
|
||||
# Greet user
|
||||
#
|
||||
echo "Running ResidualVM configure..."
|
||||
echo "Configure run on" `date` > $TMPLOG
|
||||
|
||||
#
|
||||
# Check any parameters we received
|
||||
#
|
||||
@@ -877,7 +877,7 @@ Game engines:
|
||||
--disable-all-engines disable all engines
|
||||
--enable-engine=<engine name>[,<engine name>...] enable engine(s) listed
|
||||
--disable-engine=<engine name>[,<engine name>...] disable engine(s) listed
|
||||
--enable-engine-static=<engine name>[,<engine name>...]
|
||||
--enable-engine-static=<engine name>[,<engine name>...]
|
||||
enable engine(s) listed as static builtin (when plugins are enabled)
|
||||
--enable-engine-dynamic=<engine name>[,<engine name>...]
|
||||
enable engine(s) listed as dynamic plugin (when plugins are enabled)
|
||||
@@ -953,8 +953,10 @@ Optional Libraries:
|
||||
installed (optional)
|
||||
--disable-fluidsynth disable fluidsynth MIDI driver [autodetect]
|
||||
|
||||
--with-sparkle-prefix=DIR Prefix where sparkle is installed (Mac OS X only - optional)
|
||||
--disable-sparkle disable sparkle automatic update support [Mac OS X only - autodetect]
|
||||
--with-sparkle-prefix=DIR Prefix where sparkle is installed (OS X/Windows only - optional)
|
||||
--disable-sparkle disable sparkle automatic update support [OS X/Windows only - autodetect]
|
||||
|
||||
--disable-osx-dock-plugin disable the NSDockTilePlugin support [Mac OS X only - autodetect]
|
||||
|
||||
--with-sdl-prefix=DIR Prefix where the sdl-config script is
|
||||
installed (optional)
|
||||
@@ -993,9 +995,25 @@ EOF
|
||||
fi
|
||||
done # for parm in ...
|
||||
|
||||
|
||||
#
|
||||
# If we're not showing help, greet the user and start the log file
|
||||
#
|
||||
echo "Running ResidualVM configure..."
|
||||
echo "Configure run on" `date` > $TMPLOG
|
||||
cat >> $TMPLOG <<EOF
|
||||
Invocation command line was:
|
||||
$0 $@
|
||||
Saved environment variables:
|
||||
LDFLAGS="$SAVED_LDFLAGS" CXX="$SAVED_CXX" CXXFLAGS="$SAVED_CXXFLAGS" CPPFLAGS="$SAVED_CPPFLAGS" ASFLAGS="$SAVED_ASFLAGS" WINDRESFLAGS="$SAVED_WINDRESFLAGS" SDL_CONFIG="$SAVED_SDL_CONFIG"
|
||||
EOF
|
||||
|
||||
|
||||
for ac_option in $@; do
|
||||
case "$ac_option" in
|
||||
# --disable-16bit) _16bit=no ;; #ResidualVM: not supported
|
||||
# --enable-highres) _highres=yes ;; #ResidualVM: not supported
|
||||
# --disable-highres) _highres=no ;; #ResidualVM: not supported
|
||||
--disable-savegame-timestamp) _savegame_timestamp=no ;;
|
||||
# --disable-scalers) _build_scalers=no ;; #ResidualVM: not supported
|
||||
# --disable-hq-scalers) _build_hq_scalers=no ;; #ResidualVM: not supported
|
||||
@@ -1019,6 +1037,8 @@ for ac_option in $@; do
|
||||
--disable-zlib) _zlib=no ;;
|
||||
--enable-sparkle) _sparkle=yes ;;
|
||||
--disable-sparkle) _sparkle=no ;;
|
||||
--enable-osx-dock-plugin) _osxdockplugin=yes;;
|
||||
--disable-osx-dock-plugin) _osxdockplugin=no;;
|
||||
--enable-nasm) _nasm=yes ;;
|
||||
--disable-nasm) _nasm=no ;;
|
||||
--enable-mpeg2) _mpeg2=yes ;;
|
||||
@@ -1141,8 +1161,7 @@ for ac_option in $@; do
|
||||
;;
|
||||
--with-sparkle-prefix=*)
|
||||
arg=`echo $ac_option | cut -d '=' -f 2`
|
||||
SPARKLE_CFLAGS="-F$arg"
|
||||
SPARKLE_LIBS="-F$arg"
|
||||
_sparklepath=$arg
|
||||
;;
|
||||
--with-readline-prefix=*)
|
||||
arg=`echo $ac_option | cut -d '=' -f 2`
|
||||
@@ -1225,6 +1244,9 @@ for ac_option in $@; do
|
||||
--with-staticlib-prefix=*)
|
||||
_staticlibpath=`echo $ac_option | cut -d '=' -f 2`
|
||||
;;
|
||||
--with-xcodetools-path=*)
|
||||
_xcodetoolspath=`echo $ac_option | cut -d '=' -f 2`
|
||||
;;
|
||||
--host=*)
|
||||
_host=`echo $ac_option | cut -d '=' -f 2`
|
||||
;;
|
||||
@@ -1289,6 +1311,11 @@ get_system_exe_extension $guessed_host
|
||||
NATIVEEXEEXT=$_exeext
|
||||
|
||||
case $_host in
|
||||
3ds)
|
||||
_host_os=3ds
|
||||
_host_cpu=arm
|
||||
_host_alias=arm-none-eabi
|
||||
;;
|
||||
android | android-arm | android-v7a | android-arm-v7a | ouya)
|
||||
_host_os=android
|
||||
_host_cpu=arm
|
||||
@@ -1304,6 +1331,26 @@ android-x86)
|
||||
_host_cpu=i686
|
||||
_host_alias=i686-linux-android
|
||||
;;
|
||||
androidsdl-armeabi | androidsdl-armeabi-v7a)
|
||||
_host_os=androidsdl
|
||||
_host_cpu=arm
|
||||
_host_alias=arm-linux-androideabi
|
||||
;;
|
||||
androidsdl-arm64-v8a)
|
||||
_host_os=androidsdl
|
||||
_host_cpu=aarch64
|
||||
_host_alias=aarch64-linux-android
|
||||
;;
|
||||
androidsdl-mips)
|
||||
_host_os=androidsdl
|
||||
_host_cpu=mipsel
|
||||
_host_alias=mipsel-linux-android
|
||||
;;
|
||||
androidsdl-x86)
|
||||
_host_os=androidsdl
|
||||
_host_cpu=i686
|
||||
_host_alias=i686-linux-android
|
||||
;;
|
||||
arm-riscos)
|
||||
_host_os=riscos
|
||||
_host_cpu=arm
|
||||
@@ -1313,7 +1360,7 @@ raspberrypi)
|
||||
_host_cpu=arm
|
||||
# This tuple is the one used by the official Rpi toolchain.
|
||||
# It may change in the future.
|
||||
_host_alias=bcm2708hardfp
|
||||
_host_alias=arm-linux-gnueabihf
|
||||
;;
|
||||
caanoo)
|
||||
_host_os=gph-linux
|
||||
@@ -1570,7 +1617,7 @@ android)
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
ds | gamecube | wii)
|
||||
3ds | ds | gamecube | wii)
|
||||
if test -z "$DEVKITPRO"; then
|
||||
echo "Please set DEVKITPRO in your environment. export DEVKITPRO=<path to devkitPRO>"
|
||||
exit 1
|
||||
@@ -1826,7 +1873,7 @@ if test "$have_gcc" = yes ; then
|
||||
case $_host_os in
|
||||
# newlib-based system include files suppress non-C89 function
|
||||
# declarations under __STRICT_ANSI__
|
||||
amigaos* | android | dreamcast | ds | gamecube | mingw* | n64 | psp | ps2 | ps3 | tizen | wii | wince )
|
||||
3ds | amigaos* | android | androidsdl | dreamcast | ds | gamecube | mingw* | n64 | psp | ps2 | ps3 | tizen | wii | wince )
|
||||
;;
|
||||
*)
|
||||
append_var CXXFLAGS "-ansi"
|
||||
@@ -1862,7 +1909,7 @@ echo $_use_cxx11
|
||||
# However, some platforms use GNU extensions in system header files, so
|
||||
# for these we must not use -pedantic.
|
||||
case $_host_os in
|
||||
android | gamecube | psp | tizen | wii | webos)
|
||||
android | androidsdl | gamecube | psp | tizen | wii | webos)
|
||||
;;
|
||||
*)
|
||||
# ICC does not support pedantic, while GCC and clang do.
|
||||
@@ -2126,6 +2173,27 @@ esac
|
||||
echo_n "Checking hosttype... "
|
||||
echo $_host_os
|
||||
case $_host_os in
|
||||
3ds)
|
||||
_optimization_level=-O2
|
||||
append_var DEFINES "-D__3DS__"
|
||||
append_var DEFINES "-DARM"
|
||||
append_var DEFINES "-DARM11"
|
||||
append_var CXXFLAGS "-march=armv6k"
|
||||
append_var CXXFLAGS "-mtune=mpcore"
|
||||
append_var CXXFLAGS "-mword-relocations"
|
||||
append_var CXXFLAGS "-mfloat-abi=hard"
|
||||
append_var CXXFLAGS "-ffunction-sections"
|
||||
append_var CXXFLAGS "-fomit-frame-pointer"
|
||||
append_var CXXFLAGS "-I$DEVKITPRO/libctru/include"
|
||||
append_var CXXFLAGS "-I$DEVKITPRO/portlibs/3ds/include"
|
||||
if test "$_dynamic_modules" = no ; then
|
||||
append_var LDFLAGS "-Wl,--gc-sections"
|
||||
else
|
||||
append_var LDFLAGS "-Wl,--no-gc-sections"
|
||||
fi
|
||||
append_var LDFLAGS "-L$DEVKITPRO/portlibs/3ds/lib"
|
||||
append_var LIBS "-lcitro3d -lctru"
|
||||
;;
|
||||
amigaos*)
|
||||
append_var LDFLAGS "-Wl,--export-dynamic"
|
||||
append_var LDFLAGS "-L/sdk/local/newlib/lib"
|
||||
@@ -2280,7 +2348,7 @@ case $_host_os in
|
||||
|
||||
LDFLAGS="-L${macport_prefix}/lib $LDFLAGS"
|
||||
CXXFLAGS="-I${macport_prefix}/include $CXXFLAGS"
|
||||
|
||||
|
||||
if test -z "$_staticlibpath"; then
|
||||
_staticlibpath=${macport_prefix}
|
||||
echo "Set staticlib-prefix to ${_staticlibpath}"
|
||||
@@ -2342,6 +2410,17 @@ case $_host_os in
|
||||
echo "Could not determine prefix for static libraries"
|
||||
fi
|
||||
fi
|
||||
|
||||
# If _xcodetoolspath is not set yet use xcode-select to get the path
|
||||
if test -z "$_xcodetoolspath"; then
|
||||
_xcodetoolspath=`xcode-select -print-path`/Tools
|
||||
if test -d "$_xcodetoolspath"; then
|
||||
echo "Set xcodetools-path to ${_xcodetoolspath}"
|
||||
else
|
||||
_xcodetoolspath=
|
||||
echo "Could not determine path for Xcode Tools"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
dreamcast)
|
||||
append_var DEFINES "-D__DC__"
|
||||
@@ -2435,6 +2514,10 @@ case $_host_os in
|
||||
mint*)
|
||||
append_var DEFINES "-DSYSTEM_NOT_SUPPORTING_D_TYPE"
|
||||
;;
|
||||
msys)
|
||||
echo ERROR: Using the MSYS shell in msys mode is not supported. Please use the MSYS shell in mingw mode instead.
|
||||
exit 1
|
||||
;;
|
||||
n64)
|
||||
append_var DEFINES "-D__N64__"
|
||||
append_var DEFINES "-DLIMIT_FPS"
|
||||
@@ -2550,6 +2633,18 @@ if test -n "$_host"; then
|
||||
# Cross-compiling mode - add your target here if needed
|
||||
echo "Cross-compiling to $_host"
|
||||
case "$_host" in
|
||||
3ds)
|
||||
append_var DEFINES "-DDISABLE_FANCY_THEMES"
|
||||
append_var DEFINES "-DDISABLE_SID"
|
||||
append_var DEFINES "-DDISABLE_NES_APU"
|
||||
_backend="3ds"
|
||||
_build_scalers=no
|
||||
_vkeybd=yes
|
||||
_mt32emu=no
|
||||
# Should use Tremor instead of Vorbis
|
||||
_vorbis=no
|
||||
_port_mk="backends/platform/3ds/3ds.mk"
|
||||
;;
|
||||
android | android-arm | android-v7a | android-arm-v7a | android-mips | android-x86 | ouya)
|
||||
# we link a .so as default
|
||||
append_var LDFLAGS "-shared"
|
||||
@@ -2563,6 +2658,15 @@ if test -n "$_host"; then
|
||||
_mt32emu=no
|
||||
_timidity=no
|
||||
;;
|
||||
androidsdl | androidsdl-armeabi | androidsdl-armeabi-v7a | androidsdl-mips | androidsdl-x86 | androidsdl-arm64-v8a)
|
||||
DEFINES="$DEFINES -DANDROIDSDL"
|
||||
_unix=yes
|
||||
_seq_midi=no
|
||||
_mt32emu=no
|
||||
_timidity=no
|
||||
_backend="androidsdl"
|
||||
_port_mk="backends/platform/androidsdl/androidsdl.mk"
|
||||
;;
|
||||
arm-linux|arm*-linux-gnueabi|arm-*-linux)
|
||||
;;
|
||||
arm-riscos|linupy)
|
||||
@@ -2601,7 +2705,7 @@ if test -n "$_host"; then
|
||||
_mt32emu=no
|
||||
_optimization_level=-O3
|
||||
# Disable alsa midi to get the port build on OpenDingux toolchain
|
||||
_alsa=no
|
||||
_alsa=no
|
||||
_vkeybd=yes
|
||||
_build_hq_scalers=no
|
||||
_keymapper=no
|
||||
@@ -2628,14 +2732,15 @@ if test -n "$_host"; then
|
||||
_eventrec=no
|
||||
_build_scalers=no
|
||||
_build_hq_scalers=no
|
||||
# We prefer SDL2 on the Raspberry Pi: acceleration now depends on it
|
||||
# We prefer SDL2 on the Raspberry Pi: acceleration now depends on it
|
||||
# since SDL2 manages dispmanx/GLES2 very well internally.
|
||||
# SDL1 is bit-rotten on this platform.
|
||||
_sdlconfig=sdl2-config
|
||||
# OpenGL(ES) support is mature enough as to be the best option on
|
||||
# OpenGL ES support is mature enough as to be the best option on
|
||||
# the Raspberry Pi, so it's enabled by default.
|
||||
_opengl=yes
|
||||
_opengles=yes
|
||||
# The Raspberry Pi always supports OpenGL ES 2.0 contexts, thus we
|
||||
# take advantage of those.
|
||||
_opengl_mode=gles2
|
||||
;;
|
||||
dreamcast)
|
||||
append_var DEFINES "-DDISABLE_DEFAULT_SAVEFILEMANAGER"
|
||||
@@ -2656,7 +2761,11 @@ if test -n "$_host"; then
|
||||
_build_scalers=no
|
||||
_mad=yes
|
||||
_zlib=yes
|
||||
add_line_to_config_mk 'ronindir = /usr/local/ronin'
|
||||
if test -z "$RONINDIR"; then
|
||||
add_line_to_config_mk "ronindir := /usr/local/ronin"
|
||||
else
|
||||
add_line_to_config_mk "ronindir := $RONINDIR"
|
||||
fi
|
||||
_port_mk="backends/platform/dc/dreamcast.mk"
|
||||
;;
|
||||
ds)
|
||||
@@ -2689,22 +2798,22 @@ if test -n "$_host"; then
|
||||
add_line_to_config_h "/* #define DEBUG_WII_GDB */"
|
||||
add_line_to_config_h "#define USE_WII_DI"
|
||||
;;
|
||||
gcw0)
|
||||
append_var DEFINES "-DDINGUX -DGCW0"
|
||||
gcw0)
|
||||
_sysroot=`$CXX --print-sysroot`
|
||||
_sdlpath=$_sysroot/usr/bin
|
||||
append_var DEFINES "-DDINGUX -DGCW0 -DGUI_ONLY_FULLSCREEN"
|
||||
append_var DEFINES "-DREDUCE_MEMORY_USAGE"
|
||||
append_var CXXFLAGS "-mips32"
|
||||
_backend="dingux"
|
||||
_mt32emu=no
|
||||
_optimization_level=-O3
|
||||
# Disable alsa midi to get the port build on OpenDingux toolchain
|
||||
_alsa=no
|
||||
_vkeybd=yes
|
||||
_build_hq_scalers=no
|
||||
_keymapper=yes
|
||||
# Force disable vorbis on dingux, it has terrible performance compared to tremor
|
||||
_vorbis=no
|
||||
# Force disable seq on dingux, no way to use it and it would get enabled by default with configure
|
||||
_mt32emu=no
|
||||
_seq_midi=no
|
||||
_timidity=no
|
||||
_build_scalers=no
|
||||
_optimization_level=-O3
|
||||
_vkeybd=yes
|
||||
_keymapper=yes
|
||||
_vorbis=no
|
||||
_port_mk="backends/platform/dingux/dingux.mk"
|
||||
;;
|
||||
gp2x)
|
||||
@@ -2746,11 +2855,8 @@ if test -n "$_host"; then
|
||||
;;
|
||||
ios7)
|
||||
append_var DEFINES "-DIPHONE"
|
||||
append_var CFLAGS "-Wno-shift-count-overflow"
|
||||
append_var CXXFLAGS "-Wno-shift-count-overflow"
|
||||
_backend="ios7"
|
||||
_build_scalers=no
|
||||
_mt32emu=no
|
||||
_seq_midi=no
|
||||
_timidity=no
|
||||
;;
|
||||
@@ -2767,7 +2873,7 @@ if test -n "$_host"; then
|
||||
append_var INCLUDES "-I/usr/X11R6/include"
|
||||
append_var LIBS "-lX11"
|
||||
append_var LIBS "-L/usr/lib"
|
||||
|
||||
|
||||
_backend="maemo"
|
||||
_vkeybd=yes
|
||||
_keymapper=yes
|
||||
@@ -2960,6 +3066,8 @@ if test -n "$_host"; then
|
||||
_mt32emu=no
|
||||
_timidity=no
|
||||
_vkeybd=yes
|
||||
# Tizen relies on the OpenGL ES output thus we always enable it.
|
||||
_opengl_mode=gles
|
||||
;;
|
||||
webos)
|
||||
_backend="webos"
|
||||
@@ -3005,12 +3113,16 @@ fi
|
||||
# Backend related stuff
|
||||
#
|
||||
case $_backend in
|
||||
3ds)
|
||||
;;
|
||||
android)
|
||||
append_var DEFINES "-DREDUCE_MEMORY_USAGE"
|
||||
append_var CXXFLAGS "-Wa,--noexecstack"
|
||||
append_var LDFLAGS "-Wl,-z,noexecstack"
|
||||
append_var INCLUDES "-I$ANDROID_NDK/sources/cxx-stl/system/include"
|
||||
;;
|
||||
androidsdl)
|
||||
;;
|
||||
dc)
|
||||
append_var INCLUDES '-I$(srcdir)/backends/platform/dc'
|
||||
append_var INCLUDES '-isystem $(ronindir)/include'
|
||||
@@ -3107,6 +3219,8 @@ case $_backend in
|
||||
append_var LDFLAGS "-shared"
|
||||
append_var LDFLAGS "-fpic"
|
||||
;;
|
||||
sdl)
|
||||
;;
|
||||
tizen)
|
||||
# dirent.h not available. NONSTANDARD_PORT==ensure portdefs.h is included
|
||||
append_var DEFINES "-DTIZEN -DDISABLE_STDIO_FILESTREAM -DNONSTANDARD_PORT"
|
||||
@@ -3155,8 +3269,6 @@ case $_backend in
|
||||
append_var DEFINES "-DSDL_BACKEND"
|
||||
add_line_to_config_mk "SDL_BACKEND = 1"
|
||||
;;
|
||||
sdl)
|
||||
;;
|
||||
*)
|
||||
echo "support for $_backend backend not implemented in configure script yet"
|
||||
exit 1
|
||||
@@ -3168,7 +3280,7 @@ append_var MODULES "backends/platform/$_backend"
|
||||
# Setup SDL specifics for SDL based backends
|
||||
#
|
||||
case $_backend in
|
||||
dingux | gph | linuxmoto | maemo | openpandora | samsungtv | sdl)
|
||||
androidsdl | dingux | gph | linuxmoto | maemo | openpandora | samsungtv | sdl)
|
||||
find_sdlconfig
|
||||
append_var INCLUDES "`$_sdlconfig --prefix="$_sdlpath" --cflags`"
|
||||
append_var LIBS "`$_sdlconfig --prefix="$_sdlpath" --libs`"
|
||||
@@ -3191,7 +3303,7 @@ esac
|
||||
# Enable 16bit support only for backends which support it
|
||||
#
|
||||
case $_backend in
|
||||
android | dingux | dc | gph | iphone | ios7 | maemo | openpandora | psp | samsungtv | sdl | tizen | webos | wii)
|
||||
3ds | android | androidsdl | dingux | dc | gph | iphone | ios7 | maemo | openpandora | psp | samsungtv | sdl | tizen | webos | wii)
|
||||
if test "$_16bit" = auto ; then
|
||||
_16bit=yes
|
||||
else
|
||||
@@ -3203,6 +3315,26 @@ case $_backend in
|
||||
;;
|
||||
esac
|
||||
|
||||
#
|
||||
# Enable High resolution engines (>320x240) support only for backends which support it
|
||||
#
|
||||
case $_host in
|
||||
gcw0)
|
||||
if test "$_highres" = yes ; then
|
||||
_highres=yes
|
||||
else
|
||||
_highres=no
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if test "$_highres" = no ; then
|
||||
_highres=no
|
||||
else
|
||||
_highres=yes
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
#
|
||||
# Enable Event Recorder only for backends that support it
|
||||
#
|
||||
@@ -3250,7 +3382,7 @@ case $_host_os in
|
||||
amigaos* | cygwin* | dreamcast | ds | gamecube | mingw* | n64 | ps2 | ps3 | psp | wii | wince)
|
||||
_posix=no
|
||||
;;
|
||||
android | beos* | bsd* | darwin* | freebsd* | gnu* | gph-linux | haiku* | hpux* | iphone | ios7 | irix*| k*bsd*-gnu* | linux* | maemo | mint* | netbsd* | openbsd* | solaris* | sunos* | uclinux* | webos)
|
||||
3ds | android | androidsdl | beos* | bsd* | darwin* | freebsd* | gnu* | gph-linux | haiku* | hpux* | iphone | ios7 | irix*| k*bsd*-gnu* | linux* | maemo | mint* | netbsd* | openbsd* | solaris* | sunos* | uclinux* | webos)
|
||||
_posix=yes
|
||||
;;
|
||||
os2-emx*)
|
||||
@@ -3515,6 +3647,11 @@ define_in_config_if_yes "$_mt32emu" 'USE_MT32EMU'
|
||||
#
|
||||
define_in_config_if_yes "$_16bit" 'USE_RGB_COLOR'
|
||||
|
||||
#
|
||||
# Check whether High resolution graphics support is requested
|
||||
#
|
||||
define_in_config_if_yes "$_highres" 'USE_HIGHRES'
|
||||
|
||||
#
|
||||
# Check whether save games use the current time as default description
|
||||
#
|
||||
@@ -3873,39 +4010,100 @@ echo "$_mpeg2"
|
||||
#
|
||||
# Check for Sparkle if updates support is enabled
|
||||
#
|
||||
echocheck "Sparkle"
|
||||
if test "$_updates" = no; then
|
||||
_sparkle=no
|
||||
else
|
||||
if test "$_sparkle" = auto ; then
|
||||
_sparkle=no
|
||||
cat > $TMPC << EOF
|
||||
#
|
||||
# Check is NSDockTilePlugIn protocol is supported
|
||||
#
|
||||
case $_host_os in
|
||||
darwin*)
|
||||
echocheck "Sparkle"
|
||||
if test "$_updates" = no; then
|
||||
_sparkle=no
|
||||
else
|
||||
if test ! -z $_sparklepath ; then
|
||||
SPARKLE_CFLAGS="-F$_sparklepath"
|
||||
SPARKLE_LIBS="-F$_sparklepath"
|
||||
fi
|
||||
if test "$_sparkle" = auto ; then
|
||||
_sparkle=no
|
||||
cat > $TMPC << EOF
|
||||
#include <Cocoa/Cocoa.h>
|
||||
#include <Sparkle/Sparkle.h>
|
||||
int main(void) { SUUpdater *updater = [SUUpdater sharedUpdater]; return 0; }
|
||||
EOF
|
||||
cc_check $SPARKLE_CFLAGS $SPARKLE_LIBS -framework Sparkle -ObjC++ -lobjc && _sparkle=yes
|
||||
fi
|
||||
if test "$_sparkle" = yes ; then
|
||||
append_var LIBS "$SPARKLE_LIBS -framework Sparkle"
|
||||
append_var INCLUDES "$SPARKLE_CFLAGS"
|
||||
fi
|
||||
define_in_config_if_yes "$_sparkle" 'USE_SPARKLE'
|
||||
fi
|
||||
echo "$_sparkle"
|
||||
cc_check $SPARKLE_CFLAGS $SPARKLE_LIBS -framework Sparkle -ObjC++ -lobjc && _sparkle=yes
|
||||
fi
|
||||
if test "$_sparkle" = yes ; then
|
||||
append_var LIBS "$SPARKLE_LIBS -framework Sparkle"
|
||||
append_var INCLUDES "$SPARKLE_CFLAGS"
|
||||
fi
|
||||
define_in_config_if_yes "$_sparkle" 'USE_SPARKLE'
|
||||
fi
|
||||
echo "$_sparkle"
|
||||
;;
|
||||
mingw*)
|
||||
echocheck "Sparkle"
|
||||
if test "$_updates" = no; then
|
||||
_sparkle=no
|
||||
else
|
||||
if test ! -z $_sparklepath ; then
|
||||
SPARKLE_CFLAGS="-I$_sparklepath/include"
|
||||
SPARKLE_LIBS="-L$_sparklepath/Release -L$_sparklepath/x64/Release"
|
||||
fi
|
||||
if test "$_sparkle" = auto ; then
|
||||
_sparkle=no
|
||||
cat > $TMPC << EOF
|
||||
#include <winsparkle.h>
|
||||
int main(void) { win_sparkle_get_update_check_interval(); return 0; }
|
||||
EOF
|
||||
cc_check $SPARKLE_CFLAGS $SPARKLE_LIBS -lWinSparkle && _sparkle=yes
|
||||
fi
|
||||
if test "$_sparkle" = yes ; then
|
||||
append_var LIBS "$SPARKLE_LIBS -lWinSparkle"
|
||||
append_var INCLUDES "$SPARKLE_CFLAGS"
|
||||
fi
|
||||
define_in_config_if_yes "$_sparkle" 'USE_SPARKLE'
|
||||
fi
|
||||
echo "$_sparkle"
|
||||
;;
|
||||
*)
|
||||
_sparkle=no
|
||||
;;
|
||||
esac
|
||||
|
||||
#
|
||||
# Check for FluidSynth
|
||||
# Check is NSDockTilePlugIn protocol is supported
|
||||
#
|
||||
case $_host_os in
|
||||
darwin*)
|
||||
# NSDockTilePlugIn was added in OS X 10.6, so will not be available when compiling on older OS X versions.
|
||||
echocheck "DockTilePlugin"
|
||||
if test "$_osxdockplugin" = auto ; then
|
||||
_osxdockplugin=no
|
||||
cat > $TMPC << EOF
|
||||
#include <Cocoa/Cocoa.h>
|
||||
@interface ScummVMDockTilePlugIn : NSObject <NSDockTilePlugIn> {
|
||||
}
|
||||
@end
|
||||
EOF
|
||||
cc_check -c -ObjC++ && _osxdockplugin=yes
|
||||
fi
|
||||
define_in_config_if_yes "$_osxdockplugin" 'USE_DOCKTILEPLUGIN'
|
||||
echo "$_osxdockplugin"
|
||||
;;
|
||||
*)
|
||||
_osxdockplugin=no
|
||||
;;
|
||||
esac
|
||||
|
||||
#
|
||||
# Check for FluidSynth
|
||||
#
|
||||
echocheck "FluidSynth"
|
||||
|
||||
append_var FLUIDSYNTH_LIBS "-lfluidsynth"
|
||||
case $_host_os in
|
||||
mingw*)
|
||||
# NOTE: Windows builds use an older FluidSynth version (1.0.9)
|
||||
# which doesn't require glib, to avoid bundling the complete glib
|
||||
# libraries with Windows builds.
|
||||
FLUIDSYNTH_STATIC_LIBS="$FLUIDSYNTH_LIBS -ldsound -lwinmm"
|
||||
FLUIDSYNTH_STATIC_LIBS="$FLUIDSYNTH_LIBS -lglib-2.0 -lintl -liconv -lws2_32 -lole32 -lshlwapi -lpcre -ldsound -lwinmm"
|
||||
;;
|
||||
|
||||
darwin*)
|
||||
@@ -4138,87 +4336,7 @@ EOF
|
||||
fi
|
||||
|
||||
define_in_config_if_yes "$_glew" "USE_GLEW"
|
||||
# ResidualVM specific end <-
|
||||
|
||||
#
|
||||
# Check for iconv
|
||||
#
|
||||
echo_n "Checking whether iconv.h is present... "
|
||||
if test "$_iconv" = auto ; then
|
||||
_iconv=no
|
||||
cat > $TMPC << EOF
|
||||
#include <iconv.h>
|
||||
int main(int, char **) {
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
cc_check $ICONV_CFLAGS $ICONV_LIBS && _iconv=yes
|
||||
fi
|
||||
|
||||
create_iconv_test() {
|
||||
cat > $TMPC << EOF
|
||||
#include <iconv.h>
|
||||
int main(int, char **) {
|
||||
iconv_t iconv = iconv_open("UTF-32", "SJIS");
|
||||
iconv_close(iconv);
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
}
|
||||
echo "$_iconv"
|
||||
|
||||
if test "$_iconv" = yes ; then
|
||||
echo_n "Checking whether iconv needs linking against libiconv... "
|
||||
|
||||
needs_iconvlib='auto'
|
||||
create_iconv_test
|
||||
cc_check $ICONV_CFLAGS $ICONV_LIBS -liconv && needs_iconvlib='yes'
|
||||
# We do check linking without -liconv here too, just in case
|
||||
# it would fail otherwise too
|
||||
create_iconv_test
|
||||
cc_check $ICONV_CFLAGS $ICONV_LIBS && needs_iconvlib='no'
|
||||
|
||||
if test "$needs_iconvlib" = auto ; then
|
||||
_iconv=no
|
||||
echo "does not link at all"
|
||||
else
|
||||
if test "$needs_iconvlib" = yes ; then
|
||||
append_var ICONV_LIBS "-liconv"
|
||||
fi
|
||||
echo "$needs_iconvlib"
|
||||
|
||||
echo_n "Checking signature of iconv... "
|
||||
uses_const=no
|
||||
|
||||
cat > $TMPC << EOF
|
||||
#include <iconv.h>
|
||||
int main(int argc, char **argv) {
|
||||
iconv_t iconvP;
|
||||
const char **inbuf = 0;
|
||||
iconv(iconvP, inbuf, 0, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
cc_check $ICONV_CFLAGS $ICONV_LIBS && uses_const=yes
|
||||
|
||||
if test "$uses_const" = yes ; then
|
||||
echo "iconv_t, const char **, size_t *, char **, size_t *"
|
||||
else
|
||||
echo "iconv_t, char **, size_t *, char **, size_t *"
|
||||
fi
|
||||
|
||||
define_in_config_if_yes "$uses_const" 'ICONV_USES_CONST'
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$_iconv" = yes ; then
|
||||
append_var LIBS "$ICONV_LIBS"
|
||||
append_var INCLUDES "$ICONV_CFLAGS"
|
||||
fi
|
||||
|
||||
echocheck "iconv"
|
||||
define_in_config_if_yes "$_iconv" 'USE_ICONV'
|
||||
echo "$_iconv"
|
||||
|
||||
#
|
||||
# Check for OpenGL (ES)
|
||||
@@ -4239,7 +4357,6 @@ case $_backend in
|
||||
;;
|
||||
esac
|
||||
|
||||
# ResidualVM specific start ->
|
||||
if test "$_opengl" = auto ; then
|
||||
_opengl=no
|
||||
if test "$_backend" = "sdl" || test "$_backend" = "android"; then
|
||||
@@ -4340,19 +4457,10 @@ EOF
|
||||
fi
|
||||
cc_check_clean
|
||||
fi
|
||||
# ResidualVM specific end <-
|
||||
|
||||
case $_host_os in
|
||||
tizen)
|
||||
# components live in non-standard locations so just assume sane SDK
|
||||
_opengl=yes
|
||||
_opengles=yes
|
||||
;;
|
||||
esac
|
||||
|
||||
if test "$_opengles" = "yes" ; then
|
||||
echo "yes (OpenGL ES)"
|
||||
# ResidualVM specific start here ->
|
||||
elif test "$_opengles2" = "yes" ; then
|
||||
echo "yes (OpenGL ES2)"
|
||||
else
|
||||
@@ -4369,8 +4477,112 @@ define_in_config_if_yes "$_opengl" "USE_OPENGL"
|
||||
define_in_config_if_yes "$_opengles" "USE_GLES"
|
||||
define_in_config_if_yes "$_opengles2" "USE_GLES2"
|
||||
define_in_config_if_yes "$_opengl_shaders" "USE_OPENGL_SHADERS"
|
||||
|
||||
#
|
||||
# Check for iconv
|
||||
#
|
||||
echo_n "Checking whether iconv.h is present... "
|
||||
if test "$_iconv" = auto ; then
|
||||
_iconv=no
|
||||
cat > $TMPC << EOF
|
||||
#include <iconv.h>
|
||||
int main(int, char **) {
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
cc_check $ICONV_CFLAGS $ICONV_LIBS && _iconv=yes
|
||||
fi
|
||||
|
||||
create_iconv_test() {
|
||||
cat > $TMPC << EOF
|
||||
#include <iconv.h>
|
||||
int main(int, char **) {
|
||||
iconv_t iconv = iconv_open("UTF-32", "SJIS");
|
||||
iconv_close(iconv);
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
}
|
||||
echo "$_iconv"
|
||||
|
||||
if test "$_iconv" = yes ; then
|
||||
echo_n "Checking whether iconv needs linking against libiconv... "
|
||||
|
||||
needs_iconvlib='auto'
|
||||
create_iconv_test
|
||||
cc_check $ICONV_CFLAGS $ICONV_LIBS -liconv && needs_iconvlib='yes'
|
||||
# We do check linking without -liconv here too, just in case
|
||||
# it would fail otherwise too
|
||||
create_iconv_test
|
||||
cc_check $ICONV_CFLAGS $ICONV_LIBS && needs_iconvlib='no'
|
||||
|
||||
if test "$needs_iconvlib" = auto ; then
|
||||
_iconv=no
|
||||
echo "does not link at all"
|
||||
else
|
||||
if test "$needs_iconvlib" = yes ; then
|
||||
append_var ICONV_LIBS "-liconv"
|
||||
fi
|
||||
echo "$needs_iconvlib"
|
||||
|
||||
echo_n "Checking signature of iconv... "
|
||||
uses_const=no
|
||||
|
||||
cat > $TMPC << EOF
|
||||
#include <iconv.h>
|
||||
int main(int argc, char **argv) {
|
||||
iconv_t iconvP;
|
||||
const char **inbuf = 0;
|
||||
iconv(iconvP, inbuf, 0, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
cc_check $ICONV_CFLAGS $ICONV_LIBS && uses_const=yes
|
||||
|
||||
if test "$uses_const" = yes ; then
|
||||
echo "iconv_t, const char **, size_t *, char **, size_t *"
|
||||
else
|
||||
echo "iconv_t, char **, size_t *, char **, size_t *"
|
||||
fi
|
||||
|
||||
define_in_config_if_yes "$uses_const" 'ICONV_USES_CONST'
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$_iconv" = yes ; then
|
||||
append_var LIBS "$ICONV_LIBS"
|
||||
append_var INCLUDES "$ICONV_CFLAGS"
|
||||
fi
|
||||
|
||||
echocheck "iconv"
|
||||
define_in_config_if_yes "$_iconv" 'USE_ICONV'
|
||||
echo "$_iconv"
|
||||
# ResidualVM specific ends here <-
|
||||
|
||||
|
||||
#
|
||||
# Check for Linux CD-ROM support
|
||||
#
|
||||
case $_host_os in
|
||||
*linux*)
|
||||
echocheck "Linux CD-ROM"
|
||||
linuxcd=no
|
||||
cat > $TMPC << EOF
|
||||
#include <linux/cdrom.h>
|
||||
#include <sys/types.h>
|
||||
int main(void) {
|
||||
int x = CDROMREADAUDIO;
|
||||
dev_t dev;
|
||||
return major(dev) + x;
|
||||
}
|
||||
EOF
|
||||
cc_check && linuxcd=yes
|
||||
define_in_config_if_yes "$linuxcd" 'USE_LINUXCD'
|
||||
echo "$linuxcd"
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
#
|
||||
# Check for nasm
|
||||
#
|
||||
@@ -4605,6 +4817,10 @@ if test "$_16bit" = yes ; then
|
||||
: # residualvm not use it
|
||||
fi
|
||||
|
||||
if test "$_highres" = yes ; then
|
||||
: # residualvm not use it
|
||||
fi
|
||||
|
||||
if test "$_savegame_timestamp" = yes ; then
|
||||
echo_n ", savegame timestamp"
|
||||
fi
|
||||
@@ -4618,7 +4834,7 @@ if test "$_build_scalers" = yes ; then
|
||||
fi
|
||||
|
||||
if test "$_mt32emu" = yes ; then
|
||||
echo_n ", MT-32 emu"
|
||||
echo_n ", MT-32 emulator"
|
||||
fi
|
||||
|
||||
if test "$_text_console" = yes ; then
|
||||
@@ -4644,6 +4860,14 @@ fi
|
||||
# after all of CXXFLAGS, LDFLAGS, LIBS etc. have been setup
|
||||
#
|
||||
case $_backend in
|
||||
3ds)
|
||||
if test "$_freetype2" = yes -a "$_png" = yes; then
|
||||
append_var LIBS "-lpng"
|
||||
fi
|
||||
if test "$_tremor" = yes -o "$_flac" = yes; then
|
||||
append_var LIBS "-logg"
|
||||
fi
|
||||
;;
|
||||
android)
|
||||
# ssp at this point so the cxxtests link
|
||||
if test "$_debug_build" = yes; then
|
||||
@@ -4875,6 +5099,8 @@ STAGINGPATH=$_stagingpath
|
||||
WIN32PATH=$_win32path
|
||||
AMIGAOSPATH=$_amigaospath
|
||||
STATICLIBPATH=$_staticlibpath
|
||||
XCODETOOLSPATH=$_xcodetoolspath
|
||||
SPARKLEPATH=$_sparklepath
|
||||
SDLCONFIG=$_sdlconfig
|
||||
|
||||
ABI := $ABI
|
||||
|
||||
@@ -0,0 +1,324 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "cmake.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
|
||||
namespace CreateProjectTool {
|
||||
|
||||
CMakeProvider::CMakeProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, const int version)
|
||||
: ProjectProvider(global_warnings, project_warnings, version) {
|
||||
}
|
||||
|
||||
const CMakeProvider::Library *CMakeProvider::getLibraryFromFeature(const char *feature) const {
|
||||
static const Library s_libraries[] = {
|
||||
{ "sdl", "FindSDL", "SDL", "SDL_INCLUDE_DIR", "SDL_LIBRARY", 0 },
|
||||
{ "sdl2", 0, "SDL2", "SDL2_INCLUDE_DIRS", "SDL2_LIBRARIES", 0 },
|
||||
{ "freetype", "FindFreetype", "Freetype", "FREETYPE_INCLUDE_DIRS", "FREETYPE_LIBRARIES", 0 },
|
||||
{ "libz", "FindZLIB", "ZLIB", "ZLIB_INCLUDE_DIRS", "ZLIB_LIBRARIES", 0 },
|
||||
{ "png", "FindPNG", "PNG", "PNG_INCLUDE_DIRS", "PNG_LIBRARIES", 0 },
|
||||
{ "jpeg", "FindJPEG", "JPEG", "JPEG_INCLUDE_DIRS", "JPEG_LIBRARIES", 0 },
|
||||
{ "mpeg2", "FindMPEG2", "MPEG2", "MPEG2_INCLUDE_DIRS", "MPEG2_mpeg2_LIBRARY", 0 },
|
||||
{ "flac", 0, 0, 0, 0, "FLAC" },
|
||||
{ "mad", 0, 0, 0, 0, "mad" },
|
||||
{ "vorbis", 0, 0, 0, 0, "vorbisfile vorbis ogg" },
|
||||
{ "theora", 0, 0, 0, 0, "theoradec" },
|
||||
{ "fluidsynth",0, 0, 0, 0, "fluidsynth" },
|
||||
{ "faad", 0, 0, 0, 0, "faad" }
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; i < sizeof(s_libraries) / sizeof(s_libraries[0]); i++) {
|
||||
if (std::strcmp(feature, s_libraries[i].feature) == 0) {
|
||||
return &s_libraries[i];
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CMakeProvider::createWorkspace(const BuildSetup &setup) {
|
||||
std::string filename = setup.outputDir + "/CMakeLists.txt";
|
||||
std::ofstream workspace(filename.c_str());
|
||||
if (!workspace)
|
||||
error("Could not open \"" + filename + "\" for writing");
|
||||
|
||||
workspace << "cmake_minimum_required(VERSION 3.2)\n"
|
||||
"project(" << setup.projectDescription << ")\n\n";
|
||||
|
||||
workspace << "# Define the engines and subengines\n";
|
||||
writeEngines(setup, workspace);
|
||||
writeSubEngines(setup, workspace);
|
||||
workspace << "# Generate options for the engines\n";
|
||||
writeEngineOptions(workspace);
|
||||
|
||||
workspace << "include_directories(${" << setup.projectDescription << "_SOURCE_DIR} ${" << setup.projectDescription << "_SOURCE_DIR}/engines\n"
|
||||
"$ENV{"<<LIBS_DEFINE<<"}/include)\n\n";
|
||||
|
||||
workspace << "# Libraries and features\n";
|
||||
writeFeatureLibSearch(workspace, setup.useSDL2 ? "sdl2" : "sdl");
|
||||
for (FeatureList::const_iterator i = setup.features.begin(), end = setup.features.end(); i != end; ++i) {
|
||||
if (!i->enable || featureExcluded(i->name)) continue;
|
||||
|
||||
writeFeatureLibSearch(workspace, i->name);
|
||||
workspace << "add_definitions(-D" << i->define << ")\n";
|
||||
}
|
||||
workspace << "\n";
|
||||
|
||||
writeWarnings(workspace);
|
||||
writeDefines(setup, workspace);
|
||||
workspace << "# Generate definitions for the engines\n";
|
||||
writeEngineDefinitions(workspace);
|
||||
|
||||
workspace << "# Generate \"engines/plugins_table.h\"\n";
|
||||
writeGeneratePluginsTable(workspace);
|
||||
}
|
||||
|
||||
void CMakeProvider::writeFeatureLibSearch(std::ofstream &workspace, const char *feature) const {
|
||||
const Library *library = getLibraryFromFeature(feature);
|
||||
if (library) {
|
||||
if (library->module) {
|
||||
workspace << "Include(" << library->module << ")\n";
|
||||
}
|
||||
if (library->package) {
|
||||
workspace << "Find_Package(" << library->package << " REQUIRED)\n";
|
||||
}
|
||||
if (library->includesVar) {
|
||||
workspace << "include_directories(${" << library->includesVar << "})\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CMakeProvider::writeEngines(const BuildSetup &setup, std::ofstream &workspace) const {
|
||||
workspace << "set(ENGINES";
|
||||
for (EngineDescList::const_iterator i = setup.engines.begin(), end = setup.engines.end(); i != end; ++i) {
|
||||
// We ignore all sub engines here because they require special handling.
|
||||
if (!i->enable || isSubEngine(i->name, setup.engines)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string engineName;
|
||||
std::transform(i->name.begin(), i->name.end(), std::back_inserter(engineName), toupper);
|
||||
|
||||
workspace << " " << engineName;
|
||||
}
|
||||
workspace << ")\n";
|
||||
}
|
||||
|
||||
void CMakeProvider::writeSubEngines(const BuildSetup &setup, std::ofstream &workspace) const {
|
||||
for (EngineDescList::const_iterator i = setup.engines.begin(), end = setup.engines.end(); i != end; ++i) {
|
||||
// We ignore all sub engines here because they are handled in the inner loop
|
||||
if (!i->enable || isSubEngine(i->name, setup.engines) || i->subEngines.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string engineName;
|
||||
std::transform(i->name.begin(), i->name.end(), std::back_inserter(engineName), toupper);
|
||||
|
||||
workspace << "set(SUB_ENGINES_" << engineName;
|
||||
for (StringList::const_iterator j = i->subEngines.begin(), subEnd = i->subEngines.end(); j != subEnd; ++j) {
|
||||
const EngineDesc &subEngine = findEngineDesc(*j, setup.engines);
|
||||
if (!subEngine.enable) continue;
|
||||
|
||||
std::string subEngineName;
|
||||
std::transform(j->begin(), j->end(), std::back_inserter(subEngineName), toupper);
|
||||
|
||||
workspace << " " << subEngineName;
|
||||
}
|
||||
workspace << ")\n";
|
||||
}
|
||||
|
||||
workspace << "\n";
|
||||
}
|
||||
|
||||
void CMakeProvider::createProjectFile(const std::string &name, const std::string &, const BuildSetup &setup, const std::string &moduleDir,
|
||||
const StringList &includeList, const StringList &excludeList) {
|
||||
|
||||
const std::string projectFile = setup.outputDir + "/CMakeLists.txt";
|
||||
std::ofstream project(projectFile.c_str(), std::ofstream::out | std::ofstream::app);
|
||||
if (!project)
|
||||
error("Could not open \"" + projectFile + "\" for writing");
|
||||
|
||||
if (name == setup.projectName) {
|
||||
project << "add_executable(" << name << "\n";
|
||||
} else {
|
||||
std::string engineName;
|
||||
std::transform(name.begin(), name.end(), std::back_inserter(engineName), toupper);
|
||||
|
||||
project << "if (ENABLE_" << engineName << ")\n";
|
||||
project << "add_library(" << name << "\n";
|
||||
}
|
||||
|
||||
std::string modulePath;
|
||||
if (!moduleDir.compare(0, setup.srcDir.size(), setup.srcDir)) {
|
||||
modulePath = moduleDir.substr(setup.srcDir.size());
|
||||
if (!modulePath.empty() && modulePath.at(0) == '/')
|
||||
modulePath.erase(0, 1);
|
||||
}
|
||||
|
||||
if (modulePath.size())
|
||||
addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix + '/' + modulePath);
|
||||
else
|
||||
addFilesToProject(moduleDir, project, includeList, excludeList, setup.filePrefix);
|
||||
|
||||
|
||||
project << ")\n";
|
||||
if (name != setup.projectName) {
|
||||
project << "endif()\n";
|
||||
}
|
||||
|
||||
project << "# Libraries\n";
|
||||
if (name == setup.projectName) {
|
||||
const Library *sdlLibrary = getLibraryFromFeature(setup.useSDL2 ? "sdl2" : "sdl");
|
||||
project << "target_link_libraries(" << name << " ${" << sdlLibrary->librariesVar << "})\n";
|
||||
|
||||
for (FeatureList::const_iterator i = setup.features.begin(), end = setup.features.end(); i != end; ++i) {
|
||||
if (!i->enable || featureExcluded(i->name)) continue;
|
||||
|
||||
const Library *library = getLibraryFromFeature(i->name);
|
||||
if (!library) continue;
|
||||
|
||||
if (library->librariesVar) {
|
||||
project << "target_link_libraries(" << name << " ${" << library->librariesVar << "})\n";
|
||||
} else {
|
||||
project << "target_link_libraries(" << name << " " << library->libraries << ")\n";
|
||||
}
|
||||
}
|
||||
project << "if (WIN32)\n";
|
||||
project << " target_sources(" << name << " PUBLIC dists/" << name << ".rc)\n";
|
||||
project << " target_link_libraries(" << name << " winmm)\n";
|
||||
project << "endif()\n";
|
||||
project << "\n";
|
||||
|
||||
project << "# Engines libraries handling\n";
|
||||
writeEnginesLibrariesHandling(setup, project);
|
||||
|
||||
project << "set_property(TARGET " << name << " PROPERTY CXX_STANDARD 11)\n";
|
||||
project << "set_property(TARGET " << name << " PROPERTY CXX_STANDARD_REQUIRED ON)\n";
|
||||
}
|
||||
}
|
||||
|
||||
void CMakeProvider::writeWarnings(std::ofstream &output) const {
|
||||
output << "SET (CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS}";
|
||||
for (StringList::const_iterator i = _globalWarnings.begin(); i != _globalWarnings.end(); ++i) {
|
||||
output << " " << *i;
|
||||
}
|
||||
output << "\")\n";
|
||||
}
|
||||
|
||||
void CMakeProvider::writeDefines(const BuildSetup &setup, std::ofstream &output) const {
|
||||
output << "if (WIN32)\n";
|
||||
output << " add_definitions(-DWIN32)\n";
|
||||
output << "else()\n";
|
||||
output << " add_definitions(-DPOSIX)\n";
|
||||
output << "endif()\n";
|
||||
|
||||
output << "if (CMAKE_SIZEOF_VOID_P MATCHES 8)\n";
|
||||
output << " add_definitions(-DSCUMM_64BITS)\n";
|
||||
output << "endif()\n";
|
||||
|
||||
output << "add_definitions(-DSDL_BACKEND)\n\n";
|
||||
}
|
||||
|
||||
void CMakeProvider::writeFileListToProject(const FileNode &dir, std::ofstream &projectFile, const int indentation,
|
||||
const StringList &duplicate, const std::string &objPrefix, const std::string &filePrefix) {
|
||||
|
||||
for (FileNode::NodeList::const_iterator i = dir.children.begin(); i != dir.children.end(); ++i) {
|
||||
const FileNode *node = *i;
|
||||
|
||||
if (!node->children.empty()) {
|
||||
writeFileListToProject(*node, projectFile, indentation + 1, duplicate, objPrefix + node->name + '_', filePrefix + node->name + '/');
|
||||
} else {
|
||||
std::string name, ext;
|
||||
splitFilename(node->name, name, ext);
|
||||
projectFile << "\t" << filePrefix + node->name << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *CMakeProvider::getProjectExtension() {
|
||||
return ".txt";
|
||||
}
|
||||
|
||||
void CMakeProvider::writeEngineOptions(std::ofstream &workspace) const {
|
||||
workspace << "foreach(ENGINE IN LISTS ENGINES)\n";
|
||||
workspace << " OPTION(ENABLE_${ENGINE} \"Enable ${ENGINE}\" ON)\n";
|
||||
workspace << "endforeach(ENGINE)\n\n";
|
||||
}
|
||||
|
||||
void CMakeProvider::writeGeneratePluginsTable(std::ofstream &workspace) const {
|
||||
workspace << "file(REMOVE \"engines/plugins_table.h\")\n";
|
||||
workspace << "file(APPEND \"engines/plugins_table.h\" \"/* This file is automatically generated by CMake */\\n\")\n";
|
||||
workspace << "foreach(ENGINE IN LISTS ENGINES)\n";
|
||||
workspace << " if (ENABLE_${ENGINE})\n";
|
||||
workspace << " file(APPEND \"engines/plugins_table.h\" \"#if PLUGIN_ENABLED_STATIC(${ENGINE})\\n\")\n";
|
||||
workspace << " file(APPEND \"engines/plugins_table.h\" \"LINK_PLUGIN(${ENGINE})\\n\")\n";
|
||||
workspace << " file(APPEND \"engines/plugins_table.h\" \"#endif\\n\")\n";
|
||||
workspace << " endif()\n";
|
||||
workspace << "endforeach()\n\n";
|
||||
}
|
||||
|
||||
void CMakeProvider::writeEnginesLibrariesHandling(const BuildSetup &setup, std::ofstream &workspace) const {
|
||||
workspace << "foreach(ENGINE IN LISTS ENGINES)\n";
|
||||
workspace << " if (ENABLE_${ENGINE})\n";
|
||||
workspace << " string(TOLOWER ${ENGINE} ENGINE_LIB)\n\n";
|
||||
workspace << " # Enable C++11\n";
|
||||
workspace << " set_property(TARGET ${ENGINE_LIB} PROPERTY CXX_STANDARD 11)\n";
|
||||
workspace << " set_property(TARGET ${ENGINE_LIB} PROPERTY CXX_STANDARD_REQUIRED ON)\n\n";
|
||||
workspace << " # Link against the engine\n";
|
||||
workspace << " target_link_libraries("<< setup.projectName <<" ${ENGINE_LIB})\n";
|
||||
workspace << " endif()\n";
|
||||
workspace << "endforeach()\n\n";
|
||||
}
|
||||
|
||||
void CMakeProvider::writeEngineDefinitions(std::ofstream &workspace) const {
|
||||
workspace << "foreach(ENGINE IN LISTS ENGINES)\n";
|
||||
workspace << " if (ENABLE_${ENGINE})\n";
|
||||
workspace << " add_definitions(-DENABLE_${ENGINE})\n";
|
||||
workspace << " foreach(SUB_ENGINE IN LISTS SUB_ENGINES_${ENGINE})\n";
|
||||
workspace << " add_definitions(-DENABLE_${SUB_ENGINE})\n";;
|
||||
workspace << " endforeach(SUB_ENGINE)\n";
|
||||
workspace << " endif()\n";
|
||||
workspace << "endforeach()\n\n";
|
||||
}
|
||||
|
||||
bool CMakeProvider::featureExcluded(const char *name) const {
|
||||
return std::strcmp(name, "nasm") == 0 ||
|
||||
std::strcmp(name, "updates") == 0 ; // NASM is not supported for now
|
||||
}
|
||||
|
||||
const EngineDesc &CMakeProvider::findEngineDesc(const std::string &name, const EngineDescList &engines) const {
|
||||
for (EngineDescList::const_iterator i = engines.begin(), end = engines.end(); i != end; ++i) {
|
||||
if (i->name == name) {
|
||||
return *i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
error("Unable to find requested engine");
|
||||
}
|
||||
|
||||
} // End of CreateProjectTool namespace
|
||||
@@ -0,0 +1,85 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TOOLS_CREATE_PROJECT_CMAKE_H
|
||||
#define TOOLS_CREATE_PROJECT_CMAKE_H
|
||||
|
||||
#include "create_project.h"
|
||||
|
||||
namespace CreateProjectTool {
|
||||
|
||||
/**
|
||||
* A ProjectProvider used to generate CMake project descriptions
|
||||
*
|
||||
* Generated CMake projects are minimal, and will only work with GCC.
|
||||
*/
|
||||
class CMakeProvider : public ProjectProvider {
|
||||
public:
|
||||
CMakeProvider(StringList &global_warnings, std::map<std::string, StringList> &project_warnings, const int version = 0);
|
||||
|
||||
protected:
|
||||
|
||||
void createWorkspace(const BuildSetup &setup);
|
||||
|
||||
void createOtherBuildFiles(const BuildSetup &) {}
|
||||
|
||||
void addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList) {}
|
||||
|
||||
void createProjectFile(const std::string &name, const std::string &uuid, const BuildSetup &setup, const std::string &moduleDir,
|
||||
const StringList &includeList, const StringList &excludeList);
|
||||
|
||||
void writeFileListToProject(const FileNode &dir, std::ofstream &projectFile, const int indentation,
|
||||
const StringList &duplicate, const std::string &objPrefix, const std::string &filePrefix);
|
||||
|
||||
const char *getProjectExtension();
|
||||
|
||||
private:
|
||||
/**
|
||||
* CMake properties for a library required by a feature
|
||||
*/
|
||||
struct Library {
|
||||
const char *feature;
|
||||
const char *module;
|
||||
const char *package;
|
||||
const char *includesVar;
|
||||
const char *librariesVar;
|
||||
const char *libraries;
|
||||
};
|
||||
|
||||
const Library *getLibraryFromFeature(const char *feature) const;
|
||||
|
||||
void writeWarnings(std::ofstream &output) const;
|
||||
void writeDefines(const BuildSetup &setup, std::ofstream &output) const;
|
||||
void writeEngines(const BuildSetup &setup, std::ofstream &workspace) const;
|
||||
void writeSubEngines(const BuildSetup &setup, std::ofstream &workspace) const;
|
||||
void writeEngineOptions(std::ofstream &workspace) const;
|
||||
void writeGeneratePluginsTable(std::ofstream &workspace) const;
|
||||
void writeEnginesLibrariesHandling(const BuildSetup &setup, std::ofstream &workspace) const;
|
||||
void writeEngineDefinitions(std::ofstream &workspace) const;
|
||||
void writeFeatureLibSearch(std::ofstream &workspace, const char *feature) const;
|
||||
bool featureExcluded(const char *name) const;
|
||||
const EngineDesc &findEngineDesc(const std::string &name, const EngineDescList &engines) const;
|
||||
};
|
||||
|
||||
} // End of CreateProjectTool namespace
|
||||
|
||||
#endif // TOOLS_CREATE_PROJECT_CMAKE_H
|
||||
@@ -0,0 +1,23 @@
|
||||
cmake_minimum_required(VERSION 3.2)
|
||||
project(create_project)
|
||||
|
||||
|
||||
set(SOURCE_FILES
|
||||
../cmake.cpp
|
||||
../cmake.h
|
||||
../codeblocks.cpp
|
||||
../codeblocks.h
|
||||
../create_project.cpp
|
||||
../create_project.h
|
||||
../msbuild.cpp
|
||||
../msbuild.h
|
||||
../msvc.cpp
|
||||
../msvc.h
|
||||
../visualstudio.cpp
|
||||
../visualstudio.h
|
||||
../xcode.cpp
|
||||
../xcode.h
|
||||
)
|
||||
|
||||
add_executable(create_project ${SOURCE_FILES})
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "config.h"
|
||||
#include "create_project.h"
|
||||
|
||||
#include "cmake.h"
|
||||
#include "codeblocks.h"
|
||||
#include "msvc.h"
|
||||
#include "visualstudio.h"
|
||||
@@ -53,7 +54,7 @@
|
||||
#define USE_WIN32_API
|
||||
#endif
|
||||
|
||||
#ifdef USE_WIN32_API
|
||||
#if (defined(_WIN32) || defined(WIN32))
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sstream>
|
||||
@@ -83,10 +84,18 @@ std::string unifyPath(const std::string &path);
|
||||
* @param exe Name of the executable.
|
||||
*/
|
||||
void displayHelp(const char *exe);
|
||||
|
||||
/**
|
||||
* Build a list of options to enable or disable GCC warnings
|
||||
*
|
||||
* @param globalWarnings Resulting list of warnings
|
||||
*/
|
||||
void addGCCWarnings(StringList &globalWarnings);
|
||||
} // End of anonymous namespace
|
||||
|
||||
enum ProjectType {
|
||||
kProjectNone,
|
||||
kProjectCMake,
|
||||
kProjectCodeBlocks,
|
||||
kProjectMSVC,
|
||||
kProjectXcode
|
||||
@@ -125,7 +134,6 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
ProjectType projectType = kProjectNone;
|
||||
int msvcVersion = 12;
|
||||
bool useSDL2 = false;
|
||||
|
||||
// Parse command line arguments
|
||||
using std::cout;
|
||||
@@ -142,6 +150,14 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
return 0;
|
||||
|
||||
} else if (!std::strcmp(argv[i], "--cmake")) {
|
||||
if (projectType != kProjectNone) {
|
||||
std::cerr << "ERROR: You cannot pass more than one project type!\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
projectType = kProjectCMake;
|
||||
|
||||
} else if (!std::strcmp(argv[i], "--codeblocks")) {
|
||||
if (projectType != kProjectNone) {
|
||||
std::cerr << "ERROR: You cannot pass more than one project type!\n";
|
||||
@@ -269,7 +285,7 @@ int main(int argc, char *argv[]) {
|
||||
} else if (!std::strcmp(argv[i], "--tests")) {
|
||||
setup.tests = true;
|
||||
} else if (!std::strcmp(argv[i], "--sdl2")) {
|
||||
useSDL2 = true;
|
||||
setup.useSDL2 = true;
|
||||
} else {
|
||||
std::cerr << "ERROR: Unknown parameter \"" << argv[i] << "\"\n";
|
||||
return -1;
|
||||
@@ -335,10 +351,7 @@ int main(int argc, char *argv[]) {
|
||||
StringList featureDefines = getFeatureDefines(setup.features);
|
||||
setup.defines.splice(setup.defines.begin(), featureDefines);
|
||||
|
||||
// Windows only has support for the SDL backend, so we hardcode it here (along with winmm)
|
||||
if (projectType != kProjectXcode) {
|
||||
setup.defines.push_back("WIN32");
|
||||
} else {
|
||||
if (projectType == kProjectXcode) {
|
||||
setup.defines.push_back("POSIX");
|
||||
// Define both MACOSX, and IPHONE, but only one of them will be associated to the
|
||||
// correct target by the Xcode project provider.
|
||||
@@ -347,13 +360,42 @@ int main(int argc, char *argv[]) {
|
||||
// the files, according to the target.
|
||||
setup.defines.push_back("MACOSX");
|
||||
setup.defines.push_back("IPHONE");
|
||||
} else if (projectType == kProjectMSVC || projectType == kProjectCodeBlocks) {
|
||||
// Windows only has support for the SDL backend, so we hardcode it here (along with winmm)
|
||||
setup.defines.push_back("WIN32");
|
||||
} else {
|
||||
// As a last resort, select the backend files to build based on the platform used to build create_project.
|
||||
// This is broken when cross compiling.
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
setup.defines.push_back("WIN32");
|
||||
#else
|
||||
setup.defines.push_back("POSIX");
|
||||
#endif
|
||||
}
|
||||
|
||||
bool updatesEnabled = false;
|
||||
for (FeatureList::const_iterator i = setup.features.begin(); i != setup.features.end(); ++i) {
|
||||
if (i->enable && !strcmp(i->name, "updates"))
|
||||
updatesEnabled = true;
|
||||
}
|
||||
if (updatesEnabled) {
|
||||
setup.defines.push_back("USE_SPARKLE");
|
||||
if (projectType != kProjectXcode)
|
||||
setup.libraries.push_back("winsparkle");
|
||||
else
|
||||
setup.libraries.push_back("sparkle");
|
||||
}
|
||||
|
||||
setup.defines.push_back("SDL_BACKEND");
|
||||
if (!useSDL2) {
|
||||
cout << "\nLinking to SDL 1.2\n\n";
|
||||
if (!setup.useSDL2) {
|
||||
cout << "\nBuilding against SDL 1.2\n\n";
|
||||
setup.libraries.push_back("sdl");
|
||||
} else {
|
||||
cout << "\nLinking to SDL 2.0\n\n";
|
||||
cout << "\nBuilding against SDL 2.0\n\n";
|
||||
// TODO: This also defines USE_SDL2 in the preprocessor, we don't do
|
||||
// this in our configure/make based build system. Adapt create_project
|
||||
// to replicate this behavior.
|
||||
setup.defines.push_back("USE_SDL2");
|
||||
setup.libraries.push_back("sdl2");
|
||||
}
|
||||
setup.libraries.push_back("winmm");
|
||||
@@ -380,49 +422,25 @@ int main(int argc, char *argv[]) {
|
||||
std::cerr << "ERROR: No project type has been specified!\n";
|
||||
return -1;
|
||||
|
||||
case kProjectCMake:
|
||||
if (setup.devTools || setup.tests) {
|
||||
std::cerr << "ERROR: Building tools or tests is not supported for the CMake project type!\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
addGCCWarnings(globalWarnings);
|
||||
|
||||
provider = new CreateProjectTool::CMakeProvider(globalWarnings, projectWarnings);
|
||||
|
||||
break;
|
||||
|
||||
case kProjectCodeBlocks:
|
||||
if (setup.devTools || setup.tests) {
|
||||
std::cerr << "ERROR: Building tools or tests is not supported for the CodeBlocks project type!\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Code::Blocks is using GCC behind the scenes, so we need to pass a list
|
||||
// of options to enable or disable warnings
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// -Wall
|
||||
// enable all warnings
|
||||
//
|
||||
// -Wno-long-long -Wno-multichar -Wno-unknown-pragmas -Wno-reorder
|
||||
// disable annoying and not-so-useful warnings
|
||||
//
|
||||
// -Wpointer-arith -Wcast-qual -Wcast-align
|
||||
// -Wshadow -Wimplicit -Wnon-virtual-dtor -Wwrite-strings
|
||||
// enable even more warnings...
|
||||
//
|
||||
// -fno-rtti -fno-exceptions -fcheck-new
|
||||
// disable RTTI and exceptions, and enable checking of pointers returned
|
||||
// by "new"
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
globalWarnings.push_back("-Wall");
|
||||
globalWarnings.push_back("-Wno-long-long");
|
||||
globalWarnings.push_back("-Wno-multichar");
|
||||
globalWarnings.push_back("-Wno-unknown-pragmas");
|
||||
globalWarnings.push_back("-Wno-reorder");
|
||||
globalWarnings.push_back("-Wpointer-arith");
|
||||
globalWarnings.push_back("-Wcast-qual");
|
||||
globalWarnings.push_back("-Wcast-align");
|
||||
globalWarnings.push_back("-Wshadow");
|
||||
globalWarnings.push_back("-Wimplicit");
|
||||
globalWarnings.push_back("-Wnon-virtual-dtor");
|
||||
globalWarnings.push_back("-Wwrite-strings");
|
||||
// The following are not warnings at all... We should consider adding them to
|
||||
// a different list of parameters.
|
||||
globalWarnings.push_back("-fno-exceptions");
|
||||
globalWarnings.push_back("-fcheck-new");
|
||||
addGCCWarnings(globalWarnings);
|
||||
|
||||
provider = new CreateProjectTool::CodeBlocksProvider(globalWarnings, projectWarnings);
|
||||
|
||||
@@ -636,6 +654,7 @@ void displayHelp(const char *exe) {
|
||||
" Additionally there are the following switches for changing various settings:\n"
|
||||
"\n"
|
||||
"Project specific settings:\n"
|
||||
" --cmake build CMake project files\n"
|
||||
" --codeblocks build Code::Blocks project files\n"
|
||||
" --msvc build Visual Studio project files\n"
|
||||
" --xcode build XCode project files\n"
|
||||
@@ -690,6 +709,41 @@ void displayHelp(const char *exe) {
|
||||
cout.setf(std::ios_base::right, std::ios_base::adjustfield);
|
||||
}
|
||||
|
||||
void addGCCWarnings(StringList &globalWarnings) {
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// -Wall
|
||||
// enable all warnings
|
||||
//
|
||||
// -Wno-long-long -Wno-multichar -Wno-unknown-pragmas -Wno-reorder
|
||||
// disable annoying and not-so-useful warnings
|
||||
//
|
||||
// -Wpointer-arith -Wcast-qual -Wcast-align
|
||||
// -Wshadow -Wimplicit -Wnon-virtual-dtor -Wwrite-strings
|
||||
// enable even more warnings...
|
||||
//
|
||||
// -fno-exceptions -fcheck-new
|
||||
// disable exceptions, and enable checking of pointers returned by "new"
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
globalWarnings.push_back("-Wall");
|
||||
globalWarnings.push_back("-Wno-long-long");
|
||||
globalWarnings.push_back("-Wno-multichar");
|
||||
globalWarnings.push_back("-Wno-unknown-pragmas");
|
||||
globalWarnings.push_back("-Wno-reorder");
|
||||
globalWarnings.push_back("-Wpointer-arith");
|
||||
globalWarnings.push_back("-Wcast-qual");
|
||||
globalWarnings.push_back("-Wcast-align");
|
||||
globalWarnings.push_back("-Wshadow");
|
||||
globalWarnings.push_back("-Wnon-virtual-dtor");
|
||||
globalWarnings.push_back("-Wwrite-strings");
|
||||
// The following are not warnings at all... We should consider adding them to
|
||||
// a different list of parameters.
|
||||
globalWarnings.push_back("-fno-exceptions");
|
||||
globalWarnings.push_back("-fcheck-new");
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the configure.engine file of a given engine directory and return a
|
||||
* list of all defined engines.
|
||||
@@ -937,12 +991,12 @@ const Feature s_features[] = {
|
||||
// Libraries
|
||||
{ "libz", "USE_ZLIB", "zlib", true, "zlib (compression) support" },
|
||||
{ "mad", "USE_MAD", "libmad", true, "libmad (MP3) support" },
|
||||
{ "vorbis", "USE_VORBIS", "libvorbisfile_static libvorbis_static libogg_static", false, "Ogg Vorbis support" },
|
||||
{ "flac", "USE_FLAC", "libFLAC_static win_utf8_io_static", false, "FLAC support" },
|
||||
{ "vorbis", "USE_VORBIS", "libvorbisfile_static libvorbis_static libogg_static", false, "Ogg Vorbis support" }, // ResidualVM change
|
||||
{ "flac", "USE_FLAC", "libFLAC_static win_utf8_io_static", false, "FLAC support" }, // ResidualVM change
|
||||
{ "png", "USE_PNG", "libpng", false, "libpng support" },
|
||||
{ "faad", "USE_FAAD", "libfaad", false, "AAC support" },
|
||||
{ "mpeg2", "USE_MPEG2", "libmpeg2", true, "MPEG-2 support" },
|
||||
{ "theora", "USE_THEORADEC", "libtheora_static", false, "Theora decoding support" },
|
||||
{ "mpeg2", "USE_MPEG2", "libmpeg2", true, "MPEG-2 support" }, // ResidualVM change
|
||||
{ "theora", "USE_THEORADEC", "libtheora_static", false, "Theora decoding support" }, // ResidualVM change
|
||||
{ "freetype", "USE_FREETYPE2", "freetype", true, "FreeType support" },
|
||||
{ "jpeg", "USE_JPEG", "jpeg-static", true, "libjpeg support" },
|
||||
{"fluidsynth", "USE_FLUIDSYNTH", "libfluidsynth", true, "FluidSynth support" },
|
||||
@@ -952,29 +1006,22 @@ const Feature s_features[] = {
|
||||
{ "scalers", "USE_SCALERS", "", true, "Scalers" },
|
||||
{ "hqscalers", "USE_HQ_SCALERS", "", true, "HQ scalers" },
|
||||
{ "16bit", "USE_RGB_COLOR", "", true, "16bit color support" },
|
||||
{ "mt32emu", "USE_MT32EMU", "", false, "integrated MT-32 emulator" },
|
||||
{ "mt32emu", "USE_MT32EMU", "", false, "integrated MT-32 emulator" }, // ResidualVM change
|
||||
{ "nasm", "USE_NASM", "", true, "IA-32 assembly support" }, // This feature is special in the regard, that it needs additional handling.
|
||||
{ "opengl", "USE_OPENGL", "opengl32", true, "OpenGL support" },
|
||||
{ "opengl", "USE_OPENGL", "", true, "OpenGL support" },
|
||||
{ "opengles", "USE_GLES", "", true, "forced OpenGL ES mode" },
|
||||
{ "taskbar", "USE_TASKBAR", "", true, "Taskbar integration support" },
|
||||
{ "translation", "USE_TRANSLATION", "", true, "Translation support" },
|
||||
{ "vkeybd", "ENABLE_VKEYBD", "", false, "Virtual keyboard support"},
|
||||
{ "keymapper", "ENABLE_KEYMAPPER", "", false, "Keymapper support"},
|
||||
{ "eventrecorder", "ENABLE_EVENTRECORDER", "", false, "Event recorder support"},
|
||||
{ "updates", "USE_UPDATES", "", false, "Updates support"},
|
||||
{ "langdetect", "USE_DETECTLANG", "", true, "System language detection support" } // This feature actually depends on "translation", there
|
||||
// is just no current way of properly detecting this...
|
||||
};
|
||||
|
||||
const Tool s_tools[] = {
|
||||
{ "create_drascula", true},
|
||||
{ "create_hugo", true},
|
||||
{ "create_kyradat", true},
|
||||
{ "create_lure", true},
|
||||
{ "create_neverhood", true},
|
||||
{ "create_teenagent", true},
|
||||
{ "create_tony", true},
|
||||
{ "create_toon", true},
|
||||
{ "create_translations", true},
|
||||
{ "qtable", true}
|
||||
};
|
||||
} // End of anonymous namespace
|
||||
|
||||
@@ -1156,7 +1203,7 @@ bool compareNodes(const FileNode *l, const FileNode *r) {
|
||||
|
||||
FileList listDirectory(const std::string &dir) {
|
||||
FileList result;
|
||||
#ifdef USE_WIN32_API
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
WIN32_FIND_DATA fileInformation;
|
||||
HANDLE fileHandle = FindFirstFile((dir + "/*").c_str(), &fileInformation);
|
||||
|
||||
@@ -1359,7 +1406,7 @@ void ProjectProvider::createProject(BuildSetup &setup) {
|
||||
in.push_back(setup.srcDir + "/COPYING.FREEFONT");
|
||||
in.push_back(setup.srcDir + "/COPYRIGHT");
|
||||
in.push_back(setup.srcDir + "/NEWS");
|
||||
in.push_back(setup.srcDir + "/README.md");
|
||||
in.push_back(setup.srcDir + "/README.md"); // ResidualVM change
|
||||
in.push_back(setup.srcDir + "/TODO");
|
||||
|
||||
// Create the main project file.
|
||||
|
||||
@@ -229,15 +229,17 @@ struct BuildSetup {
|
||||
StringList testDirs; ///< List of all folders containing tests
|
||||
|
||||
bool devTools; ///< Generate project files for the tools
|
||||
bool tests; ///< Generate project files for the tests
|
||||
bool tests; ///< Generate project files for the tests
|
||||
bool runBuildEvents; ///< Run build events as part of the build (generate revision number and copy engine/theme data & needed files to the build folder
|
||||
bool createInstaller; ///< Create NSIS installer after the build
|
||||
bool useSDL2; ///< Whether to use SDL2 or not.
|
||||
|
||||
BuildSetup() {
|
||||
devTools = false;
|
||||
tests = false;
|
||||
runBuildEvents = false;
|
||||
createInstaller = false;
|
||||
useSDL2 = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
MODULE := devtools/create_project
|
||||
|
||||
MODULE_OBJS := \
|
||||
cmake.o \
|
||||
create_project.o \
|
||||
codeblocks.o \
|
||||
msvc.o \
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user