mirror of
https://github.com/libretro/scummvm.git
synced 2024-11-30 12:50:51 +00:00
Merged revisions 33052-33053,33056-33058,33061-33064,33068,33070,33072,33075,33078-33079,33083,33086-33087,33089,33094-33096,33098-33099,33104,33108-33109,33114-33117,33120,33135-33146,33160,33162,33165,33167-33169 via svnmerge from
https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk svn-id: r33183
This commit is contained in:
commit
09f4fd946e
@ -132,8 +132,7 @@ bail:
|
||||
return MERR_DEVICE_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
void MidiDriver_QT::close()
|
||||
{
|
||||
void MidiDriver_QT::close() {
|
||||
MidiDriver_MPU401::close();
|
||||
dispose();
|
||||
}
|
||||
@ -248,8 +247,7 @@ void MidiDriver_QT::setPitchBendRange (byte channel, uint range) {
|
||||
NASetController(qtNoteAllocator, qtNoteChannel[channel], kControllerPitchBend, theBend);
|
||||
}
|
||||
|
||||
void MidiDriver_QT::dispose()
|
||||
{
|
||||
void MidiDriver_QT::dispose() {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (qtNoteChannel[i] != 0)
|
||||
NADisposeNoteChannel(qtNoteAllocator, qtNoteChannel[i]);
|
||||
|
@ -19,16 +19,17 @@ RM = rm -f
|
||||
srcdir = ../../..
|
||||
VPATH = $(srcdir)
|
||||
INCDIR = ../../../
|
||||
DEPDIR = .deps
|
||||
|
||||
DEFINES = -DUSE_VORBIS -DUSE_TREMOR -DUSE_MAD -DUSE_MPEG2 -DUSE_ZLIB -D_EE -D__PLAYSTATION2__ -O2 -Wall -Wno-multichar
|
||||
|
||||
# PS2SDK-Ports from ps2dev.org's SVN repository for libmad, zlib and ucl
|
||||
PS2SDK_PORTS = /home/robby/libStuffNew/ps2sdk-ports
|
||||
PS2SDK_PORTS = /mnt/winxp/scummvm/ports
|
||||
PS2SDK_PORTS_INCS = /ucl /zlib/include /libmad/ee/include
|
||||
PS2SDK_PORTS_LIBS = /ucl /zlib/lib /libmad/ee/lib
|
||||
|
||||
# we also need SjPcm, Tremor and libmpeg2
|
||||
MORE_LIBS_DIR = /home/robby/libStuff
|
||||
MORE_LIBS_DIR = /mnt/winxp/scummvm/ports
|
||||
MORE_LIBS_INCS = /SjPcm/ee/src /mpeg2dec/include /tremor
|
||||
MORE_LIBS_LIBS = /SjPcm/ee/lib /mpeg2dec/libmpeg2 /tremor/tremor
|
||||
|
||||
|
@ -340,8 +340,6 @@ FILE *ps2_fopen(const char *fname, const char *mode) {
|
||||
assert(cacheListSema >= 0);
|
||||
}
|
||||
|
||||
//printf("ps2_fopen: %s, %s\n", fname, mode);
|
||||
|
||||
if (((mode[0] != 'r') && (mode[0] != 'w')) || ((mode[1] != '\0') && (mode[1] != 'b'))) {
|
||||
printf("unsupported mode \"%s\" for file \"%s\"\n", mode, fname);
|
||||
return NULL;
|
||||
@ -363,6 +361,8 @@ FILE *ps2_fopen(const char *fname, const char *mode) {
|
||||
} else {
|
||||
// Regular access to one of the devices
|
||||
|
||||
printf("ps2_fopen = %s\n", fname); // romeo : temp
|
||||
|
||||
if (!rdOnly)
|
||||
return NULL; // we only provide readaccess for cd,dvd,hdd,usb
|
||||
|
||||
@ -378,19 +378,22 @@ FILE *ps2_fopen(const char *fname, const char *mode) {
|
||||
}
|
||||
|
||||
int64 cacheId = -1;
|
||||
if (rdOnly && tocManager.haveEntries())
|
||||
if (tocManager.haveEntries())
|
||||
cacheId = tocManager.fileExists(fname);
|
||||
|
||||
if (cacheId != 0) {
|
||||
Ps2File *file = findInCache(cacheId);
|
||||
if (file)
|
||||
if (file) {
|
||||
printf(" findInCache(%x)\n", cacheId); // romeo : temp
|
||||
return (FILE*)file;
|
||||
}
|
||||
|
||||
bool isAudioFile = strstr(fname, ".bun") || strstr(fname, ".BUN") || strstr(fname, ".Bun");
|
||||
file = new Ps2ReadFile(cacheId, isAudioFile);
|
||||
|
||||
if (file->open(fname)) {
|
||||
openFileCount++;
|
||||
printf(" new cacheID = %x\n", cacheId); // romeo : temp
|
||||
return (FILE*)file;
|
||||
} else
|
||||
delete file;
|
||||
@ -579,7 +582,7 @@ void TocManager::readEntries(const char *root) {
|
||||
}
|
||||
char readPath[256];
|
||||
sprintf(readPath, "%s/", _root);
|
||||
printf("readDir: %s\n", readPath);
|
||||
printf("readDir: %s (root: %s )\n", readPath, root);
|
||||
readDir(readPath, &_rootNode, 0);
|
||||
}
|
||||
|
||||
@ -587,28 +590,62 @@ void TocManager::readDir(const char *path, TocNode **node, int level) {
|
||||
if (level <= 2) { // we don't scan deeper than that
|
||||
iox_dirent_t dirent;
|
||||
int fd = fio.dopen(path);
|
||||
if (fd >= 0) {
|
||||
while (fio.dread(fd, &dirent) > 0)
|
||||
if (dirent.name[0] != '.') { // skip '.' and '..'
|
||||
*node = new TocNode;
|
||||
(*node)->sub = (*node)->next = NULL;
|
||||
TocNode *eNode = NULL; // = *node; // entry node
|
||||
bool first = true;
|
||||
|
||||
printf("path=%s - level=%d fd=%d\n", path, level, fd); // romeo : temp
|
||||
if (fd >= 0) {
|
||||
while (fio.dread(fd, &dirent) > 0) {
|
||||
if (dirent.name[0] != '.') { // skip '.' & '..' - romeo : check
|
||||
// --- do we have them on PS2?
|
||||
*node = new TocNode;
|
||||
if (first) {
|
||||
eNode = *node;
|
||||
first = false;
|
||||
}
|
||||
(*node)->sub = (*node)->next = NULL;
|
||||
(*node)->nameLen = strlen(dirent.name);
|
||||
memcpy((*node)->name, dirent.name, (*node)->nameLen + 1);
|
||||
|
||||
if (dirent.stat.mode & FIO_S_IFDIR) { // directory
|
||||
if (dirent.stat.mode & FIO_S_IFDIR) {
|
||||
(*node)->isDir = true;
|
||||
char nextPath[256];
|
||||
sprintf(nextPath, "%s%s/", path, dirent.name);
|
||||
readDir(nextPath, &((*node)->sub), level + 1);
|
||||
} else
|
||||
printf("dirent.name = %s [DIR]\n", dirent.name);
|
||||
}
|
||||
else {
|
||||
(*node)->isDir = false;
|
||||
printf("dirent.name = %s\n", dirent.name);
|
||||
}
|
||||
|
||||
node = &((*node)->next);
|
||||
}
|
||||
}
|
||||
|
||||
fio.dclose(fd);
|
||||
} else
|
||||
printf("Can't open path: %s\n", path);
|
||||
}
|
||||
|
||||
TocNode *iNode = eNode;
|
||||
char nextPath[256];
|
||||
|
||||
while (iNode) {
|
||||
if (iNode->isDir == true) {
|
||||
sprintf(nextPath, "%s%s/", path, iNode->name);
|
||||
readDir(nextPath, &(iNode->sub), level + 1);
|
||||
}
|
||||
iNode = iNode->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
** Wizard of Oz' trick (to get all games running from USB on PS2):
|
||||
|
||||
1. Make a list of files / dirs in level #0 (dclose before continuing)
|
||||
|
||||
2. Go through the dirs : dopen / dread them / mark dirs / dclose
|
||||
|
||||
It's a safe recursion, cause it recurses on 'isDir' nodes
|
||||
after dclosing the higher hierarchy
|
||||
*/
|
||||
}
|
||||
|
||||
int64 TocManager::fileExists(const char *name) {
|
||||
|
30
backends/platform/ps2/iop/rpckbd/Makefile
Normal file
30
backends/platform/ps2/iop/rpckbd/Makefile
Normal file
@ -0,0 +1,30 @@
|
||||
# _____ ___ ____ ___ ____
|
||||
# ____| | ____| | | |____|
|
||||
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
|
||||
# Licenced under Academic Free License version 2.0
|
||||
# Review ps2sdk README & LICENSE files for further details.
|
||||
#
|
||||
# $Id$
|
||||
|
||||
|
||||
IOP_OBJS_DIR = obj/
|
||||
IOP_BIN_DIR = bin/
|
||||
IOP_SRC_DIR = src/
|
||||
IOP_INC_DIR = include/
|
||||
|
||||
IOP_BIN=bin/rpckbd.irx
|
||||
IOP_OBJS=obj/ps2kbd.o obj/imports.o
|
||||
|
||||
IOP_CFLAGS=-Wall
|
||||
IOP_INCS += -I$(PS2SDKSRC)/iop/usb/usbd/include
|
||||
|
||||
all: $(IOP_OBJS_DIR) $(IOP_BIN_DIR) $(IOP_BIN)
|
||||
|
||||
clean:
|
||||
rm -f -r $(IOP_OBJS_DIR) $(IOP_BIN_DIR)
|
||||
|
||||
include $(PS2SDKSRC)/Defs.make
|
||||
include $(PS2SDKSRC)/iop/Rules.make
|
||||
include $(PS2SDKSRC)/iop/Rules.release
|
90
backends/platform/ps2/iop/rpckbd/include/ps2kbd.h
Normal file
90
backends/platform/ps2/iop/rpckbd/include/ps2kbd.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
# _____ ___ ____ ___ ____
|
||||
# ____| | ____| | | |____|
|
||||
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright 2001-2004, ps2dev - http://www.ps2dev.org
|
||||
# Licenced under Academic Free License version 2.0
|
||||
# Review ps2sdk README & LICENSE files for further details.
|
||||
#
|
||||
# $Id$
|
||||
# USB Keyboard Driver for PS2
|
||||
*/
|
||||
|
||||
#ifndef __PS2KBD_H__
|
||||
#define __PS2KBD_H__
|
||||
|
||||
#define PS2KBD_RPC_ID 0xb0b0b80
|
||||
|
||||
#define PS2KBD_LED_NUMLOCK 1
|
||||
#define PS2KBD_LED_CAPSLOCK 2
|
||||
#define PS2KBD_LED_SCRLOCK 4
|
||||
#define PS2KBD_LED_COMPOSE 8
|
||||
#define PS2KBD_LED_KANA 16
|
||||
|
||||
#define PS2KBD_LED_MASK 0x1F;
|
||||
|
||||
#define PS2KBD_ESCAPE_KEY 0x1B
|
||||
|
||||
#define PS2KBD_LEFT_CTRL (1 << 0)
|
||||
#define PS2KBD_LEFT_SHIFT (1 << 1)
|
||||
#define PS2KBD_LEFT_ALT (1 << 2)
|
||||
#define PS2KBD_LEFT_GUI (1 << 3)
|
||||
#define PS2KBD_RIGHT_CTRL (1 << 4)
|
||||
#define PS2KBD_RIGHT_SHIFT (1 << 5)
|
||||
#define PS2KBD_RIGHT_ALT (1 << 6)
|
||||
#define PS2KBD_RIGHT_GUI (1 << 7)
|
||||
|
||||
#define PS2KBD_CTRL (PS2KBD_LEFT_CTRL | PS2KBD_RIGHT_CTRL)
|
||||
#define PS2KBD_SHIFT (PS2KBD_LEFT_SHIFT | PS2KBD_RIGHT_SHIFT)
|
||||
#define PS2KBD_ALT (PS2KBD_LEFT_ALT | PS2KBD_RIGHT_ALT)
|
||||
#define PS2KBD_GUI (PS2KBD_LEFT_GUI | PS2KBD_RIGHT_GUI)
|
||||
|
||||
#define PS2KBD_RAWKEY_UP 0xF0
|
||||
#define PS2KBD_RAWKEY_DOWN 0xF1
|
||||
|
||||
typedef struct _kbd_rawkey {
|
||||
u8 state;
|
||||
u8 key;
|
||||
} kbd_rawkey __attribute__ ((packed));
|
||||
|
||||
#define PS2KBD_READMODE_NORMAL 1
|
||||
#define PS2KBD_READMODE_RAW 2
|
||||
|
||||
/* Notes on read mode */
|
||||
/* In normal readmode (default) read multiples of 1 character off the keyboard file. These are
|
||||
processed by the keymaps so that you get back ASCII data */
|
||||
/* In raw readmode must read multiples of 2. First byte indicates state (i.e. Up or Down)
|
||||
Second byte is the USB key code for that key. This table is presented in the USB HID Usage Tables manaual
|
||||
from usb.org */
|
||||
|
||||
#define PS2KBD_KEYMAP_SIZE 256
|
||||
|
||||
typedef struct _kbd_keymap
|
||||
|
||||
{
|
||||
u8 keymap[PS2KBD_KEYMAP_SIZE];
|
||||
u8 shiftkeymap[PS2KBD_KEYMAP_SIZE];
|
||||
u8 keycap[PS2KBD_KEYMAP_SIZE];
|
||||
} kbd_keymap;
|
||||
|
||||
|
||||
/* IRPC function numbers */
|
||||
#define KBD_RPC_SETREADMODE 1 /* Sets up keymapped or raw mode */
|
||||
#define KBD_RPC_SETLEDS 2 /* Sets the LED state for ALL keyboards connected */
|
||||
#define KBD_RPC_SETREPEATRATE 3 /* Sets the repeat rate of the keyboard */
|
||||
#define KBD_RPC_SETKEYMAP 4 /* Sets the keymap for the standard keys, non shifted and shifted */
|
||||
#define KBD_RPC_SETCTRLMAP 5 /* Sets the control key mapping */
|
||||
#define KBD_RPC_SETALTMAP 6 /* Sets the alt key mapping */
|
||||
#define KBD_RPC_SETSPECIALMAP 7 /* Sets the special key mapping */
|
||||
#define KBD_RPC_FLUSHBUFFER 9 /* Flush the internal buffer, probably best after a keymap change */
|
||||
#define KBD_RPC_RESETKEYMAP 10 /* Reset keymaps to default states */
|
||||
#define KBD_RPC_READKEY 11
|
||||
#define KBD_RPC_READRAW 12
|
||||
|
||||
/* Note on keymaps. In normal keymap a 0 would indicate no key */
|
||||
/* Key maps are represented by 3 256*8bit tables. First table maps USB key to a char when not shifted */
|
||||
/* Second table maps USB key to a char when shifted */
|
||||
/* Third table contains boolean values. If 1 then the key is shifted/unshifted in capslock, else capslock is ignored */
|
||||
|
||||
#endif
|
58
backends/platform/ps2/iop/rpckbd/src/imports.lst
Normal file
58
backends/platform/ps2/iop/rpckbd/src/imports.lst
Normal file
@ -0,0 +1,58 @@
|
||||
|
||||
sysclib_IMPORTS_start
|
||||
I_memset
|
||||
I_strcmp
|
||||
I_memcpy
|
||||
sysclib_IMPORTS_end
|
||||
|
||||
loadcore_IMPORTS_start
|
||||
I_FlushDcache
|
||||
loadcore_IMPORTS_end
|
||||
|
||||
sifcmd_IMPORTS_start
|
||||
I_sceSifInitRpc
|
||||
I_sceSifSetRpcQueue
|
||||
I_sceSifRegisterRpc
|
||||
I_sceSifRpcLoop
|
||||
sifcmd_IMPORTS_end
|
||||
|
||||
stdio_IMPORTS_start
|
||||
I_printf
|
||||
stdio_IMPORTS_end
|
||||
|
||||
thsemap_IMPORTS_start
|
||||
I_CreateSema
|
||||
I_SignalSema
|
||||
I_WaitSema
|
||||
I_PollSema
|
||||
I_DeleteSema
|
||||
thsemap_IMPORTS_end
|
||||
|
||||
thbase_IMPORTS_start
|
||||
I_StartThread
|
||||
I_CreateThread
|
||||
I_USec2SysClock
|
||||
I_iSetAlarm
|
||||
I_SetAlarm
|
||||
I_CancelAlarm
|
||||
thbase_IMPORTS_end
|
||||
|
||||
thevent_IMPORTS_start
|
||||
I_WaitEventFlag
|
||||
I_iSetEventFlag
|
||||
I_CreateEventFlag
|
||||
thevent_IMPORTS_end
|
||||
|
||||
sysmem_IMPORTS_start
|
||||
I_AllocSysMemory
|
||||
I_FreeSysMemory
|
||||
sysmem_IMPORTS_end
|
||||
|
||||
usbd_IMPORTS_start
|
||||
I_UsbGetDeviceStaticDescriptor
|
||||
I_UsbOpenEndpoint
|
||||
I_UsbSetDevicePrivateData
|
||||
I_UsbTransfer
|
||||
I_UsbRegisterDriver
|
||||
usbd_IMPORTS_end
|
||||
|
35
backends/platform/ps2/iop/rpckbd/src/irx_imports.h
Normal file
35
backends/platform/ps2/iop/rpckbd/src/irx_imports.h
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
# _____ ___ ____ ___ ____
|
||||
# ____| | ____| | | |____|
|
||||
# | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
|
||||
#-----------------------------------------------------------------------
|
||||
# Copyright (c) 2003 Marcus R. Brown <mrbrown@0xd6.org>
|
||||
# Licenced under Academic Free License version 2.0
|
||||
# Review ps2sdk README & LICENSE files for further details.
|
||||
#
|
||||
# $Id$
|
||||
# Defines all IRX imports.
|
||||
*/
|
||||
|
||||
#ifndef IOP_IRX_IMPORTS_H
|
||||
#define IOP_IRX_IMPORTS_H
|
||||
|
||||
#include "irx.h"
|
||||
|
||||
/* Please keep these in alphabetical order! */
|
||||
#include "dmacman.h"
|
||||
#include "intrman.h"
|
||||
#include "libsd.h"
|
||||
#include "loadcore.h"
|
||||
#include "sifcmd.h"
|
||||
#include "stdio.h"
|
||||
#include "sysclib.h"
|
||||
#include "sysmem.h"
|
||||
#include "thbase.h"
|
||||
#include "thevent.h"
|
||||
#include "thmsgbx.h"
|
||||
#include "thsemap.h"
|
||||
#include "usbd.h"
|
||||
#include "vblank.h"
|
||||
|
||||
#endif /* IOP_IRX_IMPORTS_H */
|
1199
backends/platform/ps2/iop/rpckbd/src/ps2kbd.c
Normal file
1199
backends/platform/ps2/iop/rpckbd/src/ps2kbd.c
Normal file
File diff suppressed because it is too large
Load Diff
1579
backends/platform/ps2/iop/rpckbd/src/us_keymap.h
Normal file
1579
backends/platform/ps2/iop/rpckbd/src/us_keymap.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -43,7 +43,7 @@ IrxFile irxFiles[] = {
|
||||
{ "PADMAN", BIOS, NOTHING, NULL, 0 },
|
||||
{ "LIBSD", BIOS, NOTHING, NULL, 0 },
|
||||
|
||||
{ "IOMANX.IRX", SYSTEM | NOT_HOST, NOTHING, NULL, 0 }, // already loaded by ps2link
|
||||
{ "IOMANX.IRX", SYSTEM /*| NOT_HOST*/, NOTHING, NULL, 0 }, // already loaded by ps2link
|
||||
{ "FILEXIO.IRX", SYSTEM, NOTHING, NULL, 0 },
|
||||
{ "CODYVDFS.IRX", SYSTEM, NOTHING, NULL, 0 },
|
||||
{ "SJPCM.IRX", SYSTEM, NOTHING, NULL, 0 },
|
||||
|
@ -54,9 +54,11 @@
|
||||
#include "graphics/surface.h"
|
||||
#include "graphics/font.h"
|
||||
#include "backends/timer/default/default-timer.h"
|
||||
#include "sound/mixer.h"
|
||||
#include "sound/mixer_intern.h"
|
||||
#include "common/events.h"
|
||||
#include "backends/platform/ps2/ps2debug.h"
|
||||
#include "backends/fs/ps2/ps2-fs-factory.h"
|
||||
|
||||
// asm("mfc0 %0, $9\n" : "=r"(tickStart));
|
||||
|
||||
extern void *_gp;
|
||||
@ -309,7 +311,9 @@ OSystem_PS2::OSystem_PS2(const char *elfPath) {
|
||||
void OSystem_PS2::init(void) {
|
||||
sioprintf("Timer...\n");
|
||||
_scummTimerManager = new DefaultTimerManager();
|
||||
_scummMixer = new Audio::Mixer();
|
||||
_scummMixer = new Audio::MixerImpl(this);
|
||||
_scummMixer->setOutputRate(44100);
|
||||
_scummMixer->setReady(true);
|
||||
initTimer();
|
||||
|
||||
sioprintf("Starting SavefileManager\n");
|
||||
@ -410,7 +414,8 @@ void OSystem_PS2::soundThread(void) {
|
||||
// we have to produce more samples, call sound mixer
|
||||
// the scratchpad at 0x70000000 is used as temporary soundbuffer
|
||||
//_scummSoundProc(_scummSoundParam, (uint8*)0x70000000, SMP_PER_BLOCK * 2 * sizeof(int16));
|
||||
Audio::Mixer::mixCallback(_scummMixer, (byte*)0x70000000, SMP_PER_BLOCK * 2 * sizeof(int16));
|
||||
// Audio::Mixer::mixCallback(_scummMixer, (byte*)0x70000000, SMP_PER_BLOCK * 2 * sizeof(int16));
|
||||
_scummMixer->mixCallback((byte*)0x70000000, SMP_PER_BLOCK * 2 * sizeof(int16));
|
||||
|
||||
// demux data into 2 buffers, L and R
|
||||
__asm__ (
|
||||
@ -534,10 +539,6 @@ Common::TimerManager *OSystem_PS2::getTimerManager() {
|
||||
return _scummTimerManager;
|
||||
}
|
||||
|
||||
int OSystem_PS2::getOutputSampleRate(void) const {
|
||||
return 48000;
|
||||
}
|
||||
|
||||
Audio::Mixer *OSystem_PS2::getMixer() {
|
||||
return _scummMixer;
|
||||
}
|
||||
@ -546,6 +547,10 @@ Common::SaveFileManager *OSystem_PS2::getSavefileManager(void) {
|
||||
return _saveManager;
|
||||
}
|
||||
|
||||
FilesystemFactory *OSystem_PS2::getFilesystemFactory() {
|
||||
return &Ps2FilesystemFactory::instance();
|
||||
}
|
||||
|
||||
void OSystem_PS2::setShakePos(int shakeOffset) {
|
||||
_screen->setShakePos(shakeOffset);
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ class DefaultTimerManager;
|
||||
class Gs2dScreen;
|
||||
class Ps2Input;
|
||||
class Ps2SaveFileManager;
|
||||
// class Ps2FilesystemFactory;
|
||||
struct IrxReference;
|
||||
|
||||
#define MAX_MUTEXES 16
|
||||
@ -48,7 +49,7 @@ namespace Common {
|
||||
};
|
||||
|
||||
namespace Audio {
|
||||
class Mixer;
|
||||
class MixerImpl;
|
||||
};
|
||||
|
||||
class OSystem_PS2 : public OSystem {
|
||||
@ -87,7 +88,6 @@ public:
|
||||
virtual bool pollEvent(Common::Event &event);
|
||||
|
||||
virtual Audio::Mixer *getMixer();
|
||||
virtual int getOutputSampleRate(void) const;
|
||||
|
||||
virtual bool openCD(int drive);
|
||||
virtual bool pollCD();
|
||||
@ -112,6 +112,7 @@ public:
|
||||
virtual void colorToRGB(OverlayColor color, uint8 &r, uint8 &g, uint8 &b);
|
||||
|
||||
virtual Common::SaveFileManager *getSavefileManager();
|
||||
virtual FilesystemFactory *getFilesystemFactory();
|
||||
|
||||
virtual void getTimeAndDate(struct tm &t) const;
|
||||
|
||||
@ -133,7 +134,7 @@ private:
|
||||
void readRtcTime(void);
|
||||
|
||||
DefaultTimerManager *_scummTimerManager;
|
||||
Audio::Mixer *_scummMixer;
|
||||
Audio::MixerImpl *_scummMixer;
|
||||
|
||||
|
||||
bool _mouseVisible;
|
||||
|
@ -191,7 +191,7 @@ OSystem_SDL::OSystem_SDL()
|
||||
|
||||
OSystem_SDL::~OSystem_SDL() {
|
||||
SDL_RemoveTimer(_timerID);
|
||||
SDL_CloseAudio();
|
||||
closeMixer();
|
||||
|
||||
free(_dirtyChecksums);
|
||||
free(_currentPalette);
|
||||
@ -199,7 +199,6 @@ OSystem_SDL::~OSystem_SDL() {
|
||||
free(_mouseData);
|
||||
|
||||
delete _savefile;
|
||||
delete _mixer;
|
||||
delete _timer;
|
||||
}
|
||||
|
||||
@ -306,7 +305,7 @@ void OSystem_SDL::quit() {
|
||||
SDL_ShowCursor(SDL_ENABLE);
|
||||
|
||||
SDL_RemoveTimer(_timerID);
|
||||
SDL_CloseAudio();
|
||||
closeMixer();
|
||||
|
||||
free(_dirtyChecksums);
|
||||
free(_currentPalette);
|
||||
@ -314,7 +313,6 @@ void OSystem_SDL::quit() {
|
||||
free(_mouseData);
|
||||
|
||||
delete _savefile;
|
||||
delete _mixer;
|
||||
delete _timer;
|
||||
|
||||
SDL_Quit();
|
||||
@ -389,14 +387,110 @@ void OSystem_SDL::deleteMutex(MutexRef mutex) {
|
||||
#pragma mark --- Audio ---
|
||||
#pragma mark -
|
||||
|
||||
#ifdef MIXER_DOUBLE_BUFFERING
|
||||
|
||||
void OSystem_SDL::mixerProducerThread() {
|
||||
byte nextSoundBuffer;
|
||||
|
||||
SDL_LockMutex(_soundMutex);
|
||||
while (true) {
|
||||
// Wait till we are allowed to produce data
|
||||
SDL_CondWait(_soundCond, _soundMutex);
|
||||
|
||||
if (_soundThreadShouldQuit)
|
||||
break;
|
||||
|
||||
// Generate samples and put them into the next buffer
|
||||
nextSoundBuffer = _activeSoundBuf ^ 1;
|
||||
_mixer->mixCallback(_soundBuffers[nextSoundBuffer], _soundBufSize);
|
||||
|
||||
// Swap buffers
|
||||
_activeSoundBuf = nextSoundBuffer;
|
||||
}
|
||||
SDL_UnlockMutex(_soundMutex);
|
||||
}
|
||||
|
||||
int SDLCALL OSystem_SDL::mixerProducerThreadEntry(void *arg) {
|
||||
OSystem_SDL *this_ = (OSystem_SDL *)arg;
|
||||
assert(this_);
|
||||
this_->mixerProducerThread();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void OSystem_SDL::initThreadedMixer(Audio::MixerImpl *mixer, uint bufSize) {
|
||||
_soundThreadIsRunning = false;
|
||||
_soundThreadShouldQuit = false;
|
||||
|
||||
// Create mutex and condition variable
|
||||
_soundMutex = SDL_CreateMutex();
|
||||
_soundCond = SDL_CreateCond();
|
||||
|
||||
// Create two sound buffers
|
||||
_activeSoundBuf = 0;
|
||||
_soundBufSize = bufSize;
|
||||
_soundBuffers[0] = (byte *)calloc(1, bufSize);
|
||||
_soundBuffers[1] = (byte *)calloc(1, bufSize);
|
||||
|
||||
_soundThreadIsRunning = true;
|
||||
|
||||
// Finally start the thread
|
||||
_soundThread = SDL_CreateThread(mixerProducerThreadEntry, this);
|
||||
}
|
||||
|
||||
void OSystem_SDL::deinitThreadedMixer() {
|
||||
// Kill thread?? _soundThread
|
||||
|
||||
if (_soundThreadIsRunning) {
|
||||
// Signal the producer thread to end, and wait for it to actually finish.
|
||||
_soundThreadShouldQuit = true;
|
||||
SDL_CondBroadcast(_soundCond);
|
||||
SDL_WaitThread(_soundThread, NULL);
|
||||
|
||||
// Kill the mutex & cond variables.
|
||||
// Attention: AT this point, the mixer callback must not be running
|
||||
// anymore, else we will crash!
|
||||
SDL_DestroyMutex(_soundMutex);
|
||||
SDL_DestroyCond(_soundCond);
|
||||
|
||||
_soundThreadIsRunning = false;
|
||||
|
||||
free(_soundBuffers[0]);
|
||||
free(_soundBuffers[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void OSystem_SDL::mixCallback(void *arg, byte *samples, int len) {
|
||||
OSystem_SDL *this_ = (OSystem_SDL *)arg;
|
||||
assert(this_);
|
||||
assert(this_->_mixer);
|
||||
|
||||
assert((int)this_->_soundBufSize == len);
|
||||
|
||||
// Lock mutex, to ensure our data is not overwritten by the producer thread
|
||||
SDL_LockMutex(this_->_soundMutex);
|
||||
|
||||
// Copy data from the current sound buffer
|
||||
memcpy(samples, this_->_soundBuffers[this_->_activeSoundBuf], len);
|
||||
|
||||
// Unlock mutex and wake up the produced thread
|
||||
SDL_UnlockMutex(this_->_soundMutex);
|
||||
SDL_CondSignal(this_->_soundCond);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void OSystem_SDL::mixCallback(void *sys, byte *samples, int len) {
|
||||
OSystem_SDL *this_ = (OSystem_SDL *)sys;
|
||||
assert(this_);
|
||||
assert(this_->_mixer);
|
||||
|
||||
if (this_->_mixer)
|
||||
this_->_mixer->mixCallback(samples, len);
|
||||
this_->_mixer->mixCallback(samples, len);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void OSystem_SDL::setupMixer() {
|
||||
SDL_AudioSpec desired;
|
||||
SDL_AudioSpec obtained;
|
||||
@ -443,10 +537,31 @@ void OSystem_SDL::setupMixer() {
|
||||
// Tell the mixer that we are ready and start the sound processing
|
||||
_mixer->setOutputRate(_samplesPerSec);
|
||||
_mixer->setReady(true);
|
||||
|
||||
#ifdef MIXER_DOUBLE_BUFFERING
|
||||
initThreadedMixer(_mixer, obtained.samples * 4);
|
||||
#endif
|
||||
|
||||
// start the sound system
|
||||
SDL_PauseAudio(0);
|
||||
}
|
||||
}
|
||||
|
||||
void OSystem_SDL::closeMixer() {
|
||||
if (_mixer)
|
||||
_mixer->setReady(false);
|
||||
|
||||
SDL_CloseAudio();
|
||||
|
||||
delete _mixer;
|
||||
_mixer = 0;
|
||||
|
||||
#ifdef MIXER_DOUBLE_BUFFERING
|
||||
deinitThreadedMixer();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
Audio::Mixer *OSystem_SDL::getMixer() {
|
||||
assert(_mixer);
|
||||
return _mixer;
|
||||
|
@ -51,6 +51,15 @@ namespace Common {
|
||||
#define USE_OSD 1
|
||||
#endif
|
||||
|
||||
#if defined(MACOSX)
|
||||
// On Mac OS X, we need to double buffer the audio buffer, else anything
|
||||
// which produces sampled data with high latency (like the MT-32 emulator)
|
||||
// will sound terribly.
|
||||
// This could be enabled for more / most ports in the future, but needs some
|
||||
// testing.
|
||||
#define MIXER_DOUBLE_BUFFERING 1
|
||||
#endif
|
||||
|
||||
|
||||
enum {
|
||||
GFX_NORMAL = 0,
|
||||
@ -137,6 +146,8 @@ public:
|
||||
virtual void setupMixer();
|
||||
static void mixCallback(void *s, byte *samples, int len);
|
||||
|
||||
virtual void closeMixer();
|
||||
|
||||
virtual Audio::Mixer *getMixer();
|
||||
|
||||
// Poll CD status
|
||||
@ -369,6 +380,23 @@ protected:
|
||||
*/
|
||||
MutexRef _graphicsMutex;
|
||||
|
||||
#ifdef MIXER_DOUBLE_BUFFERING
|
||||
SDL_mutex *_soundMutex;
|
||||
SDL_cond *_soundCond;
|
||||
SDL_Thread *_soundThread;
|
||||
bool _soundThreadIsRunning;
|
||||
bool _soundThreadShouldQuit;
|
||||
|
||||
byte _activeSoundBuf;
|
||||
uint _soundBufSize;
|
||||
byte *_soundBuffers[2];
|
||||
|
||||
void mixerProducerThread();
|
||||
static int SDLCALL mixerProducerThreadEntry(void *arg);
|
||||
void initThreadedMixer(Audio::MixerImpl *mixer, uint bufSize);
|
||||
void deinitThreadedMixer();
|
||||
#endif
|
||||
|
||||
|
||||
Common::SaveFileManager *_savefile;
|
||||
Audio::MixerImpl *_mixer;
|
||||
@ -377,7 +405,7 @@ protected:
|
||||
Common::TimerManager *_timer;
|
||||
|
||||
|
||||
|
||||
protected:
|
||||
void addDirtyRgnAuto(const byte *buf);
|
||||
void makeChecksums(const byte *buf);
|
||||
|
||||
|
@ -226,28 +226,31 @@
|
||||
$VariationSets{'ALL'}{'all'} = "$DefaultFeatures @WorkingEngines @EnablableSubEngines";
|
||||
|
||||
# now one for each ready-for-release engine
|
||||
|
||||
if (0)
|
||||
{
|
||||
foreach (@WorkingEngines)
|
||||
{
|
||||
$VariationSets{'ALL'}{$_} = "$DefaultFeatures $_";
|
||||
}
|
||||
# for scumm, we need to add 2 features:
|
||||
$VariationSets{'ALL'}{'scumm'} .= " scumm_7_8 he";
|
||||
|
||||
#$VariationSets{'ALL'}{'scumm'} .= " scumm_7_8 he";
|
||||
}
|
||||
|
||||
# now one for each not-ready-for-release-or-testing engine
|
||||
|
||||
if (0)
|
||||
{
|
||||
foreach (@TestingEngines)
|
||||
{
|
||||
$VariationSets{'ALL'}{"test_$_"} = "$DefaultFeatures $_";
|
||||
}
|
||||
|
||||
}
|
||||
# below here you could specify weird & experimental combinations, non-ready engines
|
||||
|
||||
# a small version of the saga engine, because it is so big (no tremor,mad,zlib)
|
||||
$VariationSets{'ALL'}{'saga_mini'} = "saga";
|
||||
#$VariationSets{'ALL'}{'saga_mini'} = "saga";
|
||||
|
||||
# a smaller version of scumm without support for v7, v8 and HE games
|
||||
$VariationSets{'ALL'}{'scumm_no78he'} = "$DefaultFeatures scumm";
|
||||
#$VariationSets{'ALL'}{'scumm_no78he'} = "$DefaultFeatures scumm";
|
||||
|
||||
# maybe you feel lucky and want to test the sword engines? :P
|
||||
#$VariationSets{'S60v2'}{'test_sword'} = "$DefaultFeatures mpeg2 sword1 sword2";
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include "gui/Actions.h"
|
||||
#include "gui/Key.h"
|
||||
#include "gui/message.h"
|
||||
|
||||
#include "sound/mixer_intern.h"
|
||||
#include "..\..\sdl\main.cpp"
|
||||
|
||||
#ifdef SAMPLES_PER_SEC_8000 // the GreanSymbianMMP format cannot handle values for defines :(
|
||||
@ -42,10 +42,22 @@
|
||||
#define SAMPLES_PER_SEC 16000
|
||||
#endif
|
||||
|
||||
#define KInputBufferLength 128
|
||||
// Symbian libc file functionality in order to provide shared file handles
|
||||
struct TSymbianFileEntry {
|
||||
RFile iFileHandle;
|
||||
char iInputBuffer[KInputBufferLength];
|
||||
TInt iInputBufferLen;
|
||||
TInt iInputPos;
|
||||
};
|
||||
|
||||
#define FILE void
|
||||
|
||||
////////// extern "C" ///////////////////////////////////////////////////
|
||||
namespace Symbian {
|
||||
|
||||
|
||||
|
||||
// Show a simple Symbian Info win with Msg & exit
|
||||
void FatalError(const char *msg) {
|
||||
TPtrC8 msgPtr((const TUint8 *)msg);
|
||||
@ -246,9 +258,9 @@ void OSystem_SDL_Symbian::symbianMixCallback(void *sys, byte *samples, int len)
|
||||
if (!this_->_mixer)
|
||||
return;
|
||||
|
||||
#ifdef S60
|
||||
#if defined (S60) && !defined(S60V3)
|
||||
// If not stereo then we need to downmix
|
||||
if (_channels != 2) {
|
||||
if (this_->_mixer->_channels != 2) {
|
||||
this_->_mixer->mixCallback(_stereo_mix_buffer, len * 2);
|
||||
|
||||
int16 *bitmixDst = (int16 *)samples;
|
||||
@ -443,15 +455,9 @@ void OSystem_SDL_Symbian::initZones() {
|
||||
}
|
||||
}
|
||||
|
||||
// Symbian libc file functionality in order to provide shared file handles
|
||||
struct TSymbianFileEntry {
|
||||
RFile iFileHandle;
|
||||
};
|
||||
|
||||
#define FILE void
|
||||
|
||||
FILE* symbian_fopen(const char* name, const char* mode) {
|
||||
TSymbianFileEntry* fileEntry = new TSymbianFileEntry;
|
||||
fileEntry->iInputPos = KErrNotFound;
|
||||
|
||||
if (fileEntry != NULL) {
|
||||
TInt modeLen = strlen(mode);
|
||||
@ -509,9 +515,71 @@ void symbian_fclose(FILE* handle) {
|
||||
}
|
||||
|
||||
size_t symbian_fread(const void* ptr, size_t size, size_t numItems, FILE* handle) {
|
||||
TPtr8 pointer( (unsigned char*) ptr, size*numItems);
|
||||
TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle));
|
||||
TUint32 totsize = size*numItems;
|
||||
TPtr8 pointer ( (unsigned char*) ptr, totsize);
|
||||
|
||||
((TSymbianFileEntry*)(handle))->iFileHandle.Read(pointer);
|
||||
// Nothing cached and we want to load at least KInputBufferLength bytes
|
||||
if(totsize >= KInputBufferLength) {
|
||||
TUint32 totLength = 0;
|
||||
if(entry->iInputPos != KErrNotFound)
|
||||
{
|
||||
TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer+entry->iInputPos, entry->iInputBufferLen - entry->iInputPos, KInputBufferLength);
|
||||
pointer.Append(cacheBuffer);
|
||||
entry->iInputPos = KErrNotFound;
|
||||
totLength+=pointer.Length();
|
||||
pointer.Set(totLength+(unsigned char*) ptr, 0, totsize-totLength);
|
||||
}
|
||||
|
||||
entry->iFileHandle.Read(pointer);
|
||||
totLength+=pointer.Length();
|
||||
|
||||
pointer.Set((unsigned char*) ptr, totLength, totsize);
|
||||
|
||||
}
|
||||
else {
|
||||
// Nothing in buffer
|
||||
if(entry->iInputPos == KErrNotFound) {
|
||||
TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer, KInputBufferLength);
|
||||
entry->iFileHandle.Read(cacheBuffer);
|
||||
|
||||
if(cacheBuffer.Length() >= totsize) {
|
||||
pointer.Copy(cacheBuffer.Left(totsize));
|
||||
entry->iInputPos = totsize;
|
||||
entry->iInputBufferLen = cacheBuffer.Length();
|
||||
}
|
||||
else {
|
||||
pointer.Copy(cacheBuffer);
|
||||
entry->iInputPos = KErrNotFound;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
TPtr8 cacheBuffer( (unsigned char*) entry->iInputBuffer, entry->iInputBufferLen, KInputBufferLength);
|
||||
|
||||
if(entry->iInputPos+totsize < entry->iInputBufferLen) {
|
||||
pointer.Copy(cacheBuffer.Mid(entry->iInputPos, totsize));
|
||||
entry->iInputPos+=totsize;
|
||||
}
|
||||
else {
|
||||
|
||||
pointer.Copy(cacheBuffer.Mid(entry->iInputPos, entry->iInputBufferLen-entry->iInputPos));
|
||||
cacheBuffer.SetLength(0);
|
||||
entry->iFileHandle.Read(cacheBuffer);
|
||||
|
||||
if(cacheBuffer.Length() >= totsize-pointer.Length()) {
|
||||
TUint32 restSize = totsize-pointer.Length();
|
||||
pointer.Append(cacheBuffer.Left(restSize));
|
||||
entry->iInputPos = restSize;
|
||||
entry->iInputBufferLen = cacheBuffer.Length();
|
||||
}
|
||||
else {
|
||||
pointer.Append(cacheBuffer);
|
||||
entry->iInputPos = KErrNotFound;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pointer.Length()/size;
|
||||
}
|
||||
@ -519,6 +587,7 @@ size_t symbian_fread(const void* ptr, size_t size, size_t numItems, FILE* handle
|
||||
size_t symbian_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handle) {
|
||||
TPtrC8 pointer( (unsigned char*) ptr, size*numItems);
|
||||
|
||||
((TSymbianFileEntry*)(handle))->iInputPos = KErrNotFound;
|
||||
if (((TSymbianFileEntry*)(handle))->iFileHandle.Write(pointer) == KErrNone) {
|
||||
return numItems;
|
||||
}
|
||||
@ -528,12 +597,18 @@ size_t symbian_fwrite(const void* ptr, size_t size, size_t numItems, FILE* handl
|
||||
|
||||
bool symbian_feof(FILE* handle) {
|
||||
TInt pos = 0;
|
||||
if (((TSymbianFileEntry*)(handle))->iFileHandle.Seek(ESeekCurrent, pos) == KErrNone) {
|
||||
TSymbianFileEntry* entry = ((TSymbianFileEntry*)(handle));
|
||||
|
||||
if (entry->iFileHandle.Seek(ESeekCurrent, pos) == KErrNone) {
|
||||
|
||||
TInt size = 0;
|
||||
if (((TSymbianFileEntry*)(handle))->iFileHandle.Size(size) == KErrNone) {
|
||||
if (pos == size)
|
||||
if (entry->iFileHandle.Size(size) == KErrNone) {
|
||||
if(entry->iInputPos == KErrNotFound && pos == size)
|
||||
return true;
|
||||
|
||||
if(entry->iInputPos != KErrNotFound && pos == size && entry->iInputPos == entry->iInputBufferLen)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -549,6 +624,7 @@ long int symbian_ftell(FILE* handle) {
|
||||
}
|
||||
|
||||
int symbian_fseek(FILE* handle, long int offset, int whence) {
|
||||
|
||||
TSeek seekMode = ESeekStart;
|
||||
TInt pos = offset;
|
||||
|
||||
@ -564,6 +640,8 @@ int symbian_fseek(FILE* handle, long int offset, int whence) {
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
((TSymbianFileEntry*)(handle))->iInputPos = KErrNotFound;
|
||||
|
||||
return ((TSymbianFileEntry*)(handle))->iFileHandle.Seek(seekMode, pos);
|
||||
}
|
||||
|
@ -1,8 +1,34 @@
|
||||
/* MISSING.C
|
||||
Implementation for standard and semi-standard C library calls missing in WinCE
|
||||
environment.
|
||||
by Vasyl Tsvirkunov
|
||||
*/
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* $URL$
|
||||
* $Id$
|
||||
*
|
||||
*/
|
||||
|
||||
/* Original code:
|
||||
* Implementation for standard and semi-standard C library calls missing in WinCE
|
||||
* environment.
|
||||
* by Vasyl Tsvirkunov
|
||||
*/
|
||||
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
@ -17,19 +43,8 @@
|
||||
#include "time.h"
|
||||
#include "dirent.h"
|
||||
|
||||
/* forward declaration */
|
||||
|
||||
#if _WIN32_WCE < 300
|
||||
|
||||
#define _STDAFX_H
|
||||
#include "portdefs.h"
|
||||
|
||||
#else
|
||||
|
||||
char *strdup(const char *strSource);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define EXT_C extern "C"
|
||||
#else
|
||||
@ -40,19 +55,27 @@ char *strdup(const char *strSource);
|
||||
|
||||
void *bsearch(const void *key, const void *base, size_t nmemb,
|
||||
size_t size, int (*compar)(const void *, const void *)) {
|
||||
size_t i;
|
||||
// Perform binary search
|
||||
size_t lo = 0;
|
||||
size_t hi = nmemb;
|
||||
while (lo < hi) {
|
||||
size_t mid = (lo + hi) / 2;
|
||||
const void *p = ((const char *)base) + mid * size;
|
||||
int tmp = (*compar)(key, p);
|
||||
if (tmp < 0)
|
||||
hi = mid;
|
||||
else if (tmp > 0)
|
||||
lo = mid + 1;
|
||||
else
|
||||
return (void *)p;
|
||||
}
|
||||
|
||||
for (i=0; i<nmemb; i++)
|
||||
if (compar(key, (void*)((size_t)base + size * i)) == 0)
|
||||
return (void*)((size_t)base + size * i);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static WIN32_FIND_DATA wfd;
|
||||
|
||||
/* Very limited implementation of stat. Used by UI.C, MEMORY-P.C (latter is not critical) */
|
||||
int stat(const char *fname, struct stat *ss)
|
||||
{
|
||||
int stat(const char *fname, struct stat *ss) {
|
||||
TCHAR fnameUnc[MAX_PATH+1];
|
||||
HANDLE handle;
|
||||
int len;
|
||||
@ -63,8 +86,7 @@ int stat(const char *fname, struct stat *ss)
|
||||
/* Special case (dummy on WinCE) */
|
||||
len = strlen(fname);
|
||||
if (len >= 2 && fname[len-1] == '.' && fname[len-2] == '.' &&
|
||||
(len == 2 || fname[len-3] == '\\'))
|
||||
{
|
||||
(len == 2 || fname[len-3] == '\\')) {
|
||||
/* That's everything implemented so far */
|
||||
memset(ss, 0, sizeof(struct stat));
|
||||
ss->st_size = 1024;
|
||||
@ -74,6 +96,7 @@ int stat(const char *fname, struct stat *ss)
|
||||
|
||||
MultiByteToWideChar(CP_ACP, 0, fname, -1, fnameUnc, MAX_PATH);
|
||||
handle = FindFirstFile(fnameUnc, &wfd);
|
||||
FindClose(handle);
|
||||
if (handle == INVALID_HANDLE_VALUE)
|
||||
return -1;
|
||||
else
|
||||
@ -83,20 +106,16 @@ int stat(const char *fname, struct stat *ss)
|
||||
ss->st_size = wfd.nFileSizeLow;
|
||||
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
ss->st_mode |= S_IFDIR;
|
||||
|
||||
FindClose(handle);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char cwd[MAX_PATH+1] = "";
|
||||
EXT_C char *getcwd(char *buffer, int maxlen)
|
||||
{
|
||||
EXT_C char *getcwd(char *buffer, int maxlen) {
|
||||
TCHAR fileUnc[MAX_PATH+1];
|
||||
char* plast;
|
||||
|
||||
if (cwd[0] == 0)
|
||||
{
|
||||
if (cwd[0] == 0) {
|
||||
GetModuleFileName(NULL, fileUnc, MAX_PATH);
|
||||
WideCharToMultiByte(CP_ACP, 0, fileUnc, -1, cwd, MAX_PATH, NULL, NULL);
|
||||
plast = strrchr(cwd, '\\');
|
||||
@ -114,8 +133,7 @@ EXT_C char *getcwd(char *buffer, int maxlen)
|
||||
#ifdef __GNUC__
|
||||
#undef GetCurrentDirectory
|
||||
#endif
|
||||
EXT_C void GetCurrentDirectory(int len, char *buf)
|
||||
{
|
||||
EXT_C void GetCurrentDirectory(int len, char *buf) {
|
||||
getcwd(buf,len);
|
||||
};
|
||||
|
||||
@ -125,26 +143,22 @@ fully qualified paths refer to root folder rather
|
||||
than current folder (concept not implemented in CE).
|
||||
*/
|
||||
#undef fopen
|
||||
EXT_C FILE *wce_fopen(const char* fname, const char* fmode)
|
||||
{
|
||||
EXT_C FILE *wce_fopen(const char* fname, const char* fmode) {
|
||||
char fullname[MAX_PATH+1];
|
||||
|
||||
if (!fname || fname[0] == '\0')
|
||||
return NULL;
|
||||
if (fname[0] != '\\' && fname[0] != '/')
|
||||
{
|
||||
if (fname[0] != '\\' && fname[0] != '/') {
|
||||
getcwd(fullname, MAX_PATH);
|
||||
strncat(fullname, "\\", MAX_PATH-strlen(fullname)-1);
|
||||
strncat(fullname, fname, MAX_PATH-strlen(fullname)-strlen(fname));
|
||||
return fopen(fullname, fmode);
|
||||
}
|
||||
else
|
||||
} else
|
||||
return fopen(fname, fmode);
|
||||
}
|
||||
|
||||
/* Remove file by name */
|
||||
int remove(const char* path)
|
||||
{
|
||||
int remove(const char* path) {
|
||||
TCHAR pathUnc[MAX_PATH+1];
|
||||
MultiByteToWideChar(CP_ACP, 0, path, -1, pathUnc, MAX_PATH);
|
||||
return !DeleteFile(pathUnc);
|
||||
@ -158,14 +172,22 @@ int _access(const char *path, int mode) {
|
||||
|
||||
WIN32_FIND_DATA ffd;
|
||||
HANDLE h=FindFirstFile(fname, &ffd);
|
||||
FindClose(h);
|
||||
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
return -1; //Can't find file
|
||||
FindClose(h);
|
||||
|
||||
if (ffd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
|
||||
if (ffd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY) {
|
||||
// WORKAROUND: WinCE (or the emulator) sometimes returns bogus direcotry
|
||||
// hits for files that don't exist. Checking for the same fname twice
|
||||
// seems to weed out those false positives.
|
||||
HANDLE h=FindFirstFile(fname, &ffd);
|
||||
FindClose(h);
|
||||
if (h == INVALID_HANDLE_VALUE)
|
||||
return -1; //Can't find file
|
||||
|
||||
return 0; //Always return success if target is directory and exists
|
||||
|
||||
}
|
||||
switch (mode) {
|
||||
case 00: //Check existence
|
||||
return 0;
|
||||
@ -183,8 +205,7 @@ int _access(const char *path, int mode) {
|
||||
#ifndef __GNUC__
|
||||
|
||||
/* Limited dirent implementation. Used by UI.C and DEVICES.C */
|
||||
DIR* opendir(const char* fname)
|
||||
{
|
||||
DIR* opendir(const char* fname) {
|
||||
DIR* pdir;
|
||||
char fnameMask[MAX_PATH+1];
|
||||
TCHAR fnameUnc[MAX_PATH+1];
|
||||
@ -209,13 +230,10 @@ DIR* opendir(const char* fname)
|
||||
strcpy(pdir->dd_name, fname); /* it has exactly enough space for fname and nul char */
|
||||
|
||||
MultiByteToWideChar(CP_ACP, 0, fnameMask, -1, fnameUnc, MAX_PATH);
|
||||
if ((pdir->dd_handle = (long)FindFirstFile(fnameUnc, &wfd)) == (long)INVALID_HANDLE_VALUE)
|
||||
{
|
||||
if ((pdir->dd_handle = (long)FindFirstFile(fnameUnc, &wfd)) == (long)INVALID_HANDLE_VALUE) {
|
||||
free(pdir);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
WideCharToMultiByte(CP_ACP, 0, wfd.cFileName, -1, nameFound, MAX_PATH, NULL, NULL);
|
||||
|
||||
pdir->dd_dir.d_name = strdup(nameFound);
|
||||
@ -224,34 +242,25 @@ DIR* opendir(const char* fname)
|
||||
return pdir;
|
||||
}
|
||||
|
||||
struct dirent* readdir(DIR* dir)
|
||||
{
|
||||
struct dirent* readdir(DIR* dir) {
|
||||
char nameFound[MAX_PATH+1];
|
||||
static struct dirent dummy;
|
||||
|
||||
if (dir->dd_stat == 0)
|
||||
{
|
||||
if (dir->dd_stat == 0) {
|
||||
dummy.d_name = ".";
|
||||
dummy.d_namlen = 1;
|
||||
dir->dd_stat ++;
|
||||
return &dummy;
|
||||
}
|
||||
else if (dir->dd_stat == 1)
|
||||
{
|
||||
} else if (dir->dd_stat == 1) {
|
||||
dummy.d_name = "..";
|
||||
dummy.d_namlen = 2;
|
||||
dir->dd_stat ++;
|
||||
return &dummy;
|
||||
}
|
||||
else if (dir->dd_stat == 2)
|
||||
{
|
||||
} else if (dir->dd_stat == 2) {
|
||||
dir->dd_stat++;
|
||||
return &dir->dd_dir;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (FindNextFile((HANDLE)dir->dd_handle, &wfd) == 0)
|
||||
{
|
||||
} else {
|
||||
if (FindNextFile((HANDLE)dir->dd_handle, &wfd) == 0) {
|
||||
dir->dd_stat = -1;
|
||||
return NULL;
|
||||
}
|
||||
@ -283,12 +292,6 @@ int closedir(DIR* dir)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* in our case unlink is the same as remove */
|
||||
int unlink(const char* path)
|
||||
{
|
||||
return remove(path);
|
||||
}
|
||||
|
||||
/* Make directory, Unix style */
|
||||
void mkdir(char* dirname, int mode)
|
||||
{
|
||||
@ -299,10 +302,8 @@ void mkdir(char* dirname, int mode)
|
||||
if (*path == '/')
|
||||
*path = '\\';
|
||||
/* Run through the string and attempt creating all subdirs on the path */
|
||||
for (ptr = path+1; *ptr; ptr ++)
|
||||
{
|
||||
if (*ptr == '\\' || *ptr == '/')
|
||||
{
|
||||
for (ptr = path+1; *ptr; ptr ++) {
|
||||
if (*ptr == '\\' || *ptr == '/') {
|
||||
*ptr = 0;
|
||||
MultiByteToWideChar(CP_ACP, 0, path, -1, pathUnc, MAX_PATH);
|
||||
CreateDirectory(pathUnc, 0);
|
||||
@ -313,373 +314,40 @@ void mkdir(char* dirname, int mode)
|
||||
CreateDirectory(pathUnc, 0);
|
||||
}
|
||||
|
||||
/* Used in DEVICES.C and UI.C for some purpose. Not critical in this port */
|
||||
int system(const char* path) { return 0; }
|
||||
|
||||
#if 0
|
||||
|
||||
char *tmpnam(char *string)
|
||||
{
|
||||
TCHAR pTemp[MAX_PATH+1];
|
||||
static char buffer[MAX_PATH+1];
|
||||
GetTempFileName(TEXT("."), TEXT("A8_"), 0, pTemp);
|
||||
WideCharToMultiByte(CP_ACP, 0, pTemp, -1, buffer, MAX_PATH, NULL, NULL);
|
||||
|
||||
if (string)
|
||||
{
|
||||
strcpy(string, buffer);
|
||||
return string;
|
||||
}
|
||||
else
|
||||
return buffer;
|
||||
}
|
||||
|
||||
FILE *tmpfile()
|
||||
{
|
||||
TCHAR pTemp[MAX_PATH+1];
|
||||
if (!GetTempFileName(TEXT("."), TEXT("A8_"), 0, pTemp))
|
||||
return _wfopen(pTemp, TEXT("w+b"));
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void rewind(FILE *stream)
|
||||
{
|
||||
fseek(stream, 0, SEEK_SET);
|
||||
}
|
||||
|
||||
|
||||
#if _WIN32_WCE < 300
|
||||
|
||||
int isalnum(int c) {
|
||||
return ((c >= 'A' && c <= 'Z') ||
|
||||
(c >= 'a' && c <= 'z') ||
|
||||
(c >= '0' && c <= '9'));
|
||||
}
|
||||
|
||||
char *_strdup(const char *strSource)
|
||||
#else
|
||||
char *strdup(const char *strSource)
|
||||
#endif
|
||||
{
|
||||
char* buffer;
|
||||
buffer = (char*)malloc(strlen(strSource)+1);
|
||||
size_z len = strlen(strSource)+1;
|
||||
buffer = (char*)malloc(len);
|
||||
if (buffer)
|
||||
strcpy(buffer, strSource);
|
||||
memcpy(buffer, strSource, len);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* Very limited implementation of sys/time.h */
|
||||
void usleep(long usec)
|
||||
{
|
||||
long msec = usec/1000;
|
||||
if (msec <= 0)
|
||||
Sleep(0);
|
||||
else
|
||||
Sleep(msec);
|
||||
}
|
||||
|
||||
/* This may provide for better sync mechanism */
|
||||
unsigned int clock()
|
||||
{
|
||||
return GetTickCount();
|
||||
}
|
||||
|
||||
/* And why do people use this? */
|
||||
#if _WIN32_WCE >= 300
|
||||
void abort()
|
||||
{
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
IMHO, no project should use this one, it is not portable at all. This implementation
|
||||
at least allows some projects to work.
|
||||
*/
|
||||
char* getenv(char* name)
|
||||
{
|
||||
static char buffer[MAX_PATH+1];
|
||||
if (strcmp(name, "HOME") == 0 || strcmp(name, "HOMEDIR") == 0)
|
||||
{
|
||||
getcwd(buffer, MAX_PATH);
|
||||
return buffer;
|
||||
}
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
#if _WIN32_WCE < 300 || defined(_TEST_HPC_STDIO)
|
||||
|
||||
void *calloc(size_t n, size_t s) {
|
||||
void *result = malloc(n * s);
|
||||
if (result)
|
||||
memset(result, 0, n * s);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char *strpbrk(const char *s, const char *accept) {
|
||||
int i;
|
||||
|
||||
if (!s || !accept)
|
||||
return NULL;
|
||||
|
||||
for (i=0; i<strlen(s); i++) {
|
||||
int j;
|
||||
for (j=0; j<strlen(accept); j++)
|
||||
if (s[i] == accept[j])
|
||||
return (char*)&s[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef _TEST_HPC_STDIO
|
||||
|
||||
int isdigit(int c) {
|
||||
return (c >='0' && c <= '9');
|
||||
}
|
||||
|
||||
int isprint(int c) {
|
||||
return (c >= ' ' && c <= '~');
|
||||
}
|
||||
|
||||
int isspace(int c) {
|
||||
return (c == ' ');
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef WIN32_PLATFORM_HPCPRO
|
||||
|
||||
|
||||
int printf(const char *format, ...) {
|
||||
// useless anyway :)
|
||||
return 0;
|
||||
}
|
||||
|
||||
FILE *fopen(const char *path, const char *mode) {
|
||||
TCHAR tempo[MAX_PATH];
|
||||
HANDLE result;
|
||||
bool writeAccess = (mode[0] == 'W' || mode[0] == 'w');
|
||||
|
||||
MultiByteToWideChar(CP_ACP, 0, path, strlen(path) + 1, tempo, sizeof(tempo));
|
||||
|
||||
result = CreateFile(tempo, ( writeAccess ? GENERIC_WRITE : GENERIC_READ), 0, NULL, (writeAccess ? CREATE_ALWAYS : OPEN_EXISTING), FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (result == INVALID_HANDLE_VALUE)
|
||||
return NULL;
|
||||
else
|
||||
return (FILE*)result;
|
||||
}
|
||||
|
||||
FILE * _wfopen(const TCHAR *path, const TCHAR *mode) {
|
||||
HANDLE result;
|
||||
bool writeAccess = (mode[0] == 'W' || mode[0] == 'w');
|
||||
result = CreateFile(path, ( writeAccess ? GENERIC_WRITE : GENERIC_READ), 0, NULL, (writeAccess ? CREATE_ALWAYS : OPEN_EXISTING), FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (result == INVALID_HANDLE_VALUE)
|
||||
return NULL;
|
||||
else
|
||||
return (FILE*)result;
|
||||
}
|
||||
|
||||
FILE *_wfreopen(const TCHAR *path, const TCHAR *mode, FILE *stream) {
|
||||
fclose(stream);
|
||||
stream = _wfopen(path, mode);
|
||||
return stream;
|
||||
}
|
||||
|
||||
int fclose(FILE *stream) {
|
||||
CloseHandle((HANDLE)stream);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int fseek(FILE *stream, long offset, int whence) {
|
||||
SetFilePointer((HANDLE)stream, offset, NULL, (whence == SEEK_CUR ? FILE_CURRENT : whence == SEEK_END ? FILE_END : FILE_BEGIN));
|
||||
return 0;
|
||||
}
|
||||
|
||||
long ftell(FILE *stream) {
|
||||
return (SetFilePointer((HANDLE)stream, 0, NULL, FILE_CURRENT));
|
||||
}
|
||||
|
||||
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) {
|
||||
DWORD sizeWritten;
|
||||
|
||||
WriteFile((HANDLE)stream, ptr, size * nmemb, &sizeWritten, NULL);
|
||||
|
||||
if (size != 0)
|
||||
return sizeWritten / size;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) {
|
||||
DWORD sizeRead;
|
||||
|
||||
ReadFile((HANDLE)stream, ptr, size * nmemb, &sizeRead, NULL);
|
||||
|
||||
if (size != 0)
|
||||
return sizeRead / size;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fgetc(FILE *stream) {
|
||||
unsigned char c;
|
||||
if (fread(&c, 1, 1, stream) != 1)
|
||||
return -1;
|
||||
else
|
||||
return c;
|
||||
}
|
||||
|
||||
char *fgets(char *s, int size, FILE *stream) {
|
||||
int i = 0;
|
||||
char tempo[1];
|
||||
|
||||
memset(s, 0, size);
|
||||
while (fread(tempo, 1, 1, stream)) {
|
||||
//if (tempo[0] == '\r')
|
||||
// break;
|
||||
if (tempo[0] == '\r')
|
||||
continue;
|
||||
s[i++] = tempo[0];
|
||||
if (tempo[0] == '\n')
|
||||
break;
|
||||
if (i == size)
|
||||
break;
|
||||
}
|
||||
if (!i)
|
||||
return NULL;
|
||||
else
|
||||
return s;
|
||||
}
|
||||
|
||||
int feof(FILE *stream) {
|
||||
DWORD fileSize;
|
||||
DWORD filePos;
|
||||
fileSize = GetFileSize((HANDLE)stream, NULL);
|
||||
filePos = SetFilePointer((HANDLE)stream, 0, 0, FILE_CURRENT);
|
||||
return (filePos == 0xFFFFFFFF || filePos > (fileSize - 1));
|
||||
}
|
||||
|
||||
int ferror(FILE *stream) {
|
||||
return 0; // FIXME !
|
||||
}
|
||||
|
||||
int fprintf(FILE *stream, const char *format, ...) {
|
||||
char buf[1024];
|
||||
va_list va;
|
||||
|
||||
va_start(va, format);
|
||||
vsnprintf(buf, 1024, format, va);
|
||||
va_end(va);
|
||||
|
||||
if (buf[strlen(buf) - 1] == '\n') {
|
||||
int i = strlen(buf) - 1;
|
||||
buf[i] = '\r';
|
||||
buf[i + 1] = '\n';
|
||||
buf[i + 2] = 0;
|
||||
}
|
||||
|
||||
return fwrite(buf, 1, strlen(buf), stream);
|
||||
}
|
||||
|
||||
FILE* _getstdfilex(int) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void clearerr(FILE *stream) {
|
||||
}
|
||||
|
||||
int fflush(FILE *stream) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int stricmp( const char *string1, const char *string2 ) {
|
||||
char src[4096];
|
||||
char dest[4096];
|
||||
int i;
|
||||
|
||||
for (i=0; i<strlen(string1); i++)
|
||||
if (string1[i] >= 'A' && string1[i] <= 'Z')
|
||||
src[i] = string1[i] + 32;
|
||||
else
|
||||
src[i] = string1[i];
|
||||
src[i] = 0;
|
||||
|
||||
for (i=0; i<strlen(string2); i++)
|
||||
if (string2[i] >= 'A' && string2[i] <= 'Z')
|
||||
dest[i] = string2[i] + 32;
|
||||
else
|
||||
dest[i] = string2[i];
|
||||
dest[i] = 0;
|
||||
|
||||
return strcmp(src, dest);
|
||||
}
|
||||
|
||||
char *strrchr(const char *s, int c) {
|
||||
int i;
|
||||
|
||||
for (i = strlen(s) - 1; i > 0; i--)
|
||||
if (s[i] == c)
|
||||
return (char*)(s + i);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
long int strtol(const char *nptr, char **endptr, int base) {
|
||||
// not correct but that's all we are using
|
||||
|
||||
long int result;
|
||||
sscanf(nptr, "%ld", &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// gcc build only functions follow
|
||||
#else // defined(__GNUC__)
|
||||
|
||||
#ifndef __MINGW32CE__
|
||||
int islower(int c)
|
||||
{
|
||||
int islower(int c) {
|
||||
return (c>='a' && c<='z');
|
||||
}
|
||||
|
||||
int isspace(int c)
|
||||
{
|
||||
int isspace(int c) {
|
||||
return (c==' ' || c=='\f' || c=='\n' || c=='\r' || c=='\t' || c=='\v');
|
||||
}
|
||||
|
||||
int isalpha(int c)
|
||||
{
|
||||
return (islower(c) || (c>='A' && c<='Z'));
|
||||
int isalpha(int c) {
|
||||
return ((c>='a' && c<='z') || (c>='A' && c<='Z'));
|
||||
}
|
||||
|
||||
int isalnum(int c)
|
||||
{
|
||||
return (isalpha(c) || (c>='0' && c<='9'));
|
||||
int isalnum(int c) {
|
||||
return ((c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9'));
|
||||
}
|
||||
|
||||
int isprint(int c)
|
||||
{
|
||||
static char punct[] = "!\"#%&'();<=>?[\\]*+,-./:^_{|}~";
|
||||
int i = 0, flag = 0;
|
||||
while ((punct[i] != 0) && (flag = (punct[i] != c)))
|
||||
i++;
|
||||
return (isalnum(c) || flag);
|
||||
}
|
||||
|
||||
extern "C" int atexit(void (*function)(void))
|
||||
{
|
||||
return 0;
|
||||
int isprint(int c) {
|
||||
//static const char punct[] = "!\"#%&'();<=>?[\\]*+,-./:^_{|}~";
|
||||
//return (isalnum(c) || strchr(punct, c));
|
||||
return (32 <= c && c <= 126); // based on BSD manpage
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -32,10 +32,10 @@ const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const Pla
|
||||
const PlainGameDescriptor *g = list;
|
||||
while (g->gameid) {
|
||||
if (0 == scumm_stricmp(gameid, g->gameid))
|
||||
break;
|
||||
return g;
|
||||
g++;
|
||||
}
|
||||
return g;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GameDescriptor::updateDesc(const char *extra) {
|
||||
|
@ -48,7 +48,7 @@ struct PlainGameDescriptor {
|
||||
/**
|
||||
* Given a list of PlainGameDescriptors, returns the first PlainGameDescriptor
|
||||
* matching the given gameid. If not match is found return 0.
|
||||
* The end of the list marked by a PlainGameDescriptor with gameid equal to 0.
|
||||
* The end of the list must marked by a PlainGameDescriptor with gameid equal to 0.
|
||||
*/
|
||||
const PlainGameDescriptor *findPlainGameDescriptor(const char *gameid, const PlainGameDescriptor *list);
|
||||
|
||||
|
@ -1 +1 @@
|
||||
#define SCUMMVM_VERSION "0.12.0svn"
|
||||
#define SCUMMVM_VERSION "0.13.0svn"
|
||||
|
@ -81,17 +81,11 @@ extern int pluginTypeVersions[PLUGIN_TYPE_MAX];
|
||||
#define STATIC_PLUGIN 1
|
||||
#define DYNAMIC_PLUGIN 2
|
||||
|
||||
// Note: The spaces around ENABLE_##ID have been added on purpose for
|
||||
// MSVC. For some reason, MSVC tries to add the parenthesis after
|
||||
// ENABLE_##ID to the check, thus making it false all the time.
|
||||
// Please do NOT remove them, otherwise no engine plugins will be
|
||||
// registered under MSVC
|
||||
|
||||
#define PLUGIN_ENABLED_STATIC(ID) \
|
||||
(defined( ENABLE_##ID ) && !PLUGIN_ENABLED_DYNAMIC(ID))
|
||||
(ENABLE_##ID && !PLUGIN_ENABLED_DYNAMIC(ID))
|
||||
|
||||
#define PLUGIN_ENABLED_DYNAMIC(ID) \
|
||||
(defined( ENABLE_##ID ) && (ENABLE_##ID == DYNAMIC_PLUGIN) && defined(DYNAMIC_MODULES))
|
||||
(ENABLE_##ID && (ENABLE_##ID == DYNAMIC_PLUGIN) && DYNAMIC_MODULES)
|
||||
|
||||
/**
|
||||
* REGISTER_PLUGIN_STATIC is a convenience macro which is used to declare
|
||||
|
@ -176,7 +176,6 @@ void ConfigManager::loadFile(const String &filename) {
|
||||
if (!cfg_file.open(filename)) {
|
||||
printf("Creating configuration file: %s\n", filename.c_str());
|
||||
} else {
|
||||
char buf[MAXLINELEN];
|
||||
String domain;
|
||||
String comment;
|
||||
int lineno = 0;
|
||||
@ -184,20 +183,28 @@ void ConfigManager::loadFile(const String &filename) {
|
||||
// TODO: Detect if a domain occurs multiple times (or likewise, if
|
||||
// a key occurs multiple times inside one domain).
|
||||
|
||||
while (!cfg_file.eof()) {
|
||||
while (!cfg_file.eof() && !cfg_file.ioFailed()) {
|
||||
lineno++;
|
||||
if (!cfg_file.readLine(buf, MAXLINELEN))
|
||||
break;
|
||||
|
||||
if (buf[0] == '#') {
|
||||
// Read a line
|
||||
String line;
|
||||
while (line.lastChar() != '\n') {
|
||||
char buf[MAXLINELEN];
|
||||
if (!cfg_file.readLine_NEW(buf, MAXLINELEN))
|
||||
break;
|
||||
line += buf;
|
||||
}
|
||||
|
||||
if (line.size() == 0) {
|
||||
// Do nothing
|
||||
} else if (line[0] == '#') {
|
||||
// Accumulate comments here. Once we encounter either the start
|
||||
// of a new domain, or a key-value-pair, we associate the value
|
||||
// of the 'comment' variable with that entity.
|
||||
comment += buf;
|
||||
comment += '\n';
|
||||
} else if (buf[0] == '[') {
|
||||
comment += line;
|
||||
} else if (line[0] == '[') {
|
||||
// It's a new domain which begins here.
|
||||
char *p = buf + 1;
|
||||
const char *p = line.c_str() + 1;
|
||||
// Get the domain name, and check whether it's valid (that
|
||||
// is, verify that it only consists of alphanumerics,
|
||||
// dashes and underscores).
|
||||
@ -209,8 +216,8 @@ void ConfigManager::loadFile(const String &filename) {
|
||||
error("Config file buggy: missing ] in line %d", lineno);
|
||||
break;
|
||||
case ']':
|
||||
*p = 0;
|
||||
domain = buf + 1;
|
||||
domain = String(line.c_str() + 1, p - (line.c_str() + 1));
|
||||
//domain = String(line.c_str() + 1, p); // TODO: Pending Common::String changes
|
||||
break;
|
||||
default:
|
||||
error("Config file buggy: Invalid character '%c' occured in domain name in line %d", *p, lineno);
|
||||
@ -226,10 +233,14 @@ void ConfigManager::loadFile(const String &filename) {
|
||||
|
||||
_domainSaveOrder.push_back(domain);
|
||||
} else {
|
||||
// Skip leading & trailing whitespaces
|
||||
char *t = rtrim(ltrim(buf));
|
||||
// This line should be a line with a 'key=value' pair, or an empty one.
|
||||
|
||||
// Skip leading whitespaces
|
||||
const char *t = line.c_str();
|
||||
while (isspace(*t))
|
||||
t++;
|
||||
|
||||
// Skip empty lines
|
||||
// Skip empty lines / lines with only whitespace
|
||||
if (*t == 0)
|
||||
continue;
|
||||
|
||||
@ -238,13 +249,30 @@ void ConfigManager::loadFile(const String &filename) {
|
||||
error("Config file buggy: Key/value pair found outside a domain in line %d", lineno);
|
||||
}
|
||||
|
||||
// Split string at '=' into 'key' and 'value'.
|
||||
char *p = strchr(t, '=');
|
||||
// Split string at '=' into 'key' and 'value'. First, find the "=" delimeter.
|
||||
const char *p = strchr(t, '=');
|
||||
if (!p)
|
||||
error("Config file buggy: Junk found in line line %d: '%s'", lineno, t);
|
||||
*p = 0;
|
||||
String key = rtrim(t);
|
||||
String value = ltrim(p + 1);
|
||||
|
||||
// Trim spaces before the '=' to obtain the key
|
||||
const char *p2 = p;
|
||||
while (p2 > t && isspace(*(p2-1)))
|
||||
p2--;
|
||||
String key(t, p2 - t);
|
||||
|
||||
// Skip spaces after the '='
|
||||
t = p + 1;
|
||||
while (isspace(*t))
|
||||
t++;
|
||||
|
||||
// Trim trailing spaces
|
||||
p2 = t + strlen(t);
|
||||
while (p2 > t && isspace(*(p2-1)))
|
||||
p2--;
|
||||
|
||||
String value(t, p2 - t);
|
||||
|
||||
// Finally, store the key/value pair in the active domain
|
||||
set(key, value, domain);
|
||||
|
||||
// Store comment
|
||||
|
@ -452,10 +452,12 @@ bool File::isOpen() const {
|
||||
}
|
||||
|
||||
bool File::ioFailed() const {
|
||||
// TODO/FIXME: Just use ferror() here?
|
||||
return _ioFailed != 0;
|
||||
}
|
||||
|
||||
void File::clearIOFailed() {
|
||||
// TODO/FIXME: Just use clearerr() here?
|
||||
_ioFailed = false;
|
||||
}
|
||||
|
||||
|
@ -43,32 +43,43 @@ static int computeCapacity(int len) {
|
||||
return ((len + 32 - 1) & ~0x1F) - 1;
|
||||
}
|
||||
|
||||
String::String(const char *str, uint32 len)
|
||||
: _len(0), _str(_storage) {
|
||||
String::String(const char *str) : _len(0), _str(_storage) {
|
||||
if (str == 0) {
|
||||
_storage[0] = 0;
|
||||
_len = 0;
|
||||
} else
|
||||
initWithCStr(str, strlen(str));
|
||||
}
|
||||
|
||||
String::String(const char *str, uint32 len) : _len(0), _str(_storage) {
|
||||
initWithCStr(str, len);
|
||||
}
|
||||
|
||||
String::String(const char *beginP, const char *endP) : _len(0), _str(_storage) {
|
||||
assert(endP >= beginP);
|
||||
initWithCStr(beginP, endP - beginP);
|
||||
}
|
||||
|
||||
void String::initWithCStr(const char *str, uint32 len) {
|
||||
assert(str);
|
||||
|
||||
// Init _storage member explicitly (ie. without calling its constructor)
|
||||
// for GCC 2.95.x compatibility (see also tracker item #1602879).
|
||||
_storage[0] = 0;
|
||||
|
||||
if (str && *str) {
|
||||
const uint32 tmp = strlen(str);
|
||||
assert(len <= tmp);
|
||||
if (len <= 0)
|
||||
len = tmp;
|
||||
_len = len;
|
||||
_len = len;
|
||||
|
||||
if (len >= _builtinCapacity) {
|
||||
// Not enough internal storage, so allocate more
|
||||
_extern._capacity = computeCapacity(len);
|
||||
_extern._refCount = 0;
|
||||
_str = (char *)malloc(_extern._capacity+1);
|
||||
assert(_str != 0);
|
||||
}
|
||||
|
||||
// Copy the string into the storage area
|
||||
memcpy(_str, str, len);
|
||||
_str[len] = 0;
|
||||
if (len >= _builtinCapacity) {
|
||||
// Not enough internal storage, so allocate more
|
||||
_extern._capacity = computeCapacity(len);
|
||||
_extern._refCount = 0;
|
||||
_str = (char *)malloc(_extern._capacity+1);
|
||||
assert(_str != 0);
|
||||
}
|
||||
|
||||
// Copy the string into the storage area
|
||||
memmove(_str, str, len);
|
||||
_str[len] = 0;
|
||||
}
|
||||
|
||||
String::String(const String &str)
|
||||
@ -91,6 +102,8 @@ String::String(char c)
|
||||
_storage[0] = c;
|
||||
_storage[1] = 0;
|
||||
|
||||
// TODO/FIXME: There is no reason for the following check -- we *do*
|
||||
// allow strings to contain 0 bytes!
|
||||
_len = (c == 0) ? 0 : 1;
|
||||
}
|
||||
|
||||
@ -130,11 +143,14 @@ String& String::operator =(const char *str) {
|
||||
uint32 len = strlen(str);
|
||||
ensureCapacity(len, false);
|
||||
_len = len;
|
||||
memcpy(_str, str, len + 1);
|
||||
memmove(_str, str, len + 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &String::operator =(const String &str) {
|
||||
if (&str == this)
|
||||
return *this;
|
||||
|
||||
if (str.isStorageIntern()) {
|
||||
decRefCount(_extern._refCount);
|
||||
_len = str._len;
|
||||
|
19
common/str.h
19
common/str.h
@ -96,10 +96,24 @@ public:
|
||||
static const char *emptyString;
|
||||
#endif
|
||||
|
||||
/** Construct a new empty string. */
|
||||
String() : _len(0), _str(_storage) { _storage[0] = 0; }
|
||||
String(const char *str, uint32 len = 0);
|
||||
|
||||
/** Construct a new string from the given NULL-terminated C string. */
|
||||
String(const char *str);
|
||||
|
||||
/** Construct a new string containing exactly len characters read from address str. */
|
||||
String(const char *str, uint32 len);
|
||||
|
||||
/** Construct a new string containing the characters between beginP (including) and endP (excluding). */
|
||||
String(const char *beginP, const char *endP);
|
||||
|
||||
/** Construct a copy of the given string. */
|
||||
String(const String &str);
|
||||
|
||||
/** Construct a string consisting of the given character. */
|
||||
String(char c);
|
||||
|
||||
~String();
|
||||
|
||||
String &operator =(const char *str);
|
||||
@ -162,7 +176,7 @@ public:
|
||||
|
||||
void toLowercase();
|
||||
void toUppercase();
|
||||
|
||||
|
||||
uint hash() const;
|
||||
|
||||
public:
|
||||
@ -189,6 +203,7 @@ protected:
|
||||
void ensureCapacity(uint32 new_len, bool keep_old);
|
||||
void incRefCount() const;
|
||||
void decRefCount(int *oldRefCount);
|
||||
void initWithCStr(const char *str, uint32 len);
|
||||
};
|
||||
|
||||
// Append two strings to form a new (temp) string
|
||||
|
@ -148,6 +148,61 @@ char *SeekableReadStream::readLine(char *buf, size_t bufSize) {
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *SeekableReadStream::readLine_NEW(char *buf, size_t bufSize) {
|
||||
assert(buf != 0 && bufSize > 1);
|
||||
char *p = buf;
|
||||
size_t len = 0;
|
||||
char c = 0;
|
||||
|
||||
// If end-of-file occurs before any characters are read, return NULL
|
||||
// and the buffer contents remain unchanged.
|
||||
if (eos() || ioFailed()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Loop as long as the stream has not ended, there is still free
|
||||
// space in the buffer, and the line has not ended
|
||||
while (!eos() && len + 1 < bufSize && c != LF) {
|
||||
c = readByte();
|
||||
|
||||
// If end-of-file occurs before any characters are read, return
|
||||
// NULL and the buffer contents remain unchanged. If an error
|
||||
/// occurs, return NULL and the buffer contents are indeterminate.
|
||||
if (ioFailed() || (len == 0 && eos()))
|
||||
return 0;
|
||||
|
||||
// Check for CR or CR/LF
|
||||
// * DOS and Windows use CRLF line breaks
|
||||
// * Unix and OS X use LF line breaks
|
||||
// * Macintosh before OS X used CR line breaks
|
||||
if (c == CR) {
|
||||
// Look at the next char -- is it LF? If not, seek back
|
||||
c = readByte();
|
||||
if (c != LF && !eos())
|
||||
seek(-1, SEEK_CUR);
|
||||
// Treat CR & CR/LF as plain LF
|
||||
c = LF;
|
||||
}
|
||||
|
||||
*p++ = c;
|
||||
len++;
|
||||
}
|
||||
|
||||
// FIXME:
|
||||
// This should fix a bug while using readLine with Common::File
|
||||
// it seems that it sets the eos flag after an invalid read
|
||||
// and at the same time the ioFailed flag
|
||||
// the config file parser fails out of that reason for the new themes
|
||||
if (eos()) {
|
||||
clearIOFailed();
|
||||
}
|
||||
|
||||
// We always terminate the buffer if no error occured
|
||||
*p = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
uint32 SubReadStream::read(void *dataPtr, uint32 dataSize) {
|
||||
dataSize = MIN(dataSize, _end - _pos);
|
||||
|
||||
|
@ -304,13 +304,40 @@ public:
|
||||
* Read one line of text from a CR or CR/LF terminated plain text file.
|
||||
* This method is a rough analog of the (f)gets function.
|
||||
*
|
||||
* @bug A main difference (and flaw) in this function is that there is no
|
||||
* way to detect that a line exceeeds the length of the buffer.
|
||||
* Code which needs this should use the new readLine_NEW() method instead.
|
||||
*
|
||||
* @param buf the buffer to store into
|
||||
* @param bufSize the size of the buffer
|
||||
* @return a pointer to the read string, or NULL if an error occurred
|
||||
*
|
||||
* @note The line terminator (CR or CR/LF) is stripped and not inserted
|
||||
* into the buffer.
|
||||
*/
|
||||
virtual char *readLine(char *buf, size_t bufSize);
|
||||
|
||||
/**
|
||||
* Reads at most one less than the number of characters specified
|
||||
* by bufSize from the and stores them in the string buf. Reading
|
||||
* stops when the end of a line is reached (CR, CR/LF or LF), at
|
||||
* end-of-file or error. The newline, if any, is retained (CR and
|
||||
* CR/LF are translated to LF = 0xA = '\n'). If any characters are
|
||||
* read and there is no error, a `\0' character is appended to end
|
||||
* the string.
|
||||
*
|
||||
* Upon successful completion, return a pointer to the string. If
|
||||
* end-of-file occurs before any characters are read, returns NULL
|
||||
* and the buffer contents remain unchanged. If an error occurs,
|
||||
* returns NULL and the buffer contents are indeterminate.
|
||||
* This method does not distinguish between end-of-file and error;
|
||||
* callers muse use ioFailed() or eos() to determine which occurred.
|
||||
*
|
||||
* @param buf the buffer to store into
|
||||
* @param bufSize the size of the buffer
|
||||
* @return a pointer to the read string, or NULL if an error occurred
|
||||
*/
|
||||
virtual char *readLine_NEW(char *s, size_t bufSize);
|
||||
};
|
||||
|
||||
/**
|
||||
|
4
configure
vendored
4
configure
vendored
@ -129,10 +129,10 @@ _srcdir=`dirname $0`
|
||||
if type mktemp > /dev/null 2>&1 ; then
|
||||
TMPO=`mktemp /tmp/scummvm-conf.XXXXXXXXXX`
|
||||
else
|
||||
TMPO=${_srcdir}/scummvm-conf
|
||||
TMPO=scummvm-conf
|
||||
fi
|
||||
TMPC=${TMPO}.cpp
|
||||
TMPLOG=${_srcdir}/config.log
|
||||
TMPLOG=config.log
|
||||
|
||||
# For cross compiling
|
||||
_host=""
|
||||
|
@ -7,7 +7,7 @@
|
||||
# Prologue information
|
||||
#------------------------------------------------------------------------------
|
||||
Name : scummvm
|
||||
Version : 0.12.0svn
|
||||
Version : 0.13.0svn
|
||||
Release : 1
|
||||
Summary : Graphic adventure game interpreter
|
||||
Group : Interpreters
|
||||
|
@ -7,8 +7,8 @@ IDI_ICON ICON DISCARDABLE "../../icons/scummvm.ico"
|
||||
#endif
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,12,0,0
|
||||
PRODUCTVERSION 0,12,0,0
|
||||
FILEVERSION 0,13,0,0
|
||||
PRODUCTVERSION 0,13,0,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@ -25,13 +25,13 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "Comments", "Look! A three headed monkey (TM)! .. Nice use of the TM!\0"
|
||||
VALUE "FileDescription", "http://www.scummvm.org/\0"
|
||||
VALUE "FileVersion", "0.12.0svn\0"
|
||||
VALUE "FileVersion", "0.13.0svn\0"
|
||||
VALUE "InternalName", "scummvm\0"
|
||||
VALUE "LegalCopyright", "Copyright © 2001-2007 The ScummVM Team\0"
|
||||
VALUE "LegalTrademarks", "'SCUMM', and all SCUMM games are a TM of LucasArts. Simon The Sorcerer is a TM of AdventureSoft. Beneath a Steel Sky and Broken Sword are a TM of Revolution. Flight of the Amazon Queen is a TM of John Passfield and Steve Stamatiadis. \0"
|
||||
VALUE "OriginalFilename", "scummvm.exe\0"
|
||||
VALUE "ProductName", "ScummVM\0"
|
||||
VALUE "ProductVersion", "0.12.0svn\0"
|
||||
VALUE "ProductVersion", "0.13.0svn\0"
|
||||
END
|
||||
END
|
||||
BLOCK "VarFileInfo"
|
||||
|
@ -8,7 +8,7 @@ if [ "$TMP" = "" ]; then
|
||||
fi
|
||||
PKG=$TMP/package-scummvm
|
||||
|
||||
VERSION=0.12.0svn
|
||||
VERSION=0.13.0svn
|
||||
ARCH=i486
|
||||
BUILD=1
|
||||
|
||||
|
@ -1076,6 +1076,8 @@ protected:
|
||||
virtual void drawImage(VC10_state *state);
|
||||
void drawBackGroundImage(VC10_state *state);
|
||||
void drawVertImage(VC10_state *state);
|
||||
void drawVertImageCompressed(VC10_state *state);
|
||||
void drawVertImageUncompressed(VC10_state *state);
|
||||
|
||||
void setMoveRect(uint16 x, uint16 y, uint16 width, uint16 height);
|
||||
|
||||
|
@ -744,10 +744,6 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) {
|
||||
}
|
||||
|
||||
void AGOSEngine::drawBackGroundImage(VC10_state *state) {
|
||||
const byte *src;
|
||||
byte *dst;
|
||||
uint h, i;
|
||||
|
||||
state->width = _screenWidth;
|
||||
if (_window3Flag == 1) {
|
||||
state->width = 0;
|
||||
@ -755,15 +751,19 @@ void AGOSEngine::drawBackGroundImage(VC10_state *state) {
|
||||
state->y_skip = 0;
|
||||
}
|
||||
|
||||
src = state->srcPtr + (state->width * state->y_skip) + (state->x_skip * 8);
|
||||
dst = state->surf_addr;
|
||||
const byte* src = state->srcPtr + (state->width * state->y_skip) + (state->x_skip * 8);
|
||||
byte* dst = state->surf_addr;
|
||||
|
||||
state->draw_width *= 2;
|
||||
|
||||
h = state->draw_height;
|
||||
uint h = state->draw_height;
|
||||
const uint w = state->draw_width;
|
||||
const byte paletteMod = state->paletteMod;
|
||||
do {
|
||||
for (i = 0; i != state->draw_width; i++)
|
||||
dst[i] = src[i] + state->paletteMod;
|
||||
for (uint i = 0; i != w; i+=2) {
|
||||
dst[i] = src[i] + paletteMod;
|
||||
dst[i+1] = src[i+1] + paletteMod;
|
||||
}
|
||||
dst += state->surf_pitch;
|
||||
src += state->width;
|
||||
} while (--h);
|
||||
@ -771,63 +771,86 @@ void AGOSEngine::drawBackGroundImage(VC10_state *state) {
|
||||
|
||||
void AGOSEngine::drawVertImage(VC10_state *state) {
|
||||
if (state->flags & kDFCompressed) {
|
||||
uint w, h;
|
||||
byte *src, *dst, *dstPtr;
|
||||
drawVertImageCompressed(state);
|
||||
} else {
|
||||
drawVertImageUncompressed(state);
|
||||
}
|
||||
}
|
||||
|
||||
state->x_skip *= 4; /* reached */
|
||||
void AGOSEngine::drawVertImageUncompressed(VC10_state *state) {
|
||||
assert ((state->flags & kDFCompressed) == 0) ;
|
||||
|
||||
state->dl = state->width;
|
||||
state->dh = state->height;
|
||||
const byte *src;
|
||||
byte *dst;
|
||||
uint count;
|
||||
|
||||
vc10_skip_cols(state);
|
||||
src = state->srcPtr + (state->width * state->y_skip) * 8;
|
||||
dst = state->surf_addr;
|
||||
state->x_skip *= 4;
|
||||
|
||||
dstPtr = state->surf_addr;
|
||||
if (!(state->flags & kDFNonTrans) && (state->flags & 0x40)) { /* reached */
|
||||
dstPtr += vcReadVar(252);
|
||||
}
|
||||
w = 0;
|
||||
do {
|
||||
do {
|
||||
for (count = 0; count != state->draw_width; count++) {
|
||||
byte color;
|
||||
color = (src[count + state->x_skip] / 16) + state->paletteMod;
|
||||
if ((state->flags & kDFNonTrans) || color)
|
||||
dst[count * 2] = color | state->palette;
|
||||
color = (src[count + state->x_skip] & 15) + state->paletteMod;
|
||||
if ((state->flags & kDFNonTrans) || color)
|
||||
dst[count * 2 + 1] = color | state->palette;
|
||||
}
|
||||
dst += state->surf_pitch;
|
||||
src += state->width * 8;
|
||||
} while (--state->draw_height);
|
||||
}
|
||||
|
||||
src = vc10_depackColumn(state);
|
||||
dst = dstPtr;
|
||||
void AGOSEngine::drawVertImageCompressed(VC10_state *state) {
|
||||
assert (state->flags & kDFCompressed) ;
|
||||
uint w, h;
|
||||
|
||||
h = 0;
|
||||
state->x_skip *= 4; /* reached */
|
||||
|
||||
state->dl = state->width;
|
||||
state->dh = state->height;
|
||||
|
||||
vc10_skip_cols(state);
|
||||
|
||||
byte *dstPtr = state->surf_addr;
|
||||
if (!(state->flags & kDFNonTrans) && (state->flags & 0x40)) { /* reached */
|
||||
dstPtr += vcReadVar(252);
|
||||
}
|
||||
w = 0;
|
||||
do {
|
||||
byte color;
|
||||
|
||||
const byte *src = vc10_depackColumn(state);
|
||||
byte *dst = dstPtr;
|
||||
|
||||
h = 0;
|
||||
if (state->flags & kDFNonTrans) {
|
||||
do {
|
||||
color = (*src / 16);
|
||||
if ((state->flags & kDFNonTrans) || color != 0)
|
||||
byte colors = *src;
|
||||
color = (colors / 16);
|
||||
dst[0] = color | state->palette;
|
||||
color = (colors & 15);
|
||||
dst[1] = color | state->palette;
|
||||
dst += state->surf_pitch;
|
||||
src++;
|
||||
} while (++h != state->draw_height);
|
||||
} else {
|
||||
do {
|
||||
byte colors = *src;
|
||||
color = (colors / 16);
|
||||
if (color != 0)
|
||||
dst[0] = color | state->palette;
|
||||
color = (*src & 15);
|
||||
if ((state->flags & kDFNonTrans) || color != 0)
|
||||
color = (colors & 15);
|
||||
if (color != 0)
|
||||
dst[1] = color | state->palette;
|
||||
dst += state->surf_pitch;
|
||||
src++;
|
||||
} while (++h != state->draw_height);
|
||||
dstPtr += 2;
|
||||
} while (++w != state->draw_width);
|
||||
} else {
|
||||
const byte *src;
|
||||
byte *dst;
|
||||
uint count;
|
||||
|
||||
src = state->srcPtr + (state->width * state->y_skip) * 8;
|
||||
dst = state->surf_addr;
|
||||
state->x_skip *= 4;
|
||||
|
||||
do {
|
||||
for (count = 0; count != state->draw_width; count++) {
|
||||
byte color;
|
||||
color = (src[count + state->x_skip] / 16) + state->paletteMod;
|
||||
if ((state->flags & kDFNonTrans) || color)
|
||||
dst[count * 2] = color | state->palette;
|
||||
color = (src[count + state->x_skip] & 15) + state->paletteMod;
|
||||
if ((state->flags & kDFNonTrans) || color)
|
||||
dst[count * 2 + 1] = color | state->palette;
|
||||
}
|
||||
dst += state->surf_pitch;
|
||||
src += state->width * 8;
|
||||
} while (--state->draw_height);
|
||||
}
|
||||
}
|
||||
dstPtr += 2;
|
||||
} while (++w != state->draw_width);
|
||||
}
|
||||
|
||||
void AGOSEngine::drawImage(VC10_state *state) {
|
||||
|
@ -94,6 +94,7 @@ public:
|
||||
|
||||
Common::StringList _volumeResourceFiles;
|
||||
StringPtrHashMap _volumeEntriesMap;
|
||||
TextHandler _textHandler;
|
||||
|
||||
private:
|
||||
void initialize(void);
|
||||
@ -107,6 +108,7 @@ private:
|
||||
extern CineEngine *g_cine;
|
||||
|
||||
#define BOOT_PRC_NAME "AUTO00.PRC"
|
||||
#define COPY_PROT_FAIL_PRC_NAME "L201.ANI"
|
||||
|
||||
enum {
|
||||
VAR_MOUSE_X_MODE = 253,
|
||||
|
@ -337,7 +337,7 @@ int FWRenderer::drawChar(char character, int x, int y) {
|
||||
x += 5;
|
||||
} else if ((width = fontParamTable[(unsigned char)character].characterWidth)) {
|
||||
idx = fontParamTable[(unsigned char)character].characterIdx;
|
||||
drawSpriteRaw(textTable[idx][0], textTable[idx][1], 16, 8, _backBuffer, x, y);
|
||||
drawSpriteRaw(g_cine->_textHandler.textTable[idx][0], g_cine->_textHandler.textTable[idx][1], 16, 8, _backBuffer, x, y);
|
||||
x += width + 1;
|
||||
}
|
||||
|
||||
@ -938,7 +938,7 @@ int OSRenderer::drawChar(char character, int x, int y) {
|
||||
x += 5;
|
||||
} else if ((width = fontParamTable[(unsigned char)character].characterWidth)) {
|
||||
idx = fontParamTable[(unsigned char)character].characterIdx;
|
||||
drawSpriteRaw2(textTable[idx][0], 0, 16, 8, _backBuffer, x, y);
|
||||
drawSpriteRaw2(g_cine->_textHandler.textTable[idx][0], 0, 16, 8, _backBuffer, x, y);
|
||||
x += width + 1;
|
||||
}
|
||||
|
||||
|
@ -41,8 +41,9 @@ ScriptList objectScripts;
|
||||
|
||||
/*! \todo Is script size of 0 valid?
|
||||
* \todo Fix script dump code
|
||||
* @return Was the loading successful?
|
||||
*/
|
||||
void loadPrc(const char *pPrcName) {
|
||||
bool loadPrc(const char *pPrcName) {
|
||||
byte i;
|
||||
uint16 numScripts;
|
||||
byte *scriptPtr, *dataPtr;
|
||||
@ -53,11 +54,11 @@ void loadPrc(const char *pPrcName) {
|
||||
scriptTable.clear();
|
||||
|
||||
// This is copy protection. Used to hang the machine
|
||||
if (!scumm_stricmp(pPrcName, "L201.ANI")) {
|
||||
if (!scumm_stricmp(pPrcName, COPY_PROT_FAIL_PRC_NAME)) {
|
||||
Common::Event event;
|
||||
event.type = Common::EVENT_RTL;
|
||||
g_system->getEventManager()->pushEvent(event);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
checkDataDisk(-1);
|
||||
@ -110,6 +111,8 @@ void loadPrc(const char *pPrcName) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // End of namespace Cine
|
||||
|
@ -31,7 +31,7 @@ namespace Cine {
|
||||
extern ScriptList globalScripts;
|
||||
extern ScriptList objectScripts;
|
||||
|
||||
void loadPrc(const char *pPrcName);
|
||||
bool loadPrc(const char *pPrcName);
|
||||
|
||||
} // End of namespace Cine
|
||||
|
||||
|
@ -1019,6 +1019,20 @@ int FWScript::o1_divVar() {
|
||||
}
|
||||
|
||||
int FWScript::o1_compareVar() {
|
||||
// WORKAROUND: A workaround for a script bug in script file CODE2.PRC
|
||||
// in at least some of the Amiga and Atari ST versions of Future Wars.
|
||||
// Fixes bug #2016647 (FW: crash with italian amiga version). A local
|
||||
// variable 251 is compared against value 0 although it's quite apparent
|
||||
// from the context in the script that instead global variable 251 should
|
||||
// be compared against value 0. So looks like someone made a typo when
|
||||
// making the scripts. Therefore we change that particular comparison
|
||||
// from using the local variable 251 to using the global variable 251.
|
||||
if (g_cine->getGameType() == Cine::GType_FW && scumm_stricmp(currentPrcName, "CODE2.PRC") == 0 &&
|
||||
(g_cine->getPlatform() == Common::kPlatformAmiga || g_cine->getPlatform() == Common::kPlatformAtariST) &&
|
||||
_script.getByte(_pos) == 251 && _script.getByte(_pos + 1) == 0 && _script.getWord(_pos + 2) == 0) {
|
||||
return o1_compareGlobalVar();
|
||||
}
|
||||
|
||||
byte varIdx = getNextByte();
|
||||
byte varType = getNextByte();
|
||||
|
||||
|
@ -31,8 +31,6 @@ namespace Cine {
|
||||
|
||||
byte *textDataPtr;
|
||||
|
||||
byte textTable[256][2][16 * 8];
|
||||
|
||||
const char **failureMessages;
|
||||
const CommandeType *defaultActionCommand;
|
||||
const CommandeType *systemMenu;
|
||||
@ -77,14 +75,14 @@ void loadTextData(const char *pFileName, byte *pDestinationBuffer) {
|
||||
loadRelatedPalette(pFileName);
|
||||
|
||||
for (i = 0; i < numCharacters; i++) {
|
||||
gfxConvertSpriteToRaw(textTable[i][0], tempBuffer, 16, 8);
|
||||
generateMask(textTable[i][0], textTable[i][1], 16 * 8, 0);
|
||||
gfxConvertSpriteToRaw(g_cine->_textHandler.textTable[i][0], tempBuffer, 16, 8);
|
||||
generateMask(g_cine->_textHandler.textTable[i][0], g_cine->_textHandler.textTable[i][1], 16 * 8, 0);
|
||||
tempBuffer += dataSize;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < 90; i++) {
|
||||
gfxConvertSpriteToRaw(textTable[i][0], tempBuffer, 8, 8);
|
||||
generateMask(textTable[i][0], textTable[i][1], 8 * 8, 0);
|
||||
gfxConvertSpriteToRaw(g_cine->_textHandler.textTable[i][0], tempBuffer, 8, 8);
|
||||
generateMask(g_cine->_textHandler.textTable[i][0], g_cine->_textHandler.textTable[i][1], 8 * 8, 0);
|
||||
tempBuffer += 0x40;
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,10 @@ namespace Cine {
|
||||
typedef char CommandeType[20];
|
||||
|
||||
extern byte *textDataPtr;
|
||||
extern byte textTable[256][2][16 * 8];
|
||||
|
||||
struct TextHandler {
|
||||
byte textTable[256][2][16 * 8];
|
||||
};
|
||||
|
||||
extern const char **failureMessages;
|
||||
extern const CommandeType *defaultActionCommand;
|
||||
|
@ -464,17 +464,26 @@ bool CineEngine::makeLoad(char *saveName) {
|
||||
|
||||
broken = brokenSave(*fHandle);
|
||||
|
||||
// At savefile position 0x0000:
|
||||
currentDisk = fHandle->readUint16BE();
|
||||
|
||||
// At 0x0002:
|
||||
fHandle->read(currentPartName, 13);
|
||||
// At 0x000F:
|
||||
fHandle->read(currentDatName, 13);
|
||||
|
||||
// At 0x001C:
|
||||
saveVar2 = fHandle->readSint16BE();
|
||||
|
||||
// At 0x001E:
|
||||
fHandle->read(currentPrcName, 13);
|
||||
// At 0x002B:
|
||||
fHandle->read(currentRelName, 13);
|
||||
// At 0x0038:
|
||||
fHandle->read(currentMsgName, 13);
|
||||
// At 0x0045:
|
||||
fHandle->read(bgName, 13);
|
||||
// At 0x0052:
|
||||
fHandle->read(currentCtName, 13);
|
||||
|
||||
checkDataDisk(currentDisk);
|
||||
@ -499,52 +508,84 @@ bool CineEngine::makeLoad(char *saveName) {
|
||||
loadCtFW(currentCtName);
|
||||
}
|
||||
|
||||
// At 0x005F:
|
||||
fHandle->readUint16BE();
|
||||
// At 0x0061:
|
||||
fHandle->readUint16BE();
|
||||
|
||||
// At 0x0063:
|
||||
for (i = 0; i < 255; i++) {
|
||||
// At 0x0063 + i * 32 + 0:
|
||||
objectTable[i].x = fHandle->readSint16BE();
|
||||
// At 0x0063 + i * 32 + 2:
|
||||
objectTable[i].y = fHandle->readSint16BE();
|
||||
// At 0x0063 + i * 32 + 4:
|
||||
objectTable[i].mask = fHandle->readUint16BE();
|
||||
// At 0x0063 + i * 32 + 6:
|
||||
objectTable[i].frame = fHandle->readSint16BE();
|
||||
// At 0x0063 + i * 32 + 8:
|
||||
objectTable[i].costume = fHandle->readSint16BE();
|
||||
// At 0x0063 + i * 32 + 10:
|
||||
fHandle->read(objectTable[i].name, 20);
|
||||
// At 0x0063 + i * 32 + 30:
|
||||
objectTable[i].part = fHandle->readUint16BE();
|
||||
}
|
||||
|
||||
// At 0x2043 (i.e. 0x0063 + 255 * 32):
|
||||
renderer->restorePalette(*fHandle);
|
||||
|
||||
// At 0x2083 (i.e. 0x2043 + 16 * 2 * 2):
|
||||
globalVars.load(*fHandle, NUM_MAX_VAR - 1);
|
||||
|
||||
// At 0x2281 (i.e. 0x2083 + 255 * 2):
|
||||
for (i = 0; i < 16; i++) {
|
||||
// At 0x2281 + i * 2:
|
||||
zoneData[i] = fHandle->readUint16BE();
|
||||
}
|
||||
|
||||
// At 0x22A1 (i.e. 0x2281 + 16 * 2):
|
||||
for (i = 0; i < 4; i++) {
|
||||
// At 0x22A1 + i * 2:
|
||||
commandVar3[i] = fHandle->readUint16BE();
|
||||
}
|
||||
|
||||
// At 0x22A9 (i.e. 0x22A1 + 4 * 2):
|
||||
fHandle->read(commandBuffer, 0x50);
|
||||
renderer->setCommand(commandBuffer);
|
||||
|
||||
// At 0x22F9 (i.e. 0x22A9 + 0x50):
|
||||
renderer->_cmdY = fHandle->readUint16BE();
|
||||
|
||||
// At 0x22FB:
|
||||
bgVar0 = fHandle->readUint16BE();
|
||||
// At 0x22FD:
|
||||
allowPlayerInput = fHandle->readUint16BE();
|
||||
// At 0x22FF:
|
||||
playerCommand = fHandle->readSint16BE();
|
||||
// At 0x2301:
|
||||
commandVar1 = fHandle->readSint16BE();
|
||||
// At 0x2303:
|
||||
isDrawCommandEnabled = fHandle->readUint16BE();
|
||||
// At 0x2305:
|
||||
var5 = fHandle->readUint16BE();
|
||||
// At 0x2307:
|
||||
var4 = fHandle->readUint16BE();
|
||||
// At 0x2309:
|
||||
var3 = fHandle->readUint16BE();
|
||||
// At 0x230B:
|
||||
var2 = fHandle->readUint16BE();
|
||||
// At 0x230D:
|
||||
commandVar2 = fHandle->readSint16BE();
|
||||
|
||||
// At 0x230F:
|
||||
renderer->_messageBg = fHandle->readUint16BE();
|
||||
|
||||
// At 0x2311:
|
||||
fHandle->readUint16BE();
|
||||
// At 0x2313:
|
||||
fHandle->readUint16BE();
|
||||
|
||||
// At 0x2315:
|
||||
loadResourcesFromSave(*fHandle, broken);
|
||||
|
||||
// TODO: handle screen params (really required ?)
|
||||
@ -1516,12 +1557,22 @@ void mainLoopSub6(void) {
|
||||
|
||||
void checkForPendingDataLoad(void) {
|
||||
if (newPrcName[0] != 0) {
|
||||
loadPrc(newPrcName);
|
||||
bool loadPrcOk = loadPrc(newPrcName);
|
||||
|
||||
strcpy(currentPrcName, newPrcName);
|
||||
strcpy(newPrcName, "");
|
||||
|
||||
addScriptToList0(1);
|
||||
// Check that the loading of the script file was successful before
|
||||
// trying to add script 1 from it to the global scripts list. This
|
||||
// fixes a crash when failing copy protection in Amiga or Atari ST
|
||||
// versions of Future Wars.
|
||||
if (loadPrcOk) {
|
||||
addScriptToList0(1);
|
||||
} else if (scumm_stricmp(currentPrcName, COPY_PROT_FAIL_PRC_NAME)) {
|
||||
// We only show an error here for other files than the file that
|
||||
// is loaded if copy protection fails (i.e. L201.ANI).
|
||||
warning("checkForPendingDataLoad: loadPrc(%s) failed", currentPrcName);
|
||||
}
|
||||
}
|
||||
|
||||
if (newRelName[0] != 0) {
|
||||
|
@ -112,7 +112,7 @@ int KyraEngine_v1::init() {
|
||||
_sound = new SoundTownsPC98_v2(this, _mixer);
|
||||
} else if (_flags.platform == Common::kPlatformPC98) {
|
||||
if (_flags.gameID == GI_KYRA1)
|
||||
_sound = new SoundPC98(this, _mixer);
|
||||
_sound = new SoundTowns/*SoundPC98*/(this, _mixer);
|
||||
else
|
||||
_sound = new SoundTownsPC98_v2(this, _mixer);
|
||||
} else if (midiDriver == MD_ADLIB) {
|
||||
|
@ -2363,7 +2363,7 @@ TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) :
|
||||
_numSSG(type == OD_TOWNS ? 0 : 3), _hasADPCM(type == OD_TYPE86 ? true : false),
|
||||
_numChan(type == OD_TYPE26 ? 3 : 6), _hasStereo(type == OD_TYPE26 ? false : true) {
|
||||
setTempo(84);
|
||||
_baserate = (3579545.0 / (double)getRate()) / 144.0;
|
||||
_baserate = (double)getRate() / 10368.0;
|
||||
}
|
||||
|
||||
TownsPC98_OpnDriver::~TownsPC98_OpnDriver() {
|
||||
@ -3095,8 +3095,8 @@ SoundTownsPC98_v2::~SoundTownsPC98_v2() {
|
||||
}
|
||||
|
||||
bool SoundTownsPC98_v2::init() {
|
||||
_driver = new TownsPC98_OpnDriver(_mixer, _vm->gameFlags().platform == Common::kPlatformPC98 ?
|
||||
TownsPC98_OpnDriver::OD_TYPE86 : TownsPC98_OpnDriver::OD_TOWNS);
|
||||
_driver = new TownsPC98_OpnDriver(_mixer, /*_vm->gameFlags().platform == Common::kPlatformPC98 ?
|
||||
TownsPC98_OpnDriver::OD_TYPE86 :*/ TownsPC98_OpnDriver::OD_TOWNS);
|
||||
_useFmSfx = _vm->gameFlags().platform == Common::kPlatformPC98 ? true : false;
|
||||
_vm->checkCD();
|
||||
// FIXME: While checking for 'track1.XXX(X)' looks like
|
||||
|
@ -1034,8 +1034,10 @@ void KyraEngine_LoK::initStaticResource() {
|
||||
}
|
||||
|
||||
// audio data tables
|
||||
#if 0
|
||||
static const char *tIntro98[] = { "intro%d.dat" };
|
||||
static const char *tIngame98[] = { "kyram%d.dat" };
|
||||
#endif
|
||||
|
||||
static const AudioDataStruct soundData_PC[] = {
|
||||
{ _soundFilesIntro, _soundFilesIntroSize, 0, 0 },
|
||||
@ -1049,18 +1051,20 @@ void KyraEngine_LoK::initStaticResource() {
|
||||
{ 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
#if 0
|
||||
static const AudioDataStruct soundData_PC98[] = {
|
||||
{ tIntro98, 1, 0, 0 },
|
||||
{ tIngame98, 1, 0, 0 },
|
||||
{ 0, 0, 0, 0}
|
||||
};
|
||||
#endif
|
||||
|
||||
if (_flags.platform == Common::kPlatformPC)
|
||||
_soundData = soundData_PC;
|
||||
else if (_flags.platform == Common::kPlatformFMTowns)
|
||||
_soundData = soundData_TOWNS;
|
||||
else if (_flags.platform == Common::kPlatformPC98)
|
||||
_soundData = soundData_PC98;
|
||||
_soundData = soundData_TOWNS/*soundData_PC98*/;
|
||||
|
||||
}
|
||||
|
||||
@ -1259,9 +1263,11 @@ void KyraEngine_HoF::initStaticResource() {
|
||||
static const char *fmtMusicFileListFinale[] = { "finale%d.twn" };
|
||||
static const char *fmtMusicFileListIngame[] = { "km%02d.twn" };
|
||||
|
||||
#if 0
|
||||
static const char *pc98MusicFileListIntro[] = { "intro%d.86" };
|
||||
static const char *pc98MusicFileListFinale[] = { "finale%d.86" };
|
||||
static const char *pc98MusicFileListIngame[] = { "km%02d.86" };
|
||||
#endif
|
||||
|
||||
static const AudioDataStruct soundData_PC[] = {
|
||||
{ _musicFileListIntro, _musicFileListIntroSize, 0, 0 },
|
||||
@ -1275,18 +1281,20 @@ void KyraEngine_HoF::initStaticResource() {
|
||||
{ fmtMusicFileListFinale, 1, _cdaTrackTableFinale, _cdaTrackTableFinaleSize >> 1 }
|
||||
};
|
||||
|
||||
#if 0
|
||||
static const AudioDataStruct soundData_PC98[] = {
|
||||
{ pc98MusicFileListIntro, 1, 0, 0 },
|
||||
{ pc98MusicFileListIngame, 1, 0, 0 },
|
||||
{ pc98MusicFileListFinale, 1, 0, 0 }
|
||||
};
|
||||
#endif
|
||||
|
||||
if (_flags.platform == Common::kPlatformPC)
|
||||
_soundData = soundData_PC;
|
||||
else if (_flags.platform == Common::kPlatformFMTowns)
|
||||
_soundData = soundData_TOWNS;
|
||||
else if (_flags.platform == Common::kPlatformPC98)
|
||||
_soundData = soundData_PC98;
|
||||
_soundData = soundData_TOWNS/*soundData_PC98*/;
|
||||
|
||||
// setup sequence data
|
||||
_sequences = _staticres->loadHofSequenceData(k2SeqplaySeqData, tmpSize);
|
||||
|
@ -36,7 +36,7 @@ namespace Lure {
|
||||
#define LURE_DAT_MAJOR 1
|
||||
#define LURE_DAT_MINOR 29
|
||||
#define LURE_MIN_SAVEGAME_MINOR 25
|
||||
#define LURE_SAVEGAME_MINOR 32
|
||||
#define LURE_SAVEGAME_MINOR 33
|
||||
|
||||
#define LURE_DEBUG 1
|
||||
|
||||
|
@ -456,6 +456,8 @@ void HotspotData::saveToStream(WriteStream *stream) {
|
||||
stream->writeSint16LE(startY);
|
||||
stream->writeUint16LE(roomNumber);
|
||||
stream->writeByte(layer);
|
||||
stream->writeUint16LE(walkX);
|
||||
stream->writeUint16LE(walkY);
|
||||
|
||||
stream->writeUint16LE(width);
|
||||
stream->writeUint16LE(height);
|
||||
@ -503,6 +505,10 @@ void HotspotData::loadFromStream(ReadStream *stream) {
|
||||
uint8 saveVersion = LureEngine::getReference().saveVersion();
|
||||
if (saveVersion >= 29)
|
||||
layer = stream->readByte();
|
||||
if (saveVersion >= 33) {
|
||||
walkX = stream->readUint16LE();
|
||||
walkY = stream->readUint16LE();
|
||||
}
|
||||
|
||||
width = stream->readUint16LE();
|
||||
height = stream->readUint16LE();
|
||||
|
@ -424,6 +424,7 @@ void Parallaction_ns::_c_testResult(void *parm) {
|
||||
}
|
||||
_inTestResult = true;
|
||||
|
||||
_gfx->freeLabels();
|
||||
_gfx->updateScreen();
|
||||
|
||||
_disk->selectArchive("disk1");
|
||||
|
@ -42,13 +42,23 @@ namespace Parallaction {
|
||||
#define ANSWER_CHARACTER_X 10
|
||||
#define ANSWER_CHARACTER_Y 80
|
||||
|
||||
|
||||
class DialogueManager {
|
||||
|
||||
enum {
|
||||
RUN_QUESTION,
|
||||
RUN_ANSWER,
|
||||
NEXT_QUESTION,
|
||||
NEXT_ANSWER,
|
||||
DIALOGUE_OVER
|
||||
} _state;
|
||||
|
||||
Parallaction *_vm;
|
||||
SpeakData *_data;
|
||||
Dialogue *_dialogue;
|
||||
|
||||
bool _askPassword;
|
||||
int _passwordLen;
|
||||
bool _passwordChanged;
|
||||
|
||||
bool isNpc;
|
||||
GfxObj *_questioner;
|
||||
@ -59,92 +69,69 @@ class DialogueManager {
|
||||
uint16 _visAnswers[5];
|
||||
int _numVisAnswers;
|
||||
|
||||
int _answerId;
|
||||
|
||||
int _selection, _oldSelection;
|
||||
|
||||
uint32 _mouseButtons;
|
||||
Common::Point _mousePos;
|
||||
bool _isKeyDown;
|
||||
uint16 _downKey;
|
||||
|
||||
|
||||
public:
|
||||
DialogueManager(Parallaction *vm, SpeakData *data) : _vm(vm), _data(data) {
|
||||
_dialogue = _data->_dialogue;
|
||||
isNpc = scumm_stricmp(_data->_name, "yourself") && _data->_name[0] != '\0';
|
||||
_questioner = isNpc ? _vm->_disk->loadTalk(_data->_name) : _vm->_char._talk;
|
||||
_answerer = _vm->_char._talk;
|
||||
}
|
||||
DialogueManager(Parallaction *vm, ZonePtr z);
|
||||
~DialogueManager();
|
||||
|
||||
~DialogueManager() {
|
||||
if (isNpc) {
|
||||
delete _questioner;
|
||||
}
|
||||
bool isOver() {
|
||||
return _state == DIALOGUE_OVER;
|
||||
}
|
||||
|
||||
void run();
|
||||
|
||||
ZonePtr _z;
|
||||
CommandList *_cmdList;
|
||||
|
||||
protected:
|
||||
void displayQuestion();
|
||||
bool displayQuestion();
|
||||
bool displayAnswers();
|
||||
bool displayAnswer(uint16 i);
|
||||
|
||||
uint16 getAnswer();
|
||||
int16 selectAnswer();
|
||||
uint16 askPassword();
|
||||
int16 selectAnswer1();
|
||||
int16 selectAnswerN();
|
||||
int16 askPassword();
|
||||
int16 getHoverAnswer(int16 x, int16 y);
|
||||
|
||||
void runQuestion();
|
||||
void runAnswer();
|
||||
void nextQuestion();
|
||||
void nextAnswer();
|
||||
|
||||
bool checkPassword();
|
||||
void resetPassword();
|
||||
void accumPassword(uint16 ascii);
|
||||
};
|
||||
|
||||
uint16 DialogueManager::askPassword() {
|
||||
debugC(3, kDebugExec, "checkDialoguePassword()");
|
||||
DialogueManager::DialogueManager(Parallaction *vm, ZonePtr z) : _vm(vm), _z(z) {
|
||||
_dialogue = _z->u.speak->_dialogue;
|
||||
isNpc = scumm_stricmp(_z->u.speak->_name, "yourself") && _z->u.speak->_name[0] != '\0';
|
||||
_questioner = isNpc ? _vm->_disk->loadTalk(_z->u.speak->_name) : _vm->_char._talk;
|
||||
_answerer = _vm->_char._talk;
|
||||
|
||||
uint16 passwordLen = 0;
|
||||
_password[0] = '\0';
|
||||
_askPassword = false;
|
||||
_q = _dialogue->_questions[0];
|
||||
|
||||
_vm->_balloonMan->setDialogueBalloon(_q->_answers[0]->_text, 1, 3);
|
||||
int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y);
|
||||
_vm->_gfx->setItemFrame(id, 0);
|
||||
|
||||
Common::Event e;
|
||||
bool changed = true; // force first refresh
|
||||
|
||||
while (true) {
|
||||
e.kbd.ascii = 0;
|
||||
|
||||
if (g_system->getEventManager()->pollEvent(e)) {
|
||||
if ((e.type == Common::EVENT_KEYDOWN) && isdigit(e.kbd.ascii)) {
|
||||
_password[passwordLen] = e.kbd.ascii;
|
||||
passwordLen++;
|
||||
_password[passwordLen] = '\0';
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
_vm->_balloonMan->setBalloonText(0, _q->_answers[0]->_text, 3);
|
||||
_vm->_gfx->updateScreen();
|
||||
changed = false;
|
||||
}
|
||||
|
||||
if ((passwordLen == MAX_PASSWORD_LENGTH) || (e.kbd.ascii == Common::KEYCODE_RETURN)) {
|
||||
|
||||
if ((!scumm_stricmp(_vm->_char.getBaseName(), _doughName) && !scumm_strnicmp(_password, "1732461", 7)) ||
|
||||
(!scumm_stricmp(_vm->_char.getBaseName(), _donnaName) && !scumm_strnicmp(_password, "1622", 4)) ||
|
||||
(!scumm_stricmp(_vm->_char.getBaseName(), _dinoName) && !scumm_strnicmp(_password, "179", 3))) {
|
||||
|
||||
break;
|
||||
|
||||
} else {
|
||||
passwordLen = 0;
|
||||
_password[0] = '\0';
|
||||
changed = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
g_system->delayMillis(20);
|
||||
|
||||
}
|
||||
|
||||
_vm->hideDialogueStuff();
|
||||
|
||||
return 0;
|
||||
_cmdList = 0;
|
||||
_answerId = 0;
|
||||
|
||||
_state = displayQuestion() ? RUN_QUESTION : NEXT_ANSWER;
|
||||
}
|
||||
|
||||
|
||||
DialogueManager::~DialogueManager() {
|
||||
if (isNpc) {
|
||||
delete _questioner;
|
||||
}
|
||||
_z = nullZonePtr;
|
||||
}
|
||||
|
||||
bool DialogueManager::displayAnswer(uint16 i) {
|
||||
|
||||
@ -161,7 +148,7 @@ bool DialogueManager::displayAnswer(uint16 i) {
|
||||
assert(id >= 0);
|
||||
_visAnswers[id] = i;
|
||||
|
||||
_askPassword = (strstr(a->_text, "%p") != NULL);
|
||||
_askPassword = (strstr(a->_text, "%P") != NULL);
|
||||
_numVisAnswers++;
|
||||
|
||||
return true;
|
||||
@ -178,134 +165,244 @@ bool DialogueManager::displayAnswers() {
|
||||
displayAnswer(i);
|
||||
}
|
||||
|
||||
if (_askPassword) {
|
||||
resetPassword();
|
||||
// _vm->_balloonMan->setDialogueBalloon(_q->_answers[0]->_text, 1, 3);
|
||||
int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y);
|
||||
_vm->_gfx->setItemFrame(id, 0);
|
||||
} else
|
||||
if (_numVisAnswers == 1) {
|
||||
int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y);
|
||||
_vm->_gfx->setItemFrame(id, _q->_answers[0]->_mood & 0xF);
|
||||
_vm->_balloonMan->setBalloonText(0, _q->_answers[_visAnswers[0]]->_text, 0);
|
||||
} else
|
||||
if (_numVisAnswers > 1) {
|
||||
int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y);
|
||||
_vm->_gfx->setItemFrame(id, _q->_answers[_visAnswers[0]]->_mood & 0xF);
|
||||
_oldSelection = -1;
|
||||
_selection = 0;
|
||||
}
|
||||
|
||||
return _numVisAnswers > 0;
|
||||
}
|
||||
|
||||
void DialogueManager::displayQuestion() {
|
||||
|
||||
if (!scumm_stricmp(_q->_text, "NULL")) return;
|
||||
bool DialogueManager::displayQuestion() {
|
||||
if (!scumm_stricmp(_q->_text, "NULL")) return false;
|
||||
|
||||
_vm->_balloonMan->setSingleBalloon(_q->_text, QUESTION_BALLOON_X, QUESTION_BALLOON_Y, _q->_mood & 0x10, 0);
|
||||
int id = _vm->_gfx->setItem(_questioner, QUESTION_CHARACTER_X, QUESTION_CHARACTER_Y);
|
||||
_vm->_gfx->setItemFrame(id, _q->_mood & 0xF);
|
||||
|
||||
_vm->_gfx->updateScreen();
|
||||
_vm->_input->waitUntilLeftClick();
|
||||
_vm->hideDialogueStuff();
|
||||
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint16 DialogueManager::getAnswer() {
|
||||
|
||||
uint16 answer = 0;
|
||||
bool DialogueManager::checkPassword() {
|
||||
return ((!scumm_stricmp(_vm->_char.getBaseName(), _doughName) && !scumm_strnicmp(_password, "1732461", 7)) ||
|
||||
(!scumm_stricmp(_vm->_char.getBaseName(), _donnaName) && !scumm_strnicmp(_password, "1622", 4)) ||
|
||||
(!scumm_stricmp(_vm->_char.getBaseName(), _dinoName) && !scumm_strnicmp(_password, "179", 3)));
|
||||
}
|
||||
|
||||
if (_askPassword == false) {
|
||||
answer = selectAnswer();
|
||||
} else {
|
||||
answer = askPassword();
|
||||
void DialogueManager::resetPassword() {
|
||||
_passwordLen = 0;
|
||||
_password[0] = '\0';
|
||||
_passwordChanged = true;
|
||||
}
|
||||
|
||||
void DialogueManager::accumPassword(uint16 ascii) {
|
||||
if (!isdigit(ascii)) {
|
||||
return;
|
||||
}
|
||||
|
||||
debugC(3, kDebugExec, "runDialogue: user selected answer #%i", answer);
|
||||
_password[_passwordLen] = ascii;
|
||||
_passwordLen++;
|
||||
_password[_passwordLen] = '\0';
|
||||
_passwordChanged = true;
|
||||
}
|
||||
|
||||
return answer;
|
||||
int16 DialogueManager::askPassword() {
|
||||
|
||||
if (_isKeyDown) {
|
||||
accumPassword(_downKey);
|
||||
}
|
||||
|
||||
if (_passwordChanged) {
|
||||
_vm->_balloonMan->setBalloonText(0, _q->_answers[0]->_text, 3);
|
||||
_passwordChanged = false;
|
||||
}
|
||||
|
||||
if ((_passwordLen == MAX_PASSWORD_LENGTH) || ((_isKeyDown) && (_downKey == Common::KEYCODE_RETURN))) {
|
||||
if (checkPassword()) {
|
||||
return 0;
|
||||
} else {
|
||||
resetPassword();
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int16 DialogueManager::selectAnswer1() {
|
||||
|
||||
if (_mouseButtons == kMouseLeftUp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int16 DialogueManager::selectAnswerN() {
|
||||
|
||||
_selection = _vm->_balloonMan->hitTestDialogueBalloon(_mousePos.x, _mousePos.y);
|
||||
|
||||
if (_selection != _oldSelection) {
|
||||
if (_oldSelection != -1) {
|
||||
_vm->_balloonMan->setBalloonText(_oldSelection, _q->_answers[_visAnswers[_oldSelection]]->_text, 3);
|
||||
}
|
||||
|
||||
if (_vm->quit())
|
||||
return -1;
|
||||
|
||||
if (_selection != -1) {
|
||||
_vm->_balloonMan->setBalloonText(_selection, _q->_answers[_visAnswers[_selection]]->_text, 0);
|
||||
_vm->_gfx->setItemFrame(0, _q->_answers[_visAnswers[_selection]]->_mood & 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
_oldSelection = _selection;
|
||||
|
||||
if ((_mouseButtons == kMouseLeftUp) && (_selection != -1)) {
|
||||
return _visAnswers[_selection];
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void DialogueManager::runQuestion() {
|
||||
debugC(9, kDebugDialogue, "runQuestion\n");
|
||||
|
||||
if (_mouseButtons == kMouseLeftUp) {
|
||||
_vm->hideDialogueStuff();
|
||||
_state = NEXT_ANSWER;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void DialogueManager::nextAnswer() {
|
||||
debugC(9, kDebugDialogue, "nextAnswer\n");
|
||||
|
||||
if (_q->_answers[0] == NULL) {
|
||||
_state = DIALOGUE_OVER;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!scumm_stricmp(_q->_answers[0]->_text, "NULL")) {
|
||||
_answerId = 0;
|
||||
_state = NEXT_QUESTION;
|
||||
return;
|
||||
}
|
||||
|
||||
_state = displayAnswers() ? RUN_ANSWER : DIALOGUE_OVER;
|
||||
}
|
||||
|
||||
void DialogueManager::runAnswer() {
|
||||
debugC(9, kDebugDialogue, "runAnswer\n");
|
||||
|
||||
if (_askPassword) {
|
||||
_answerId = askPassword();
|
||||
} else
|
||||
if (_numVisAnswers == 1) {
|
||||
_answerId = selectAnswer1();
|
||||
} else {
|
||||
_answerId = selectAnswerN();
|
||||
}
|
||||
|
||||
if (_answerId != -1) {
|
||||
_cmdList = &_q->_answers[_answerId]->_commands;
|
||||
_vm->hideDialogueStuff();
|
||||
_state = NEXT_QUESTION;
|
||||
}
|
||||
}
|
||||
|
||||
void DialogueManager::nextQuestion() {
|
||||
debugC(9, kDebugDialogue, "nextQuestion\n");
|
||||
|
||||
_q = _q->_answers[_answerId]->_following._question;
|
||||
if (_q == 0) {
|
||||
_state = DIALOGUE_OVER;
|
||||
} else {
|
||||
_state = displayQuestion() ? RUN_QUESTION : NEXT_ANSWER;
|
||||
}
|
||||
}
|
||||
|
||||
void DialogueManager::run() {
|
||||
|
||||
_askPassword = false;
|
||||
CommandList *cmdlist = NULL;
|
||||
// cache event data
|
||||
_mouseButtons = _vm->_input->getLastButtonEvent();
|
||||
_vm->_input->getCursorPos(_mousePos);
|
||||
_isKeyDown = _vm->_input->getLastKeyDown(_downKey);
|
||||
|
||||
_q = _dialogue->_questions[0];
|
||||
int16 answer;
|
||||
switch (_state) {
|
||||
case RUN_QUESTION:
|
||||
runQuestion();
|
||||
break;
|
||||
|
||||
while (_q) {
|
||||
case NEXT_ANSWER:
|
||||
nextAnswer();
|
||||
break;
|
||||
|
||||
answer = 0;
|
||||
case NEXT_QUESTION:
|
||||
nextQuestion();
|
||||
break;
|
||||
|
||||
displayQuestion();
|
||||
case RUN_ANSWER:
|
||||
runAnswer();
|
||||
break;
|
||||
|
||||
if (_vm->quit())
|
||||
return;
|
||||
|
||||
if (_q->_answers[0] == NULL) break;
|
||||
|
||||
if (scumm_stricmp(_q->_answers[0]->_text, "NULL")) {
|
||||
if (!displayAnswers()) break;
|
||||
answer = getAnswer();
|
||||
|
||||
if (_vm->quit())
|
||||
return;
|
||||
|
||||
cmdlist = &_q->_answers[answer]->_commands;
|
||||
case DIALOGUE_OVER:
|
||||
if (_cmdList) {
|
||||
_vm->_cmdExec->run(*_cmdList);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
error("unknown state in DialogueManager");
|
||||
|
||||
_q = _q->_answers[answer]->_following._question;
|
||||
}
|
||||
|
||||
if (cmdlist)
|
||||
_vm->_cmdExec->run(*cmdlist);
|
||||
|
||||
}
|
||||
|
||||
int16 DialogueManager::selectAnswer() {
|
||||
|
||||
int16 numAvailableAnswers = _numVisAnswers;
|
||||
|
||||
int id = _vm->_gfx->setItem(_answerer, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y);
|
||||
_vm->_gfx->setItemFrame(id, _q->_answers[0]->_mood & 0xF);
|
||||
|
||||
if (numAvailableAnswers == 1) {
|
||||
_vm->_balloonMan->setBalloonText(0, _q->_answers[0]->_text, 0);
|
||||
_vm->_input->waitUntilLeftClick();
|
||||
_vm->hideDialogueStuff();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int oldSelection = -1;
|
||||
int selection = 0;
|
||||
|
||||
uint32 event;
|
||||
Common::Point p;
|
||||
while (!_vm->quit()) {
|
||||
|
||||
_vm->_input->readInput();
|
||||
_vm->_input->getCursorPos(p);
|
||||
event = _vm->_input->getLastButtonEvent();
|
||||
selection = _vm->_balloonMan->hitTestDialogueBalloon(p.x, p.y);
|
||||
|
||||
if (selection != oldSelection) {
|
||||
if (oldSelection != -1) {
|
||||
_vm->_balloonMan->setBalloonText(oldSelection, _q->_answers[_visAnswers[oldSelection]]->_text, 3);
|
||||
}
|
||||
|
||||
if (selection != -1) {
|
||||
_vm->_balloonMan->setBalloonText(selection, _q->_answers[_visAnswers[selection]]->_text, 0);
|
||||
_vm->_gfx->setItemFrame(0, _q->_answers[_visAnswers[selection]]->_mood & 0xF);
|
||||
}
|
||||
}
|
||||
|
||||
if ((selection != -1) && (event == kMouseLeftUp)) {
|
||||
break;
|
||||
}
|
||||
|
||||
_vm->_gfx->updateScreen();
|
||||
g_system->delayMillis(20);
|
||||
|
||||
oldSelection = selection;
|
||||
}
|
||||
|
||||
_vm->hideDialogueStuff();
|
||||
|
||||
return _visAnswers[selection];
|
||||
void Parallaction::enterDialogueMode(ZonePtr z) {
|
||||
debugC(1, kDebugDialogue, "Parallaction::enterDialogueMode(%s)", z->u.speak->_name);
|
||||
_dialogueMan = new DialogueManager(this, z);
|
||||
_input->_inputMode = Input::kInputModeDialogue;
|
||||
}
|
||||
|
||||
void Parallaction::exitDialogueMode() {
|
||||
debugC(1, kDebugDialogue, "Parallaction::exitDialogueMode()");
|
||||
_input->_inputMode = Input::kInputModeGame;
|
||||
|
||||
void Parallaction::runDialogue(SpeakData *data) {
|
||||
debugC(1, kDebugExec, "runDialogue: starting dialogue '%s'", data->_name);
|
||||
// The current instance of _dialogueMan must be destroyed before the zone commands
|
||||
// are executed, because they may create another instance of _dialogueMan that
|
||||
// overwrite the current one. This would cause headaches (and it did, actually).
|
||||
ZonePtr z = _dialogueMan->_z;
|
||||
delete _dialogueMan;
|
||||
_dialogueMan = 0;
|
||||
|
||||
DialogueManager man(this, data);
|
||||
man.run();
|
||||
_cmdExec->run(z->_commands, z);
|
||||
}
|
||||
|
||||
void Parallaction::runDialogueFrame() {
|
||||
if (_input->_inputMode != Input::kInputModeDialogue) {
|
||||
return;
|
||||
}
|
||||
|
||||
_dialogueMan->run();
|
||||
|
||||
if (_dialogueMan->isOver()) {
|
||||
exitDialogueMode();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -224,7 +224,11 @@ DECLARE_COMMAND_OPCODE(start) {
|
||||
|
||||
|
||||
DECLARE_COMMAND_OPCODE(speak) {
|
||||
_vm->_activeZone = _ctxt.cmd->u._zone;
|
||||
if ((_ctxt.cmd->u._zone->_type & 0xFFFF) == kZoneSpeak) {
|
||||
_vm->enterDialogueMode(_ctxt.cmd->u._zone);
|
||||
} else {
|
||||
_vm->_activeZone = _ctxt.cmd->u._zone;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -322,6 +326,7 @@ DECLARE_COMMAND_OPCODE(stop) {
|
||||
|
||||
|
||||
void Parallaction_ns::drawAnimations() {
|
||||
debugC(9, kDebugExec, "Parallaction_ns::drawAnimations()\n");
|
||||
|
||||
uint16 layer = 0;
|
||||
|
||||
@ -362,6 +367,8 @@ void Parallaction_ns::drawAnimations() {
|
||||
}
|
||||
}
|
||||
|
||||
debugC(9, kDebugExec, "Parallaction_ns::drawAnimations done()\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -417,7 +424,6 @@ label1:
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void CommandExec::run(CommandList& list, ZonePtr z) {
|
||||
if (list.size() == 0) {
|
||||
debugC(3, kDebugExec, "runCommands: nothing to do");
|
||||
@ -542,11 +548,8 @@ uint16 Parallaction::runZone(ZonePtr z) {
|
||||
break;
|
||||
|
||||
case kZoneSpeak:
|
||||
runDialogue(z->u.speak);
|
||||
if (_vm->quit())
|
||||
return 0;
|
||||
break;
|
||||
|
||||
enterDialogueMode(z);
|
||||
return 0;
|
||||
}
|
||||
|
||||
debugC(3, kDebugExec, "runZone completed");
|
||||
|
@ -267,9 +267,6 @@ void Gfx::drawWrappedText(Font *font, Graphics::Surface* surf, char *text, byte
|
||||
}
|
||||
|
||||
|
||||
// this is the maximum size of an unpacked frame in BRA
|
||||
byte _unpackedBitmap[640*401];
|
||||
|
||||
#if 0
|
||||
void Gfx::unpackBlt(const Common::Rect& r, byte *data, uint size, Graphics::Surface *surf, uint16 z, byte transparentColor) {
|
||||
|
||||
|
@ -33,6 +33,11 @@
|
||||
|
||||
namespace Parallaction {
|
||||
|
||||
// this is the size of the receiving buffer for unpacked frames,
|
||||
// since BRA uses some insanely big animations.
|
||||
#define MAXIMUM_UNPACKED_BITMAP_SIZE 640*401
|
||||
|
||||
|
||||
void Gfx::registerVar(const Common::String &name, int32 initialValue) {
|
||||
if (_vars.contains(name)) {
|
||||
warning("Variable '%s' already registered, ignoring initial value.\n", name.c_str());
|
||||
@ -752,6 +757,9 @@ Gfx::Gfx(Parallaction* vm) :
|
||||
_halfbrite = false;
|
||||
_hbCircleRadius = 0;
|
||||
|
||||
_unpackedBitmap = new byte[MAXIMUM_UNPACKED_BITMAP_SIZE];
|
||||
assert(_unpackedBitmap);
|
||||
|
||||
registerVar("background_mode", 1);
|
||||
_varBackgroundMode = 1;
|
||||
|
||||
@ -769,6 +777,8 @@ Gfx::~Gfx() {
|
||||
freeBackground();
|
||||
freeLabels();
|
||||
|
||||
delete []_unpackedBitmap;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -547,6 +547,8 @@ public:
|
||||
uint _screenX; // scrolling position
|
||||
uint _screenY;
|
||||
|
||||
byte *_unpackedBitmap;
|
||||
|
||||
protected:
|
||||
Parallaction* _vm;
|
||||
bool _halfbrite;
|
||||
|
@ -42,12 +42,14 @@ uint16 Input::readInput() {
|
||||
uint16 KeyDown = 0;
|
||||
|
||||
_mouseButtons = kMouseNone;
|
||||
_lastKeyDownAscii = -1;
|
||||
|
||||
Common::EventManager *eventMan = _vm->_system->getEventManager();
|
||||
while (eventMan->pollEvent(e)) {
|
||||
|
||||
switch (e.type) {
|
||||
case Common::EVENT_KEYDOWN:
|
||||
_lastKeyDownAscii = e.kbd.ascii;
|
||||
if (e.kbd.flags == Common::KBD_CTRL && e.kbd.keycode == 'd')
|
||||
_vm->_debugger->attach();
|
||||
if (_vm->getFeatures() & GF_DEMO) break;
|
||||
@ -97,6 +99,11 @@ uint16 Input::readInput() {
|
||||
|
||||
}
|
||||
|
||||
bool Input::getLastKeyDown(uint16 &ascii) {
|
||||
ascii = _lastKeyDownAscii;
|
||||
return (_lastKeyDownAscii != -1);
|
||||
}
|
||||
|
||||
// FIXME: see comment for readInput()
|
||||
void Input::waitForButtonEvent(uint32 buttonEventMask, int32 timeout) {
|
||||
|
||||
@ -192,11 +199,38 @@ InputData* Input::updateInput() {
|
||||
case kInputModeGame:
|
||||
updateGameInput();
|
||||
break;
|
||||
|
||||
case kInputModeDialogue:
|
||||
readInput();
|
||||
break;
|
||||
}
|
||||
|
||||
return &_inputData;
|
||||
}
|
||||
|
||||
void Input::trackMouse(ZonePtr z) {
|
||||
if ((z != _hoverZone) && (_hoverZone)) {
|
||||
stopHovering();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!z) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((!_hoverZone) && ((z->_flags & kFlagsNoName) == 0)) {
|
||||
_hoverZone = z;
|
||||
_vm->_gfx->showFloatingLabel(_hoverZone->_label);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Input::stopHovering() {
|
||||
_hoverZone = nullZonePtr;
|
||||
_vm->_gfx->hideFloatingLabel();
|
||||
}
|
||||
|
||||
|
||||
bool Input::translateGameInput() {
|
||||
|
||||
if ((_engineFlags & kEnginePauseJobs) || (_engineFlags & kEngineInventory)) {
|
||||
@ -231,23 +265,10 @@ bool Input::translateGameInput() {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((z != _hoverZone) && (_hoverZone)) {
|
||||
_hoverZone = nullZonePtr;
|
||||
_inputData._event = kEvExitZone;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!z) {
|
||||
_inputData._event = kEvNone;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((!_hoverZone) && ((z->_flags & kFlagsNoName) == 0)) {
|
||||
_hoverZone = z;
|
||||
_inputData._event = kEvEnterZone;
|
||||
_inputData._label = z->_label;
|
||||
return true;
|
||||
}
|
||||
trackMouse(z);
|
||||
if (!z) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((_mouseButtons == kMouseLeftUp) && ((_activeItem._id != 0) || ((z->_type & 0xFFFF) == kZoneCommand))) {
|
||||
|
||||
|
@ -66,6 +66,7 @@ class Input {
|
||||
|
||||
Common::Point _mousePos;
|
||||
uint16 _mouseButtons;
|
||||
int32 _lastKeyDownAscii;
|
||||
|
||||
bool _mouseHidden;
|
||||
ZonePtr _hoverZone;
|
||||
@ -73,7 +74,8 @@ class Input {
|
||||
public:
|
||||
enum {
|
||||
kInputModeGame = 0,
|
||||
kInputModeComment = 1
|
||||
kInputModeComment = 1,
|
||||
kInputModeDialogue = 2
|
||||
};
|
||||
|
||||
|
||||
@ -99,14 +101,13 @@ public:
|
||||
|
||||
uint16 readInput();
|
||||
InputData* updateInput();
|
||||
void trackMouse(ZonePtr z);
|
||||
void waitUntilLeftClick();
|
||||
void waitForButtonEvent(uint32 buttonEventMask, int32 timeout = -1);
|
||||
uint32 getLastButtonEvent() { return _mouseButtons; }
|
||||
bool getLastKeyDown(uint16 &ascii);
|
||||
|
||||
void stopHovering() {
|
||||
_hoverZone = nullZonePtr;
|
||||
}
|
||||
|
||||
void stopHovering();
|
||||
};
|
||||
|
||||
} // namespace Parallaction
|
||||
|
@ -164,6 +164,11 @@ void Parallaction::updateView() {
|
||||
}
|
||||
|
||||
|
||||
void Parallaction::hideDialogueStuff() {
|
||||
_gfx->freeItems();
|
||||
_balloonMan->freeBalloons();
|
||||
}
|
||||
|
||||
|
||||
void Parallaction::freeCharacter() {
|
||||
debugC(1, kDebugExec, "freeCharacter()");
|
||||
@ -297,16 +302,6 @@ void Parallaction::showLocationComment(const char *text, bool end) {
|
||||
void Parallaction::processInput(InputData *data) {
|
||||
|
||||
switch (data->_event) {
|
||||
case kEvEnterZone:
|
||||
debugC(2, kDebugInput, "processInput: kEvEnterZone");
|
||||
_gfx->showFloatingLabel(data->_label);
|
||||
break;
|
||||
|
||||
case kEvExitZone:
|
||||
debugC(2, kDebugInput, "processInput: kEvExitZone");
|
||||
_gfx->hideFloatingLabel();
|
||||
break;
|
||||
|
||||
case kEvAction:
|
||||
debugC(2, kDebugInput, "processInput: kEvAction");
|
||||
_input->stopHovering();
|
||||
@ -317,7 +312,6 @@ void Parallaction::processInput(InputData *data) {
|
||||
|
||||
case kEvOpenInventory:
|
||||
_input->stopHovering();
|
||||
_gfx->hideFloatingLabel();
|
||||
if (hitZone(kZoneYou, data->_mousePos.x, data->_mousePos.y) == 0) {
|
||||
setArrowCursor();
|
||||
}
|
||||
@ -367,25 +361,29 @@ void Parallaction::processInput(InputData *data) {
|
||||
void Parallaction::runGame() {
|
||||
|
||||
InputData *data = _input->updateInput();
|
||||
if (data->_event != kEvNone) {
|
||||
processInput(data);
|
||||
if (_vm->quit())
|
||||
return;
|
||||
|
||||
if (_input->_inputMode == Input::kInputModeDialogue) {
|
||||
runDialogueFrame();
|
||||
} else {
|
||||
if (data->_event != kEvNone) {
|
||||
processInput(data);
|
||||
}
|
||||
|
||||
if (_vm->quit())
|
||||
return;
|
||||
|
||||
runPendingZones();
|
||||
|
||||
if (_vm->quit())
|
||||
return;
|
||||
|
||||
if (_engineFlags & kEngineChangeLocation) {
|
||||
changeLocation(_location._name);
|
||||
}
|
||||
}
|
||||
|
||||
if (_vm->quit())
|
||||
return;
|
||||
|
||||
runPendingZones();
|
||||
|
||||
if (_vm->quit())
|
||||
return;
|
||||
|
||||
if (_engineFlags & kEngineChangeLocation) {
|
||||
changeLocation(_location._name);
|
||||
}
|
||||
|
||||
if (_vm->quit())
|
||||
return;
|
||||
|
||||
_gfx->beginFrame();
|
||||
|
||||
if (_input->_inputMode == Input::kInputModeGame) {
|
||||
@ -400,7 +398,6 @@ void Parallaction::runGame() {
|
||||
|
||||
// change this to endFrame?
|
||||
updateView();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -668,6 +665,7 @@ void Parallaction::beep() {
|
||||
}
|
||||
|
||||
void Parallaction::scheduleLocationSwitch(const char *location) {
|
||||
debugC(9, kDebugExec, "scheduleLocationSwitch(%s)\n", location);
|
||||
strcpy(_location._name, location);
|
||||
_engineFlags |= kEngineChangeLocation;
|
||||
}
|
||||
|
@ -113,8 +113,6 @@ enum EngineFlags {
|
||||
|
||||
enum {
|
||||
kEvNone = 0,
|
||||
kEvEnterZone = 1,
|
||||
kEvExitZone = 2,
|
||||
kEvAction = 3,
|
||||
kEvOpenInventory = 4,
|
||||
kEvCloseInventory = 5,
|
||||
@ -164,6 +162,7 @@ class Debugger;
|
||||
class Gfx;
|
||||
class SoundMan;
|
||||
class Input;
|
||||
class DialogueManager;
|
||||
|
||||
struct Location {
|
||||
|
||||
@ -281,8 +280,6 @@ public:
|
||||
uint16 runZone(ZonePtr z);
|
||||
void freeZones();
|
||||
|
||||
void runDialogue(SpeakData*);
|
||||
|
||||
AnimationPtr findAnimation(const char *name);
|
||||
void freeAnimations();
|
||||
|
||||
@ -425,10 +422,11 @@ public:
|
||||
|
||||
void setupBalloonManager();
|
||||
|
||||
void hideDialogueStuff() {
|
||||
_gfx->freeItems();
|
||||
_balloonMan->freeBalloons();
|
||||
}
|
||||
void hideDialogueStuff();
|
||||
DialogueManager *_dialogueMan;
|
||||
void enterDialogueMode(ZonePtr z);
|
||||
void exitDialogueMode();
|
||||
void runDialogueFrame();
|
||||
|
||||
};
|
||||
|
||||
|
@ -212,13 +212,21 @@ void Parallaction_br::runPendingZones() {
|
||||
if (_activeZone) {
|
||||
z = _activeZone; // speak Zone or sound
|
||||
_activeZone = nullZonePtr;
|
||||
runZone(z); // FIXME: BRA doesn't handle sound yet
|
||||
if ((z->_type & 0xFFFF) == kZoneSpeak) {
|
||||
enterDialogueMode(z);
|
||||
} else {
|
||||
runZone(z); // FIXME: BRA doesn't handle sound yet
|
||||
}
|
||||
}
|
||||
|
||||
if (_activeZone2) {
|
||||
z = _activeZone2; // speak Zone or sound
|
||||
_activeZone2 = nullZonePtr;
|
||||
runZone(z);
|
||||
if ((z->_type & 0xFFFF) == kZoneSpeak) {
|
||||
enterDialogueMode(z);
|
||||
} else {
|
||||
runZone(z); // FIXME: BRA doesn't handle sound yet
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,7 +191,7 @@ void Parallaction_ns::setArrowCursor() {
|
||||
debugC(1, kDebugInput, "setting mouse cursor to arrow");
|
||||
|
||||
// this stuff is needed to avoid artifacts with labels and selected items when switching cursors
|
||||
_gfx->hideFloatingLabel();
|
||||
_input->stopHovering();
|
||||
_input->_activeItem._id = 0;
|
||||
|
||||
_system->setMouseCursor(_mouseArrow, MOUSEARROW_WIDTH, MOUSEARROW_HEIGHT, 0, 0, 0);
|
||||
@ -302,12 +302,11 @@ void Parallaction_ns::changeLocation(char *location) {
|
||||
|
||||
_soundMan->playLocationMusic(location);
|
||||
|
||||
_gfx->hideFloatingLabel();
|
||||
_input->stopHovering();
|
||||
_gfx->freeLabels();
|
||||
|
||||
_zoneTrap = nullZonePtr;
|
||||
|
||||
_input->stopHovering();
|
||||
if (_engineFlags & kEngineBlockInput) {
|
||||
setArrowCursor();
|
||||
}
|
||||
@ -420,6 +419,7 @@ void Parallaction_ns::changeCharacter(const char *name) {
|
||||
Common::String oldArchive = _disk->selectArchive((getFeatures() & GF_DEMO) ? "disk0" : "disk1");
|
||||
_char._ani->gfxobj = _gfx->loadAnim(_char.getFullName());
|
||||
_char._ani->gfxobj->setFlags(kGfxObjCharacter);
|
||||
_char._ani->gfxobj->clearFlags(kGfxObjNormal);
|
||||
|
||||
if (!_char.dummy()) {
|
||||
if (getPlatform() == Common::kPlatformAmiga) {
|
||||
|
@ -354,6 +354,7 @@ void Parallaction_ns::walk(Character &character) {
|
||||
if (newPos == curPos) {
|
||||
debugC(1, kDebugWalk, "walk was blocked by an unforeseen obstacle");
|
||||
finalizeWalk(character);
|
||||
targetPos = newPos; // when walking is interrupted, targetPos must be hacked so that a still frame can be selected
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1175,15 +1175,8 @@ BamScene::BamScene(QueenEngine *vm)
|
||||
}
|
||||
|
||||
void BamScene::playSfx() {
|
||||
// Don't try to play all the sounds. This is only necessary for the
|
||||
// fight bam, in which the number of 'sfx bam frames' is too much
|
||||
// important / too much closer. The original game does not have
|
||||
// this problem since its playSfx() function returns immediately
|
||||
// if a sound is already being played.
|
||||
if (_lastSoundIndex == 0 || _index - _lastSoundIndex >= SFX_SKIP) {
|
||||
_vm->sound()->playSfx(_vm->logic()->currentRoomSfx());
|
||||
_lastSoundIndex = _index;
|
||||
}
|
||||
_vm->sound()->playSfx(_vm->logic()->currentRoomSfx());
|
||||
_lastSoundIndex = _index;
|
||||
}
|
||||
|
||||
void BamScene::prepareAnimation() {
|
||||
|
@ -248,10 +248,6 @@ public:
|
||||
F_REQ_STOP = 2
|
||||
};
|
||||
|
||||
enum {
|
||||
SFX_SKIP = 8
|
||||
};
|
||||
|
||||
uint16 _flag, _index;
|
||||
|
||||
private:
|
||||
|
@ -227,11 +227,6 @@ void PCSound::setVolume(int vol) {
|
||||
_music->setVolume(vol);
|
||||
}
|
||||
|
||||
void PCSound::waitFinished(bool isSpeech) {
|
||||
while (_mixer->isSoundHandleActive(isSpeech ? _speechHandle : _sfxHandle))
|
||||
_vm->input()->delay(10);
|
||||
}
|
||||
|
||||
void PCSound::playSound(const char *base, bool isSpeech) {
|
||||
char name[13];
|
||||
strcpy(name, base);
|
||||
@ -241,7 +236,13 @@ void PCSound::playSound(const char *base, bool isSpeech) {
|
||||
name[i] = '0';
|
||||
}
|
||||
strcat(name, ".SB");
|
||||
waitFinished(isSpeech);
|
||||
if (isSpeech) {
|
||||
while (_mixer->isSoundHandleActive(_speechHandle)) {
|
||||
_vm->input()->delay(10);
|
||||
}
|
||||
} else {
|
||||
_mixer->stopHandle(_sfxHandle);
|
||||
}
|
||||
uint32 size;
|
||||
Common::File *f = _vm->resource()->findSound(name, &size);
|
||||
if (f) {
|
||||
@ -253,6 +254,8 @@ void PCSound::playSound(const char *base, bool isSpeech) {
|
||||
}
|
||||
|
||||
void SBSound::playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) {
|
||||
// In order to simplify the code, we don't parse the .sb header but hard-code the
|
||||
// values. Refer to tracker item #1876741 for details on the format/fields.
|
||||
int headerSize;
|
||||
f->seek(2, SEEK_CUR);
|
||||
uint16 version = f->readUint16LE();
|
||||
|
@ -143,7 +143,6 @@ public:
|
||||
void setVolume(int vol);
|
||||
|
||||
protected:
|
||||
void waitFinished(bool isSpeech);
|
||||
void playSound(const char *base, bool isSpeech);
|
||||
|
||||
virtual void playSoundData(Common::File *f, uint32 size, Audio::SoundHandle *soundHandle) = 0;
|
||||
|
@ -949,7 +949,7 @@ SaveStateList ScummMetaEngine::listSaves(const char *target) const {
|
||||
sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)
|
||||
|
||||
SaveStateList saveList;
|
||||
for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); file++) {
|
||||
for (Common::StringList::const_iterator file = filenames.begin(); file != filenames.end(); ++file) {
|
||||
// Obtain the last 2 digits of the filename, since they correspond to the save slot
|
||||
int slotNum = atoi(file->c_str() + file->size() - 2);
|
||||
|
||||
|
@ -297,7 +297,7 @@ void SaveLoadChooser::handleCommand(CommandSender *sender, uint32 cmd, uint32 da
|
||||
break;
|
||||
case GUI::kListSelectionChangedCmd: {
|
||||
if (_gfxWidget) {
|
||||
updateInfos();
|
||||
updateInfos(true);
|
||||
}
|
||||
|
||||
if (_saveMode) {
|
||||
@ -350,7 +350,7 @@ void SaveLoadChooser::reflowLayout() {
|
||||
_fillR = g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillR");
|
||||
_fillG = g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillG");
|
||||
_fillB = g_gui.evaluator()->getVar("scummsaveload_thumbnail.fillB");
|
||||
updateInfos();
|
||||
updateInfos(false);
|
||||
} else {
|
||||
_container->setFlags(GUI::WIDGET_INVISIBLE);
|
||||
_gfxWidget->setFlags(GUI::WIDGET_INVISIBLE);
|
||||
@ -362,7 +362,7 @@ void SaveLoadChooser::reflowLayout() {
|
||||
Dialog::reflowLayout();
|
||||
}
|
||||
|
||||
void SaveLoadChooser::updateInfos() {
|
||||
void SaveLoadChooser::updateInfos(bool redraw) {
|
||||
int selItem = _list->getSelected();
|
||||
Graphics::Surface *thumb;
|
||||
thumb = _vm->loadThumbnailFromSlot(_saveMode ? selItem + 1 : selItem);
|
||||
@ -376,7 +376,8 @@ void SaveLoadChooser::updateInfos() {
|
||||
}
|
||||
|
||||
delete thumb;
|
||||
_gfxWidget->draw();
|
||||
if (redraw)
|
||||
_gfxWidget->draw();
|
||||
|
||||
InfoStuff infos;
|
||||
memset(&infos, 0, sizeof(InfoStuff));
|
||||
@ -386,12 +387,14 @@ void SaveLoadChooser::updateInfos() {
|
||||
(infos.date >> 24) & 0xFF, (infos.date >> 16) & 0xFF,
|
||||
infos.date & 0xFFFF);
|
||||
_date->setLabel(buffer);
|
||||
_date->draw();
|
||||
if (redraw)
|
||||
_date->draw();
|
||||
|
||||
snprintf(buffer, 32, "Time: %.2d:%.2d",
|
||||
(infos.time >> 8) & 0xFF, infos.time & 0xFF);
|
||||
_time->setLabel(buffer);
|
||||
_time->draw();
|
||||
if (redraw)
|
||||
_time->draw();
|
||||
|
||||
int minutes = infos.playtime / 60;
|
||||
int hours = minutes / 60;
|
||||
@ -400,19 +403,23 @@ void SaveLoadChooser::updateInfos() {
|
||||
snprintf(buffer, 32, "Playtime: %.2d:%.2d",
|
||||
hours & 0xFF, minutes & 0xFF);
|
||||
_playtime->setLabel(buffer);
|
||||
_playtime->draw();
|
||||
if (redraw)
|
||||
_playtime->draw();
|
||||
} else {
|
||||
snprintf(buffer, 32, "No date saved");
|
||||
_date->setLabel(buffer);
|
||||
_date->draw();
|
||||
if (redraw)
|
||||
_date->draw();
|
||||
|
||||
snprintf(buffer, 32, "No time saved");
|
||||
_time->setLabel(buffer);
|
||||
_time->draw();
|
||||
if (redraw)
|
||||
_time->draw();
|
||||
|
||||
snprintf(buffer, 32, "No playtime saved");
|
||||
_playtime->setLabel(buffer);
|
||||
_playtime->draw();
|
||||
if (redraw)
|
||||
_playtime->draw();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ protected:
|
||||
|
||||
uint8 _fillR, _fillG, _fillB;
|
||||
|
||||
void updateInfos();
|
||||
void updateInfos(bool redraw);
|
||||
public:
|
||||
SaveLoadChooser(const String &title, const String &buttonLabel, bool saveMode, ScummEngine *engine);
|
||||
~SaveLoadChooser();
|
||||
|
@ -102,10 +102,10 @@ void ImuseDigiSndMgr::prepareSoundFromRMAP(Common::File *file, SoundDesc *sound,
|
||||
int32 version = file->readUint32BE();
|
||||
if (version != 3) {
|
||||
if (version == 2) {
|
||||
warning("ImuseDigiSndMgr::prepareSoundFromRMAP: Wrong version of compressed *.bun file, expected 3, but it's 2.");
|
||||
warning("Suggested to recompress with latest tool from daily builds.");
|
||||
warning("ImuseDigiSndMgr::prepareSoundFromRMAP: Wrong version of compressed *.bun file, expected 3, but it's 2");
|
||||
warning("Suggested to recompress with latest tool from daily builds");
|
||||
} else
|
||||
error("ImuseDigiSndMgr::prepareSoundFromRMAP: Wrong version number, expected 3, but it's: %d.", version);
|
||||
error("ImuseDigiSndMgr::prepareSoundFromRMAP: Wrong version number, expected 3, but it's: %d", version);
|
||||
}
|
||||
sound->bits = file->readUint32BE();
|
||||
sound->freq = file->readUint32BE();
|
||||
|
@ -52,9 +52,11 @@ namespace Sword2 {
|
||||
static Audio::AudioStream *makeCLUStream(Common::File *fp, int size);
|
||||
|
||||
static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base, int cd, uint32 id, uint32 *numSamples) {
|
||||
debug(3, "Playing %s from CD %d", base, cd);
|
||||
bool alreadyOpen;
|
||||
|
||||
if (!fh->file.isOpen()) {
|
||||
alreadyOpen = false;
|
||||
|
||||
struct {
|
||||
const char *ext;
|
||||
int mode;
|
||||
@ -75,16 +77,14 @@ static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base,
|
||||
char filename[20];
|
||||
|
||||
for (int i = 0; i < ARRAYSIZE(file_types); i++) {
|
||||
Common::File f;
|
||||
|
||||
sprintf(filename, "%s%d.%s", base, cd, file_types[i].ext);
|
||||
if (f.open(filename)) {
|
||||
if (Common::File::exists(filename)) {
|
||||
soundMode = file_types[i].mode;
|
||||
break;
|
||||
}
|
||||
|
||||
sprintf(filename, "%s.%s", base, file_types[i].ext);
|
||||
if (f.open(filename)) {
|
||||
if (Common::File::exists(filename)) {
|
||||
soundMode = file_types[i].mode;
|
||||
break;
|
||||
}
|
||||
@ -105,7 +105,8 @@ static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base,
|
||||
fh->idxTab = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
alreadyOpen = true;
|
||||
|
||||
uint32 entrySize = (fh->fileType == kCLUMode) ? 2 : 3;
|
||||
|
||||
@ -134,7 +135,13 @@ static Audio::AudioStream *getAudioStream(SoundFileHandle *fh, const char *base,
|
||||
*numSamples = len;
|
||||
|
||||
if (!pos || !len) {
|
||||
fh->file.close();
|
||||
// We couldn't find the sound. Possibly as a result of a bad
|
||||
// installation (e.g. using the music file from CD 2 as the
|
||||
// first music file). Don't close the file if it was already
|
||||
// open though, because something is playing from it.
|
||||
warning("getAudioStream: Could not find %s ID %d! Possibly the wrong file", base, id);
|
||||
if (!alreadyOpen)
|
||||
fh->file.close();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ private:
|
||||
void refill();
|
||||
|
||||
inline bool eosIntern() const {
|
||||
return _pos >= _bufferEnd;
|
||||
return !_file->isOpen() || _pos >= _bufferEnd;
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -5,16 +5,25 @@
|
||||
class StringTestSuite : public CxxTest::TestSuite
|
||||
{
|
||||
public:
|
||||
void test_empty_clear( void )
|
||||
{
|
||||
void test_constructors(void) {
|
||||
Common::String str("test-string");
|
||||
TS_ASSERT( str == "test-string" );
|
||||
str = Common::String(str.c_str()+5, 3);
|
||||
TS_ASSERT( str == "str" );
|
||||
str = "test-string";
|
||||
TS_ASSERT( str == "test-string" );
|
||||
str = Common::String(str.c_str()+5, str.c_str()+8);
|
||||
TS_ASSERT( str == "str" );
|
||||
}
|
||||
|
||||
void test_empty_clear(void) {
|
||||
Common::String str("test");
|
||||
TS_ASSERT( !str.empty() );
|
||||
str.clear();
|
||||
TS_ASSERT( str.empty() );
|
||||
}
|
||||
|
||||
void test_lastChar( void )
|
||||
{
|
||||
void test_lastChar(void) {
|
||||
Common::String str;
|
||||
TS_ASSERT_EQUALS( str.lastChar(), '\0' );
|
||||
str = "test";
|
||||
@ -23,8 +32,7 @@ class StringTestSuite : public CxxTest::TestSuite
|
||||
TS_ASSERT_EQUALS( str2.lastChar(), 'r' );
|
||||
}
|
||||
|
||||
void test_concat1( void )
|
||||
{
|
||||
void test_concat1(void) {
|
||||
Common::String str("foo");
|
||||
Common::String str2("bar");
|
||||
str += str2;
|
||||
@ -32,22 +40,19 @@ class StringTestSuite : public CxxTest::TestSuite
|
||||
TS_ASSERT_EQUALS( str2, "bar" );
|
||||
}
|
||||
|
||||
void test_concat2( void )
|
||||
{
|
||||
void test_concat2(void) {
|
||||
Common::String str("foo");
|
||||
str += "bar";
|
||||
TS_ASSERT_EQUALS( str, "foobar" );
|
||||
}
|
||||
|
||||
void test_concat3( void )
|
||||
{
|
||||
void test_concat3(void) {
|
||||
Common::String str("foo");
|
||||
str += 'X';
|
||||
TS_ASSERT_EQUALS( str, "fooX" );
|
||||
}
|
||||
|
||||
void test_refCount( void )
|
||||
{
|
||||
void test_refCount(void) {
|
||||
Common::String foo1("foo");
|
||||
Common::String foo2("foo");
|
||||
Common::String foo3(foo2);
|
||||
@ -57,8 +62,7 @@ class StringTestSuite : public CxxTest::TestSuite
|
||||
TS_ASSERT_EQUALS( foo3, "foo""X" );
|
||||
}
|
||||
|
||||
void test_refCount2( void )
|
||||
{
|
||||
void test_refCount2(void) {
|
||||
Common::String foo1("fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd");
|
||||
Common::String foo2("fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd");
|
||||
Common::String foo3(foo2);
|
||||
@ -68,8 +72,7 @@ class StringTestSuite : public CxxTest::TestSuite
|
||||
TS_ASSERT_EQUALS( foo3, "fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd""X" );
|
||||
}
|
||||
|
||||
void test_refCount3( void )
|
||||
{
|
||||
void test_refCount3(void) {
|
||||
Common::String foo1("0123456789abcdefghijk");
|
||||
Common::String foo2("0123456789abcdefghijk");
|
||||
Common::String foo3(foo2);
|
||||
@ -79,8 +82,7 @@ class StringTestSuite : public CxxTest::TestSuite
|
||||
TS_ASSERT_EQUALS( foo3, "0123456789abcdefghijk""0123456789abcdefghijk" );
|
||||
}
|
||||
|
||||
void test_refCount4( void )
|
||||
{
|
||||
void test_refCount4(void) {
|
||||
Common::String foo1("fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd");
|
||||
Common::String foo2("fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd");
|
||||
Common::String foo3(foo2);
|
||||
@ -90,8 +92,7 @@ class StringTestSuite : public CxxTest::TestSuite
|
||||
TS_ASSERT_EQUALS( foo3, "fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd""fooasdkadklasdjklasdjlkasjdlkasjdklasjdlkjasdasd" );
|
||||
}
|
||||
|
||||
void test_hasPrefix( void )
|
||||
{
|
||||
void test_hasPrefix(void) {
|
||||
Common::String str("this/is/a/test, haha");
|
||||
TS_ASSERT_EQUALS( str.hasPrefix(""), true );
|
||||
TS_ASSERT_EQUALS( str.hasPrefix("this"), true );
|
||||
@ -99,8 +100,7 @@ class StringTestSuite : public CxxTest::TestSuite
|
||||
TS_ASSERT_EQUALS( str.hasPrefix("foo"), false );
|
||||
}
|
||||
|
||||
void test_hasSuffix( void )
|
||||
{
|
||||
void test_hasSuffix(void) {
|
||||
Common::String str("this/is/a/test, haha");
|
||||
TS_ASSERT_EQUALS( str.hasSuffix(""), true );
|
||||
TS_ASSERT_EQUALS( str.hasSuffix("haha"), true );
|
||||
@ -108,8 +108,7 @@ class StringTestSuite : public CxxTest::TestSuite
|
||||
TS_ASSERT_EQUALS( str.hasSuffix("hahah"), false );
|
||||
}
|
||||
|
||||
void test_contains( void )
|
||||
{
|
||||
void test_contains(void) {
|
||||
Common::String str("this/is/a/test, haha");
|
||||
TS_ASSERT_EQUALS( str.contains(""), true );
|
||||
TS_ASSERT_EQUALS( str.contains("haha"), true );
|
||||
@ -117,15 +116,13 @@ class StringTestSuite : public CxxTest::TestSuite
|
||||
TS_ASSERT_EQUALS( str.contains("test"), true );
|
||||
}
|
||||
|
||||
void test_toLowercase( void )
|
||||
{
|
||||
void test_toLowercase(void) {
|
||||
Common::String str("Test it, NOW! 42");
|
||||
str.toLowercase();
|
||||
TS_ASSERT_EQUALS( str, "test it, now! 42" );
|
||||
}
|
||||
|
||||
void test_toUppercase( void )
|
||||
{
|
||||
void test_toUppercase(void) {
|
||||
Common::String str("Test it, NOW! 42");
|
||||
str.toUppercase();
|
||||
TS_ASSERT_EQUALS( str, "TEST IT, NOW! 42" );
|
||||
|
Loading…
Reference in New Issue
Block a user