diff options
author | David Corrales | 2007-07-08 16:58:54 +0000 |
---|---|---|
committer | David Corrales | 2007-07-08 16:58:54 +0000 |
commit | 9bfe5d53540af7dc9bf0214202f4e35b272320ea (patch) | |
tree | 69dcaf6f735e9fd0913a3e2f163852d4b9af87e3 | |
parent | 256e4d9521b79160d1f9ed670656097a96dc5a34 (diff) | |
parent | 17da12ca07a1f18f3fe1ef5b0c2c0cd9fd8359b4 (diff) | |
download | scummvm-rg350-9bfe5d53540af7dc9bf0214202f4e35b272320ea.tar.gz scummvm-rg350-9bfe5d53540af7dc9bf0214202f4e35b272320ea.tar.bz2 scummvm-rg350-9bfe5d53540af7dc9bf0214202f4e35b272320ea.zip |
Merged the FSNode branch with trunk r27681:27969
svn-id: r27970
243 files changed, 4785 insertions, 2265 deletions
@@ -138,6 +138,8 @@ ScummVM Team Miscellaneous: Jerome Fisher - MT-32 emulator Jochen Hoenicke - Speaker & PCjr sound support, Adlib work + Robin Watts - ARM assembly routines for nice speedups on + several ports; improvements to the sound mixer Website (content) ----------------- @@ -246,7 +248,6 @@ Other contributions Daniel Schepler - Final MI1 CD music support, initial Ogg Vorbis support Andre Souza - SDL-based OpenGL renderer - Robin Watts - ARM assembly routines for the Windows CE port And to all the contributors, users, and beta testers we've missed. Thanks! @@ -13,7 +13,7 @@ Jurgen Braam Ralph Brorsen James Brown Stuart Caie -Filippos Carapetis +Filippos Karapetis Jamieson Christian Marcus Comstedt Paolo Costabel @@ -83,7 +83,7 @@ Andreas Bierfert "awjb" Elio Blanca "eblanca76" David Breakey "dbreakey" Robert Buchholz "prendi" -Filippos Carapetis "thebluegr" +Filippos Karapetis "thebluegr" Mathieu Carot "yokna" Stefano Ceccherini "jackburton" Travis S Coady "theealien" @@ -108,6 +108,7 @@ Matti Hamalainen "ccrtnsp" Matt Hargett "matt_hargett" Stefan Haubenthal "polluks" Alexander Holler "holler" +Matthew Hoops "clone2727" Falk Hueffner "mellum" Casey Hutchinson "nnooiissee" Gregor Jasny "gjasny" @@ -2,9 +2,27 @@ For a more comprehensive changelog for the latest experimental SVN code, see: http://scummvm.sourceforge.net/daily/ChangeLog 0.11.0 (????-??-??) + General: + - Added ARM assembly routines for code in the sound mixer and SCUMM + video playback, resulting in some nice speedups on several ports. + - Improved the way keyboard input is handled internally, resolving + some odd quirks in some game / port combinations. + - Added optional 'confirm exit' dialog to the SDL backend. + + AGOS: + - Fixed crashes related to OmniTV playback in The Feeble Files. + Broken Sword 1: - Added support for FLAC encoded music. + SCUMM: + - Added subtitle skipping (via '.' key) in older games which didn't have + this feature so far (e.g. Zak, MM, Indy3, Loom). + + SAGA: + - Added support for compressed sound effects, voices and music + + 0.10.0 (2007-06-20) New Games: - Added Cinematique evo 1 engine. Currently only Future Wars is supported. @@ -1422,6 +1422,9 @@ files. Running "compress_sword1 --vorbis" will compress the files using Ogg Vorbis instead of MP3. +Running "compress_sword1 --flac" will compress the files using Flac +instead of MP3. + Use "compress_sword1 --help" to get a full list of the options. @@ -1572,6 +1575,8 @@ The following keywords are recognized: super2xsai, supereagle, advmame2x, advmame3x, hq2x, hq3x, tv2x, dotmatrix) + confirm_exit bool Ask for confirmation by the user before quitting + (SDL backend only). cdrom number Number of CD-ROM unit to use for audio. If negative, don't even try to access the CD-ROM. joystick_num number Number of joystick device to use for input @@ -1597,8 +1602,8 @@ The following keywords are recognized: midi_gain number The MIDI gain (0-1000) (default: 100) (Only supported by some MIDI drivers.) - copy_protection bool Enable copy protection in SCUMM games, when - ScummVM disables it by default. + copy_protection bool Enable copy protection in certain games, in those + cases where ScummVM disables it by default. demo_mode bool Start demo in Maniac Mansion alt_intro bool Use alternative intro for CD versions of Beneath a Steel Sky and Flight of the Amazon diff --git a/backends/events/default/default-events.cpp b/backends/events/default/default-events.cpp index ad21b09070..6bd97c7f71 100644 --- a/backends/events/default/default-events.cpp +++ b/backends/events/default/default-events.cpp @@ -26,9 +26,13 @@ #if !defined(DISABLE_DEFAULT_EVENTMANAGER) #include "common/stdafx.h" +#include "common/config-manager.h" #include "common/system.h" #include "backends/events/default/default-events.h" +#include "engines/engine.h" +#include "gui/message.h" + DefaultEventManager::DefaultEventManager(OSystem *boss) : _boss(boss), _buttonState(0), @@ -93,7 +97,15 @@ bool DefaultEventManager::pollEvent(Common::Event &event) { break; case Common::EVENT_QUIT: - _shouldQuit = true; + if (ConfMan.getBool("confirm_exit")) { + if (g_engine) + g_engine->pauseEngine(true); + GUI::MessageDialog alert("Do you really want to quit?", "Yes", "No"); + result = _shouldQuit = (alert.runModal() == GUI::kMessageOK); + if (g_engine) + g_engine->pauseEngine(false); + } else + _shouldQuit = true; break; default: diff --git a/backends/platform/PalmOS/Src/be_base.h b/backends/platform/PalmOS/Src/be_base.h index a5891b99c8..7881275358 100644 --- a/backends/platform/PalmOS/Src/be_base.h +++ b/backends/platform/PalmOS/Src/be_base.h @@ -196,10 +196,6 @@ public: virtual int16 getOverlayHeight(); virtual int16 getOverlayWidth(); - virtual int screenToOverlayX(int x); - virtual int screenToOverlayY(int y); - virtual int overlayToScreenX(int x); - virtual int overlayToScreenY(int y); virtual OverlayColor ARGBToColor(uint8 a, uint8 r, uint8 g, uint8 b); virtual void colorToARGB(OverlayColor color, uint8 &a, uint8 &r, uint8 &g, uint8 &b); diff --git a/backends/platform/PalmOS/Src/launcher/launch.cpp b/backends/platform/PalmOS/Src/launcher/launch.cpp index 7bc07c4fdf..9613abf1cc 100644 --- a/backends/platform/PalmOS/Src/launcher/launch.cpp +++ b/backends/platform/PalmOS/Src/launcher/launch.cpp @@ -424,7 +424,7 @@ Boolean StartScummVM(Int16 engine) { toLauncher= (gPrefs->exitLauncher); // gVars values - // (gVars->HRrefNum defined in checkHRmode on Clié) + // (gVars->HRrefNum defined in checkHRmode on Clie) #ifndef _DEBUG_ENGINE gVars->VFS.volRefNum = (gPrefs->card.autoDetect ? vfsInvalidVolRef : gPrefs->card.volRefNum); #else diff --git a/backends/platform/dc/dc.h b/backends/platform/dc/dc.h index fa47ed21f5..aa2f7b2f92 100644 --- a/backends/platform/dc/dc.h +++ b/backends/platform/dc/dc.h @@ -144,10 +144,6 @@ class OSystem_Dreamcast : public OSystem { // Overlay int16 getOverlayHeight(); int16 getOverlayWidth(); - int screenToOverlayX(int x); - int screenToOverlayY(int y); - int overlayToScreenX(int x); - int overlayToScreenY(int y); void showOverlay(); void hideOverlay(); void clearOverlay(); diff --git a/backends/platform/dc/display.cpp b/backends/platform/dc/display.cpp index da9f6e83ff..1790785b67 100644 --- a/backends/platform/dc/display.cpp +++ b/backends/platform/dc/display.cpp @@ -585,7 +585,7 @@ void OSystem_Dreamcast::copyRectToOverlay(const int16 *buf, int pitch, static const OSystem::GraphicsMode gfxmodes[] = { - { "default", "640×480 16bpp", 0 }, + { "default", "640x480 16bpp", 0 }, { NULL, NULL, 0 } }; @@ -645,23 +645,3 @@ int16 OSystem_Dreamcast::getOverlayWidth() return OVL_W; } -int OSystem_Dreamcast::screenToOverlayX(int x) -{ - return x - _overlay_x; -} - -int OSystem_Dreamcast::screenToOverlayY(int y) -{ - return y - _overlay_y; -} - -int OSystem_Dreamcast::overlayToScreenX(int x) -{ - return x + _overlay_x; -} - -int OSystem_Dreamcast::overlayToScreenY(int y) -{ - return y + _overlay_y; -} - diff --git a/backends/platform/dc/input.cpp b/backends/platform/dc/input.cpp index f3638a28db..aa0d9efa21 100644 --- a/backends/platform/dc/input.cpp +++ b/backends/platform/dc/input.cpp @@ -48,7 +48,7 @@ int handleInput(struct mapledev *pad, int &mouse_x, int &mouse_y, if(!(buttons & 4)) lmb++; if(!(buttons & 2)) rmb++; - if(!(buttons & 8)) newkey = Common::ASCII_F5; + if(!(buttons & 8)) newkey = Common::KEYCODE_F5; else if(!(buttons & 512)) newkey = ' '; else if(!(buttons & 1024)) newkey = numpadmap[(buttons>>4)&15]; @@ -69,7 +69,7 @@ int handleInput(struct mapledev *pad, int &mouse_x, int &mouse_y, if(!(buttons & 4)) lmb++; if(!(buttons & 2)) rmb++; - if(!(buttons & 8)) newkey = Common::ASCII_F5; + if(!(buttons & 8)) newkey = Common::KEYCODE_F5; mouse_x += pad->cond.mouse.axis1; mouse_y += pad->cond.mouse.axis2; @@ -98,10 +98,10 @@ int handleInput(struct mapledev *pad, int &mouse_x, int &mouse_y, newkey = key+('1'-0x59); else if(key >= 0x2d && key <= 0x38 && key != 0x31) newkey = ((shift & 0x22)? - "=¯`{ }+*½<>?" : - "-^@[ ];:§,./")[key - 0x2d]; + "=?`{ }+*?<>?" : + "-^@[ ];:?,./")[key - 0x2d]; else if(key >= 0x3a && key <= 0x43) - newkey = key+(Common::ASCII_F1-0x3a); + newkey = key+(Common::KEYCODE_F1-0x3a); else if(key >= 0x54 && key <= 0x57) newkey = "/*-+"[key-0x54]; else switch(key) { @@ -134,7 +134,7 @@ int handleInput(struct mapledev *pad, int &mouse_x, int &mouse_y, case 0x64: case 0x87: newkey = ((shift & 0x22)? '_' : '\\'); break; case 0x89: - newkey = ((shift & 0x22)? '|' : '¥'); break; + newkey = ((shift & 0x22)? '|' : '?'); break; } } } diff --git a/backends/platform/dc/selector.cpp b/backends/platform/dc/selector.cpp index 8262a39614..b082afabf5 100644 --- a/backends/platform/dc/selector.cpp +++ b/backends/platform/dc/selector.cpp @@ -364,7 +364,7 @@ int gameMenu(Game *games, int num_games) event = handleInput(locked_get_pads(), mousex, mousey, shiftFlags); setimask(mask); - if(event==-Common::EVENT_LBUTTONDOWN || event==13 || event==Common::ASCII_F5) { + if(event==-Common::EVENT_LBUTTONDOWN || event==Common::KEYCODE_ENTER || event==Common::KEYCODE_F5) { int selected_game = top_game + selector_pos; for(int fade=0; fade<=256; fade+=4) { diff --git a/backends/platform/dc/softkbd.cpp b/backends/platform/dc/softkbd.cpp index 58b492f6db..79363713a5 100644 --- a/backends/platform/dc/softkbd.cpp +++ b/backends/platform/dc/softkbd.cpp @@ -52,7 +52,7 @@ static const char key_names[] = static const short key_codes[] = { - Common::KEYCODE_ESCAPE, Common::ASCII_F1, Common::ASCII_F2, Common::ASCII_F3, Common::ASCII_F4, Common::ASCII_F5, Common::ASCII_F6, Common::ASCII_F7, Common::ASCII_F8, Common::ASCII_F9, Common::ASCII_F10, + Common::KEYCODE_ESCAPE, Common::KEYCODE_F1, Common::KEYCODE_F2, Common::KEYCODE_F3, Common::KEYCODE_F4, Common::KEYCODE_F5, Common::KEYCODE_F6, Common::KEYCODE_F7, Common::KEYCODE_F8, Common::KEYCODE_F9, Common::KEYCODE_F10, K('1','!'), K('2','"'), K('3','#'), K('4','$'), K('5','%'), K('6','&'), K('7','\''), K('8','('), K('9',')'), K('0','~'), K('-','='), K('q','Q'), K('w','W'), K('e','E'), K('r','R'), K('t','T'), diff --git a/backends/platform/ds/arm9/data/icons.raw b/backends/platform/ds/arm9/data/icons.raw Binary files differindex c2915b2914..c8fbfd6e9a 100644 --- a/backends/platform/ds/arm9/data/icons.raw +++ b/backends/platform/ds/arm9/data/icons.raw diff --git a/backends/platform/ds/arm9/makefile b/backends/platform/ds/arm9/makefile index cb41774064..c9ca5467f3 100644 --- a/backends/platform/ds/arm9/makefile +++ b/backends/platform/ds/arm9/makefile @@ -4,18 +4,32 @@ libndsdir = /home/neil/devkitpro/libnds # Select the build you want by uncommenting one of the following lines: -DS_BUILD_A = 1 + +#DS_BUILD_A = 1 #DS_BUILD_B = 1 #DS_BUILD_C = 1 -#DS_BUILD_D = 1 +DS_BUILD_D = 1 +#DS_BUILD_E = 1 +#DS_BUILD_F = 1 # Uncomment the following line to build in support for MP3 audio # using libmad: -USE_MAD = 1 + +ifdef DS_BUILD_F + # TODO: Fix this. When libmad is compiled in, the Kyrandia resource loading + # searches through it's entire index to find an mp3 each time a voice sample is requested + # this causes a nasty pause. +else + USE_MAD = 1 +endif # Uncomment the following line to enable support for the # ace DS Debugger (remembering to make the same change in the arm7 makefile): #USE_DEBUGGER = 1 + +# Uncomment the following line to enable the profiler +#USE_PROFILER = 1 + # NOTE: The header and libs for the debugger is assumed to be in the libnds # folder. @@ -24,6 +38,7 @@ VPATH = $(srcdir) # Command to build libmad is: # ./configure --host=arm-elf --enable-speed --enable-sso -enable-fpm=arm CFLAGS='-specs=ds_arm9.specs -mthumb-interwork' +ARM = 1 ifdef DS_BUILD_A DEFINES = -DDS_SCUMM_BUILD -DDS_BUILD_A @@ -44,6 +59,7 @@ ifdef DS_BUILD_A DISABLE_AGI = 1 DISABLE_TOUCHE = 1 DISABLE_PARALLACTION = 1 + DISABLE_CRUISE = 1 BUILD=scummvm-A endif @@ -66,6 +82,7 @@ ifdef DS_BUILD_B DISABLE_AGI = 1 DISABLE_TOUCHE = 1 DISABLE_PARALLACTION = 1 + DISABLE_CRUISE = 1 BUILD=scummvm-B endif @@ -81,13 +98,14 @@ ifdef DS_BUILD_C DISABLE_SWORD2 = 1 DISABLE_QUEEN = 1 DISABLE_SAGA = 1 - #DISABLE_KYRA = 1 - #DISABLE_GOB = 1 + DISABLE_KYRA = 1 + DISABLE_GOB = 1 DISABLE_LURE = 1 DISABLE_CINE = 1 DISABLE_AGI = 1 DISABLE_TOUCHE = 1 DISABLE_PARALLACTION = 1 + DISABLE_CRUISE = 1 BUILD=scummvm-C endif @@ -104,15 +122,62 @@ ifdef DS_BUILD_D DISABLE_QUEEN = 1 DISABLE_SAGA = 1 DISABLE_KYRA = 1 - DISABLE_GOB = 1 + #DISABLE_GOB = 1 DISABLE_LURE = 1 #DISABLE_CINE = 1 #DISABLE_AGI = 1 DISABLE_TOUCHE = 1 DISABLE_PARALLACTION = 1 - BUILD=scummvm-A + DISABLE_CRUISE = 1 + BUILD=scummvm-D endif +ifdef DS_BUILD_E + DEFINES = -DDS_NON_SCUMM_BUILD -DDS_BUILD_E + LOGO = logoc.bmp + DISABLE_HE = 1 + DISABLE_SCUMM = 1 + DISABLE_SCUMM_7_8 = 1 + DISABLE_AGOS = 1 + DISABLE_SKY = 1 + DISABLE_SWORD1 = 1 + DISABLE_SWORD2 = 1 + DISABLE_QUEEN = 1 + #DISABLE_SAGA = 1 + DISABLE_KYRA = 1 + DISABLE_GOB = 1 + DISABLE_LURE = 1 + DISABLE_CINE = 1 + DISABLE_AGI = 1 + DISABLE_TOUCHE = 1 + DISABLE_PARALLACTION = 1 + DISABLE_CRUISE = 1 + BUILD=scummvm-E +endif + +ifdef DS_BUILD_F + DEFINES = -DDS_NON_SCUMM_BUILD -DDS_BUILD_F + LOGO = logoc.bmp + DISABLE_HE = 1 + DISABLE_SCUMM = 1 + DISABLE_SCUMM_7_8 = 1 + DISABLE_AGOS = 1 + DISABLE_SKY = 1 + DISABLE_SWORD1 = 1 + DISABLE_SWORD2 = 1 + DISABLE_QUEEN = 1 + DISABLE_SAGA = 1 + #DISABLE_KYRA = 1 + DISABLE_GOB = 1 + DISABLE_LURE = 1 + DISABLE_CINE = 1 + DISABLE_AGI = 1 + DISABLE_TOUCHE = 1 + DISABLE_PARALLACTION = 1 + DISABLE_CRUISE = 1 + BUILD=scummvm-F + +endif ARM7BIN := -7 $(CURDIR)/../../arm7/arm7.bin ICON := -b ../../../logo.bmp "ScummVM;By Neil Millstone;" @@ -120,7 +185,7 @@ ICON := -b ../../../logo.bmp "ScummVM;By Neil Millstone;" CC = arm-eabi-gcc CXX = arm-eabi-g++ -CFLAGS = -Wno-multichar -Wall -Os\ +CFLAGS = -Wno-multichar -Wall\ -Wno-multichar -mcpu=arm9tdmi -mtune=arm9tdmi \ -mcpu=arm9tdmi -mtune=arm9tdmi -fomit-frame-pointer\ -ffast-math -mthumb-interwork @@ -129,12 +194,17 @@ ifdef USE_DEBUGGER DEFINES += -DUSE_DEBUGGER CFLAGS += -g endif + +ifdef USE_PROFILER + CFLAGS += -mpoke-function-name -finstrument-functions -g + DEFINES += -DUSE_PROFILER +endif CXXFLAGS= $(CFLAGS) -Wno-non-virtual-dtor -Wno-non-virtual-dtor \ -fno-exceptions -fno-rtti ASFLAGS = -mcpu=arm9tdmi -mthumb-interwork -DEFINES += -D__DS__ -DNDS -DARM9 -DNONSTANDARD_PORT -DDISABLE_FANCY_THEMES -DDISABLE_DEFAULT_SAVEFILEMANAGER +DEFINES += -D__DS__ -DNDS -DARM9 -DNONSTANDARD_PORT -DDISABLE_FANCY_THEMES -DDISABLE_DEFAULT_SAVEFILEMANAGER -DARM ifdef USE_MAD DEFINES += -DUSE_MAD endif @@ -182,9 +252,14 @@ PORT_OBJS := $(portdir)/source/blitters.o $(portdir)/source/cdaudio.o $(portdir) $(portdir)/../../../fs/ds/ds-fs.o $(portdir)/source/gbampsave.o $(portdir)/source/scummhelp.o\ $(portdir)/source/osystem_ds.o $(portdir)/source/portdefs.o $(portdir)/source/ramsave.o\ $(portdir)/source/scummconsole.o $(portdir)/source/touchkeyboard.o $(portdir)/source/zipreader.o\ - $(portdir)/source/dsoptions.o $(portdir)/source/keys.o + $(portdir)/source/dsoptions.o $(portdir)/source/keys.o $(portdir)/source/wordcompletion.o -DATA_OBJS := $(portdir)/data/icons.o $(portdir)/data/keyboard.o $(portdir)/data/keyboard_pal.o $(portdir)/data/default_font.o +ifdef USE_PROFILER + PORT_OBJS += $(portdir)/source/profiler/cyg-profile.o +endif + + +DATA_OBJS := $(portdir)/data/icons.o $(portdir)/data/keyboard.o $(portdir)/data/keyboard_pal.o $(portdir)/data/default_font.o $(portdir)/data/8x8font_tga.o COMPRESSOR_OBJS := $(portdir)/source/compressor/lz.o @@ -209,7 +284,9 @@ FAT_OBJS := $(portdir)/source/fat/disc_io.o $(portdir)/source/fat/gba_nds_fat.o LIBCARTRESET_OBJS := $(portdir)/source/libcartreset/cartreset.o - +# Files in this list will be compiled with -O2, otherwise they will be compiled with -Os +OPTLIST := actor.cpp ds_main.cpp osystem_ds.cpp blitters.cpp fmopl.cpp rate.cpp mixer.cpp +#OPTLIST := OBJS := $(DATA_OBJS) $(LIBCARTRESET_OBJS) $(PORT_OBJS) $(COMPRESSOR_OBJS) $(FAT_OBJS) @@ -269,6 +346,7 @@ endef # rm $(*).tmp #endef + ############## # Replacement rule for the one in makefile.common ############## @@ -276,6 +354,7 @@ ifndef HAVE_GCC3 # If you use GCC, disable the above and enable this for intelligent # dependency tracking. .cpp.o: + $(MKDIR) $(*D)/$(DEPDIR) $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d2" $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o # $(ECHO) "$(*D)/" > $(*D)/$(DEPDIR)/$(*F).d @@ -287,9 +366,19 @@ else # Also, with this GCC inserts additional dummy rules for the involved headers, # which ensures a smooth compilation even if said headers become obsolete. .cpp.o: +# echo !!!!!!!!!!!! $(notdir $<) +# ifeq ( $(notdir $<), $(findstring $(notdir $<), $(OPTLIST)) ) +# OPTFLAG=-O3 +# else +# OPTFLAG=-Os +# endif + +# export OPTFLAG = ; +# echo !!!!!!!! $(OPTFLAG) + $(MKDIR) $(*D)/$(DEPDIR) -# $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o - $(CXX) -MMD -MF "$(*D)/$(DEPDIR)/$(*F).d" $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o + $(CXX) -Wp,-MMD,"$(*D)/$(DEPDIR)/$(*F).d",-MQ,"$@",-MP $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o + $(CXX) -MMD -MF "$(*D)/$(DEPDIR)/$(*F).d" $(CXXFLAGS) $(CPPFLAGS) -c $(<) -o $*.o $(if $(findstring $(notdir $<), $(OPTLIST)), -O2, -Os) endif @@ -333,8 +422,8 @@ endif #--------------------------------------------------------------------------------- %.nds: %.bin - @echo ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../../$(LOGO) "$(shell basename $@);ScummVM 0.11.0svn;DS Port" - ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../../$(LOGO) "$(shell basename $@);ScummVM 0.11.0svn;DS Port" + @echo ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../../$(LOGO) "$(shell basename $@);ScummVM 0.10.0;DS Port" + ndstool -c $@ -9 scummvm.bin $(ARM7BIN) -b ../../$(LOGO) "$(shell basename $@);ScummVM 0.10.0;DS Port" dsbuild $@ -l ../ndsloader.bin padbin 16 $(basename $@).ds.gba diff --git a/backends/platform/ds/arm9/source/blitters.cpp b/backends/platform/ds/arm9/source/blitters.cpp index 9af3c5d611..ec33a5aab4 100644 --- a/backends/platform/ds/arm9/source/blitters.cpp +++ b/backends/platform/ds/arm9/source/blitters.cpp @@ -1,8 +1,6 @@ -/* 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. +/* ScummVM - Scumm Interpreter + * Copyright (C) 2005-2006 Neil Millstone + * Copyright (C) 2006 The ScummVM project * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/backends/platform/ds/arm9/source/blitters.h b/backends/platform/ds/arm9/source/blitters.h index 9fb50cdf0d..fe6966fdae 100644 --- a/backends/platform/ds/arm9/source/blitters.h +++ b/backends/platform/ds/arm9/source/blitters.h @@ -23,6 +23,10 @@ #ifndef _BLITTERS_H_ #define _BLITTERS_H_ +#define USING_ARM_BLITTERS + +#ifndef USING_ARM_BLITTERS + namespace DS { void asmDrawStripToScreen(int height, int width, byte const* text, byte const* src, byte* dst, @@ -33,4 +37,18 @@ void Rescale_320x256x1555_To_256x256x1555(u16* dest, const u16* src, int destStr } +#else + +extern "C" { + +void asmDrawStripToScreen(int height, int width, byte const* text, byte const* src, byte* dst, + int vsPitch, int vmScreenWidth, int textSurfacePitch); +void asmCopy8Col(byte* dst, int dstPitch, const byte* src, int height); +void Rescale_320x256xPAL8_To_256x256x1555(u16* dest, const u8* src, const u16* palette, int destStride, int srcStride); +void Rescale_320x256x1555_To_256x256x1555(u16* dest, const u16* src, int destStride, int srcStride); + +} + +#endif + #endif diff --git a/backends/platform/ds/arm9/source/blitters.s b/backends/platform/ds/arm9/source/blitters.s new file mode 100644 index 0000000000..2f14c5a140 --- /dev/null +++ b/backends/platform/ds/arm9/source/blitters.s @@ -0,0 +1,339 @@ +@ ScummVM Scumm Interpreter +@ Copyright (C) 2007 The ScummVM project +@ +@ This program is free software@ you can redistribute it and/or +@ modify it under the terms of the GNU General Public License +@ as published by the Free Software Foundation@ either version 2 +@ of the License, or (at your option) any later version. +@ +@ This program is distributed in the hope that it will be useful, +@ but WITHOUT ANY WARRANTY; without even the implied warranty of +@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +@ GNU General Public License for more details. +@ +@ You should have received a copy of the GNU General Public License +@ along with this program@ if not, write to the Free Software +@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +@ +@ $URL: $ +@ $Id: $ +@ +@ @author Robin Watts (robin@wss.co.uk) + + .text + + .global asmDrawStripToScreen + .global asmCopy8Col + .global Rescale_320x256xPAL8_To_256x256x1555 + .global Rescale_320x256x1555_To_256x256x1555 + + @ ARM implementation of asmDrawStripToScreen. + @ + @ C prototype would be: + @ + @ extern "C" void asmDrawStripToScreen(int height, + @ int width, + @ byte const *text, + @ byte const *src, + @ byte *dst, + @ int vsPitch, + @ int vsScreenWidth, + @ int textSurfacePitch); + @ + @ In addition, we assume that text, src and dst are all word (4 byte) + @ aligned. This is the same assumption that the old 'inline' version + @ made. +asmDrawStripToScreen: + @ r0 = height + @ r1 = width + @ r2 = text + @ r3 = src + MOV r12,r13 + STMFD r13!,{r4-r7,r9-r11,R14} + LDMIA r12,{r4,r5,r6,r7} + @ r4 = dst + @ r5 = vsPitch + @ r6 = vmScreenWidth + @ r7 = textSurfacePitch + + CMP r0,#0 @ If height<=0 + MOVLE r0,#1 @ height=1 + CMP r1,#4 @ If width<4 + BLT end @ return + + @ Width &= ~4 ? What's that about then? Width &= ~3 I could have + @ understood... + BIC r1,r1,#4 + + SUB r5,r5,r1 @ vsPitch -= width + SUB r6,r6,r1 @ vmScreenWidth -= width + SUB r7,r7,r1 @ textSurfacePitch -= width + MOV r10,#253 + ORR r10,r10,r10,LSL #8 + ORR r10,r10,r10,LSL #16 @ r10 = mask +yLoop: + MOV r14,r1 @ r14 = width +xLoop: + LDR r12,[r2],#4 @ r12 = [text] + LDR r11,[r3],#4 @ r11 = [src] + CMP r12,r10 + BNE singleByteCompare + SUBS r14,r14,#4 + STR r11,[r4], #4 @ r4 = [dst] + BGT xLoop + + ADD r2,r2,r7 @ text += textSurfacePitch + ADD r3,r3,r5 @ src += vsPitch + ADD r4,r4,r6 @ dst += vmScreenWidth + SUBS r0,r0,#1 + BGT yLoop + LDMFD r13!,{r4-r7,r9-r11,PC} + +singleByteCompare: + MOV r9,r12,LSR #24 @ r9 = 1st byte of [text] + CMP r9,r10,LSR #24 @ if (r9 == mask) + MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src] + ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12 + + MOV r9,r12,LSR #24 @ r9 = 1st byte of [text] + CMP r9,r10,LSR #24 @ if (r9 == mask) + MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src] + ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12 + + MOV r9,r12,LSR #24 @ r9 = 1st byte of [text] + CMP r9,r10,LSR #24 @ if (r9 == mask) + MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src] + ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12 + + MOV r9,r12,LSR #24 @ r9 = 1st byte of [text] + CMP r9,r10,LSR #24 @ if (r9 == mask) + MOVEQ r9,r11,LSR #24 @ r9 = 1st byte of [src] + ORR r12,r9,r12,LSL #8 @ r12 = combine r9 and r12 + + STR r12,[r4],#4 + SUBS r14,r14,#4 + BGT xLoop + + ADD r2,r2,r7 @ text += textSurfacePitch + ADD r3,r3,r5 @ src += vsPitch + ADD r4,r4,r6 @ dst += vmScreenWidth + SUBS r0,r0,#1 + BGT yLoop +end: + LDMFD r13!,{r4-r7,r9-r11,PC} + + + @ ARM implementation of asmCopy8Col + @ + @ C prototype would be: + @ + @ extern "C" void asmCopy8Col(byte *dst, + @ int dstPitch, + @ const byte *src, + @ int height); + @ + @ In addition, we assume that src and dst are both word (4 byte) + @ aligned. This is the same assumption that the old 'inline' version + @ made. +asmCopy8Col: + @ r0 = dst + @ r1 = dstPitch + @ r2 = src + @ r3 = height + STMFD r13!,{r14} + SUB r1,r1,#4 + + TST r3,#1 + ADDNE r3,r3,#1 + BNE roll2 +yLoop2: + LDR r12,[r2],#4 + LDR r14,[r2],r1 + STR r12,[r0],#4 + STR r14,[r0],r1 +roll2: + LDR r12,[r2],#4 + LDR r14,[r2],r1 + SUBS r3,r3,#2 + STR r12,[r0],#4 + STR r14,[r0],r1 + BNE yLoop2 + + LDMFD r13!,{PC} + + + @ ARM implementation of Rescale_320x256x1555_To_256x256x1555 + @ + @ C prototype would be: + @ + @ extern "C" void Rescale_320x256x1555_To_256x256x1555( + @ u16 *dst, + @ const u16 *src, + @ int dstStride, + @ int srcStride); +Rescale_320x256x1555_To_256x256x1555: + @ r0 = dst + @ r1 = src + @ r2 = dstStride + @ r3 = srcStride + STMFD r13!,{r4-r5,r8-r11,r14} + + SUB r2,r2,#64*5 @ srcStride -= line length + SUB r3,r3,#64*4 @ dstStride -= line length + + MOV r8, #0x0000001F + ORR r8, r8,#0x00007C00 + ORR r8, r8,#0x03E00000 @ r8 = mask + MOV r5, #200 @ r5 = y +yLoop3: + MOV r4, #64 @ r4 = x +xLoop3: + LDRH r9, [r0],#2 @ r9 = src0 + LDRH r10,[r0],#2 @ r10= src1 + LDRH r11,[r0],#2 @ r11= src2 + LDRH r12,[r0],#2 @ r12= src3 + LDRH r14,[r0],#2 @ r14= src4 + + ORR r9, r9, r9, LSL #16 @ r9 = src0 | src0 + ORR r10,r10,r10,LSL #16 @ r10= src1 | src1 + ORR r11,r11,r11,LSL #16 @ r11= src2 | src2 + ORR r12,r12,r12,LSL #16 @ r12= src3 | src3 + ORR r14,r14,r14,LSL #16 @ r13= src4 | src4 + + AND r9, r9, r8 @ r9 = 0 | G0 | 0 | B0 | 0 | R0 + AND r10,r10,r8 @ r10= 0 | G1 | 0 | B1 | 0 | R1 + AND r11,r11,r8 @ r11= 0 | G2 | 0 | B2 | 0 | R2 + AND r12,r12,r8 @ r12= 0 | G3 | 0 | B3 | 0 | R3 + AND r14,r14,r8 @ r14= 0 | G4 | 0 | B4 | 0 | R4 + + ADD r9, r9, r9, LSL #1 @ r9 = 3*src0 + ADD r9, r9, r10 @ r9 = dst0<<2 + ADD r10,r10,r11 @ r10= dst1 + ADD r11,r11,r12 @ r11= dst2 + ADD r12,r12,r14 @ r12= src3 + src4 + ADD r12,r12,r14,LSL #1 @ r12= src3 + src4*3 = dst3<<2 + + AND r9, r8, r9, LSR #2 @ r9 = dst0 (split) + AND r10,r8, r10,LSR #1 @ r10= dst1 (split) + AND r11,r8, r11,LSR #1 @ r11= dst2 (split) + AND r12,r8, r12,LSR #2 @ r12= dst3 (split) + + ORR r9, r9, r9, LSR #16 @ r9 = dst0 + ORR r10,r10,r10,LSR #16 @ r10= dst1 + ORR r11,r11,r11,LSR #16 @ r11= dst2 + ORR r12,r12,r12,LSR #16 @ r12= dst3 + + ORR r9, r9, #0x8000 + ORR r10,r10,#0x8000 + ORR r11,r11,#0x8000 + ORR r12,r12,#0x8000 + + STRH r9, [r1],#2 + STRH r10,[r1],#2 + STRH r11,[r1],#2 + STRH r12,[r1],#2 + + SUBS r4,r4,#1 + BGT xLoop3 + + ADD r0,r0,r2,LSL #1 + ADD r1,r2,r3,LSL #1 + SUBS r5,r5,#1 + BGT yLoop3 + + LDMFD r13!,{r4-r5,r8-r11,PC} + + @ ARM implementation of Rescale_320x256xPAL8_To_256x256x1555 + @ + @ C prototype would be: + @ + @ extern "C" void Rescale_320x256xPAL8_To_256x256x1555( + @ u16 *dst, + @ const u8 *src, + @ int dstStride, + @ int srcStride, + @ const u16 *pal); + @ + @ This is a slight reordering of the params from the existing C one. + @ Sorry, but it makes the code easier. +Rescale_320x256xPAL8_To_256x256x1555: + @ r0 = dst + @ r1 = src + @ r2 = dstStride + @ r3 = srcStride + STMFD r13!,{r4-r5,r8-r11,r14} + MOV r8, #0x0000001F + ORR r8, r8,#0x00007C00 + ORR r8, r8,#0x03E00000 @ r8 = mask + LDR r9, [r13,#7*4] @ r9 = palette + + SUB r13,r13,#256*4 @ r13 = 1K of space on the stack. + MOV r5, r13 @ r5 points to this space + MOV r14,#256 +palLoop: + LDRH r10,[r9],#2 @ r10 = palette entry + SUBS r14,r14,#1 + ORR r10,r10,r10,LSL #16 + AND r10,r10,r8 @ r10 = separated palette entry + STR r10,[r5], #4 + BGT palLoop + + SUB r2,r2,#64*5 @ srcStride -= line length + SUB r3,r3,#64*4 @ dstStride -= line length + + MOV r5,#200 @ r5 = y +yLoop4: + MOV r4,#64 @ r4 = x +xLoop4: + LDRB r9, [r0],#1 @ r9 = src0 + LDRB r10,[r0],#1 @ r10= src1 + LDRB r11,[r0],#1 @ r11= src2 + LDRB r12,[r0],#1 @ r12= src3 + LDRB r14,[r0],#1 @ r14= src4 + + LDR r9, [r13,r9, LSL #2] @ r9 = pal[src0] + LDR r10,[r13,r10,LSL #2] @ r10= pal[src1] + LDR r11,[r13,r11,LSL #2] @ r11= pal[src2] + LDR r12,[r13,r12,LSL #2] @ r12= pal[src3] + LDR r14,[r13,r14,LSL #2] @ r13= pal[src4] + + ADD r9, r9, r9, LSL #1 @ r9 = 3*src0 + ADD r9, r9, r10 @ r9 = dst0<<2 + ADD r10,r10,r11 @ r10= dst1 + ADD r11,r11,r12 @ r11= dst2 + ADD r12,r12,r14 @ r12= src3 + src4 + ADD r12,r12,r14,LSL #1 @ r12= src3 + src4*3 = dst3<<2 + + AND r9, r8, r9, LSR #2 @ r9 = dst0 (split) + AND r10,r8, r10,LSR #1 @ r10= dst1 (split) + AND r11,r8, r11,LSR #1 @ r11= dst2 (split) + AND r12,r8, r12,LSR #2 @ r12= dst3 (split) + + ORR r9, r9, r9, LSR #16 @ r9 = dst0 + ORR r10,r10,r10,LSR #16 @ r10= dst1 + ORR r11,r11,r11,LSR #16 @ r11= dst2 + ORR r12,r12,r12,LSR #16 @ r12= dst3 + + ORR r9, r9, #0x8000 + ORR r10,r10,#0x8000 + ORR r11,r11,#0x8000 + ORR r12,r12,#0x8000 + + STRH r9, [r1],#2 + STRH r10,[r1],#2 + STRH r11,[r1],#2 + STRH r12,[r1],#2 + + SUBS r4,r4,#1 + BGT xLoop4 + + ADD r0,r0,r2 + ADD r1,r2,r3,LSL #1 + SUBS r5,r5,#1 + BGT yLoop4 + + ADD r13,r13,#256*4 + + LDMFD r13!,{r4-r5,r8-r11,PC} + + diff --git a/backends/platform/ds/arm9/source/dsmain.cpp b/backends/platform/ds/arm9/source/dsmain.cpp index af5addac66..aafa54e347 100644 --- a/backends/platform/ds/arm9/source/dsmain.cpp +++ b/backends/platform/ds/arm9/source/dsmain.cpp @@ -44,9 +44,32 @@ // - Delete saves? // - Software scaler? // - 100% scale + +// - Arrow keys cause key events when keyboard enabled - Done +// - Mouse cursor display - Done +// - Disable scaler on options menu - Done +// - Fix scale icons on top screen - Done +// - Fseek optimisation? - No need +// - Fix agi hack to be cleaner - done +// - Fix not typing looong words - Done +// - Show keyboard by default in AGI games +// - Fix mouse moving when cursor on keyboard screen - Done +// - Fix 'fit' thingy always appearing - Done +// - check cine backbuffer code - Done +// - Add long filename support - Done +// - New icons +// - Add key config for gob engine: Start:F1, Shift-numbers: F keys - Done +// - Fix [ds] appearing in game menu + // - Find out what's going wrong when you turn the console off +// - enable console when asserting + +// - AGI: Adding keyboard hack +// - CINE: Framebuffer modification should check if it works without, fix for overwrite crash +// - KYRA: GetFileSize modification + -#define USE_LIBCARTRESET +//#define USE_LIBCARTRESET //#define USE_BUILT_IN_DRIVER_SELECTION #include <nds.h> @@ -78,6 +101,8 @@ #include "blitters.h" #include "cartreset_nolibfat.h" #include "keys.h" +#include "profiler/cyg-profile.h" +//test namespace DS { @@ -151,13 +176,16 @@ bool displayModeIs8Bit = false; // Game id u8 gameID; -bool consoleEnable = true; +bool consoleEnable = false; bool gameScreenSwap = false; bool isCpuScalerEnabled(); //#define HEAVY_LOGGING MouseMode mouseMode; +int storedMouseX = 0; +int storedMouseY = 0; + // Sprites SpriteEntry sprites[128]; SpriteEntry spritesMain[128]; @@ -173,6 +201,9 @@ bool keyboardIcon = false; // Touch int touchScX, touchScY, touchX, touchY; +int mouseHotspotX, mouseHotspotY; +bool cursorEnable = false; +bool mouseCursorVisible = true; // Dragging int dragStartX, dragStartY; @@ -188,20 +219,12 @@ int gameHeight = 200; // Scale bool twoHundredPercentFixedScale = false; +#define NUM_SUPPORTED_GAMES 17 -enum controlType { - CONT_SCUMM_ORIGINAL, - CONT_SCUMM_SAMNMAX, - CONT_SKY, - CONT_SIMON, -}; - -struct gameListType { - char gameId[16]; - controlType control; -}; +#ifdef USE_PROFILER +int hBlankCount = 0; +#endif -#define NUM_SUPPORTED_GAMES 15 gameListType gameList[NUM_SUPPORTED_GAMES] = { // Unknown game - use normal SCUMM controls @@ -222,8 +245,10 @@ gameListType gameList[NUM_SUPPORTED_GAMES] = { {"sky", CONT_SKY}, {"simon1", CONT_SIMON}, {"simon2", CONT_SIMON}, - {"gob1", CONT_SCUMM_ORIGINAL}, - {"queen", CONT_SCUMM_ORIGINAL} + {"gob", CONT_GOBLINS}, + {"queen", CONT_SCUMM_ORIGINAL}, + {"cine", CONT_FUTURE_WARS}, + {"agi", CONT_AGI} }; gameListType* currentGame = NULL; @@ -259,9 +284,11 @@ int getKeysChanged(); void updateStatus(); void triggerIcon(int imageNum); void setIcon(int num, int x, int y, int imageNum, int flags, bool enable); +void setIconMain(int num, int x, int y, int imageNum, int flags, bool enable); TransferSound soundControl; + bool isCpuScalerEnabled() { return (ConfMan.hasKey("cpu_scaler", "ds") && ConfMan.getBool("cpu_scaler", "ds")); @@ -332,20 +359,21 @@ void initSprites() { void saveGameBackBuffer() { #ifdef DISABLE_SCUMM - if (savedBuffer == NULL) savedBuffer = new u8[gameWidth * gameHeight]; + if (savedBuffer == NULL) savedBuffer = new u8[gameWidth * gameHeight]; for (int r = 0; r < gameHeight; r++) { memcpy(savedBuffer + (r * gameWidth), ((u8 *) (get8BitBackBuffer())) + (r * 512), gameWidth); + } #endif } void restoreGameBackBuffer() { #ifdef DISABLE_SCUMM if (savedBuffer) { - for (int r = 0; r < gameHeight; r++) { - memcpy(((u8 *) (BG_GFX_SUB)) + (r * 512), savedBuffer + (r * gameWidth), gameWidth); - memcpy(((u8 *) (get8BitBackBuffer())) + (r * 512), savedBuffer + (r * gameWidth), gameWidth); - } - + for (int r = 0; r < gameHeight; r++) { + memcpy(((u8 *) (BG_GFX_SUB)) + (r * 512), savedBuffer + (r * gameWidth), gameWidth); + memcpy(((u8 *) (get8BitBackBuffer())) + (r * 512), savedBuffer + (r * gameWidth), gameWidth); + } + delete savedBuffer; savedBuffer = NULL; } @@ -413,7 +441,7 @@ void initGame() { //strcpy(gameName, ConfMan.getActiveDomain().c_str()); strcpy(gameName, ConfMan.get("gameid").c_str()); -// consolePrintf("\n\n\n\nCurrent game: '%s' %d\n", gameName, gameName[0]); + //consolePrintf("\n\n\n\nCurrent game: '%s' %d\n", gameName, gameName[0]); currentGame = &gameList[0]; // Default game @@ -590,7 +618,51 @@ void checkSleepMode() { } } -void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor) { +void setShowCursor(bool enable) +{ + if (currentGame->control == CONT_SCUMM_SAMNMAX) + { + if (cursorEnable) { + sprites[1].attribute[0] = ATTR0_BMP | 150; + } else { + sprites[1].attribute[0] = ATTR0_DISABLED; + } + + } + + cursorEnable = enable; +} + +void setMouseCursorVisible(bool enable) +{ + mouseCursorVisible = enable; +} + +void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor, int hotspotX, int hotspotY) { + + mouseHotspotX = hotspotX; + mouseHotspotY = hotspotY; + + { + int off = 128*64; + + + memset(SPRITE_GFX + off, 0, 32 * 32 * 2); + + for (uint y=0; y<h; y++) { + for (uint x=0; x<w; x++) { + int color = icon[y*w+x]; + + if (color == keycolor) { + SPRITE_GFX[off+(y)*32+x] = 0x0000; // black background + } else { + SPRITE_GFX[off+(y)*32+x] = BG_PALETTE[color] | 0x8000; + } + } + } + + } + if (currentGame->control != CONT_SCUMM_SAMNMAX) return; @@ -619,6 +691,7 @@ void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor) { for (uint y=0; y<h; y++) { for (uint x=0; x<w; x++) { int color = icon[y*w+x]; + if (color == keycolor) { SPRITE_GFX_SUB[off+(y+1+offset)*64+(x+1)] = 0x8000; // black background } else { @@ -626,10 +699,18 @@ void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor) { } } } - - sprites[1].attribute[0] = ATTR0_BMP | 150; - sprites[1].attribute[1] = ATTR1_SIZE_64 | pos; - sprites[1].attribute[2] = ATTR2_ALPHA(1) | 48; + + + if ((cursorEnable)) + { + sprites[1].attribute[0] = ATTR0_BMP | 150; + sprites[1].attribute[1] = ATTR1_SIZE_64 | pos; + sprites[1].attribute[2] = ATTR2_ALPHA(1) | 48; + } else { + sprites[1].attribute[0] = ATTR0_DISABLED | 150; + sprites[1].attribute[1] = ATTR1_SIZE_64 | pos; + sprites[1].attribute[2] = ATTR2_ALPHA(1) | 48; + } } @@ -734,7 +815,7 @@ void displayMode16BitFlipBuffer() { #endif const u8* back = (const u8*)get8BitBackBuffer(); u16* base = BG_GFX + 0x10000; - DS::Rescale_320x256xPAL8_To_256x256x1555( base, + Rescale_320x256xPAL8_To_256x256x1555( base, back, BG_PALETTE, 256, @@ -867,7 +948,7 @@ void addIndyFightingKeys() { event.type = Common::EVENT_KEYDOWN; event.kbd.flags = 0; - consolePrintf("Fight keys\n"); +// consolePrintf("Fight keys\n"); if ((getKeysDown() & KEY_L)) { indyFightRight = false; @@ -877,7 +958,7 @@ void addIndyFightingKeys() { indyFightRight = true; } - consolePrintf("ifr:%d\n", indyFightRight); +// consolePrintf("ifr:%d\n", indyFightRight); if ((getKeysChanged() & KEY_UP)) { event.type = getKeyEvent(KEY_UP); @@ -966,10 +1047,10 @@ void setKeyboardEnable(bool en) { if (keyboardEnable) { - DS::drawKeyboard(1, 12, backupBank); + DS::drawKeyboard(1, 14, backupBank); - SUB_BG1_CR = BG_TILE_BASE(1) | BG_MAP_BASE(12); + SUB_BG1_CR = BG_TILE_BASE(1) | BG_MAP_BASE(14); if (displayModeIs8Bit) { SUB_DISPLAY_CR |= DISPLAY_BG1_ACTIVE; // Turn on keyboard layer @@ -1025,6 +1106,16 @@ void addEventsToQueue() { Common::Event event; +#ifdef USE_PROFILER + if (keysDown() & KEY_R) { + cygprofile_begin(); + cygprofile_enable(); + } + if (keysDown() & KEY_L) { + cygprofile_disable(); + cygprofile_end(); + } +#endif if (system->isEventQueueEmpty()) { @@ -1051,7 +1142,7 @@ void addEventsToQueue() { if (!indyFightState) { - if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { + if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R)) && (getKeysChanged() & KEY_B)) { event.kbd.keycode = 27; event.kbd.ascii = 27; event.kbd.flags = 0; @@ -1073,8 +1164,37 @@ void addEventsToQueue() { } } + if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (getKeyboardEnable())) { + event.kbd.flags = 0; + + if (getKeysChanged() & KEY_LEFT) { + event.kbd.keycode = SDLK_LEFT; + event.kbd.ascii = SDLK_LEFT; + event.type = getKeyEvent(KEY_LEFT); + } + + if (getKeysChanged() & KEY_RIGHT) { + event.kbd.keycode = SDLK_RIGHT; + event.kbd.ascii = SDLK_RIGHT; + event.type = getKeyEvent(KEY_RIGHT); + } + + if (getKeysChanged() & KEY_UP) { + event.kbd.keycode = SDLK_UP; + event.kbd.ascii = SDLK_UP; + event.type = getKeyEvent(KEY_UP); + } + + if (getKeysChanged() & KEY_DOWN) { + event.kbd.keycode = SDLK_DOWN; + event.kbd.ascii = SDLK_DOWN; + event.type = getKeyEvent(KEY_DOWN); + } + + system->addEvent(event); + } - if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (!getIndyFightState())) { + if (!((getKeysHeld() & KEY_L) || (getKeysHeld() & KEY_R)) && (!getIndyFightState()) && (!getKeyboardEnable())) { if ((getKeysDown() & KEY_A) && (!indyFightState)) { gameScreenSwap = !gameScreenSwap; @@ -1084,16 +1204,25 @@ void addEventsToQueue() { if (getKeysDown() & KEY_LEFT) { mouseMode = MOUSE_LEFT; } + if (getKeysDown() & KEY_RIGHT) { - if (currentGame->control != CONT_SCUMM_SAMNMAX) { + if ((currentGame->control != CONT_SCUMM_SAMNMAX) && (currentGame->control != CONT_FUTURE_WARS)) { mouseMode = MOUSE_RIGHT; } else { // If we're playing sam and max, click and release the right mouse // button to change verb Common::Event event; + + if (currentGame->control == CONT_FUTURE_WARS) { + event.mouse = Common::Point(320 - 128, 200 - 128); + event.type = Common::EVENT_MOUSEMOVE; + system->addEvent(event); + } else { + event.mouse = Common::Point(getPenX(), getPenY()); + } + event.type = Common::EVENT_RBUTTONDOWN; - event.mouse = Common::Point(getPenX(), getPenY()); system->addEvent(event); event.type = Common::EVENT_RBUTTONUP; @@ -1126,14 +1255,16 @@ void addEventsToQueue() { Common::Event event; - if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { - event.type = Common::EVENT_MOUSEMOVE; - event.mouse = Common::Point(getPenX(), getPenY()); - system->addEvent(event); - //consolePrintf("x=%d y=%d \n", getPenX(), getPenY()); - } if (!keyboardEnable) { + + if ((!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { + event.type = Common::EVENT_MOUSEMOVE; + event.mouse = Common::Point(getPenX(), getPenY()); + system->addEvent(event); + //consolePrintf("x=%d y=%d \n", getPenX(), getPenY()); + } + if ((mouseMode != MOUSE_HOVER) || (!displayModeIs8Bit)) { if (getPenDown() && (!(getKeysHeld() & KEY_L)) && (!(getKeysHeld() & KEY_R))) { event.type = ((mouseMode == MOUSE_LEFT) || (!displayModeIs8Bit))? Common::EVENT_LBUTTONDOWN: Common::EVENT_RBUTTONDOWN; @@ -1179,7 +1310,7 @@ void addEventsToQueue() { if (currentGame->control == CONT_SKY) { - // Extra controls for Benieth a Steel Sky + // Extra controls for Beneath a Steel Sky if ((getKeysDown() & KEY_DOWN)) { penY = 0; penX = 160; // Show inventory by moving mouse onto top line @@ -1253,8 +1384,18 @@ void addEventsToQueue() { if ((getKeysChanged() & KEY_START)) { event.type = getKeyEvent(KEY_START); - event.kbd.keycode = Common::KEYCODE_F5; - event.kbd.ascii = Common::ASCII_F5; + if (currentGame->control == CONT_FUTURE_WARS) { + event.kbd.keycode = Common::KEYCODE_F10; + event.kbd.ascii = Common::ASCII_F10; + } else if (currentGame->control == CONT_GOBLINS) { + event.kbd.keycode = Common::KEYCODE_F1; + event.kbd.ascii = Common::ASCII_F1; +// consolePrintf("!!!!!F1!!!!!"); + } else { + event.kbd.keycode = Common::KEYCODE_F5; + event.kbd.ascii = Common::ASCII_F5; +// consolePrintf("!!!!!F5!!!!!"); + } event.kbd.flags = 0; system->addEvent(event); } @@ -1280,11 +1421,17 @@ void triggerIcon(int imageNum) { void setIcon(int num, int x, int y, int imageNum, int flags, bool enable) { - sprites[num].attribute[0] = ATTR0_BMP | y | (!enable? ATTR0_DISABLED: 0); + sprites[num].attribute[0] = ATTR0_BMP | (enable? y: 192) | (!enable? ATTR0_DISABLED: 0); sprites[num].attribute[1] = ATTR1_SIZE_32 | x | flags; sprites[num].attribute[2] = ATTR2_ALPHA(1)| (imageNum * 16); } +void setIconMain(int num, int x, int y, int imageNum, int flags, bool enable) { + spritesMain[num].attribute[0] = ATTR0_BMP | (y & 0x1FF) | (!enable? ATTR0_DISABLED: 0); + spritesMain[num].attribute[1] = ATTR1_SIZE_32 | (x & 0x1FF) | flags; + spritesMain[num].attribute[2] = ATTR2_ALPHA(1)| (imageNum * 16); +} + void updateStatus() { int offs; @@ -1313,7 +1460,7 @@ void updateStatus() { if (indyFightState) { setIcon(1, (190 - 32), 150, 3, (indyFightRight? 0: ATTR1_FLIP_X), true); - consolePrintf("%d\n", indyFightRight); +// consolePrintf("%d\n", indyFightRight); } else { // setIcon(1, 0, 0, 0, 0, false); } @@ -1324,7 +1471,7 @@ void updateStatus() { } else { setIcon(4, 0, 0, 0, 0, false); } - + } else { setIcon(0, 0, 0, 0, 0, false); setIcon(1, 0, 0, 0, 0, false); @@ -1334,14 +1481,16 @@ void updateStatus() { } if ((keyboardIcon) && (!keyboardEnable) && (!displayModeIs8Bit)) { - spritesMain[0].attribute[0] = ATTR0_BMP | 160; - spritesMain[0].attribute[1] = ATTR1_SIZE_32 | 0; - spritesMain[0].attribute[2] = ATTR2_ALPHA(1) | 64; +// spritesMain[0].attribute[0] = ATTR0_BMP | 160; +// spritesMain[0].attribute[1] = ATTR1_SIZE_32 | 0; +// spritesMain[0].attribute[2] = ATTR2_ALPHA(1) | 64; + setIconMain(0, 0, 160, 4, 0, true); } else { - spritesMain[0].attribute[0] = ATTR0_DISABLED; - spritesMain[0].attribute[1] = 0; - spritesMain[0].attribute[2] = 0; - spritesMain[0].attribute[3] = 0; +// spritesMain[0].attribute[0] = ATTR0_DISABLED; +// spritesMain[0].attribute[1] = 0; +// spritesMain[0].attribute[2] = 0; +// spritesMain[0].attribute[3] = 0; + setIconMain(0, 0, 0, 0, 0, false); } } @@ -1428,6 +1577,10 @@ void setZoomedScreenScale(int x, int y) { } } +#ifdef USE_PROFILER +void VBlankHandler(void) __attribute__ ((no_instrument_function)); +#endif + void VBlankHandler(void) { // BG_PALETTE[0] = RGB15(31, 31, 31); // if (*((int *) (0x023FFF00)) != 0xBEEFCAFE) { @@ -1473,6 +1626,19 @@ void VBlankHandler(void) { frameCount++; + if ((cursorEnable) && (mouseCursorVisible)) + { + if (!keyboardEnable) { + storedMouseX = penX; + storedMouseY = penY; + } + + setIconMain(3, storedMouseX - mouseHotspotX, storedMouseY - mouseHotspotY, 8, 0, true); + } + else + { + setIconMain(3, 0, 0, 0, 0, false); + } if (callback) { @@ -1563,7 +1729,7 @@ void VBlankHandler(void) { if (zooming) { subScX = subScTargetX; subScY = subScTargetY; - triggerIcon(0); + triggerIcon(5); } } else if ( ((subScreenWidth) > 128 - 8) && ((subScreenWidth) < 128 + 8) ) { subScreenWidth = 128; @@ -1571,7 +1737,7 @@ void VBlankHandler(void) { if (zooming) { subScX = subScTargetX; subScY = subScTargetY; - triggerIcon(1); + triggerIcon(6); } } else if (subScreenWidth > 256) { subScreenWidth = 320; @@ -1579,10 +1745,10 @@ void VBlankHandler(void) { if (zooming) { subScX = subScTargetX; subScY = subScTargetY; - triggerIcon(2); + triggerIcon(7); } } else { - triggerIcon(-1); + //triggerIcon(-1); } } @@ -1745,6 +1911,14 @@ void setTopScreenTarget(int x, int y) { subScTargetY <<=8; } +#ifdef USE_PROFILER +void hBlankHanlder() __attribute__ ((no_instrument_function)); + +void hBlankHandler() { + hBlankCount++; +} +#endif + void initHardware() { // Guard band //((int *) (0x023FFF00)) = 0xBEEFCAFE; @@ -1757,7 +1931,7 @@ void initHardware() { vramSetBankB(VRAM_B_MAIN_BG); vramSetBankC(VRAM_C_SUB_BG); */ vramSetBankI(VRAM_I_SUB_SPRITE); - vramSetBankG(VRAM_G_MAIN_SPRITE); + vramSetBankE(VRAM_E_MAIN_SPRITE); currentTimeMillis = 0; @@ -1825,6 +1999,11 @@ void initHardware() { irqEnable(IRQ_VBLANK); irqEnable(IRQ_TIMER0); irqEnable(IRQ_TIMER2); + +#ifdef USE_PROFILER + irqSet(IRQ_HBLANK, hBlankHandler); + irqEnable(IRQ_HBLANK); +#endif // Set up a millisecond timer @@ -1847,14 +2026,22 @@ void initHardware() { // Convert texture from 24bit 888 to 16bit 1555, remembering to set top bit! u8* srcTex = (u8 *) icons_raw; - for (int r = 32 * 160 ; r >= 0; r--) { + for (int r = 32 * 256 ; r >= 0; r--) { SPRITE_GFX_SUB[r] = 0x8000 | (srcTex[r * 3] >> 3) | ((srcTex[r * 3 + 1] >> 3) << 5) | ((srcTex[r * 3 + 2] >> 3) << 10); SPRITE_GFX[r] = 0x8000 | (srcTex[r * 3] >> 3) | ((srcTex[r * 3 + 1] >> 3) << 5) | ((srcTex[r * 3 + 2] >> 3) << 10); } + + + + WAIT_CR &= ~(0x0080); // REG_WRAM_CNT = 0; + // This is a bodge to get around the fact that the cursor is turned on before it's image is set + // during startup in Sam & Max. This bodge moves the cursor offscreen so it is not seen. + sprites[1].attribute[1] = ATTR1_SIZE_64 | 192; + } @@ -2067,23 +2254,28 @@ bool getIndyFightState() { return indyFightState; } +gameListType* getCurrentGame() { + return currentGame; +} + /////////////////// // Fast Ram /////////////////// -#define FAST_RAM_SIZE (30000) +#define FAST_RAM_SIZE (24000) u8* fastRamPointer; u8 fastRamData[FAST_RAM_SIZE] ITCM_DATA; void* fastRamAlloc(int size) { +// return malloc(size); void* result = (void *) fastRamPointer; fastRamPointer += size; return (void *) (result); } void fastRamReset() { - fastRamPointer = fastRamData; + fastRamPointer = &fastRamData[0]; } @@ -2308,24 +2500,34 @@ int main(void) // } - + //2372 consolePrintf("-------------------------------\n"); consolePrintf("ScummVM DS\n"); consolePrintf("Ported by Neil Millstone\n"); - FIXME: Change this code to make use of base/internal_version.h - resp. uses gScummVMVersion from base/version.h - consolePrintf("Version 0.10.0SVN "); + consolePrintf("Version 0.10.0 beta1 "); #if defined(DS_BUILD_A) consolePrintf("build A\n"); - consolePrintf("Supports: Lucasarts SCUMM\n"); + consolePrintf("Lucasarts SCUMM games (SCUMM)\n"); consolePrintf("-------------------------------\n"); #elif defined(DS_BUILD_B) consolePrintf("build B\n"); - consolePrintf("Supports: BASS, QUEEN\n"); + consolePrintf("BASS, QUEEN\n"); consolePrintf("-------------------------------\n"); #elif defined(DS_BUILD_C) consolePrintf("build C\n"); - consolePrintf("Supports: SIMON, KYRA, GOB\n"); + consolePrintf("Simon the Sorcerer 1/2 (SIMON)\n"); + consolePrintf("-------------------------------\n"); +#elif defined(DS_BUILD_D) + consolePrintf("build D\n"); + consolePrintf("AGI, CINE, GOB\n"); + consolePrintf("-------------------------------\n"); +#elif defined(DS_BUILD_E) + consolePrintf("build E\n"); + consolePrintf("Inherit the earth (SAGA)\n"); + consolePrintf("-------------------------------\n"); +#elif defined(DS_BUILD_F) + consolePrintf("build F\n"); + consolePrintf("The Legend of Kyrandia (KYRA)\n"); consolePrintf("-------------------------------\n"); #endif consolePrintf("L/R + D-pad/pen: Scroll view\n"); @@ -2333,7 +2535,7 @@ int main(void) consolePrintf("D-pad right: Right mouse button\n"); consolePrintf("D-pad up: Hover mouse\n"); consolePrintf("B button: Skip cutscenes\n"); - consolePrintf("Select: DS Options menu\n"); + consolePrintf("Select: DS Options menu\n"); consolePrintf("Start: Game menu (some games)\n"); consolePrintf("Y (in game): Toggle console\n"); consolePrintf("X: Toggle keyboard\n"); @@ -2457,10 +2659,13 @@ int main(void) #elif defined(DS_BUILD_C) char* argv[2] = {"/scummvmds", "--config=scummvmc.ini"}; #elif defined(DS_BUILD_D) - char* argv[2] = {"/scummvmds", "--config=scummvmd.ini"}; + char* argv[3] = {"/scummvmds", "--config=scummvmd.ini"}; +#elif defined(DS_BUILD_E) + char* argv[3] = {"/scummvmds", "--config=scummvme.ini"}; +#elif defined(DS_BUILD_F) + char* argv[3] = {"/scummvmds", "--config=scummvmf.ini"}; #endif - #ifdef DS_NON_SCUMM_BUILD while (1) { @@ -2482,3 +2687,13 @@ int main(void) int main() { DS::main(); } + + +#ifdef USE_PROFILER +int cygprofile_getHBlanks() __attribute__ ((no_instrument_function)); + + +int cygprofile_getHBlanks() { + return DS::hBlankCount; +} +#endif diff --git a/backends/platform/ds/arm9/source/dsmain.h b/backends/platform/ds/arm9/source/dsmain.h index 58a5be9240..94f02145a2 100644 --- a/backends/platform/ds/arm9/source/dsmain.h +++ b/backends/platform/ds/arm9/source/dsmain.h @@ -31,6 +31,22 @@ namespace DS { + +enum controlType { + CONT_SCUMM_ORIGINAL, + CONT_SCUMM_SAMNMAX, + CONT_SKY, + CONT_SIMON, + CONT_FUTURE_WARS, + CONT_AGI, + CONT_GOBLINS +}; + +struct gameListType { + char gameId[16]; + controlType control; +}; + // Pen reading functions void penInit(); void penUpdate(); @@ -83,7 +99,9 @@ void VBlankHandler(); // Sam and Max Stuff void setGameID(int id); -void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor); +void setCursorIcon(const u8* icon, uint w, uint h, byte keycolor, int hotspotX, int hotspotY); +void setShowCursor(bool enable); +void setMouseCursorVisible(bool visible); // Shake void setShakePos(int shakePos); @@ -123,7 +141,12 @@ void fastRamReset(); void* fastRamAlloc(int size); +gameListType* getCurrentGame(); + + } +int cygprofile_getHBlanks(); + #endif diff --git a/backends/platform/ds/arm9/source/dsoptions.cpp b/backends/platform/ds/arm9/source/dsoptions.cpp index 171d1e044c..b29b1d9fa7 100644 --- a/backends/platform/ds/arm9/source/dsoptions.cpp +++ b/backends/platform/ds/arm9/source/dsoptions.cpp @@ -55,7 +55,8 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(20, 0, 320 - 40, 200 - 20) { _twoHundredPercentCheckbox = new GUI::CheckboxWidget(this, 20, 70, 230, 20, "Zoomed screen at fixed 200% zoom", 0, 'T'); _highQualityAudioCheckbox = new GUI::CheckboxWidget(this, 20, 85, 250, 20, "High quality audio (slower) (reboot)", 0, 'T'); _disablePowerOff = new GUI::CheckboxWidget(this, 20, 100, 250, 20, "Disable power off on quit", 0, 'T'); - _cpuScaler = new GUI::CheckboxWidget(this, 20, 115, 250, 20, "CPU scaler", 0, 'T'); +// _cpuScaler = new GUI::CheckboxWidget(this, 20, 115, 250, 20, "CPU scaler", 0, 'T'); + _showCursorCheckbox = new GUI::CheckboxWidget(this, 20, 115, 250, 20, "Show mouse cursor", 0, 'T'); new GUI::StaticTextWidget(this, 20, 130, 110, 15, "Touch X Offset", GUI::kTextAlignLeft); _touchX = new GUI::SliderWidget(this, 130, 130, 130, 12, 1); @@ -79,6 +80,12 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(20, 0, 320 - 40, 200 - 20) { _delDialog = new Scumm::SaveLoadChooser("Delete game:", "Delete", false, Scumm::g_scumm); #endif + if (ConfMan.hasKey("showcursor", "ds")) { + _showCursorCheckbox->setState(ConfMan.getBool("showcursor", "ds")); + } else { + _showCursorCheckbox->setState(false); + } + if (ConfMan.hasKey("lefthanded", "ds")) { _leftHandedCheckbox->setState(ConfMan.getBool("lefthanded", "ds")); } else { @@ -108,13 +115,13 @@ DSOptionsDialog::DSOptionsDialog() : GUI::Dialog(20, 0, 320 - 40, 200 - 20) { } else { _disablePowerOff->setState(false); } - +/* if (ConfMan.hasKey("cpu_scaler", "ds")) { _cpuScaler->setState(ConfMan.getBool("cpu_scaler", "ds")); } else { _cpuScaler->setState(false); } - +*/ _indyFightCheckbox->setState(DS::getIndyFightState()); if (ConfMan.hasKey("xoffset", "ds")) { @@ -137,9 +144,10 @@ DSOptionsDialog::~DSOptionsDialog() { ConfMan.setBool("twohundredpercent", _twoHundredPercentCheckbox->getState(), "ds"); ConfMan.setBool("22khzaudio", _highQualityAudioCheckbox->getState(), "ds"); ConfMan.setBool("disablepoweroff", _disablePowerOff->getState(), "ds"); - ConfMan.setBool("cpu_scaler", _cpuScaler->getState(), "ds"); +// ConfMan.setBool("cpu_scaler", _cpuScaler->getState(), "ds"); ConfMan.setInt("xoffset", _touchX->getValue(), "ds"); ConfMan.setInt("yoffset", _touchY->getValue(), "ds"); + ConfMan.setBool("showcursor", _showCursorCheckbox->getState(), "ds"); DS::setOptions(); DS::setIndyFightState(_indyFightCheckbox->getState()); ConfMan.flushToDisk(); @@ -181,15 +189,27 @@ void DSOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, uint } +void togglePause() { + // Toggle pause mode by simulating pressing 'p'. Not a good way of doing things! + + if (getCurrentGame()->control == CONT_SCUMM_ORIGINAL) { + Common::Event event; + OSystem_DS* system = OSystem_DS::instance(); + + event.type = Common::EVENT_KEYDOWN; + event.kbd.keycode = 'p'; + event.kbd.ascii = 'p'; + event.kbd.flags = 0; + system->addEvent(event); + + event.type = Common::EVENT_KEYUP; + system->addEvent(event); + } +} + void showOptionsDialog() { - OSystem_DS* system = OSystem_DS::instance(); - Common::Event event; - event.type = Common::EVENT_KEYDOWN; - event.kbd.keycode = 'P'; // F5 - event.kbd.ascii = 'P'; - event.kbd.flags = 0; - system->addEvent(event); + togglePause(); DS::displayMode16Bit(); @@ -201,11 +221,7 @@ void showOptionsDialog() { DS::displayMode8Bit(); - event.type = Common::EVENT_KEYDOWN; - event.kbd.keycode = 'P'; // F5 - event.kbd.ascii = 'P'; - event.kbd.flags = 0; - system->addEvent(event); + togglePause(); } void setOptions() { @@ -217,6 +233,12 @@ void setOptions() { DS::setLeftHanded(false); } + if (ConfMan.hasKey("showcursor", "ds")) { + DS::setMouseCursorVisible(ConfMan.getBool("showcursor", "ds")); + } else { + DS::setMouseCursorVisible(true); + } + if (ConfMan.hasKey("unscaled", "ds")) { DS::setUnscaledMode(ConfMan.getBool("unscaled", "ds")); } else { diff --git a/backends/platform/ds/arm9/source/dsoptions.h b/backends/platform/ds/arm9/source/dsoptions.h index 8dde086f57..6976fb1a59 100644 --- a/backends/platform/ds/arm9/source/dsoptions.h +++ b/backends/platform/ds/arm9/source/dsoptions.h @@ -43,7 +43,7 @@ public: protected: virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data); - + void togglePause(); GUI::SliderWidget* _touchX; GUI::SliderWidget* _touchY; @@ -54,6 +54,7 @@ protected: GUI::CheckboxWidget* _highQualityAudioCheckbox; GUI::CheckboxWidget* _disablePowerOff; GUI::CheckboxWidget* _cpuScaler; + GUI::CheckboxWidget* _showCursorCheckbox; #ifdef DS_SCUMM_BUILD Scumm::SaveLoadChooser* _delDialog; diff --git a/backends/platform/ds/arm9/source/fat/disc_io.c b/backends/platform/ds/arm9/source/fat/disc_io.c index c706cf8b3e..3cb70f510b 100644 --- a/backends/platform/ds/arm9/source/fat/disc_io.c +++ b/backends/platform/ds/arm9/source/fat/disc_io.c @@ -358,7 +358,7 @@ void disc_getDldiId(char* id) { bool disc_setDsSlotInterface (void) { #ifdef ARM9 - REG_EXMEMCNT &= ~(1<<11); + REG_EXEMEMCNT &= ~(1<<11); #endif #ifdef ARM7 REG_EXEMEMCNT |= (1<<11); diff --git a/backends/platform/ds/arm9/source/fat/disc_io.h b/backends/platform/ds/arm9/source/fat/disc_io.h index 1fbcc78c19..06804afec7 100644 --- a/backends/platform/ds/arm9/source/fat/disc_io.h +++ b/backends/platform/ds/arm9/source/fat/disc_io.h @@ -33,7 +33,11 @@ // Disk caching is disabled on GBA to conserve memory #define DISC_CACHE // uncomment this line to enable disc caching +#ifdef DS_BUILD_F +#define DISC_CACHE_COUNT 128 // maximum number of sectors to cache (512 bytes per sector) +#else #define DISC_CACHE_COUNT 32 // maximum number of sectors to cache (512 bytes per sector) +#endif //#define DISK_CACHE_DMA // use DMA for cache copies. If this is enabled, the data buffers must be word aligned diff --git a/backends/platform/ds/arm9/source/fat/gba_nds_fat.c b/backends/platform/ds/arm9/source/fat/gba_nds_fat.c index f343c4b997..b5fdd665df 100644 --- a/backends/platform/ds/arm9/source/fat/gba_nds_fat.c +++ b/backends/platform/ds/arm9/source/fat/gba_nds_fat.c @@ -1362,9 +1362,18 @@ DIR_ENT FAT_DirEntFromPath (const char* path) DIR_ENT dirEntry; u32 dirCluster; bool flagLFN, dotSeen; - // Start at beginning of path pathPos = 0; + +#ifdef DS_BUILD_F + // Problems with Kyrandia doing a load of path lookups are reduced by this hack. + if (strstr(path, ".voc") || strstr(path, ".voc")) + { + dirEntry.name[0] = FILE_FREE; + dirEntry.attrib = 0x00; + return; + } +#endif if (path[pathPos] == '/') { @@ -2499,6 +2508,7 @@ int FAT_fseek(FAT_FILE* file, s32 offset, int origin) u32 position; u32 curPos; + if ((file == NULL) || (file->inUse == false)) // invalid file { return -1; @@ -2613,6 +2623,7 @@ int FAT_fseek(FAT_FILE* file, s32 offset, int origin) } return 0; + } /*----------------------------------------------------------------- diff --git a/backends/platform/ds/arm9/source/fat/io_dldi.h b/backends/platform/ds/arm9/source/fat/io_dldi.h index 86c3407374..053de3a94c 100644 --- a/backends/platform/ds/arm9/source/fat/io_dldi.h +++ b/backends/platform/ds/arm9/source/fat/io_dldi.h @@ -30,7 +30,7 @@ extern u8 _dldi_driver_name; static inline LPIO_INTERFACE DLDI_GetInterface(void) { #ifdef NDS // NDM: I'm really not sure about this change ARM9 - ARM7 - REG_EXMEMCNT &= ~(ARM7_OWNS_ROM | ARM7_OWNS_CARD); + REG_EXEMEMCNT &= ~(ARM7_OWNS_ROM | ARM7_OWNS_CARD); #endif // defined NDS return &_io_dldi; } diff --git a/backends/platform/ds/arm9/source/gbampsave.cpp b/backends/platform/ds/arm9/source/gbampsave.cpp index 7f7bf958df..0131040e1d 100644 --- a/backends/platform/ds/arm9/source/gbampsave.cpp +++ b/backends/platform/ds/arm9/source/gbampsave.cpp @@ -29,7 +29,7 @@ GBAMPSaveFile::GBAMPSaveFile(char* name, bool saveOrLoad) { handle = DS::std_fopen(name, saveOrLoad? "w": "r"); -// consolePrintf("%s handle is %d\n", name, handle); + consolePrintf("%s handle is %d\n", name, handle); // consolePrintf("Created %s\n", name); bufferPos = 0; saveSize = 0; @@ -39,6 +39,7 @@ GBAMPSaveFile::GBAMPSaveFile(char* name, bool saveOrLoad) { GBAMPSaveFile::~GBAMPSaveFile() { flushSaveBuffer(); if (handle) DS::std_fclose(handle); + consolePrintf("Closed file\n"); } uint32 GBAMPSaveFile::read(void *buf, uint32 size) { @@ -57,7 +58,7 @@ void GBAMPSaveFile::skip(uint32 bytes) { void GBAMPSaveFile::flushSaveBuffer() { if (bufferPos != 0) { - consolePrintf("Flushing %d bytes from %x\n", bufferPos, buffer); +// consolePrintf("Flushing %d bytes from %x\n", bufferPos, buffer); flushed += bufferPos; DS::std_fwrite(buffer, 1, bufferPos, handle); bufferPos = 0; @@ -174,8 +175,10 @@ void GBAMPSaveFileManager::listSavefiles(char const* prefix, bool* marks, int nu char path[128]; DS::std_cwd((char *) getSavePath()); + + consolePrintf("Save path: %s\n", getSavePath()); - int fileType = FAT_FindFirstFile(name); + int fileType = FAT_FindFirstFileLFN(name); for (int r = 0; r < num; r++) { marks[r] = false; @@ -192,17 +195,17 @@ void GBAMPSaveFileManager::listSavefiles(char const* prefix, bool* marks, int nu sprintf(str, "%s%02d", prefix, r); -// consolePrintf("%s != %s", str, name); + consolePrintf("%s != %s", str, name); if (!stricmp(str, name)) { marks[r] = true; -// consolePrintf("Matched %d", r); + consolePrintf("Matched %d", r); } } } - } while ((fileType = FAT_FindNextFile(name))); + } while ((fileType = FAT_FindNextFileLFN(name))); FAT_chdir("/"); } diff --git a/backends/platform/ds/arm9/source/gbampsave.h b/backends/platform/ds/arm9/source/gbampsave.h index 1580533f66..c7d9732d4c 100644 --- a/backends/platform/ds/arm9/source/gbampsave.h +++ b/backends/platform/ds/arm9/source/gbampsave.h @@ -37,7 +37,7 @@ class GBAMPSaveFile : public Common::InSaveFile, public Common::OutSaveFile { public: GBAMPSaveFile(char* name, bool saveOrLoad); - ~GBAMPSaveFile(); + virtual ~GBAMPSaveFile(); virtual uint32 read(void *buf, uint32 size); virtual uint32 write(const void *buf, uint32 size); diff --git a/backends/platform/ds/arm9/source/osystem_ds.cpp b/backends/platform/ds/arm9/source/osystem_ds.cpp index cad6ad6b78..32eafe1af7 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.cpp +++ b/backends/platform/ds/arm9/source/osystem_ds.cpp @@ -37,6 +37,7 @@ #include "common/str.h" #include "cdaudio.h" #include "graphics/surface.h" +#include "touchkeyboard.h" OSystem_DS* OSystem_DS::_instance = NULL; @@ -138,9 +139,12 @@ void OSystem_DS::setPalette(const byte *colors, uint start, uint num) { green >>= 3; blue >>= 3; - BG_PALETTE[r] = red | (green << 5) | (blue << 10); - if (!DS::getKeyboardEnable()) { - BG_PALETTE_SUB[r] = red | (green << 5) | (blue << 10); +// if (r != 255) + { + BG_PALETTE[r] = red | (green << 5) | (blue << 10); + if (!DS::getKeyboardEnable()) { + BG_PALETTE_SUB[r] = red | (green << 5) | (blue << 10); + } } // if (num == 16) consolePrintf("pal:%d r:%d g:%d b:%d\n", r, red, green, blue); @@ -173,8 +177,8 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int u16* src = (u16 *) buf; if (DS::getKeyboardEnable()) { - for (int dy = y; dy < y + h; dy++) - { + + for (int dy = y; dy < y + h; dy++) { u16* dest = bg + (dy << 8) + (x >> 1); DC_FlushRange(src, w << 1); @@ -185,8 +189,7 @@ void OSystem_DS::copyRectToScreen(const byte *buf, int pitch, int x, int y, int } } else { - for (int dy = y; dy < y + h; dy++) - { + for (int dy = y; dy < y + h; dy++) { u16* dest1 = bg + (dy << 8) + (x >> 1); u16* dest2 = bgSub + (dy << 8) + (x >> 1); @@ -294,6 +297,7 @@ int16 OSystem_DS::getOverlayWidth() bool OSystem_DS::showMouse(bool visible) { + DS::setShowCursor(visible); return true; } @@ -302,7 +306,7 @@ void OSystem_DS::warpMouse(int x, int y) } void OSystem_DS::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor, int targetCursorScale) { - DS::setCursorIcon(buf, w, h, keycolor); + DS::setCursorIcon(buf, w, h, keycolor, hotspotX, hotspotY); } void OSystem_DS::addEvent(Common::Event& e) { @@ -323,11 +327,11 @@ bool OSystem_DS::pollEvent(Common::Event &event) event.kbd.ascii = 0; event.kbd.keycode = 0; event.kbd.flags = 0; - consolePrintf("type: %d\n", event.type); +// consolePrintf("type: %d\n", event.type); return false; } else { event = eventQueue[eventNum++]; - consolePrintf("type: %d\n", event.type); +// consolePrintf("type: %d\n", event.type); return true; } } @@ -474,36 +478,25 @@ Common::SaveFileManager* OSystem_DS::getSavefileManager() } } -Graphics::Surface *OSystem_DS::lockScreen() { - // For now, we create a full temporary screen surface, to which we copy the - // the screen content. Later unlockScreen will copy everything back. - // Not very nice nor efficient, but at least works, and is not worse - // than in the bad old times where we used grabRawScreen + copyRectToScreen. - - _framebuffer.create(DS::getGameWidth(), DS::getGameHeight(), 1); +bool OSystem_DS::grabRawScreen(Graphics::Surface* surf) { + surf->create(DS::getGameWidth(), DS::getGameHeight(), 1); // Ensure we copy using 16 bit quantities due to limitation of VRAM addressing + size_t imageStrideInBytes = DS::isCpuScalerEnabled()? DS::getGameWidth() : 512; + size_t imageStrideInWords = imageStrideInBytes / 2; u16* image = (u16 *) DS::get8BitBackBuffer(); for (int y = 0; y < DS::getGameHeight(); y++) { - DC_FlushRange(image + (y << 8), DS::getGameWidth()); + DC_FlushRange(image + (y * imageStrideInWords), DS::getGameWidth()); for (int x = 0; x < DS::getGameWidth() >> 1; x++) { - *(((u16 *) (_framebuffer.pixels)) + y * (DS::getGameWidth() >> 1) + x) = image[y << 8 + x]; + *(((u16 *) (surf->pixels)) + y * (DS::getGameWidth() >> 1) + x) = image[y * imageStrideInWords + x]; } } - return &_framebuffer; -} - -void OSystem_DS::unlockScreen() { - // Copy temp framebuffer back to screen - copyRectToScreen((byte *)_framebuffer.pixels, _framebuffer.pitch, 0, 0, _framebuffer.w, _framebuffer.h); - - // Free memory - _framebuffer.free(); + return true; } void OSystem_DS::setFocusRectangle(const Common::Rect& rect) { @@ -515,6 +508,18 @@ void OSystem_DS::clearFocusRectangle() { } +void OSystem_DS::addAutoComplete(const char *word) { + DS::addAutoComplete((char *) word); +} + +void OSystem_DS::clearAutoComplete() { + DS::clearAutoComplete(); +} + +void OSystem_DS::setCharactersEntered(int count) { + DS::setCharactersEntered(count); +} + OSystem *OSystem_DS_create() { return new OSystem_DS(); } diff --git a/backends/platform/ds/arm9/source/osystem_ds.h b/backends/platform/ds/arm9/source/osystem_ds.h index 58b940af2c..d943a362ca 100644 --- a/backends/platform/ds/arm9/source/osystem_ds.h +++ b/backends/platform/ds/arm9/source/osystem_ds.h @@ -41,11 +41,12 @@ class DSTimerManager : public DefaultTimerManager { class OSystem_DS : public OSystem { public: + static OSystem_DS *instance() { return _instance; } int eventNum; int lastPenFrame; - Common::Event eventQueue[64]; + Common::Event eventQueue[96]; int queuePos; DSSaveFileManager saveManager; @@ -53,9 +54,8 @@ public: DSAudioMixer* _mixer; DSTimerManager* _timer; - Graphics::Surface _framebuffer; - static OSystem_DS* _instance; + typedef void (*SoundProc)(void *param, byte *buf, int len); typedef int (*TimerProc)(int interval); @@ -129,8 +129,7 @@ public: void addEvent(Common::Event& e); bool isEventQueueEmpty() { return queuePos == 0; } - virtual Graphics::Surface *lockScreen(); - virtual void unlockScreen(); + virtual bool grabRawScreen(Graphics::Surface* surf); virtual void setFocusRectangle(const Common::Rect& rect); @@ -141,6 +140,14 @@ public: virtual Audio::Mixer* getMixer() { return _mixer; } virtual Common::TimerManager* getTimerManager() { return _timer; } static int timerHandler(int t); + + + virtual void addAutoComplete(const char *word); + virtual void clearAutoComplete(); + virtual void setCharactersEntered(int count); + + + }; static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { @@ -162,9 +169,4 @@ void OSystem_DS::colorToRGB(OverlayColor color, uint8 &r, uint8 &g, uint8 &b) //consolePrintf("coltorgb\n"); } -namespace DS -{ -bool isCpuScalerEnabled(); -} - #endif diff --git a/backends/platform/ds/arm9/source/touchkeyboard.cpp b/backends/platform/ds/arm9/source/touchkeyboard.cpp index 8f7af668d8..26f03ca9d1 100644 --- a/backends/platform/ds/arm9/source/touchkeyboard.cpp +++ b/backends/platform/ds/arm9/source/touchkeyboard.cpp @@ -23,6 +23,7 @@ #include "touchkeyboard.h" #include "keyboard_raw.h" #include "keyboard_pal_raw.h" +#include "8x8font_tga_raw.h" #include "dsmain.h" #include "osystem_ds.h" @@ -127,11 +128,22 @@ int keyboardY; int mapBase; int tileBase; +u16* baseAddress; + bool shiftState; bool capsLockState; bool closed; +char autoCompleteWord[NUM_WORDS][32]; +int autoCompleteCount; + +char autoCompleteBuffer[128]; + +int selectedCompletion = -1; +int charactersEntered = 0; + + void restoreVRAM(int tileBase, int mapBase, u16* saveSpace) { /* for (int r = 0; r < 32 * 32; r++) { ((u16 *) SCREEN_BASE_BLOCK_SUB(mapBase))[r] = *saveSpace++; @@ -159,6 +171,26 @@ void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) { BG_PALETTE_SUB[r] = ((u16 *) (keyboard_pal_raw))[r]; } + // this is the font + for (int tile = 0; tile < 94; tile++) { + + u16* tileAddr = (u16 *) (CHAR_BASE_BLOCK_SUB(tileBase) + (8192 + (tile * 32))); + u8* src = ((u8 *) (_8x8font_tga_raw)) + 18 + tile * 8; + + for (int y = 0 ; y < 8; y++) { + for (int x = 0; x < 2; x++) { + *(tileAddr + (y * 2) + x) =(*(src + (y * 752) + (x * 4) + 0) & 0x0F) + | ((*(src + (y * 752) + (x * 4) + 1) & 0x0F) << 4) + | ((*(src + (y * 752) + (x * 4) + 2) & 0x0F) << 8) + | ((*(src + (y * 752) + (x * 4) + 3) & 0x0F) << 12); + + } + } + } + + + + for (int r = 0; r < 16; r++) { int col = ((u16 *) (keyboard_pal_raw))[r]; @@ -167,17 +199,19 @@ void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) { int blue = (col & 0x7C00) >> 10; red = (red * 8) / 16; - green = (green * 8) / 16; + green = (green * 24) / 16; blue = (blue * 8) / 16; + + if (green > 31) green = 31; BG_PALETTE_SUB[16 + r] = red | (green << 5) | (blue << 10); } keyboardX = -2; - keyboardY = 2; + keyboardY = 1; - mapBase = mapBase; - tileBase = tileBase; + DS::mapBase = mapBase; + DS::tileBase = tileBase; shiftState = false; capsLockState = false; @@ -186,6 +220,7 @@ void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) { int y = keyboardY; u16* base = ((u16 *) SCREEN_BASE_BLOCK_SUB(mapBase)); + baseAddress = base; for (int r = 0; r < DS_NUM_KEYS; r++) { base[(y + keys[r].y) * 32 + x + keys[r].x] = keys[r].keyNum * 2; @@ -198,6 +233,36 @@ void drawKeyboard(int tileBase, int mapBase, u16* saveSpace) { } closed = false; + clearAutoComplete(); +} + +void drawAutoComplete() { + + for (int y = 12; y < 24; y++) { + for (int x = 0; x < 32; x++) { + baseAddress[y * 32 + x] = 127; + } + } + + + for (int r = 0; r < autoCompleteCount; r++) { + int y = 12 + (r % 6) * 2; + int x = 0 + ((r / 6) * 16); + + for (int p = 0; p < strlen(autoCompleteWord[r]); p++) { + char c = autoCompleteWord[r][p]; + + int tile = c - 32 + 255; + + if (selectedCompletion == r) { + tile |= 0x1000; + } + + baseAddress[y * 32 + x + p] = tile; + + + } + } } bool getKeyboardClosed() { @@ -220,13 +285,106 @@ void setKeyHighlight(int key, bool highlight) { } } +void addAutoComplete(char* word) { + if (autoCompleteCount == NUM_WORDS) return; + strcpy(&autoCompleteWord[autoCompleteCount++][0], word); + drawAutoComplete(); +} + +void setCharactersEntered(int count) { + charactersEntered = count; +} + +void clearAutoComplete() { + autoCompleteCount = 0; + selectedCompletion = -1; + drawAutoComplete(); +} + +void typeCompletion(int current) { + Common::Event event; + OSystem_DS* system = OSystem_DS::instance(); + + strcat(autoCompleteBuffer, &autoCompleteWord[current][charactersEntered]); + strcat(autoCompleteBuffer, " "); + +/* consolePrintf("Typing word: %s\n", autoCompleteWord[current]); + + for (int r = charactersEntered; r < strlen(autoCompleteWord[current]); r++) { + event.kbd.keycode = autoCompleteWord[current][r]; + event.kbd.ascii = autoCompleteWord[current][r]; + event.type = Common::EVENT_KEYDOWN; + event.kbd.flags = 0; + system->addEvent(event); + + event.type = Common::EVENT_KEYUP; + system->addEvent(event); + } + + event.kbd.keycode = ' '; + event.kbd.ascii = ' '; + + event.type = Common::EVENT_KEYDOWN; + system->addEvent(event); + + event.type = Common::EVENT_KEYUP; + system->addEvent(event);*/ +} + +void updateTypeEvents() +{ + if (autoCompleteBuffer[0] != '\0') + { + Common::Event event; + OSystem_DS* system = OSystem_DS::instance(); + + event.kbd.keycode = autoCompleteBuffer[0]; + event.kbd.ascii = autoCompleteBuffer[0]; + event.type = Common::EVENT_KEYDOWN; + event.kbd.flags = 0; + system->addEvent(event); + + event.type = Common::EVENT_KEYUP; + system->addEvent(event); + + for (int r = 0; r < strlen(autoCompleteBuffer); r++) + { + autoCompleteBuffer[r] = autoCompleteBuffer[r + 1]; + } + } +} + + void addKeyboardEvents() { + updateTypeEvents(); + if (DS::getPenDown()) { int x = IPC->touchXpx; int y = IPC->touchYpx; - int tx = (x >> 3) - keyboardX; - int ty = (y >> 3) - keyboardY; + int tx = (x >> 3); + int ty = (y >> 3); + + if (ty >= 12) { + int current = -1; + + if (tx < 12) { + current = (ty - 12) / 2; + } else { + current = 6 + (ty - 12) / 2; + } + + if (selectedCompletion == current) { + typeCompletion(current); + } else { + selectedCompletion = current; + } + + drawAutoComplete(); + } + + tx -= keyboardX; + ty -= keyboardY; // consolePrintf("x=%d y=%d\n", tx, ty); @@ -241,8 +399,14 @@ void addKeyboardEvents() { // Close button DS::closed = true; } else if ((keys[r].character >= '0') && (keys[r].character <= '9')) { - event.kbd.ascii = keys[r].character; - event.kbd.keycode = 0; + + if (!DS::shiftState) { + event.kbd.ascii = keys[r].character; + event.kbd.keycode = 0; + } else { + event.kbd.keycode = SDLK_F1 - (keys[r].character - '1'); + event.kbd.ascii = 0; + } } else if ((keys[r].character >= 'A') && (keys[r].character <= 'Z')) { diff --git a/backends/platform/ds/arm9/source/touchkeyboard.h b/backends/platform/ds/arm9/source/touchkeyboard.h index e8f5fda37e..42051a1f11 100644 --- a/backends/platform/ds/arm9/source/touchkeyboard.h +++ b/backends/platform/ds/arm9/source/touchkeyboard.h @@ -25,11 +25,18 @@ namespace DS { +static const int NUM_WORDS = 12; + + void drawKeyboard(int tileBase, int mapBase, u16* saveSpace); void restoreVRAM(int tileBase, int mapBase, u16* saveSpace); void addKeyboardEvents(); bool getKeyboardClosed(); +void addAutoComplete(char* word); +void clearAutoComplete(); +void setCharactersEntered(int count); + } #endif diff --git a/backends/platform/ds/arm9/source/wordcompletion.cpp b/backends/platform/ds/arm9/source/wordcompletion.cpp new file mode 100644 index 0000000000..a73656ea61 --- /dev/null +++ b/backends/platform/ds/arm9/source/wordcompletion.cpp @@ -0,0 +1,67 @@ +#include "wordcompletion.h" +#include "engines/agi/agi.h" +#include "osystem_ds.h" + +#ifndef DISABLE_AGI + +namespace DS { + +void findWordCompletions(char* input) { + int start = 0; + for (int r = strlen(input) - 1; r>0; r--) { + if (input[r] == ' ') { + start = r + 1; + break; + } + } + + char word[32]; + strcpy(word, &input[start]); + + int fchr = word[0] - 'a'; + int len = strlen(word); + + OSystem_DS* system = (OSystem_DS *) g_system; + system->clearAutoComplete(); + system->setCharactersEntered(strlen(word)); + + if (strlen(word) == 0) { + return; + } + + uint8 *wordList = Agi::AgiEngine::getWordsData(); + uint8 *wordListEnd = Agi::AgiEngine::getWordsData() + Agi::AgiEngine::getWordsDataSize(); + + /* Get the offset to the first word beginning with the + * right character + */ + wordList += READ_BE_UINT16(wordList + 2 * fchr); + + char currentWord[32]; + + + while (wordList < wordListEnd) { + int pos = *wordList++; // Number of chars to keep from previous word + + if (wordList == wordListEnd) + break; + + char c; + do { + c = *wordList++; + currentWord[pos++] = (~c) & 0x7F; + } while ((c & 0x80) == 0); // Top bit indicates end of word + currentWord[pos++] = '\0'; + + if (!strncmp(currentWord, word, strlen(word))) { + system->addAutoComplete(currentWord); + } + + wordList += 2; // Skip the two byte word id. + + } + +} + +} +#endif diff --git a/backends/platform/ds/arm9/source/wordcompletion.h b/backends/platform/ds/arm9/source/wordcompletion.h new file mode 100644 index 0000000000..b0d43713cc --- /dev/null +++ b/backends/platform/ds/arm9/source/wordcompletion.h @@ -0,0 +1,8 @@ + + + +namespace DS { + +extern void findWordCompletions(char* input); + +}
\ No newline at end of file diff --git a/backends/platform/ds/arm9/source/zipreader.cpp b/backends/platform/ds/arm9/source/zipreader.cpp index 59f695ebce..0c86bd97ae 100644 --- a/backends/platform/ds/arm9/source/zipreader.cpp +++ b/backends/platform/ds/arm9/source/zipreader.cpp @@ -31,7 +31,7 @@ ZipFile::ZipFile() { // Locate a zip file in cartridge memory space - consolePrintf("ZIP file check..."); +// consolePrintf("ZIP file check..."); char* p = (char *) ZF_SEARCH_START; bool found = false; @@ -52,9 +52,9 @@ ZipFile::ZipFile() { } if (_zipFile) { - consolePrintf("Ok!\n"); + consolePrintf("ZIP File found Ok!\n"); } else { - consolePrintf("Not in use!\n"); +// consolePrintf("Not in use!\n"); return; } diff --git a/backends/platform/gp2x/build/build.sh b/backends/platform/gp2x/build/build.sh index dc2f56cb18..1ea77f4937 100644 --- a/backends/platform/gp2x/build/build.sh +++ b/backends/platform/gp2x/build/build.sh @@ -10,6 +10,7 @@ export CXX=arm-open2x-linux-g++ export CC=arm-open2x-linux-gcc export CXXFLAGS=-march=armv4t export LDFLAGS=-static +export ASFLAGS=-mfloat-abi=soft cd ../../../.. diff --git a/backends/platform/gp2x/build/bundle.sh b/backends/platform/gp2x/build/bundle.sh index 93ae45f0e3..526742e2e7 100644 --- a/backends/platform/gp2x/build/bundle.sh +++ b/backends/platform/gp2x/build/bundle.sh @@ -19,6 +19,7 @@ cp ./scummvm.gpe ./scummvm-gp2x-`date '+%Y-%m-%d'`/ cp ./scummvm.png ./scummvm-gp2x-`date '+%Y-%m-%d'`/ cp ./README-GP2X.html ./scummvm-gp2x-`date '+%Y-%m-%d'`/ cp ./README-GP2X ./scummvm-gp2x-`date '+%Y-%m-%d'`/ +cp ./mmuhack.o ./scummvm-gp2x-`date '+%Y-%m-%d'`/ cp ../../../../scummvm.gp2x ./scummvm-gp2x-`date '+%Y-%m-%d'`/ cp ../../../../AUTHORS ./scummvm-gp2x-`date '+%Y-%m-%d'`/ cp ../../../../README ./scummvm-gp2x-`date '+%Y-%m-%d'`/ @@ -27,10 +28,22 @@ cp ../../../../COPYRIGHT ./scummvm-gp2x-`date '+%Y-%m-%d'`/ cp ../../../../NEWS ./scummvm-gp2x-`date '+%Y-%m-%d'`/ cp ../../../../gui/themes/modern.ini ./scummvm-gp2x-`date '+%Y-%m-%d'`/ cp ../../../../gui/themes/modern.zip ./scummvm-gp2x-`date '+%Y-%m-%d'`/ - +cp ../../../../dists/pred.dic ./scummvm-gp2x-`date '+%Y-%m-%d'`/ echo Making Stripped GPE. arm-open2x-linux-strip ./scummvm-gp2x-`date '+%Y-%m-%d'`/scummvm.gp2x echo Building ZIP bundle. -echo You should have a "scummvm-gp2x-`date '+%Y-%m-%d'`.zip" for the GP2X port ready to go. +if [ -f /usr/bin/zip ] + then + rm ./"gp2xkernel-open2x-`date '+%Y-%m-%d'`.zip" + cd "scummvm-gp2x-`date '+%Y-%m-%d'`" + zip -r -9 "../scummvm-gp2x-`date '+%Y-%m-%d'`.zip" * + echo You should have a "scummvm-gp2x-`date '+%Y-%m-%d'`.zip" for the GP2X port ready to go. + cd .. + rm -R ./"scummvm-gp2x-`date '+%Y-%m-%d'`" + else + echo - /usr/bin/zip not found, ZIP bundle not created. + echo All included files can also be found in ./"scummvm-gp2x-`date '+%Y-%m-%d'`" + echo - Please use you preferred archive tool to bundle these files. +fi diff --git a/backends/platform/gp2x/build/config.sh b/backends/platform/gp2x/build/config.sh index 193210a1b8..f899c7665a 100644 --- a/backends/platform/gp2x/build/config.sh +++ b/backends/platform/gp2x/build/config.sh @@ -17,6 +17,6 @@ export DEFINES=-DNDEBUG # Edit the configure line to suit. cd ../../../.. -./configure --backend=gp2x --disable-mt32emu --host=gp2x --disable-mpeg2 --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 +./configure --backend=gp2x --disable-mt32emu --host=gp2x --disable-flac --disable-nasm --disable-hq-scalers --with-sdl-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6/bin --with-mpeg2-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-tremor --with-tremor-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-zlib --with-zlib-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 --enable-mad --with-mad-prefix=/opt/open2x/gcc-4.1.1-glibc-2.3.6 echo Generating config for GP2X complete. Check for errors. diff --git a/backends/platform/gp2x/build/mmuhack.o b/backends/platform/gp2x/build/mmuhack.o Binary files differnew file mode 100644 index 0000000000..475f4a54ae --- /dev/null +++ b/backends/platform/gp2x/build/mmuhack.o diff --git a/backends/platform/gp2x/events.cpp b/backends/platform/gp2x/events.cpp index 72b188afd2..ef39ab333e 100644 --- a/backends/platform/gp2x/events.cpp +++ b/backends/platform/gp2x/events.cpp @@ -72,7 +72,7 @@ static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode) return key; } else if (unicode) { return unicode; - } else if (key >= 'a' && key <= 'z' && mod & KMOD_SHIFT) { + } else if (key >= 'a' && key <= 'z' && (mod & KMOD_SHIFT)) { return key & ~0x20; } else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) { return 0; @@ -168,17 +168,10 @@ void OSystem_GP2X::handleKbdMouse() { static byte SDLModToOSystemKeyFlags(SDLMod mod) { byte b = 0; -#ifdef LINUPY - // Yopy has no ALT key, steal the SHIFT key - // (which isn't used much anyway) - if (mod & KMOD_SHIFT) - b |= Common::KBD_ALT; -#else if (mod & KMOD_SHIFT) b |= Common::KBD_SHIFT; if (mod & KMOD_ALT) b |= Common::KBD_ALT; -#endif if (mod & KMOD_CTRL) b |= Common::KBD_CTRL; @@ -246,7 +239,7 @@ void OSystem_GP2X::moveStick() { //int GP2X_BUTTON_STATE_B = FALSE; //int GP2X_BUTTON_STATE_Y = FALSE; //int GP2X_BUTTON_STATE_X = FALSE; - int GP2X_BUTTON_STATE_L = FALSE; + int GP2X_BUTTON_STATE_L = FALSE; //int GP2X_BUTTON_STATE_R = FALSE; //int GP2X_BUTTON_STATE_START = FALSE; //int GP2X_BUTTON_STATE_SELECT = FALSE; @@ -306,6 +299,7 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) { GP2X_BUTTON_VOLUP & GP2X_BUTTON_VOLDOWN 0 (For Monkey 2 CP) GP2X_BUTTON_L & GP2X_BUTTON_SELECT Common::EVENT_QUIT (Calls Sync() to make sure SD is flushed) GP2X_BUTTON_L & GP2X_BUTTON_Y Toggles setZoomOnMouse() for larger then 320*240 games to scale to the point + raduis. + GP2X_BUTTON_L & GP2X_BUTTON_A Common::EVENT_PREDICTIVE_DIALOG for predictive text entry box (AGI games) */ while(SDL_PollEvent(&ev)) { @@ -341,45 +335,13 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) { break; } - // Ctrl-m toggles mouse capture - //if (b == Common::KBD_CTRL && ev.key.keysym.sym == 'm') { - // toggleMouseGrab(); - // break; - //} - -//#ifdef MACOSX -// // On Macintosh', Cmd-Q quits -// if ((ev.key.keysym.mod & KMOD_META) && ev.key.keysym.sym == 'q') { -// event.type = Common::EVENT_QUIT; -// return true; -// } -//#elif defined(UNIX) -// // On other unices, Control-Q quits -// if ((ev.key.keysym.mod & KMOD_CTRL) && ev.key.keysym.sym == 'q') { -// event.type = Common::EVENT_QUIT; -// return true; -// } -//#else -// // Ctrl-z and Alt-X quit -// if ((b == Common::KBD_CTRL && ev.key.keysym.sym == 'z') || (b == Common::KBD_ALT && ev.key.keysym.sym == 'x')) { -// event.type = Common::EVENT_QUIT; -// return true; -// } -//#endif -// -// // Ctrl-Alt-<key> will change the GFX mode -// if ((b & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) { -// -// handleScalerHotkeys(ev.key); -// break; -// } const bool event_complete = remapKey(ev,event); if (event_complete) return true; event.type = Common::EVENT_KEYDOWN; - event.kbd.keycode = ev.key.keysym.sym; + event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode); return true; @@ -392,7 +354,7 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) { return true; event.type = Common::EVENT_KEYUP; - event.kbd.keycode = ev.key.keysym.sym; + event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym; event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode); b = event.kbd.flags = SDLModToOSystemKeyFlags(SDL_GetModState()); @@ -484,8 +446,15 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) { } break; case GP2X_BUTTON_A: + if (GP2X_BUTTON_STATE_L == TRUE) { + event.type = Common::EVENT_PREDICTIVE_DIALOG; + } else { event.kbd.keycode = Common::KEYCODE_PERIOD; event.kbd.ascii = mapKey(SDLK_PERIOD, ev.key.keysym.mod, 0); + } +// event.kbd.keycode = Common::KEYCODE_PERIOD; +// event.kbd.ascii = mapKey(SDLK_PERIOD, ev.key.keysym.mod, 0); + break; case GP2X_BUTTON_Y: if (GP2X_BUTTON_STATE_L == TRUE) { @@ -606,10 +575,6 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) { axis = 0; if ( ev.jaxis.axis == JOY_XAXIS) { -#ifdef JOY_ANALOG - _km.x_vel = axis/2000; - _km.x_down_count = 0; -#else if (axis != 0) { _km.x_vel = (axis > 0) ? 1:-1; _km.x_down_count = 1; @@ -617,7 +582,6 @@ bool OSystem_GP2X::pollEvent(Common::Event &event) { _km.x_vel = 0; _km.x_down_count = 0; } -#endif } else if (ev.jaxis.axis == JOY_YAXIS) { #ifndef JOY_INVERT_Y diff --git a/backends/platform/gp2x/gp2x-common.h b/backends/platform/gp2x/gp2x-common.h index 68f2fb997e..a48239222b 100644 --- a/backends/platform/gp2x/gp2x-common.h +++ b/backends/platform/gp2x/gp2x-common.h @@ -181,7 +181,6 @@ public: virtual bool setGraphicsMode(int mode); virtual int getGraphicsMode() const; - //virtual void setWindowCaption(const char *caption); virtual bool openCD(int drive); virtual int getOutputSampleRate() const; @@ -267,6 +266,9 @@ protected: int _mode; int _transactionMode; bool _fullscreen; + + bool _screenIsLocked; + Graphics::Surface _framebuffer; /** Current video mode flags (see DF_* constants) */ uint32 _modeFlags; @@ -382,14 +384,13 @@ protected: /** Set the position of the virtual mouse cursor. */ void setMousePos(int x, int y); - virtual void fillMouseEvent(Common::Event &event, int x, int y); - //void toggleMouseGrab(); + void fillMouseEvent(Common::Event &event, int x, int y); - virtual void internUpdateScreen(); + void internUpdateScreen(); - virtual void loadGFXMode(); - virtual void unloadGFXMode(); - virtual void hotswapGFXMode(); + void loadGFXMode(); + void unloadGFXMode(); + void hotswapGFXMode(); void setFullscreenMode(bool enable); void setAspectRatioCorrection(bool enable); diff --git a/backends/platform/gp2x/gp2x-hw.cpp b/backends/platform/gp2x/gp2x-hw.cpp index d1b6f80a1e..d322aa5d08 100644 --- a/backends/platform/gp2x/gp2x-hw.cpp +++ b/backends/platform/gp2x/gp2x-hw.cpp @@ -33,17 +33,20 @@ #include "gp2x-common.h" #include "gp2x-hw.h" +#include "gp2x-mem.h" -// Linux includes to let us goof about with the system. +// Linux includes to let us goof about with the system in a 'standard' way. +#include <fcntl.h> +#include <pthread.h> +#include <signal.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> #include <sys/mman.h> #include <sys/ioctl.h> #include <sys/soundcard.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -static unsigned long gp2x_dev[8]={0,0,0,0,0,0,0,0};//, gp2x_ticks_per_second; -static volatile unsigned short *gp2x_memregs; +#include <sys/time.h> +#include <unistd.h> /* system registers */ static struct @@ -67,19 +70,27 @@ void GP2X_device_init() { void GP2X_device_deinit() { // Close devices - if (gp2x_dev[0]) close(gp2x_dev[0]); - if (gp2x_dev[1]) close(gp2x_dev[1]); - if (gp2x_dev[2]) close(gp2x_dev[2]); - - MEM_REG[0x91c>>1]=system_reg.SYSCSETREG; - MEM_REG[0x910>>1]=system_reg.FPLLVSETREG; - MEM_REG[0x3B40>>1]=system_reg.DUALINT920; - MEM_REG[0x3B42>>1]=system_reg.DUALINT940; - MEM_REG[0x3B48>>1]=system_reg.DUALCTRL940; - MEM_REG[0x904>>1]=system_reg.SYSCLKENREG; - MEM_REG[0x924>>1]=dispclockdiv; -} + { + int i; + for(i=0;i<8;i++) + { + if(gp2x_dev[i]) + { + close(gp2x_dev[i]); + } + } + } + + MEM_REG[0x91c>>1] = system_reg.SYSCSETREG; + MEM_REG[0x910>>1] = system_reg.FPLLVSETREG; + MEM_REG[0x3B40>>1] = system_reg.DUALINT920; + MEM_REG[0x3B42>>1] = system_reg.DUALINT940; + MEM_REG[0x3B48>>1] = system_reg.DUALCTRL940; + MEM_REG[0x904>>1] = system_reg.SYSCLKENREG; + MEM_REG[0x924>>1] = dispclockdiv; + unpatchMMU(); +} // Vairous mixer level fudges. // TODO: Clean up and merge quick hacks. diff --git a/backends/platform/gp2x/gp2x-hw.h b/backends/platform/gp2x/gp2x-hw.h index bb681154d7..0427698bc4 100644 --- a/backends/platform/gp2x/gp2x-hw.h +++ b/backends/platform/gp2x/gp2x-hw.h @@ -65,7 +65,6 @@ extern void GP2X_mixer_move_volume(int); extern void GP2X_setCpuspeed(unsigned int cpuspeed); extern int GP2X_getBattLevel(); - extern void save_system_regs(void); /* save some registers */ extern void set_display_clock_div(unsigned div); extern void set_FCLK(unsigned MHZ); /* adjust the clock frequency (in Mhz units) */ diff --git a/backends/platform/gp2x/gp2x-mem.c b/backends/platform/gp2x/gp2x-mem.c index f129deb783..1c2c1562a8 100644 --- a/backends/platform/gp2x/gp2x-mem.c +++ b/backends/platform/gp2x/gp2x-mem.c @@ -39,20 +39,22 @@ #include "gp2x-mem.h" -void InitRam (void) -{ - if(!gp2x_dev) - { - gp2x_dev = open("/dev/mem", O_RDWR); - gp2x_ram = (unsigned short *)mmap(0, 0x10000, 3, 1, gp2x_dev, 0x03000000); - gp2x_memregs = (unsigned short *)mmap(0, 0x10000, 3, 1, gp2x_dev, 0xc0000000); - } -} - -void CloseRam (void) -{ - if(gp2x_dev) close(gp2x_dev); -} +char uname[256]; + +//void InitRam (void) +//{ +// if(!gp2x_dev) +// { +// gp2x_dev = open("/dev/mem", O_RDWR); +// gp2x_ram = (unsigned short *)mmap(0, 0x10000, 3, 1, gp2x_dev, 0x03000000); +// gp2x_memregs = (unsigned short *)mmap(0, 0x10000, 3, 1, gp2x_dev, 0xc0000000); +// } +//} + +//void CloseRam (void) +//{ +// if(gp2x_dev) close(gp2x_dev); +//} /* ****** [BEGIN] Squidge's MMU hack code ****** @@ -201,34 +203,30 @@ int hackpgtable (void) // do this in user mode, so we have to patch the kernel to get it to run it for us in supervisor mode. We dothis // at the moment by overwriting the sys_newuname function and then calling it. - lseek (gp2x_dev, 0x6ec00, SEEK_SET); // fixme: We should ask the kernel for this address rather than assuming it... - read (gp2x_dev, &oldc1, 4); - read (gp2x_dev, &oldc2, 4); - read (gp2x_dev, &oldc3, 4); - read (gp2x_dev, &oldc4, 4); - - printf ("0:%08X %08X - %08X %08X\n", oldc1, oldc2, newc1, newc2); - + lseek (gp2x_dev[2], 0x6ec00, SEEK_SET); // fixme: We should ask the kernel for this address rather than assuming it... + read (gp2x_dev[2], &oldc1, 4); + read (gp2x_dev[2], &oldc2, 4); + read (gp2x_dev[2], &oldc3, 4); + read (gp2x_dev[2], &oldc4, 4); + //printf ("0:%08X %08X - %08X %08X\n", oldc1, oldc2, newc1, newc2); + //printf ("point1 %d\n",a); - printf ("point1 %d\n",a); do { - lseek (gp2x_dev, 0x6ec00, SEEK_SET); - a+=write (gp2x_dev, &newc1, 4); - a+=write (gp2x_dev, &newc2, 4); + lseek (gp2x_dev[2], 0x6ec00, SEEK_SET); + a+=write (gp2x_dev[2], &newc1, 4); + a+=write (gp2x_dev[2], &newc2, 4); SDL_Delay(200); try++; - ttb = myuname(name); - printf ("2:%08X try %d\n", ttb,try); + ttb = myuname(uname); + //printf ("2:%08X try %d\n", ttb,try); } while (ttb==0 && try<4); + lseek (gp2x_dev[2], 0x6ec00, SEEK_SET); + a+=write (gp2x_dev[2], &oldc1, 4); + a+=write (gp2x_dev[2], &oldc2, 4); - - lseek (gp2x_dev, 0x6ec00, SEEK_SET); - a+=write (gp2x_dev, &oldc1, 4); - a+=write (gp2x_dev, &oldc2, 4); - - printf ("2:%08X %d\n", ttb,a); + //printf ("2:%08X %d\n", ttb,a); if (ttb!=0) { @@ -243,28 +241,28 @@ int hackpgtable (void) unsigned int tlbc3 = 0xee080f17; // mcr 15, 0, r0, cr8, cr7, 0 unsigned int tlbc4 = 0xe1a0f00e; // mov pc, lr - lseek (gp2x_dev, 0x6ec00, SEEK_SET); - write (gp2x_dev, &tlbc1, 4); - write (gp2x_dev, &tlbc2, 4); - write (gp2x_dev, &tlbc3, 4); - write (gp2x_dev, &tlbc4, 4); + lseek (gp2x_dev[2], 0x6ec00, SEEK_SET); + write (gp2x_dev[2], &tlbc1, 4); + write (gp2x_dev[2], &tlbc2, 4); + write (gp2x_dev[2], &tlbc3, 4); + write (gp2x_dev[2], &tlbc4, 4); SDL_Delay(200); - ttx = myuname(name); + ttx = myuname(uname); printf ("Return from uname: %08X\n", ttx); - lseek (gp2x_dev, 0x6ec00, SEEK_SET); - write (gp2x_dev, &oldc1, 4); - write (gp2x_dev, &oldc2, 4); - write (gp2x_dev, &oldc3, 4); - write (gp2x_dev, &oldc4, 4); - lseek (gp2x_dev, 0x0, SEEK_SET); + lseek (gp2x_dev[2], 0x6ec00, SEEK_SET); + write (gp2x_dev[2], &oldc1, 4); + write (gp2x_dev[2], &oldc2, 4); + write (gp2x_dev[2], &oldc3, 4); + write (gp2x_dev[2], &oldc4, 4); + lseek (gp2x_dev[2], 0x0, SEEK_SET); return 0; } - lseek (gp2x_dev, 0x0, SEEK_SET); + lseek (gp2x_dev[2], 0x0, SEEK_SET); return 1; //printf ("Restored contents\n"); @@ -292,10 +290,34 @@ void SetClock (unsigned c) gp2x_memregs[0x910>>1] = v; } -void MMUpatch (void) +void patchMMU (void) { - volatile unsigned int *secbuf = (unsigned int *)malloc (204800); + //volatile unsigned int *secbuf = (unsigned int *)malloc (204800); - // Squidge's MMU hack - hackpgtable(); + printf ("Reconfiguring cached memory regions...\n"); + + //hackpgtable(); + //printf ("Sucess...\n"); + + system("/sbin/rmmod mmuhack"); + system("/sbin/insmod -f mmuhack.o"); + + int mmufd = open("/dev/mmuhack", O_RDWR); + + if(mmufd < 0) + { + printf ("Upper memory uncached (attempt failed, access to upper memory will be slower)...\n"); + } + else + { + printf ("Upper memory cached...\n"); + close(mmufd); + } +} + +void unpatchMMU (void) +{ + printf ("Restoreing cached memory regions...\n"); + system("/sbin/rmmod mmuhack"); + return 1; } diff --git a/backends/platform/gp2x/gp2x-mem.h b/backends/platform/gp2x/gp2x-mem.h index bf2d050623..b4df7b3a00 100644 --- a/backends/platform/gp2x/gp2x-mem.h +++ b/backends/platform/gp2x/gp2x-mem.h @@ -39,17 +39,20 @@ extern "C" { // Use Squidge's MMU patch rather then myown (his is neater). // The effect if not that great but cacheing the upper RAM is no bad thing (tm) ;). -void InitRam (void); -void CloseRam (void); +//extern void InitRam (void); +//extern void CloseRam (void); // Set ARM920t clock frequency -void SetClock (unsigned c); -void MMUpatch (void); +extern void SetClock (unsigned c); +extern void patchMMU (void); +extern void unpatchMMU (void); #define SYS_CLK_FREQ 7372800 -char name[256]; -unsigned long gp2x_dev; -volatile unsigned short *gp2x_ram, *gp2x_memregs; +//unsigned long gp2x_dev; +//volatile unsigned short *gp2x_ram, *gp2x_memregs; + +static unsigned long gp2x_dev[8]={0,0,0,0,0,0,0,0};//, gp2x_ticks_per_second; +static volatile unsigned short *gp2x_ram, *gp2x_memregs; #ifdef __cplusplus } diff --git a/backends/platform/gp2x/gp2x.cpp b/backends/platform/gp2x/gp2x.cpp index 42a9345762..3cf5df2e3a 100644 --- a/backends/platform/gp2x/gp2x.cpp +++ b/backends/platform/gp2x/gp2x.cpp @@ -60,11 +60,6 @@ static Uint32 timer_handler(Uint32 interval, void *param) { } int main(int argc, char *argv[]) { - - // Setup GP2X upper 32MB caching - //InitRam(); - //MMUpatch(); - extern OSystem *OSystem_GP2X_create(); g_system = OSystem_GP2X_create(); assert(g_system); @@ -82,7 +77,7 @@ OSystem *OSystem_GP2X_create() { void OSystem_GP2X::initBackend() { assert(!_inited); - ConfMan.set("joystick_num", 0); + ConfMan.setInt("joystick_num", 0); int joystick_num = ConfMan.getInt("joystick_num"); uint32 sdlFlags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER; @@ -96,6 +91,7 @@ void OSystem_GP2X::initBackend() { error("Could not initialize SDL: %s", SDL_GetError()); } + SDL_ShowCursor(SDL_DISABLE); // Setup default save path to be workingdir/saves #ifndef PATH_MAX @@ -187,19 +183,10 @@ void OSystem_GP2X::initBackend() { // enable joystick if (joystick_num > -1 && SDL_NumJoysticks() > 0) { - printf("Using joystick: %s\n", SDL_JoystickName(0)); + //printf("Using joystick: %s\n", SDL_JoystickName(0)); _joystick = SDL_JoystickOpen(joystick_num); } - // Initialise any GP2X specific stuff we may want (Volume, Batt Status etc.) - GP2X_device_init(); - - // Set Default hardware mixer volume to a plesent level. - // This is done to 'reset' volume level if set by other apps. - GP2X_mixer_set_volume(70, 70); - - SDL_ShowCursor(SDL_DISABLE); - // Create the savefile manager, if none exists yet (we check for this to // allow subclasses to provide their own). if (_savefile == 0) { @@ -225,6 +212,14 @@ void OSystem_GP2X::initBackend() { // switch. But it's a long term goal to do just that! _timer = new DefaultTimerManager(); _timerID = SDL_AddTimer(10, &timer_handler, _timer); + + // Initialise any GP2X specific stuff we may want (Volume, Batt Status etc.) + GP2X_device_init(); + + // Set Default hardware mixer volume to a plesent level. + // This is done to 'reset' volume level if set by other apps. + GP2X_mixer_set_volume(70, 70); + } OSystem::initBackend(); @@ -321,6 +316,9 @@ void OSystem_GP2X::setFeatureState(Feature f, bool enable) { else _modeFlags &= ~DF_WANT_RECT_OPTIM; break; + case kFeatureDisableKeyFiltering: + // TODO: Extend as more support for this is added to engines. + return; default: break; } diff --git a/backends/platform/gp2x/graphics.cpp b/backends/platform/gp2x/graphics.cpp index c3ed5c627c..1aa7519f86 100644 --- a/backends/platform/gp2x/graphics.cpp +++ b/backends/platform/gp2x/graphics.cpp @@ -29,10 +29,10 @@ */ #include "backends/platform/gp2x/gp2x-common.h" -#include "graphics/scaler.h" #include "common/util.h" #include "graphics/font.h" #include "graphics/fontman.h" +#include "graphics/scaler.h" #include "graphics/surface.h" static const OSystem::GraphicsMode s_supportedGraphicsModes[] = { @@ -236,17 +236,12 @@ void OSystem_GP2X::initSize(uint w, uint h){ } void OSystem_GP2X::loadGFXMode() { - - //enable 320x240 image to fit the 320x240 display area (aka, disable scaling) - //gp2x_video_RGB_setscaling(320,240); - assert(_inited); _forceFull = true; _modeFlags |= DF_UPDATE_EXPAND_1_PIXEL; int hwW, hwH; -#ifndef __MAEMO__ _overlayWidth = _screenWidth * _scaleFactor; _overlayHeight = _screenHeight * _scaleFactor; @@ -258,10 +253,6 @@ void OSystem_GP2X::loadGFXMode() { hwW = _screenWidth * _scaleFactor; hwH = effectiveScreenHeight(); -#else - hwW = _overlayWidth; - hwH = _overlayHeight; -#endif // // Create the surface that contains the 8 bit game data @@ -349,7 +340,6 @@ void OSystem_GP2X::loadGFXMode() { _km.y_max = effectiveScreenHeight() - 1; _km.delay_time = 25; _km.last_time = 0; - } void OSystem_GP2X::unloadGFXMode() { @@ -691,8 +681,10 @@ void OSystem_GP2X::copyRectToScreen(const byte *src, int pitch, int x, int y, in assert (_transactionMode == kTransactionNone); assert(src); - if (_screen == NULL) + if (_screen == NULL) { + warning("OSystem_GP2X::copyRectToScreen: _screen == NULL"); return; + } Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends @@ -757,6 +749,19 @@ void OSystem_GP2X::copyRectToScreen(const byte *src, int pitch, int x, int y, in } Graphics::Surface *OSystem_GP2X::lockScreen() { + assert (_transactionMode == kTransactionNone); + + // Lock the graphics mutex + lockMutex(_graphicsMutex); + + // paranoia check + assert(!_screenIsLocked); + _screenIsLocked = true; + + // Try to lock the screen surface + if (SDL_LockSurface(_screen) == -1) + error("SDL_LockSurface failed: %s", SDL_GetError()); + _framebuffer.pixels = _screen->pixels; _framebuffer.w = _screen->w; _framebuffer.h = _screen->h; @@ -767,8 +772,20 @@ Graphics::Surface *OSystem_GP2X::lockScreen() { } void OSystem_GP2X::unlockScreen() { - // Force screen update + assert (_transactionMode == kTransactionNone); + + // paranoia check + assert(_screenIsLocked); + _screenIsLocked = false; + + // Unlock the screen surface + SDL_UnlockSurface(_screen); + + // Trigger a full screen update _forceFull = true; + + // Finally unlock the graphics mutex + unlockMutex(_graphicsMutex); } void OSystem_GP2X::addDirtyRect(int x, int y, int w, int h, bool realCoordinates) { @@ -818,11 +835,9 @@ void OSystem_GP2X::addDirtyRect(int x, int y, int w, int h, bool realCoordinates h = height - y; } -#ifndef DISABLE_SCALERS if (_adjustAspectRatio && !_overlayVisible && !realCoordinates) { makeRectStretchable(x, y, w, h); } -#endif if (w == width && h == height) { _forceFull = true; @@ -851,7 +866,7 @@ void OSystem_GP2X::makeChecksums(const byte *buf) { /* the 8x8 blocks in buf are enumerated starting in the top left corner and * reading each line at a time from left to right */ for (y = 0; y != last_y; y++, buf += _screenWidth * (8 - 1)) - for (x = 0; x != last_x; x++, buf += 8) { // Adler32 checksum algorithm (from RFC1950, used by gzip and zlib). + for (x = 0; x != last_x; x++, buf += 8) { // Adler32 checksum algorithm (from RFC1950, used by gzip and zlib). // This computes the Adler32 checksum of a 8x8 pixel block. Note // that we can do the modulo operation (which is the slowest part) @@ -1165,8 +1180,6 @@ bool OSystem_GP2X::showMouse(bool visible) { bool last = _mouseVisible; _mouseVisible = visible; - //updateScreen(); - return last; } @@ -1174,7 +1187,6 @@ void OSystem_GP2X::setMousePos(int x, int y) { if (x != _mouseCurState.x || y != _mouseCurState.y) { _mouseCurState.x = x; _mouseCurState.y = y; - //updateScreen(); } } @@ -1521,7 +1533,6 @@ void OSystem_GP2X::drawMouse() { zoomdst.h = (tmpScreenHeight); SDL_GP2X_Display(&zoomdst); - }; @@ -1545,6 +1556,8 @@ void OSystem_GP2X::displayMessageOnOSD(const char *msg) { assert (_transactionMode == kTransactionNone); assert(msg); + Common::StackLock lock(_graphicsMutex); // Lock the mutex until this function ends + uint i; // Lock the OSD surface for drawing @@ -1696,7 +1709,5 @@ void OSystem_GP2X::handleScalerHotkeys(const SDL_KeyboardEvent &key) { displayMessageOnOSD(buffer); } } - } - } diff --git a/backends/platform/ps2/systemps2.cpp b/backends/platform/ps2/systemps2.cpp index 32290bddea..6572166e91 100644 --- a/backends/platform/ps2/systemps2.cpp +++ b/backends/platform/ps2/systemps2.cpp @@ -332,6 +332,16 @@ OSystem_PS2::OSystem_PS2(const char *elfPath) { OSystem_PS2::~OSystem_PS2(void) { } +void OSystem_PS2::initBackend() { + // FIXME: Should probably move lots of stuff from the constructor to here + _mixer = new Audio::Mixer(); + _timer = new DefaultTimerManager(); + setSoundCallback(Audio::Mixer::mixCallback, _mixer); + setTimerCallback(&timer_handler, 10); + + OSystem::initBackend(); +} + void OSystem_PS2::initTimer(void) { // first setup the two threads that get activated by the timer: // the timerthread and the soundthread diff --git a/backends/platform/ps2/systemps2.h b/backends/platform/ps2/systemps2.h index b5c84d3b95..033431a6fd 100644 --- a/backends/platform/ps2/systemps2.h +++ b/backends/platform/ps2/systemps2.h @@ -48,6 +48,9 @@ class OSystem_PS2 : public OSystem { public: OSystem_PS2(const char *elfPath); virtual ~OSystem_PS2(void); + + virtual void initBackend(); + virtual void initSize(uint width, uint height); virtual int16 getHeight(void); @@ -103,6 +106,8 @@ public: virtual void colorToRGB(OverlayColor color, uint8 &r, uint8 &g, uint8 &b); virtual Common::SaveFileManager *getSavefileManager(); + virtual Audio::Mixer *getMixer() { return _mixer; } + virtual Common::TimerManager *getTimerManager() { return _timer; } void timerThread(void); void soundThread(void); @@ -129,6 +134,8 @@ private: bool _useMouse, _useKbd, _useHdd, _usbMassLoaded, _usbMassConnected; Ps2SaveFileManager *_saveManager; + Audio::Mixer *_mixer; + Common::TimerManager *_timer; Gs2dScreen *_screen; Ps2Input *_input; diff --git a/backends/platform/psp/osys_psp.h b/backends/platform/psp/osys_psp.h index d5d3669a22..7c0932dc20 100644 --- a/backends/platform/psp/osys_psp.h +++ b/backends/platform/psp/osys_psp.h @@ -38,15 +38,6 @@ enum GraphicModeID { CENTERED_362X272 }; -namespace Graphics { - struct Surface; -} - -namespace Common { - class SaveFileManager; - class TimerManager; -} - class OSystem_PSP : public OSystem { public: static const OSystem::GraphicsMode s_supportedGraphicsModes[]; diff --git a/backends/platform/sdl/events.cpp b/backends/platform/sdl/events.cpp index 2b3c2c18fe..19fb2372df 100644 --- a/backends/platform/sdl/events.cpp +++ b/backends/platform/sdl/events.cpp @@ -259,7 +259,7 @@ bool OSystem_SDL::pollEvent(Common::Event &event) { handleScalerHotkeys(ev.key); break; } - const bool event_complete = remapKey(ev,event); + const bool event_complete = remapKey(ev, event); if (event_complete) return true; @@ -445,7 +445,7 @@ bool OSystem_SDL::pollEvent(Common::Event &event) { return false; } -bool OSystem_SDL::remapKey(SDL_Event &ev,Common::Event &event) { +bool OSystem_SDL::remapKey(SDL_Event &ev, Common::Event &event) { #ifdef LINUPY // On Yopy map the End button to quit if ((ev.key.keysym.sym == 293)) { diff --git a/backends/platform/wince/Makefile b/backends/platform/wince/Makefile index 0d9556e967..a4b4fa4f12 100644 --- a/backends/platform/wince/Makefile +++ b/backends/platform/wince/Makefile @@ -51,7 +51,7 @@ USE_ZLIB = 1 #DISABLE_HQ_SCALERS = 1 USE_ARM_SOUND_ASM = 1 -USE_ARM_SMUSH = 1 +USE_ARM_SMUSH_ASM = 1 ######################################################################## diff --git a/backends/saves/default/default-saves.cpp b/backends/saves/default/default-saves.cpp index 8c9b0ffd2a..b58dd87d93 100644 --- a/backends/saves/default/default-saves.cpp +++ b/backends/saves/default/default-saves.cpp @@ -187,16 +187,21 @@ void DefaultSaveFileManager::listSavefiles(const char *prefix , bool *marks, int search += '*'; //match all files that start with the given prefix search.c_str(); //FIXME: subtle bug? removing this line will break things. Looks like the string isn't getting updated. + assert(marks); memset(marks, false, num * sizeof(bool)); //assume no savegames for this title if(savePath.lookupFile(savefiles, savePath, search, false, true)) { char slot[2]; + int slotNum; for(FSList::const_iterator file = savefiles.begin(); file != savefiles.end(); file++) { //TODO: check if this is the behavior for all engines //Obtain the last 2 digits of the filename, since they correspond to the save slot slot[0] = file->getName()[file->getName().size()-2]; slot[1] = file->getName()[file->getName().size()-1]; - marks[atoi(slot)] = true; //mark this slot as valid + + slotNum = atoi(slot); + if(slotNum >= 0 && slotNum < num) + marks[slotNum] = true; //mark this slot as valid } } } diff --git a/base/main.cpp b/base/main.cpp index 85e711bce1..d8239db6e4 100644 --- a/base/main.cpp +++ b/base/main.cpp @@ -203,6 +203,9 @@ static int runGame(const Plugin *plugin, OSystem &system, const Common::String & // the command line arugments here Common::enableSpecialDebugLevelList(edebuglevels); + // Inform backend that the engine is about to be run + system.engineInit(); + int result; // Init the engine (this might change the screen parameters) @@ -216,6 +219,9 @@ static int runGame(const Plugin *plugin, OSystem &system, const Common::String & // TODO: Set an error flag, notify user about the problem } + // Inform backend that the engine finished + system.engineDone(); + // We clear all debug levels again even though the engine should do it Common::clearAllSpecialDebugLevels(); diff --git a/common/frac.h b/common/frac.h new file mode 100644 index 0000000000..b1e6c518d1 --- /dev/null +++ b/common/frac.h @@ -0,0 +1,55 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef COMMON_FRAC_H +#define COMMON_FRAC_H + +#include "common/scummsys.h" + +/** + * The precision of the fractional (fixed point) type we define below. + * Normally you should never have to modify this value. + */ +enum { + FRAC_BITS = 16, + FRAC_LO_MASK = ((1L << FRAC_BITS) - 1), + FRAC_HI_MASK = ((1L << FRAC_BITS) - 1) << FRAC_BITS, + + FRAC_ONE = (1L << FRAC_BITS), // 1.0 + FRAC_HALF = (1L << (FRAC_BITS-1)) // 0.5 +}; + +/** + * Fixed-point fractions, used by the sound rate converter and other code. + */ +typedef int32 frac_t; + +inline frac_t doubleToFrac(double value) { return (frac_t)(value * FRAC_ONE); } +inline double fracToDouble(frac_t value) { return ((double)value) / FRAC_ONE; } + +inline frac_t intToFrac(int16 value) { return value << FRAC_BITS; } +inline int16 fracToInt(frac_t value) { return value >> FRAC_BITS; } + +#endif diff --git a/common/savefile.h b/common/savefile.h index e1a54638b5..612d6ae210 100644 --- a/common/savefile.h +++ b/common/savefile.h @@ -99,7 +99,7 @@ public: * TODO: Or even replace it with a better API. For example, one that * returns a list of strings for all present file names. */ - virtual void listSavefiles(const char * /* prefix */, bool *marks, int num) = 0; + virtual void listSavefiles(const char *prefix , bool *marks, int num) = 0; /** * Get the path to the save game directory. diff --git a/common/scummsys.h b/common/scummsys.h index 4cb8d5d8e9..fb81bcb25a 100644 --- a/common/scummsys.h +++ b/common/scummsys.h @@ -313,8 +313,10 @@ // #if defined(__GNUC__) #define NORETURN __attribute__((__noreturn__)) + #define PACKED_STRUCT __attribute__((packed)) #define GCC_PRINTF(x,y) __attribute__((format(printf, x, y))) #else + #define PACKED_STRUCT #define GCC_PRINTF(x,y) #endif diff --git a/common/system.h b/common/system.h index 95f970d956..79680c4655 100644 --- a/common/system.h +++ b/common/system.h @@ -73,6 +73,18 @@ public: */ virtual void initBackend() { } + /** + * Allows the backend to perform engine specific init. + * Called just before the engine is run. + */ + virtual void engineInit() { } + + /** + * Allows the backend to perform engine specific de-init. + * Called after the engine finishes. + */ + virtual void engineDone() { } + /** @name Feature flags */ //@{ @@ -587,11 +599,6 @@ public: */ virtual int16 getOverlayWidth() { return getWidth(); } - virtual int screenToOverlayX(int x) { return x; } - virtual int screenToOverlayY(int y) { return y; } - virtual int overlayToScreenX(int x) { return x; } - virtual int overlayToScreenY(int y) { return y; } - /** * Convert the given RGB triplet into an OverlayColor. A OverlayColor can * be 8bit, 16bit or 32bit, depending on the target system. The default @@ -63,11 +63,15 @@ _build_agi=yes _build_touche=yes _build_parallaction=yes _build_cruise=no +_build_hq_scalers=yes +_build_scalers=yes + +_endian=unknown _need_memalign=no +_have_x86=no _build_plugins=no _nasm=auto -_build_hq_scalers=yes -_build_scalers=yes + # more defaults _backend=sdl _ranlib=ranlib @@ -89,7 +93,6 @@ _nasmpath="$PATH" NASMFLAGS="" NASM="" _prefix=/usr/local -_have_x86="" _srcdir=`dirname $0` @@ -105,9 +108,6 @@ _host_cpu="" _host_vendor="" _host_os="" -# config.h defaults -_def_linupy="#undef LINUPY" - cc_check() { echo >> "$TMPLOG" cat "$TMPC" >> "$TMPLOG" @@ -124,20 +124,47 @@ echocheck () { echo_n "Checking for $@... " } -# Add a boolean flag to config.mk. Takes two parameters: -# The first one can be set to 'yes' to "comment out" the flag, -# i.e. make it ineffective, use 'no' otherwise. -# The second param is the name of the flag to set. -# -# For now the variable is always set to 1, but we could add -# another parameter for that... -add_flag_to_config_mk_if_no() { +# Add a line of data to config.mk. +add_line_to_config_mk() { + _config_mk_data="$_config_mk_data"' +'"$1" +} + +# Add a line of data to h.mk. +add_line_to_config_h() { + _config_h_data="$_config_h_data"' +'"$1" +} + +add_to_config_h_if_yes() { + if test "$1" = yes ; then + add_line_to_config_h "$2" + else + add_line_to_config_h "/* $2 */" + fi +} + +# Conditionally add a line of data to config.mk. Takes two parameters: +# The first one can be set to 'no' to "comment out" the line, i.e. +# make it ineffective, use 'yes' otherwise. +# The second param is the line to insert. +add_to_config_mk_if_yes() { + if test "$1" = yes ; then + add_line_to_config_mk "$2" + else + add_line_to_config_mk "# $2" + fi +} + +# Conditionally add a line of data to config.mk. Takes two parameters: +# The first one can be set to 'yes' to "comment out" the line, i.e. +# make it ineffective, use 'no' otherwise. +# The second param is the line to insert. +add_to_config_mk_if_no() { if test "$1" = no ; then - _config_mk_data="$_config_mk_data"' -'"$2 = 1" + add_line_to_config_mk "$2" else - _config_mk_data="$_config_mk_data"' -'"# $2 = 1" + add_line_to_config_mk "# $2" fi } @@ -680,31 +707,31 @@ if test "$_cxx_major" -ge "3" ; then CXXFLAGS="$CXXFLAGS -ansi -W -Wno-unused-parameter" ;; esac - add_flag_to_config_mk_if_no no 'HAVE_GCC3' + add_line_to_config_mk 'HAVE_GCC3 = 1' fi; # # Engine selection # -add_flag_to_config_mk_if_no $_build_scumm 'DISABLE_SCUMM' -add_flag_to_config_mk_if_no $_build_scumm_7_8 'DISABLE_SCUMM_7_8' -add_flag_to_config_mk_if_no $_build_he 'DISABLE_HE' -add_flag_to_config_mk_if_no $_build_agos 'DISABLE_AGOS' -add_flag_to_config_mk_if_no $_build_sky 'DISABLE_SKY' -add_flag_to_config_mk_if_no $_build_sword1 'DISABLE_SWORD1' -add_flag_to_config_mk_if_no $_build_sword2 'DISABLE_SWORD2' -add_flag_to_config_mk_if_no $_build_queen 'DISABLE_QUEEN' -add_flag_to_config_mk_if_no $_build_kyra 'DISABLE_KYRA' -add_flag_to_config_mk_if_no $_build_saga 'DISABLE_SAGA' -add_flag_to_config_mk_if_no $_build_gob 'DISABLE_GOB' -add_flag_to_config_mk_if_no $_build_lure 'DISABLE_LURE' -add_flag_to_config_mk_if_no $_build_cine 'DISABLE_CINE' -add_flag_to_config_mk_if_no $_build_agi 'DISABLE_AGI' -add_flag_to_config_mk_if_no $_build_touche 'DISABLE_TOUCHE' -add_flag_to_config_mk_if_no $_build_parallaction 'DISABLE_PARALLACTION' -add_flag_to_config_mk_if_no $_build_cruise 'DISABLE_CRUISE' -add_flag_to_config_mk_if_no $_build_hq_scalers 'DISABLE_HQ_SCALERS' -add_flag_to_config_mk_if_no $_build_scalers 'DISABLE_SCALERS' +add_to_config_mk_if_no $_build_scumm 'DISABLE_SCUMM = 1' +add_to_config_mk_if_no $_build_scumm_7_8 'DISABLE_SCUMM_7_8 = 1' +add_to_config_mk_if_no $_build_he 'DISABLE_HE = 1' +add_to_config_mk_if_no $_build_agos 'DISABLE_AGOS = 1' +add_to_config_mk_if_no $_build_sky 'DISABLE_SKY = 1' +add_to_config_mk_if_no $_build_sword1 'DISABLE_SWORD1 = 1' +add_to_config_mk_if_no $_build_sword2 'DISABLE_SWORD2 = 1' +add_to_config_mk_if_no $_build_queen 'DISABLE_QUEEN = 1' +add_to_config_mk_if_no $_build_kyra 'DISABLE_KYRA = 1' +add_to_config_mk_if_no $_build_saga 'DISABLE_SAGA = 1' +add_to_config_mk_if_no $_build_gob 'DISABLE_GOB = 1' +add_to_config_mk_if_no $_build_lure 'DISABLE_LURE = 1' +add_to_config_mk_if_no $_build_cine 'DISABLE_CINE = 1' +add_to_config_mk_if_no $_build_agi 'DISABLE_AGI = 1' +add_to_config_mk_if_no $_build_touche 'DISABLE_TOUCHE = 1' +add_to_config_mk_if_no $_build_parallaction 'DISABLE_PARALLACTION = 1' +add_to_config_mk_if_no $_build_cruise 'DISABLE_CRUISE = 1' +add_to_config_mk_if_no $_build_hq_scalers 'DISABLE_HQ_SCALERS = 1' +add_to_config_mk_if_no $_build_scalers 'DISABLE_SCALERS = 1' if test -n "$_host"; then # Cross-compiling mode - add your target here if needed @@ -712,39 +739,43 @@ if test -n "$_host"; then linupy|arm-riscos) echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes" DEFINES="$DEFINES -DUNIX" - _def_endianness='#define SCUMM_LITTLE_ENDIAN' - _def_align='#define SCUMM_NEED_ALIGNMENT' - _def_linupy="#define DLINUPY" + _endian=little + _need_memalign=yes + add_line_to_config_h "#define LINUPY" type_1_byte='char' type_2_byte='short' type_4_byte='int' ;; arm-linux|arm-linux-gnueabi|arm-*-linux-gnueabi) echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes" - DEFINES="$DEFINES -DUNIX -DUSE_ARM_SOUND_ASM" + DEFINES="$DEFINES -DUNIX -DUSE_ARM_SOUND_ASM -DUSE_ARM_SMUSH_ASM" #not true for all ARM systems, but the interesting ones are all LE. Most (if not all) BE arm devices don't have a screen - _def_endianness='#define SCUMM_LITTLE_ENDIAN' - _def_align='#define SCUMM_NEED_ALIGNMENT' + _endian=little + _need_memalign=yes type_1_byte='char' type_2_byte='short' type_4_byte='int' + add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1' + add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1' ;; gp2x) echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes" - DEFINES="$DEFINES -DUNIX -DGP2X -DUSE_ARM_SOUND_ASM" - _def_endianness='#define SCUMM_LITTLE_ENDIAN' - _def_align='#define SCUMM_NEED_ALIGNMENT' + DEFINES="$DEFINES -DUNIX -DGP2X -DUSE_ARM_SOUND_ASM -DUSE_ARM_SMUSH_ASM" + _endian=little + _need_memalign=yes type_1_byte='char' type_2_byte='short' type_4_byte='int' + add_line_to_config_mk 'USE_ARM_SOUND_ASM = 1' + add_line_to_config_mk 'USE_ARM_SMUSH_ASM = 1' _backend="gp2x" _mak_hq_scalers='DISABLE_HQ_SCALERS = 1' _build_hq_scalers="no" ;; ppc-amigaos) echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes" - _def_endianness='#define SCUMM_BIG_ENDIAN' - _def_align='#define SCUMM_NEED_ALIGNMENT' + _endian=big + _need_memalign=yes type_1_byte='char' type_2_byte='short' type_4_byte='long' @@ -754,8 +785,8 @@ if test -n "$_host"; then m68k-atari-mint) echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes" DEFINES="$DEFINES -DUNIX -DSYSTEM_NOT_SUPPORTING_D_TYPE" - _def_endianness='#define SCUMM_BIG_ENDIAN' - _def_align='#define SCUMM_NEED_ALIGNMENT' + _endian=big + _need_memalign=yes type_1_byte='char' type_2_byte='short' type_4_byte='long' @@ -765,9 +796,7 @@ if test -n "$_host"; then i586-mingw32msvc) echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes" DEFINES="$DEFINES -DWIN32" - _def_x86='#define HAVE_X86' - _def_endianness='#define SCUMM_LITTLE_ENDIAN' - _def_align='#undef SCUMM_NEED_ALIGNMENT' + _endian=little _have_x86=yes type_1_byte='char' type_2_byte='short' @@ -851,19 +880,8 @@ int main(int argc, char **argv) } EOF $CXX $CXXFLAGS -o tmp_endianness_check$EXEEXT tmp_endianness_check.cpp - endianness=`./tmp_endianness_check` - echo $endianness; - case $endianness in - big) - _def_endianness='#define SCUMM_BIG_ENDIAN' - ;; - little) - _def_endianness='#define SCUMM_LITTLE_ENDIAN' - ;; - *) - exit 1 - ;; - esac + _endian=`./tmp_endianness_check` + echo $_endian; rm -f tmp_endianness_check$EXEEXT tmp_endianness_check.cpp # @@ -878,12 +896,6 @@ EOF _have_x86=no ;; esac - - if test "$_have_x86" = yes ; then - _def_x86='#define HAVE_X86' - else - _def_x86='#undef HAVE_X86' - fi echo "$_have_x86" # @@ -931,12 +943,6 @@ EOF cc_check && $TMPO && _need_memalign=no ;; esac - - if test "$_need_memalign" = yes ; then - _def_align='#define SCUMM_NEED_ALIGNMENT' - else - _def_align='#undef SCUMM_NEED_ALIGNMENT' - fi echo "$_need_memalign" # @@ -963,12 +969,34 @@ EOF fi # +# Add the results of the above checks to config.h +# +case $_endian in + big) + add_line_to_config_h '/* #define SCUMM_LITTLE_ENDIAN */' + add_line_to_config_h '#define SCUMM_BIG_ENDIAN' + ;; + little) + add_line_to_config_h '#define SCUMM_LITTLE_ENDIAN' + add_line_to_config_h '/* #define SCUMM_BIG_ENDIAN */' + ;; + *) + exit 1 + ;; +esac + +add_to_config_h_if_yes $_have_x86 '#define HAVE_X86' + +add_to_config_h_if_yes $_need_memalign '#define SCUMM_NEED_ALIGNMENT' + + +# # Check whether plugin support is requested and possible # echo_n "Checking whether building plugins was requested... " echo "$_build_plugins" _mak_plugins= -_def_plugin= +_def_plugin="/* -> plugins disabled */" if test "$_build_plugins" = yes ; then echo_n "Checking whether building plugins is supported... " @@ -1056,10 +1084,10 @@ fi # if test "$_mt32emu" = no ; then _def_mt32emu='#undef USE_MT32EMU' - add_flag_to_config_mk_if_no yes 'USE_MT32EMU' + add_to_config_mk_if_no yes 'USE_MT32EMU = 1' else _def_mt32emu='#define USE_MT32EMU' - add_flag_to_config_mk_if_no no 'USE_MT32EMU' + add_to_config_mk_if_no no 'USE_MT32EMU = 1' fi # @@ -1079,10 +1107,10 @@ if test "$_vorbis" = yes ; then _def_vorbis='#define USE_VORBIS' LIBS="$LIBS $OGG_LIBS $VORBIS_LIBS -lvorbisfile -lvorbis -logg" INCLUDES="$INCLUDES $OGG_CFLAGS $VORBIS_CFLAGS" - add_flag_to_config_mk_if_no no 'USE_VORBIS' + add_to_config_mk_if_no no 'USE_VORBIS = 1' else _def_vorbis='#undef USE_VORBIS' - add_flag_to_config_mk_if_no yes 'USE_VORBIS' + add_to_config_mk_if_no yes 'USE_VORBIS = 1' fi echo "$_vorbis" @@ -1104,13 +1132,13 @@ if test "$_tremor" = yes && test "$_vorbis" = no; then _def_vorbis='#define USE_VORBIS' LIBS="$LIBS $TREMOR_LIBS -lvorbisidec" INCLUDES="$INCLUDES $TREMOR_CFLAGS" - add_flag_to_config_mk_if_no no 'USE_TREMOR' + add_to_config_mk_if_no no 'USE_TREMOR = 1' else if test "$_vorbis" = yes; then _tremor="no (Ogg Vorbis/Tremor support is mutually exclusive)" fi _def_tremor='#undef USE_TREMOR' - add_flag_to_config_mk_if_no yes 'USE_TREMOR' + add_to_config_mk_if_no yes 'USE_TREMOR = 1' fi echo "$_tremor" @@ -1131,10 +1159,10 @@ if test "$_flac" = yes ; then _def_flac='#define USE_FLAC' LIBS="$LIBS $FLAC_LIBS $OGG_LIBS -lFLAC -logg" INCLUDES="$INCLUDES $FLAC_CFLAGS" - add_flag_to_config_mk_if_no no 'USE_FLAC' + add_to_config_mk_if_no no 'USE_FLAC = 1' else _def_flac='#undef USE_FLAC' - add_flag_to_config_mk_if_no yes 'USE_FLAC' + add_to_config_mk_if_no yes 'USE_FLAC = 1' fi echo "$_flac" @@ -1154,10 +1182,10 @@ if test "$_mad" = yes ; then _def_mad='#define USE_MAD' LIBS="$LIBS $MAD_LIBS -lmad" INCLUDES="$INCLUDES $MAD_CFLAGS" - add_flag_to_config_mk_if_no no 'USE_MAD' + add_to_config_mk_if_no no 'USE_MAD = 1' else _def_mad='#undef USE_MAD' - add_flag_to_config_mk_if_no yes 'USE_MAD' + add_to_config_mk_if_no yes 'USE_MAD = 1' fi echo "$_mad" @@ -1243,10 +1271,10 @@ if test "$_mpeg2" = yes ; then _def_mpeg2='#define USE_MPEG2' INCLUDES="$INCLUDES $MPEG2_CFLAGS" LIBS="$LIBS $MPEG2_LIBS -lmpeg2" - add_flag_to_config_mk_if_no no 'USE_MPEG2' + add_to_config_mk_if_no no 'USE_MPEG2 = 1' else _def_mpeg2='#undef USE_MPEG2' - add_flag_to_config_mk_if_no yes 'USE_MPEG2' + add_to_config_mk_if_no yes 'USE_MPEG2 = 1' fi echo "$_mpeg2" rm -f $TMPC $TMPO$EXEEXT @@ -1280,13 +1308,8 @@ if test "$_have_x86" = yes ; then CheckNASM fi -if test "$_nasm" = yes ; then - _def_nasm='#define USE_NASM' - add_flag_to_config_mk_if_no no 'HAVE_NASM' -else - _def_nasm='#undef USE_NASM' - add_flag_to_config_mk_if_no yes 'HAVE_NASM' -fi +add_to_config_h_if_yes $_nasm '#define USE_NASM' +add_to_config_mk_if_yes $_nasm 'HAVE_NASM = 1' # # figure out installation directories @@ -1429,11 +1452,7 @@ cat > config.h << EOF #ifndef CONFIG_H #define CONFIG_H -$_def_endianness -$_def_align -$_def_x86 - -$_def_linupy +$_config_h_data /* Data types */ typedef unsigned $type_1_byte byte; @@ -1456,9 +1475,6 @@ $_def_mpeg2 $_def_fluidsynth $_def_mt32emu -/* Whether we should use i386 assembly routines */ -$_def_nasm - /* Plugin settings */ $_def_plugin diff --git a/dists/msvc8/scummvm.vcproj b/dists/msvc8/scummvm.vcproj index 2f59d57b18..9c41118229 100644 --- a/dists/msvc8/scummvm.vcproj +++ b/dists/msvc8/scummvm.vcproj @@ -299,6 +299,10 @@ > </File> <File + RelativePath="..\..\common\frac.h" + > + </File> + <File RelativePath="..\..\common\fs.cpp" > </File> diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index 74795271fc..0839b7de99 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -334,7 +334,7 @@ void AgiEngine::replayImageStackCall(uint8 type, int16 p1, int16 p2, int16 p3, case ADD_PIC: debugC(8, kDebugLevelMain, "--- decoding picture %d ---", p1); agiLoadResource(rPICTURE, p1); - _picture->decodePicture(p1, p2); + _picture->decodePicture(p1, p2, p3 != 0); break; case ADD_VIEW: agiLoadResource(rVIEW, p1); diff --git a/engines/agi/agi.h b/engines/agi/agi.h index 56ae1288b8..01db2acb23 100644 --- a/engines/agi/agi.h +++ b/engines/agi/agi.h @@ -247,6 +247,18 @@ enum { }; /** + * Different monitor types. + * Used with AGI variable 26 i.e. vMonitor. + */ +enum AgiMonitorType { + kAgiMonitorCga = 0, + // kAgiMonitorTandy = 1, // Not sure about this + kAgiMonitorHercules = 2, + kAgiMonitorEga = 3 + // kAgiMonitorVga = 4 // Not sure about this +}; + +/** * AGI flags */ enum { diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp index 22d2582021..bd8fcb0394 100644 --- a/engines/agi/cycle.cpp +++ b/engines/agi/cycle.cpp @@ -367,7 +367,26 @@ int AgiEngine::runGame() { setvar(vComputer, 0); /* IBM PC (4 = Atari ST) */ setvar(vSoundgen, 1); /* IBM PC SOUND */ - setvar(vMonitor, 0x3); /* EGA monitor */ + + // Set monitor type (v26 i.e. vMonitor) + switch (_renderMode) { + case Common::kRenderCGA: + setvar(vMonitor, kAgiMonitorCga); + break; + case Common::kRenderHercG: + case Common::kRenderHercA: + setvar(vMonitor, kAgiMonitorHercules); + break; + // Don't know if Amiga AGI games use a different value than kAgiMonitorEga + // for vMonitor so I just use kAgiMonitorEga for them (As was done before too). + case Common::kRenderAmiga: + case Common::kRenderDefault: + case Common::kRenderEGA: + default: + setvar(vMonitor, kAgiMonitorEga); + break; + } + setvar(vMaxInputChars, 38); _game.inputMode = INPUT_NONE; _game.inputEnabled = 0; diff --git a/engines/agi/graphics.cpp b/engines/agi/graphics.cpp index 2d64a4352e..54f1783d83 100644 --- a/engines/agi/graphics.cpp +++ b/engines/agi/graphics.cpp @@ -624,8 +624,7 @@ int GfxMgr::keypress() { /** * Initialize the color palette * This function initializes the color palette using the specified 16-color - * RGB palette and creates 16 extra palette entries with translucent colors - * for the interpreter console. + * RGB palette. * @param p A pointer to the 16-color RGB palette. */ void GfxMgr::initPalette(uint8 *p) { @@ -633,7 +632,6 @@ void GfxMgr::initPalette(uint8 *p) { for (i = 0; i < 48; i++) { _palette[i] = p[i]; - _palette[i + 48] = (p[i] + 0x30) >> 2; } } @@ -642,13 +640,13 @@ void GfxMgr::gfxSetPalette() { byte pal[256 * 4]; if (!(_vm->getFeatures() & (GF_AGI256 | GF_AGI256_2))) { - for (i = 0; i < 32; i++) { + for (i = 0; i < 16; i++) { pal[i * 4 + 0] = _palette[i * 3 + 0] << 2; pal[i * 4 + 1] = _palette[i * 3 + 1] << 2; pal[i * 4 + 2] = _palette[i * 3 + 2] << 2; pal[i * 4 + 3] = 0; } - g_system->setPalette(pal, 0, 32); + g_system->setPalette(pal, 0, 16); } else { for (i = 0; i < 256; i++) { pal[i * 4 + 0] = vgaPalette[i * 3 + 0]; @@ -715,19 +713,107 @@ void GfxMgr::gfxPutBlock(int x1, int y1, int x2, int y2) { g_system->copyRectToScreen(_screen + y1 * 320 + x1, 320, x1, y1, x2 - x1 + 1, y2 - y1 + 1); } -static const byte mouseCursorArrow[] = { - // This is the same arrow cursor that was later used in early SCI games - 0x00, 0x00, 0x40, 0x00, 0x60, 0x00, 0x70, 0x00, - 0x78, 0x00, 0x7C, 0x00, 0x7E, 0x00, 0x7F, 0x00, - 0x7F, 0x80, 0x7F, 0xC0, 0x7C, 0x00, 0x46, 0x00, - 0x06, 0x00, 0x03, 0x00, 0x03, 0x00, 0x01, 0x80, - 0xC0, 0x00, 0xA0, 0x00, 0x90, 0x00, 0x88, 0x00, - 0x84, 0x00, 0x82, 0x00, 0x81, 0x00, 0x80, 0x80, - 0x80, 0x40, 0x80, 0x20, 0x82, 0x00, 0xA9, 0x00, - 0xC9, 0x00, 0x04, 0x80, 0x04, 0x80, 0x02, 0x40 +/** + * A black and white SCI-style arrow cursor (11x16). + * 0 = Transparent. + * 1 = Black (#000000 in 24-bit RGB). + * 2 = White (#FFFFFF in 24-bit RGB). + */ +static const byte sciMouseCursor[] = { + 1,1,0,0,0,0,0,0,0,0,0, + 1,2,1,0,0,0,0,0,0,0,0, + 1,2,2,1,0,0,0,0,0,0,0, + 1,2,2,2,1,0,0,0,0,0,0, + 1,2,2,2,2,1,0,0,0,0,0, + 1,2,2,2,2,2,1,0,0,0,0, + 1,2,2,2,2,2,2,1,0,0,0, + 1,2,2,2,2,2,2,2,1,0,0, + 1,2,2,2,2,2,2,2,2,1,0, + 1,2,2,2,2,2,2,2,2,2,1, + 1,2,2,2,2,2,1,0,0,0,0, + 1,2,1,0,1,2,2,1,0,0,0, + 1,1,0,0,1,2,2,1,0,0,0, + 0,0,0,0,0,1,2,2,1,0,0, + 0,0,0,0,0,1,2,2,1,0,0, + 0,0,0,0,0,0,1,2,2,1,0 +}; + +/** + * RGBA-palette for the black and white SCI-style arrow cursor. + */ +static const byte sciMouseCursorPalette[] = { + 0x00, 0x00, 0x00, 0x00, // Black + 0xFF, 0xFF, 0xFF, 0x00 // White +}; + +/** + * An Amiga-style arrow cursor (8x11). + * 0 = Transparent. + * 1 = Black (#000000 in 24-bit RGB). + * 2 = Red (#DE2021 in 24-bit RGB). + * 3 = Light red (#FFCFAD in 24-bit RGB). + */ +static const byte amigaMouseCursor[] = { + 2,3,1,0,0,0,0,0, + 2,2,3,1,0,0,0,0, + 2,2,2,3,1,0,0,0, + 2,2,2,2,3,1,0,0, + 2,2,2,2,2,3,1,0, + 2,2,2,2,2,2,3,1, + 2,0,2,2,3,1,0,0, + 0,0,0,2,3,1,0,0, + 0,0,0,2,2,3,1,0, + 0,0,0,0,2,3,1,0, + 0,0,0,0,2,2,3,1 +}; + +/** + * RGBA-palette for the Amiga-style arrow cursor + * and the Amiga-style busy cursor. + */ +static const byte amigaMouseCursorPalette[] = { + 0x00, 0x00, 0x00, 0x00, // Black + 0xDE, 0x20, 0x21, 0x00, // Red + 0xFF, 0xCF, 0xAD, 0x00 // Light red }; /** + * An Amiga-style busy cursor showing an hourglass (13x16). + * 0 = Transparent. + * 1 = Black (#000000 in 24-bit RGB). + * 2 = Red (#DE2021 in 24-bit RGB). + * 3 = Light red (#FFCFAD in 24-bit RGB). + */ +static const byte busyAmigaMouseCursor[] = { + 1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,2,2,2,2,2,2,2,2,2,2,2,1, + 1,2,2,2,2,2,2,2,2,2,2,2,1, + 0,1,3,3,3,3,3,3,3,3,3,1,0, + 0,0,1,3,3,3,3,3,3,3,1,0,0, + 0,0,0,1,3,3,3,3,3,1,0,0,0, + 0,0,0,0,1,3,3,3,1,0,0,0,0, + 0,0,0,0,0,1,3,1,0,0,0,0,0, + 0,0,0,0,0,1,3,1,0,0,0,0,0, + 0,0,0,0,1,2,3,2,1,0,0,0,0, + 0,0,0,1,2,2,3,2,2,1,0,0,0, + 0,0,1,2,2,2,3,2,2,2,1,0,0, + 0,1,2,2,2,3,3,3,2,2,2,1,0, + 1,3,3,3,3,3,3,3,3,3,3,3,1, + 1,3,3,3,3,3,3,3,3,3,3,3,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1 +}; + +void GfxMgr::setCursor(bool amigaStyleCursor) { + if (!amigaStyleCursor) { + CursorMan.replaceCursorPalette(sciMouseCursorPalette, 1, ARRAYSIZE(sciMouseCursorPalette) / 4); + CursorMan.replaceCursor(sciMouseCursor, 11, 16, 1, 1, 0); + } else { // amigaStyleCursor + CursorMan.replaceCursorPalette(amigaMouseCursorPalette, 1, ARRAYSIZE(amigaMouseCursorPalette) / 4); + CursorMan.replaceCursor(amigaMouseCursor, 8, 11, 1, 1, 0); + } +} + +/** * Initialize graphics device. * * @see deinit_video() @@ -743,31 +829,7 @@ int GfxMgr::initVideo() { gfxSetPalette(); - byte mouseCursor[16 * 16]; - const byte *src = mouseCursorArrow; - for (int i = 0; i < 32; ++i) { - int offs = i * 8; - for (byte mask = 0x80; mask != 0; mask >>= 1) { - if (src[0] & mask) { - mouseCursor[offs] = 2; - } else if (src[32] & mask) { - mouseCursor[offs] = 0; - } else { - mouseCursor[offs] = 0xFF; - } - ++offs; - } - ++src; - } - - const byte cursorPalette[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 255, 255, 255, 0 - }; - - CursorMan.replaceCursorPalette(cursorPalette, 0, 3); - CursorMan.replaceCursor(mouseCursor, 16, 16, 1, 1); + setCursor(_vm->_renderMode == Common::kRenderAmiga); return errOK; } @@ -804,23 +866,26 @@ int GfxMgr::deinitMachine() { * @param x x coordinate of the row start (AGI coord.) * @param y y coordinate of the row start (AGI coord.) * @param n number of pixels in the row - * @param p pointer to the row start in the AGI screen + * @param p pointer to the row start in the AGI screen (Always use sbuf16c as base, not sbuf256c) + * FIXME: CGA rendering doesn't work correctly with AGI256 or AGI256-2. */ void GfxMgr::putPixelsA(int x, int y, int n, uint8 *p) { + const uint rShift = _vm->_debug.priority ? 4 : 0; // Priority information is in the top 4 bits of a byte taken from sbuf16c. + + // Choose the correct screen to read from. If AGI256 or AGI256-2 is used and we're not trying to show the priority information, + // then choose the 256 color screen, otherwise choose the 16 color screen (Which also has the priority information). + p += _vm->getFeatures() & (GF_AGI256 | GF_AGI256_2) && !_vm->_debug.priority ? FROM_SBUF16_TO_SBUF256_OFFSET : 0; + if (_vm->_renderMode == Common::kRenderCGA) { for (x *= 2; n--; p++, x += 2) { register uint16 q = (cgaMap[(*p & 0xf0) >> 4] << 4) | cgaMap[*p & 0x0f]; - if (_vm->_debug.priority) - q >>= 4; - *(uint16 *)&_agiScreen[x + y * GFX_WIDTH] = q & 0x0f0f; + *(uint16 *)&_agiScreen[x + y * GFX_WIDTH] = (q >> rShift) & 0x0f0f; } } else { - const uint16 mask = _vm->getFeatures() & (GF_AGI256 | GF_AGI256_2) ? 0xffff : 0x0f0f; + const uint16 mask = _vm->getFeatures() & (GF_AGI256 | GF_AGI256_2) && !_vm->_debug.priority ? 0xffff : 0x0f0f; for (x *= 2; n--; p++, x += 2) { register uint16 q = ((uint16) * p << 8) | *p; - if (_vm->_debug.priority) - q >>= 4; - *(uint16 *)&_agiScreen[x + y * GFX_WIDTH] = q & mask; + *(uint16 *)&_agiScreen[x + y * GFX_WIDTH] = (q >> rShift) & mask; } } } diff --git a/engines/agi/graphics.h b/engines/agi/graphics.h index cdbae8d6e6..b1f9c0e1d7 100644 --- a/engines/agi/graphics.h +++ b/engines/agi/graphics.h @@ -41,7 +41,7 @@ class GfxMgr { private: AgiEngine *_vm; - uint8 _palette[32 * 3]; + uint8 _palette[16 * 3]; uint8 *_agiScreen; unsigned char *_screen; @@ -87,6 +87,7 @@ public: void putPixel(int, int, int); void putBlock(int x1, int y1, int x2, int y2); void gfxSetPalette(); + void setCursor(bool amigaStyleCursor = false); int keypress(); int getKey(); diff --git a/engines/agi/keyboard.cpp b/engines/agi/keyboard.cpp index 17865e1f3a..3acc81ddff 100644 --- a/engines/agi/keyboard.cpp +++ b/engines/agi/keyboard.cpp @@ -29,6 +29,9 @@ #include "agi/graphics.h" #include "agi/keyboard.h" #include "agi/menu.h" +#ifdef __DS__ +#include "wordcompletion.h" +#endif namespace Agi { @@ -308,6 +311,9 @@ void AgiEngine::handleKeys(int key) { debugC(3, kDebugLevelInput, "clear lines"); clearLines(l, l + 1, bg); flushLines(l, l + 1); +#ifdef __DS__ + DS::findWordCompletions((char *) _game.inputBuffer); +#endif break; case KEY_ESCAPE: @@ -324,6 +330,10 @@ void AgiEngine::handleKeys(int key) { _game.inputBuffer[--_game.cursorPos] = 0; /* Print cursor */ _gfx->printCharacter(_game.cursorPos + 1, l, _game.cursorChar, fg, bg); + +#ifdef __DS__ + DS::findWordCompletions((char *) _game.inputBuffer); +#endif break; default: /* Ignore invalid keystrokes */ @@ -337,6 +347,10 @@ void AgiEngine::handleKeys(int key) { _game.inputBuffer[_game.cursorPos++] = key; _game.inputBuffer[_game.cursorPos] = 0; +#ifdef __DS__ + DS::findWordCompletions((char *) _game.inputBuffer); +#endif + /* echo */ _gfx->printCharacter(_game.cursorPos, l, _game.inputBuffer[_game.cursorPos - 1], fg, bg); diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp index c51514f237..588ee1dd30 100644 --- a/engines/agi/op_cmd.cpp +++ b/engines/agi/op_cmd.cpp @@ -153,6 +153,18 @@ cmd(toggle_v) { cmd(new_room) { g_agi->newRoom(p0); + + // WORKAROUND: Works around intro skipping bug (#1737343) in Gold Rush. + // Intro was skipped because the enter-keypress finalizing the entering + // of the copy protection string (Copy protection is in logic.128) was + // left over to the intro scene (Starts with room 73 i.e. logic.073). + // The intro scene checks for any keys pressed and if it finds any it + // jumps to the game's start (Room 1 i.e. logic.001). We clear the + // keyboard buffer when the intro sequence's first room (Room 73) is + // loaded so that no keys from the copy protection scene can be left + // over to cause the intro to skip to the game's start. + if (g_agi->getGameID() == GID_GOLDRUSH && p0 == 73) + game.keypress = 0; } cmd(new_room_f) { diff --git a/engines/agi/picture.cpp b/engines/agi/picture.cpp index cd8ef83de0..144e965465 100644 --- a/engines/agi/picture.cpp +++ b/engines/agi/picture.cpp @@ -652,7 +652,7 @@ int PictureMgr::decodePicture(int n, int clear, bool agi256) { if (clear) _vm->clearImageStack(); - _vm->recordImageStackCall(ADD_PIC, n, clear, 0, 0, 0, 0, 0); + _vm->recordImageStackCall(ADD_PIC, n, clear, agi256, 0, 0, 0, 0); return errOK; } @@ -686,7 +686,7 @@ void PictureMgr::showPic() { i = 0; offset = _vm->_game.lineMinPrint * CHAR_LINES; for (y = 0; y < _HEIGHT; y++) { - _gfx->putPixelsA(0, y + offset, _WIDTH, &_vm->_game.sbuf[i]); + _gfx->putPixelsA(0, y + offset, _WIDTH, &_vm->_game.sbuf16c[i]); i += _WIDTH; } diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp index ab5f818d17..9144dae96c 100644 --- a/engines/agi/saveload.cpp +++ b/engines/agi/saveload.cpp @@ -519,41 +519,48 @@ int AgiEngine::selectSlot() { _gfx->drawButton(buttonX[i], buttonY, buttonText[i], 0, 0, MSG_BOX_TEXT, MSG_BOX_COLOUR); AllowSyntheticEvents on(this); + int oldFirstSlot = _firstSlot + 1; + int oldActive = active + 1; for (;;) { - char dstr[64]; - for (i = 0; i < NUM_VISIBLE_SLOTS; i++) { - sprintf(dstr, "[%2d. %-28.28s]", i + _firstSlot, desc[i]); - printText(dstr, 0, hm + 1, vm + 4 + i, - (40 - 2 * hm) - 1, i == active ? MSG_BOX_COLOUR : MSG_BOX_TEXT, - i == active ? MSG_BOX_TEXT : MSG_BOX_COLOUR); - } + int sbPos; - char upArrow[] = "^"; - char downArrow[] = "v"; - char scrollBar[] = " "; + if (oldFirstSlot != _firstSlot || oldActive != active) { + char dstr[64]; + for (i = 0; i < NUM_VISIBLE_SLOTS; i++) { + sprintf(dstr, "[%2d. %-28.28s]", i + _firstSlot, desc[i]); + printText(dstr, 0, hm + 1, vm + 4 + i, + (40 - 2 * hm) - 1, i == active ? MSG_BOX_COLOUR : MSG_BOX_TEXT, + i == active ? MSG_BOX_TEXT : MSG_BOX_COLOUR); + } - int sbPos; + char upArrow[] = "^"; + char downArrow[] = "v"; + char scrollBar[] = " "; + + // Use the extreme scrollbar positions only if the + // extreme slots are in sight. + + if (_firstSlot == 0) + sbPos = 1; + else if (_firstSlot == NUM_SLOTS - NUM_VISIBLE_SLOTS) + sbPos = NUM_VISIBLE_SLOTS - 2; + else { + sbPos = 2 + (_firstSlot * (NUM_VISIBLE_SLOTS - 4)) / (NUM_SLOTS - NUM_VISIBLE_SLOTS - 1); + if (sbPos >= NUM_VISIBLE_SLOTS - 3) + sbPos = NUM_VISIBLE_SLOTS - 3; + } - // Use the extreme scrollbar positions only if the extreme - // slots are in sight. - - if (_firstSlot == 0) - sbPos = 1; - else if (_firstSlot == NUM_SLOTS - NUM_VISIBLE_SLOTS) - sbPos = NUM_VISIBLE_SLOTS - 2; - else { - sbPos = 2 + (_firstSlot * (NUM_VISIBLE_SLOTS - 4)) / (NUM_SLOTS - NUM_VISIBLE_SLOTS - 1); - if (sbPos >= NUM_VISIBLE_SLOTS - 3) - sbPos = NUM_VISIBLE_SLOTS - 3; - } + for (i = 1; i < NUM_VISIBLE_SLOTS - 1; i++) + printText(scrollBar, 35, hm + 1, vm + 4 + i, 1, MSG_BOX_COLOUR, 7, true); - for (i = 1; i < NUM_VISIBLE_SLOTS - 1; i++) - printText(scrollBar, 35, hm + 1, vm + 4 + i, 1, MSG_BOX_COLOUR, 7, true); + printText(upArrow, 35, hm + 1, vm + 4, 1, 8, 7); + printText(downArrow, 35, hm + 1, vm + 4 + NUM_VISIBLE_SLOTS - 1, 1, 8, 7); + printText(scrollBar, 35, hm + 1, vm + 4 + sbPos, 1, MSG_BOX_COLOUR, MSG_BOX_TEXT); - printText(upArrow, 35, hm + 1, vm + 4, 1, 8, 7); - printText(downArrow, 35, hm + 1, vm + 4 + NUM_VISIBLE_SLOTS - 1, 1, 8, 7); - printText(scrollBar, 35, hm + 1, vm + 4 + sbPos, 1, MSG_BOX_COLOUR, MSG_BOX_TEXT); + oldActive = active; + oldFirstSlot = _firstSlot; + } _gfx->pollTimer(); /* msdos driver -> does nothing */ key = doPollKeyboard(); diff --git a/engines/agi/sprite.cpp b/engines/agi/sprite.cpp index 3d69968075..006e3dddee 100644 --- a/engines/agi/sprite.cpp +++ b/engines/agi/sprite.cpp @@ -215,7 +215,8 @@ void SpritesMgr::objsRestoreArea(Sprite *s) { int y, offset; int16 xPos = s->xPos, yPos = s->yPos; int16 xSize = s->xSize, ySize = s->ySize; - uint8 *p0, *q; + uint8 *q; + uint32 pos0; if (xPos + xSize > _WIDTH) xSize = _WIDTH - xPos; @@ -236,14 +237,14 @@ void SpritesMgr::objsRestoreArea(Sprite *s) { if (xSize <= 0 || ySize <= 0) return; - p0 = &_vm->_game.sbuf[xPos + yPos * _WIDTH]; + pos0 = xPos + yPos * _WIDTH; q = s->buffer; offset = _vm->_game.lineMinPrint * CHAR_LINES; for (y = 0; y < ySize; y++) { - memcpy(p0, q, xSize); - _gfx->putPixelsA(xPos, yPos + y + offset, xSize, p0); + memcpy(&_vm->_game.sbuf[pos0], q, xSize); + _gfx->putPixelsA(xPos, yPos + y + offset, xSize, &_vm->_game.sbuf16c[pos0]); q += xSize; - p0 += _WIDTH; + pos0 += _WIDTH; } } @@ -728,7 +729,7 @@ void SpritesMgr::commitBlock(int x1, int y1, int x2, int y2) { debugC(7, kDebugLevelSprites, "%d, %d, %d, %d", x1, y1, x2, y2); w = x2 - x1 + 1; - q = &_vm->_game.sbuf[x1 + _WIDTH * y1]; + q = &_vm->_game.sbuf16c[x1 + _WIDTH * y1]; offset = _vm->_game.lineMinPrint * CHAR_LINES; for (i = y1; i <= y2; i++) { _gfx->putPixelsA(x1, i + offset, w, q); diff --git a/engines/agi/words.cpp b/engines/agi/words.cpp index 5fc3c3bca9..ed33b9463a 100644 --- a/engines/agi/words.cpp +++ b/engines/agi/words.cpp @@ -88,7 +88,7 @@ void AgiEngine::unloadWords() { * Uses an algorithm hopefully like the one Sierra used. Returns the ID * of the word and the length in flen. Returns -1 if not found. * - * Thomas Åkesson, November 2001 + * Thomas Akesson, November 2001 */ int AgiEngine::findWord(char *word, int *flen) { int mchr = 0; /* matched chars */ diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp index c98257f028..ae7f692c3f 100644 --- a/engines/agos/agos.cpp +++ b/engines/agos/agos.cpp @@ -110,8 +110,6 @@ AGOSEngine::AGOSEngine(OSystem *syst) _debugger = 0; - _keyPressed = 0; - _gameFile = 0; _opcode = 0; @@ -746,10 +744,12 @@ void AGOSEngine_Simon2::setupGame() { _tableIndexBase = 1580 / 4; _textIndexBase = 1500 / 4; _numVideoOpcodes = 75; -#ifndef PALMOS_68K - _vgaMemSize = 2000000; -#else +#if defined(__DS__) + _vgaMemSize = 1300000; +#elif defined(PALMOS_68K) _vgaMemSize = gVars->memory[kMemSimon2Games]; +#else + _vgaMemSize = 2000000; #endif _itemMemSize = 20000; _tableMemSize = 100000; @@ -958,8 +958,8 @@ GUI::Debugger *AGOSEngine::getDebugger() { } void AGOSEngine::pause() { - _keyPressed = 1; - _pause = 1; + _keyPressed.reset(); + _pause = true; bool ambient_status = _ambientPaused; bool music_status = _musicPaused; @@ -969,8 +969,8 @@ void AGOSEngine::pause() { while (_pause) { delay(1); - if (_keyPressed == 'p') - _pause = 0; + if (_keyPressed.keycode == Common::KEYCODE_p) + _pause = false; } _midi.pause(music_status); diff --git a/engines/agos/agos.h b/engines/agos/agos.h index e487c38cc7..d233d0bfeb 100644 --- a/engines/agos/agos.h +++ b/engines/agos/agos.h @@ -28,6 +28,7 @@ #include "engines/engine.h" +#include "common/keyboard.h" #include "common/rect.h" #include "common/util.h" @@ -216,7 +217,7 @@ protected: const GameSpecificSettings *gss; - byte _keyPressed; + Common::KeyState _keyPressed; Common::File *_gameFile; @@ -875,8 +876,8 @@ public: void vc36_setWindowImage(); void vc38_ifVarNotZero(); void vc39_setVar(); - void vc40(); - void vc41(); + void vc40_scrollRight(); + void vc41_scrollLeft(); void vc42_delayIfNotEQ(); // Video Script Opcodes, Elvira 1 @@ -1316,7 +1317,9 @@ public: void oe2_moveDirn(); void oe2_doClass(); void oe2_pObj(); + void oe2_isCalled(); void oe2_loadGame(); + void oe2_menu(); void oe2_drawItem(); void oe2_doTable(); void oe2_pauseGame(); @@ -1410,7 +1413,6 @@ public: void oww_setLongText(); void oww_printLongText(); void oww_whereTo(); - void oww_menu(); void oww_textMenu(); void oww_pauseGame(); void oww_boxMessage(); diff --git a/engines/agos/animation.cpp b/engines/agos/animation.cpp index 8748cff54e..8d5238259d 100644 --- a/engines/agos/animation.cpp +++ b/engines/agos/animation.cpp @@ -130,8 +130,11 @@ void MoviePlayer::play() { return; } - if (!_fd) { - return; + if (_omniTVFile) { + // Clear any paused OmniTV video + _mixer->stopHandle(_omniTVSound); + delete _omniTVFile; + _omniTVFile = 0; } _leftButtonDown = false; diff --git a/engines/agos/contain.cpp b/engines/agos/contain.cpp index b5ca344905..891ac36d30 100644 --- a/engines/agos/contain.cpp +++ b/engines/agos/contain.cpp @@ -34,8 +34,8 @@ int AGOSEngine::canPlace(Item *x, Item *y) { Item *z = derefItem(x->parent); if (getGameType() == GType_ELVIRA1) { - SubPlayer *p = (SubPlayer *)findChildOfType(y, 3); - SubContainer *c = (SubContainer *)findChildOfType(y, 7); + SubPlayer *p = (SubPlayer *)findChildOfType(y, kPlayerType); + SubContainer *c = (SubContainer *)findChildOfType(y, kContainerType); int cap = 0; int wt; @@ -59,7 +59,7 @@ int AGOSEngine::canPlace(Item *x, Item *y) { return -2; /* Too heavy */ } } else { - SubObject *o = (SubObject *)findChildOfType(y, 2); + SubObject *o = (SubObject *)findChildOfType(y, kObjectType); int ct; int cap = 0; @@ -120,11 +120,11 @@ int AGOSEngine::sizeRec(Item *x, int d) { } int AGOSEngine::sizeOfRec(Item *i, int d) { - SubObject *o = (SubObject *)findChildOfType(i, 2); + SubObject *o = (SubObject *)findChildOfType(i, kObjectType); if (getGameType() == GType_ELVIRA1) { - SubPlayer *p = (SubPlayer *)findChildOfType(i, 3); - SubContainer *c = (SubContainer *)findChildOfType(i, 7); + SubPlayer *p = (SubPlayer *)findChildOfType(i, kPlayerType); + SubContainer *c = (SubContainer *)findChildOfType(i, kContainerType); if ((c) && (c->flags & 1)) { if (o) @@ -174,10 +174,10 @@ int AGOSEngine::weightRec(Item *x, int d) { } int AGOSEngine::weightOf(Item *x) { - SubObject *o = (SubObject *)findChildOfType(x, 2); + SubObject *o = (SubObject *)findChildOfType(x, kObjectType); if (getGameType() == GType_ELVIRA1) { - SubPlayer *p = (SubPlayer *)findChildOfType(x, 3); + SubPlayer *p = (SubPlayer *)findChildOfType(x, kPlayerType); if (o) return o->objectWeight; if (p) diff --git a/engines/agos/debugger.cpp b/engines/agos/debugger.cpp index ce50460621..3fc5a1f967 100644 --- a/engines/agos/debugger.cpp +++ b/engines/agos/debugger.cpp @@ -174,7 +174,7 @@ bool Debugger::Cmd_SetObjectFlag(int argc, const char **argv) { prop = atoi(argv[2]); if (obj >= 1 && obj < _vm->_itemArraySize) { - SubObject *o = (SubObject *)_vm->findChildOfType(_vm->derefItem(obj), 2); + SubObject *o = (SubObject *)_vm->findChildOfType(_vm->derefItem(obj), kObjectType); if (o != NULL) { if (o->objectFlags & (1 << prop) && prop < 16) { uint offs = _vm->getOffsetOfChild2Param(o, 1 << prop); diff --git a/engines/agos/detection_tables.h b/engines/agos/detection_tables.h index cb6123dc54..5efcaa3b86 100644 --- a/engines/agos/detection_tables.h +++ b/engines/agos/detection_tables.h @@ -426,7 +426,7 @@ static const AGOSGameDescription gameDescriptions[] = { { "gamepc", GAME_BASEFILE, "4bf28ab00f5324fd938e632595742382", -1}, { "icon.dat", GAME_ICONFILE, "83a7278bff55c82fbb3aef92981866c9", -1}, { "menus.dat", GAME_MENUFILE, "a2fdc88a77c8bdffec6b36cbeda4d955", -1}, - { "start", GAME_RESTFILE, "4d380a35ba941d03ee5084c71d20055b", -1}, + { "start", GAME_RESTFILE, "016107aced82d0cc5d758a9fba716270", -1}, { "stripped.txt", GAME_STRFILE, "c3a8f644551a27c8a2fec0f8070b46b7", -1}, { "tbllist", GAME_TBLFILE, "8252660df0edbdbc3e6377e155bbd0c5", -1}, { NULL, 0, NULL, 0} diff --git a/engines/agos/event.cpp b/engines/agos/event.cpp index 32329f34d9..5c673de700 100644 --- a/engines/agos/event.cpp +++ b/engines/agos/event.cpp @@ -500,10 +500,7 @@ void AGOSEngine::delay(uint amount) { } // Make sure backspace works right (this fixes a small issue on OS X) - if (event.kbd.keycode == Common::KEYCODE_BACKSPACE) - _keyPressed = 8; - else - _keyPressed = (byte)event.kbd.ascii; + _keyPressed = event.kbd; break; case Common::EVENT_MOUSEMOVE: break; diff --git a/engines/agos/input.cpp b/engines/agos/input.cpp index ef0791dc10..0f1c234b79 100644 --- a/engines/agos/input.cpp +++ b/engines/agos/input.cpp @@ -195,7 +195,8 @@ void AGOSEngine::waitForInput() { _dragAccept = 1; for (;;) { - if ((getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) && _keyPressed == 35) + if ((getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) && + _keyPressed.keycode == Common::KEYCODE_HASH) displayBoxStars(); if (processSpecialKeys()) { if ((getGameType() == GType_PP && getGameId() != GID_DIMP) || @@ -238,7 +239,6 @@ void AGOSEngine::waitForInput() { _dragMode = 0; _dragCount = 0; _dragEnd = 0; - continue; } } while (!_dragEnd); @@ -472,39 +472,39 @@ bool AGOSEngine::processSpecialKeys() { } } - switch (_keyPressed) { - case 17: // Up + switch (_keyPressed.keycode) { + case Common::KEYCODE_UP: if (getGameType() == GType_PP) _verbHitArea = 302; else if (getGameType() == GType_WW) _verbHitArea = 239; verbCode = true; break; - case 18: // Down + case Common::KEYCODE_DOWN: if (getGameType() == GType_PP) _verbHitArea = 304; else if (getGameType() == GType_WW) _verbHitArea = 241; verbCode = true; break; - case 19: // Right + case Common::KEYCODE_RIGHT: if (getGameType() == GType_PP) _verbHitArea = 303; else if (getGameType() == GType_WW) _verbHitArea = 240; verbCode = true; break; - case 20: // Left + case Common::KEYCODE_LEFT: if (getGameType() == GType_PP) _verbHitArea = 301; else if (getGameType() == GType_WW) _verbHitArea = 242; verbCode = true; break; - case 27: // escape + case Common::KEYCODE_ESCAPE: _exitCutscene = true; break; - case 59: // F1 + case Common::KEYCODE_F1: if (getGameType() == GType_SIMON2) { vcWriteVar(5, 50); vcWriteVar(86, 0); @@ -513,7 +513,7 @@ bool AGOSEngine::processSpecialKeys() { vcWriteVar(86, 0); } break; - case 60: // F2 + case Common::KEYCODE_F2: if (getGameType() == GType_SIMON2) { vcWriteVar(5, 75); vcWriteVar(86, 1); @@ -522,7 +522,7 @@ bool AGOSEngine::processSpecialKeys() { vcWriteVar(86, 1); } break; - case 61: // F3 + case Common::KEYCODE_F3: if (getGameType() == GType_SIMON2) { vcWriteVar(5, 125); vcWriteVar(86, 2); @@ -531,19 +531,19 @@ bool AGOSEngine::processSpecialKeys() { vcWriteVar(86, 2); } break; - case 63: // F5 + case Common::KEYCODE_F5: if (getGameType() == GType_SIMON2 || getGameType() == GType_FF) _exitCutscene = true; break; - case 65: // F7 + case Common::KEYCODE_F7: if (getGameType() == GType_FF && getBitFlag(76)) _variableArray[254] = 70; break; - case 67: // F9 + case Common::KEYCODE_F9: if (getGameType() == GType_FF) setBitFlag(73, !getBitFlag(73)); break; - case 37: // F12 + case Common::KEYCODE_F12: if (getGameType() == GType_PP && getGameId() != GID_DIMP) { if (!getBitFlag(110)) { setBitFlag(107, !getBitFlag(107)); @@ -551,73 +551,77 @@ bool AGOSEngine::processSpecialKeys() { } } break; - case 'p': + case Common::KEYCODE_p: pause(); break; - case 't': + case Common::KEYCODE_t: if (getGameType() == GType_FF || (getGameType() == GType_SIMON2 && (getFeatures() & GF_TALKIE)) || ((getFeatures() & GF_TALKIE) && _language != Common::EN_ANY && _language != Common::DE_DEU)) { if (_speech) _subtitles ^= 1; } break; - case 'v': + case Common::KEYCODE_v: if (getGameType() == GType_FF || (getGameType() == GType_SIMON2 && (getFeatures() & GF_TALKIE))) { if (_subtitles) _speech ^= 1; } - case '+': + case Common::KEYCODE_PLUS: + case Common::KEYCODE_KP_PLUS: if (_midiEnabled) { _midi.setVolume(_midi.getVolume() + 16); } _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) + 16); break; - case '-': + case Common::KEYCODE_MINUS: + case Common::KEYCODE_KP_MINUS: if (_midiEnabled) { _midi.setVolume(_midi.getVolume() - 16); } _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType) - 16); break; - case 'm': + case Common::KEYCODE_m: _musicPaused ^= 1; if (_midiEnabled) { _midi.pause(_musicPaused); } _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, (_musicPaused) ? 0 : ConfMan.getInt("music_volume")); break; - case 's': + case Common::KEYCODE_s: if (getGameId() == GID_SIMON1DOS) { _midi._enable_sfx ^= 1; } else { _sound->effectsPause(_effectsPaused ^= 1); } break; - case 'b': + case Common::KEYCODE_b: _sound->ambientPause(_ambientPaused ^= 1); break; - case 'r': + case Common::KEYCODE_r: if (_debugMode) _startMainScript ^= 1; break; - case 'o': + case Common::KEYCODE_o: if (_debugMode) _continousMainScript ^= 1; break; - case 'a': + case Common::KEYCODE_a: if (_debugMode) _startVgaScript ^= 1; break; - case 'g': + case Common::KEYCODE_g: if (_debugMode) _continousVgaScript ^= 1; break; - case 'd': + case Common::KEYCODE_d: if (_debugMode) _dumpImages ^=1; break; + default: + break; } - _keyPressed = 0; + _keyPressed.reset(); return verbCode; } diff --git a/engines/agos/intern.h b/engines/agos/intern.h index a863dc7c0f..44d38fbeed 100644 --- a/engines/agos/intern.h +++ b/engines/agos/intern.h @@ -28,6 +28,20 @@ namespace AGOS { +enum ChildType { + kRoomType = 1, + kObjectType = 2, + kPlayerType = 3, + kGenExitType = 4, // Elvira 1 specific + kSuperRoomType = 4, // Elvira 2 specific + + kContainerType = 7, + kChainType = 8, + kUserFlagType = 9, + + kInheritType = 255 +}; + struct Child { Child *next; uint16 type; diff --git a/engines/agos/items.cpp b/engines/agos/items.cpp index a911bee5a5..9a46b6e8ac 100644 --- a/engines/agos/items.cpp +++ b/engines/agos/items.cpp @@ -66,7 +66,7 @@ bool AGOSEngine::hasIcon(Item *item) { if (getGameType() == GType_ELVIRA1) { return (getUserFlag(item, 7) != 0); } else { - SubObject *child = (SubObject *)findChildOfType(item, 2); + SubObject *child = (SubObject *)findChildOfType(item, kObjectType); return (child && (child->objectFlags & kOFIcon) != 0); } } @@ -75,7 +75,7 @@ uint AGOSEngine::itemGetIconNumber(Item *item) { if (getGameType() == GType_ELVIRA1) { return getUserFlag(item, 7); } else { - SubObject *child = (SubObject *)findChildOfType(item, 2); + SubObject *child = (SubObject *)findChildOfType(item, kObjectType); uint offs; if (child == NULL || !(child->objectFlags & kOFIcon)) @@ -97,7 +97,7 @@ void AGOSEngine::createPlayer() { _currentPlayer->adjective = -1; _currentPlayer->noun = 10000; - p = (SubPlayer *)allocateChildBlock(_currentPlayer, 3, sizeof(SubPlayer)); + p = (SubPlayer *)allocateChildBlock(_currentPlayer, kPlayerType, sizeof(SubPlayer)); if (p == NULL) error("createPlayer: player create failure"); @@ -135,14 +135,14 @@ Child *AGOSEngine::findChildOfType(Item *i, uint type) { int AGOSEngine::getUserFlag(Item *item, int a) { SubUserFlag *subUserFlag; - subUserFlag = (SubUserFlag *) findChildOfType(item, 9); + subUserFlag = (SubUserFlag *)findChildOfType(item, kUserFlagType); if (subUserFlag == NULL) return 0; if (a < 0 || a > 7) return 0; - return subUserFlag->userFlags[a]; + return subUserFlag->userFlags[a]; } int AGOSEngine::getUserFlag1(Item *item, int a) { @@ -151,7 +151,7 @@ int AGOSEngine::getUserFlag1(Item *item, int a) { if (item == NULL || item == _dummyItem2 || item == _dummyItem3) return -1; - subUserFlag = (SubUserFlag *) findChildOfType(item, 9); + subUserFlag = (SubUserFlag *)findChildOfType(item, kUserFlagType); if (subUserFlag == NULL) return 0; @@ -164,9 +164,9 @@ int AGOSEngine::getUserFlag1(Item *item, int a) { void AGOSEngine::setUserFlag(Item *item, int a, int b) { SubUserFlag *subUserFlag; - subUserFlag = (SubUserFlag *) findChildOfType(item, 9); + subUserFlag = (SubUserFlag *)findChildOfType(item, kUserFlagType); if (subUserFlag == NULL) { - subUserFlag = (SubUserFlag *) allocateChildBlock(item, 9, sizeof(SubUserFlag)); + subUserFlag = (SubUserFlag *)allocateChildBlock(item, kUserFlagType, sizeof(SubUserFlag)); } if (a < 0 || a > 7) @@ -178,7 +178,7 @@ void AGOSEngine::setUserFlag(Item *item, int a, int b) { int AGOSEngine::getUserItem(Item *item, int n) { SubUserFlag *subUserFlag; - subUserFlag = (SubUserFlag *) findChildOfType(item, 9); + subUserFlag = (SubUserFlag *)findChildOfType(item, kUserFlagType); if (subUserFlag == NULL) return 0; @@ -191,9 +191,9 @@ int AGOSEngine::getUserItem(Item *item, int n) { void AGOSEngine::setUserItem(Item *item, int n, int m) { SubUserFlag *subUserFlag; - subUserFlag = (SubUserFlag *) findChildOfType(item, 9); + subUserFlag = (SubUserFlag *)findChildOfType(item, kUserFlagType); if (subUserFlag == NULL) { - subUserFlag = (SubUserFlag *) allocateChildBlock(item, 9, sizeof(SubUserFlag)); + subUserFlag = (SubUserFlag *)allocateChildBlock(item, kUserFlagType, sizeof(SubUserFlag)); } if (n == 0) @@ -201,15 +201,15 @@ void AGOSEngine::setUserItem(Item *item, int n, int m) { } bool AGOSEngine::isRoom(Item *item) { - return findChildOfType(item, 1) != NULL; + return findChildOfType(item, kRoomType) != NULL; } bool AGOSEngine::isObject(Item *item) { - return findChildOfType(item, 2) != NULL; + return findChildOfType(item, kObjectType) != NULL; } bool AGOSEngine::isPlayer(Item *item) { - return findChildOfType(item, 3) != NULL; + return findChildOfType(item, kPlayerType) != NULL; } uint AGOSEngine::getOffsetOfChild2Param(SubObject *child, uint prop) { diff --git a/engines/agos/menus.cpp b/engines/agos/menus.cpp index 6dd1a356d8..81df34c311 100644 --- a/engines/agos/menus.cpp +++ b/engines/agos/menus.cpp @@ -199,7 +199,7 @@ uint AGOSEngine::menuFor_e2(Item *item) { if (item == NULL || item == _dummyItem2 || item == _dummyItem3) return 0xFFFF; - SubObject *subObject = (SubObject *)findChildOfType(item, 2); + SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType); if (subObject != NULL && subObject->objectFlags & kOFMenu) { uint offs = getOffsetOfChild2Param(subObject, kOFMenu); return subObject->objectFlagValue[offs]; @@ -216,7 +216,7 @@ uint AGOSEngine::menuFor_ww(Item *item, uint id) { if (item == NULL || item == _dummyItem2 || item == _dummyItem3) return _agosMenu; - SubObject *subObject = (SubObject *)findChildOfType(item, 2); + SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType); if (subObject != NULL && subObject->objectFlags & kOFMenu) { uint offs = getOffsetOfChild2Param(subObject, kOFMenu); return subObject->objectFlagValue[offs]; diff --git a/engines/agos/oracle.cpp b/engines/agos/oracle.cpp index 787596a966..c7ad0ee8b7 100644 --- a/engines/agos/oracle.cpp +++ b/engines/agos/oracle.cpp @@ -464,37 +464,37 @@ void AGOSEngine_Feeble::saveUserGame(int slot) { windowPutChar(window, 0x7f); for (;;) { - _keyPressed = 0; + _keyPressed.reset(); delay(1); - if (_keyPressed == 0 || _keyPressed >= 127) + if (_keyPressed.ascii == 0 || _keyPressed.ascii >= 127) continue; window->textColumn -= getFeebleFontSize(127); name[len] = 0; windowBackSpace(_windowArray[3]); - if (_keyPressed == 27) { - _variableArray[55] = _keyPressed; + if (_keyPressed.keycode == Common::KEYCODE_ESCAPE) { + _variableArray[55] = 27; break; } - if (_keyPressed == 10 || _keyPressed == 13) { + if (_keyPressed.keycode == Common::KEYCODE_KP_ENTER || _keyPressed.keycode == Common::KEYCODE_RETURN) { if (!saveGame(readVariable(55), name)) _variableArray[55] = (int16)0xFFFF; else _variableArray[55] = 0; break; } - if (_keyPressed == 8 && len != 0) { + if (_keyPressed.keycode == Common::KEYCODE_BACKSPACE && len != 0) { len--; byte chr = name[len]; window->textColumn -= getFeebleFontSize(chr); name[len] = 0; windowBackSpace(_windowArray[3]); } - if (_keyPressed >= 32 && window->textColumn + 26 <= window->width) { - name[len++] = _keyPressed; - windowPutChar(_windowArray[3], _keyPressed); + if (_keyPressed.ascii >= 32 && window->textColumn + 26 <= window->width) { + name[len++] = _keyPressed.ascii; + windowPutChar(_windowArray[3], _keyPressed.ascii); } windowPutChar(window, 0x7f); diff --git a/engines/agos/res.cpp b/engines/agos/res.cpp index 394c4956ae..4898cc9a45 100644 --- a/engines/agos/res.cpp +++ b/engines/agos/res.cpp @@ -350,13 +350,13 @@ void AGOSEngine::readItemFromGamePc(Common::SeekableReadStream *in, Item *item) } void AGOSEngine::readItemChildren(Common::SeekableReadStream *in, Item *item, uint type) { - if (type == 1) { - SubRoom *subRoom = (SubRoom *)allocateChildBlock(item, 1, sizeof(SubRoom)); + if (type == kRoomType) { + SubRoom *subRoom = (SubRoom *)allocateChildBlock(item, kRoomType, sizeof(SubRoom)); subRoom->roomShort = in->readUint32BE(); subRoom->roomLong = in->readUint32BE(); subRoom->flags = in->readUint16BE(); - } else if (type == 2) { - SubObject *subObject = (SubObject *)allocateChildBlock(item, 2, sizeof(SubObject)); + } else if (type == kObjectType) { + SubObject *subObject = (SubObject *)allocateChildBlock(item, kObjectType, sizeof(SubObject)); in->readUint32BE(); in->readUint32BE(); in->readUint32BE(); @@ -364,8 +364,8 @@ void AGOSEngine::readItemChildren(Common::SeekableReadStream *in, Item *item, ui subObject->objectSize = in->readUint16BE(); subObject->objectWeight = in->readUint16BE(); subObject->objectFlags = in->readUint16BE(); - } else if (type == 4) { - SubGenExit *genExit = (SubGenExit *)allocateChildBlock(item, 4, sizeof(SubGenExit)); + } else if (type == kGenExitType) { + SubGenExit *genExit = (SubGenExit *)allocateChildBlock(item, kGenExitType, sizeof(SubGenExit)); genExit->dest[0] = (uint16)fileReadItemID(in); genExit->dest[1] = (uint16)fileReadItemID(in); genExit->dest[2] = (uint16)fileReadItemID(in); @@ -378,14 +378,14 @@ void AGOSEngine::readItemChildren(Common::SeekableReadStream *in, Item *item, ui fileReadItemID(in); fileReadItemID(in); fileReadItemID(in); - } else if (type == 7) { - SubContainer *container = (SubContainer *)allocateChildBlock(item, 7, sizeof(SubContainer)); + } else if (type == kContainerType) { + SubContainer *container = (SubContainer *)allocateChildBlock(item, kContainerType, sizeof(SubContainer)); container->volume = in->readUint16BE(); container->flags = in->readUint16BE(); - } else if (type == 8) { - SubChain *chain = (SubChain *)allocateChildBlock(item, 8, sizeof(SubChain)); + } else if (type == kChainType) { + SubChain *chain = (SubChain *)allocateChildBlock(item, kChainType, sizeof(SubChain)); chain->chChained = (uint16)fileReadItemID(in); - } else if (type == 9) { + } else if (type == kUserFlagType) { setUserFlag(item, 0, in->readUint16BE()); setUserFlag(item, 1, in->readUint16BE()); setUserFlag(item, 2, in->readUint16BE()); @@ -394,13 +394,13 @@ void AGOSEngine::readItemChildren(Common::SeekableReadStream *in, Item *item, ui setUserFlag(item, 5, in->readUint16BE()); setUserFlag(item, 6, in->readUint16BE()); setUserFlag(item, 7, in->readUint16BE()); - SubUserFlag *subUserFlag = (SubUserFlag *) findChildOfType(item, 9); + SubUserFlag *subUserFlag = (SubUserFlag *)findChildOfType(item, kUserFlagType); subUserFlag->userItems[0] = (uint16)fileReadItemID(in); fileReadItemID(in); fileReadItemID(in); fileReadItemID(in); - } else if (type == 255) { - SubInherit *inherit = (SubInherit *)allocateChildBlock(item, 255, sizeof(SubInherit)); + } else if (type == kInheritType) { + SubInherit *inherit = (SubInherit *)allocateChildBlock(item, kInheritType, sizeof(SubInherit)); inherit->inMaster = (uint16)fileReadItemID(in); } else { error("readItemChildren: invalid type %d", type); @@ -408,7 +408,7 @@ void AGOSEngine::readItemChildren(Common::SeekableReadStream *in, Item *item, ui } void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item *item, uint type) { - if (type == 1) { + if (type == kRoomType) { uint fr1 = in->readUint16BE(); uint fr2 = in->readUint16BE(); uint i, size; @@ -420,14 +420,14 @@ void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item * if (j & 3) size += sizeof(subRoom->roomExit[0]); - subRoom = (SubRoom *)allocateChildBlock(item, 1, size); + subRoom = (SubRoom *)allocateChildBlock(item, kRoomType, size); subRoom->subroutine_id = fr1; subRoom->roomExitStates = fr2; for (i = k = 0, j = fr2; i != 6; i++, j >>= 2) if (j & 3) subRoom->roomExit[k++] = (uint16)fileReadItemID(in); - } else if (type == 2) { + } else if (type == kObjectType) { uint32 fr = in->readUint32BE(); uint i, k, size; SubObject *subObject; @@ -437,7 +437,7 @@ void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item * if (fr & (1 << i)) size += sizeof(subObject->objectFlagValue[0]); - subObject = (SubObject *)allocateChildBlock(item, 2, size); + subObject = (SubObject *)allocateChildBlock(item, kObjectType, size); subObject->objectFlags = fr; k = 0; @@ -450,7 +450,7 @@ void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item * if (getGameType() != GType_ELVIRA2) subObject->objectName = (uint16)in->readUint32BE(); - } else if (type == 4) { + } else if (type == kSuperRoomType) { assert(getGameType() == GType_ELVIRA2); uint i, j, k, size; @@ -467,7 +467,7 @@ void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item * for (i = 0; i != j; i++) size += sizeof(subSuperRoom->roomExitStates[0]); - subSuperRoom = (SubSuperRoom *)allocateChildBlock(item, 4, size); + subSuperRoom = (SubSuperRoom *)allocateChildBlock(item, kSuperRoomType, size); subSuperRoom->subroutine_id = id; subSuperRoom->roomX = x; subSuperRoom->roomY = y; @@ -475,20 +475,20 @@ void AGOSEngine_Elvira2::readItemChildren(Common::SeekableReadStream *in, Item * for (i = k = 0; i != j; i++) subSuperRoom->roomExitStates[k++] = in->readUint16BE(); - } else if (type == 7) { - SubContainer *container = (SubContainer *)allocateChildBlock(item, 7, sizeof(SubContainer)); + } else if (type == kContainerType) { + SubContainer *container = (SubContainer *)allocateChildBlock(item, kContainerType, sizeof(SubContainer)); container->volume = in->readUint16BE(); container->flags = in->readUint16BE(); - } else if (type == 8) { - SubChain *chain = (SubChain *)allocateChildBlock(item, 8, sizeof(SubChain)); + } else if (type == kChainType) { + SubChain *chain = (SubChain *)allocateChildBlock(item, kChainType, sizeof(SubChain)); chain->chChained = (uint16)fileReadItemID(in); - } else if (type == 9) { + } else if (type == kUserFlagType) { setUserFlag(item, 0, in->readUint16BE()); setUserFlag(item, 1, in->readUint16BE()); setUserFlag(item, 2, in->readUint16BE()); setUserFlag(item, 3, in->readUint16BE()); - } else if (type == 255) { - SubInherit *inherit = (SubInherit *)allocateChildBlock(item, 255, sizeof(SubInherit)); + } else if (type == kInheritType) { + SubInherit *inherit = (SubInherit *)allocateChildBlock(item, kInheritType, sizeof(SubInherit)); inherit->inMaster = (uint16)fileReadItemID(in); } else { error("readItemChildren: invalid type %d", type); diff --git a/engines/agos/rooms.cpp b/engines/agos/rooms.cpp index af1bd0fe93..5e612080df 100644 --- a/engines/agos/rooms.cpp +++ b/engines/agos/rooms.cpp @@ -49,7 +49,7 @@ uint16 AGOSEngine::getDoorState(Item *item, uint16 d) { uint16 mask = 3; uint16 n; - SubRoom *subRoom = (SubRoom *)findChildOfType(item, 1); + SubRoom *subRoom = (SubRoom *)findChildOfType(item, kRoomType); if (subRoom == NULL) return 0; @@ -66,7 +66,7 @@ uint16 AGOSEngine::getExitOf(Item *item, uint16 d) { uint16 x; uint16 y = 0; - subRoom = (SubRoom *)findChildOfType(item, 1); + subRoom = (SubRoom *)findChildOfType(item, kRoomType); if (subRoom == NULL) return 0; x = d; @@ -93,7 +93,7 @@ void AGOSEngine::setDoorState(Item *i, uint16 d, uint16 n) { uint16 d1; uint16 y = 0; - r = (SubRoom *)findChildOfType(i, 1); + r = (SubRoom *)findChildOfType(i, kRoomType); if (r == NULL) return; d1 = d; @@ -107,7 +107,7 @@ void AGOSEngine::setDoorState(Item *i, uint16 d, uint16 n) { j = derefItem(r->roomExit[d1]); if (j == NULL) return; - r1 = (SubRoom *)findChildOfType(j, 1); + r1 = (SubRoom *)findChildOfType(j, kRoomType); if (r1 == NULL) return; d = getBackExit(d); @@ -130,7 +130,7 @@ Item *AGOSEngine::getDoorOf(Item *i, uint16 d) { SubGenExit *g; Item *x; - g = (SubGenExit *)findChildOfType(i, 4); + g = (SubGenExit *)findChildOfType(i, kGenExitType); if (g == NULL) return 0; @@ -146,7 +146,7 @@ Item *AGOSEngine::getExitOf_e1(Item *item, uint16 d) { SubGenExit *g; Item *x; - g = (SubGenExit *)findChildOfType(item, 4); + g = (SubGenExit *)findChildOfType(item, kGenExitType); if (g == NULL) return 0; @@ -192,10 +192,10 @@ void AGOSEngine_Elvira2::moveDirn(Item *i, uint x) { return; p = derefItem(i->parent); - if (findChildOfType(p, 4)) { + if (findChildOfType(p, kSuperRoomType)) { n = getExitState(p, _superRoomNumber,x); if (n == 1) { - sr = (SubSuperRoom *)findChildOfType(p, 4); + sr = (SubSuperRoom *)findChildOfType(p, kSuperRoomType); switch (x) { case 0: a = -(sr->roomX); break; case 1: a = 1; break; @@ -319,7 +319,7 @@ uint16 AGOSEngine_Elvira2::getExitState(Item *i, uint16 x, uint16 d) { uint16 mask = 3; uint16 n; - sr = (SubSuperRoom *)findChildOfType(i, 4); + sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType); if (sr == NULL) return 0; @@ -331,7 +331,7 @@ uint16 AGOSEngine_Elvira2::getExitState(Item *i, uint16 x, uint16 d) { } void AGOSEngine_Elvira2::setExitState(Item *i, uint16 n, uint16 d, uint16 s) { - SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, 4); + SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType); if (sr) changeExitStates(sr, n, d, s); } @@ -339,7 +339,7 @@ void AGOSEngine_Elvira2::setExitState(Item *i, uint16 n, uint16 d, uint16 s) { void AGOSEngine_Elvira2::setSRExit(Item *i, int n, int d, uint16 s) { uint16 mask = 3; - SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, 4); + SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType); if (sr) { n--; d <<= 1; diff --git a/engines/agos/saveload.cpp b/engines/agos/saveload.cpp index eb2266550a..32b767073a 100644 --- a/engines/agos/saveload.cpp +++ b/engines/agos/saveload.cpp @@ -257,12 +257,12 @@ restart: for (;;) { windowPutChar(window, 128); - _keyPressed = 0; + _keyPressed.reset(); for (;;) { delay(10); - if (_keyPressed && _keyPressed < 128) { - i = _keyPressed; + if (_keyPressed.ascii && _keyPressed.ascii < 128) { + i = _keyPressed.ascii; break; } } @@ -490,16 +490,16 @@ int AGOSEngine_Elvira2::userGameGetKey(bool *b, char *buf, uint maxChar) { HitArea *ha; *b = true; - _keyPressed = 0; + _keyPressed.reset(); for (;;) { _lastHitArea = NULL; _lastHitArea3 = NULL; do { - if (_saveLoadEdit && _keyPressed && _keyPressed < maxChar) { + if (_saveLoadEdit && _keyPressed.ascii && _keyPressed.ascii < maxChar) { *b = false; - return _keyPressed; + return _keyPressed.ascii; } delay(10); } while (_lastHitArea3 == 0); @@ -759,16 +759,16 @@ int AGOSEngine_Simon1::userGameGetKey(bool *b, char *buf, uint maxChar) { listSaveGames(buf); } - _keyPressed = 0; + _keyPressed.reset(); for (;;) { _lastHitArea = NULL; _lastHitArea3 = NULL; do { - if (_saveLoadEdit && _keyPressed && _keyPressed < maxChar) { + if (_saveLoadEdit && _keyPressed.ascii && _keyPressed.ascii < maxChar) { *b = false; - return _keyPressed; + return _keyPressed.ascii; } delay(10); } while (_lastHitArea3 == 0); @@ -999,13 +999,13 @@ bool AGOSEngine::loadGame(const char *filename, bool restartMode) { item->state = f->readUint16BE(); item->classFlags = f->readUint16BE(); - SubObject *o = (SubObject *)findChildOfType(item, 2); + SubObject *o = (SubObject *)findChildOfType(item, kObjectType); if (o) { o->objectSize = f->readUint16BE(); o->objectWeight = f->readUint16BE(); } - SubPlayer *p = (SubPlayer *)findChildOfType(item, 3); + SubPlayer *p = (SubPlayer *)findChildOfType(item, kPlayerType); if (p) { p->score = f->readUint32BE(); p->level = f->readUint16BE(); @@ -1014,7 +1014,7 @@ bool AGOSEngine::loadGame(const char *filename, bool restartMode) { p->strength = f->readUint16BE(); } - SubUserFlag *u = (SubUserFlag *) findChildOfType(item, 9); + SubUserFlag *u = (SubUserFlag *)findChildOfType(item, kUserFlagType); if (u) { for (i = 0; i != 8; i++) { u->userFlags[i] = f->readUint16BE(); @@ -1083,13 +1083,13 @@ bool AGOSEngine::saveGame(uint slot, const char *caption) { f->writeUint16BE(item->state); f->writeUint16BE(item->classFlags); - SubObject *o = (SubObject *)findChildOfType(item, 2); + SubObject *o = (SubObject *)findChildOfType(item, kObjectType); if (o) { f->writeUint16BE(o->objectSize); f->writeUint16BE(o->objectWeight); } - SubPlayer *p = (SubPlayer *)findChildOfType(item, 3); + SubPlayer *p = (SubPlayer *)findChildOfType(item, kPlayerType); if (p) { f->writeUint32BE(p->score); f->writeUint16BE(p->level); @@ -1098,7 +1098,7 @@ bool AGOSEngine::saveGame(uint slot, const char *caption) { f->writeUint16BE(p->strength); } - SubUserFlag *u = (SubUserFlag *) findChildOfType(item, 9); + SubUserFlag *u = (SubUserFlag *)findChildOfType(item, kUserFlagType); if (u) { for (i = 0; i != 8; i++) { f->writeUint16BE(u->userFlags[i]); @@ -1204,19 +1204,19 @@ bool AGOSEngine_Elvira2::loadGame(const char *filename, bool restartMode) { item->state = f->readUint16BE(); item->classFlags = f->readUint16BE(); - SubRoom *r = (SubRoom *)findChildOfType(item, 1); + SubRoom *r = (SubRoom *)findChildOfType(item, kRoomType); if (r) { r->roomExitStates = f->readUint16BE(); } - SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(item, 4); + SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(item, kSuperRoomType); if (sr) { uint16 n = sr->roomX * sr->roomY * sr->roomZ; for (i = j = 0; i != n; i++) sr->roomExitStates[j++] = f->readUint16BE(); } - SubObject *o = (SubObject *)findChildOfType(item, 2); + SubObject *o = (SubObject *)findChildOfType(item, kObjectType); if (o) { o->objectFlags = f->readUint32BE(); i = o->objectFlags & 1; @@ -1228,7 +1228,7 @@ bool AGOSEngine_Elvira2::loadGame(const char *filename, bool restartMode) { } } - SubUserFlag *u = (SubUserFlag *) findChildOfType(item, 9); + SubUserFlag *u = (SubUserFlag *)findChildOfType(item, kUserFlagType); if (u) { for (i = 0; i != 4; i++) { u->userFlags[i] = f->readUint16BE(); @@ -1283,9 +1283,12 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) { Common::OutSaveFile *f; uint item_index, num_item, i, j; TimeEvent *te; - uint32 curTime = 0; uint32 gsc = _gameStoppedClock; + uint32 curTime = 0; + if (getGameType() != GType_SIMON1 && getGameType() != GType_SIMON2) + curTime = time(NULL); + _lockWord |= 0x100; f = _saveFileMan->openForSaving(genSaveName(slot)); @@ -1299,7 +1302,6 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) { // No caption } else if (getGameType() == GType_FF) { f->write(caption, 100); - curTime = time(NULL); } else if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { f->write(caption, 18); } else { @@ -1308,7 +1310,7 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) { f->writeUint32BE(_itemArrayInited - 1); f->writeUint32BE(0xFFFFFFFF); - f->writeUint32BE(0); + f->writeUint32BE(curTime); f->writeUint32BE(0); i = 0; @@ -1345,19 +1347,19 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) { f->writeUint16BE(item->state); f->writeUint16BE(item->classFlags); - SubRoom *r = (SubRoom *)findChildOfType(item, 1); + SubRoom *r = (SubRoom *)findChildOfType(item, kRoomType); if (r) { f->writeUint16BE(r->roomExitStates); } - SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(item, 4); + SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(item, kSuperRoomType); if (sr) { uint16 n = sr->roomX * sr->roomY * sr->roomZ; for (i = j = 0; i != n; i++) f->writeUint16BE(sr->roomExitStates[j++]); } - SubObject *o = (SubObject *)findChildOfType(item, 2); + SubObject *o = (SubObject *)findChildOfType(item, kObjectType); if (o) { f->writeUint32BE(o->objectFlags); i = o->objectFlags & 1; @@ -1369,7 +1371,7 @@ bool AGOSEngine_Elvira2::saveGame(uint slot, const char *caption) { } } - SubUserFlag *u = (SubUserFlag *)findChildOfType(item, 9); + SubUserFlag *u = (SubUserFlag *)findChildOfType(item, kUserFlagType); if (u) { for (i = 0; i != 4; i++) { f->writeUint16BE(u->userFlags[i]); diff --git a/engines/agos/script.cpp b/engines/agos/script.cpp index c5cf6c5872..ace0b9d50f 100644 --- a/engines/agos/script.cpp +++ b/engines/agos/script.cpp @@ -206,7 +206,7 @@ void AGOSEngine::o_state() { void AGOSEngine::o_oflag() { // 28: item has prop - SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); + SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType); uint num = getVarOrByte(); setScriptCondition(subObject != NULL && (subObject->objectFlags & (1 << num)) != 0); } @@ -326,7 +326,7 @@ void AGOSEngine::o_goto() { void AGOSEngine::o_oset() { // 56: set child2 fr bit - SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); + SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType); int value = getVarOrByte(); if (subObject != NULL && value >= 16) subObject->objectFlags |= (1 << value); @@ -334,7 +334,7 @@ void AGOSEngine::o_oset() { void AGOSEngine::o_oclear() { // 57: clear child2 fr bit - SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); + SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType); int value = getVarOrByte(); if (subObject != NULL && value >= 16) subObject->objectFlags &= ~(1 << value); @@ -426,7 +426,7 @@ void AGOSEngine::o_if2() { void AGOSEngine::o_isCalled() { // 79: childstruct fr2 is - SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); + SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType); uint stringId = getNextStringID(); setScriptCondition((subObject != NULL) && subObject->objectName == stringId); } @@ -753,7 +753,7 @@ void AGOSEngine::o_setAdjNoun() { void AGOSEngine::o_saveUserGame() { // 132: save user game if (getGameId() == GID_SIMON1CD32) { - // The Amiga CD32 version of Simon the Sorcerer 1uses a single slot + // The Amiga CD32 version of Simon the Sorcerer 1 uses a single slot if (!saveGame(0, "Default Saved Game")) { vc33_setMouseOn(); fileError(_windowArray[5], true); @@ -799,7 +799,7 @@ void AGOSEngine::o_freezeZones() { freezeBottom(); if (!_copyProtection && !(getFeatures() & GF_TALKIE)) { - if ((getGameType() == GType_SIMON1 && _subroutine == 2924) || + if ((getGameType() == GType_SIMON1 && _subroutine == 2924) || (getGameType() == GType_SIMON2 && _subroutine == 1322)) { _variableArray[134] = 3; _variableArray[135] = 3; @@ -985,10 +985,10 @@ Child *nextSub(Child *sub, int16 key) { } void AGOSEngine::synchChain(Item *i) { - SubChain *c = (SubChain *)findChildOfType(i, 8); + SubChain *c = (SubChain *)findChildOfType(i, kChainType); while (c) { setItemState(derefItem(c->chChained), i->state); - c = (SubChain *)nextSub((Child *)c, 8); + c = (SubChain *)nextSub((Child *)c, kChainType); } } diff --git a/engines/agos/script_e1.cpp b/engines/agos/script_e1.cpp index b003a7262f..5a1d7d104b 100644 --- a/engines/agos/script_e1.cpp +++ b/engines/agos/script_e1.cpp @@ -419,7 +419,7 @@ void AGOSEngine_Elvira1::oe1_notPresent() { void AGOSEngine_Elvira1::oe1_worn() { // 4: worn Item *item = getNextItemPtr(); - SubObject *subObject = (SubObject *)findChildOfType(item, 2); + SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType); if (item->parent != getItem1ID() || subObject == NULL) setScriptCondition(false); @@ -430,7 +430,7 @@ void AGOSEngine_Elvira1::oe1_worn() { void AGOSEngine_Elvira1::oe1_notWorn() { // 5: not worn Item *item = getNextItemPtr(); - SubObject *subObject = (SubObject *)findChildOfType(item, 2); + SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType); if (item->parent != getItem1ID() || subObject == NULL) setScriptCondition(false); @@ -532,7 +532,7 @@ void AGOSEngine_Elvira1::oe1_moveDirn() { void AGOSEngine_Elvira1::oe1_score() { // 90: score - SubPlayer *p = (SubPlayer *) findChildOfType(me(), 3); + SubPlayer *p = (SubPlayer *)findChildOfType(me(), kPlayerType); showMessageFormat("Your score is %ld.\n", p->score); } @@ -542,9 +542,9 @@ void AGOSEngine_Elvira1::oe1_look() { if (i == NULL) return; - SubRoom *r = (SubRoom *)findChildOfType(i, 1); - SubObject *o = (SubObject *)findChildOfType(i, 2); - SubPlayer *p = (SubPlayer *)findChildOfType(i, 3); + SubRoom *r = (SubRoom *)findChildOfType(i, kRoomType); + SubObject *o = (SubObject *)findChildOfType(i, kObjectType); + SubPlayer *p = (SubPlayer *)findChildOfType(i, kPlayerType); if (p == NULL) return; @@ -594,7 +594,7 @@ void AGOSEngine_Elvira1::oe1_doClass() { void AGOSEngine_Elvira1::oe1_pObj() { // 112: print object - SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); + SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType); getVarOrWord(); if (subObject != NULL) @@ -624,7 +624,7 @@ void AGOSEngine_Elvira1::oe1_isCalled() { void AGOSEngine_Elvira1::oe1_cFlag() { // 162: check container flag - SubContainer *c = (SubContainer *)findChildOfType(getNextItemPtr(), 7); + SubContainer *c = (SubContainer *)findChildOfType(getNextItemPtr(), kContainerType); uint bit = getVarOrWord(); if (c == NULL) @@ -678,7 +678,7 @@ void AGOSEngine_Elvira1::oe1_doorExit() { int16 f = getVarOrWord(); int16 ct = 0; - c = (SubChain *)findChildOfType(d, 8); + c = (SubChain *)findChildOfType(d, kChainType); if (c) a = derefItem(c->chChained); while (ct < 6) { @@ -986,7 +986,7 @@ void AGOSEngine_Elvira1::oe1_printMonsterHit() { } int16 AGOSEngine::levelOf(Item *item) { - SubPlayer *p = (SubPlayer *) findChildOfType(item, 3); + SubPlayer *p = (SubPlayer *)findChildOfType(item, kPlayerType); if (p == NULL) return 0; @@ -998,7 +998,7 @@ int16 AGOSEngine::moreText(Item *i) { i = derefItem(i->next); while (i) { - o = (SubObject *)findChildOfType(i, 2); + o = (SubObject *)findChildOfType(i, kObjectType); if ((o) && (o->objectFlags & 1)) goto l1; if (i != me()) @@ -1014,7 +1014,7 @@ void AGOSEngine::lobjFunc(Item *i, const char *f) { SubObject *o; while (i) { - o = (SubObject *)findChildOfType(i, 2); + o = (SubObject *)findChildOfType(i, kObjectType); if ((o) && (o->objectFlags & 1)) goto l1; if (i == me()) diff --git a/engines/agos/script_e2.cpp b/engines/agos/script_e2.cpp index 00f0848ed9..77df3feecb 100644 --- a/engines/agos/script_e2.cpp +++ b/engines/agos/script_e2.cpp @@ -132,7 +132,7 @@ void AGOSEngine_Elvira2::setupOpcodes() { OPCODE(o_when), OPCODE(o_if1), OPCODE(o_if2), - OPCODE(oe1_isCalled), + OPCODE(oe2_isCalled), /* 80 */ OPCODE(o_is), OPCODE(o_invalid), @@ -165,7 +165,7 @@ void AGOSEngine_Elvira2::setupOpcodes() { OPCODE(o_cls), /* 104 */ OPCODE(o_closeWindow), - OPCODE(o_invalid), + OPCODE(oe2_menu), OPCODE(o_invalid), OPCODE(o_addBox), /* 108 */ @@ -309,12 +309,19 @@ void AGOSEngine_Elvira2::oe2_doClass() { void AGOSEngine_Elvira2::oe2_pObj() { // 73: print object - SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); + SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType); if (subObject != NULL && subObject->objectFlags & kOFText) showMessageFormat("%s\n", (const char *)getStringPtrByID(subObject->objectFlagValue[0])); // Difference } +void AGOSEngine_Elvira2::oe2_isCalled() { + // 79: childstruct fr2 is + Item *i = getNextItemPtr(); + uint stringId = getNextStringID(); + setScriptCondition(i->itemName == stringId); +} + void AGOSEngine_Elvira2::oe2_loadGame() { // 89: load game uint16 stringId = getNextStringID(); @@ -326,6 +333,11 @@ void AGOSEngine_Elvira2::oe2_loadGame() { } } +void AGOSEngine_Elvira2::oe2_menu() { + // 105: set agos menu + _agosMenu = getVarOrByte(); +} + void AGOSEngine_Elvira2::oe2_drawItem() { // 113: draw item Item *i = getNextItemPtr(); @@ -341,7 +353,7 @@ void AGOSEngine_Elvira2::oe2_doTable() { // 143: start item sub Item *i = getNextItemPtr(); - SubRoom *r = (SubRoom *)findChildOfType(i, 1); + SubRoom *r = (SubRoom *)findChildOfType(i, kRoomType); if (r != NULL) { Subroutine *sub = getSubroutineByID(r->subroutine_id); if (sub) { @@ -351,7 +363,7 @@ void AGOSEngine_Elvira2::oe2_doTable() { } if (getGameType() == GType_ELVIRA2) { - SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, 4); + SubSuperRoom *sr = (SubSuperRoom *)findChildOfType(i, kSuperRoomType); if (sr != NULL) { Subroutine *sub = getSubroutineByID(sr->subroutine_id); if (sub) { @@ -478,7 +490,7 @@ void AGOSEngine_Elvira2::oe2_bNotZero() { void AGOSEngine_Elvira2::oe2_getOValue() { // 157: get item int prop Item *item = getNextItemPtr(); - SubObject *subObject = (SubObject *)findChildOfType(item, 2); + SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType); uint prop = getVarOrByte(); if (subObject != NULL && subObject->objectFlags & (1 << prop) && prop < 16) { @@ -492,7 +504,7 @@ void AGOSEngine_Elvira2::oe2_getOValue() { void AGOSEngine_Elvira2::oe2_setOValue() { // 158: set item prop Item *item = getNextItemPtr(); - SubObject *subObject = (SubObject *)findChildOfType(item, 2); + SubObject *subObject = (SubObject *)findChildOfType(item, kObjectType); uint prop = getVarOrByte(); int value = getVarOrWord(); @@ -640,6 +652,16 @@ void AGOSEngine_Elvira2::oe2_isAdjNoun() { // 179: item unk1 unk2 is Item *item = getNextItemPtr(); int16 a = getNextWord(), b = getNextWord(); + + if (getGameType() == GType_ELVIRA2) { + // WORKAROUND: A NULL item can occur when interacting with Wine Bottles + if (item == NULL) { + warning("Please report where exactly this occurs in Elvira 2"); + setScriptCondition(false); + return; + } + } + setScriptCondition(item->adjective == a && item->noun == b); } @@ -707,7 +729,7 @@ void AGOSEngine_Elvira2::printStats() { if (val > 9999) val = 9999; writeChar(window, 30, y, 6, val / 100); - writeChar(window, 32, y, 2, val / 10); + writeChar(window, 32, y, 2, val % 100); mouseOn(); } diff --git a/engines/agos/script_ff.cpp b/engines/agos/script_ff.cpp index c3e6dc5192..8b7af31a66 100644 --- a/engines/agos/script_ff.cpp +++ b/engines/agos/script_ff.cpp @@ -528,7 +528,7 @@ void AGOSEngine_Feeble::off_screenTextPObj() { TextLocation *tl = NULL; char buf[256]; - SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); + SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType); if (subObject != NULL && subObject->objectFlags & kOFText) { string_ptr = (const char *)getStringPtrByID(subObject->objectFlagValue[0]); tl = getTextLocation(vgaSpriteId); diff --git a/engines/agos/script_s1.cpp b/engines/agos/script_s1.cpp index 93b907e688..1a4f956b8b 100644 --- a/engines/agos/script_s1.cpp +++ b/engines/agos/script_s1.cpp @@ -311,29 +311,29 @@ void AGOSEngine_Simon1::os1_pauseGame() { _system->setFeatureState(OSystem::kFeatureVirtualKeyboard, true); // If all else fails, use English as fallback. - byte keyYes = 'y'; - byte keyNo = 'n'; + Common::KeyCode keyYes = Common::KEYCODE_y; + Common::KeyCode keyNo = Common::KEYCODE_n; switch (_language) { case Common::RU_RUS: break; case Common::PL_POL: - keyYes = 't'; + keyYes = Common::KEYCODE_t; break; case Common::HB_ISR: - keyYes = 'f'; + keyYes = Common::KEYCODE_f; break; case Common::ES_ESP: - keyYes = 's'; + keyYes = Common::KEYCODE_s; break; case Common::IT_ITA: - keyYes = 's'; + keyYes = Common::KEYCODE_s; break; case Common::FR_FRA: - keyYes = 'o'; + keyYes = Common::KEYCODE_o; break; case Common::DE_DEU: - keyYes = 'j'; + keyYes = Common::KEYCODE_j; break; default: break; @@ -343,17 +343,17 @@ void AGOSEngine_Simon1::os1_pauseGame() { delay(1); #ifdef _WIN32_WCE if (isSmartphone()) { - if (_keyPressed) { - if (_keyPressed == 13) + if (_keyPressed.keycode) { + if (_keyPressed.keycode == Common::KEYCODE_RETURN) shutdown(); else break; } } #endif - if (_keyPressed == keyYes || _keyPressed == (keyYes - 32)) + if (_keyPressed.keycode == keyYes) shutdown(); - else if (_keyPressed == keyNo || _keyPressed == (keyNo - 32)) + else if (_keyPressed.keycode == keyNo) break; } @@ -419,7 +419,7 @@ void AGOSEngine_Simon1::os1_screenTextPObj() { uint vgaSpriteId = getVarOrByte(); uint color = getVarOrByte(); - SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); + SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType); if (getFeatures() & GF_TALKIE) { if (subObject != NULL && subObject->objectFlags & kOFVoice) { uint offs = getOffsetOfChild2Param(subObject, kOFVoice); diff --git a/engines/agos/script_s2.cpp b/engines/agos/script_s2.cpp index dfc1200d7c..00addce396 100644 --- a/engines/agos/script_s2.cpp +++ b/engines/agos/script_s2.cpp @@ -355,7 +355,7 @@ void AGOSEngine_Simon2::os2_screenTextPObj() { uint vgaSpriteId = getVarOrByte(); uint color = getVarOrByte(); - SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); + SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType); if (getFeatures() & GF_TALKIE) { if (subObject != NULL && subObject->objectFlags & kOFVoice) { uint speechId = subObject->objectFlagValue[getOffsetOfChild2Param(subObject, kOFVoice)]; diff --git a/engines/agos/script_ww.cpp b/engines/agos/script_ww.cpp index 377b49ae3f..fc472fd3c3 100644 --- a/engines/agos/script_ww.cpp +++ b/engines/agos/script_ww.cpp @@ -167,7 +167,7 @@ void AGOSEngine_Waxworks::setupOpcodes() { OPCODE(o_cls), /* 104 */ OPCODE(o_closeWindow), - OPCODE(oww_menu), + OPCODE(oe2_menu), OPCODE(oww_textMenu), OPCODE(o_addBox), /* 108 */ @@ -355,11 +355,6 @@ void AGOSEngine_Waxworks::oww_whereTo() { _objectItem = derefItem(getExitOf(i, d)); } -void AGOSEngine_Waxworks::oww_menu() { - // 105: set agos menu - _agosMenu = getVarOrByte(); -} - void AGOSEngine_Waxworks::oww_textMenu() { // 106: set text menu byte slot = getVarOrByte(); @@ -419,7 +414,7 @@ void AGOSEngine_Waxworks::oww_printBox() { void AGOSEngine_Waxworks::oww_boxPObj() { // 188: print object name to box - SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), 2); + SubObject *subObject = (SubObject *)findChildOfType(getNextItemPtr(), kObjectType); if (subObject != NULL && subObject->objectFlags & kOFText) boxTextMsg((const char *)getStringPtrByID(subObject->objectFlagValue[0])); diff --git a/engines/agos/string.cpp b/engines/agos/string.cpp index 483f101889..521a3ab6ea 100644 --- a/engines/agos/string.cpp +++ b/engines/agos/string.cpp @@ -274,7 +274,7 @@ bool AGOSEngine::printNameOf(Item *item, uint x, uint y) { if (item == 0 || item == _dummyItem2 || item == _dummyItem3) return false; - subObject = (SubObject *)findChildOfType(item, 2); + subObject = (SubObject *)findChildOfType(item, kObjectType); if (subObject == NULL) return false; @@ -370,10 +370,12 @@ void AGOSEngine::printScreenText(uint vgaSpriteId, uint color, const char *strin if (y < 2) y = 2; - if (getGameType() == GType_SIMON1) - animate(windowNum, 2, 199 + vgaSpriteId, x, y, 12); - else + if (getGameType() == GType_SIMON1) { + uint16 id = 199 + vgaSpriteId; + animate(windowNum, id / 100, id, x, y, 12); + } else { animate(windowNum, 2, vgaSpriteId, x, y, 12); + } } // The Feeble Files specific diff --git a/engines/agos/vga.cpp b/engines/agos/vga.cpp index 2b8f6d3a09..38c401a80d 100644 --- a/engines/agos/vga.cpp +++ b/engines/agos/vga.cpp @@ -70,8 +70,8 @@ void AGOSEngine::setupVideoOpcodes(VgaOpcodeProc *op) { op[36] = &AGOSEngine::vc36_setWindowImage; op[38] = &AGOSEngine::vc38_ifVarNotZero; op[39] = &AGOSEngine::vc39_setVar; - op[40] = &AGOSEngine::vc40; - op[41] = &AGOSEngine::vc41; + op[40] = &AGOSEngine::vc40_scrollRight; + op[41] = &AGOSEngine::vc41_scrollLeft; op[42] = &AGOSEngine::vc42_delayIfNotEQ; op[43] = &AGOSEngine::vc43_ifBitSet; op[44] = &AGOSEngine::vc44_ifBitClear; @@ -124,8 +124,8 @@ void AGOSEngine_Elvira1::setupVideoOpcodes(VgaOpcodeProc *op) { op[41] = &AGOSEngine::vc37_pokePalette; op[51] = &AGOSEngine::vc38_ifVarNotZero; op[52] = &AGOSEngine::vc39_setVar; - op[53] = &AGOSEngine::vc40; - op[54] = &AGOSEngine::vc41; + op[53] = &AGOSEngine::vc40_scrollRight; + op[54] = &AGOSEngine::vc41_scrollLeft; op[56] = &AGOSEngine::vc42_delayIfNotEQ; } @@ -1257,57 +1257,38 @@ void AGOSEngine::vc39_setVar() { vcWriteVar(var, value); } -void AGOSEngine::vc40() { +void AGOSEngine::vc40_scrollRight() { uint16 var = vcReadNextWord(); int16 value = vcReadVar(var) + vcReadNextWord(); if (getGameType() == GType_SIMON2 && var == 15 && !getBitFlag(80)) { - int16 tmp; - if (_scrollCount != 0) { - if (_scrollCount >= 0) - goto no_scroll; + if ((_scrollCount < 0) || (_scrollCount == 0 && _scrollFlag == 0)) { _scrollCount = 0; - } else { - if (_scrollFlag != 0) - goto no_scroll; - } - - if (value - _scrollX >= 30) { - _scrollCount = 20; - tmp = _scrollXMax - _scrollX; - if (tmp < 20) - _scrollCount = tmp; - addVgaEvent(6, SCROLL_EVENT, NULL, 0, 0); + if (value - _scrollX >= 30) { + _scrollCount = MIN(20, _scrollXMax - _scrollX); + addVgaEvent(6, SCROLL_EVENT, NULL, 0, 0); + } } } -no_scroll:; vcWriteVar(var, value); } -void AGOSEngine::vc41() { +void AGOSEngine::vc41_scrollLeft() { uint16 var = vcReadNextWord(); int16 value = vcReadVar(var) - vcReadNextWord(); if (getGameType() == GType_SIMON2 && var == 15 && !getBitFlag(80)) { - if (_scrollCount != 0) { - if (_scrollCount < 0) - goto no_scroll; - _scrollCount = 0; - } else { - if (_scrollFlag != 0) - goto no_scroll; - } - if ((uint16)(value - _scrollX) < 11) { - _scrollCount = -20; - if (_scrollX < 20) - _scrollCount = -_scrollX; - addVgaEvent(6, SCROLL_EVENT, NULL, 0, 0); + if ((_scrollCount > 0) || (_scrollCount == 0 && _scrollFlag == 0)) { + _scrollCount = 0; + if ((uint16)(value - _scrollX) < 11) { + _scrollCount = -MIN(20, (int)_scrollX); + addVgaEvent(6, SCROLL_EVENT, NULL, 0, 0); + } } } -no_scroll:; vcWriteVar(var, value); } diff --git a/engines/agos/vga.h b/engines/agos/vga.h index 37c5d37106..1994f59f7f 100644 --- a/engines/agos/vga.h +++ b/engines/agos/vga.h @@ -40,20 +40,20 @@ struct VgaFileHeader2_Feeble { uint16 x_4; uint16 animationTable; uint16 x_5; -}; +} PACKED_STRUCT; struct ImageHeader_Feeble { uint16 id; uint16 x_1; uint16 scriptOffs; uint16 x_2; -}; +} PACKED_STRUCT; struct AnimationHeader_Feeble { uint16 scriptOffs; uint16 x_2; uint16 id; -}; +} PACKED_STRUCT; // Simon 1/2 struct ImageHeader_Simon { @@ -61,13 +61,13 @@ struct ImageHeader_Simon { uint16 color; uint16 x_2; uint16 scriptOffs; -}; +} PACKED_STRUCT; struct AnimationHeader_Simon { uint16 id; uint16 x_2; uint16 scriptOffs; -}; +} PACKED_STRUCT; // Elvira 1/2 and Waxworks @@ -76,14 +76,14 @@ struct ImageHeader_WW { uint16 color; uint16 x_2; uint16 scriptOffs; -}; +} PACKED_STRUCT; struct AnimationHeader_WW { uint16 id; uint16 x_1; uint16 x_2; uint16 scriptOffs; -}; +} PACKED_STRUCT; // Common struct VgaFileHeader2_Common { @@ -96,7 +96,7 @@ struct VgaFileHeader2_Common { uint16 x_4; uint16 animationTable; uint16 x_5; -}; +} PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/cine/various.cpp b/engines/cine/various.cpp index 281c4807b8..49b10b6b14 100644 --- a/engines/cine/various.cpp +++ b/engines/cine/various.cpp @@ -2458,6 +2458,7 @@ void drawFailureMessage(byte cmd) { void drawOverlays(void) { overlayHeadElement *currentOverlay; + overlayHeadElement *nextOverlay; backupOverlayPage(); @@ -2468,6 +2469,8 @@ void drawOverlays(void) { currentOverlay = currentOverlay->next; while (currentOverlay) { + nextOverlay = currentOverlay->next; + switch (currentOverlay->type) { case 0: // sprite { @@ -2630,7 +2633,7 @@ void drawOverlays(void) { } } - currentOverlay = currentOverlay->next; + currentOverlay = nextOverlay; } } diff --git a/engines/cruise/saveload.cpp b/engines/cruise/saveload.cpp index d6b2c9ec93..ffda142e66 100644 --- a/engines/cruise/saveload.cpp +++ b/engines/cruise/saveload.cpp @@ -177,12 +177,12 @@ int loadSavegameData(int saveGameIdx) { fileHandle = fopen(buffer, "rb"); if (!fileHandle) { - printInfoBlackBox("Sauvegarde non trouvée..."); + printInfoBlackBox("Savegame not found..."); waitForPlayerInput(); return (-1); } - printInfoBlackBox("Chargement en cours..."); + printInfoBlackBox("Loading in progress..."); fread(saveIdentBuffer, 6, 1, fileHandle); diff --git a/engines/engine.cpp b/engines/engine.cpp index 05e2235cc9..f2b7198510 100644 --- a/engines/engine.cpp +++ b/engines/engine.cpp @@ -54,7 +54,8 @@ Engine::Engine(OSystem *syst) _eventMan(_system->getEventManager()), _saveFileMan(_system->getSavefileManager()), _targetName(ConfMan.getActiveDomainName()), - _gameDataPath(ConfMan.get("path")) { + _gameDataPath(ConfMan.get("path")), + _pauseLevel(0) { g_engine = this; _autosavePeriod = ConfMan.getInt("autosave_period"); @@ -180,3 +181,23 @@ void Engine::GUIErrorMessage(const Common::String msg) { GUI::MessageDialog dialog(msg); dialog.runModal(); } + +void Engine::pauseEngine(bool pause) { + assert((pause && _pauseLevel >= 0) || (!pause && _pauseLevel)); + + if (pause) + _pauseLevel++; + else + _pauseLevel--; + + if (_pauseLevel == 1) { + pauseEngineIntern(true); + } else if (_pauseLevel == 0) { + pauseEngineIntern(false); + } +} + +void Engine::pauseEngineIntern(bool pause) { + // By default, just (un)pause all digital sounds + _mixer->pauseAll(pause); +} diff --git a/engines/engine.h b/engines/engine.h index 7b40a377ef..f9aeb7718f 100644 --- a/engines/engine.h +++ b/engines/engine.h @@ -56,7 +56,18 @@ protected: const Common::String _gameDataPath; private: + /** + * The autosave interval, given in second. Used by shouldPerformAutoSave. + */ int _autosavePeriod; + + /** + * The pause level, 0 means 'running', a positive value indicates + * how often the engine has been paused (and hence how often it has + * to be un-paused before it resumes running). This makes it possible + * to nest code which pauses the engine. + */ + int _pauseLevel; public: Engine(OSystem *syst); @@ -79,22 +90,49 @@ public: /** Specific for each engine: prepare error string. */ virtual void errorString(const char *buf_input, char *buf_output); + /** + * Return the engine's debugger instance, if any. Used by error() to + * invoke the debugger when a severe error is reported. + */ + virtual GUI::Debugger *getDebugger() { return 0; } + + /** + * Pause or resume the engine. This should stop/resume any audio playback + * and other stuff. Called right before the system runs a global dialog + * (like a global pause, main menu, options or 'confirm exit' dialog). + * + * This is a convenience tracker which automatically keeps track on how + * often the engine has been paused, ensuring that after pausing an engine + * e.g. twice, it has to be unpaused twice before actuallying resuming. + * + * @param pause true to pause the engine, false to resume it + */ + void pauseEngine(bool pause); + + /** + * Return whether the engine is currently paused or not. + */ + bool isPaused() const { return _pauseLevel != 0; } + +public: + + /** Setup the backend's graphics mode. */ void initCommonGFX(bool defaultTo1XScaler); /** On some systems, check if the game appears to be run from CD. */ void checkCD(); - /* Indicate if an autosave should be performed. */ + /** Indicate whether an autosave should be performed. */ bool shouldPerformAutoSave(int lastSaveTime); /** Initialized graphics and shows error message. */ void GUIErrorMessage(const Common::String msg); - + /** - * Return the engine's debugger instance, if any. Used by error() to - * invoke the debugger when a severe error is reported. + * Actual implementation of pauseEngine by subclasses. See there + * for details. */ - virtual GUI::Debugger *getDebugger() { return 0; } + virtual void pauseEngineIntern(bool pause); }; extern Engine *g_engine; diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp index 9dfbf534d4..1c275185ca 100644 --- a/engines/gob/detection.cpp +++ b/engines/gob/detection.cpp @@ -757,14 +757,30 @@ static const GOBGameDescription gameDescriptions[] = { { "gob3", "", - AD_ENTRY1("intro.stk", "32b0f57f5ae79a9ae97e8011df38af42"), - UNK_LANG, + AD_ENTRY1s("intro.stk", "32b0f57f5ae79a9ae97e8011df38af42", 157084), + EN_GRB, kPlatformPC, Common::ADGF_NO_FLAGS }, GF_GOB3, "intro" }, + { // Supplied by fac76 in bug report #1742716 + { + "gob3", + "", + { + {"intro.stk", 0, "32b0f57f5ae79a9ae97e8011df38af42", 157084}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {NULL, 0, NULL, 0} + }, + EN_GRB, + kPlatformMacintosh, + Common::ADGF_NO_FLAGS + }, + GF_GOB3, + "intro" + }, { { "gob3", diff --git a/engines/gob/game.h b/engines/gob/game.h index 4a1796c6d9..2181d219f2 100644 --- a/engines/gob/game.h +++ b/engines/gob/game.h @@ -48,7 +48,7 @@ public: uint16 funcEnter; uint16 funcLeave; uint16 funcSub; - }; + } PACKED_STRUCT; #define szGame_TotResItem (4 + 2 + 2 + 2) struct TotResItem { @@ -57,7 +57,7 @@ public: int16 size; int16 width; int16 height; - }; + } PACKED_STRUCT; #define szGame_TotResTable (2 + 1) struct TotResTable { @@ -65,7 +65,7 @@ public: byte unknown; TotResItem *items; byte *dataPtr; - }; + } PACKED_STRUCT; #define szGame_ExtItem (4 + 2 + 2 + 2) struct ExtItem { @@ -73,34 +73,34 @@ public: uint16 size; int16 width; // width & 0x7FFF: width, width & 0x8000: pack flag int16 height; // not zero - }; + } PACKED_STRUCT; #define szGame_ExtTable (2 + 1) struct ExtTable { int16 itemsCount; byte unknown; ExtItem* items; - }; + } PACKED_STRUCT; #define szGame_TotTextItem (2 + 2) struct TotTextItem { int16 offset; int16 size; - }; + } PACKED_STRUCT; #define szGame_TotTextTable (2) struct TotTextTable { int16 itemsCount; TotTextItem *items; byte *dataPtr; - }; + } PACKED_STRUCT; struct InputDesc { int16 fontIndex; int16 backColor; int16 frontColor; byte *ptr; - }; + } PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/gob/goblin.h b/engines/gob/goblin.h index 61ac9dff5e..38c19a48d3 100644 --- a/engines/gob/goblin.h +++ b/engines/gob/goblin.h @@ -51,7 +51,7 @@ public: int16 freq; // high/low byte * 100 - frequency int16 repCount; // high/low byte - repeat count int16 sndFrame; - }; + } PACKED_STRUCT; typedef Gob_State *Gob_PState; @@ -90,12 +90,12 @@ public: char multObjIndex; char unk14; char visible; - }; + } PACKED_STRUCT; struct Gob_Pos { char x; char y; - }; + } PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/gob/imd.h b/engines/gob/imd.h index 3d04f18c6d..27d95cd579 100644 --- a/engines/gob/imd.h +++ b/engines/gob/imd.h @@ -41,7 +41,7 @@ public: int16 top; int16 right; int16 bottom; - }; + } PACKED_STRUCT; struct Imd { int16 handle; @@ -65,7 +65,7 @@ public: int32 frameDataSize; int32 vidBufferSize; Video::Color *extraPalette; - }; + } PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index fcf825b4c3..a3277047e7 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -1647,6 +1647,13 @@ bool Inter_v1::o1_keyFunc(OpFuncParams ¶ms) { lastCalled = now; _noBusyWait = false; + // WORKAROUND for bug #1726130: Ween busy-waits in the intro for a counter + // to become 5000. We deliberately slow down busy-waiting, so we shorten + // the counting, too. + if (((_vm->_global->_inter_execPtr - _vm->_game->_totFileData) == 729) && + (VAR(59) < 4000) && !scumm_stricmp(_vm->_game->_curTotFile, "intro5.tot")) + WRITE_VAR(59, 4000); + switch (cmd) { case 0: _vm->_draw->_showCursor &= ~2; diff --git a/engines/gob/map.h b/engines/gob/map.h index 9b45c5c04e..0e0a80aad3 100644 --- a/engines/gob/map.h +++ b/engines/gob/map.h @@ -51,7 +51,7 @@ public: int16 x; int16 y; int16 notWalkable; - }; + } PACKED_STRUCT; #define szMap_ItemPos 3 @@ -59,7 +59,7 @@ public: int8 x; int8 y; int8 orient; - }; + } PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/gob/mult.h b/engines/gob/mult.h index 194126cd8b..edfbb682ea 100644 --- a/engines/gob/mult.h +++ b/engines/gob/mult.h @@ -63,7 +63,7 @@ public: int8 redrawAnimation; int8 redrawLayer; uint8 redrawFrame; - }; + } PACKED_STRUCT; struct Mult_GobState { int16 animation; // . @@ -74,7 +74,7 @@ public: int16 freq; // |- [1+] int8 repCount; // | uint8 speaker; // ' - }; + } PACKED_STRUCT; struct Mult_Object { int32 *pPosX; @@ -104,12 +104,12 @@ public: int16 newTop; int16 newRight; int16 newBottom; - }; + } PACKED_STRUCT; struct Mult_StaticKey { int16 frame; int16 layer; - }; + } PACKED_STRUCT; struct Mult_AnimKey { int16 frame; @@ -117,14 +117,14 @@ public: int16 posX; int16 posY; int16 order; - }; + } PACKED_STRUCT; struct Mult_TextKey { int16 frame; int16 cmd; char unknown[18]; byte script[6]; - }; + } PACKED_STRUCT; struct Mult_PalKey { int16 frame; @@ -133,14 +133,14 @@ public: int16 unknown0; int16 unknown1; int8 subst[16][4]; - }; + } PACKED_STRUCT; struct Mult_PalFadeKey { int16 frame; int16 fade; int16 palIndex; int8 flag; - }; + } PACKED_STRUCT; struct Mult_SndKey { int16 frame; @@ -150,7 +150,7 @@ public: int16 repCount; int16 resId; int16 soundIndex; - }; + } PACKED_STRUCT; struct Mult_ImdKey { int16 frame; @@ -162,7 +162,7 @@ public: int16 lastFrame; int8 palStart; int8 palEnd; - }; + } PACKED_STRUCT; struct Mult_Data { int16 palFadeKeysCount; @@ -212,7 +212,7 @@ public: char *imdFiles; char *somepointer10; // ? byte *execPtr; - }; + } PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/gob/music.cpp b/engines/gob/music.cpp index 6e678c103e..0f38827363 100644 --- a/engines/gob/music.cpp +++ b/engines/gob/music.cpp @@ -268,20 +268,20 @@ void Adlib::setKey(byte voice, byte note, bool on, bool spec) { // 0x3A donne 0x2AF; // 3A // << 7 = 1D00 - // + E000 = FD00 négatif + // + E000 = FD00 negatif // * 19 = xB500 // / 2000 = -2 => Ligne 17h, colonne -1 // 2E // << 7 = 1700 - // + E000 = F700 négatif + // + E000 = F700 negatif // * 19 = x1F00 // / 2000 = short a; short lin; short col; - a = (note << 7) + 0xE000; // Volontairement tronqué + a = (note << 7) + 0xE000; // Volontairement tronque a = (short)((long)a * 25 / 0x2000); if (a < 0) { col = - ((24 - a) / 25); diff --git a/engines/gob/saveload_v3.cpp b/engines/gob/saveload_v3.cpp index 3f8aeb81bd..b376a8a75c 100644 --- a/engines/gob/saveload_v3.cpp +++ b/engines/gob/saveload_v3.cpp @@ -258,7 +258,10 @@ bool SaveLoad_v3::loadScreenshot(int16 dataVar, int32 size, int32 offset) { } in->seek(1040 + varSize * 2); - return loadSprite(*in, size); + + bool success = loadSprite(*in, size); + delete in; + return success; } else warning("Invalid attempt at loading a screenshot (%d, %d, %d, %d)", diff --git a/engines/gob/scenery.h b/engines/gob/scenery.h index 32ff727c46..acb7aecba7 100644 --- a/engines/gob/scenery.h +++ b/engines/gob/scenery.h @@ -38,7 +38,7 @@ public: int16 right; //These are stored in Little Endian format int16 top; //And should be converted by client code when accessed int16 bottom; //i.e. use FROM_LE_16() - }; + } PACKED_STRUCT; struct StaticPlane { int8 pictIndex; @@ -47,13 +47,13 @@ public: int16 destX; int16 destY; int8 transp; - }; + } PACKED_STRUCT; struct StaticLayer { int16 backResId; int16 planeCount; StaticPlane *planes; - }; + } PACKED_STRUCT; // Animations @@ -63,7 +63,7 @@ public: int8 destX; int8 destY; int8 notFinal; - }; + } PACKED_STRUCT; struct AnimLayer { int16 unknown0; @@ -74,7 +74,7 @@ public: int8 transp; int16 framesCount; AnimFramePiece *frames; - }; + } PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/gob/sound.cpp b/engines/gob/sound.cpp index e3a4715920..b47e6795ac 100644 --- a/engines/gob/sound.cpp +++ b/engines/gob/sound.cpp @@ -35,8 +35,6 @@ namespace Gob { -#define FRAC_BITS 16 - void SoundDesc::set(SoundType type, SoundSource src, byte *data, uint32 dSize) { @@ -176,7 +174,6 @@ Snd::Snd(GobEngine *vm) : _vm(vm) { _offset = 0; _offsetFrac = 0; _offsetInc = 0; - _offsetIncFrac = 0; _cur = 0; _last = 0; @@ -325,10 +322,7 @@ void Snd::setSample(SoundDesc &sndDesc, int16 repCount, int16 frequency, _offset = 0; _offsetFrac = 0; - - uint32 incr = (_freq << FRAC_BITS) / _rate; - _offsetInc = incr >> FRAC_BITS; - _offsetIncFrac = incr & ((1UL << FRAC_BITS) - 1); + _offsetInc = (_freq << FRAC_BITS) / _rate; _last = _cur; _cur = _data[0]; @@ -393,9 +387,6 @@ void Snd::checkEndSample() { int Snd::readBuffer(int16 *buffer, const int numSamples) { Common::StackLock slock(_mutex); - int16 val; - uint32 tmp, oldOffset; - for (int i = 0; i < numSamples; i++) { if (!_data) return i; @@ -406,19 +397,18 @@ int Snd::readBuffer(int16 *buffer, const int numSamples) { // Linear interpolation. See sound/rate.cpp - val = (_last + (((_cur - _last) * _offsetFrac + - (1UL << (FRAC_BITS - 1))) >> FRAC_BITS)) << 8; - *buffer++ = (((int32) val) * _fadeVol) >> 16; + int32 val = (_last + (((_cur - _last) * _offsetFrac + + FRAC_HALF) >> FRAC_BITS)) << 8; + *buffer++ = (val * _fadeVol) >> 16; - oldOffset = _offset; - - tmp = _offsetFrac + _offsetIncFrac; - _offset += _offsetInc + (tmp >> FRAC_BITS); - _offsetFrac = tmp & ((1UL << FRAC_BITS) - 1); + _offsetFrac += _offsetInc; - if (oldOffset < _offset) { + // Was there an integral change? + if (fracToInt(_offsetFrac) > 0) { _last = _cur; - _cur = _data[oldOffset]; + _cur = _data[_offset]; + _offset += fracToInt(_offsetFrac); + _offsetFrac &= FRAC_LO_MASK; } if (_fade) { diff --git a/engines/gob/sound.h b/engines/gob/sound.h index 76b9f2b159..15909f5452 100644 --- a/engines/gob/sound.h +++ b/engines/gob/sound.h @@ -27,6 +27,7 @@ #define GOB_SOUND_H #include "common/mutex.h" +#include "common/frac.h" #include "sound/audiostream.h" #include "sound/mixer.h" @@ -175,9 +176,8 @@ protected: int32 _repCount; uint32 _offset; - uint32 _offsetFrac; - uint32 _offsetInc; - uint32 _offsetIncFrac; + frac_t _offsetFrac; + frac_t _offsetInc; int16 _cur; int16 _last; diff --git a/engines/gob/video.cpp b/engines/gob/video.cpp index 0bc87f42d5..6f88a5a993 100644 --- a/engines/gob/video.cpp +++ b/engines/gob/video.cpp @@ -235,7 +235,7 @@ void Video::drawLine(SurfaceDesc *dest, int16 x0, int16 y0, int16 x1, /* * The original's version of the Bresenham Algorithm was a bit "unclean" - * and produced strange edges at 45°, 135°, 225° and 315°, so using the + * and produced strange edges at 45, 135, 225 and 315 degrees, so using the * version found in the Wikipedia article about the * "Bresenham's line algorithm" instead */ diff --git a/engines/gob/video.h b/engines/gob/video.h index faa9555abb..51d02bd219 100644 --- a/engines/gob/video.h +++ b/engines/gob/video.h @@ -85,7 +85,7 @@ public: byte red; byte green; byte blue; - }; + } PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui.cpp index 8cafb54fb8..6fc347158f 100644 --- a/engines/kyra/gui.cpp +++ b/engines/kyra/gui.cpp @@ -230,14 +230,14 @@ int KyraEngine::buttonAmuletCallback(Button *caller) { drawJewelsFadeOutEnd(jewel); _scriptInterpreter->initScript(_scriptClick, _scriptClickData); - _scriptClick->variables[3] = 0; - _scriptClick->variables[6] = jewel; + _scriptClick->regs[3] = 0; + _scriptClick->regs[6] = jewel; _scriptInterpreter->startScript(_scriptClick, 4); while (_scriptInterpreter->validScript(_scriptClick)) _scriptInterpreter->runScript(_scriptClick); - if (_scriptClick->variables[3]) + if (_scriptClick->regs[3]) return 1; _unkAmuletVar = 1; diff --git a/engines/kyra/kyra.cpp b/engines/kyra/kyra.cpp index 249a5f6c21..1664ce144f 100644 --- a/engines/kyra/kyra.cpp +++ b/engines/kyra/kyra.cpp @@ -923,16 +923,16 @@ int KyraEngine::processInputHelper(int xpos, int ypos) { int KyraEngine::clickEventHandler(int xpos, int ypos) { debugC(9, kDebugLevelMain, "KyraEngine::clickEventHandler(%d, %d)", xpos, ypos); _scriptInterpreter->initScript(_scriptClick, _scriptClickData); - _scriptClick->variables[1] = xpos; - _scriptClick->variables[2] = ypos; - _scriptClick->variables[3] = 0; - _scriptClick->variables[4] = _itemInHand; + _scriptClick->regs[1] = xpos; + _scriptClick->regs[2] = ypos; + _scriptClick->regs[3] = 0; + _scriptClick->regs[4] = _itemInHand; _scriptInterpreter->startScript(_scriptClick, 1); while (_scriptInterpreter->validScript(_scriptClick)) _scriptInterpreter->runScript(_scriptClick); - return _scriptClick->variables[3]; + return _scriptClick->regs[3]; } void KyraEngine::updateMousePointer(bool forceUpdate) { @@ -1068,10 +1068,10 @@ void KyraEngine::clickEventHandler2() { Common::Point mouse = getMousePos(); _scriptInterpreter->initScript(_scriptClick, _scriptClickData); - _scriptClick->variables[0] = _currentCharacter->sceneId; - _scriptClick->variables[1] = mouse.x; - _scriptClick->variables[2] = mouse.y; - _scriptClick->variables[4] = _itemInHand; + _scriptClick->regs[0] = _currentCharacter->sceneId; + _scriptClick->regs[1] = mouse.x; + _scriptClick->regs[2] = mouse.y; + _scriptClick->regs[4] = _itemInHand; _scriptInterpreter->startScript(_scriptClick, 6); while (_scriptInterpreter->validScript(_scriptClick)) @@ -1132,9 +1132,9 @@ void KyraEngine::runNpcScript(int func) { debugC(9, kDebugLevelMain, "KyraEngine::runNpcScript(%d)", func); _scriptInterpreter->initScript(_npcScript, _npcScriptData); _scriptInterpreter->startScript(_npcScript, func); - _npcScript->variables[0] = _currentCharacter->sceneId; - _npcScript->variables[4] = _itemInHand; - _npcScript->variables[5] = func; + _npcScript->regs[0] = _currentCharacter->sceneId; + _npcScript->regs[4] = _itemInHand; + _npcScript->regs[5] = func; while (_scriptInterpreter->validScript(_npcScript)) _scriptInterpreter->runScript(_npcScript); diff --git a/engines/kyra/resource.cpp b/engines/kyra/resource.cpp index 319845c22c..2425444be1 100644 --- a/engines/kyra/resource.cpp +++ b/engines/kyra/resource.cpp @@ -195,15 +195,22 @@ uint8 *Resource::fileData(const char *file, uint32 *size) const { if (!(*cur)->isOpen()) continue; - uint32 fileSize = (*cur)->getFileSize(fileHash); - if (!fileSize) - continue; + uint8* result = (*cur)->getFile(fileHash); + + if (result) { + uint32 fileSize = (*cur)->getFileSize(fileHash); + + if (!fileSize) + continue; + + if (size) + *size = fileSize; + + return result; + } - if (size) - *size = fileSize; - return (*cur)->getFile(fileHash); } } @@ -221,13 +228,15 @@ bool Resource::getFileHandle(const char *file, uint32 *size, Common::File &fileh if (!(*start)->isOpen()) continue; - *size = (*start)->getFileSize(fileHash); + if ((*start)->getFileHandle(fileHash, filehandle)) { + + *size = (*start)->getFileSize(fileHash); - if (!(*size)) - continue; + if (!(*size)) + continue; - if ((*start)->getFileHandle(fileHash, filehandle)) return true; + } } return false; diff --git a/engines/kyra/scene.cpp b/engines/kyra/scene.cpp index 2ba1870fcd..a92fd9ce7c 100644 --- a/engines/kyra/scene.cpp +++ b/engines/kyra/scene.cpp @@ -450,8 +450,8 @@ void KyraEngine::startSceneScript(int brandonAlive) { _scriptInterpreter->unloadScript(_scriptClickData); _scriptInterpreter->loadScript(fileNameBuffer, _scriptClickData, &_opcodes); _scriptInterpreter->startScript(_scriptClick, 0); - _scriptClick->variables[0] = _currentCharacter->sceneId; - _scriptClick->variables[7] = brandonAlive; + _scriptClick->regs[0] = _currentCharacter->sceneId; + _scriptClick->regs[7] = brandonAlive; while (_scriptInterpreter->validScript(_scriptClick)) _scriptInterpreter->runScript(_scriptClick); @@ -620,8 +620,8 @@ void KyraEngine::initSceneData(int facing, int unk1, int brandonAlive) { if (unk1 && brandonAlive == 0) moveCharacterToPos(0, facing, xpos2, ypos2); - _scriptClick->variables[4] = _itemInHand; - _scriptClick->variables[7] = brandonAlive; + _scriptClick->regs[4] = _itemInHand; + _scriptClick->regs[7] = brandonAlive; _scriptInterpreter->startScript(_scriptClick, 3); while (_scriptInterpreter->validScript(_scriptClick)) _scriptInterpreter->runScript(_scriptClick); @@ -852,7 +852,7 @@ void KyraEngine::initSceneScreen(int brandonAlive) { if (!_scriptInterpreter->startScript(_scriptClick, 2)) error("Could not start script function 2 of scene script"); - _scriptClick->variables[7] = brandonAlive; + _scriptClick->regs[7] = brandonAlive; while (_scriptInterpreter->validScript(_scriptClick)) _scriptInterpreter->runScript(_scriptClick); diff --git a/engines/kyra/screen.cpp b/engines/kyra/screen.cpp index 02eb1c9ea7..641a034eab 100644 --- a/engines/kyra/screen.cpp +++ b/engines/kyra/screen.cpp @@ -504,7 +504,12 @@ void Screen::copyToPage0(int y, int h, uint8 page, uint8 *seqBuf) { dstPage += SCREEN_W; } addDirtyRect(0, y, SCREEN_W, h); - clearOverlayRect(0, 0, y, SCREEN_W, h); + // This would remove the text in the end sequence of + // the FM-Towns version. + // Since this method is just used for the Seqplayer + // this shouldn't be a problem anywhere else, so it's + // safe to disable the call here. + //clearOverlayRect(0, 0, y, SCREEN_W, h); } void Screen::copyRegion(int x1, int y1, int x2, int y2, int w, int h, int srcPage, int dstPage, int flags) { diff --git a/engines/kyra/script.cpp b/engines/kyra/script.cpp index c2ec984d5c..b43cd3b471 100644 --- a/engines/kyra/script.cpp +++ b/engines/kyra/script.cpp @@ -49,12 +49,12 @@ ScriptHelper::ScriptHelper(KyraEngine *vm) : _vm(vm) { COMMAND(c1_push), // 0x04 COMMAND(c1_push), - COMMAND(c1_pushVar), + COMMAND(c1_pushReg), COMMAND(c1_pushBPNeg), COMMAND(c1_pushBPAdd), // 0x08 COMMAND(c1_popRetOrPos), - COMMAND(c1_popVar), + COMMAND(c1_popReg), COMMAND(c1_popBPNeg), COMMAND(c1_popBPAdd), // 0x0C @@ -324,8 +324,8 @@ void ScriptHelper::c1_push(ScriptState* script) { script->stack[--script->sp] = _parameter; } -void ScriptHelper::c1_pushVar(ScriptState* script) { - script->stack[--script->sp] = script->variables[_parameter]; +void ScriptHelper::c1_pushReg(ScriptState* script) { + script->stack[--script->sp] = script->regs[_parameter]; } void ScriptHelper::c1_pushBPNeg(ScriptState* script) { @@ -359,8 +359,8 @@ void ScriptHelper::c1_popRetOrPos(ScriptState* script) { } } -void ScriptHelper::c1_popVar(ScriptState* script) { - script->variables[_parameter] = script->stack[script->sp++]; +void ScriptHelper::c1_popReg(ScriptState* script) { + script->regs[_parameter] = script->stack[script->sp++]; } void ScriptHelper::c1_popBPNeg(ScriptState* script) { diff --git a/engines/kyra/script.h b/engines/kyra/script.h index dfca7700a1..5e43039110 100644 --- a/engines/kyra/script.h +++ b/engines/kyra/script.h @@ -70,8 +70,8 @@ struct ScriptState { int16 retValue; uint16 bp; uint16 sp; - int16 variables[30]; - int16 stack[61]; + int16 regs[30]; // VM registers + int16 stack[61]; // VM stack }; class ScriptHelper { @@ -99,7 +99,7 @@ protected: typedef void (ScriptHelper::*CommandProc)(ScriptState*); struct CommandEntry { CommandProc proc; - const char* desc; + const char *desc; }; const CommandEntry *_commands; @@ -109,11 +109,11 @@ private: void c1_pushRetOrPos(ScriptState*); void c1_push(ScriptState*); //void c1_push(); same as 03 - void c1_pushVar(ScriptState*); + void c1_pushReg(ScriptState*); void c1_pushBPNeg(ScriptState*); void c1_pushBPAdd(ScriptState*); void c1_popRetOrPos(ScriptState*); - void c1_popVar(ScriptState*); + void c1_popReg(ScriptState*); void c1_popBPNeg(ScriptState*); void c1_popBPAdd(ScriptState*); void c1_addSP(ScriptState*); diff --git a/engines/kyra/script_v1.cpp b/engines/kyra/script_v1.cpp index 8e604b972b..87123222fb 100644 --- a/engines/kyra/script_v1.cpp +++ b/engines/kyra/script_v1.cpp @@ -1379,8 +1379,8 @@ int KyraEngine_v1::o1_waitForConfirmationMouseClick(ScriptState *script) { processButtonList(_buttonList); _skipFlag = false; Common::Point mouse = getMousePos(); - script->variables[1] = mouse.x; - script->variables[2] = mouse.y; + script->regs[1] = mouse.x; + script->regs[2] = mouse.y; return 0; } diff --git a/engines/kyra/sound_digital.cpp b/engines/kyra/sound_digital.cpp index e2f92c9925..72d19ffd32 100644 --- a/engines/kyra/sound_digital.cpp +++ b/engines/kyra/sound_digital.cpp @@ -29,7 +29,7 @@ namespace Kyra { -// Thanks to Torbjörn Andersson (eriktorbjorn) for his aud player on which +// Thanks to Torbjorn Andersson (eriktorbjorn) for his aud player on which // this code is based on // TODO: cleanup of whole AUDStream diff --git a/engines/lure/res_struct.h b/engines/lure/res_struct.h index 59581b9c7d..b5e4aef724 100644 --- a/engines/lure/res_struct.h +++ b/engines/lure/res_struct.h @@ -47,7 +47,7 @@ struct VersionStructure { uint16 id; byte vMajor; byte vMinor; -}; +} PACKED_STRUCT; struct FileEntry { uint16 id; @@ -55,7 +55,7 @@ struct FileEntry { byte sizeExtension; uint16 size; uint16 offset; -}; +} PACKED_STRUCT; struct HotspotResource { uint16 hotspotId; @@ -91,7 +91,7 @@ struct HotspotResource { uint16 delayCtr; byte flags2; byte hdrFlags; -}; +} PACKED_STRUCT; struct HotspotAnimResource { uint16 animRecordId; @@ -105,18 +105,18 @@ struct HotspotAnimResource { uint8 downFrame; uint8 leftFrame; uint8 rightFrame; -}; +} PACKED_STRUCT; struct MovementResource { uint16 frameNumber; int16 xChange; int16 yChange; -}; +} PACKED_STRUCT; struct RoomRect { int16 xs, xe; int16 ys, ye; -}; +} PACKED_STRUCT; struct RoomResource { uint16 roomNumber; @@ -133,7 +133,7 @@ struct RoomResource { uint8 areaFlag; RoomRect walkBounds; uint16 numExits; -}; +} PACKED_STRUCT; struct RoomExitResource { int16 xs, xe, ys, ye; @@ -141,12 +141,12 @@ struct RoomExitResource { uint8 newRoom; uint8 direction; int16 newRoomX, newRoomY; -}; +} PACKED_STRUCT; struct HotspotOverrideResource { uint16 hotspotId; int16 xs, xe, ys, ye; -}; +} PACKED_STRUCT; struct RoomExitHotspotResource { uint16 hotspotId; @@ -154,7 +154,7 @@ struct RoomExitHotspotResource { int16 ys, ye; uint16 cursorNum; uint16 destRoomNumber; -}; +} PACKED_STRUCT; struct RoomExitJoinResource { uint16 hotspot1Id; @@ -168,41 +168,41 @@ struct RoomExitJoinResource { uint8 h2OpenSound; uint8 h2CloseSound; byte blocked; -}; +} PACKED_STRUCT; struct HotspotActionResource { byte action; uint16 sequenceOffset; -}; +} PACKED_STRUCT; struct TalkHeaderResource { uint16 hotspotId; uint16 offset; -}; +} PACKED_STRUCT; struct TalkDataHeaderResource { uint16 recordId; uint16 listOffset; uint16 responsesOffset; -}; +} PACKED_STRUCT; struct TalkDataResource { uint16 preSequenceId; uint16 descId; uint16 postSequenceId; -}; +} PACKED_STRUCT; struct TalkResponseResource { uint16 sequenceId1; uint16 sequenceId2; uint16 sequenceId3; -}; +} PACKED_STRUCT; struct RoomExitCoordinateResource { int16 x; int16 y; uint16 roomNumber; -}; +} PACKED_STRUCT; #define ROOM_EXIT_COORDINATES_NUM_ENTRIES 6 #define ROOM_EXIT_COORDINATES_NUM_ROOMS 52 @@ -210,20 +210,20 @@ struct RoomExitCoordinateResource { struct RoomExitCoordinateEntryResource { uint8 roomIndex[ROOM_EXIT_COORDINATES_NUM_ROOMS]; RoomExitCoordinateResource entries[ROOM_EXIT_COORDINATES_NUM_ENTRIES]; -}; +} PACKED_STRUCT; #define MAX_SCHEDULE_ENTRY_PARAMS 5 struct CharacterScheduleResource { uint16 action; uint16 params[MAX_SCHEDULE_ENTRY_PARAMS]; -}; +} PACKED_STRUCT; struct RoomExitIndexedHotspotResource { uint8 roomNumber; uint8 hotspotIndex; uint16 hotspotId; -}; +} PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/parallaction/animation.cpp b/engines/parallaction/animation.cpp index 33caaa1b58..d4f538c451 100644 --- a/engines/parallaction/animation.cpp +++ b/engines/parallaction/animation.cpp @@ -166,15 +166,19 @@ void jobDisplayAnimations(void *parm, Job *j) { if ((v18->_flags & kFlagsActive) && ((v18->_flags & kFlagsRemove) == 0)) { v14._width = v18->width(); v14._height = v18->height(); - v14._data0 = v18->getFrameData(v18->_frame); -// v14._data1 = v18->_cnv->field_8[v18->_frame]; + + int16 frame = CLIP((int)v18->_frame, 0, v18->getFrameNum()-1); + + v14._data0 = v18->getFrameData(frame); +// v14._data1 = v18->_cnv->field_8[frame]; if (v18->_flags & kFlagsNoMasked) _si = 3; else _si = _vm->_gfx->queryMask(v18->_top + v18->height()); - debugC(9, kDebugLocation, "jobDisplayAnimations(%s, x:%i, y:%i, z:%i, w:%i, h:%i, %p)", v18->_label._text, v18->_left, v18->_top, _si, v14._width, v14._height, v14._data0); + debugC(9, kDebugLocation, "jobDisplayAnimations(%s, x:%i, y:%i, z:%i, w:%i, h:%i, f:%i/%i, %p)", v18->_label._text, v18->_left, v18->_top, _si, v14._width, v14._height, + frame, v18->getFrameNum(), v14._data0); _vm->_gfx->blitCnv(&v14, v18->_left, v18->_top, _si, Gfx::kBitBack); } diff --git a/engines/parallaction/archive.cpp b/engines/parallaction/archive.cpp index b678b6df3c..9eef3f44e9 100644 --- a/engines/parallaction/archive.cpp +++ b/engines/parallaction/archive.cpp @@ -37,7 +37,7 @@ namespace Parallaction { // Amiga version of Nippon Safes, and one archive ('fr') in the Amiga Demo of // Nippon Safes used different internal offsets than all the other archives. // -// When an archive is opened in the Amiga demo, its size is checked against +// When an archive is opened in the Amiga demo, its size is checked against // SIZEOF_SMALL_ARCHIVE to detect when the smaller archive is used. // // When an archive is opened in Amiga multi-lingual version, the header is @@ -72,6 +72,8 @@ void Archive::open(const char *file) { if (!_archive.open(path)) error("archive '%s' not found", path); + _archiveName = file; + bool isSmallArchive = false; if (_vm->getPlatform() == Common::kPlatformAmiga) { if (_vm->getFeatures() & GF_DEMO) { @@ -105,8 +107,12 @@ void Archive::close() { resetArchivedFile(); _archive.close(); + _archiveName.clear(); } +Common::String Archive::name() const { + return _archiveName; +} bool Archive::openArchivedFile(const char *filename) { debugC(3, kDebugDisk, "Archive::openArchivedFile(%s)", filename); diff --git a/engines/parallaction/callables.cpp b/engines/parallaction/callables.cpp index 1154250ffa..be92ca1daa 100644 --- a/engines/parallaction/callables.cpp +++ b/engines/parallaction/callables.cpp @@ -253,7 +253,7 @@ void _c_endComment(void *param) { _vm->_gfx->floodFill(Gfx::kBitFront, r, 1); _vm->_gfx->setFont(kFontDialogue); - _vm->_gfx->displayWrappedString(_vm->_location._endComment, 3, 5, 130, 0); + _vm->_gfx->displayWrappedString(_vm->_location._endComment, 3, 5, 0, 130); _vm->_gfx->updateScreen(); uint32 di = 0; diff --git a/engines/parallaction/defs.h b/engines/parallaction/defs.h index d7dc3388e7..c41130670e 100644 --- a/engines/parallaction/defs.h +++ b/engines/parallaction/defs.h @@ -28,6 +28,7 @@ #include "common/stdafx.h" #include "common/list.h" +#include "common/rect.h" namespace Parallaction { diff --git a/engines/parallaction/dialogue.cpp b/engines/parallaction/dialogue.cpp index b3de3e5da3..7d2224164a 100644 --- a/engines/parallaction/dialogue.cpp +++ b/engines/parallaction/dialogue.cpp @@ -46,10 +46,6 @@ namespace Parallaction { #define ANSWER_CHARACTER_X 10 #define ANSWER_CHARACTER_Y 80 - -void enterDialogue(); -void exitDialogue(); - int16 selectAnswer(Question *q, StaticCnv*); int16 getHoverAnswer(int16 x, int16 y, Question *q); @@ -62,110 +58,109 @@ int16 _answerBalloonH[10] = { 0 }; Dialogue *Parallaction::parseDialogue(Script &script) { // printf("parseDialogue()\n"); - uint16 num_questions = 0; - uint16 v50[20]; - Table _questions_names(20); - Question *_questions[20]; + uint16 numQuestions = 0; - for (uint16 _si = 0; _si < 20; _si++) { - v50[_si] = 0; - } + Dialogue *dialogue = new Dialogue; + + Table forwards(20); fillBuffers(script, true); while (scumm_stricmp(_tokens[0], "enddialogue")) { if (scumm_stricmp(_tokens[0], "Question")) continue; - _questions[num_questions] = new Dialogue; - Dialogue *vB4 = _questions[num_questions]; + Question *question = new Question; + dialogue->_questions[numQuestions] = question; - _questions_names.addData(_tokens[1]); + forwards.addData(_tokens[1]); - vB4->_text = parseDialogueString(script); -// printf("Question: '%s'\n", vB4->_text); + question->_text = parseDialogueString(script); fillBuffers(script, true); - vB4->_mood = atoi(_tokens[0]); + question->_mood = atoi(_tokens[0]); - uint16 _di = 0; + uint16 numAnswers = 0; fillBuffers(script, true); while (scumm_stricmp(_tokens[0], "endquestion")) { // parse answers - vB4->_answers[_di] = new Answer; + Answer *answer = new Answer; + question->_answers[numAnswers] = answer; if (_tokens[1][0]) { - Table* v60 = _localFlagNames; - uint16 v56 = 1; + Table* flagNames; + uint16 token; if (!scumm_stricmp(_tokens[1], "global")) { - v56 = 2; - v60 = _globalTable; - vB4->_answers[_di]->_yesFlags |= kFlagsGlobal; + token = 2; + flagNames = _globalTable; + answer->_yesFlags |= kFlagsGlobal; + } else { + token = 1; + flagNames = _localFlagNames; } do { - if (!scumm_strnicmp(_tokens[v56], "no", 2)) { - byte _al = v60->lookup(_tokens[v56]+2); - vB4->_answers[_di]->_noFlags |= 1 << (_al - 1); + if (!scumm_strnicmp(_tokens[token], "no", 2)) { + byte _al = flagNames->lookup(_tokens[token]+2); + answer->_noFlags |= 1 << (_al - 1); } else { - byte _al = v60->lookup(_tokens[v56]); - vB4->_answers[_di]->_yesFlags |= 1 << (_al - 1); + byte _al = flagNames->lookup(_tokens[token]); + answer->_yesFlags |= 1 << (_al - 1); } - v56++; + token++; - } while (!scumm_stricmp(_tokens[v56++], "|")); + } while (!scumm_stricmp(_tokens[token++], "|")); } - vB4->_answers[_di]->_text = parseDialogueString(script); - -// printf("answer[%i]: '%s'\n", _di, vB4->_answers[_di]); + answer->_text = parseDialogueString(script); fillBuffers(script, true); - vB4->_answers[_di]->_mood = atoi(_tokens[0]); - vB4->_answers[_di]->_following._name = parseDialogueString(script); + answer->_mood = atoi(_tokens[0]); + answer->_following._name = parseDialogueString(script); fillBuffers(script, true); if (!scumm_stricmp(_tokens[0], "commands")) { - parseCommands(script, vB4->_answers[_di]->_commands); + parseCommands(script, answer->_commands); fillBuffers(script, true); } - _di++; + numAnswers++; } fillBuffers(script, true); - num_questions++; + numQuestions++; } - for (uint16 _si = 0; _si <num_questions; _si++) { + // link questions + byte v50[20]; + memset(v50, 0, 20); - for (uint16 v5A = 0; v5A < 5; v5A++) { - if (_questions[_si]->_answers[v5A] == 0) continue; + for (uint16 i = 0; i < numQuestions; i++) { + Question *question = dialogue->_questions[i]; - int16 v58 = _questions_names.lookup(_questions[_si]->_answers[v5A]->_following._name); - free(_questions[_si]->_answers[v5A]->_following._name); + for (uint16 j = 0; j < NUM_ANSWERS; j++) { + Answer *answer = question->_answers[j]; + if (answer == 0) continue; - if (v58 == -1) { - _questions[_si]->_answers[v5A]->_following._question = 0; - } else { - _questions[_si]->_answers[v5A]->_following._question = _questions[v58-1]; + int16 index = forwards.lookup(answer->_following._name); + free(answer->_following._name); + + if (index == -1) + answer->_following._question = 0; + else + answer->_following._question = dialogue->_questions[index - 1]; - if (v50[v58]) { - _questions[_si]->_answers[v5A]->_mood |= 0x10; - } - v50[v58] = 1; - } } } - return _questions[0]; + return dialogue; } @@ -183,7 +178,7 @@ char *Parallaction::parseDialogueString(Script &script) { } while (strlen(vD0) == 0); vD0[strlen(vD0)-1] = '\0'; // deletes the trailing '0xA' - // this is critical for Gfx::displayBalloonString to work properly + // this is critical for Gfx::displayWrappedString to work properly char *vCC = (char*)malloc(strlen(vD0)+1); strcpy(vCC, vD0); @@ -191,23 +186,71 @@ char *Parallaction::parseDialogueString(Script &script) { return vCC; } -uint16 Parallaction::askDialoguePassword(Dialogue *q, StaticCnv *face) { +class DialogueManager { + + Parallaction *_vm; + SpeakData *_data; + Dialogue *_dialogue; + + bool _askPassword; + + bool isNpc; + Cnv *_questioner; + Cnv *_answerer; + + Question *_q; + +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() { + if (isNpc) { + delete _questioner; + } + } + + void run(); + +protected: + void clear() { + _vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront); + } + + void displayQuestion(); + bool displayAnswers(); + bool displayAnswer(uint16 i); + + uint16 getAnswer(); + int16 selectAnswer(); + uint16 askPassword(); + int16 getHoverAnswer(int16 x, int16 y); + +}; + +uint16 DialogueManager::askPassword() { debugC(1, kDebugDialogue, "checkDialoguePassword()"); char password[100]; uint16 passwordLen = 0; while (true) { + clear(); + strcpy(password, "......."); - _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront); Common::Rect r(_answerBalloonW[0], _answerBalloonH[0]); r.moveTo(_answerBalloonX[0], _answerBalloonY[0]); - _gfx->drawBalloon(r, 1); - _gfx->displayWrappedString(q->_answers[0]->_text, _answerBalloonX[0], _answerBalloonY[0], MAX_BALLOON_WIDTH, 3); - _gfx->flatBlitCnv(face, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront); - _gfx->displayBalloonString(_answerBalloonX[0] + 5, _answerBalloonY[0] + _answerBalloonH[0] - 15, "> ", 0); + _vm->_gfx->drawBalloon(r, 1); + _vm->_gfx->displayWrappedString(_q->_answers[0]->_text, _answerBalloonX[0], _answerBalloonY[0], 3, MAX_BALLOON_WIDTH); + _vm->_gfx->flatBlitCnv(_answerer, 0, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront); + _vm->_gfx->displayString(_answerBalloonX[0] + 5, _answerBalloonY[0] + _answerBalloonH[0] - 15, "> ", 0); + _vm->_gfx->updateScreen(); Common::Event e; while (e.kbd.ascii != Common::KEYCODE_RETURN && passwordLen < MAX_PASSWORD_LENGTH) { @@ -223,15 +266,15 @@ uint16 Parallaction::askDialoguePassword(Dialogue *q, StaticCnv *face) { passwordLen++; password[passwordLen] = '\0'; - _gfx->displayBalloonString(_answerBalloonX[0] + 5, _answerBalloonY[0] + _answerBalloonH[0] - 15, password, 0); - _gfx->updateScreen(); + _vm->_gfx->displayString(_answerBalloonX[0] + 10, _answerBalloonY[0] + _answerBalloonH[0] - 15, password, 0); + _vm->_gfx->updateScreen(); g_system->delayMillis(20); } - if ((!scumm_stricmp(_characterName, _doughName) && !scumm_strnicmp(password, "1732461", 7)) || - (!scumm_stricmp(_characterName, _donnaName) && !scumm_strnicmp(password, "1622", 4)) || - (!scumm_stricmp(_characterName, _dinoName) && !scumm_strnicmp(password, "179", 3))) { + if ((!scumm_stricmp(_vm->_characterName, _doughName) && !scumm_strnicmp(password, "1732461", 7)) || + (!scumm_stricmp(_vm->_characterName, _donnaName) && !scumm_strnicmp(password, "1622", 4)) || + (!scumm_stricmp(_vm->_characterName, _dinoName) && !scumm_strnicmp(password, "179", 3))) { break; @@ -243,165 +286,135 @@ uint16 Parallaction::askDialoguePassword(Dialogue *q, StaticCnv *face) { } -bool _askPassword; -bool Parallaction::displayAnswer(Dialogue *q, uint16 i) { - uint32 v28 = _localFlags[_currentLocationIndex]; - if (q->_answers[i]->_yesFlags & kFlagsGlobal) +bool DialogueManager::displayAnswer(uint16 i) { + + uint32 v28 = _localFlags[_vm->_currentLocationIndex]; + if (_q->_answers[i]->_yesFlags & kFlagsGlobal) v28 = _commandFlags | kFlagsGlobal; // display suitable answers - if (((q->_answers[i]->_yesFlags & v28) == q->_answers[i]->_yesFlags) && ((q->_answers[i]->_noFlags & ~v28) == q->_answers[i]->_noFlags)) { + if (((_q->_answers[i]->_yesFlags & v28) == _q->_answers[i]->_yesFlags) && ((_q->_answers[i]->_noFlags & ~v28) == _q->_answers[i]->_noFlags)) { - _gfx->getStringExtent(q->_answers[i]->_text, MAX_BALLOON_WIDTH, &_answerBalloonW[i], &_answerBalloonH[i]); + _vm->_gfx->getStringExtent(_q->_answers[i]->_text, MAX_BALLOON_WIDTH, &_answerBalloonW[i], &_answerBalloonH[i]); Common::Rect r(_answerBalloonW[i], _answerBalloonH[i]); r.moveTo(_answerBalloonX[i], _answerBalloonY[i]); - _gfx->drawBalloon(r, 1); + _vm->_gfx->drawBalloon(r, 1); _answerBalloonY[i+1] = 10 + _answerBalloonY[i] + _answerBalloonH[i]; - _askPassword = _gfx->displayWrappedString(q->_answers[i]->_text, _answerBalloonX[i], _answerBalloonY[i], MAX_BALLOON_WIDTH, 3); + _askPassword = _vm->_gfx->displayWrappedString(_q->_answers[i]->_text, _answerBalloonX[i], _answerBalloonY[i], 3, MAX_BALLOON_WIDTH); return true; } + _answerBalloonY[i+1] = _answerBalloonY[i]; + _answerBalloonY[i] = SKIPPED_ANSWER; + return false; } -bool Parallaction::displayAnswers(Dialogue *q) { +bool DialogueManager::displayAnswers() { bool displayed = false; uint16 i = 0; - while (i < NUM_ANSWERS && q->_answers[i]) { - if (displayAnswer(q, i)) { + while (i < NUM_ANSWERS && _q->_answers[i]) { + if (displayAnswer(i)) displayed = true; - } else { - _answerBalloonY[i+1] = _answerBalloonY[i]; - _answerBalloonY[i] = SKIPPED_ANSWER; - } + i++; } - _gfx->updateScreen(); + _vm->_gfx->updateScreen(); return displayed; } -void Parallaction::displayQuestion(Dialogue *q, Cnv *cnv) { +void DialogueManager::displayQuestion() { int16 w = 0, h = 0; - if (!scumm_stricmp(q->_text, "NULL")) return; - - StaticCnv face; - face._width = cnv->_width; - face._height = cnv->_height; - face._data0 = cnv->getFramePtr(q->_mood & 0xF); - face._data1 = NULL; // cnv->field_8[v60->_mood & 0xF]; + if (!scumm_stricmp(_q->_text, "NULL")) return; - _gfx->flatBlitCnv(&face, QUESTION_CHARACTER_X, QUESTION_CHARACTER_Y, Gfx::kBitFront); - _gfx->getStringExtent(q->_text, MAX_BALLOON_WIDTH, &w, &h); + _vm->_gfx->flatBlitCnv(_questioner, _q->_mood & 0xF, QUESTION_CHARACTER_X, QUESTION_CHARACTER_Y, Gfx::kBitFront); + _vm->_gfx->getStringExtent(_q->_text, MAX_BALLOON_WIDTH, &w, &h); Common::Rect r(w, h); r.moveTo(QUESTION_BALLOON_X, QUESTION_BALLOON_Y); - _gfx->drawBalloon(r, q->_mood & 0x10); - _gfx->displayWrappedString(q->_text, QUESTION_BALLOON_X, QUESTION_BALLOON_Y, MAX_BALLOON_WIDTH, 0); - _gfx->updateScreen(); + _vm->_gfx->drawBalloon(r, _q->_mood & 0x10); + _vm->_gfx->displayWrappedString(_q->_text, QUESTION_BALLOON_X, QUESTION_BALLOON_Y, 0, MAX_BALLOON_WIDTH); + _vm->_gfx->updateScreen(); waitUntilLeftClick(); - _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront); + clear(); return; } -uint16 Parallaction::getDialogueAnswer(Dialogue *q, Cnv *cnv) { +uint16 DialogueManager::getAnswer() { uint16 answer = 0; - StaticCnv face; - face._width = cnv->_width; - face._height = cnv->_height; - face._data0 = cnv->getFramePtr(0); - face._data1 = NULL; // cnv->field_8[0]; - - _gfx->flatBlitCnv(&face, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront); - if (_askPassword == false) { - answer = selectAnswer(q, &face); + answer = selectAnswer(); } else { - answer = askDialoguePassword(q, &face); + answer = askPassword(); } - _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront); // erase answer screen + clear(); debugC(1, kDebugDialogue, "runDialogue: user selected answer #%i", answer); return answer; } -void Parallaction::runDialogue(SpeakData *data) { - debugC(1, kDebugDialogue, "runDialogue: starting dialogue '%s'", data->_name); - - enterDialogue(); - - _gfx->setFont(kFontDialogue); - - bool isNpc = scumm_stricmp(data->_name, "yourself") && data->_name[0] != '\0'; - Cnv *face = isNpc ? _disk->loadTalk(data->_name) : _char._talk; +void DialogueManager::run() { _askPassword = false; CommandList *cmdlist = NULL; - uint16 answer; - Dialogue *q = data->_dialogue; - while (q) { + _q = _dialogue->_questions[0]; + int16 answer; + + while (_q) { answer = 0; - displayQuestion(q, face); - if (q->_answers[0] == NULL) break; + displayQuestion(); + if (_q->_answers[0] == NULL) break; _answerBalloonY[0] = 10; - if (scumm_stricmp(q->_answers[0]->_text, "NULL")) { - if (!displayAnswers(q)) break; - answer = getDialogueAnswer(q, _char._talk); - cmdlist = &q->_answers[answer]->_commands; + if (scumm_stricmp(_q->_answers[0]->_text, "NULL")) { + if (!displayAnswers()) break; + answer = getAnswer(); + cmdlist = &_q->_answers[answer]->_commands; } - q = q->_answers[answer]->_following._question; + _q = _q->_answers[answer]->_following._question; } - debugC(1, kDebugDialogue, "runDialogue: out of dialogue loop"); - - _gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront); - - if (isNpc) { - delete face; - } + clear(); - exitDialogue(); if (cmdlist) - runCommands(*cmdlist); - - return; + _vm->runCommands(*cmdlist); } -int16 Parallaction::selectAnswer(Question *q, StaticCnv *cnv) { +int16 DialogueManager::selectAnswer() { int16 numAvailableAnswers = 0; int16 _si = 0; int16 _di = 0; int16 i = 0; - for (; q->_answers[i]; i++) { + for (; _q->_answers[i]; i++) { if (_answerBalloonY[i] == SKIPPED_ANSWER) continue; _di = i; @@ -410,11 +423,9 @@ int16 Parallaction::selectAnswer(Question *q, StaticCnv *cnv) { _answerBalloonY[i] = 2000; if (numAvailableAnswers == 1) { - _gfx->displayWrappedString(q->_answers[_di]->_text, _answerBalloonX[_di], _answerBalloonY[_di], MAX_BALLOON_WIDTH, 0); - cnv->_data0 = _char._talk->getFramePtr(q->_answers[_di]->_mood & 0xF); -// cnv->_data1 = _char._talk->field_8[q->_answers[_di]->_mood & 0xF]; - _gfx->flatBlitCnv(cnv, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront); - _gfx->updateScreen(); + _vm->_gfx->displayWrappedString(_q->_answers[_di]->_text, _answerBalloonX[_di], _answerBalloonY[_di], 0, MAX_BALLOON_WIDTH); + _vm->_gfx->flatBlitCnv(_answerer, _q->_answers[_di]->_mood & 0xF, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront); + _vm->_gfx->updateScreen(); waitUntilLeftClick(); return _di; } @@ -424,20 +435,18 @@ int16 Parallaction::selectAnswer(Question *q, StaticCnv *cnv) { _mouseButtons = kMouseNone; while (_mouseButtons != kMouseLeftUp) { - updateInput(); - _si = getHoverAnswer(_mousePos.x, _mousePos.y, q); + _vm->updateInput(); + _si = getHoverAnswer(_vm->_mousePos.x, _vm->_mousePos.y); if (_si != v2) { if (v2 != -1) - _gfx->displayWrappedString(q->_answers[v2]->_text, _answerBalloonX[v2], _answerBalloonY[v2], MAX_BALLOON_WIDTH, 3); + _vm->_gfx->displayWrappedString(_q->_answers[v2]->_text, _answerBalloonX[v2], _answerBalloonY[v2], 3, MAX_BALLOON_WIDTH); - _gfx->displayWrappedString(q->_answers[_si]->_text, _answerBalloonX[_si], _answerBalloonY[_si], MAX_BALLOON_WIDTH, 0); - cnv->_data0 = _char._talk->getFramePtr(q->_answers[_si]->_mood & 0xF); -// cnv->_data1 = _char._talk->field_8[q->_answers[_si]->_mood & 0xF]; - _gfx->flatBlitCnv(cnv, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront); + _vm->_gfx->displayWrappedString(_q->_answers[_si]->_text, _answerBalloonX[_si], _answerBalloonY[_si], 0, MAX_BALLOON_WIDTH); + _vm->_gfx->flatBlitCnv(_answerer, _q->_answers[_si]->_mood & 0xF, ANSWER_CHARACTER_X, ANSWER_CHARACTER_Y, Gfx::kBitFront); } - _gfx->updateScreen(); + _vm->_gfx->updateScreen(); g_system->delayMillis(30); v2 = _si; } @@ -449,13 +458,13 @@ int16 Parallaction::selectAnswer(Question *q, StaticCnv *cnv) { // // finds out which answer is currently selected // -int16 getHoverAnswer(int16 x, int16 y, Question *q) { +int16 DialogueManager::getHoverAnswer(int16 x, int16 y) { int16 top = 1000; int16 bottom = 1000; for (int16 _si = 0; _si < NUM_ANSWERS; _si++) { - if (q->_answers[_si] == NULL) break; + if (_q->_answers[_si] == NULL) break; if (_answerBalloonY[_si] != SKIPPED_ANSWER) { top = _answerBalloonY[_si]; @@ -476,21 +485,21 @@ int16 getHoverAnswer(int16 x, int16 y, Question *q) { } -void Parallaction::enterDialogue() { - showCursor(false); - - return; -} +void Parallaction::runDialogue(SpeakData *data) { + debugC(1, kDebugDialogue, "runDialogue: starting dialogue '%s'", data->_name); -// rebuilds inventory -// -void Parallaction::exitDialogue() { + _gfx->setFont(kFontDialogue); - refreshInventory(_characterName); + if (_vm->getPlatform() == Common::kPlatformPC) + showCursor(false); + DialogueManager man(this, data); + man.run(); + + refreshInventory(_characterName); showCursor(true); - + return; } @@ -503,12 +512,8 @@ Answer::Answer() { } Answer::~Answer() { - if (_mood & 0x10) - delete _following._question; - if (_text) free(_text); - } Question::Question() { diff --git a/engines/parallaction/disk.cpp b/engines/parallaction/disk.cpp index 7b11fbbbed..2e6d9e4820 100644 --- a/engines/parallaction/disk.cpp +++ b/engines/parallaction/disk.cpp @@ -26,6 +26,8 @@ #include "common/stdafx.h" #include "graphics/iff.h" +#include "graphics/surface.h" + #include "parallaction/parallaction.h" @@ -90,8 +92,10 @@ void Disk::errorFileNotFound(const char *s) { } -void Disk::selectArchive(const char *name) { - _resArchive.open(name); +Common::String Disk::selectArchive(const Common::String& name) { + Common::String oldName = _resArchive.name(); + _resArchive.open(name.c_str()); + return oldName; } void Disk::setLanguage(uint16 language) { @@ -691,33 +695,106 @@ AmigaDisk::~AmigaDisk() { #define NUM_PLANES 5 -// FIXME: no mask is loaded -void AmigaDisk::unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 planeSize) { +/* + unpackFrame transforms images from 5-bitplanes format to + 8-bit color-index mode +*/ +void AmigaDisk::unpackFrame(byte *dst, byte *src, uint16 planeSize) { byte s0, s1, s2, s3, s4, mask, t0, t1, t2, t3, t4; - for (uint32 i = 0; i < numFrames; i++) { - for (uint32 j = 0; j < planeSize; j++) { - s0 = src[j]; - s1 = src[j+planeSize]; - s2 = src[j+planeSize*2]; - s3 = src[j+planeSize*3]; - s4 = src[j+planeSize*4]; - - for (uint32 k = 0; k < 8; k++) { - mask = 1 << (7 - k); - t0 = (s0 & mask ? 1 << 0 : 0); - t1 = (s1 & mask ? 1 << 1 : 0); - t2 = (s2 & mask ? 1 << 2 : 0); - t3 = (s3 & mask ? 1 << 3 : 0); - t4 = (s4 & mask ? 1 << 4 : 0); - *dst++ = t0 | t1 | t2 | t3 | t4; + for (uint32 j = 0; j < planeSize; j++) { + s0 = src[j]; + s1 = src[j+planeSize]; + s2 = src[j+planeSize*2]; + s3 = src[j+planeSize*3]; + s4 = src[j+planeSize*4]; + + for (uint32 k = 0; k < 8; k++) { + mask = 1 << (7 - k); + t0 = (s0 & mask ? 1 << 0 : 0); + t1 = (s1 & mask ? 1 << 1 : 0); + t2 = (s2 & mask ? 1 << 2 : 0); + t3 = (s3 & mask ? 1 << 3 : 0); + t4 = (s4 & mask ? 1 << 4 : 0); + *dst++ = t0 | t1 | t2 | t3 | t4; + } + + } + +} + +/* + patchFrame applies DLTA data (dlta) to specified buffer (dst) +*/ +void AmigaDisk::patchFrame(byte *dst, byte *dlta, uint16 bytesPerPlane, uint16 height) { + + uint32 *dataIndex = (uint32*)dlta; + uint32 *ofslenIndex = (uint32*)dlta + 8; + + uint16 *base = (uint16*)dlta; + uint16 wordsPerLine = bytesPerPlane >> 1; + + for (uint j = 0; j < NUM_PLANES; j++) { + uint16 *dst16 = (uint16*)(dst + j * bytesPerPlane * height); + + uint16 *data = base + READ_BE_UINT32(dataIndex); + dataIndex++; + uint16 *ofslen = base + READ_BE_UINT32(ofslenIndex); + ofslenIndex++; + + while (*ofslen != 0xFFFF) { + + uint16 ofs = READ_BE_UINT16(ofslen); + ofslen++; + uint16 size = READ_BE_UINT16(ofslen); + ofslen++; + + while (size > 0) { + dst16[ofs] ^= *data++; + ofs += wordsPerLine; + size--; } } - src += planeSize * NUM_PLANES; } + +} + +// FIXME: no mask is loaded +void AmigaDisk::unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 bytesPerPlane, uint16 height) { + + byte *baseFrame = src; + byte *tempBuffer = 0; + + uint16 planeSize = bytesPerPlane * height; + + for (uint32 i = 0; i < numFrames; i++) { + if (READ_BE_UINT32(src) == MKID_BE('DLTA')) { + + uint size = READ_BE_UINT32(src + 4); + + if (tempBuffer == 0) + tempBuffer = (byte*)malloc(planeSize * NUM_PLANES); + + memcpy(tempBuffer, baseFrame, planeSize * NUM_PLANES); + + patchFrame(tempBuffer, src + 8, bytesPerPlane, height); + unpackFrame(dst, tempBuffer, planeSize); + + src += (size + 8); + dst += planeSize * 8; + } else { + unpackFrame(dst, src, planeSize); + src += planeSize * NUM_PLANES; + dst += planeSize * 8; + } + } + + if (tempBuffer) + free(tempBuffer); + } StaticCnv* AmigaDisk::makeStaticCnv(Common::SeekableReadStream &stream) { @@ -737,7 +814,7 @@ StaticCnv* AmigaDisk::makeStaticCnv(Common::SeekableReadStream &stream) { uint32 decsize = width * height; byte *data = (byte*)calloc(decsize, 1); - unpackBitmap(data, buf, 1, height * bytesPerPlane); + unpackBitmap(data, buf, 1, bytesPerPlane, height); free(buf); @@ -767,7 +844,7 @@ Cnv* AmigaDisk::makeCnv(Common::SeekableReadStream &stream) { uint32 decsize = numFrames * width * height; byte *data = (byte*)calloc(decsize, 1); - unpackBitmap(data, buf, numFrames, height * bytesPerPlane); + unpackBitmap(data, buf, numFrames, bytesPerPlane, height); free(buf); diff --git a/engines/parallaction/disk.h b/engines/parallaction/disk.h index bfef6d81df..14ea4f0e16 100644 --- a/engines/parallaction/disk.h +++ b/engines/parallaction/disk.h @@ -60,6 +60,7 @@ protected: uint32 _fileCursor; uint32 _fileEndOffset; + Common::String _archiveName; char _archiveDir[MAX_ARCHIVE_ENTRIES][32]; uint32 _archiveLenghts[MAX_ARCHIVE_ENTRIES]; uint32 _archiveOffsets[MAX_ARCHIVE_ENTRIES]; @@ -74,9 +75,11 @@ protected: public: Archive(); - void open(const char *file); + void open(const char* file); void close(); + Common::String name() const; + bool openArchivedFile(const char *name); void closeArchivedFile(); @@ -103,7 +106,7 @@ public: Disk(Parallaction *vm); virtual ~Disk(); - void selectArchive(const char *name); + Common::String selectArchive(const Common::String &name); void setLanguage(uint16 language); virtual Script* loadLocation(const char *name) = 0; @@ -163,7 +166,9 @@ class AmigaDisk : public Disk { protected: Cnv* makeCnv(Common::SeekableReadStream &stream); StaticCnv* makeStaticCnv(Common::SeekableReadStream &stream); - void unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 planeSize); + void patchFrame(byte *dst, byte *dlta, uint16 bytesPerPlane, uint16 height); + void unpackFrame(byte *dst, byte *src, uint16 planeSize); + void unpackBitmap(byte *dst, byte *src, uint16 numFrames, uint16 bytesPerPlane, uint16 height); Common::SeekableReadStream *openArchivedFile(const char* name, bool errorOnFileNotFound = false); Font *createFont(const char *name, Common::SeekableReadStream &stream); void loadMask(const char *name); diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp index aab35f8562..59645381b6 100644 --- a/engines/parallaction/graphics.cpp +++ b/engines/parallaction/graphics.cpp @@ -306,8 +306,6 @@ void Gfx::floodFill(Gfx::Buffers buffer, const Common::Rect& r, byte color) { d += SCREEN_WIDTH; } - if (buffer == kBitFront) updateScreen(); - return; } @@ -350,8 +348,6 @@ void Gfx::flatBlit(const Common::Rect& r, byte *data, Gfx::Buffers buffer) { d += (SCREEN_WIDTH - q.width()); } - if (buffer == kBitFront) updateScreen(); - return; } @@ -389,8 +385,6 @@ void Gfx::blit(const Common::Rect& r, uint16 z, byte *data, Gfx::Buffers buffer) d += (SCREEN_WIDTH - q.right + q.left); } - if (buffer == kBitFront) updateScreen(); - return; } @@ -480,6 +474,18 @@ void Gfx::setMousePointer(int16 index) { // // Cnv management // +void Gfx::flatBlitCnv(Cnv *cnv, uint16 frame, int16 x, int16 y, Gfx::Buffers buffer) { + + StaticCnv scnv; + + scnv._width = cnv->_width; + scnv._height = cnv->_height; + scnv._data0 = cnv->getFramePtr(frame); + scnv._data1 = NULL; // _questioner->field_8[v60->_mood & 0xF]; + + flatBlitCnv(&scnv, x, y, buffer); +} + void Gfx::flatBlitCnv(StaticCnv *cnv, int16 x, int16 y, Gfx::Buffers buffer) { Common::Rect r(cnv->_width, cnv->_height); r.moveTo(x, y); @@ -577,30 +583,19 @@ void Gfx::makeCnvFromString(StaticCnv *cnv, char *text) { } -void Gfx::displayString(uint16 x, uint16 y, const char *text) { - assert(_font == _fonts[kFontMenu]); - +void Gfx::displayString(uint16 x, uint16 y, const char *text, byte color) { byte *dst = _buffers[kBitFront] + x + y*SCREEN_WIDTH; - _font->setColor(1); + _font->setColor(color); _font->drawString(dst, SCREEN_WIDTH, text); } void Gfx::displayCenteredString(uint16 y, const char *text) { uint16 x = (SCREEN_WIDTH - getStringWidth(text)) / 2; - displayString(x, y, text); -} - -void Gfx::displayBalloonString(uint16 x, uint16 y, const char *text, byte color) { - assert(_font == _fonts[kFontDialogue]); - - byte *dst = _buffers[kBitFront] + x + y*SCREEN_WIDTH; - - _font->setColor(color); - _font->drawString(dst, SCREEN_WIDTH, text); + displayString(x, y, text, 1); } -bool Gfx::displayWrappedString(char *text, uint16 x, uint16 y, uint16 maxwidth, byte color) { -// printf("Gfx::displayWrappedString(%s, %i, %i, %i, %i)...", text, x, y, maxwidth, color); +bool Gfx::displayWrappedString(char *text, uint16 x, uint16 y, byte color, uint16 wrapwidth) { +// printf("Gfx::displayWrappedString(%s, %i, %i, %i, %i)...", text, x, y, color, wrapwidth); uint16 lines = 0; bool rv = false; @@ -613,10 +608,10 @@ bool Gfx::displayWrappedString(char *text, uint16 x, uint16 y, uint16 maxwidth, while (strlen(text) > 0) { - text = parseNextToken(text, token, 40, " "); + text = parseNextToken(text, token, 40, " ", true); linewidth += getStringWidth(token); - if (linewidth > maxwidth) { + if (linewidth > wrapwidth) { // wrap line lines++; rx = x + 10; // x @@ -630,7 +625,7 @@ bool Gfx::displayWrappedString(char *text, uint16 x, uint16 y, uint16 maxwidth, if (!scumm_stricmp(token, "%p")) { rv = true; } else - displayBalloonString(rx, ry, token, color); + displayString(rx, ry, token, color); rx += getStringWidth(token) + getStringWidth(" "); linewidth += getStringWidth(" "); @@ -658,7 +653,7 @@ void Gfx::getStringExtent(char *text, uint16 maxwidth, int16* width, int16* heig while (strlen(text) != 0) { - text = parseNextToken(text, token, 40, " "); + text = parseNextToken(text, token, 40, " ", true); w += getStringWidth(token); if (w > maxwidth) { diff --git a/engines/parallaction/graphics.h b/engines/parallaction/graphics.h index 1f0c467293..d535d3cf05 100644 --- a/engines/parallaction/graphics.h +++ b/engines/parallaction/graphics.h @@ -67,7 +67,7 @@ struct PaletteFxRange { byte _first; byte _last; -}; +} PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING @@ -165,10 +165,9 @@ public: // dialogue and text void drawBalloon(const Common::Rect& r, uint16 arg_8); - void displayBalloonString(uint16 x, uint16 y, const char *text, byte color); - void displayString(uint16 x, uint16 y, const char *text); + void displayString(uint16 x, uint16 y, const char *text, byte color); void displayCenteredString(uint16 y, const char *text); - bool displayWrappedString(char *text, uint16 x, uint16 y, uint16 maxwidth, byte color); + bool displayWrappedString(char *text, uint16 x, uint16 y, byte color, uint16 wrapwidth = SCREEN_WIDTH); uint16 getStringWidth(const char *text); void getStringExtent(char *text, uint16 maxwidth, int16* width, int16* height); @@ -204,6 +203,8 @@ public: // DOS version didn't make use of it, but it is probably needed for Amiga stuff. void flatBlitCnv(StaticCnv *cnv, int16 x, int16 y, Gfx::Buffers buffer); void blitCnv(StaticCnv *cnv, int16 x, int16 y, uint16 z, Gfx::Buffers buffer); + void flatBlitCnv(Cnv *cnv, uint16 frame, int16 x, int16 y, Gfx::Buffers buffer); + // palette void setPalette(Palette palette, uint32 first = FIRST_BASE_COLOR, uint32 num = BASE_PALETTE_COLORS); diff --git a/engines/parallaction/location.cpp b/engines/parallaction/location.cpp index 4d8efa3255..3c54460692 100644 --- a/engines/parallaction/location.cpp +++ b/engines/parallaction/location.cpp @@ -38,6 +38,7 @@ void Parallaction::parseLocation(const char *filename) { _gfx->setFont(kFontLabel); Script *_locationScript = _disk->loadLocation(filename); + _hasLocationSound = false; fillBuffers(*_locationScript, true); while (scumm_stricmp(_tokens[0], "ENDLOCATION")) { @@ -140,16 +141,15 @@ void Parallaction::parseLocation(const char *filename) { parseAnimation(*_locationScript, _animations, _tokens[1]); } if (!scumm_stricmp(_tokens[0], "SOUND")) { - strcpy(_soundFile, _tokens[1]); + if (getPlatform() == Common::kPlatformAmiga) { + strcpy(_locationSound, _tokens[1]); + _hasLocationSound = true; + } } if (!scumm_stricmp(_tokens[0], "MUSIC")) { if (getPlatform() == Common::kPlatformAmiga) _soundMan->setMusicFile(_tokens[1]); } - if (!scumm_stricmp(_tokens[0], "SOUND")) { -// if (getPlatform() == Common::kPlatformAmiga) -// _soundMan->loadSfx(_tokens[1], atoi(_tokens[2])); - } fillBuffers(*_locationScript, true); } @@ -182,14 +182,14 @@ void Parallaction::freeLocation() { if (_localFlagNames) delete _localFlagNames; - + // HACK: prevents leakage. A routine like this // should allocate memory at all, though. if ((_engineFlags & kEngineQuit) == 0) { _localFlagNames = new Table(120); _localFlagNames->addData("visited"); } - + _location._walkNodes.clear(); // TODO (LIST): helperNode should be rendered useless by the use of a Common::List<> @@ -379,11 +379,11 @@ void Parallaction::changeLocation(char *location) { runJobs(); _gfx->swapBuffers(); } - + if (_location._comment) { doLocationEnterTransition(); } - + runJobs(); _gfx->swapBuffers(); @@ -392,7 +392,8 @@ void Parallaction::changeLocation(char *location) { runCommands(_location._aCommands); } -// _soundMan->playSfx(0); + if (_hasLocationSound) + _soundMan->playSfx(_locationSound, 0, true); debugC(1, kDebugLocation, "changeLocation() done"); @@ -416,7 +417,7 @@ void Parallaction::doLocationEnterTransition() { debugC(3, kDebugLocation, "skipping location transition"); return; // visited } - + byte pal[PALETTE_SIZE]; _gfx->buildBWPalette(pal); _gfx->setPalette(pal); @@ -437,7 +438,7 @@ void Parallaction::doLocationEnterTransition() { _gfx->floodFill(Gfx::kBitFront, r, 0); r.grow(-1); _gfx->floodFill(Gfx::kBitFront, r, 1); - _gfx->displayWrappedString(_location._comment, 3, 5, 130, 0); + _gfx->displayWrappedString(_location._comment, 3, 5, 0, 130); _gfx->updateScreen(); waitUntilLeftClick(); diff --git a/engines/parallaction/menu.cpp b/engines/parallaction/menu.cpp index b1b6fb44c8..427f24a467 100644 --- a/engines/parallaction/menu.cpp +++ b/engines/parallaction/menu.cpp @@ -201,7 +201,7 @@ uint16 Menu::chooseLanguage() { _vm->_gfx->setPalette(_vm->_gfx->_palette); _vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBitFront); - _vm->_gfx->displayString(60, 30, "SELECT LANGUAGE"); + _vm->_gfx->displayString(60, 30, "SELECT LANGUAGE", 1); _vm->_gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack); _vm->_gfx->copyScreen(Gfx::kBitBack, Gfx::kBit2); @@ -287,10 +287,10 @@ uint16 Menu::selectGame() { if (_si != 0) { // load a game - _vm->_gfx->displayString(60, 30, loadGameMsg[_language]); + _vm->_gfx->displayString(60, 30, loadGameMsg[_language], 1); } else { // new game - _vm->_gfx->displayString(60, 30, newGameMsg[_language]); + _vm->_gfx->displayString(60, 30, newGameMsg[_language], 1); } _vm->_gfx->updateScreen(); @@ -353,7 +353,7 @@ void Menu::selectCharacter() { askPassword = false; _di = 0; - _vm->_gfx->displayString(60, 30, introMsg1[_language]); // displays message + _vm->_gfx->displayString(60, 30, introMsg1[_language], 1); // displays message _vm->_gfx->copyScreen(Gfx::kBitFront, Gfx::kBitBack); _donna_points = 0; @@ -415,7 +415,7 @@ void Menu::selectCharacter() { if (askPassword == false) break; _vm->_gfx->copyScreen(Gfx::kBit2, Gfx::kBitFront); - _vm->_gfx->displayString(60, 30, introMsg2[_language]); + _vm->_gfx->displayString(60, 30, introMsg2[_language], 1); _vm->_gfx->updateScreen(); g_system->delayMillis(2000); diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp index e0291c5a2a..c830b575a9 100644 --- a/engines/parallaction/parallaction.cpp +++ b/engines/parallaction/parallaction.cpp @@ -84,7 +84,6 @@ Command * _forwardedCommands[20] = { char _forwardedAnimationNames[20][20]; uint16 _numForwards = 0; -char _soundFile[20]; uint32 _commandFlags = 0; uint16 _introSarcData3 = 200; @@ -158,6 +157,8 @@ int Parallaction::init() { _localFlagNames = NULL; initResources(); + _hasLocationSound = false; + _skipMenu = false; _transCurrentHoverItem = 0; @@ -369,6 +370,9 @@ void Parallaction::runGame() { if (_location._comment) doLocationEnterTransition(); + if (_hasLocationSound) + _soundMan->playSfx(_locationSound, 0, true); + changeCursor(kCursorArrow); if (_location._aCommands.size() > 0) @@ -759,10 +763,13 @@ void Parallaction::changeCharacter(const char *name) { // character for sanity before memory is freed freeCharacter(); - _disk->selectArchive((_vm->getPlatform() == Common::kPlatformAmiga) ? "disk0" : "disk1"); + Common::String oldArchive = _disk->selectArchive((_vm->getFeatures() & GF_LANG_MULT) ? "disk1" : "disk0"); _vm->_char._ani._cnv = _disk->loadFrames(fullName); if (!IS_DUMMY_CHARACTER(name)) { + if (_vm->getPlatform() == Common::kPlatformAmiga && (_vm->getFeatures() & GF_LANG_MULT)) + _disk->selectArchive("disk0"); + _vm->_char._head = _disk->loadHead(baseName); _vm->_char._talk = _disk->loadTalk(baseName); _vm->_char._objs = _disk->loadObjects(baseName); @@ -774,6 +781,9 @@ void Parallaction::changeCharacter(const char *name) { if (!(getFeatures() & GF_DEMO)) parseLocation("common"); } + + if (!oldArchive.empty()) + _disk->selectArchive(oldArchive); } strcpy(_characterName1, fullName); diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h index 38db16ce99..561b15acc9 100644 --- a/engines/parallaction/parallaction.h +++ b/engines/parallaction/parallaction.h @@ -27,8 +27,7 @@ #define PARALLACTION_H #include "common/str.h" -#include "gui/dialog.h" -#include "gui/widget.h" + #include "engines/engine.h" @@ -62,7 +61,7 @@ enum { enum { GF_DEMO = 1 << 0, GF_LANG_EN = 1 << 1, - GF_LANG_FR = 1 << 2, + GF_LANG_FR = 1 << 2, GF_LANG_DE = 1 << 3, GF_LANG_IT = 1 << 4, GF_LANG_MULT = 1 << 5 @@ -177,7 +176,6 @@ extern uint32 _localFlags[]; extern Command *_forwardedCommands[]; extern char _forwardedAnimationNames[][20]; extern uint16 _numForwards; -extern char _soundFile[]; extern char _slideText[][40]; extern uint16 _introSarcData3; // sarcophagus stuff to be saved extern uint16 _introSarcData2; // sarcophagus stuff to be saved @@ -398,7 +396,7 @@ protected: // data bool _skipMenu; bool _mouseHidden; - + // input-only InputData _input; bool _actionAfterWalk; // actived when the character needs to move before taking an action @@ -417,6 +415,9 @@ protected: // data Common::String _saveFileName; + bool _hasLocationSound; + char _locationSound[50]; + protected: // members bool detectGame(void); @@ -461,15 +462,6 @@ protected: // members void freeCharacter(); - uint16 askDialoguePassword(Dialogue *q, StaticCnv *face); - bool displayAnswer(Dialogue *q, uint16 i); - bool displayAnswers(Dialogue *q); - void displayQuestion(Dialogue *q, Cnv *cnv); - uint16 getDialogueAnswer(Dialogue *q, Cnv *cnv); - int16 selectAnswer(Question *q, StaticCnv *cnv); - void enterDialogue(); - void exitDialogue(); - int addInventoryItem(uint16 item); void dropItem(uint16 item); int16 pickupItem(Zone *z); @@ -480,33 +472,6 @@ protected: // members // FIXME: remove global extern Parallaction *_vm; -class SaveLoadChooser : public GUI::Dialog { - typedef Common::String String; - typedef Common::StringList StringList; -protected: - GUI::ListWidget *_list; - GUI::ButtonWidget *_chooseButton; - GUI::GraphicsWidget *_gfxWidget; - GUI::StaticTextWidget *_date; - GUI::StaticTextWidget *_time; - GUI::StaticTextWidget *_playtime; - GUI::ContainerWidget *_container; - Parallaction *_vm; - - uint8 _fillR, _fillG, _fillB; - -public: - SaveLoadChooser(const String &title, const String &buttonLabel, Parallaction *engine); - ~SaveLoadChooser(); - - virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data); - const String &getResultString() const; - void setList(const StringList& list); - int runModal(); - - virtual void reflowLayout(); -}; - } // namespace Parallaction diff --git a/engines/parallaction/parser.cpp b/engines/parallaction/parser.cpp index f044e6c3c7..44aae6c1cc 100644 --- a/engines/parallaction/parser.cpp +++ b/engines/parallaction/parser.cpp @@ -119,24 +119,72 @@ void clearTokens() { } -// looks for next token in a string // -// scans 's' until one of the stop-chars in 'brk' is found -// builds a token and return the part of the string which hasn't been parsed - -char *parseNextToken(char *s, char *tok, uint16 count, const char *brk) { - - while (*s != '\0') { +// Scans 's' until one of the stop-chars in 'brk' is found, building a token. +// If the routine encounters quotes, it will extract the contained text and +// make a proper token. When scanning inside quotes, 'brk' is ignored and +// only newlines are considered stop-chars. +// +// The routine returns the unparsed portion of the input string 's'. +// +char *parseNextToken(char *s, char *tok, uint16 count, const char *brk, bool ignoreQuotes) { + + enum STATES { NORMAL, QUOTED }; + + STATES state = NORMAL; + + char *t = s; + + while (count > 0) { + + switch (state) { + case NORMAL: + if (*s == '\0') { + *tok = '\0'; + return s; + } + + if (strchr(brk, *s)) { + *tok = '\0'; + return ++s; + } + + if (*s == '"') { + if (ignoreQuotes) { + *tok++ = *s++; + count--; + } else { + state = QUOTED; + s++; + } + } else { + *tok++ = *s++; + count--; + } + break; - if (brk[0] == *s) break; - if (brk[1] == *s) break; - if (brk[2] == *s) break; + case QUOTED: + if (*s == '\0') { + *tok = '\0'; + return s; + } + if (*s == '"' || *s == '\n' || *s == '\t') { + *tok = '\0'; + return ++s; + } + + *tok++ = *s++; + count--; + break; + } - *tok++ = *s++; } *tok = '\0'; - return s; + warning("token was truncated from line '%s'", t); + + return tok; + } uint16 fillTokens(char* line) { @@ -144,15 +192,6 @@ uint16 fillTokens(char* line) { uint16 i = 0; while (strlen(line) > 0 && i < 20) { line = parseNextToken(line, _tokens[i], 40, " \t\n"); - if (_tokens[i][0] == '"' && _tokens[i][strlen(_tokens[i]) - 1] != '"') { - - line = parseNextToken(line, _tokens[i+1], 40, "\""); - strcat(_tokens[i], _tokens[i+1]); - _tokens[i][0] = ' '; - line++; - - } - line = Common::ltrim(line); i++; } diff --git a/engines/parallaction/parser.h b/engines/parallaction/parser.h index e27095bd16..aa3929a52c 100644 --- a/engines/parallaction/parser.h +++ b/engines/parallaction/parser.h @@ -33,7 +33,7 @@ namespace Parallaction { uint16 fillBuffers(Common::SeekableReadStream &stream, bool errorOnEOF = false); -char *parseNextToken(char *s, char *tok, uint16 count, const char *brk); +char *parseNextToken(char *s, char *tok, uint16 count, const char *brk, bool ignoreQuotes = false); extern char _tokens[][40]; diff --git a/engines/parallaction/saveload.cpp b/engines/parallaction/saveload.cpp index f1dc53539d..2a9431ef94 100644 --- a/engines/parallaction/saveload.cpp +++ b/engines/parallaction/saveload.cpp @@ -26,6 +26,7 @@ #include "common/stdafx.h" #include "common/savefile.h" +#include "gui/dialog.h" #include "gui/widget.h" #include "gui/ListWidget.h" #include "gui/message.h" @@ -48,6 +49,37 @@ namespace Parallaction { extern char _gameNames[][20]; + +class SaveLoadChooser : public GUI::Dialog { + typedef Common::String String; + typedef Common::StringList StringList; +protected: + GUI::ListWidget *_list; + GUI::ButtonWidget *_chooseButton; + GUI::GraphicsWidget *_gfxWidget; + GUI::StaticTextWidget *_date; + GUI::StaticTextWidget *_time; + GUI::StaticTextWidget *_playtime; + GUI::ContainerWidget *_container; + Parallaction *_vm; + + uint8 _fillR, _fillG, _fillB; + +public: + SaveLoadChooser(const String &title, const String &buttonLabel, Parallaction *engine); + ~SaveLoadChooser(); + + virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data); + const String &getResultString() const; + void setList(const StringList& list); + int runModal(); + + virtual void reflowLayout(); +}; + + + + void Parallaction::doLoadGame(uint16 slot) { _introSarcData3 = 200; diff --git a/engines/parallaction/zone.cpp b/engines/parallaction/zone.cpp index 7d74a6a59f..d9bd36a1f5 100644 --- a/engines/parallaction/zone.cpp +++ b/engines/parallaction/zone.cpp @@ -216,22 +216,13 @@ void Parallaction::parseZoneTypeBlock(Script &script, Zone *z) { strcpy(vC8, _tokens[1]); - StaticCnv vE0; u->door->_cnv = _disk->loadFrames(vC8); - - vE0._width = u->door->_cnv->_width; - vE0._height = u->door->_cnv->_height; - uint16 _ax = (z->_flags & kFlagsClosed ? 0 : 1); - vE0._data0 = u->door->_cnv->getFramePtr(_ax); - -// _ax = (z->_flags & kFlagsClosed ? 0 : 1); -// vE0._data1 = doorcnv->field_8[_ax]; - u->door->_background = (byte*)malloc(vE0._width*vE0._height); + u->door->_background = (byte*)malloc(u->door->_cnv->_width * u->door->_cnv->_height); _gfx->backupDoorBackground(u->door, z->_left, z->_top); - _gfx->flatBlitCnv(&vE0, z->_left, z->_top, Gfx::kBitBack); + _gfx->flatBlitCnv(u->door->_cnv, _ax, z->_left, z->_top, Gfx::kBitBack); } if (!scumm_stricmp(_tokens[0], "startpos")) { @@ -304,21 +295,15 @@ void Parallaction::parseZoneTypeBlock(Script &script, Zone *z) { void Parallaction::displayCharacterComment(ExamineData *data) { if (data->_description == NULL) return; - StaticCnv v3C; - v3C._width = _char._talk->_width; - v3C._height = _char._talk->_height; - v3C._data0 = _char._talk->getFramePtr(0); - v3C._data1 = NULL; //_talk->field_8[0]; - _gfx->setFont(kFontDialogue); - _gfx->flatBlitCnv(&v3C, 190, 80, Gfx::kBitFront); + _gfx->flatBlitCnv(_char._talk, 0, 190, 80, Gfx::kBitFront); int16 v26, v28; _gfx->getStringExtent(data->_description, 130, &v28, &v26); Common::Rect r(v28, v26); r.moveTo(140, 10); _gfx->drawBalloon(r, 0); - _gfx->displayWrappedString(data->_description, 140, 10, 130, 0); + _gfx->displayWrappedString(data->_description, 140, 10, 0, 130); _gfx->updateScreen(); @@ -359,7 +344,7 @@ void Parallaction::displayItemComment(ExamineData *data) { r.moveTo(0, 90); _gfx->drawBalloon(r, 0); _gfx->flatBlitCnv(_vm->_char._head, 100, 152, Gfx::kBitFront); - _gfx->displayWrappedString(data->_description, 0, 90, 130, 0); + _gfx->displayWrappedString(data->_description, 0, 90, 0, 130); jobEraseAnimations((void*)1, NULL); _gfx->updateScreen(); @@ -441,10 +426,8 @@ void jobToggleDoor(void *parm, Job *j) { uint16 _ax = (z->_flags & kFlagsClosed ? 0 : 1); - v14._data0 = z->u.door->_cnv->getFramePtr(_ax); - - _vm->_gfx->flatBlitCnv(&v14, z->_left, z->_top, Gfx::kBitBack); - _vm->_gfx->flatBlitCnv(&v14, z->_left, z->_top, Gfx::kBit2); + _vm->_gfx->flatBlitCnv(z->u.door->_cnv, _ax, z->_left, z->_top, Gfx::kBitBack); + _vm->_gfx->flatBlitCnv(z->u.door->_cnv, _ax, z->_left, z->_top, Gfx::kBit2); } count++; diff --git a/engines/parallaction/zone.h b/engines/parallaction/zone.h index 9cc0fd6767..634a1364aa 100644 --- a/engines/parallaction/zone.h +++ b/engines/parallaction/zone.h @@ -68,7 +68,8 @@ enum ZoneFlags { }; -#define NUM_ANSWERS 5 +#define NUM_QUESTIONS 20 +#define NUM_ANSWERS 5 struct Command; struct Question; @@ -97,7 +98,9 @@ struct Question { ~Question(); }; -typedef Question Dialogue; +struct Dialogue { + Question *_questions[NUM_QUESTIONS]; +}; struct GetData { // size = 24 uint32 _icon; diff --git a/engines/saga/actor.cpp b/engines/saga/actor.cpp index e0e9415cab..d7882a78fd 100644 --- a/engines/saga/actor.cpp +++ b/engines/saga/actor.cpp @@ -268,6 +268,8 @@ Actor::Actor(SagaEngine *vm) : _vm(vm) { _pathRect.top = _vm->getDisplayInfo().pathStartY; _pathRect.bottom = _vm->_scene->getHeight(); + _showActors = true; + // Get actor resource file context _actorContext = _vm->_resource->getContext(GAME_RESOURCEFILE); if (_actorContext == NULL) { @@ -1130,7 +1132,7 @@ void Actor::handleSpeech(int msec) { } if (_activeSpeech.stringsCount == 0) { - _vm->_script->wakeUpThreadsDelayed(kWaitTypeSpeech, ticksToMSec(kScriptTimeTicksPerSecond / 3)); + _vm->_script->wakeUpThreadsDelayed(kWaitTypeSpeech, _vm->ticksToMSec(kScriptTimeTicksPerSecond / 3)); } return; @@ -1808,6 +1810,10 @@ void Actor::drawActors() { return; } + if (!_showActors) { + return; + } + CommonObjectOrderList::iterator drawOrderIterator; CommonObjectDataPointer drawObject; int frameNumber; @@ -2349,6 +2355,11 @@ void Actor::simulSpeech(const char *string, uint16 *actorIds, int actorIdsCount, } void Actor::abortAllSpeeches() { + // WORKAROUND: Don't abort speeches in scene 31 (tree with beehive). This prevents the + // making fire animation from breaking + if (_vm->getGameType() == GType_ITE && _vm->_scene->currentSceneNumber() == 31) + return; + abortSpeech(); if (_vm->_script->_abortEnabled) diff --git a/engines/saga/actor.h b/engines/saga/actor.h index 1557abffb9..b9ec62337c 100644 --- a/engines/saga/actor.h +++ b/engines/saga/actor.h @@ -612,6 +612,8 @@ public: void freeObjList(); void loadObjList(int objectCount, int objectsResourceID); + void showActors(bool flag) { _showActors = flag; } + /* uint16 _currentFrameIndex; void frameTest() { @@ -712,6 +714,7 @@ private: int _xCellCount; int _yCellCount; Rect _pathRect; + bool _showActors; PathDirectionData *_pathDirectionList; int _pathDirectionListCount; diff --git a/engines/saga/animation.cpp b/engines/saga/animation.cpp index 59c3339c9b..d29fc6ebe6 100644 --- a/engines/saga/animation.cpp +++ b/engines/saga/animation.cpp @@ -445,6 +445,18 @@ void Anim::play(uint16 animId, int vectorTime, bool playing) { if (anim->completed < anim->cycles) { frame = anim->currentFrame; + + // WORKAROUND for a buggy animation in IHNM. Animation 0 in scene 67 (the mob of angry prisoners) should + // start from frame 0, not frame 1. Frame 0 is the background of the animation (the mob of prisoners), whereas + // the rest of the frames are their animated arms. Therefore, in order for the prisoners to appear correctly, + // frame 0 should be displayed as the first frame, but anim->currentframe is set to 1, which means that the + // prisoners will never be shown. In the original, the prisoners (first frame in the animation) are shown a + // bit after the animation is started (which is wrong again, but not that apparent), whereas in ScummVM the + // first frame is never shown. Therefore, make sure that for this animation, frame 0 is shown first + if (_vm->getGameType() == GType_IHNM && _vm->_scene->currentChapterNumber() == 4 && + _vm->_scene->currentSceneNumber() == 67 && animId == 0 && anim->completed == 1) + frame = 0; + // FIXME: if start > 0, then this works incorrectly decodeFrame(anim, anim->frameOffsets[frame], displayBuffer, _vm->getDisplayWidth() * _vm->getDisplayHeight()); _vm->_frameCount++; diff --git a/engines/saga/detection_tables.h b/engines/saga/detection_tables.h index 631a1a4e83..da06255a82 100644 --- a/engines/saga/detection_tables.h +++ b/engines/saga/detection_tables.h @@ -481,6 +481,37 @@ static const SAGAGameDescription gameDescriptions[] = { ITEMacPatch_Files, }, + // Inherit the earth - MAC CD Wyrmkeep version (compressed sound) + { + { + "ite", + "Wyrmkeep CD", + { + {"ite.rsc", GAME_RESOURCEFILE, "4f7fa11c5175980ed593392838523060", -1}, + {"scripts.rsc", GAME_SCRIPTFILE, "adf1f46c1d0589083996a7060c798ad0", -1}, + {"sounds.cmp", GAME_SOUNDFILE, NULL, -1}, + {"inherit the earth voices.cmp",GAME_VOICEFILE, NULL, -1}, + {"music.cmp", GAME_MUSICFILE, NULL, -1}, + { NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformMacintosh, + Common::ADGF_NO_FLAGS + }, + GType_ITE, + GID_ITE_MACCD, + GF_BIG_ENDIAN_DATA | GF_WYRMKEEP | GF_CD_FX | GF_COMPRESSED_SOUNDS, + ITE_DEFAULT_SCENE, + &ITE_Resources, + ARRAYSIZE(ITEWINDEMO_GameFonts), + ITEWINDEMO_GameFonts, + &ITEMACCD_GameSound, + &ITEMACCD_GameSound, + &ITEMACCD_GameMusic, + ARRAYSIZE(ITEMacPatch_Files), + ITEMacPatch_Files, + }, + // Inherit the earth - Linux Demo version // Note: it should be before GID_ITE_WINDEMO2 version { @@ -640,6 +671,42 @@ static const SAGAGameDescription gameDescriptions[] = { NULL, }, + // Inherit the earth - Wyrmkeep combined Windows/Mac/Linux CD (compressed sound) + + // version is different from the other Wyrmkeep re-releases in that it does + // not have any substitute files. Presumably the ite.rsc file has been + // modified to include the Wyrmkeep changes. The resource files are little- + // endian, except for the voice file which is big-endian. + { + { + "ite", + "Multi-OS CD Version", + { + {"ite.rsc", GAME_RESOURCEFILE, "a6433e34b97b15e64fe8214651012db9", -1}, + {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1}, + {"sounds.cmp", GAME_SOUNDFILE, NULL, -1}, + {"inherit the earth voices.cmp",GAME_VOICEFILE | GAME_SWAPENDIAN, NULL, -1}, + {"music.cmp", GAME_MUSICFILE, NULL, -1}, + { NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformUnknown, + Common::ADGF_NO_FLAGS + }, + GType_ITE, + GID_ITE_MULTICD, + GF_WYRMKEEP | GF_CD_FX | GF_COMPRESSED_SOUNDS, + ITE_DEFAULT_SCENE, + &ITE_Resources, + ARRAYSIZE(ITECD_GameFonts), + ITECD_GameFonts, + &ITEMACCD_GameSound, + &ITECD_GameSound, + &ITEMACCD_GameMusic, + 0, + NULL, + }, + // Inherit the earth - Wyrmkeep Linux CD version { { @@ -671,6 +738,37 @@ static const SAGAGameDescription gameDescriptions[] = { ITELinPatch_Files, }, + // Inherit the earth - Wyrmkeep Linux CD version (compressed sound) + { + { + "ite", + "CD Version", + { + {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1}, + {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1}, + {"sounds.cmp", GAME_SOUNDFILE, NULL, -1}, + {"voices.cmp", GAME_VOICEFILE, NULL, -1}, + {"music.cmp", GAME_MUSICFILE, NULL, -1}, + { NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformLinux, + Common::ADGF_NO_FLAGS + }, + GType_ITE, + GID_ITE_LINCD, + GF_WYRMKEEP | GF_CD_FX | GF_COMPRESSED_SOUNDS, + ITE_DEFAULT_SCENE, + &ITE_Resources, + ARRAYSIZE(ITECD_GameFonts), + ITECD_GameFonts, + &ITECD_GameSound, + &ITECD_GameSound, + &ITEMACCD_GameMusic, + ARRAYSIZE(ITELinPatch_Files), + ITELinPatch_Files, + }, + // Inherit the earth - Wyrmkeep Windows CD version { { @@ -701,6 +799,36 @@ static const SAGAGameDescription gameDescriptions[] = { ITEWinPatch1_Files, }, + // Inherit the earth - Wyrmkeep Windows CD version (compressed sound) + { + { + "ite", + "CD Version", + { + {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1}, + {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1}, + {"sounds.cmp", GAME_SOUNDFILE, NULL, -1}, + {"voices.cmp", GAME_VOICEFILE, NULL, -1}, + { NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformWindows, + Common::ADGF_NO_FLAGS + }, + GType_ITE, + GID_ITE_WINCD, + GF_WYRMKEEP | GF_CD_FX | GF_COMPRESSED_SOUNDS, + ITE_DEFAULT_SCENE, + &ITE_Resources, + ARRAYSIZE(ITECD_GameFonts), + ITECD_GameFonts, + &ITECD_GameSound, + &ITECD_GameSound, + NULL, + ARRAYSIZE(ITEWinPatch1_Files), + ITEWinPatch1_Files, + }, + // Inherit the earth - DOS CD version { { @@ -731,6 +859,36 @@ static const SAGAGameDescription gameDescriptions[] = { NULL, }, + // Inherit the earth - DOS CD version (compressed sound) + { + { + "ite", + "CD Version", + { + {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1}, + {"scripts.rsc", GAME_SCRIPTFILE, "50a0d2d7003c926a3832d503c8534e90", -1}, + {"sounds.cmp", GAME_SOUNDFILE, NULL, -1}, + {"voices.cmp", GAME_VOICEFILE, NULL, -1}, + { NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GType_ITE, + GID_ITE_CD_G, + GF_CD_FX | GF_COMPRESSED_SOUNDS, + ITE_DEFAULT_SCENE, + &ITE_Resources, + ARRAYSIZE(ITECD_GameFonts), + ITECD_GameFonts, + &ITECD_GameSound, + &ITECD_GameSound, + NULL, + 0, + NULL, + }, + // Inherit the earth - DOS CD version with digital music { { @@ -762,6 +920,37 @@ static const SAGAGameDescription gameDescriptions[] = { NULL, }, + // Inherit the earth - DOS CD version with digital music (compressed sound) + { + { + "ite", + "CD Version", + { + {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1}, + {"scripts.rsc", GAME_SCRIPTFILE, "50a0d2d7003c926a3832d503c8534e90", -1}, + {"sounds.cmp", GAME_SOUNDFILE, NULL, -1}, + {"voices.cmp", GAME_VOICEFILE, NULL, -1}, + {"music.cmp", GAME_MUSICFILE, NULL, -1}, + { NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GType_ITE, + GID_ITE_CD_G2, + GF_CD_FX | GF_COMPRESSED_SOUNDS, + ITE_DEFAULT_SCENE, + &ITE_Resources, + ARRAYSIZE(ITECD_GameFonts), + ITECD_GameFonts, + &ITECD_GameSound, + &ITECD_GameSound, + &ITEMACCD_GameMusic, + 0, + NULL, + }, + // Inherit the earth - DOS CD German version // reported by mld. Bestsellergamers cover disk { @@ -793,6 +982,37 @@ static const SAGAGameDescription gameDescriptions[] = { NULL, }, + // Inherit the earth - DOS CD German version (compressed sound) + // reported by mld. Bestsellergamers cover disk + { + { + "ite", + "CD Version", + { + {"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1}, + {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1}, + {"sounds.cmp", GAME_SOUNDFILE, NULL, -1}, + {"voices.cmp", GAME_VOICEFILE, NULL, -1}, + { NULL, 0, NULL, 0} + }, + Common::DE_DEU, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GType_ITE, + GID_ITE_CD_DE, + GF_CD_FX | GF_COMPRESSED_SOUNDS, + ITE_DEFAULT_SCENE, + &ITE_Resources, + ARRAYSIZE(ITECD_GameFonts), + ITECD_GameFonts, + &ITECD_GameSound, + &ITECD_GameSound, + NULL, + 0, + NULL, + }, + // Inherit the earth - DOS CD German version with digital music { { @@ -824,6 +1044,37 @@ static const SAGAGameDescription gameDescriptions[] = { NULL, }, + // Inherit the earth - DOS CD German version with digital music (compressed sound) + { + { + "ite", + "CD Version", + { + {"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1}, + {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1}, + {"sounds.cmp", GAME_SOUNDFILE, NULL, -1}, + {"voices.cmp", GAME_VOICEFILE, NULL, -1}, + {"music.cmp", GAME_MUSICFILE, NULL, -1}, + { NULL, 0, NULL, 0} + }, + Common::DE_DEU, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GType_ITE, + GID_ITE_CD_DE2, + GF_CD_FX | GF_COMPRESSED_SOUNDS, + ITE_DEFAULT_SCENE, + &ITE_Resources, + ARRAYSIZE(ITECD_GameFonts), + ITECD_GameFonts, + &ITECD_GameSound, + &ITECD_GameSound, + &ITEMACCD_GameMusic, + 0, + NULL, + }, + // Inherit the earth - CD version { { @@ -854,6 +1105,36 @@ static const SAGAGameDescription gameDescriptions[] = { NULL, }, + // Inherit the earth - CD version (compressed sound) + { + { + "ite", + "CD Version", + { + {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1}, + {"scripts.rsc", GAME_SCRIPTFILE, "a891405405edefc69c9d6c420c868b84", -1}, + {"sounds.cmp", GAME_SOUNDFILE, NULL, -1}, + {"voices.cmp", GAME_VOICEFILE, NULL, -1}, + { NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GType_ITE, + GID_ITE_CD, + GF_CD_FX | GF_COMPRESSED_SOUNDS, + ITE_DEFAULT_SCENE, + &ITE_Resources, + ARRAYSIZE(ITECD_GameFonts), + ITECD_GameFonts, + &ITECD_GameSound, + &ITECD_GameSound, + NULL, + 0, + NULL, + }, + // Inherit the earth - German Floppy version { { @@ -883,6 +1164,35 @@ static const SAGAGameDescription gameDescriptions[] = { NULL, }, + // Inherit the earth - German Floppy version (compressed sound) + { + { + "ite", + "Floppy", + { + {"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1}, + {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1}, + {"voices.cmp", GAME_SOUNDFILE | GAME_VOICEFILE, NULL, -1}, + { NULL, 0, NULL, 0} + }, + Common::DE_DEU, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GType_ITE, + GID_ITE_DISK_DE, + GF_COMPRESSED_SOUNDS, + ITE_DEFAULT_SCENE, + &ITE_Resources, + ARRAYSIZE(ITEDISK_GameFonts), + ITEDISK_GameFonts, + &ITEDISK_GameSound, + &ITEDISK_GameSound, + NULL, + 0, + NULL, + }, + // Inherit the earth - German Floppy version with digital music { { @@ -913,6 +1223,36 @@ static const SAGAGameDescription gameDescriptions[] = { NULL, }, + // Inherit the earth - German Floppy version with digital music (compressed sound) + { + { + "ite", + "Floppy", + { + {"ite.rsc", GAME_RESOURCEFILE, "869fc23c8f38f575979ec67152914fee", -1}, + {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1}, + {"voices.cmp", GAME_SOUNDFILE | GAME_VOICEFILE, NULL, -1}, + {"music.cmp", GAME_MUSICFILE, NULL, -1}, + { NULL, 0, NULL, 0} + }, + Common::DE_DEU, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GType_ITE, + GID_ITE_DISK_DE2, + GF_COMPRESSED_SOUNDS, + ITE_DEFAULT_SCENE, + &ITE_Resources, + ARRAYSIZE(ITEDISK_GameFonts), + ITEDISK_GameFonts, + &ITEDISK_GameSound, + &ITEDISK_GameSound, + &ITEMACCD_GameMusic, + 0, + NULL, + }, + // Inherit the earth - Disk version { { @@ -942,6 +1282,35 @@ static const SAGAGameDescription gameDescriptions[] = { NULL, }, + // Inherit the earth - Disk version (compressed sound) + { + { + "ite", + "Floppy", + { + {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1}, + {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1}, + {"voices.cmp", GAME_SOUNDFILE | GAME_VOICEFILE, NULL, -1}, + { NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GType_ITE, + GID_ITE_DISK_G, + GF_COMPRESSED_SOUNDS, + ITE_DEFAULT_SCENE, + &ITE_Resources, + ARRAYSIZE(ITEDISK_GameFonts), + ITEDISK_GameFonts, + &ITEDISK_GameSound, + &ITEDISK_GameSound, + NULL, + 0, + NULL, + }, + // Inherit the earth - Disk version with digital music { { @@ -972,6 +1341,36 @@ static const SAGAGameDescription gameDescriptions[] = { NULL, }, + // Inherit the earth - Disk version with digital music (compressed sound) + { + { + "ite", + "Floppy", + { + {"ite.rsc", GAME_RESOURCEFILE, "8f4315a9bb10ec839253108a032c8b54", -1}, + {"scripts.rsc", GAME_SCRIPTFILE, "516f7330f8410057b834424ea719d1ef", -1}, + {"voices.cmp", GAME_SOUNDFILE | GAME_VOICEFILE, NULL, -1}, + {"music.cmp", GAME_MUSICFILE, NULL, -1}, + { NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformPC, + Common::ADGF_NO_FLAGS + }, + GType_ITE, + GID_ITE_DISK_G2, + GF_COMPRESSED_SOUNDS, + ITE_DEFAULT_SCENE, + &ITE_Resources, + ARRAYSIZE(ITEDISK_GameFonts), + ITEDISK_GameFonts, + &ITEDISK_GameSound, + &ITEDISK_GameSound, + &ITEMACCD_GameMusic, + 0, + NULL, + }, + // I Have No Mouth And I Must Scream - Demo version { { diff --git a/engines/saga/events.cpp b/engines/saga/events.cpp index 191ea4ed61..b93c6017c7 100644 --- a/engines/saga/events.cpp +++ b/engines/saga/events.cpp @@ -341,6 +341,7 @@ int Events::handleOneShot(Event *event) { _vm->_gfx->setPalette(palPointer); } } + _vm->_actor->showActors(true); } break; case kAnimEvent: diff --git a/engines/saga/gfx.h b/engines/saga/gfx.h index 8658e6d992..0fa7aab742 100644 --- a/engines/saga/gfx.h +++ b/engines/saga/gfx.h @@ -85,7 +85,7 @@ struct PalEntry { byte red; byte green; byte blue; -}; +} PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/saga/interface.cpp b/engines/saga/interface.cpp index 03fc0beb7a..55b2b0a996 100644 --- a/engines/saga/interface.cpp +++ b/engines/saga/interface.cpp @@ -1478,6 +1478,7 @@ void Interface::setOption(PanelButton *panelButton) { case kTextLoad: if (_vm->getSaveFilesCount() > 0) { if (_vm->isSaveListFull() || (_optionSaveFileTitleNumber > 0)) { + debug(1, "Loading save game %d", _vm->getSaveFile(_optionSaveFileTitleNumber)->slotNumber); fileName = _vm->calcSaveFileName(_vm->getSaveFile(_optionSaveFileTitleNumber)->slotNumber); setMode(kPanelMain); _vm->load(fileName); diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index 27729247ef..71b6964530 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -354,7 +354,7 @@ bool Music::isPlaying() { void Music::play(uint32 resourceId, MusicFlags flags) { Audio::AudioStream *audioStream = NULL; MidiParser *parser; - ResourceContext *context; + ResourceContext *context = NULL; byte *resourceData; size_t resourceSize; uint32 loopStart; @@ -413,7 +413,61 @@ void Music::play(uint32 resourceId, MusicFlags flags) { loopStart = 4 * 18727; } - audioStream = new RAWInputStream(_vm, _musicContext, resourceId - 9, flags == MUSIC_LOOP, loopStart); + if (!(_vm->getFeatures() & GF_COMPRESSED_SOUNDS)) { + // uncompressed digital music + audioStream = new RAWInputStream(_vm, _musicContext, resourceId - 9, flags == MUSIC_LOOP, loopStart); + } else { + // compressed digital music + ResourceData * musicResourceData; + Common::File *_file; + byte compressedHeader[10]; + GameSoundTypes soundType; + + musicResourceData = _vm->_resource->getResourceData(_musicContext, resourceId - 9); + _file = _musicContext->getFile(musicResourceData); + + if (_vm->getMusicInfo() == NULL) { + error("RAWInputStream() wrong musicInfo"); + } + + _file->seek((long)musicResourceData->offset, SEEK_SET); + + _file->read(compressedHeader, 9); + + if (compressedHeader[0] == char(0)) { + soundType = kSoundMP3; + } else if (compressedHeader[0] == char(1)) { + soundType = kSoundOGG; + } else if (compressedHeader[0] == char(2)) { + soundType = kSoundFLAC; + } + + switch (soundType) { +#ifdef USE_MAD + case kSoundMP3: + debug(1, "Playing MP3 compressed digital music"); + audioStream = Audio::makeMP3Stream(_file, musicResourceData->size); + break; +#endif +#ifdef USE_VORBIS + case kSoundOGG: + debug(1, "Playing OGG compressed digital music"); + audioStream = Audio::makeVorbisStream(_file, musicResourceData->size); + break; +#endif +#ifdef USE_FLAC + case kSoundFLAC: + debug(1, "Playing FLAC compressed digital music"); + audioStream = Audio::makeFlacStream(_file, musicResourceData->size); + break; +#endif + default: + // Unknown compression + error("Trying to play a compressed digital music, but the compression is not known"); + break; + } + + } } } } diff --git a/engines/saga/music.h b/engines/saga/music.h index 125c85aa9b..96d8608bcd 100644 --- a/engines/saga/music.h +++ b/engines/saga/music.h @@ -31,6 +31,9 @@ #include "sound/audiocd.h" #include "sound/mididrv.h" #include "sound/midiparser.h" +#include "sound/mp3.h" +#include "sound/vorbis.h" +#include "sound/flac.h" namespace Saga { diff --git a/engines/saga/render.cpp b/engines/saga/render.cpp index 4e5d98bbf9..16536f762e 100644 --- a/engines/saga/render.cpp +++ b/engines/saga/render.cpp @@ -77,7 +77,7 @@ void Render::drawScene() { assert(_initialized); - _frameCount++; + _renderedFrameCount++; backBufferSurface = _vm->_gfx->getBackBuffer(); @@ -183,8 +183,8 @@ void Render::fpsTimerCallback(void *refCon) { } void Render::fpsTimer(void) { - _fps = _frameCount; - _frameCount = 0; + _fps = _renderedFrameCount; + _renderedFrameCount = 0; } } // End of namespace Saga diff --git a/engines/saga/render.h b/engines/saga/render.h index c97de8efc9..4c6e3ee5b1 100644 --- a/engines/saga/render.h +++ b/engines/saga/render.h @@ -85,7 +85,7 @@ private: Surface _backGroundSurface; unsigned int _fps; - unsigned int _frameCount; + unsigned int _renderedFrameCount; uint32 _flags; }; diff --git a/engines/saga/saga.h b/engines/saga/saga.h index 9532d2fd56..844a738418 100644 --- a/engines/saga/saga.h +++ b/engines/saga/saga.h @@ -152,7 +152,8 @@ enum GameFeatures { GF_BIG_ENDIAN_DATA = 1 << 0, GF_WYRMKEEP = 1 << 1, GF_CD_FX = 1 << 2, - GF_SCENE_SUBSTITUTES = 1 << 3 + GF_SCENE_SUBSTITUTES = 1 << 3, + GF_COMPRESSED_SOUNDS = 1 << 4 }; enum VerbTypeIds { @@ -224,7 +225,10 @@ enum GameSoundTypes { kSoundVOX = 1, kSoundVOC = 2, kSoundWAV = 3, - kSoundMacPCM = 4 + kSoundMacPCM = 4, + kSoundMP3 = 5, + kSoundOGG = 6, + kSoundFLAC = 7 }; enum TextStringIds { @@ -335,6 +339,7 @@ enum GameObjectTypes { enum ScriptTimings { kScriptTimeTicksPerSecond = (728L/10L), + kScriptTimeTicksPerSecondIHNM = 72, kRepeatSpeedTicks = (728L/10L)/3, kNormalFadeDuration = 320, // 64 steps, 5 msec each kQuickFadeDuration = 64, // 64 steps, 1 msec each @@ -455,10 +460,6 @@ struct SaveGameHeader { char name[SAVE_TITLE_SIZE]; }; -inline int ticksToMSec(int tick) { - return tick * 1000 / kScriptTimeTicksPerSecond; -} - inline int clamp(int minValue, int value, int maxValue) { if (value <= minValue) { return minValue; @@ -591,6 +592,13 @@ public: return _leftMouseButtonPressed || _rightMouseButtonPressed; } + inline int ticksToMSec(int tick) { + if (getGameType() == GType_ITE) + return tick * 1000 / kScriptTimeTicksPerSecond; + else + return tick * 1000 / kScriptTimeTicksPerSecondIHNM; + } + private: uint _saveFilesMaxCount; uint _saveFilesCount; diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp index 84d1b45114..362b212b14 100644 --- a/engines/saga/scene.cpp +++ b/engines/saga/scene.cpp @@ -570,6 +570,8 @@ void Scene::loadScene(LoadSceneParams *loadSceneParams) { _chapterPointsChanged = false; + _vm->_actor->showActors(false); + if ((_vm->getGameType() == GType_IHNM) && (loadSceneParams->chapter != NO_CHAPTER_CHANGE)) { if (loadSceneParams->loadFlag != kLoadBySceneNumber) { error("loadScene wrong usage"); diff --git a/engines/saga/script.h b/engines/saga/script.h index ec3a7e1cf4..5adfb6181a 100644 --- a/engines/saga/script.h +++ b/engines/saga/script.h @@ -598,7 +598,7 @@ private: void sfClearGlobalFlag(SCRIPTFUNC_PARAMS); void sfTestGlobalFlag(SCRIPTFUNC_PARAMS); void sfSetPoints(SCRIPTFUNC_PARAMS); - void sf103(SCRIPTFUNC_PARAMS); + void sfQueueMusic(SCRIPTFUNC_PARAMS); void sfDisableAbortSpeeches(SCRIPTFUNC_PARAMS); void SF_stub(const char *name, ScriptThread *thread, int nArgs); diff --git a/engines/saga/sfuncs.cpp b/engines/saga/sfuncs.cpp index e713326661..4954188a6e 100644 --- a/engines/saga/sfuncs.cpp +++ b/engines/saga/sfuncs.cpp @@ -240,7 +240,7 @@ static const ScriptFunctionDescription IHNMscriptFunctionsList[IHNM_SCRIPT_FUNCT OPCODE(sfSetSpeechBox), OPCODE(sfDebugShowData), OPCODE(sfWaitFramesEsc), - OPCODE(sf103), + OPCODE(sfQueueMusic), OPCODE(sfDisableAbortSpeeches) }; if (_vm->getGameType() == GType_IHNM) @@ -266,7 +266,7 @@ void Script::sfWait(SCRIPTFUNC_PARAMS) { time = thread->pop(); if (!_skipSpeeches) { - thread->waitDelay(ticksToMSec(time)); // put thread to sleep + thread->waitDelay(_vm->ticksToMSec(time)); // put thread to sleep } } @@ -437,7 +437,7 @@ void Script::sfStartBgdAnim(SCRIPTFUNC_PARAMS) { int16 cycles = thread->pop(); _vm->_anim->setCycles(animId, cycles); - _vm->_anim->setFrameTime(animId, ticksToMSec(kRepeatSpeedTicks)); + _vm->_anim->setFrameTime(animId, _vm->ticksToMSec(kRepeatSpeedTicks)); _vm->_anim->play(animId, 0); debug(1, "sfStartBgdAnim(%d, %d)", animId, cycles); @@ -548,23 +548,30 @@ void Script::sfScriptGotoScene(SCRIPTFUNC_PARAMS) { sceneNumber = thread->pop(); entrance = thread->pop(); - if (_vm->getGameType() == GType_IHNM) + if (_vm->getGameType() == GType_IHNM) { transition = thread->pop(); - if (sceneNumber < 0) { - if (_vm->getGameType() == GType_ITE) { - _vm->shutDown(); - return; - } + _vm->_gfx->setCursor(kCursorBusy); } - if (_vm->getGameType() == GType_IHNM) { - warning("FIXME: implement sfScriptGotoScene differences for IHNM"); + if ((_vm->getGameType() == GType_ITE && sceneNumber < 0) || + (_vm->getGameType() == GType_IHNM && sceneNumber == 0)) { + // TODO: set creditsFlag to true for IHNM + _vm->shutDown(); + return; + } + if (_vm->getGameType() == GType_IHNM) { // Since it doesn't look like the IHNM scripts remove the // cutaway after the intro, this is probably the best place to // to it. - _vm->_anim->clearCutaway(); + Event event; + event.type = kEvTImmediate; + event.code = kCutawayEvent; + event.op = kEventClear; + event.time = 0; + event.duration = 0; + _vm->_events->queue(&event); } // It is possible to leave scene when converse panel is on, @@ -574,6 +581,7 @@ void Script::sfScriptGotoScene(SCRIPTFUNC_PARAMS) { _vm->_interface->setMode(kPanelMain); } + // changeScene calls loadScene which calls setVerb. setVerb resets all pending objects and object flags if (sceneNumber == -1 && _vm->getGameType() == GType_IHNM) { // TODO: This is used to return back to the character selection screen in IHNM. // However, it seems more than this is needed, AM's speech is wrong and no actors @@ -583,10 +591,19 @@ void Script::sfScriptGotoScene(SCRIPTFUNC_PARAMS) { _vm->_scene->changeScene(sceneNumber, entrance, (sceneNumber == ITE_SCENE_ENDCREDIT1) ? kTransitionFade : kTransitionNoFade); } - //TODO: placard stuff + if (_vm->_interface->getMode() == kPanelPlacard || + _vm->_interface->getMode() == kPanelCutaway || + _vm->_interface->getMode() == kPanelVideo) { + _vm->_gfx->showCursor(true); + _vm->_interface->setMode(kPanelMain); + } + _pendingVerb = _vm->_script->getVerbType(kVerbNone); _currentObject[0] = _currentObject[1] = ID_NOTHING; - showVerb(); + showVerb(); // calls setStatusText("") + + if (_vm->getGameType() == GType_IHNM) + _vm->_gfx->setCursor(kCursorNormal); } // Script function #17 (0x11) @@ -684,7 +701,7 @@ void Script::sfSetBgdAnimSpeed(SCRIPTFUNC_PARAMS) { int16 animId = thread->pop(); int16 speed = thread->pop(); - _vm->_anim->setFrameTime(animId, ticksToMSec(speed)); + _vm->_anim->setFrameTime(animId, _vm->ticksToMSec(speed)); debug(1, "sfSetBgdAnimSpeed(%d, %d)", animId, speed); } @@ -712,7 +729,7 @@ void Script::sfStartBgdAnimSpeed(SCRIPTFUNC_PARAMS) { int16 speed = thread->pop(); _vm->_anim->setCycles(animId, cycles); - _vm->_anim->setFrameTime(animId, ticksToMSec(speed)); + _vm->_anim->setFrameTime(animId, _vm->ticksToMSec(speed)); _vm->_anim->play(animId, 0); debug(1, "sfStartBgdAnimSpeed(%d, %d, %d)", animId, cycles, speed); @@ -1008,7 +1025,13 @@ void Script::sfCycleFrames(SCRIPTFUNC_PARAMS) { actor->_actorFlags |= kActorRandom; } if (flags & kCycleReverse) { - actor->_actorFlags |= kActorBackwards; + if (_vm->getGameType() == GType_IHNM && + _vm->_scene->currentChapterNumber() == 2 && _vm->_scene->currentSceneNumber() == 41) { + // Prevent Benny from walking backwards after talking to the child via the monitor. This occurs in the + // original as well, and is fixed by not setting the kActorBackwards flag at this point + } else { + actor->_actorFlags |= kActorBackwards; + } } actor->_cycleFrameSequence = cycleFrameSequence; @@ -1075,7 +1098,7 @@ void Script::sfChainBgdAnim(SCRIPTFUNC_PARAMS) { if (speed >= 0) { _vm->_anim->setCycles(animId, cycles); _vm->_anim->stop(animId); - _vm->_anim->setFrameTime(animId, ticksToMSec(speed)); + _vm->_anim->setFrameTime(animId, _vm->ticksToMSec(speed)); } _vm->_anim->link(animId1, animId); @@ -2108,8 +2131,41 @@ void Script::sfWaitFramesEsc(SCRIPTFUNC_PARAMS) { thread->_returnValue = _vm->_framesEsc; } -void Script::sf103(SCRIPTFUNC_PARAMS) { - SF_stub("sf103", thread, nArgs); +void Script::sfQueueMusic(SCRIPTFUNC_PARAMS) { + int16 param1 = thread->pop(); + int16 param2 = thread->pop(); + Event event; + + if (param1 < 0) { + _vm->_music->stop(); + return; + } + + if (param1 >= _vm->_music->_songTableLen) { + warning("sfQueueMusic: Wrong song number (%d > %d)", param1, _vm->_music->_songTableLen - 1); + } else { + _vm->_music->setVolume(-1, 1); + event.type = kEvTOneshot; + event.code = kMusicEvent; + event.param = _vm->_music->_songTable[param1]; + event.param2 = param2 ? MUSIC_LOOP : MUSIC_NORMAL; + event.op = kEventPlay; + event.time = _vm->ticksToMSec(500); // I find the delay in the original to be too long, so I've set it to + // wait for half the time, which sounds better when chapter points + // change + // FIXME: If this is too short for other cases apart from chapter + // point change, set it back to 1000 + + _vm->_events->queue(&event); + + if (!_vm->_scene->haveChapterPointsChanged()) { + _vm->_scene->setCurrentMusicTrack(param1); + _vm->_scene->setCurrentMusicRepeat(param2); + } else { + // Don't save this music track when saving in IHNM + _vm->_scene->setChapterPointsChanged(false); + } + } } void Script::sfDisableAbortSpeeches(SCRIPTFUNC_PARAMS) { diff --git a/engines/saga/sndres.cpp b/engines/saga/sndres.cpp index c0442c75de..ceb1ebf630 100644 --- a/engines/saga/sndres.cpp +++ b/engines/saga/sndres.cpp @@ -156,7 +156,6 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff return false; } - _vm->_resource->loadResource(context, resourceId, soundResource, soundResourceLength); if ((context->fileType & GAME_VOICEFILE) != 0) { @@ -175,9 +174,20 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff if (soundResourceLength >= 8) { if (!memcmp(soundResource, "Creative", 8)) { resourceType = kSoundVOC; - } else if (!memcmp(soundResource, "RIFF", 4) != 0) { + } else if (!memcmp(soundResource, "RIFF", 4) != 0) { resourceType = kSoundWAV; + } + + if (_vm->getFeatures() & GF_COMPRESSED_SOUNDS) { + if (soundResource[0] == char(0)) { + resourceType = kSoundMP3; + } else if (soundResource[0] == char(1)) { + resourceType = kSoundOGG; + } else if (soundResource[0] == char(2)) { + resourceType = kSoundFLAC; + } } + } @@ -266,6 +276,29 @@ bool SndRes::load(ResourceContext *context, uint32 resourceId, SoundBuffer &buff } free(soundResource); break; + case kSoundMP3: + case kSoundOGG: + case kSoundFLAC: + ResourceData *resourceData; + resourceData = _vm->_resource->getResourceData(context, resourceId); + + // Read compressed sfx header + readS.seek(1); // Skip compression identifier byte + buffer.frequency = readS.readUint16LE(); + buffer.originalSize = readS.readUint32LE(); + buffer.sampleBits = readS.readByte(); + buffer.stereo = (readS.readByte() == char(0)) ? false : true; + + buffer.size = soundResourceLength; + buffer.soundType = resourceType; + buffer.soundFile = context->getFile(resourceData); + buffer.fileOffset = resourceData->offset + 9; // skip compressed sfx header: byte + uint16 + uint32 + byte + byte + + buffer.buffer = NULL; + + result = true; + free(soundResource); + break; default: error("SndRes::load Unknown sound type"); } @@ -286,7 +319,10 @@ int SndRes::getVoiceLength(uint32 resourceId) { return -1; } - msDouble = (double)buffer.size; + if (!(_vm->getFeatures() & GF_COMPRESSED_SOUNDS)) + msDouble = (double)buffer.size; + else + msDouble = (double)buffer.originalSize; if (buffer.sampleBits == 16) { msDouble /= 2.0; } diff --git a/engines/saga/sound.cpp b/engines/saga/sound.cpp index a4ce79b9c4..6c2516c8a3 100644 --- a/engines/saga/sound.cpp +++ b/engines/saga/sound.cpp @@ -80,7 +80,40 @@ void Sound::playSoundBuffer(Audio::SoundHandle *handle, SoundBuffer &buffer, int if (!buffer.isSigned) flags |= Audio::Mixer::FLAG_UNSIGNED; - _mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer.buffer, buffer.size, buffer.frequency, flags, -1, volume); + if (!(_vm->getFeatures() & GF_COMPRESSED_SOUNDS)) { + _mixer->playRaw(Audio::Mixer::kSFXSoundType, handle, buffer.buffer, buffer.size, buffer.frequency, flags, -1, volume); + } else { + buffer.soundFile->seek((long)buffer.fileOffset, SEEK_SET); + Audio::AudioStream *stream = NULL; + + switch (buffer.soundType) { +#ifdef USE_MAD + case kSoundMP3: + debug(1, "Playing MP3 compressed sound"); + stream = Audio::makeMP3Stream(buffer.soundFile, buffer.size); + break; +#endif +#ifdef USE_VORBIS + case kSoundOGG: + debug(1, "Playing OGG compressed sound"); + stream = Audio::makeVorbisStream(buffer.soundFile, buffer.size); + break; +#endif +#ifdef USE_FLAC + case kSoundFLAC: + debug(1, "Playing FLAC compressed sound"); + stream = Audio::makeFlacStream(buffer.soundFile, buffer.size); + break; +#endif + default: + // Unknown compression + error("Trying to play a compressed sound, but the compression is not known"); + break; + } + + if (stream != NULL) + _mixer->playInputStream(Audio::Mixer::kSFXSoundType, handle, stream, -1, volume, 0, true, false); + } } void Sound::playSound(SoundBuffer &buffer, int volume, bool loop) { diff --git a/engines/saga/sound.h b/engines/saga/sound.h index 3abea583ba..961f8eba56 100644 --- a/engines/saga/sound.h +++ b/engines/saga/sound.h @@ -28,7 +28,11 @@ #ifndef SAGA_SOUND_H #define SAGA_SOUND_H +#include "common/file.h" #include "sound/mixer.h" +#include "sound/mp3.h" +#include "sound/vorbis.h" +#include "sound/flac.h" namespace Saga { @@ -46,7 +50,11 @@ struct SoundBuffer { byte *buffer; size_t size; + size_t originalSize; bool isBigEndian; + GameSoundTypes soundType; + Common::File *soundFile; + size_t fileOffset; }; enum sndHandleType { diff --git a/engines/scumm/akos.cpp b/engines/scumm/akos.cpp index 2a51464341..c8667d7ab2 100644 --- a/engines/scumm/akos.cpp +++ b/engines/scumm/akos.cpp @@ -47,12 +47,12 @@ struct AkosHeader { uint16 num_anims; uint16 unk_3; uint16 codec; -}; +} PACKED_STRUCT; struct AkosOffset { uint32 akcd; // offset into the akcd data uint16 akci; // offset into the akci data -}; +} PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/scumm/base-costume.h b/engines/scumm/base-costume.h index e6ef618a3e..155bbff97f 100644 --- a/engines/scumm/base-costume.h +++ b/engines/scumm/base-costume.h @@ -37,7 +37,7 @@ struct CostumeInfo { uint16 width, height; int16 rel_x, rel_y; int16 move_x, move_y; -}; +} PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/scumm/boxes.cpp b/engines/scumm/boxes.cpp index 424e5d891e..e79cea4359 100644 --- a/engines/scumm/boxes.cpp +++ b/engines/scumm/boxes.cpp @@ -80,7 +80,7 @@ struct Box { /* Internal walkbox file format */ uint32 unk3; } v8; }; -}; +} PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 8624f80fe7..e9430337ff 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -765,19 +765,22 @@ PluginError Engine_SCUMM_create(OSystem *syst, Engine **engine) { // narrow down the list a bit more. if (results.size() > 1 && ConfMan.hasKey("platform")) { Common::Platform platform = Common::parsePlatform(ConfMan.get("platform")); + Common::List<DetectorResult> tmp; + + // Copy only those candidates which match the platform setting for (Common::List<DetectorResult>::iterator x = results.begin(); x != results.end(); ) { - if (x->game.platform != platform) { - x = results.erase(x); - } else { - ++x; + if (x->game.platform == platform) { + tmp.push_back(*x); } } - } - // If we narrowed it down too much, abort - if (results.empty()) { - warning("Engine_SCUMM_create: Game data inconsistent with platform override"); - return kNoGameDataFoundError; + // If we narrowed it down too much, print a warning, else use the list + // we just computed as new candidates list. + if (tmp.empty()) { + warning("Engine_SCUMM_create: Game data inconsistent with platform override"); + } else { + results = tmp; + } } // Still no unique match found -> print a warning diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp index 85a7a4b675..16fe72531b 100644 --- a/engines/scumm/dialogs.cpp +++ b/engines/scumm/dialogs.cpp @@ -825,26 +825,26 @@ PauseDialog::PauseDialog(ScummEngine *scumm, int res) : InfoDialog(scumm, res) { } -void PauseDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { - if (ascii == ' ') // Close pause dialog if space key is pressed +void PauseDialog::handleKeyDown(Common::KeyState state) { + if (state.ascii == ' ') // Close pause dialog if space key is pressed close(); else - ScummDialog::handleKeyDown(ascii, keycode, modifiers); + ScummDialog::handleKeyDown(state); } ConfirmDialog::ConfirmDialog(ScummEngine *scumm, int res) : InfoDialog(scumm, res) { } -void ConfirmDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { - if (tolower(ascii) == 'n') { +void ConfirmDialog::handleKeyDown(Common::KeyState state) { + if (state.keycode == Common::KEYCODE_n) { setResult(0); close(); - } else if (tolower(ascii) == 'y') { + } else if (state.keycode == Common::KEYCODE_y) { setResult(1); close(); } else - ScummDialog::handleKeyDown(ascii, keycode, modifiers); + ScummDialog::handleKeyDown(state); } #pragma mark - @@ -892,11 +892,11 @@ void ValueDisplayDialog::reflowLayout() { _h = height; } -void ValueDisplayDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { - if (ascii == _incKey || ascii == _decKey) { - if (ascii == _incKey && _value < _max) +void ValueDisplayDialog::handleKeyDown(Common::KeyState state) { + if (state.ascii == _incKey || state.ascii == _decKey) { + if (state.ascii == _incKey && _value < _max) _value++; - else if (ascii == _decKey && _value > _min) + else if (state.ascii == _decKey && _value > _min) _value--; setResult(_value); @@ -924,8 +924,8 @@ void SubtitleSettingsDialog::handleTickle() { close(); } -void SubtitleSettingsDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { - if (keycode == 't' && modifiers == Common::KBD_CTRL) { +void SubtitleSettingsDialog::handleKeyDown(Common::KeyState state) { + if (state.keycode == 't' && state.flags == Common::KBD_CTRL) { cycleValue(); reflowLayout(); @@ -959,11 +959,11 @@ Indy3IQPointsDialog::Indy3IQPointsDialog(ScummEngine *scumm, char* text) : InfoDialog(scumm, text) { } -void Indy3IQPointsDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { - if (ascii == 'i') +void Indy3IQPointsDialog::handleKeyDown(Common::KeyState state) { + if (state.ascii == 'i') close(); else - ScummDialog::handleKeyDown(ascii, keycode, modifiers); + ScummDialog::handleKeyDown(state); } } // End of namespace Scumm diff --git a/engines/scumm/dialogs.h b/engines/scumm/dialogs.h index b69e989f8a..23c63d8992 100644 --- a/engines/scumm/dialogs.h +++ b/engines/scumm/dialogs.h @@ -169,8 +169,8 @@ public: setResult(0); close(); } - virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers) { - setResult(ascii); + virtual void handleKeyDown(Common::KeyState state) { + setResult(state.ascii); close(); } @@ -189,7 +189,7 @@ protected: class PauseDialog : public InfoDialog { public: PauseDialog(ScummEngine *scumm, int res); - virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers); + virtual void handleKeyDown(Common::KeyState state); }; /** @@ -199,7 +199,7 @@ public: class ConfirmDialog : public InfoDialog { public: ConfirmDialog(ScummEngine *scumm, int res); - virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers); + virtual void handleKeyDown(Common::KeyState state); }; /** @@ -216,7 +216,7 @@ public: virtual void handleMouseDown(int x, int y, int button, int clickCount) { close(); } - virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers); + virtual void handleKeyDown(Common::KeyState state); virtual void reflowLayout(); @@ -247,7 +247,7 @@ public: virtual void handleMouseDown(int x, int y, int button, int clickCount) { close(); } - virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers); + virtual void handleKeyDown(Common::KeyState state); protected: int _value; uint32 _timer; @@ -259,7 +259,7 @@ protected: class Indy3IQPointsDialog : public InfoDialog { public: Indy3IQPointsDialog(ScummEngine *scumm, char* text); - virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers); + virtual void handleKeyDown(Common::KeyState state); }; } // End of namespace Scumm diff --git a/engines/scumm/file.cpp b/engines/scumm/file.cpp index 3ab3e1a2e0..2c7f9ead5b 100644 --- a/engines/scumm/file.cpp +++ b/engines/scumm/file.cpp @@ -1257,10 +1257,11 @@ struct _lfl_index { uint16 script_addr[200]; byte sound_lfl[100]; uint16 sound_addr[100]; -} lfl_index; +} PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING +_lfl_index lfl_index; bool ScummNESFile::generateResource(int res) { const LFL *lfl = &lfls[res - 1]; diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h index 54eb470c26..84ad8adb3b 100644 --- a/engines/scumm/he/intern_he.h +++ b/engines/scumm/he/intern_he.h @@ -250,7 +250,7 @@ protected: int32 dim2start; //0C int32 dim2end; //10 byte data[1]; //14 - }; + } PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/scumm/he/resource_he.h b/engines/scumm/he/resource_he.h index 757cf13b7c..d7f4d99754 100644 --- a/engines/scumm/he/resource_he.h +++ b/engines/scumm/he/resource_he.h @@ -172,7 +172,7 @@ class Win32ResExtractor : public ResExtractor { byte *memory; byte *first_resource; int total_size; - }; + } PACKED_STRUCT; struct WinResource { char id[256]; @@ -183,7 +183,7 @@ class Win32ResExtractor : public ResExtractor { bool is_directory; char *get_resource_id_quoted(); - }; + } PACKED_STRUCT; struct Win32IconResDir { @@ -191,12 +191,12 @@ class Win32ResExtractor : public ResExtractor { byte height; byte color_count; byte reserved; - }; + } PACKED_STRUCT; struct Win32CursorDir { uint16 width; uint16 height; - }; + } PACKED_STRUCT; struct Win32CursorIconDirEntry { union { @@ -207,14 +207,14 @@ class Win32ResExtractor : public ResExtractor { uint16 bit_count; uint32 bytes_in_res; uint16 res_id; - }; + } PACKED_STRUCT; struct Win32CursorIconDir { uint16 reserved; uint16 type; uint16 count; Win32CursorIconDirEntry entries[1]; - }; + } PACKED_STRUCT; struct Win32CursorIconFileDirEntry { byte width; @@ -225,14 +225,14 @@ class Win32ResExtractor : public ResExtractor { uint16 hotspot_y; uint32 dib_size; uint32 dib_offset; - }; + } PACKED_STRUCT; struct Win32CursorIconFileDir { uint16 reserved; uint16 type; uint16 count; Win32CursorIconFileDirEntry entries[1]; - }; + } PACKED_STRUCT; struct Win32BitmapInfoHeader { uint32 size; @@ -246,25 +246,25 @@ class Win32ResExtractor : public ResExtractor { int32 y_pels_per_meter; uint32 clr_used; uint32 clr_important; - }; + } PACKED_STRUCT; struct Win32RGBQuad { byte blue; byte green; byte red; byte reserved; - }; + } PACKED_STRUCT; struct Win32ImageResourceDirectoryEntry { uint32 name; uint32 offset_to_data; - }; + } PACKED_STRUCT; struct Win16NETypeInfo { uint16 type_id; uint16 count; uint32 resloader; // FARPROC16 - smaller? uint16? - }; + } PACKED_STRUCT; struct DOSImageHeader { uint16 magic; @@ -286,7 +286,7 @@ class Win32ResExtractor : public ResExtractor { uint16 oeminfo; uint16 res2[10]; uint32 lfanew; - }; + } PACKED_STRUCT; struct Win32ImageFileHeader { uint16 machine; @@ -296,12 +296,12 @@ class Win32ResExtractor : public ResExtractor { uint32 number_of_symbols; uint16 size_of_optional_header; uint16 characteristics; - }; + } PACKED_STRUCT; struct Win32ImageDataDirectory { uint32 virtual_address; uint32 size; - }; + } PACKED_STRUCT; struct Win32ImageOptionalHeader { uint16 magic; @@ -335,13 +335,13 @@ class Win32ResExtractor : public ResExtractor { uint32 loader_flags; uint32 number_of_rva_and_sizes; Win32ImageDataDirectory data_directory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; - }; + } PACKED_STRUCT; struct Win32ImageNTHeaders { uint32 signature; Win32ImageFileHeader file_header; Win32ImageOptionalHeader optional_header; - }; + } PACKED_STRUCT; struct Win32ImageSectionHeader { byte name[IMAGE_SIZEOF_SHORT_NAME]; @@ -357,14 +357,14 @@ class Win32ResExtractor : public ResExtractor { uint16 number_of_relocations; uint16 number_of_linenumbers; uint32 characteristics; - }; + } PACKED_STRUCT; struct Win32ImageResourceDataEntry { uint32 offset_to_data; uint32 size; uint32 code_page; uint32 resource_handle; - }; + } PACKED_STRUCT; struct Win32ImageResourceDirectory { uint32 characteristics; @@ -373,7 +373,7 @@ class Win32ResExtractor : public ResExtractor { uint16 minor_version; uint16 number_of_named_entries; uint16 number_of_id_entries; - }; + } PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/scumm/imuse/instrument.cpp b/engines/scumm/imuse/instrument.cpp index 23b325c20b..b6ed064bc9 100644 --- a/engines/scumm/imuse/instrument.cpp +++ b/engines/scumm/imuse/instrument.cpp @@ -149,7 +149,7 @@ private: #include "common/pack-start.h" // START STRUCT PACKING - struct { + struct AdlibInstrument { byte flags_1; byte oplvl_1; byte atdec_1; @@ -166,10 +166,12 @@ private: byte flags_b; struct { byte a,b,c,d,e,f,g,h; } extra_b; byte duration; - } _instrument; + } PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING + AdlibInstrument _instrument; + public: Instrument_Adlib(const byte *data); Instrument_Adlib(Serializer *s); @@ -241,7 +243,7 @@ private: byte tva_env_sustain_level; } partial[4]; byte checksum; - }; + } PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp index 2d7401fe57..ffcb7d03f2 100644 --- a/engines/scumm/input.cpp +++ b/engines/scumm/input.cpp @@ -75,83 +75,53 @@ void ScummEngine::parseEvents() { sprintf(_saveLoadName, "Quicksave %d", _saveLoadSlot); _saveLoadFlag = (event.kbd.flags == Common::KBD_ALT) ? 1 : 2; _saveTemporaryState = false; - } else if (event.kbd.flags == Common::KBD_CTRL) { - if (event.kbd.keycode == 'f') - _fastMode ^= 1; - else if (event.kbd.keycode == 'g') - _fastMode ^= 2; - else if (event.kbd.keycode == 'd') - _debugger->attach(); - else if (event.kbd.keycode == 's') - _res->resourceStats(); - else - _keyPressed = event.kbd; // Normal key press, pass on to the game. - } else if (event.kbd.flags & Common::KBD_ALT) { - // Handle KBD_ALT combos. We know that the result must be 273 for Alt-W - // because that's what MI2 looks for in its "instant win" cheat. - - // FIXME: Handle this specific property of MI2 inside processKeyboard ? - _keyPressed = event.kbd; - _keyPressed.ascii = event.kbd.keycode + 154; + } else if (event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 'f') { + _fastMode ^= 1; + } else if (event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 'g') { + _fastMode ^= 2; + } else if ((event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 'd') || + event.kbd.ascii == '~' || event.kbd.ascii == '#') { + _debugger->attach(); + } else if (event.kbd.flags == Common::KBD_CTRL && event.kbd.keycode == 's') { + _res->resourceStats(); } else { // Normal key press, pass on to the game. _keyPressed = event.kbd; } - if (event.kbd.keycode >= Common::KEYCODE_UP && event.kbd.keycode <= Common::KEYCODE_LEFT) { - if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD) { - _keyPressed = event.kbd; - _keyPressed.ascii = event.kbd.ascii - Common::KEYCODE_UP + 54; - } else if (_game.version < 7) { - // FIXME: Handle this specific property inside processKeyboard ? - - // Don't let game see arrow keys. This fixes bug with up arrow (273) - // corresponding to the "instant win" cheat in MI2 mentioned above. - // - // This is not applicable to V7+ games, which need to see the arrow keys, - // too, else certain things (derby scene, asterorid lander) won't work. - _keyPressed.reset(); - } - } - if (_game.heversion >= 80) { // Keyboard is controlled via variable - int _keyState = 0; + int keyState = 0; if (event.kbd.keycode == Common::KEYCODE_LEFT) // Left - _keyState = 1; + keyState = 1; if (event.kbd.keycode == Common::KEYCODE_RIGHT) // Right - _keyState |= 2; + keyState |= 2; if (event.kbd.keycode == Common::KEYCODE_UP) // Up - _keyState |= 4; + keyState |= 4; if (event.kbd.keycode == Common::KEYCODE_DOWN) // Down - _keyState |= 8; + keyState |= 8; if (event.kbd.flags == Common::KBD_SHIFT) - _keyState |= 16; + keyState |= 16; if (event.kbd.flags == Common::KBD_CTRL) - _keyState |= 32; + keyState |= 32; - VAR(VAR_KEY_STATE) = _keyState; + VAR(VAR_KEY_STATE) = keyState; } - // FIXME: There is a discrepancy between EVENT_KEYDOWN and EVENT_KEYUP here: - // For EVENT_KEYDOWN, we use _keyPressed.keycode, which has potentially been - // modified, while for EVENT_KEYUP we use the unfiltered event.kbd.keycode. - // This could lead problems (like a key becoming 'stuck'). - - // FIXME #2: We are mixing ascii and keycode values here. We probably should - // be using keycodes, but at least INSANE checks for "Shift-V" by looking for - // the 'V' key being pressed. It would be easy to solve that by also storing the - // the modifier flags. However, since getKeyState() is also called by scripts, - // we have to be very careful with semantic changes. - // Nevertheless, it's bad to rely on "ascii" holdoing keycode values for special - // keys (like the function keys), so this should be fixed. - + // FIXME: We are using ASCII values to index the _keyDownMap here, + // yet later one code which checks _keyDownMap will use KEYCODEs + // to do so. That is, we are mixing ascii and keycode values here, + // which is bad. We probably should be only using keycodes, but at + // least INSANE checks for "Shift-V" by looking for the 'V' key + // being pressed. It would be easy to solve that by also storing + // the modifier flags. However, since getKeyState() is also called + // by scripts, we have to be careful with semantic changes. if (_keyPressed.ascii >= 512) debugC(DEBUG_GENERAL, "_keyPressed > 512 (%d)", _keyPressed.ascii); else @@ -159,11 +129,9 @@ void ScummEngine::parseEvents() { break; case Common::EVENT_KEYUP: - // FIXME: for some reason Common::KBD_ALT is set sometimes - // possible to a bug in sdl-common.cpp - if (event.kbd.ascii >= 512) + if (event.kbd.ascii >= 512) { debugC(DEBUG_GENERAL, "keyPressed > 512 (%d)", event.kbd.ascii); - else { + } else { _keyDownMap[event.kbd.ascii] = false; // Due to some weird bug with capslock key pressed @@ -173,6 +141,8 @@ void ScummEngine::parseEvents() { // both upper and lower letters are unpressed on keyup event // // Fixes bug #1709430: "FT: CAPSLOCK + V enables cheating for all fights" + // + // Fingolfin remarks: This wouldn't be a problem if we used keycodes. _keyDownMap[toupper(event.kbd.ascii)] = false; } break; @@ -204,24 +174,21 @@ void ScummEngine::parseEvents() { _rightBtnPressed &= ~msDown; break; - // The following two cases enable dialog choices to be - // scrolled through in the SegaCD version of MI - // as nothing else uses the wheel don't bother - // checking the gameid. Values are taken from script-14. - + // The following two cases enable dialog choices to be scrolled + // through in the SegaCD version of MI. Values are taken from script-14. + // See bug report #1193185 for details. case Common::EVENT_WHEELDOWN: - _keyPressed = Common::KeyState(Common::KEYCODE_7, 55); // '7' + if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD) + _keyPressed = Common::KeyState(Common::KEYCODE_7, 55); // '7' break; case Common::EVENT_WHEELUP: - _keyPressed = Common::KeyState(Common::KEYCODE_6, 54); // '6' + if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD) + _keyPressed = Common::KeyState(Common::KEYCODE_6, 54); // '6' break; case Common::EVENT_QUIT: - if (ConfMan.getBool("confirm_exit")) - confirmExitDialog(); - else - _quit = true; + _quit = true; break; default: @@ -446,11 +413,6 @@ void ScummEngine_v2::processKeyboard(Common::KeyState lastKeyHit) { // Fall back to default behavior ScummEngine::processKeyboard(lastKeyHit); - // Store the input type. So far we can't distinguish - // between 1, 3 and 5. - // 1) Verb 2) Scene 3) Inv. 4) Key - // 5) Sentence Bar - if (VAR_KEYPRESS != 0xFF && _mouseAndKeyboardStat) { // Key Input if (315 <= _mouseAndKeyboardStat && _mouseAndKeyboardStat <= 323) { // Convert F-Keys for V1/V2 games (they start at 1) @@ -503,12 +465,6 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) { if (_game.id == GID_CMI) mainmenuKeyEnabled = true; -/* - FIXME: We also used to force-enable F5 in Sam&Max and HE >= 72 games -- why? - if ((_game.version <= 3) || (_game.id == GID_SAMNMAX) || (_game.id == GID_CMI) || (_game.heversion >= 72)) - mainmenuKeyEnabled = true; -*/ - if (mainmenuKeyEnabled && (lastKeyHit.keycode == Common::KEYCODE_F5 && lastKeyHit.flags == 0)) { if (VAR_SAVELOAD_SCRIPT != 0xFF && _currentRoom != 0) runScript(VAR(VAR_SAVELOAD_SCRIPT), 0, 0, 0); @@ -569,15 +525,35 @@ void ScummEngine::processKeyboard(Common::KeyState lastKeyHit) { if (VAR_CHARINC != 0xFF) VAR(VAR_CHARINC) = _defaultTalkDelay; - } else if (lastKeyHit.ascii == '~' || lastKeyHit.ascii == '#') { // Debug console - _debugger->attach(); - } else { - // FIXME: Possibly convert even more keycode/ascii pairs to their SCUMM counterparts? - if (lastKeyHit.keycode >= Common::KEYCODE_F1 && lastKeyHit.keycode <= Common::KEYCODE_F9) + + if (lastKeyHit.keycode >= Common::KEYCODE_F1 && + lastKeyHit.keycode <= Common::KEYCODE_F9) { _mouseAndKeyboardStat = lastKeyHit.keycode - Common::KEYCODE_F1 + 315; - else + + } else if (_game.id == GID_MONKEY2 && (lastKeyHit.flags & Common::KBD_ALT)) { + // Handle KBD_ALT combos in MI2. We know that the result must be 273 for Alt-W + // because that's what MI2 looks for in its "instant win" cheat. + _mouseAndKeyboardStat = lastKeyHit.keycode + 154; + + } else if (lastKeyHit.keycode >= Common::KEYCODE_UP && + lastKeyHit.keycode <= Common::KEYCODE_LEFT) { + if (_game.id == GID_MONKEY && _game.platform == Common::kPlatformSegaCD) { + // Map arrow keys to number keys in the SEGA version of MI to support + // scrolling to conversation choices. See bug report #1193185 for details. + _mouseAndKeyboardStat = lastKeyHit.keycode - Common::KEYCODE_UP + 54; + } else if (_game.version >= 7) { + // Don't let pre-V7 game see arrow keys. This fixes bug with up arrow (273) + // corresponding to the "instant win" cheat in MI2 mentioned above. + // + // This is not applicable to V7+ games, which need to see the arrow keys, + // too, else certain things (derby scene, asterorid lander) won't work. + _mouseAndKeyboardStat = lastKeyHit.ascii; + } + + } else { _mouseAndKeyboardStat = lastKeyHit.ascii; + } } } diff --git a/engines/scumm/intern.h b/engines/scumm/intern.h index 008c2995e5..6723081dfe 100644 --- a/engines/scumm/intern.h +++ b/engines/scumm/intern.h @@ -313,7 +313,7 @@ protected: virtual void readGlobalObjects(); virtual void loadCharset(int no); - virtual void runInputScript(int a, int cmd, int mode); + virtual void runInputScript(int clickArea, int val, int mode); virtual void runInventoryScript(int i); virtual int getVar(); @@ -554,7 +554,7 @@ protected: int16 type; int16 dim2; byte data[1]; - }; + } PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk index d7b858a312..d8ef669410 100644 --- a/engines/scumm/module.mk +++ b/engines/scumm/module.mk @@ -82,6 +82,12 @@ MODULE_OBJS += \ smush/saud_channel.o \ smush/smush_mixer.o \ smush/smush_font.o + +ifdef USE_ARM_SMUSH_ASM +MODULE_OBJS += \ + smush/codec47ARM.o +endif + endif ifndef DISABLE_HE diff --git a/engines/scumm/object.h b/engines/scumm/object.h index bf38d42289..f27e6a501e 100644 --- a/engines/scumm/object.h +++ b/engines/scumm/object.h @@ -91,7 +91,7 @@ struct RoomHeader { uint32 transparency; } v8; }; -}; +} PACKED_STRUCT; struct CodeHeader { union { @@ -123,7 +123,7 @@ struct CodeHeader { } v7; }; -}; +} PACKED_STRUCT; struct ImageHeader { /* file format */ union { @@ -172,7 +172,7 @@ struct ImageHeader { /* file format */ } hotspot[15]; } v8; }; -}; +} PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/scumm/player_v2.h b/engines/scumm/player_v2.h index 43771d295f..cd88d57602 100644 --- a/engines/scumm/player_v2.h +++ b/engines/scumm/player_v2.h @@ -61,7 +61,7 @@ struct channel_data { uint16 unknown[4]; // 38 - 44 uint16 music_timer; // 46 uint16 music_script_nr; // 48 -}; +} PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp index 9578b05c1f..9d0d0ad654 100644 --- a/engines/scumm/saveload.cpp +++ b/engines/scumm/saveload.cpp @@ -200,8 +200,6 @@ bool ScummEngine::loadState(int slot, bool compat) { _engineStartTime = _system->getMillis() / 1000; } - _dialogStartTime = _system->getMillis() / 1000; - // Due to a bug in scummvm up to and including 0.3.0, save games could be saved // in the V8/V9 format but were tagged with a V7 mark. Ouch. So we just pretend V7 == V8 here if (hdr.ver == VER(7)) @@ -213,7 +211,7 @@ bool ScummEngine::loadState(int slot, bool compat) { // state for temporary state saves - such as certain cutscenes in DOTT, // FOA, Sam and Max, etc. // - // Thusly, we should probably not stop music when restoring from one of + // Thus, we should probably not stop music when restoring from one of // these saves. This change stops the Mole Man theme from going quiet in // Sam & Max when Doug tells you about the Ball of Twine, as mentioned in // patch #886058. @@ -378,9 +376,6 @@ bool ScummEngine::loadState(int slot, bool compat) { _sound->pauseSounds(false); - _engineStartTime += _system->getMillis() / 1000 - _dialogStartTime; - _dialogStartTime = 0; - return true; } diff --git a/engines/scumm/script.cpp b/engines/scumm/script.cpp index 46e4e64347..cc56adf622 100644 --- a/engines/scumm/script.cpp +++ b/engines/scumm/script.cpp @@ -1156,39 +1156,39 @@ void ScummEngine::checkAndRunSentenceScript() { runScript(sentenceScript, 0, 0, localParamList); } -void ScummEngine_v2::runInputScript(int a, int cmd, int mode) { +void ScummEngine_v2::runInputScript(int clickArea, int val, int mode) { int args[24]; int verbScript; verbScript = 4; - VAR(VAR_CLICK_AREA) = a; - switch (a) { - case 1: // Verb clicked - VAR(VAR_CLICK_VERB) = cmd; + VAR(VAR_CLICK_AREA) = clickArea; + switch (clickArea) { + case kVerbClickArea: // Verb clicked + VAR(VAR_CLICK_VERB) = val; break; - case 3: // Inventory clicked - VAR(VAR_CLICK_OBJECT) = cmd; + case kInventoryClickArea: // Inventory clicked + VAR(VAR_CLICK_OBJECT) = val; break; } memset(args, 0, sizeof(args)); - args[0] = a; - args[1] = cmd; + args[0] = clickArea; + args[1] = val; args[2] = mode; if (verbScript) runScript(verbScript, 0, 0, args); } -void ScummEngine::runInputScript(int a, int cmd, int mode) { +void ScummEngine::runInputScript(int clickArea, int val, int mode) { int args[24]; int verbScript; verbScript = VAR(VAR_VERB_SCRIPT); memset(args, 0, sizeof(args)); - args[0] = a; - args[1] = cmd; + args[0] = clickArea; + args[1] = val; args[2] = mode; // All HE 72+ games but only some HE 71 games. if (_game.heversion >= 71) { @@ -1198,18 +1198,18 @@ void ScummEngine::runInputScript(int a, int cmd, int mode) { // Macintosh verison of indy3ega used different interface, so adjust values. if (_game.id == GID_INDY3 && _game.platform == Common::kPlatformMacintosh) { - if (a == 1 && (cmd >= 101 && cmd <= 108)) { - if (cmd == 107) { + if (clickArea == kVerbClickArea && (val >= 101 && val <= 108)) { + if (val == 107) { VAR(67) -= 2; inventoryScript(); return; - } else if (cmd == 108) { + } else if (val == 108) { VAR(67) += 2; inventoryScript(); return; } else { args[0] = 3; - args[1] = VAR(83 + (cmd - 101)); + args[1] = VAR(83 + (val - 101)); } } } diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h index 840940caa3..cd48ef4d02 100644 --- a/engines/scumm/scumm-md5.h +++ b/engines/scumm/scumm-md5.h @@ -1,5 +1,5 @@ /* - This file was generated by the md5table tool on Fri Jun 08 10:51:50 2007 + This file was generated by the md5table tool on Mon Jul 2 22:44:41 2007 DO NOT EDIT MANUALLY! */ @@ -254,6 +254,7 @@ static const MD5Table md5table[] = { { "6886e5d08cee329b1f2e743ae2e3ceed", "monkey2", "", "", 11135, Common::DE_DEU, Common::kPlatformPC }, { "695fe0b3963333b7e15b37514db3c745", "thinkerk", "", "Demo", 29789, Common::EN_USA, Common::kPlatformUnknown }, { "697c9b7c55a05d8199c48b48e379d2c8", "puttmoon", "", "", -1, Common::HB_ISR, Common::kPlatformPC }, + { "69d70269fafc4445adbb0d223e4f9a3f", "indy3", "EGA", "EGA", 5361, Common::EN_ANY, Common::kPlatformPC }, { "69ea626f1f87eecb78ea0d6c6b983a1d", "monkey2", "", "", -1, Common::IT_ITA, Common::kPlatformPC }, { "69ffe29185b8d71f09f6199f8b2a87cb", "lost", "HE 100", "", -1, Common::RU_RUS, Common::kPlatformWindows }, { "6a30a07f353a75cdc602db27d73e1b42", "puttputt", "HE 70", "", -1, Common::EN_ANY, Common::kPlatformWindows }, @@ -486,7 +487,7 @@ static const MD5Table md5table[] = { { "d8d07efcb88f396bee0b402b10c3b1c9", "maniac", "NES", "", -1, Common::EN_USA, Common::kPlatformNES }, { "d917f311a448e3cc7239c31bddb00dd2", "samnmax", "", "CD", 9080, Common::EN_ANY, Common::kPlatformUnknown }, { "d9d0dd93d16ab4dec55cabc2b86bbd17", "samnmax", "", "Demo", 6478, Common::EN_ANY, Common::kPlatformPC }, - { "da09e666fc8f5b78d7b0ac65d1a3b56e", "monkey2", "", "", -1, Common::EN_ANY, Common::kPlatformFMTowns }, + { "da09e666fc8f5b78d7b0ac65d1a3b56e", "monkey2", "", "", 11135, Common::EN_ANY, Common::kPlatformFMTowns }, { "da6269b18fcb08189c0aa9c95533cce2", "monkey", "CD", "CD", 8955, Common::IT_ITA, Common::kPlatformPC }, { "da669b20271b85182e9c17a2a37ea02e", "monkey2", "", "", -1, Common::DE_DEU, Common::kPlatformAmiga }, { "db21a6e338fe3b70c2723b6530865bf2", "PuttTime", "HE 85", "", -1, Common::FR_FRA, Common::kPlatformUnknown }, diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 4b3a365394..2140b15544 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -120,7 +120,7 @@ ScummEngine::ScummEngine(OSystem *syst, const DetectorResult &dr) _gdi = new Gdi(this); } _res = new ResourceManager(this); - + // Convert MD5 checksum back into a digest for (int i = 0; i < 16; ++i) { char tmpStr[3] = "00"; @@ -2236,31 +2236,39 @@ void ScummEngine::startManiac() { #pragma mark --- GUI --- #pragma mark - -int ScummEngine::runDialog(Dialog &dialog) { - _dialogStartTime = _system->getMillis() / 1000; - - // Pause sound & video - bool old_soundsPaused = _sound->_soundsPaused; - _sound->pauseSounds(true); +void ScummEngine::pauseEngineIntern(bool pause) { + if (pause) { + // Record start of the pause, so that we can later + // adjust _engineStartTime accordingly. + _pauseStartTime = _system->getMillis(); - bool visible = CursorMan.isVisible(); + // Pause sound & video + _oldSoundsPaused = _sound->_soundsPaused; + _sound->pauseSounds(true); + + } else { + // Update the screen to make it less likely that the player will see a + // brief cursor palette glitch when the GUI is disabled. + _system->updateScreen(); - // Open & run the dialog - int result = dialog.runModal(); + // Resume sound & video + _sound->pauseSounds(_oldSoundsPaused); - // Restore old cursor - updateCursor(); - CursorMan.showMouse(visible); + // Adjust engine start time + _engineStartTime += (_system->getMillis() - _pauseStartTime) / 1000; + _pauseStartTime = 0; + } +} - // Update the screen to make it less likely that the player will see a - // brief cursor palette glitch when the GUI is disabled. - _system->updateScreen(); +int ScummEngine::runDialog(Dialog &dialog) { + // Pause engine + pauseEngine(true); - // Resume sound & video - _sound->pauseSounds(old_soundsPaused); + // Open & run the dialog + int result = dialog.runModal(); - _engineStartTime += (_system->getMillis() / 1000) - _dialogStartTime; - _dialogStartTime = 0; + // Resume engine + pauseEngine(false); // Return the result return result; diff --git a/engines/scumm/scumm.h b/engines/scumm/scumm.h index 8c8124714d..4146846856 100644 --- a/engines/scumm/scumm.h +++ b/engines/scumm/scumm.h @@ -406,9 +406,6 @@ class ScummEngine : public Engine { friend class CharsetRenderer; friend class ResourceManager; - GUI::Debugger *getDebugger(); - void errorString(const char *buf_input, char *buf_output); - public: /* Put often used variables at the top. * That results in a shorter form of the opcode @@ -437,17 +434,20 @@ public: protected: VirtualMachineState vm; + + bool _oldSoundsPaused; public: // Constructor / Destructor ScummEngine(OSystem *syst, const DetectorResult &dr); virtual ~ScummEngine(); - /** Startup function, main loop. */ - int go(); - - // Init functions - int init(); + // Engine APIs + virtual int init(); + virtual int go(); + virtual void errorString(const char *buf_input, char *buf_output); + virtual GUI::Debugger *getDebugger(); + virtual void pauseEngineIntern(bool pause); protected: virtual void setupScumm(); @@ -638,7 +638,7 @@ protected: void saveInfos(Common::OutSaveFile* file); int32 _engineStartTime; - int32 _dialogStartTime; + int32 _pauseStartTime; protected: /* Script VM - should be in Script class */ @@ -863,7 +863,7 @@ protected: void verbMouseOver(int verb); int findVerbAtPos(int x, int y) const; virtual void drawVerb(int verb, int mode); - virtual void runInputScript(int a, int cmd, int mode); + virtual void runInputScript(int clickArea, int val, int mode); void restoreVerbBG(int verb); void drawVerbBitmap(int verb, int x, int y); int getVerbSlot(int id, int mode) const; diff --git a/engines/scumm/smush/codec47.cpp b/engines/scumm/smush/codec47.cpp index 34d61d1c8a..6904e96c11 100644 --- a/engines/scumm/smush/codec47.cpp +++ b/engines/scumm/smush/codec47.cpp @@ -342,6 +342,24 @@ void Codec47Decoder::makeTables47(int width) { } while (c < 32768); } +#ifdef USE_ARM_SMUSH_ASM + +extern "C" void ARM_Smush_decode2( byte *dst, + const byte *src, + int width, + int height, + const byte *param_ptr, + int16 *_table, + byte *_tableBig, + int32 offset1, + int32 offset2, + byte *_tableSmall); + +#define decode2(SRC,DST,WIDTH,HEIGHT,PARAM) \ + ARM_Smush_decode2(SRC,DST,WIDTH,HEIGHT,PARAM,_table,_tableBig, \ + _offset1,_offset2,_tableSmall) + +#else void Codec47Decoder::level3(byte *d_dst) { int32 tmp; byte code = *_d_src++; @@ -503,6 +521,7 @@ void Codec47Decoder::decode2(byte *dst, const byte *src, int width, int height, dst += next_line; } while (--bh); } +#endif Codec47Decoder::Codec47Decoder(int width, int height) { _width = width; diff --git a/engines/scumm/smush/codec47ARM.s b/engines/scumm/smush/codec47ARM.s new file mode 100644 index 0000000000..d96049a32c --- /dev/null +++ b/engines/scumm/smush/codec47ARM.s @@ -0,0 +1,372 @@ +@ 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:$ +@ +@ @author Robin Watts (robin@wss.co.uk) +@ +@ This file, provides an ARM optimised version of sections of codec47.cpp. +@ The algorithm is essentially the same as that within codec47.cpp +@ so to understand this file you should understand codec47.cpp first. + + .text + + .global ARM_Smush_decode2 + +ARM_Smush_decode2: + @ r0 = dst + @ r1 = src + @ r2 = width + @ r3 = height + @ r4 = param + @ <> = _table + @ <> = _tableBig + @ <> = _offset1 + @ <> = _offset2 + @ <> = _tableSmall + STMFD r13!,{r2,r4-r11,R14} + + LDR r4,[r13,#(9+1)*4] @ r4 = param + @ stall + @ stall + SUB r4,r4,#0xF8 + + @ r0 = dst + @ r1 = _d_src + @ r2 = _d_pitch + @ r3 = height + @ r4 = param + ADD r7,r2,#7 @ r14 = bw + MOV r7,r7,LSR #3 +y_loop: +x_loop: + @ LEVEL 1 + LDRB r6,[r1],#1 @ r6 = *_d_src++ + @ stall + @ stall + CMP r6,#0xF8 + BLT level1codeSMALL + CMP r6,#0xFC + BLT level1codeMID + BEQ level1codeFC + CMP r6,#0xFE + BGT level1codeFF + BEQ level1codeFE +level1codeFD: + LDRB r6,[r1],#1 @ r6 = tmp = *_d_src++ + LDR r8,[r13,#(9+1+2)*4] @ r8 = _tableBig + @ stall + ADD r12,r6,r6,LSL #1 @ r12= tmp*3 + ADD r6,r6,r12,LSL #5 @ r6 = tmp*97 + ADD r8,r8,r6,LSL #2 @ r8 = _tableBig + tmp*388 + LDRB r9,[r8,#384] @ r9 = l = tmp_ptr[384] + LDRB r6,[r1],#1 @ r6 = val = *_d_src++ + ADD r12,r8,#384 @ r12= &tmp_ptr[384] + @ I don't really believe the next 2 lines are necessary, but... + CMP r9,#0 + BEQ level1codeFD_over1 +level1codeFD_loop1: + LDRB r10,[r8],#1 + LDRB r11,[r8],#1 + SUBS r9,r9,#1 + ADD r10,r10,r0 + STRB r6,[r10,r11,LSL #8] @ *(_d_dst + (*tmp_ptr2++)) = val + BGT level1codeFD_loop1 +level1codeFD_over1: + LDRB r9,[r12,#1] @ r9 = l = tmp_ptr[385] + LDRB r6,[r1],#1 @ r6 = val = *_d_src++ + SUB r12,r12,#384-128 @ r12= &tmp_ptr[128] + @ I don't really believe the next 2 lines are necessary, but... + CMP r9,#0 + BEQ level1codeFD_over2 +level1codeFD_loop2: + LDRB r10,[r12],#1 + LDRB r11,[r12],#1 + SUBS r9,r9,#1 + ADD r10,r10,r0 + STRB r6,[r10,r11,LSL #8] @ *(_d_dst + (*tmp_ptr2++)) = val + BGT level1codeFD_loop2 +level1codeFD_over2: +level1_end: + + ADD r0,r0,#8 + SUBS r7,r7,#1 + BGT x_loop + + ADD r7,r2,#7 + MOV r7,r7,LSR #3 + ADD r0,r0,r2,LSL #3 + SUB r0,r0,r7,LSL #3 @ r0 = dst += next_line + SUBS r3,r3,#8 @ if (--bh > 0) + BGT y_loop @ loop back + + LDMFD r13!,{r2,r4-r11,PC} + +level1codeSMALL: + LDR r8,[r13,#(9+1+1)*4] @ r8 = _table + LDR r9,[r13,#(9+1+3)*4] @ r9 = _offset1 + MOV r6,r6,LSL #1 @ r6 = code<<1 + LDRSH r8,[r8,r6] @ tmp2 = _table[code] +level1codeFC: + @ EQ => FC + LDREQ r9,[r13,#(9+1+4)*4] @ r9 = _offset2 + MOVEQ r8,#0 + SUB r11,r2,#7 @ r11 = _d_pitch-7 + ADD r9,r9,r0 @ tmp2 = _d_dst+_offset + ADD r8,r8,r9 @ tmp2 = _d_dst+_table[code]+_offset + @ r8 = &_dst[tmp2] + MOV r12,#8 +level1codeSMALL_loop: + LDRB r5, [r8],#1 @ r5 = d_dst[tmp2] + LDRB r6, [r8],#1 @ r10 = d_dst[tmp2] + LDRB r9, [r8],#1 @ r10 = d_dst[tmp2] + LDRB r10,[r8],#1 @ r10 = d_dst[tmp2] + STRB r5, [r0],#1 @ d_dst[0] = r5 + STRB r6, [r0],#1 @ d_dst[1] = r6 + STRB r9, [r0],#1 @ d_dst[2] = r9 + STRB r10,[r0],#1 @ d_dst[3] = r10 + LDRB r5, [r8],#1 @ r5 = d_dst[tmp2] + LDRB r6, [r8],#1 @ r10 = d_dst[tmp2] + LDRB r9, [r8],#1 @ r10 = d_dst[tmp2] + LDRB r10,[r8],r11 @ r10 = d_dst[tmp2] + STRB r5, [r0],#1 @ d_dst[4] = r5 + STRB r6, [r0],#1 @ d_dst[5] = r6 + STRB r9, [r0],#1 @ d_dst[6] = r9 + STRB r10,[r0],r11 @ d_dst[7] = r10 d_dst += d_pitch + SUBS r12,r12,#1 + BGT level1codeSMALL_loop + SUB r0,r0,r2,LSL #3 @ revert d_dst + B level1_end + +level1codeMID: + @ LT => F8<=code<FC case + @ EQ => FE case + LDRB r6,[r4,r6] @ r6 = t = _paramPtr[code] +level1codeFE: + LDREQB r6,[r1],#1 @ r6 = t = *_d_src++ + MOV r12,#8 + SUB r11,r2,#7 @ r11 = _d_pitch-7 +level1codeMID_loop: + STRB r6,[r0],#1 + STRB r6,[r0],#1 + STRB r6,[r0],#1 + STRB r6,[r0],#1 + STRB r6,[r0],#1 + STRB r6,[r0],#1 + STRB r6,[r0],#1 + STRB r6,[r0],r11 + SUBS r12,r12,#1 + BGT level1codeMID_loop + SUB r0,r0,r2,LSL #3 @ revert d_dst + B level1_end + +level1codeFF: + BL level2 + ADD r0,r0,#4 + BL level2 + ADD r0,r0,r2,LSL #2 + SUB r0,r0,#4 + BL level2 + ADD r0,r0,#4 + BL level2 + SUB r0,r0,#4 + SUB r0,r0,r2,LSL #2 + B level1_end + +level2: + @ r0 = _d_dst + @ r1 = _d_src + @ r2 = _d_pitch + @ r3 = PRESERVE + @ r4 = param + @ r7 = PRESERVE + @ r14= return address + LDRB r6,[r1],#1 @ r6 = *_d_src++ + @ stall + @ stall + CMP r6,#0xF8 + BLT level2codeSMALL + CMP r6,#0xFC + BLT level2codeMID + BEQ level2codeFC + CMP r6,#0xFE + BGT level2codeFF + BEQ level2codeFE +level2codeFD: + LDRB r6,[r1],#1 @ r6 = tmp = *_d_src++ + LDR r8,[r13,#(9+1+5)*4] @ r8 = _tableSmall + @ stall + @ stall + ADD r8,r8,r6,LSL #7 @ r8 = _tableSmall + tmp*128 + LDRB r9,[r8,#96] @ r9 = l = tmp_ptr[96] + LDRB r6,[r1],#1 @ r6 = val = *_d_src++ + ADD r12,r8,#32 @ r12 = tmp_ptr + 32 + @ I don't really believe the next 2 lines are necessary, but... + CMP r9,#0 + BEQ level2codeFD_over1 +level2codeFD_loop1: + LDRB r10,[r8],#1 + LDRB r11,[r8],#1 + SUBS r9,r9,#1 + ADD r10,r10,r0 + STRB r6,[r10,r11,LSL #8] @ *(_d_dst + (*tmp_ptr2++)) = val + BGT level2codeFD_loop1 +level2codeFD_over1: + LDRB r9,[r12,#97-32] @ r9 = l = tmp_ptr[97] + LDRB r6,[r1],#1 @ r6 = val = *_d_src++ + @ I don't really believe the next 2 lines are necessary, but... + CMP r9,#0 + MOVEQ PC,R14 +level2codeFD_loop2: + LDRB r10,[r12],#1 + LDRB r11,[r12],#1 + SUBS r9,r9,#1 + ADD r10,r10,r0 + STRB r6,[r10,r11,LSL #8] @ *(_d_dst + (*tmp_ptr2++)) = val + BGT level2codeFD_loop2 + + MOV PC,R14 + +level2codeSMALL: + LDR r8,[r13,#(9+1+1)*4] @ r8 = _table + LDR r9,[r13,#(9+1+3)*4] @ r9 = _offset1 + MOV r6,r6,LSL #1 @ r6 = code<<1 + LDRSH r8,[r8,r6] @ tmp2 = _table[code] +level2codeFC: + @ EQ => FC + LDREQ r9,[r13,#(9+1+4)*4] @ r9 = _offset2 + MOVEQ r8,#0 + SUB r11,r2,#3 @ r11 = _d_pitch-3 + ADD r9,r9,r0 @ tmp2 = _d_dst + _table[code] + ADD r8,r8,r9 @ tmp2 = _d_dst+_table[code]+_offset1 + @ r8 = &_dst[tmp2] + MOV r12,#4 +level2codeSMALL_loop: + LDRB r5, [r8],#1 @ r5 = d_dst[tmp2] + LDRB r6, [r8],#1 @ r10 = d_dst[tmp2] + LDRB r9, [r8],#1 @ r10 = d_dst[tmp2] + LDRB r10,[r8],r11 @ r10 = d_dst[tmp2] + STRB r5, [r0],#1 @ d_dst[4] = r5 + STRB r6, [r0],#1 @ d_dst[5] = r6 + STRB r9, [r0],#1 @ d_dst[6] = r9 + STRB r10,[r0],r11 @ d_dst[7] = r10 d_dst += d_pitch + SUBS r12,r12,#1 + BGT level2codeSMALL_loop + SUB r0,r0,r2,LSL #2 @ revert d_dst + MOV PC,R14 + +level2codeMID: + @ LT => F8<=code<FC case + @ EQ => FE case + LDRB r6,[r4,r6] @ r6 = t = _paramPtr[code] +level2codeFE: + LDREQB r6,[r1],#1 @ r6 = t = *_d_src++ + MOV r12,#4 + SUB r11,r2,#3 @ r11 = _d_pitch-7 +level2codeMID_loop: + STRB r6,[r0],#1 + STRB r6,[r0],#1 + STRB r6,[r0],#1 + STRB r6,[r0],r11 + SUBS r12,r12,#1 + BGT level2codeMID_loop + SUB r0,r0,r2,LSL #2 @ revert d_dst + MOV PC,R14 + +level2codeFF: + MOV r5,r14 + BL level3 + ADD r0,r0,#2 + BL level3 + ADD r0,r0,r2,LSL #1 + SUB r0,r0,#2 + BL level3 + ADD r0,r0,#2 + BL level3 + SUB r0,r0,#2 + SUB r0,r0,r2,LSL #1 + MOV PC,R5 + +level3: + @ r0 = _d_dst + @ r1 = _d_src + @ r2 = _d_pitch + @ r3 = PRESERVE + @ r4 = param + @ r5 = preserve + @ r7 = PRESERVE + @ r14= return address + LDRB r6,[r1],#1 @ r6 = code = *_d_src++ + @ stall + @ stall + CMP r6,#0xF8 + BLT level3codeSMALL + CMP r6,#0xFC + BLT level3codeMID + BEQ level3codeFC + CMP r6,#0xFE + BGT level3codeFF +level3codeFE: + LDRB r6,[r1],#1 @ r6 = t = *_d_src++ +level3codeMID: + @ LT => F8<=code<FC case + @ EQ => FE case + LDRLTB r6,[r4,r6] @ r6 = t = _paramPtr[code] + @ stall + @ stall + STRB r6,[r0,#1] + STRB r6,[r0],r2 + STRB r6,[r0,#1] + STRB r6,[r0],-r2 + MOV PC,R14 + +level3codeFF: + LDRB r6,[r1],#1 + LDRB r9,[r1],#1 + LDRB r10,[r1],#1 + LDRB r11,[r1],#1 + STRB r9, [r0,#1] + STRB r6, [r0],r2 + STRB r11,[r0,#1] + STRB r10,[r0],-r2 + MOV PC,R14 + +level3codeSMALL: + LDR r8,[r13,#(9+1+1)*4] @ r8 = _table + LDR r9,[r13,#(9+1+3)*4] @ r9 = _offset1 + MOV r6,r6,LSL #1 @ r6 = code<<1 + LDRSH r8,[r8,r6] @ tmp2 = _table[code] +level3codeFC: + @ EQ => FC + LDREQ r9,[r13,#(9+1+4)*4] @ r9 = _offset2 + MOVEQ r8,#0 + ADD r9,r9,r0 @ tmp2 = _d_dst+offset + ADD r8,r8,r9 @ tmp2 = _d_dst+_table[code]+_offset + @ r8 = &_dst[tmp2] + LDRB r6, [r8,#1] @ r6 = d_dst[tmp2+1] + LDRB r9, [r8],r2 @ r9 = d_dst[tmp2+0] + LDRB r10,[r8,#1] @ r10= d_dst[tmp2+dst+1] + LDRB r11,[r8],-r2 @ r11= d_dst[tmp2+dst] + STRB r6, [r0,#1] @ d_dst[1 ] = r6 + STRB r9, [r0],r2 @ d_dst[0 ] = r9 + STRB r10,[r0,#1] @ d_dst[dst+1] = r10 + STRB r11,[r0],-r2 @ d_dst[dst ] = r11 + MOV PC,R14 diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp index edd8004d30..56ee454240 100644 --- a/engines/scumm/verbs.cpp +++ b/engines/scumm/verbs.cpp @@ -385,7 +385,7 @@ void ScummEngine_v2::checkV2Inventory(int x, int y) { runObject(_activeInventory, _activeVerb); } } else { - runInputScript(3, object, 0); + runInputScript(kInventoryClickArea, object, 0); } } } @@ -537,7 +537,7 @@ void ScummEngine::checkExecVerbs() { if (vs->verbid && vs->saveid == 0 && vs->curmode == 1) { if (_mouseAndKeyboardStat == vs->key) { // Trigger verb as if the user clicked it - runInputScript(1, vs->verbid, 1); + runInputScript(kVerbClickArea, vs->verbid, 1); return; } } @@ -580,14 +580,14 @@ void ScummEngine::checkExecVerbs() { // Check if person is available (see script 23 from ZAK_FM-TOWNS and script 4 from ZAK_PC). // Zak: Var[144 Bit 15], Annie: Var[145 Bit 0], Melissa: Var[145 Bit 1], Leslie: Var[145 Bit 2] if (!readVar(0x890E + fKey)) { - runInputScript(1, 36 + fKey, 0); + runInputScript(kVerbClickArea, 36 + fKey, 0); } } return; } // Generic keyboard input - runInputScript(4, _mouseAndKeyboardStat, 1); + runInputScript(kKeyClickArea, _mouseAndKeyboardStat, 1); } else if (_mouseAndKeyboardStat & MBS_MOUSE_MASK) { VirtScreen *zone = findVirtScreen(_mouse.y); byte code = _mouseAndKeyboardStat & MBS_LEFT_CLICK ? 1 : 2; @@ -600,7 +600,7 @@ void ScummEngine::checkExecVerbs() { if (_game.version <= 2 && zone->number == kVerbVirtScreen && _mouse.y <= zone->topline + 8) { // Click into V2 sentence line - runInputScript(5, 0, 0); + runInputScript(kSentenceClickArea, 0, 0); } else if (_game.version <= 2 && zone->number == kVerbVirtScreen && _mouse.y > zone->topline + inventoryArea) { // Click into V2 inventory ((ScummEngine_v2 *)this)->checkV2Inventory(_mouse.x, _mouse.y); @@ -608,10 +608,10 @@ void ScummEngine::checkExecVerbs() { over = findVerbAtPos(_mouse.x, _mouse.y); if (over != 0) { // Verb was clicked - runInputScript(1, _verbs[over].verbid, code); + runInputScript(kVerbClickArea, _verbs[over].verbid, code); } else { // Scene was clicked - runInputScript((zone->number == kMainVirtScreen) ? 2 : 1, 0, code); + runInputScript((zone->number == kMainVirtScreen) ? kSceneClickArea : kVerbClickArea, 0, code); } } } diff --git a/engines/scumm/verbs.h b/engines/scumm/verbs.h index 47fa98a9de..96a49a7ced 100644 --- a/engines/scumm/verbs.h +++ b/engines/scumm/verbs.h @@ -30,6 +30,18 @@ namespace Scumm { +/** + * The area in which some click (or key press) occured and which is passed + * to the input script. + */ +enum ClickArea { + kVerbClickArea = 1, + kSceneClickArea = 2, + kInventoryClickArea = 3, + kKeyClickArea = 4, + kSentenceClickArea = 5 +}; + enum { kTextVerbType = 0, kImageVerbType = 1 diff --git a/engines/sky/music/mt32music.cpp b/engines/sky/music/mt32music.cpp index 4f816c6856..2be19a0651 100644 --- a/engines/sky/music/mt32music.cpp +++ b/engines/sky/music/mt32music.cpp @@ -120,7 +120,7 @@ bool MT32Music::processPatchSysEx(uint8 *sysExData) { crc -= sysExBuf[cnt]; sysExBuf[14] = crc & 0x7F; // crc _midiDrv->sysEx(sysExBuf, 15); - g_system->delayMillis(5); + g_system->delayMillis(40); return true; } @@ -170,7 +170,7 @@ void MT32Music::startDriver(void) { sendBuf[len] = crc & 0x7F; len++; _midiDrv->sysEx(sendBuf, len); - g_system->delayMillis (5); + g_system->delayMillis(40); } while (processPatchSysEx(sysExData)) diff --git a/engines/sky/sound.cpp b/engines/sky/sound.cpp index cf769cb3e9..c0dc227718 100644 --- a/engines/sky/sound.cpp +++ b/engines/sky/sound.cpp @@ -46,13 +46,13 @@ struct RoomList { uint8 room; uint8 adlibVolume; uint8 rolandVolume; -}; +} PACKED_STRUCT; struct Sfx { uint8 soundNo; uint8 flags; RoomList roomList[10]; -}; +} PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/sky/struc.h b/engines/sky/struc.h index 25f0b3d772..cd7155f282 100644 --- a/engines/sky/struc.h +++ b/engines/sky/struc.h @@ -55,7 +55,7 @@ struct dataFileHeader { int16 s_offset_x; int16 s_offset_y; uint16 s_compressed_size; -}; +} PACKED_STRUCT; struct TurnTable { uint16 turnTableUp[5]; @@ -63,7 +63,7 @@ struct TurnTable { uint16 turnTableLeft[5]; uint16 turnTableRight[5]; uint16 turnTableTalk[5]; -}; +} PACKED_STRUCT; struct MegaSet { uint16 gridWidth; // 0 @@ -82,7 +82,7 @@ struct MegaSet { uint16 standRightId; // 11 uint16 standTalkId; // 12 uint16 turnTableId; // 13 -}; +} PACKED_STRUCT; struct Compact { uint16 logic; // 0: Entry in logic table to run (byte as <256entries in logic table @@ -165,7 +165,7 @@ struct Compact { MegaSet megaSet1; // MegaSet megaSet2; // MegaSet megaSet3; // -}; +} PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/sword1/control.cpp b/engines/sword1/control.cpp index 1ebfaedb2e..c5b968aabe 100644 --- a/engines/sword1/control.cpp +++ b/engines/sword1/control.cpp @@ -650,14 +650,7 @@ bool Control::getConfirm(const uint8 *title) { } bool Control::keyAccepted(uint16 ascii) { - // this routine needs changes for Czech keys... No idea how to do that, though. - // FIXME: It is not a good idea to put non-ASCII chars into a C source file, - // since there is no way to specify which encoding you are using. - // It is better to encode them as hex/octal. Although in this particular - // case, it seems questionable to do this at all, since we currently - // do not at all specify which encoding keyboard events use, so this - // check here is probably not portable anyway... - static const char allowedSpecials[] = "éèáàúùäöüÄÖÜß,.:-()?! \"\'"; + static const char allowedSpecials[] = ",.:-()?! \"\'"; if (((ascii >= 'A') && (ascii <= 'Z')) || ((ascii >= 'a') && (ascii <= 'z')) || ((ascii >= '0') && (ascii <= '9')) || diff --git a/engines/sword1/mouse.h b/engines/sword1/mouse.h index 92b26c3573..f2c800d63b 100644 --- a/engines/sword1/mouse.h +++ b/engines/sword1/mouse.h @@ -60,7 +60,7 @@ struct MousePtr { uint16 hotSpotX; uint16 hotSpotY; uint8 dummyData[0x30]; -}; +} PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/sword1/object.h b/engines/sword1/object.h index ba65002918..87cbce7b84 100644 --- a/engines/sword1/object.h +++ b/engines/sword1/object.h @@ -40,7 +40,7 @@ namespace Sword1 { struct OEventSlot { //receiving event list in the compact - int32 o_event; //array of these with O_TOTAL_EVENTS elements int32 o_event_script; -}; // size = 2*int32 = 8 bytes +} PACKED_STRUCT; // size = 2*int32 = 8 bytes #define TOTAL_script_levels 5 @@ -48,12 +48,12 @@ struct ScriptTree { //this is a logic tree, used by OBJECTs int32 o_script_level; //logic level int32 o_script_id[TOTAL_script_levels]; //script id's (are unique to each level) int32 o_script_pc[TOTAL_script_levels]; //pc of script for each (if script_manager) -}; // size = 11*int32 = 44 bytes +} PACKED_STRUCT; // size = 11*int32 = 44 bytes struct TalkOffset { int32 x; int32 y; -}; // size = 2*int32 = 8 bytes +} PACKED_STRUCT; // size = 2*int32 = 8 bytes struct WalkData { int32 frame; @@ -61,7 +61,7 @@ struct WalkData { int32 y; int32 step; int32 dir; -}; // size = 5*int32 = 20 bytes +} PACKED_STRUCT; // size = 5*int32 = 20 bytes struct Object { int32 o_type; // 0 broad description of type - object, floor, etc. @@ -119,7 +119,7 @@ struct Object { WalkData o_route[O_WALKANIM_SIZE]; // 340 size = 600*20 bytes = 12000 // mega size = 12340 bytes (+ 8 byte offset table + 20 byte header = 12368) -}; +} PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/sword1/router.h b/engines/sword1/router.h index 67be8d0593..60456cc5c8 100644 --- a/engines/sword1/router.h +++ b/engines/sword1/router.h @@ -44,7 +44,7 @@ struct BarData { int16 dx; // x2 - x1 int16 dy; // y2 - y1 int32 co; // co = (y1*dx) - (x1*dy) from an equation for a line y*dx = x*dy + co -}; +} PACKED_STRUCT; struct NodeData { int16 x; @@ -52,7 +52,7 @@ struct NodeData { int16 level; int16 prev; int16 dist; -}; +} PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/sword1/sound.cpp b/engines/sword1/sound.cpp index 4d8601a0d8..492672fad8 100644 --- a/engines/sword1/sound.cpp +++ b/engines/sword1/sound.cpp @@ -33,6 +33,7 @@ #include "sword1/logic.h" #include "sword1/sword1.h" +#include "sound/flac.h" #include "sound/mp3.h" #include "sound/vorbis.h" #include "sound/wave.h" @@ -197,10 +198,10 @@ bool Sound::startSpeech(uint16 roomNo, uint16 localNo) { if (data) _mixer->playRaw(Audio::Mixer::kSpeechSoundType, &_speechHandle, data, size, 11025, SPEECH_FLAGS, SOUND_SPEECH_ID, speechVol, speechPan); } -#ifdef USE_MAD - else if (_cowMode == CowMp3) { +#ifdef USE_FLAC + else if (_cowMode == CowFlac) { _cowFile.seek(index); - _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, Audio::makeMP3Stream(&_cowFile, sampleSize), SOUND_SPEECH_ID, speechVol, speechPan); + _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, Audio::makeFlacStream(&_cowFile, sampleSize), SOUND_SPEECH_ID, speechVol, speechPan); // with compressed audio, we can't calculate the wave volume. // so default to talking. for (int cnt = 0; cnt < 480; cnt++) @@ -212,6 +213,19 @@ bool Sound::startSpeech(uint16 roomNo, uint16 localNo) { else if (_cowMode == CowVorbis) { _cowFile.seek(index); _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, Audio::makeVorbisStream(&_cowFile, sampleSize), SOUND_SPEECH_ID, speechVol, speechPan); + // with compressed audio, we can't calculate the wave volume. + // so default to talking. + for (int cnt = 0; cnt < 480; cnt++) + _waveVolume[cnt] = true; + _waveVolPos = 0; + } +#endif +#ifdef USE_MAD + else if (_cowMode == CowMp3) { + _cowFile.seek(index); + _mixer->playInputStream(Audio::Mixer::kSpeechSoundType, &_speechHandle, Audio::makeMP3Stream(&_cowFile, sampleSize), SOUND_SPEECH_ID, speechVol, speechPan); + // with compressed audio, we can't calculate the wave volume. + // so default to talking. for (int cnt = 0; cnt < 480; cnt++) _waveVolume[cnt] = true; _waveVolPos = 0; @@ -332,6 +346,16 @@ void Sound::initCowSystem(void) { /* look for speech1/2.clu in the data dir and speech/speech.clu (running from cd or using cd layout) */ +#ifdef USE_FLAC + if (!_cowFile.isOpen()) { + sprintf(cowName, "SPEECH%d.CLF", SwordEngine::_systemVars.currentCD); + _cowFile.open(cowName); + if (_cowFile.isOpen()) { + debug(1, "Using Flac compressed Speech Cluster"); + _cowMode = CowFlac; + } + } +#endif #ifdef USE_VORBIS if (!_cowFile.isOpen()) { sprintf(cowName, "SPEECH%d.CLV", SwordEngine::_systemVars.currentCD); diff --git a/engines/sword1/sound.h b/engines/sword1/sound.h index fb608a9631..fafc9c2d06 100644 --- a/engines/sword1/sound.h +++ b/engines/sword1/sound.h @@ -66,8 +66,9 @@ class ResMan; enum CowMode { CowWave = 0, - CowMp3, + CowFlac, CowVorbis, + CowMp3, CowDemo }; diff --git a/engines/sword1/staticres.cpp b/engines/sword1/staticres.cpp index 366e2c7608..08e6a108c4 100644 --- a/engines/sword1/staticres.cpp +++ b/engines/sword1/staticres.cpp @@ -5158,7 +5158,7 @@ const FxDef Sound::_fxList[312] = { }, }, //------------------------ - // 198 Ambient sound for Montfauçon Square + // 198 Ambient sound for Montfaucon Square { FX_MONTAMB, // sampleId FX_LOOP, // type diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp index d899d25df5..b5152f33bc 100644 --- a/engines/sword1/sword1.cpp +++ b/engines/sword1/sword1.cpp @@ -355,14 +355,18 @@ const CdFile SwordEngine::_pcCdFileList[] = { { "cows.mad", FLAG_DEMO }, { "speech1.clu", FLAG_SPEECH1 }, { "speech2.clu", FLAG_SPEECH2 } -#ifdef USE_MAD - ,{ "speech1.cl3", FLAG_SPEECH1 }, - { "speech2.cl3", FLAG_SPEECH2 } +#ifdef USE_FLAC + ,{ "speech1.clf", FLAG_SPEECH1 }, + { "speech2.clf", FLAG_SPEECH2 } #endif #ifdef USE_VORBIS ,{ "speech1.clv", FLAG_SPEECH1 }, { "speech2.clv", FLAG_SPEECH2 } #endif +#ifdef USE_MAD + ,{ "speech1.cl3", FLAG_SPEECH1 }, + { "speech2.cl3", FLAG_SPEECH2 } +#endif }; const CdFile SwordEngine::_macCdFileList[] = { @@ -383,14 +387,18 @@ const CdFile SwordEngine::_macCdFileList[] = { { "text.clm", FLAG_CD1 | FLAG_DEMO }, { "speech1.clu", FLAG_SPEECH1 }, { "speech2.clu", FLAG_SPEECH2 } -#ifdef USE_MAD - ,{ "speech1.cl3", FLAG_SPEECH1 }, - { "speech2.cl3", FLAG_SPEECH2 } +#ifdef USE_FLAC + ,{ "speech1.clf", FLAG_SPEECH1 }, + { "speech2.clf", FLAG_SPEECH2 } #endif #ifdef USE_VORBIS ,{ "speech1.clv", FLAG_SPEECH1 }, { "speech2.clv", FLAG_SPEECH2 } #endif +#ifdef USE_MAD + ,{ "speech1.cl3", FLAG_SPEECH1 }, + { "speech2.cl3", FLAG_SPEECH2 } +#endif }; diff --git a/engines/sword1/sworddefs.h b/engines/sword1/sworddefs.h index aedc38ef7e..e90eafe825 100644 --- a/engines/sword1/sworddefs.h +++ b/engines/sword1/sworddefs.h @@ -100,7 +100,7 @@ struct Header { uint32 comp_length; char compression[4]; uint32 decomp_length; -}; +} PACKED_STRUCT; struct FrameHeader { uint8 runTimeComp[4]; @@ -115,25 +115,25 @@ struct ParallaxHeader { char type[16]; uint16 sizeX; uint16 sizeY; -}; +} PACKED_STRUCT; struct AnimUnit { uint32 animX; uint32 animY; uint32 animFrame; -}; +} PACKED_STRUCT; struct AnimSet { uint32 cdt; uint32 spr; -}; +} PACKED_STRUCT; struct WalkGridHeader { int32 scaleA; int32 scaleB; int32 numBars; int32 numNodes; -}; +} PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/engines/touche/ui.cpp b/engines/touche/ui.cpp index ef8f5a0d7d..15dc64aaf2 100644 --- a/engines/touche/ui.cpp +++ b/engines/touche/ui.cpp @@ -381,6 +381,11 @@ void ToucheEngine::handleOptions(int forceDisplay) { } } } + if (doRedraw) { + redrawMenu(&menuData); + updateScreenArea(90, 102, 460, 196); + doRedraw = false; + } Common::Event event; while (_eventMan->pollEvent(event)) { const Button *button = 0; @@ -419,11 +424,6 @@ void ToucheEngine::handleOptions(int forceDisplay) { break; } } - if (doRedraw) { - redrawMenu(&menuData); - updateScreenArea(90, 102, 460, 196); - doRedraw = false; - } _system->updateScreen(); _system->delayMillis(10); } diff --git a/graphics/cursorman.h b/graphics/cursorman.h index e0c6b2a4a8..2f139e8d57 100644 --- a/graphics/cursorman.h +++ b/graphics/cursorman.h @@ -34,7 +34,10 @@ namespace Graphics { class CursorManager : public Common::Singleton<CursorManager> { public: + /** Query whether the mouse cursor is visible. */ bool isVisible(); + + /** Show or hide the mouse cursor. */ bool showMouse(bool visible); /** diff --git a/graphics/dxa_player.cpp b/graphics/dxa_player.cpp index 6f2bca111e..c4c9aaed55 100644 --- a/graphics/dxa_player.cpp +++ b/graphics/dxa_player.cpp @@ -152,6 +152,8 @@ void DXAPlayer::closeFile() { return; delete _fd; + _fd = 0; + free(_frameBuffer1); free(_frameBuffer2); free(_scaledBuffer); diff --git a/gui/KeysDialog.cpp b/gui/KeysDialog.cpp index 33d09e4e69..666f03bbc9 100644 --- a/gui/KeysDialog.cpp +++ b/gui/KeysDialog.cpp @@ -126,23 +126,23 @@ void KeysDialog::handleCommand(CommandSender *sender, uint32 cmd, uint32 data) { } } -void KeysDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers){ +void KeysDialog::handleKeyDown(Common::KeyState state){ if (!Actions::Instance()->mappingActive()) - Dialog::handleKeyDown(ascii,keycode,modifiers); + Dialog::handleKeyDown(state); } -void KeysDialog::handleKeyUp(uint16 ascii, int keycode, int modifiers) { +void KeysDialog::handleKeyUp(Common::KeyState state) { #ifdef __SYMBIAN32__ if (Actions::Instance()->mappingActive()) { #else - if (modifiers == 0xff && Actions::Instance()->mappingActive()) { // GAPI key was selected + if (state.flags == 0xff && Actions::Instance()->mappingActive()) { // GAPI key was selected #endif char selection[100]; - Actions::Instance()->setMapping((ActionType)_actionSelected, ascii); + Actions::Instance()->setMapping((ActionType)_actionSelected, state.ascii); - if (ascii != 0) - sprintf(selection, "Associated key : %s", SDL_GetKeyName((SDLKey) keycode)); + if (state.ascii != 0) + sprintf(selection, "Associated key : %s", SDL_GetKeyName((SDLKey) state.keycode)); else sprintf(selection, "Associated key : none"); @@ -154,7 +154,7 @@ void KeysDialog::handleKeyUp(uint16 ascii, int keycode, int modifiers) { _actionsList->setEnabled(true); Actions::Instance()->beginMapping(false); } else - Dialog::handleKeyUp(ascii,keycode,modifiers); + Dialog::handleKeyUp(state); } } // namespace GUI diff --git a/gui/KeysDialog.h b/gui/KeysDialog.h index f4fa4d9419..6d780e665a 100644 --- a/gui/KeysDialog.h +++ b/gui/KeysDialog.h @@ -38,8 +38,8 @@ public: KeysDialog(const Common::String &title = "Choose an action to map"); virtual void handleCommand(GUI::CommandSender *sender, uint32 cmd, uint32 data); - virtual void handleKeyUp(uint16 ascii, int keycode, int modifiers); - virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers); + virtual void handleKeyUp(Common::KeyState state); + virtual void handleKeyDown(Common::KeyState state); protected: diff --git a/gui/ListWidget.cpp b/gui/ListWidget.cpp index 271cbccd94..3d5c3dee62 100644 --- a/gui/ListWidget.cpp +++ b/gui/ListWidget.cpp @@ -186,12 +186,12 @@ static int matchingCharsIgnoringCase(const char *x, const char *y, bool &stop) { return match; } -bool ListWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) { +bool ListWidget::handleKeyDown(Common::KeyState state) { bool handled = true; bool dirty = false; int oldSelectedItem = _selectedItem; - if (!_editMode && isprint((char)ascii)) { + if (!_editMode && isprint((char)state.ascii)) { // Quick selection mode: Go to first list item starting with this key // (or a substring accumulated from the last couple key presses). // Only works in a useful fashion if the list entries are sorted. @@ -199,9 +199,9 @@ bool ListWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) { // method "enableQuickSelect()" or so ? uint32 time = getMillis(); if (_quickSelectTime < time) { - _quickSelectStr = (char)ascii; + _quickSelectStr = (char)state.ascii; } else { - _quickSelectStr += (char)ascii; + _quickSelectStr += (char)state.ascii; } _quickSelectTime = time + 300; // TODO: Turn this into a proper constant (kQuickSelectDelay ?) @@ -227,11 +227,11 @@ bool ListWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) { scrollToCurrent(); } else if (_editMode) { // Class EditableWidget handles all text editing related key presses for us - handled = EditableWidget::handleKeyDown(ascii, keycode, modifiers); + handled = EditableWidget::handleKeyDown(state); } else { // not editmode - switch (keycode) { + switch (state.keycode) { case Common::KEYCODE_RETURN: case Common::KEYCODE_KP_ENTER: if (_selectedItem >= 0) { @@ -285,14 +285,14 @@ bool ListWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) { #if !defined(PALMOS_MODE) // not done on PalmOS because keyboard is emulated and keyup is not generated - _currentKeyDown = keycode; + _currentKeyDown = state.keycode; #endif return handled; } -bool ListWidget::handleKeyUp(uint16 ascii, int keycode, int modifiers) { - if (keycode == _currentKeyDown) +bool ListWidget::handleKeyUp(Common::KeyState state) { + if (state.keycode == _currentKeyDown) _currentKeyDown = 0; return true; } diff --git a/gui/ListWidget.h b/gui/ListWidget.h index a8656061d3..fe3dd4cd7e 100644 --- a/gui/ListWidget.h +++ b/gui/ListWidget.h @@ -92,8 +92,8 @@ public: virtual void handleMouseDown(int x, int y, int button, int clickCount); virtual void handleMouseUp(int x, int y, int button, int clickCount); virtual void handleMouseWheel(int x, int y, int direction); - virtual bool handleKeyDown(uint16 ascii, int keycode, int modifiers); - virtual bool handleKeyUp(uint16 ascii, int keycode, int modifiers); + virtual bool handleKeyDown(Common::KeyState state); + virtual bool handleKeyUp(Common::KeyState state); virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); virtual void reflowLayout(); diff --git a/gui/PopUpWidget.cpp b/gui/PopUpWidget.cpp index d40a01c981..ac91376269 100644 --- a/gui/PopUpWidget.cpp +++ b/gui/PopUpWidget.cpp @@ -58,7 +58,7 @@ public: void handleMouseUp(int x, int y, int button, int clickCount); void handleMouseWheel(int x, int y, int direction); // Scroll through entries with scroll wheel void handleMouseMoved(int x, int y, int button); // Redraw selections depending on mouse position - void handleKeyDown(uint16 ascii, int keycode, int modifiers); // Scroll through entries with arrow keys etc. + void handleKeyDown(Common::KeyState state); // Scroll through entries with arrow keys etc. protected: void drawMenuEntry(int entry, bool hilite); @@ -210,8 +210,8 @@ void PopUpDialog::handleMouseMoved(int x, int y, int button) { setSelection(item); } -void PopUpDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { - if (keycode == Common::KEYCODE_ESCAPE) { +void PopUpDialog::handleKeyDown(Common::KeyState state) { + if (state.keycode == Common::KEYCODE_ESCAPE) { // Don't change the previous selection setResult(-1); close(); @@ -221,7 +221,7 @@ void PopUpDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { if (isMouseDown()) return; - switch (keycode) { + switch (state.keycode) { case Common::KEYCODE_RETURN: case Common::KEYCODE_KP_ENTER: setResult(_selection); @@ -239,6 +239,8 @@ void PopUpDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { case Common::KEYCODE_END: setSelection(_popUpBoss->_entries.size()-1); break; + default: + break; } } diff --git a/gui/TabWidget.cpp b/gui/TabWidget.cpp index 38ea6229ec..c414f6bf3b 100644 --- a/gui/TabWidget.cpp +++ b/gui/TabWidget.cpp @@ -198,11 +198,11 @@ void TabWidget::handleMouseDown(int x, int y, int button, int clickCount) { } } -bool TabWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) { +bool TabWidget::handleKeyDown(Common::KeyState state) { // TODO: maybe there should be a way to switch between tabs // using the keyboard? E.g. Alt-Shift-Left/Right-Arrow or something // like that. - return Widget::handleKeyDown(ascii, keycode, modifiers); + return Widget::handleKeyDown(state); } void TabWidget::reflowLayout() { diff --git a/gui/TabWidget.h b/gui/TabWidget.h index 928f7916b6..a8c5e07525 100644 --- a/gui/TabWidget.h +++ b/gui/TabWidget.h @@ -87,7 +87,7 @@ public: void setActiveTab(int tabID); virtual void handleMouseDown(int x, int y, int button, int clickCount); - virtual bool handleKeyDown(uint16 ascii, int keycode, int modifiers); + virtual bool handleKeyDown(Common::KeyState state); virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); virtual void reflowLayout(); diff --git a/gui/about.cpp b/gui/about.cpp index 31381cadd5..780091f35d 100644 --- a/gui/about.cpp +++ b/gui/about.cpp @@ -302,13 +302,13 @@ void AboutDialog::handleMouseUp(int x, int y, int button, int clickCount) { close(); } -void AboutDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { - if (ascii) +void AboutDialog::handleKeyDown(Common::KeyState state) { + if (state.ascii) _willClose = true; } -void AboutDialog::handleKeyUp(uint16 ascii, int keycode, int modifiers) { - if (ascii && _willClose) +void AboutDialog::handleKeyUp(Common::KeyState state) { + if (state.ascii && _willClose) close(); } diff --git a/gui/about.h b/gui/about.h index a1ee96b090..d62510b1a6 100644 --- a/gui/about.h +++ b/gui/about.h @@ -52,8 +52,8 @@ public: void drawDialog(); void handleTickle(); void handleMouseUp(int x, int y, int button, int clickCount); - void handleKeyDown(uint16 ascii, int keycode, int modifiers); - void handleKeyUp(uint16 ascii, int keycode, int modifiers); + void handleKeyDown(Common::KeyState state); + void handleKeyUp(Common::KeyState state); void reflowLayout(); }; diff --git a/gui/console.cpp b/gui/console.cpp index b7c257d3ce..04a1103628 100644 --- a/gui/console.cpp +++ b/gui/console.cpp @@ -258,13 +258,13 @@ void ConsoleDialog::handleMouseWheel(int x, int y, int direction) { _scrollBar->handleMouseWheel(x, y, direction); } -void ConsoleDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { +void ConsoleDialog::handleKeyDown(Common::KeyState state) { int i; if (_slideMode != kNoSlideMode) return; - switch (keycode) { + switch (state.keycode) { case Common::KEYCODE_RETURN: case Common::KEYCODE_KP_ENTER: { if (_caretVisible) @@ -351,7 +351,7 @@ void ConsoleDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { drawLine(pos2line(_currentPos)); break; case Common::KEYCODE_PAGEUP: - if (modifiers == Common::KBD_SHIFT) { + if (state.flags == Common::KBD_SHIFT) { _scrollLine -= _linesPerPage - 1; if (_scrollLine < _firstLineInBuffer + _linesPerPage - 1) _scrollLine = _firstLineInBuffer + _linesPerPage - 1; @@ -360,7 +360,7 @@ void ConsoleDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { } break; case Common::KEYCODE_PAGEDOWN: - if (modifiers == Common::KBD_SHIFT) { + if (state.flags == Common::KBD_SHIFT) { _scrollLine += _linesPerPage - 1; if (_scrollLine > _promptEndPos / kCharsPerLine) { _scrollLine = _promptEndPos / kCharsPerLine; @@ -372,7 +372,7 @@ void ConsoleDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { } break; case Common::KEYCODE_HOME: - if (modifiers == Common::KBD_SHIFT) { + if (state.flags == Common::KBD_SHIFT) { _scrollLine = _firstLineInBuffer + _linesPerPage - 1; updateScrollBuffer(); } else { @@ -381,7 +381,7 @@ void ConsoleDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { draw(); break; case Common::KEYCODE_END: - if (modifiers == Common::KBD_SHIFT) { + if (state.flags == Common::KBD_SHIFT) { _scrollLine = _promptEndPos / kCharsPerLine; if (_scrollLine < _linesPerPage - 1) _scrollLine = _linesPerPage - 1; @@ -408,15 +408,15 @@ void ConsoleDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { drawLine(pos2line(_currentPos)); break; default: - if (ascii == '~' || ascii == '#') { + if (state.ascii == '~' || state.ascii == '#') { slideUpAndClose(); - } else if (modifiers == Common::KBD_CTRL) { - specialKeys(keycode); - } else if ((ascii >= 32 && ascii <= 127) || (ascii >= 160 && ascii <= 255)) { + } else if (state.flags == Common::KBD_CTRL) { + specialKeys(state.keycode); + } else if ((state.ascii >= 32 && state.ascii <= 127) || (state.ascii >= 160 && state.ascii <= 255)) { for (i = _promptEndPos - 1; i >= _currentPos; i--) buffer(i + 1) = buffer(i); _promptEndPos++; - putchar((byte)ascii); + putchar((byte)state.ascii); scrollToCurrent(); } } diff --git a/gui/console.h b/gui/console.h index ea28e5b449..c683a1f619 100644 --- a/gui/console.h +++ b/gui/console.h @@ -140,7 +140,7 @@ public: void handleTickle(); void reflowLayout(); void handleMouseWheel(int x, int y, int direction); - void handleKeyDown(uint16 ascii, int keycode, int modifiers); + void handleKeyDown(Common::KeyState state); void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); int printf(const char *format, ...); diff --git a/gui/credits.h b/gui/credits.h index 5babeb1faa..fba9350bca 100644 --- a/gui/credits.h +++ b/gui/credits.h @@ -144,6 +144,8 @@ static const char *credits[] = { "\\C\\c2""MT-32 emulator", "\\C\\c0""Jochen Hoenicke", "\\C\\c2""Speaker & PCjr sound support, Adlib work", +"\\C\\c0""Robin Watts", +"\\C\\c2""ARM assembly routines for nice speedups on several ports; improvements to the sound mixer", "\\C\\c0""", "\\C\\c0""", "\\C\\c1""Website (content)", @@ -286,8 +288,6 @@ static const char *credits[] = { "\\C\\c2""Final MI1 CD music support, initial Ogg Vorbis support", "\\C\\c0""Andr\351 Souza", "\\C\\c2""SDL-based OpenGL renderer", -"\\C\\c0""Robin Watts", -"\\C\\c2""ARM assembly routines for the Windows CE port", "\\C\\c0""", "\\C\\c0""And to all the contributors, users, and beta testers we've missed. Thanks!", "\\C\\c0""", diff --git a/gui/dialog.cpp b/gui/dialog.cpp index 1afd18ec52..f643e6f988 100644 --- a/gui/dialog.cpp +++ b/gui/dialog.cpp @@ -211,18 +211,18 @@ void Dialog::handleMouseWheel(int x, int y, int direction) { w->handleMouseWheel(x, y, direction); } -void Dialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { +void Dialog::handleKeyDown(Common::KeyState state) { if (_focusedWidget) { - if (_focusedWidget->handleKeyDown(ascii, keycode, modifiers)) + if (_focusedWidget->handleKeyDown(state)) return; } // Hotkey handling - if (ascii != 0) { + if (state.ascii != 0) { Widget *w = _firstWidget; - ascii = toupper(ascii); + state.ascii = toupper(state.ascii); while (w) { - if (w->_type == kButtonWidget && ascii == toupper(((ButtonWidget *)w)->_hotkey)) { + if (w->_type == kButtonWidget && state.ascii == toupper(((ButtonWidget *)w)->_hotkey)) { // The hotkey for widget w was pressed. We fake a mouse click into the // button by invoking the appropriate methods. w->handleMouseDown(0, 0, 1, 1); @@ -234,7 +234,7 @@ void Dialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { } // ESC closes all dialogs by default - if (keycode == Common::KEYCODE_ESCAPE) { + if (state.keycode == Common::KEYCODE_ESCAPE) { setResult(-1); close(); } @@ -242,10 +242,10 @@ void Dialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { // TODO: tab/shift-tab should focus the next/previous focusable widget } -void Dialog::handleKeyUp(uint16 ascii, int keycode, int modifiers) { +void Dialog::handleKeyUp(Common::KeyState state) { // Focused widget receives keyup events if (_focusedWidget) - _focusedWidget->handleKeyUp(ascii, keycode, modifiers); + _focusedWidget->handleKeyUp(state); } void Dialog::handleMouseMoved(int x, int y, int button) { diff --git a/gui/dialog.h b/gui/dialog.h index 1c97b4b185..418e3b8e63 100644 --- a/gui/dialog.h +++ b/gui/dialog.h @@ -77,8 +77,8 @@ protected: virtual void handleMouseDown(int x, int y, int button, int clickCount); virtual void handleMouseUp(int x, int y, int button, int clickCount); virtual void handleMouseWheel(int x, int y, int direction); - virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers); - virtual void handleKeyUp(uint16 ascii, int keycode, int modifiers); + virtual void handleKeyDown(Common::KeyState state); + virtual void handleKeyUp(Common::KeyState state); virtual void handleMouseMoved(int x, int y, int button); virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); diff --git a/gui/editable.cpp b/gui/editable.cpp index a8638b8b48..1333bf0a9d 100644 --- a/gui/editable.cpp +++ b/gui/editable.cpp @@ -85,7 +85,7 @@ void EditableWidget::handleTickle() { } } -bool EditableWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) { +bool EditableWidget::handleKeyDown(Common::KeyState state) { bool handled = true; bool dirty = false; bool forcecaret = false; @@ -94,7 +94,7 @@ bool EditableWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) { if (_caretVisible) drawCaret(true); - switch (keycode) { + switch (state.keycode) { case Common::KEYCODE_RETURN: case Common::KEYCODE_KP_ENTER: // confirm edit and exit editmode @@ -143,7 +143,7 @@ bool EditableWidget::handleKeyDown(uint16 ascii, int keycode, int modifiers) { forcecaret = true; break; default: - if (tryInsertChar((byte)ascii, _caretPos)) { + if (tryInsertChar((byte)state.ascii, _caretPos)) { _caretPos++; dirty = true; forcecaret = true; diff --git a/gui/editable.h b/gui/editable.h index a56b079662..c8ef8a80cb 100644 --- a/gui/editable.h +++ b/gui/editable.h @@ -63,7 +63,7 @@ public: virtual const String &getEditString() const { return _editString; } virtual void handleTickle(); - virtual bool handleKeyDown(uint16 ascii, int keycode, int modifiers); + virtual bool handleKeyDown(Common::KeyState state); virtual void reflowLayout(); diff --git a/gui/launcher.cpp b/gui/launcher.cpp index 995a0cf78a..215f389f6d 100644 --- a/gui/launcher.cpp +++ b/gui/launcher.cpp @@ -148,7 +148,7 @@ protected: EditGameDialog::EditGameDialog(const String &domain, const String &desc) : OptionsDialog(domain, "gameoptions") { - int labelWidth = g_gui.evaluator()->getVar("gameOptionsLabelWidth"); + int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); // GAME: Path to game data (r/o), extra data (r/o), and save data (r/w) String gamePath(ConfMan.get("path", _domain)); @@ -171,15 +171,15 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) tab->addTab("Game"); // GUI: Label & edit widget for the game ID - new StaticTextWidget(tab, "gameoptions_id", "ID: "); + new StaticTextWidget(tab, "gameoptions_id", "ID:"); _domainWidget = new DomainEditTextWidget(tab, "gameoptions_domain", _domain); // GUI: Label & edit widget for the description - new StaticTextWidget(tab, "gameoptions_name", "Name: "); + new StaticTextWidget(tab, "gameoptions_name", "Name:"); _descriptionWidget = new EditTextWidget(tab, "gameoptions_desc", description); // Language popup - _langPopUp = new PopUpWidget(tab, "gameoptions_lang", "Language: ", labelWidth); + _langPopUp = new PopUpWidget(tab, "gameoptions_lang", "Language:", labelWidth); _langPopUp->appendEntry("<default>"); _langPopUp->appendEntry(""); const Common::LanguageDescription *l = Common::g_languages; @@ -188,7 +188,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) } // Platform popup - _platformPopUp = new PopUpWidget(tab, "gameoptions_platform", "Platform: ", labelWidth); + _platformPopUp = new PopUpWidget(tab, "gameoptions_platform", "Platform:", labelWidth); _platformPopUp->appendEntry("<default>"); _platformPopUp->appendEntry(""); const Common::PlatformDescription *p = Common::g_platforms; @@ -242,7 +242,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) // in the small version of the GUI. // GUI: Button + Label for the game path - new ButtonWidget(tab, "gameoptions_gamepath", "Game Path: ", kCmdGameBrowser, 0); + new ButtonWidget(tab, "gameoptions_gamepath", "Game Path:", kCmdGameBrowser, 0); _gamePathWidget = new StaticTextWidget(tab, "gameoptions_gamepathText", gamePath); // GUI: Button + Label for the additional path @@ -253,7 +253,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) } // GUI: Button + Label for the save path - new ButtonWidget(tab, "gameoptions_savepath", "Save Path: ", kCmdSaveBrowser, 0); + new ButtonWidget(tab, "gameoptions_savepath", "Save Path:", kCmdSaveBrowser, 0); _savePathWidget = new StaticTextWidget(tab, "gameoptions_savepathText", savePath); if (savePath.empty() || !ConfMan.hasKey("savepath", _domain)) { _savePathWidget->setLabel("Default"); @@ -270,7 +270,7 @@ EditGameDialog::EditGameDialog(const String &domain, const String &desc) void EditGameDialog::reflowLayout() { OptionsDialog::reflowLayout(); - int labelWidth = g_gui.evaluator()->getVar("gameOptionsLabelWidth"); + int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); if (_langPopUp) _langPopUp->changeLabelWidth(labelWidth); @@ -588,6 +588,15 @@ void LauncherDialog::updateListing() { if (g.contains("description")) description = g.description(); } + +#ifdef __DS__ + // DS port uses an extra section called 'ds'. This prevents the section from being + // detected as a game. + if (gameid == "ds") { + continue; + } +#endif + if (description.empty()) description = "Unknown (target " + iter->_key + ", gameid " + gameid + ")"; @@ -789,13 +798,13 @@ void LauncherDialog::editGame(int item) { } } -void LauncherDialog::handleKeyDown(uint16 ascii, int keycode, int modifiers) { - Dialog::handleKeyDown(ascii, keycode, modifiers); +void LauncherDialog::handleKeyDown(Common::KeyState state) { + Dialog::handleKeyDown(state); updateButtons(); } -void LauncherDialog::handleKeyUp(uint16 ascii, int keycode, int modifiers) { - Dialog::handleKeyUp(ascii, keycode, modifiers); +void LauncherDialog::handleKeyUp(Common::KeyState state) { + Dialog::handleKeyUp(state); updateButtons(); } diff --git a/gui/launcher.h b/gui/launcher.h index 5ccf9cb422..164a7e0707 100644 --- a/gui/launcher.h +++ b/gui/launcher.h @@ -47,8 +47,8 @@ public: virtual void handleCommand(CommandSender *sender, uint32 cmd, uint32 data); - virtual void handleKeyDown(uint16 ascii, int keycode, int modifiers); - virtual void handleKeyUp(uint16 ascii, int keycode, int modifiers); + virtual void handleKeyDown(Common::KeyState state); + virtual void handleKeyUp(Common::KeyState state); protected: ListWidget *_list; diff --git a/gui/newgui.cpp b/gui/newgui.cpp index ad1933863a..51d67b8769 100644 --- a/gui/newgui.cpp +++ b/gui/newgui.cpp @@ -272,10 +272,10 @@ void NewGui::runLoop() { switch (event.type) { case Common::EVENT_KEYDOWN: - activeDialog->handleKeyDown(event.kbd.ascii, event.kbd.keycode, event.kbd.flags); + activeDialog->handleKeyDown(event.kbd); break; case Common::EVENT_KEYUP: - activeDialog->handleKeyUp(event.kbd.ascii, event.kbd.keycode, event.kbd.flags); + activeDialog->handleKeyUp(event.kbd); break; case Common::EVENT_MOUSEMOVE: activeDialog->handleMouseMoved(mouse.x, mouse.y, 0); diff --git a/gui/options.cpp b/gui/options.cpp index 6d588b6b44..c233c892b9 100644 --- a/gui/options.cpp +++ b/gui/options.cpp @@ -67,7 +67,7 @@ enum { static const char *savePeriodLabels[] = { "Never", "every 5 mins", "every 10 mins", "every 15 mins", "every 30 mins", 0 }; static const int savePeriodValues[] = { 0, 5 * 60, 10 * 60, 15 * 60, 30 * 60, -1 }; -static const char *outputRateLabels[] = { "Default", "22 kHz", "8 kHz", "11kHz", "44 kHz", "48 kHz", 0 }; +static const char *outputRateLabels[] = { "<default>", "22 kHz", "8 kHz", "11kHz", "44 kHz", "48 kHz", 0 }; static const int outputRateValues[] = { 0, 22050, 8000, 11025, 44100, 48000, -1 }; @@ -503,7 +503,7 @@ void OptionsDialog::addGraphicControls(GuiObject *boss, const String &prefix) { int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); // The GFX mode popup - _gfxPopUp = new PopUpWidget(boss, prefix + "grModePopup", "Graphics mode: ", labelWidth); + _gfxPopUp = new PopUpWidget(boss, prefix + "grModePopup", "Graphics mode:", labelWidth); _gfxPopUp->appendEntry("<default>"); _gfxPopUp->appendEntry(""); @@ -513,7 +513,7 @@ void OptionsDialog::addGraphicControls(GuiObject *boss, const String &prefix) { } // RenderMode popup - _renderModePopUp = new PopUpWidget(boss, prefix + "grRenderPopup", "Render mode: ", labelWidth); + _renderModePopUp = new PopUpWidget(boss, prefix + "grRenderPopup", "Render mode:", labelWidth); _renderModePopUp->appendEntry("<default>", Common::kRenderDefault); _renderModePopUp->appendEntry(""); const Common::RenderModeDescription *rm = Common::g_renderModes; @@ -540,7 +540,7 @@ void OptionsDialog::addAudioControls(GuiObject *boss, const String &prefix) { int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); // The MIDI mode popup & a label - _midiPopUp = new PopUpWidget(boss, prefix + "auMidiPopup", "Music driver: ", labelWidth); + _midiPopUp = new PopUpWidget(boss, prefix + "auMidiPopup", "Music driver:", labelWidth); // Populate it const MidiDriverDescription *md = MidiDriver::getAvailableMidiDrivers(); @@ -550,7 +550,7 @@ void OptionsDialog::addAudioControls(GuiObject *boss, const String &prefix) { } // Sample rate settings - _outputRatePopUp = new PopUpWidget(boss, prefix + "auSampleRatePopup", "Output rate: ", labelWidth); + _outputRatePopUp = new PopUpWidget(boss, prefix + "auSampleRatePopup", "Output rate:", labelWidth); for (int i = 0; outputRateLabels[i]; i++) { _outputRatePopUp->appendEntry(outputRateLabels[i], outputRateValues[i]); @@ -720,7 +720,7 @@ GlobalOptionsDialog::GlobalOptionsDialog() int labelWidth = g_gui.evaluator()->getVar("tabPopupsLabelW"); - _autosavePeriodPopUp = new PopUpWidget(tab, "globaloptions_autosaveperiod", "Autosave: ", labelWidth); + _autosavePeriodPopUp = new PopUpWidget(tab, "globaloptions_autosaveperiod", "Autosave:", labelWidth); for (int i = 0; savePeriodLabels[i]; i++) { _autosavePeriodPopUp->appendEntry(savePeriodLabels[i], savePeriodValues[i]); diff --git a/gui/theme-config.cpp b/gui/theme-config.cpp index c12ca009da..8da2be99e1 100644 --- a/gui/theme-config.cpp +++ b/gui/theme-config.cpp @@ -73,14 +73,14 @@ const char *Theme::_defaultConfigINI = "\n" "# audio tab\n" "opYoffset=vBorder\n" -"gameoptions_audioCheckbox=gox opYoffset (kFontHeight + 10 + 180) buttonHeight\n" +"gameoptions_audioCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n" "opYoffset=(opYoffset + buttonHeight + 6)\n" "useWithPrefix=audioControls gameoptions_\n" "useWithPrefix=subtitleControls gameoptions_\n" "\n" "# volume tab\n" "opYoffset=vBorder\n" -"gameoptions_volumeCheckbox=gox opYoffset (kFontHeight + 10 + 190) buttonHeight\n" +"gameoptions_volumeCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n" "opYoffset=(opYoffset + buttonHeight + 6)\n" "useWithPrefix=volumeControls gameoptions_\n" "\n" @@ -268,26 +268,26 @@ const char *Theme::_defaultConfigINI = "# graphics tab\n" "opYoffset=vBorder\n" "opXoffset=gox\n" -"gameoptions_graphicsCheckbox=gox opYoffset (kFontHeight + 10 + 192) buttonHeight\n" +"gameoptions_graphicsCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n" "opYoffset=(opYoffset + buttonHeight)\n" "useWithPrefix=graphicsControls gameoptions_\n" "\n" "# audio tab\n" "opYoffset=vBorder\n" -"gameoptions_audioCheckbox=gox opYoffset (kFontHeight + 10 + 180) buttonHeight\n" +"gameoptions_audioCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n" "opYoffset=(opYoffset + buttonHeight)\n" "useWithPrefix=audioControls gameoptions_\n" "useWithPrefix=subtitleControls gameoptions_\n" "\n" "# volume tab\n" "opYoffset=vBorder\n" -"gameoptions_volumeCheckbox=gox opYoffset (kFontHeight + 10 + 190) buttonHeight\n" +"gameoptions_volumeCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n" "opYoffset=(opYoffset + buttonHeight)\n" "useWithPrefix=volumeControls gameoptions_\n" "\n" "# midi tab\n" "opYoffset=vBorder\n" -"gameoptions_midiCheckbox=gox opYoffset (kFontHeight + 10 + 174) buttonHeight\n" +"gameoptions_midiCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight\n" "opYoffset=(opYoffset + buttonHeight)\n" "useWithPrefix=midiControls gameoptions_\n" "\n" @@ -387,9 +387,9 @@ const char *Theme::_defaultConfigINI = "opYoffset=(opYoffset + kLineHeight + 4)\n" "grRenderPopup=prev.x (opYoffset - 1) prev.w prev.h\n" "opYoffset=(opYoffset + kLineHeight + 4)\n" -"grFullscreenCheckbox=gcx opYoffset (kFontHeight + 10 + 96) buttonHeight\n" +"grFullscreenCheckbox=gcx opYoffset (parent.w - gcx - 5) buttonHeight\n" "opYoffset=(opYoffset + buttonHeight)\n" -"grAspectCheckbox=prev.x opYoffset (kFontHeight + 10 + 180) prev.h\n" +"grAspectCheckbox=prev.x opYoffset prev.w prev.h\n" "opYoffset=(opYoffset + buttonHeight)\n" "\n" "[audioControls]\n" @@ -426,11 +426,11 @@ const char *Theme::_defaultConfigINI = "mcFontPath=(prev.x2 + 20) (opYoffset + 3) (parent.w - (buttonWidth + 20) - 15 - kLineHeight - 10) kLineHeight\n" "mcFontClearButton=(prev.x2 + 10) (opYoffset + 2) kLineHeight kLineHeight\n" "opYoffset=(opYoffset + buttonHeight + 2 * midiControlsSpacing)\n" -"mcMixedCheckbox=mcx opYoffset (kFontHeight + 10 + 135) buttonHeight\n" +"mcMixedCheckbox=mcx opYoffset (parent.w - mcx - 5) buttonHeight\n" "opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)\n" -"mcMt32Checkbox=mcx opYoffset (kFontHeight + 10 + 256) buttonHeight\n" +"mcMt32Checkbox=mcx opYoffset prev.w buttonHeight\n" "opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)\n" -"mcGSCheckbox=mcx opYoffset (kFontHeight + 10 + 142) buttonHeight\n" +"mcGSCheckbox=mcx opYoffset prev.w buttonHeight\n" "opYoffset=(opYoffset + buttonHeight + midiControlsSpacing)\n" "mcMidiGainText=mcx (opYoffset + 2) 95 kLineHeight\n" "mcMidiGainText.align=kTextAlignRight\n" @@ -445,6 +445,7 @@ const char *Theme::_defaultConfigINI = "sbtextw=(100 + vcAudioTabIndent)\n" "opYoffset=(opYoffset + sbYoff)\n" "subToggleDesc=sbx (opYoffset + sbYoff) sbtextw buttonHeight\n" +"subToggleDesc.align=kTextAlignRight\n" "subToggleButton=prev.x2 (opYoffset - sbYoff) (buttonWidth + 54) buttonHeight\n" "opYoffset=(opYoffset + buttonHeight + 6)\n" "subSubtitleSpeedDesc=sbx (opYoffset + sbOff) sbtextw kLineHeight\n" @@ -549,7 +550,7 @@ void Theme::processSingleLine(const String §ion, const String &prefix, const const char **postfixes = (ntmppostfix == 2) ? postfixesRGB : postfixesXYWH; - // Now do it for real, only this time we already know the parantheses + // Now do it for real, only this time we already know the parentheses // are balanced. for (i = 0; i < str.size(); i++) { @@ -570,10 +571,15 @@ void Theme::processSingleLine(const String §ion, const String &prefix, const _evaluator->setStringVar(prefixedname, _evaluator->lastToken()); // process VAR=VALUE construct - if (npostfix == 0) + if (npostfix == 0) { _evaluator->setVar(name, value); - else + + // Fix bug #1742561: "GUI: Missaligned text" + // "blah.align=foo" should be prefixed too + _evaluator->setVar(prefixedname, value); + } else { _evaluator->setVar(prefixedname + postfixes[npostfix], value); + } // If we have all 4 parameters, set .x2 and .y2 if (npostfix == 3) { @@ -611,16 +617,16 @@ void Theme::processResSection(Common::ConfigFile &config, const String &name, bo if (iterk->key == "use") { if (iterk->value == name) error("Theme section [%s]: cannot use itself", name.c_str()); - if (!config.hasSection(name)) - error("Undefined use of section [%s]", name.c_str()); + if (!config.hasSection(iterk->value)) + error("Undefined use of section [%s]", iterk->value.c_str()); processResSection(config, iterk->value, true); continue; } if (iterk->key == "useAsIs") { if (iterk->value == name) error("Theme section [%s]: cannot use itself", name.c_str()); - if (!config.hasSection(name)) - error("Undefined use of section [%s]", name.c_str()); + if (!config.hasSection(iterk->value)) + error("Undefined use of section [%s]", iterk->value.c_str()); processResSection(config, iterk->value); continue; } diff --git a/gui/themes/classic080.ini b/gui/themes/classic080.ini index 481d00c27a..3a58ec60f7 100644 --- a/gui/themes/classic080.ini +++ b/gui/themes/classic080.ini @@ -187,26 +187,26 @@ opYoffset=(opYoffset + buttonHeight + 4) # graphics tab opYoffset=vBorder opXoffset=gox -gameoptions_graphicsCheckbox=gox opYoffset (kFontHeight + 10 + 192) buttonHeight +gameoptions_graphicsCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight opYoffset=(opYoffset + buttonHeight) useWithPrefix=graphicsControls gameoptions_ # audio tab opYoffset=vBorder -gameoptions_audioCheckbox=gox opYoffset (kFontHeight + 10 + 180) buttonHeight +gameoptions_audioCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight opYoffset=(opYoffset + buttonHeight) useWithPrefix=audioControls gameoptions_ useWithPrefix=subtitleControls gameoptions_ # volume tab opYoffset=vBorder -gameoptions_volumeCheckbox=gox opYoffset (kFontHeight + 10 + 190) buttonHeight +gameoptions_volumeCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight opYoffset=(opYoffset + buttonHeight) useWithPrefix=volumeControls gameoptions_ # midi tab opYoffset=vBorder -gameoptions_midiCheckbox=gox opYoffset (kFontHeight + 10 + 174) buttonHeight +gameoptions_midiCheckbox=gox opYoffset (parent.w - gox - 5) buttonHeight opYoffset=(opYoffset + buttonHeight) useWithPrefix=midiControls gameoptions_ @@ -305,9 +305,9 @@ grModePopup=(gcx - 5) (opYoffset - 1) (gcw + 5) (kLineHeight + 2) opYoffset=(opYoffset + kLineHeight + 4) grRenderPopup=prev.x (opYoffset - 1) prev.w prev.h opYoffset=(opYoffset + kLineHeight + 4) -grFullscreenCheckbox=gcx opYoffset (kFontHeight + 10 + 96) buttonHeight +grFullscreenCheckbox=gcx opYoffset (parent.w - gcx - 5) buttonHeight opYoffset=(opYoffset + buttonHeight) -grAspectCheckbox=prev.x opYoffset (kFontHeight + 10 + 180) prev.h +grAspectCheckbox=prev.x opYoffset prev.w prev.h opYoffset=(opYoffset + buttonHeight) [audioControls] @@ -344,11 +344,11 @@ mcFontButton=mcx opYoffset buttonWidth buttonHeight mcFontPath=(prev.x2 + 20) (opYoffset + 3) (parent.w - (buttonWidth + 20) - mcx - kLineHeight - 20) kLineHeight mcFontClearButton=(prev.x2 + 10) (opYoffset + 3) kLineHeight kLineHeight opYoffset=(opYoffset + buttonHeight + 2 * midiControlsSpacing) -mcMixedCheckbox=mcx opYoffset (kFontHeight + 10 + 135) buttonHeight +mcMixedCheckbox=mcx opYoffset (parent.w - mcx - 5) buttonHeight opYoffset=(opYoffset + buttonHeight + midiControlsSpacing) -mcMt32Checkbox=mcx opYoffset (kFontHeight + 10 + 256) buttonHeight +mcMt32Checkbox=mcx opYoffset prev.w buttonHeight opYoffset=(opYoffset + buttonHeight + midiControlsSpacing) -mcGSCheckbox=mcx opYoffset (kFontHeight + 10 + 142) buttonHeight +mcGSCheckbox=mcx opYoffset prev.w buttonHeight opYoffset=(opYoffset + buttonHeight + midiControlsSpacing) mcMidiGainText=mcx (opYoffset + 2) 95 kLineHeight mcMidiGainText.align=kTextAlignRight @@ -363,6 +363,7 @@ sbOff=((sliderHeight - kLineHeight) / 2 + 2) sbtextw=(100 + vcAudioTabIndent) opYoffset=(opYoffset + sbYoff) subToggleDesc=sbx (opYoffset + sbYoff) sbtextw buttonHeight +subToggleDesc.align=kTextAlignRight subToggleButton=prev.x2 (opYoffset - sbYoff) (buttonWidth + 54) buttonHeight opYoffset=(opYoffset + buttonHeight + 6) subSubtitleSpeedDesc=sbx (opYoffset + sbOff) sbtextw kLineHeight diff --git a/gui/themes/modern.ini b/gui/themes/modern.ini index 25fd8da01d..541c2fb00a 100644 --- a/gui/themes/modern.ini +++ b/gui/themes/modern.ini @@ -185,9 +185,9 @@ def_insetY=94 def_insetW=(w - buttonWidth - 17 * 2 - insetX) def_insetH=(h - 23 - insetY) def_optionsVPad=20 -def_gameOptionsLabelWidth=90 +def_optionsLabelWidth=110 def_gameOptionsOverrideVPad=20 -def_tabPopupsLabelW=110 +def_tabPopupsLabelW=optionsLabelWidth def_aboutXOff=8 def_aboutYOff=5 def_aboutOuterBorder=80 @@ -196,10 +196,13 @@ def_scummmainVSpace=15 def_scummmainVAddOff=5 def_scummhelpW=370 def_scummhelpX=((w - scummhelpW) / 2) -def_midiControlsSpacing=4 def_launcherVersionX=(w / 2 - 283 / 2 - 90) def_launcherVersionY=21 +def_xSeparation=10 +def_ySeparation=10 +def_xBorder=15 + use=pixmaps use=colors use=gradients @@ -214,7 +217,7 @@ ListWidget.hlLeftPadding=0 ListWidget.hlRightPadding=0 PopUpWidget.leftPadding=7 PopUpWidget.rightPadding=5 -PopUpWidget.labelSpacing=3 +PopUpWidget.labelSpacing=xSeparation EditTextWidget.font=kFontStyleNormal EditTextWidget.leftPadding=7 EditTextWidget.rightPadding=5 @@ -245,7 +248,7 @@ launcher_logo=(w / 2 - 283 / 2) 5 283 80 launcher_logo.visible=true space1=20 space2=5 -launcher_list=insetX insetY (w - buttonWidth - 17 * 2 - self.x) (h - 23 - self.y) +launcher_list=insetX insetY insetW insetH launcher_start_button=(prev.x2 + 17) prev.y buttonWidth buttonHeight launcher_addGame_button=prev.x (prev.y2 + space1) prev.w prev.h launcher_editGame_button=prev.x (prev.y2 + space2) prev.w prev.h @@ -260,7 +263,7 @@ use=scummmain globaloptions=insetX insetY insetW insetH set_parent=globaloptions vBorder=optionsVPad -globaloptions_tabwidget=0 0 parent.w (parent.h - buttonHeight - 16) +globaloptions_tabwidget=0 0 parent.w (parent.h - buttonHeight - 8 - ySeparation) # graphics tab opYoffset=vBorder @@ -283,93 +286,94 @@ useWithPrefix=midiControls globaloptions_ # paths tab yoffset=vBorder glOff=((buttonHeight - kLineHeight) / 2 + 2) -globaloptions_savebutton=10 yoffset buttonWidth buttonHeight -globaloptions_savepath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 10) kLineHeight -yoffset=(yoffset + buttonHeight + 8) -globaloptions_extrabutton=10 yoffset buttonWidth buttonHeight -globaloptions_extrapath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 10) kLineHeight -yoffset=(yoffset + buttonHeight + 8) -globaloptions_themebutton=10 yoffset buttonWidth buttonHeight -globaloptions_themepath=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 10) kLineHeight -yoffset=(yoffset + buttonHeight + 12) -globaloptions_keysbutton=5 yoffset buttonWidth buttonHeight +globaloptions_savebutton=xBorder yoffset buttonWidth buttonHeight +globaloptions_savepath=(prev.x2 + xSeparation) (yoffset + glOff) (parent.w - self.x - xBorder) kLineHeight +yoffset=(yoffset + buttonHeight + ySeparation) +globaloptions_extrabutton=xBorder yoffset buttonWidth buttonHeight +globaloptions_extrapath=(prev.x2 + xSeparation) (yoffset + glOff) (parent.w - self.x - xBorder) kLineHeight +yoffset=(yoffset + buttonHeight + ySeparation) +globaloptions_themebutton=xBorder yoffset buttonWidth buttonHeight +globaloptions_themepath=(prev.x2 + xSeparation) (yoffset + glOff) (parent.w - self.x - xBorder) kLineHeight +yoffset=(yoffset + buttonHeight + ySeparation) +globaloptions_keysbutton=xBorder yoffset buttonWidth buttonHeight # Misc options yoffset=vBorder glOff=((buttonHeight - kLineHeight) / 2 + 2) -globaloptions_themebutton2=10 yoffset buttonWidth buttonHeight -globaloptions_curtheme=(prev.x2 + 20) (yoffset + glOff) (parent.w - (prev.w + 20) - 10) kLineHeight -yoffset=(yoffset + buttonHeight + 12) -globaloptions_autosaveperiod=10 yoffset (parent.w - 10 - 25) kPopUpHeight +globaloptions_themebutton2=xBorder yoffset buttonWidth buttonHeight +globaloptions_curtheme=(prev.x2 + xSeparation) (yoffset + glOff) (parent.w - self.x - xBorder) kLineHeight +yoffset=(yoffset + buttonHeight + ySeparation) +globaloptions_autosaveperiod=xBorder yoffset (parent.w - self.x - xBorder) kPopUpHeight -globaloptions_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -globaloptions_ok=(prev.x2 + 10) prev.y prev.w prev.h +globaloptions_cancel=(parent.w - 2 * buttonWidth - xSeparation - xBorder) (parent.h - buttonHeight - 8) buttonWidth buttonHeight +globaloptions_ok=(prev.x2 + xSeparation) prev.y prev.w prev.h ### game options gameoptions=insetX insetY insetW insetH set_parent=gameoptions vBorder=gameOptionsOverrideVPad -gox=10 -gow=(parent.w - gox - 25) +gox=xBorder +gow=(parent.w - gox - xBorder) -gameoptions_tabwidget=0 0 parent.w (parent.h - buttonHeight - 16) +gameoptions_tabwidget=0 0 parent.w (parent.h - buttonHeight - 8 - ySeparation) # game tab opYoffset=optionsVPad -gameoptions_id=gox (opYoffset + 2) gameOptionsLabelWidth kLineHeight +glOff=((kPopUpHeight - kLineHeight) / 2 + 2) +gameoptions_id=gox (opYoffset + glOff) optionsLabelWidth kLineHeight gameoptions_id.align=kTextAlignRight -gameoptions_domain=prev.x2 (prev.y - 1) (gow - prev.w) kPopUpHeight -opYoffset=(opYoffset + kLineHeight + 12) -gameoptions_name=gox (opYoffset + 2) gameOptionsLabelWidth kLineHeight +gameoptions_domain=(prev.x2 + xSeparation) opYoffset (parent.w - self.x - xBorder) kPopUpHeight +opYoffset=(opYoffset + prev.h + ySeparation) +gameoptions_name=gox (opYoffset + glOff) optionsLabelWidth kLineHeight gameoptions_name.align=kTextAlignRight -gameoptions_desc=prev.x2 (prev.y - 1) (gow - prev.w) kPopUpHeight -opYoffset=(opYoffset + kLineHeight + 15) -gameoptions_lang=gox (opYoffset - 1) gow kPopUpHeight -opYoffset=(opYoffset + kLineHeight + 12) +gameoptions_desc=(prev.x2 + xSeparation) opYoffset (parent.w - self.x - xBorder) kPopUpHeight +opYoffset=(opYoffset + prev.h + ySeparation) +gameoptions_lang=gox opYoffset (parent.w - self.x - xBorder) kPopUpHeight +opYoffset=(opYoffset + prev.h + ySeparation) gameoptions_platform=prev.x opYoffset prev.w prev.h -opYoffset=(opYoffset + kLineHeight + 8) +opYoffset=(opYoffset + prev.h + ySeparation) # paths tab opYoffset=optionsVPad goOff=((buttonHeight - kLineHeight) / 2 + 2) gameoptions_savepath=gox opYoffset buttonWidth buttonHeight -gameoptions_savepathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight -opYoffset=(opYoffset + buttonHeight + 8) +gameoptions_savepathText=(prev.x2 + xSeparation) (opYoffset + goOff) (parent.w - self.x - xBorder) kLineHeight +opYoffset=(opYoffset + buttonHeight + ySeparation) gameoptions_extrapath=gox opYoffset buttonWidth buttonHeight -gameoptions_extrapathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight -opYoffset=(opYoffset + buttonHeight + 8) +gameoptions_extrapathText=(prev.x2 + xSeparation) (opYoffset + goOff) (parent.w - self.x - xBorder) kLineHeight +opYoffset=(opYoffset + buttonHeight + ySeparation) gameoptions_gamepath=gox opYoffset buttonWidth buttonHeight -gameoptions_gamepathText=(prev.x2 + 20) (opYoffset + goOff) (parent.w - self.x - 10) kLineHeight -opYoffset=(opYoffset + buttonHeight + 8) +gameoptions_gamepathText=(prev.x2 + xSeparation) (opYoffset + goOff) (parent.w - self.x - xBorder) kLineHeight +opYoffset=(opYoffset + buttonHeight + ySeparation) # graphics tab opYoffset=vBorder opXoffset=gox -gameoptions_graphicsCheckbox=gox opYoffset (kFontHeight + 10 + 192) buttonHeight -opYoffset=(opYoffset + buttonHeight + 6) +gameoptions_graphicsCheckbox=gox opYoffset (parent.w - gox - xBorder) buttonHeight +opYoffset=(prev.y2 + ySeparation) useWithPrefix=graphicsControls gameoptions_ # audio tab opYoffset=vBorder -gameoptions_audioCheckbox=gox opYoffset (kFontHeight + 10 + 180) buttonHeight -opYoffset=(opYoffset + buttonHeight + 6) +gameoptions_audioCheckbox=gox opYoffset (parent.w - gox - xBorder) buttonHeight +opYoffset=(prev.y2 + ySeparation) useWithPrefix=audioControls gameoptions_ useWithPrefix=subtitleControls gameoptions_ # volume tab opYoffset=vBorder -gameoptions_volumeCheckbox=gox opYoffset (kFontHeight + 10 + 180) buttonHeight -opYoffset=(opYoffset + buttonHeight + 6) +gameoptions_volumeCheckbox=gox opYoffset (parent.w - gox - xBorder) buttonHeight +opYoffset=(prev.y2 + ySeparation) useWithPrefix=volumeControls gameoptions_ # midi tab opYoffset=vBorder -gameoptions_midiCheckbox=gox opYoffset (kFontHeight + 10 + 174) buttonHeight -opYoffset=(opYoffset + buttonHeight + 6) +gameoptions_midiCheckbox=gox opYoffset (parent.w - gox - xBorder) buttonHeight +opYoffset=(prev.y2 + ySeparation) useWithPrefix=midiControls gameoptions_ -gameoptions_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -gameoptions_ok=(prev.x2 + 10) prev.y prev.w prev.h +gameoptions_cancel=(parent.w - 2 * buttonWidth - xSeparation - xBorder) (parent.h - buttonHeight - 8) buttonWidth buttonHeight +gameoptions_ok=(prev.x2 + xSeparation) prev.y prev.w prev.h ### keys dialog keysdialog=(w / 20) (h / 10) (w - w / 10) (h - h / 5) @@ -386,14 +390,14 @@ keysdialog_mapping.align=kTextAlignCenter ### mass add dialog massadddialog=10 20 300 174 set_parent=massadddialog -massadddialog_caption=10 (10 + 1 * kLineHeight) (parent.w - 2*10) kLineHeight +massadddialog_caption=xBorder (10 + 1 * kLineHeight) (parent.w - 2 * xBorder) kLineHeight massadddialog_caption.align=kTextAlignCenter -massadddialog_dirprogress=10 (10 + 3 * kLineHeight) prev.w prev.h +massadddialog_dirprogress=xBorder (10 + 3 * kLineHeight) prev.w prev.h massadddialog_dirprogress.align=kTextAlignCenter -massadddialog_gameprogress=10 (10 + 4 * kLineHeight) prev.w prev.h +massadddialog_gameprogress=xBorder (10 + 4 * kLineHeight) prev.w prev.h massadddialog_gameprogress.align=kTextAlignCenter -massadddialog_ok=((parent.w - (buttonWidth * 2)) / 2) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -massadddialog_cancel=(prev.x2 + 10) prev.y prev.w prev.h +massadddialog_ok=((parent.w - (buttonWidth * 2) - xSeparation) / 2) (parent.h - buttonHeight - ySeparation) buttonWidth buttonHeight +massadddialog_cancel=(prev.x2 + xSeparation) prev.y prev.w prev.h ##### SCUMM dialogs @@ -455,95 +459,93 @@ scummsaveload_extinfo.visible=true [chooser] chooserW=insetW chooser=insetX insetY chooserW opHeight -chooser_headline=10 6 (chooserW - 2 * 10) (kLineHeight) -chooser_list=10 (6 + kLineHeight + 2) prev.w (opHeight - self.y - buttonHeight - 12) -chooser_cancel=(chooserW - 2 * (buttonWidth + 10)) (opHeight - buttonHeight - 8) buttonWidth buttonHeight -chooser_ok=(prev.x2 + 10) prev.y prev.w prev.h +chooser_headline=xBorder 6 (chooserW - 2 * xBorder) kLineHeight +chooser_list=prev.x (prev.y2 + 2) prev.w (opHeight - self.y - buttonHeight - 12) +#JVPRAT: next Y doesn't seem right +chooser_cancel=(chooserW - 2 * buttonWidth - xSeparation - xBorder) (opHeight - buttonHeight - 8) buttonWidth buttonHeight +chooser_ok=(prev.x2 + xSeparation) prev.y prev.w prev.h [browser] browser=insetX insetY insetW insetH set_parent=browser -browser_headline=10 5 (parent.w - 2 * 10) kLineHeight +browser_headline=xBorder 5 (parent.w - 2 * xBorder) kLineHeight browser_headline.align=kTextAlignCenter -browser_path=10 (prev.y2 + 5) prev.w prev.h -browser_list=10 prev.y2 prev.w (parent.h - 3 * kLineHeight - buttonHeight - 14) -browser_up=10 (parent.h - buttonHeight - 8) buttonWidth buttonHeight -browser_cancel=(parent.w - 2 * (buttonWidth + 10)) (parent.h - buttonHeight - 8) buttonWidth buttonHeight -browser_choose=(prev.x2 + 10) prev.y prev.w prev.h +browser_path=prev.x (prev.y2 + 5) prev.w prev.h +browser_list=prev.x prev.y2 prev.w (parent.h - 3 * kLineHeight - buttonHeight - 14) +browser_up=prev.x (parent.h - buttonHeight - 8) buttonWidth buttonHeight +#JVPRAT: doesn't it lack insetx?: +browser_cancel=(parent.w - 2 * buttonWidth - xSeparation - xBorder) (parent.h - buttonHeight - 8) buttonWidth buttonHeight +browser_choose=(prev.x2 + xSeparation) prev.y prev.w prev.h [graphicsControls] -gcx=(opXoffset + 10) -gcw=(parent.w - gcx - 25) -grModePopup=(gcx - 5) (opYoffset - 1) (gcw + 5) kPopUpHeight -opYoffset=(opYoffset + kLineHeight + 12) +gcx=(opXoffset + xBorder) +grModePopup=gcx opYoffset (parent.w - self.x - xBorder) kPopUpHeight +opYoffset=(prev.y2 + ySeparation) grRenderPopup=prev.x (opYoffset - 1) prev.w prev.h -opYoffset=(opYoffset + kLineHeight + 16) -grFullscreenCheckbox=gcx opYoffset (kFontHeight + 10 + 96) buttonHeight -opYoffset=(opYoffset + buttonHeight + 4) -grAspectCheckbox=prev.x opYoffset (kFontHeight + 10 + 136) prev.h -opYoffset=(opYoffset + buttonHeight + 4) +opYoffset=(prev.y2 + ySeparation) +grFullscreenCheckbox=gcx opYoffset (parent.w - gcx - xBorder) kLineHeight +opYoffset=(prev.y2 + ySeparation) +grAspectCheckbox=prev.x opYoffset prev.w prev.h +opYoffset=(prev.y2 + ySeparation) [audioControls] -aux=(opXoffset + 10) -auw=(parent.w - aux - 30) -auMidiPopup=(aux) (opYoffset - 1) (auw + 5) kPopUpHeight -opYoffset=(opYoffset + buttonHeight + 4) -auSampleRatePopup=(aux) (opYoffset - 1) (auw + 5) kPopUpHeight -opYoffset=(opYoffset + buttonHeight + 4) +aux=(opXoffset + xBorder) +auMidiPopup=aux opYoffset (parent.w - self.x - xBorder) kPopUpHeight +opYoffset=(opYoffset + prev.h + ySeparation) +auSampleRatePopup=aux (opYoffset - 1) prev.w kPopUpHeight +opYoffset=(opYoffset + prev.h + ySeparation) [volumeControls] -vctextw=110 -vcxoff=(opXoffset + vctextw + 10) -vcx=(opXoffset + 10) -vcMusicText=vcx (opYoffset + 2) vctextw kLineHeight +vcx=(opXoffset + xBorder) +vcOff=((sliderHeight - kLineHeight) / 2 + 2) +vcMusicText=vcx (opYoffset + vcOff) optionsLabelWidth kLineHeight vcMusicText.align=kTextAlignRight -vcMusicSlider=vcxoff opYoffset sliderWidth sliderHeight -vcMusicLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + 8) -vcSfxText=vcx (opYoffset + 2) vctextw kLineHeight +vcMusicSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight +vcMusicLabel=(prev.x2 + xSeparation) (opYoffset + vcOff) 24 kLineHeight +opYoffset=(opYoffset + sliderHeight + ySeparation) +vcSfxText=vcx (opYoffset + vcOff) optionsLabelWidth kLineHeight vcSfxText.align=kTextAlignRight -vcSfxSlider=vcxoff opYoffset sliderWidth sliderHeight -vcSfxLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + 8) -vcSpeechText=vcx (opYoffset + 2) vctextw kLineHeight +vcSfxSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight +vcSfxLabel=(prev.x2 + xSeparation) (opYoffset + vcOff) 24 kLineHeight +opYoffset=(opYoffset + sliderHeight + ySeparation) +vcSpeechText=vcx (opYoffset + vcOff) optionsLabelWidth kLineHeight vcSpeechText.align=kTextAlignRight -vcSpeechSlider=vcxoff opYoffset sliderWidth sliderHeight -vcSpeechLabel=(vcxoff + prev.w + 10) (opYoffset + 2) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + 12) +vcSpeechSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight +vcSpeechLabel=(prev.x2 + xSeparation) (opYoffset + vcOff) 24 kLineHeight +opYoffset=(opYoffset + sliderHeight + ySeparation) [midiControls] -mcx=(opXoffset + 10) +mcx=(opXoffset + xBorder) mcOff=((buttonHeight - kLineHeight) / 2 + 2) mcFontButton=mcx opYoffset buttonWidth buttonHeight -mcFontPath=(prev.x2 + 20) (opYoffset + mcOff) (parent.w - (buttonWidth + 20) - mcx - kLineHeight - 20) kLineHeight -mcFontClearButton=(prev.x2 + 10) (opYoffset + mcOff) kLineHeight kLineHeight -opYoffset=(opYoffset + buttonHeight + 6 * midiControlsSpacing) -mcMixedCheckbox=mcx opYoffset (kFontHeight + 10 + 135) buttonHeight -opYoffset=(opYoffset + buttonHeight + midiControlsSpacing) -mcMt32Checkbox=mcx opYoffset (kFontHeight + 10 + 256) buttonHeight -opYoffset=(opYoffset + buttonHeight + midiControlsSpacing) -mcGSCheckbox=mcx opYoffset (kFontHeight + 10 + 142) buttonHeight -opYoffset=(opYoffset + buttonHeight + midiControlsSpacing) -mcMidiGainText=mcx (opYoffset + 2) 80 kLineHeight +mcFontPath=(prev.x2 + xSeparation) (opYoffset + mcOff) (parent.w - self.x - xSeparation - kLineHeight - xBorder) kLineHeight +mcFontClearButton=(prev.x2 + xSeparation) prev.y kLineHeight kLineHeight +opYoffset=(opYoffset + buttonHeight + ySeparation) +mcMixedCheckbox=mcx opYoffset (parent.w - self.x - xBorder) kLineHeight +opYoffset=(opYoffset + prev.h + ySeparation) +mcMt32Checkbox=mcx opYoffset prev.w kLineHeight +opYoffset=(opYoffset + prev.h + ySeparation) +mcGSCheckbox=mcx opYoffset prev.w kLineHeight +opYoffset=(opYoffset + prev.h + ySeparation) +mcOff=((sliderHeight - kLineHeight) / 2 + 2) +mcMidiGainText=mcx (opYoffset + mcOff) optionsLabelWidth kLineHeight mcMidiGainText.align=kTextAlignRight -mcMidiGainSlider=(prev.x2 + 10) opYoffset sliderWidth sliderHeight -mcMidiGainLabel=(prev.x2 + 10) (opYoffset + 2) 40 kLineHeight -opYoffset=(opYoffset + sliderHeight + midiControlsSpacing) +mcMidiGainSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight +mcMidiGainLabel=(prev.x2 + xSeparation) (opYoffset + mcOff) 40 kLineHeight +opYoffset=(opYoffset + sliderHeight + ySeparation) [subtitleControls] -sbx=(opXoffset + 10) -sbtextw=110 -sbYoff=(buttonHeight / 8) -sbOff=((sliderHeight - kLineHeight) / 2) -opYoffset=(opYoffset + sbYoff) -subToggleDesc=sbx (opYoffset + sbYoff) sbtextw buttonHeight -subToggleButton=prev.x2 opYoffset (buttonWidth + 34) sliderHeight -opYoffset=(opYoffset + buttonHeight + 6) -subSubtitleSpeedDesc=sbx (opYoffset + sbOff) sbtextw kLineHeight +sbx=(opXoffset + xBorder) +sbOff=((sliderHeight - kLineHeight) / 2 + 2) +subToggleDesc=sbx (opYoffset + sbOff) optionsLabelWidth kLineHeight +subToggleDesc.align=kTextAlignRight +subToggleButton=(prev.x2 + xSeparation) opYoffset (buttonWidth + 34) sliderHeight +opYoffset=(prev.y2 + ySeparation) +subSubtitleSpeedDesc=sbx (opYoffset + sbOff) optionsLabelWidth kLineHeight subSubtitleSpeedDesc.align=kTextAlignRight -subSubtitleSpeedSlider=prev.x2 opYoffset sliderWidth sliderHeight -subSubtitleSpeedLabel=(prev.x2 + 10) (opYoffset + sbOff) 24 kLineHeight -opYoffset=(opYoffset + sliderHeight + 8) +subSubtitleSpeedSlider=(prev.x2 + xSeparation) opYoffset sliderWidth sliderHeight +subSubtitleSpeedLabel=(prev.x2 + xSeparation) (opYoffset + sbOff) 24 kLineHeight +opYoffset=(opYoffset + sliderHeight + ySeparation) [scummmain] ## Main dialog @@ -592,7 +594,6 @@ def_insetW=(w - buttonWidth - 17 * 2 - insetX) def_insetH=(h - 13 - insetY) def_launcherVersionX=50 def_launcherVersionY=5 -def_midiControlsSpacing=2 def_gameOptionsOverrideVPad=10 def_aboutXOff=3 def_aboutYOff=2 diff --git a/gui/widget.h b/gui/widget.h index bf15081f79..c19059d32c 100644 --- a/gui/widget.h +++ b/gui/widget.h @@ -27,6 +27,7 @@ #include "common/scummsys.h" #include "common/str.h" +#include "common/keyboard.h" #include "graphics/font.h" #include "graphics/surface.h" #include "gui/object.h" @@ -127,8 +128,8 @@ public: virtual void handleMouseLeft(int button) {} virtual void handleMouseMoved(int x, int y, int button) {} virtual void handleMouseWheel(int x, int y, int direction) {} - virtual bool handleKeyDown(uint16 ascii, int keycode, int modifiers) { return false; } // Return true if the event was handled - virtual bool handleKeyUp(uint16 ascii, int keycode, int modifiers) { return false; } // Return true if the event was handled + virtual bool handleKeyDown(Common::KeyState state) { return false; } // Return true if the event was handled + virtual bool handleKeyUp(Common::KeyState state) { return false; } // Return true if the event was handled virtual void handleTickle() {} virtual void reflowLayout() { GuiObject::reflowLayout(); } diff --git a/sound/audiostream.cpp b/sound/audiostream.cpp index eba02c74f3..6a04da5f43 100644 --- a/sound/audiostream.cpp +++ b/sound/audiostream.cpp @@ -156,21 +156,21 @@ public: template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> int LinearMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16 *buffer, const int numSamples) { - int samples = 0; - while (samples < numSamples && _ptr < _end) { - const int len = MIN(numSamples, samples + (int)(_end - _ptr) / (is16Bit ? 2 : 1)); - while (samples < len) { + int samples = numSamples; + while (samples > 0 && _ptr < _end) { + int len = MIN(samples, (int)(_end - _ptr) / (is16Bit ? 2 : 1)); + samples -= len; + do { *buffer++ = READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, _ptr, isLE); _ptr += (is16Bit ? 2 : 1); - samples++; - } + } while (--len); // Loop, if looping was specified if (_loopPtr && _ptr >= _end) { _ptr = _loopPtr; _end = _loopEnd; } } - return samples; + return numSamples-samples; } @@ -209,7 +209,7 @@ AudioStream *makeLinearInputStream(const byte *ptr, uint32 len, int rate, byte f loopEnd = len; assert(loopStart <= loopEnd); assert(loopEnd <= len); - + loopOffset = loopStart; loopLen = loopEnd - loopStart; } @@ -250,7 +250,7 @@ protected: // the linked list) in thread aware environments. Common::Mutex _mutex; - // List of all queueud buffers + // List of all queued buffers Common::List<Buffer> _bufferQueue; // Position in the front buffer, if any @@ -292,8 +292,8 @@ template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> int AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16 *buffer, const int numSamples) { Common::StackLock lock(_mutex); - int samples = 0; - while (samples < numSamples && !eosIntern()) { + int samples = numSamples; + while (samples > 0 && !eosIntern()) { Buffer buf = *_bufferQueue.begin(); if (_pos == 0) _pos = buf.start; @@ -307,15 +307,15 @@ int AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16 continue; } - const int len = MIN(numSamples, samples + samplesLeftInCurBuffer / (is16Bit ? 2 : 1)); - while (samples < len) { + int len = MIN(samples, samplesLeftInCurBuffer / (is16Bit ? 2 : 1)); + samples -= len; + do { *buffer++ = READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, _pos, isLE); _pos += (is16Bit ? 2 : 1); - samples++; - } + } while (--len); } - return samples; + return numSamples-samples; } template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> diff --git a/sound/mididrv.cpp b/sound/mididrv.cpp index a23e277f81..658ebfa457 100644 --- a/sound/mididrv.cpp +++ b/sound/mididrv.cpp @@ -37,7 +37,7 @@ static const MidiDriverDescription s_musicDrivers[] = { // The flags for the "auto" & "null" drivers indicate that they are anything // you want it to be. - {"auto", "Default", MD_AUTO, MDT_MIDI | MDT_PCSPK | MDT_ADLIB | MDT_TOWNS}, + {"auto", "<default>", MD_AUTO, MDT_MIDI | MDT_PCSPK | MDT_ADLIB | MDT_TOWNS}, {"null", "No music", MD_NULL, MDT_MIDI | MDT_PCSPK | MDT_ADLIB | MDT_TOWNS}, #if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) diff --git a/sound/mixer.cpp b/sound/mixer.cpp index cc353d58b4..4ca7b4c897 100644 --- a/sound/mixer.cpp +++ b/sound/mixer.cpp @@ -54,7 +54,7 @@ private: bool _permanent; byte _volume; int8 _balance; - bool _paused; + int _pauseLevel; int _id; uint32 _samplesConsumed; uint32 _samplesDecoded; @@ -77,10 +77,15 @@ public: return _input->endOfStream(); } void pause(bool paused) { - _paused = paused; + assert((paused && _pauseLevel >= 0) || (!paused && _pauseLevel)); + + if (paused) + _pauseLevel++; + else + _pauseLevel--; } bool isPaused() { - return _paused; + return _pauseLevel != 0; } void setVolume(const byte volume) { _volume = volume; @@ -375,7 +380,7 @@ int Mixer::getVolumeForSoundType(SoundType type) const { Channel::Channel(Mixer *mixer, Mixer::SoundType type, AudioStream *input, bool autofreeStream, bool reverseStereo, int id, bool permanent) : _type(type), _mixer(mixer), _autofreeStream(autofreeStream), - _volume(Mixer::kMaxChannelVolume), _balance(0), _paused(false), _id(id), _samplesConsumed(0), + _volume(Mixer::kMaxChannelVolume), _balance(0), _pauseLevel(0), _id(id), _samplesConsumed(0), _samplesDecoded(0), _mixerTimeStamp(0), _converter(0), _input(input), _permanent(permanent) { assert(mixer); assert(input); diff --git a/sound/mods/infogrames.cpp b/sound/mods/infogrames.cpp index b577049657..3f607d213e 100644 --- a/sound/mods/infogrames.cpp +++ b/sound/mods/infogrames.cpp @@ -171,7 +171,7 @@ void Infogrames::init() { _chn[i].periodMod = 0; } - _end = _data == 0; + _end = (_data == 0); } void Infogrames::reset() { @@ -231,8 +231,7 @@ bool Infogrames::load(Common::SeekableReadStream &dum) { (_cmdBlocks > (_data + size))) return false; - _end = false; - _playing = true; + startPaula(); return true; } @@ -244,8 +243,6 @@ void Infogrames::unload(void) { clearVoices(); reset(); - - _end = true; } void Infogrames::getNextSample(Channel &chn) { @@ -427,15 +424,14 @@ void Infogrames::interrupt() { _volume = 0; _period = 0; getNextSample(_chn[chn]); - _voice[chn].volume = _volume; - _voice[chn].period = _period; + setChannelVolume(chn, _volume); + setChannelPeriod(chn, _period); if ((_sample != 0xFF) && (_sample < _instruments->_count)) { - _voice[chn].data = _instruments->_samples[_sample].data; - _voice[chn].length = _instruments->_samples[_sample].length; - _voice[chn].dataRepeat = _instruments->_samples[_sample].dataRepeat; - _voice[chn].lengthRepeat = - _instruments->_samples[_sample].lengthRepeat; - _voice[chn].offset = 0; + setChannelData(chn, + _instruments->_samples[_sample].data, + _instruments->_samples[_sample].dataRepeat, + _instruments->_samples[_sample].length, + _instruments->_samples[_sample].lengthRepeat); _sample = 0xFF; } } @@ -449,8 +445,7 @@ void Infogrames::interrupt() { _repCount--; init(); } else if (_repCount != -1) { - _end = true; - _playing = false; + stopPaula(); } else { init(); } diff --git a/sound/mods/infogrames.h b/sound/mods/infogrames.h index 7220c2bf9a..572c5a6426 100644 --- a/sound/mods/infogrames.h +++ b/sound/mods/infogrames.h @@ -80,14 +80,6 @@ public: Instruments *getInstruments(void) const { return _instruments; } bool getRepeating(void) const { return _repCount != 0; } void setRepeating (int32 repCount) { _repCount = repCount; } - virtual void startPlay(void) { _playing = true;} - virtual void stopPlay(void) - { - _mutex.lock(); - _playing = false; - _mutex.unlock(); - } - virtual void pausePlay(bool pause) { _playing = !pause; } bool load(Common::SeekableReadStream &dum); bool load(const char *dum) { @@ -98,7 +90,16 @@ public: return false; } void unload(void); - void restart(void) { if (_data) { stopPlay(); init(); startPlay(); } } + void restart(void) { + if (_data) { + // Use the mutex here to ensure we do not call init() + // while data is being read by the mixer thread. + _mutex.lock(); + init(); + startPlay(); + _mutex.unlock(); + } + } protected: Instruments *_instruments; diff --git a/sound/mods/module.h b/sound/mods/module.h index b25fe87b41..041eebc269 100644 --- a/sound/mods/module.h +++ b/sound/mods/module.h @@ -37,7 +37,7 @@ struct note_t { byte note; uint16 period; uint16 effect; -}; +} PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/sound/mods/paula.cpp b/sound/mods/paula.cpp index 53b8f867ea..cfd9ebff11 100644 --- a/sound/mods/paula.cpp +++ b/sound/mods/paula.cpp @@ -29,7 +29,6 @@ namespace Audio { Paula::Paula(bool stereo, int rate, int interruptFreq) : _stereo(stereo), _rate(rate), _intFreq(interruptFreq) { - _playing = false; clearVoices(); _voice[0].panning = 63; @@ -41,6 +40,7 @@ Paula::Paula(bool stereo, int rate, int interruptFreq) : _intFreq = _rate; _curInt = _intFreq; + _playing = false; _end = true; } @@ -60,16 +60,6 @@ void Paula::clearVoice(byte voice) { } int Paula::readBuffer(int16 *buffer, const int numSamples) { - int voice; - int samples; - int nSamples; - int sLen; - double frequency; - double rate; - double offset; - int16 *p; - const int8 *data; - Common::StackLock lock(_mutex); memset(buffer, 0, numSamples * 2); @@ -77,87 +67,106 @@ int Paula::readBuffer(int16 *buffer, const int numSamples) { return numSamples; } - samples = _stereo ? numSamples / 2 : numSamples; + if (_stereo) + return readBufferIntern<true>(buffer, numSamples); + else + return readBufferIntern<false>(buffer, numSamples); +} + + +template<bool stereo> +inline void mixBuffer(int16 *&buf, const int8 *data, frac_t &offset, frac_t rate, int end, byte volume, byte panning) { + for (int i = 0; i < end; i++) { + const int32 tmp = ((int32) data[fracToInt(offset)]) * volume; + if (stereo) { + *buf++ += (tmp * (255 - panning)) >> 7; + *buf++ += (tmp * (panning)) >> 7; + } else + *buf++ += tmp; + + offset += rate; + } +} + +template<bool stereo> +int Paula::readBufferIntern(int16 *buffer, const int numSamples) { + int samples = _stereo ? numSamples / 2 : numSamples; while (samples > 0) { + + // Handle 'interrupts'. This gives subclasses the chance to adjust the channel data + // (e.g. insert new samples, do pitch bending, whatever). if (_curInt == _intFreq) { interrupt(); _curInt = 0; } - nSamples = MIN(samples, _intFreq - _curInt); - for (voice = 0; voice < NUM_VOICES; voice++) { + + // Compute how many samples to generate: at most the requested number of samples, + // of course, but we may stop earlier when an 'interrupt' is expected. + const int nSamples = MIN(samples, _intFreq - _curInt); + + // Loop over the four channels of the emulated Paula chip + for (int voice = 0; voice < NUM_VOICES; voice++) { + + // No data, or paused -> skip channel if (!_voice[voice].data || (_voice[voice].period <= 0)) continue; - frequency = (7093789.2 / 2.0) / _voice[voice].period; - rate = frequency / _rate; - offset = _voice[voice].offset; - sLen = _voice[voice].length; - data = _voice[voice].data; - p = buffer; + // The Paula chip apparently run at 7.0937892 MHz. We combine this with + // the requested output sampling rate (typicall 44.1 kHz or 22.05 kHz) + // as well as the "period" of the channel we are processing right now, + // to compute the correct output 'rate'. + const double frequency = (7093789.2 / 2.0) / _voice[voice].period; + frac_t rate = doubleToFrac(frequency / _rate); + // Cap the volume _voice[voice].volume = MIN((byte) 0x40, _voice[voice].volume); - if ((_voice[voice].lengthRepeat > 2) && - ((int)(offset + nSamples * rate) >= sLen)) { - int neededSamples = nSamples; - - int end = (int)((sLen - offset) / rate); - for (int i = 0; i < end; i++) - mix(p, data[(int)(offset + rate * i)], voice); - - _voice[voice].length = sLen = _voice[voice].lengthRepeat; + // Cache some data (helps the compiler to optimize the code, by + // indirectly telling it that no data aliasing can occur). + frac_t offset = _voice[voice].offset; + frac_t sLen = intToFrac(_voice[voice].length); + const int8 *data = _voice[voice].data; + int16 *p = buffer; + int end = 0; + int neededSamples = nSamples; + + // Compute the number of samples to generate; that is, either generate + // just as many as were requested, or until the buffer is used up. + // Note that dividing two frac_t yields an integer (as the denominators + // cancel out each other). + // Note that 'end' could be 0 here. No harm in that :-). + end = MIN(neededSamples, (int)((sLen - offset + rate - 1) / rate)); + mixBuffer<stereo>(p, data, offset, rate, end, _voice[voice].volume, _voice[voice].panning); + neededSamples -= end; + + // If we have not yet generated enough samples, and looping is active: loop! + if (neededSamples > 0 && _voice[voice].lengthRepeat > 2) { + + // At this point we know that we have used up all samples in the buffer, so reset it. _voice[voice].data = data = _voice[voice].dataRepeat; - _voice[voice].offset = offset = 0; - neededSamples -= end; + _voice[voice].length = _voice[voice].lengthRepeat; + sLen = intToFrac(_voice[voice].length); + + // If the "rate" exceeds the sample rate, we would have to perform constant + // wrap arounds. So, apply the first step of the euclidean algorithm to + // achieve the same more efficiently: Take rate modulo sLen + if (sLen < rate) + rate %= sLen; + // Repeat as long as necessary. while (neededSamples > 0) { - if (neededSamples >= (int) ((sLen - offset) / rate)) { - while (rate > (sLen - offset)) - rate -= (sLen - offset); - - end = (int)((sLen - offset) / rate); - - for (int i = 0; i < end; i++) - mix(p, data[(int)(offset + rate * i)], voice); - - _voice[voice].data = data = _voice[voice].dataRepeat; - _voice[voice].length = sLen = - _voice[voice].lengthRepeat; - _voice[voice].offset = offset = 0; - - neededSamples -= end; - } else { - for (int i = 0; i < neededSamples; i++) - mix(p, data[(int)(offset + rate * i)], voice); - _voice[voice].offset += rate * neededSamples; - if (ceil(_voice[voice].offset) >= sLen) { - _voice[voice].data = data = _voice[voice].dataRepeat; - _voice[voice].length = sLen = - _voice[voice].lengthRepeat; - _voice[voice].offset = offset = 0; - } - neededSamples = 0; - } - } - } else { - if (offset < sLen) { - if ((int)(offset + nSamples * rate) >= sLen) { - // The end of the sample is the limiting factor - - int end = (int)((sLen - offset) / rate); - for (int i = 0; i < end; i++) - mix(p, data[(int)(offset + rate * i)], voice); - _voice[voice].offset = sLen; - } else { - // The requested number of samples is the limiting - // factor, not the sample - - for (int i = 0; i < nSamples; i++) - mix(p, data[(int)(offset + rate * i)], voice); - _voice[voice].offset += rate * nSamples; - } + offset = 0; + + // Compute the number of samples to generate (see above) and mix 'em. + end = MIN(neededSamples, (int)((sLen - offset + rate - 1) / rate)); + mixBuffer<stereo>(p, data, offset, rate, end, _voice[voice].volume, _voice[voice].panning); + neededSamples -= end; } } + + // Write back the cached data + _voice[voice].offset = offset; + } buffer += _stereo ? nSamples * 2 : nSamples; _curInt += nSamples; diff --git a/sound/mods/paula.h b/sound/mods/paula.h index 0e89b78db6..e86c05b7f8 100644 --- a/sound/mods/paula.h +++ b/sound/mods/paula.h @@ -27,6 +27,7 @@ #define SOUND_MODS_PAULA_H #include "sound/audiostream.h" +#include "common/frac.h" #include "common/mutex.h" namespace Audio { @@ -45,15 +46,11 @@ public: bool playing() const { return _playing; } void setInterruptFreq(int freq) { _curInt = _intFreq = freq; } - void setPanning(byte voice, byte panning) { - assert(voice < NUM_VOICES); - _voice[voice].panning = panning; - } void clearVoice(byte voice); void clearVoices() { for (int i = 0; i < NUM_VOICES; ++i) clearVoice(i); } - virtual void startPlay(void) {} - virtual void stopPlay(void) {} - virtual void pausePlay(bool pause) {} + void startPlay(void) { _playing = true; } + void stopPlay(void) { _playing = false; } + void pausePlay(bool pause) { _playing = !pause; } // AudioStream API int readBuffer(int16 *buffer, const int numSamples); @@ -69,27 +66,79 @@ protected: uint32 lengthRepeat; int16 period; byte volume; - double offset; + frac_t offset; byte panning; // For stereo mixing: 0 = far left, 255 = far right - } _voice[NUM_VOICES]; + }; - int _rate; - int _intFreq; - int _curInt; - bool _stereo; bool _end; - bool _playing; Common::Mutex _mutex; - void mix(int16 *&buf, int8 data, int voice) { - const int32 tmp = ((int32) data) * _voice[voice].volume; - if (_stereo) { - *buf++ += (tmp * (255 - _voice[voice].panning)) >> 7; - *buf++ += (tmp * (_voice[voice].panning)) >> 7; - } else - *buf++ += tmp; + virtual void interrupt(void) = 0; + + void startPaula() { + _playing = true; + _end = false; + } + + void stopPaula() { + _playing = false; + _end = true; + } + + void setChannelPanning(byte channel, byte panning) { + assert(channel < NUM_VOICES); + _voice[channel].panning = panning; } - virtual void interrupt(void) {} + + void setChannelPeriod(byte channel, int16 period) { + assert(channel < NUM_VOICES); + _voice[channel].period = period; + } + + void setChannelVolume(byte channel, byte volume) { + assert(channel < NUM_VOICES); + _voice[channel].volume = volume; + } + + void setChannelData(uint8 channel, const int8 *data, const int8 *dataRepeat, uint32 length, uint32 lengthRepeat, int32 offset = 0) { + assert(channel < NUM_VOICES); + + // For now, we only support 32k samples, as we use 16bit fixed point arithmetics. + // If this ever turns out to be a problem, we can still enhance this code. + assert(0 <= offset && offset < 32768); + assert(length < 32768); + assert(lengthRepeat < 32768); + + Channel &ch = _voice[channel]; + ch.data = data; + ch.dataRepeat = dataRepeat; + ch.length = length; + ch.lengthRepeat = lengthRepeat; + ch.offset = intToFrac(offset); + } + + void setChannelOffset(byte channel, frac_t offset) { + assert(channel < NUM_VOICES); + assert(0 <= offset); + _voice[channel].offset = offset; + } + + frac_t getChannelOffset(byte channel) { + assert(channel < NUM_VOICES); + return _voice[channel].offset; + } + +private: + Channel _voice[NUM_VOICES]; + + const bool _stereo; + const int _rate; + int _intFreq; + int _curInt; + bool _playing; + + template<bool stereo> + int readBufferIntern(int16 *buffer, const int numSamples); }; } // End of namespace Audio diff --git a/sound/mods/protracker.cpp b/sound/mods/protracker.cpp index 806df85b2b..46ee3aabf7 100644 --- a/sound/mods/protracker.cpp +++ b/sound/mods/protracker.cpp @@ -37,8 +37,6 @@ class ProtrackerStream : public ::Audio::Paula { private: Module _module; - int _rate; - int _tick; int _row; int _pos; @@ -67,7 +65,7 @@ private: struct { byte sample; uint16 period; - double offset; + frac_t offset; byte vol; byte finetune; @@ -95,7 +93,6 @@ public: ProtrackerStream(Common::ReadStream *stream, int rate, bool stereo); private: - void startPlay() { _playing = true; _end = false; } void interrupt(); void doPorta(int track) { @@ -153,7 +150,6 @@ ProtrackerStream::ProtrackerStream(Common::ReadStream *stream, int rate, bool st bool result = _module.load(*stream); assert(result); - _rate = rate; _tick = _row = _pos = 0; _speed = 6; @@ -173,7 +169,7 @@ ProtrackerStream::ProtrackerStream(Common::ReadStream *stream, int rate, bool st memset(_track, 0, sizeof(_track)); - startPlay(); + startPaula(); } void ProtrackerStream::updateRow() { @@ -181,10 +177,10 @@ void ProtrackerStream::updateRow() { _track[track].arpeggio = false; _track[track].vibrato = 0; _track[track].delaySampleTick = 0; - note_t note = + const note_t note = _module.pattern[_module.songpos[_pos]][_row][track]; - int effect = note.effect >> 8; + const int effect = note.effect >> 8; if (note.sample) { if (_track[track].sample != note.sample) { @@ -201,19 +197,18 @@ void ProtrackerStream::updateRow() { _track[track].period = _module.noteToPeriod(note.note, _track[track].finetune); else _track[track].period = note.period; - _track[track].offset = 0.0; + _track[track].offset = 0; } } - int exy = note.effect & 0xff; - if (exy); - int ex = (note.effect >> 4) & 0xf; - int ey = note.effect & 0xf; + const byte exy = note.effect & 0xff; + const byte ex = (note.effect >> 4) & 0xf; + const byte ey = note.effect & 0xf; int vol; switch (effect) { case 0x0: - if (ex || ey) { + if (exy) { _track[track].arpeggio = true; if (note.period) { _track[track].arpeggioNotes[0] = note.note; @@ -233,7 +228,7 @@ void ProtrackerStream::updateRow() { _track[track].portaToNoteSpeed = exy; break; case 0x4: - if (ex || ey) { + if (exy) { _track[track].vibratoSpeed = ex; _track[track].vibratoDepth = ey; } @@ -248,8 +243,8 @@ void ProtrackerStream::updateRow() { break; case 0x9: // Set sample offset if (exy) { - _track[track].offset = exy * 256; - _voice[track].offset = _track[track].offset; + _track[track].offset = intToFrac(exy * 256); + setChannelOffset(track, _track[track].offset); } break; case 0xA: @@ -342,26 +337,22 @@ void ProtrackerStream::updateEffects() { for (int track = 0; track < 4; track++) { _track[track].vibrato = 0; - note_t note = + const note_t note = _module.pattern[_module.songpos[_pos]][_row][track]; - int effect = note.effect >> 8; + const int effect = note.effect >> 8; - int exy = note.effect & 0xff; - int ex = (note.effect >> 4) & 0xf; - int ey = (note.effect) & 0xf; + const int exy = note.effect & 0xff; + const int ex = (note.effect >> 4) & 0xf; + const int ey = (note.effect) & 0xf; switch (effect) { case 0x0: - if (ex || ey) { - if (_tick == 1) - _track[track].period = - _module.noteToPeriod(_track[track].arpeggioNotes[0], - _track[track].finetune); - else - _track[track].period = - _module.noteToPeriod(_track[track].arpeggioNotes[_tick % 3], - _track[track].finetune); + if (exy) { + const int idx = (_tick == 1) ? 0 : (_tick % 3); + _track[track].period = + _module.noteToPeriod(_track[track].arpeggioNotes[idx], + _track[track].finetune); } break; case 0x1: @@ -392,13 +383,13 @@ void ProtrackerStream::updateEffects() { case 0x6: break; // Pattern loop case 0x9: // Retrigger note - if (ey && _tick % ey == 0) - _track[track].offset = 0.0; + if (ey && (_tick % ey) == 0) + _track[track].offset = 0; break; case 0xD: // Delay sample if (_tick == _track[track].delaySampleTick) { _track[track].sample = _track[track].delaySample; - _track[track].offset = 0.0; + _track[track].offset = 0; if (_track[track].sample) _track[track].vol = _module.sample[_track[track].sample - 1].vol; } @@ -412,14 +403,15 @@ void ProtrackerStream::updateEffects() { void ProtrackerStream::interrupt(void) { int track; - for (track = 0; track < 4; track++) - _track[track].offset = _voice[track].offset; - - if (_tick == 0) { - if (_track[track].arpeggio) { + for (track = 0; track < 4; track++) { + _track[track].offset = getChannelOffset(track); + if (_tick == 0 && _track[track].arpeggio) { _track[track].period = _module.noteToPeriod(_track[track].arpeggioNotes[0], _track[track].finetune); } + } + + if (_tick == 0) { if (_hasJumpToPattern) { _hasJumpToPattern = false; _pos = _jumpToPattern; @@ -450,15 +442,16 @@ void ProtrackerStream::interrupt(void) { } for (track = 0; track < 4; track++) { - _voice[track].period = _track[track].period + _track[track].vibrato; - _voice[track].volume = _track[track].vol; + setChannelVolume(track, _track[track].vol); + setChannelPeriod(track, _track[track].period + _track[track].vibrato); if (_track[track].sample) { sample_t &sample = _module.sample[_track[track].sample - 1]; - _voice[track].data = sample.data; - _voice[track].dataRepeat = sample.replen > 2 ? sample.data + sample.repeat : 0; - _voice[track].length = sample.len; - _voice[track].lengthRepeat = sample.replen; - _voice[track].offset = _track[track].offset; + setChannelData(track, + sample.data, + sample.replen > 2 ? sample.data + sample.repeat : 0, + sample.len, + sample.replen, + _track[track].offset); _track[track].sample = 0; } } diff --git a/sound/mods/rjp1.cpp b/sound/mods/rjp1.cpp index ab5d7430be..3f5582de51 100644 --- a/sound/mods/rjp1.cpp +++ b/sound/mods/rjp1.cpp @@ -113,8 +113,6 @@ protected: void stopPaulaChannel(uint8 channel); void setupPaulaChannel(uint8 channel, const int8 *waveData, uint16 offset, uint16 len, uint16 repeatPos, uint16 repeatLen); - void setupPaulaChannelPeriod(uint8 channel, int16 period); - void setPaulaChannelVolume(uint8 channel, uint8 volume); virtual void interrupt(); @@ -202,8 +200,7 @@ void Rjp1::startSong(int song) { } } // "start" Paula audiostream - _playing = true; - _end = false; + startPaula(); } void Rjp1::startSequence(uint8 channelNum, uint8 seqNum) { @@ -351,7 +348,7 @@ void Rjp1::modulatePeriod(Rjp1Channel *channel) { channel->freqInit += channel->freqInc; --channel->freqStep; } - setupPaulaChannelPeriod(channel - _channelsTable, channel->freqInit + channel->modulatePeriodNext); + setChannelPeriod(channel - _channelsTable, channel->freqInit + channel->modulatePeriodNext); } void Rjp1::setupNote(Rjp1Channel *channel, int16 period) { @@ -482,7 +479,7 @@ void Rjp1::modulateVolumeWaveform(Rjp1Channel *channel) { void Rjp1::setVolume(Rjp1Channel *channel) { channel->volume = (channel->volume * channel->volumeScale) / 64; channel->volume = CLIP<int16>(channel->volume, 0, 64); - setPaulaChannelVolume(channel - _channelsTable, channel->volume); + setChannelVolume(channel - _channelsTable, channel->volume); } void Rjp1::stopPaulaChannel(uint8 channel) { @@ -491,23 +488,10 @@ void Rjp1::stopPaulaChannel(uint8 channel) { void Rjp1::setupPaulaChannel(uint8 channel, const int8 *waveData, uint16 offset, uint16 len, uint16 repeatPos, uint16 repeatLen) { if (waveData) { - Channel *ch = &_voice[channel]; - ch->data = waveData; - ch->dataRepeat = waveData + repeatPos * 2; - ch->length = len * 2; - ch->lengthRepeat = repeatLen * 2; - ch->offset = offset * 2; + setChannelData(channel, waveData, waveData + repeatPos * 2, len * 2, repeatLen * 2, offset * 2); } } -void Rjp1::setupPaulaChannelPeriod(uint8 channel, int16 period) { - _voice[channel].period = period; -} - -void Rjp1::setPaulaChannelVolume(uint8 channel, uint8 volume) { - _voice[channel].volume = volume; -} - void Rjp1::interrupt() { for (int i = 0; i < 4; ++i) { _vars.currentChannel = i; diff --git a/sound/mods/soundfx.cpp b/sound/mods/soundfx.cpp index 06104f4838..e60fd8468a 100644 --- a/sound/mods/soundfx.cpp +++ b/sound/mods/soundfx.cpp @@ -63,10 +63,6 @@ protected: void updateEffects(int ch); void handleTick(); - void startPaula(); - void stopPaula(); - void setPaulaChannelPeriod(uint8 channel, int16 period); - void setPaulaChannelVolume(uint8 channel, uint8 volume); void enablePaulaChannel(uint8 channel); void disablePaulaChannel(uint8 channel); void setupPaulaChannel(uint8 channel, const int8 *data, uint16 len, uint16 repeatPos, uint16 repeatLen); @@ -174,7 +170,7 @@ void SoundFx::play() { _curOrder = 0; _ticks = 0; _eventsFreq = CIA_FREQ / _delay; - setInterruptFreq(_rate / _eventsFreq); + setInterruptFreq(getRate() / _eventsFreq); startPaula(); } @@ -202,7 +198,7 @@ void SoundFx::handlePattern(int ch, uint32 pat) { } break; } - setPaulaChannelVolume(ch, volume); + setChannelVolume(ch, volume); } } _effects[ch] = note2; @@ -211,7 +207,7 @@ void SoundFx::handlePattern(int ch, uint32 pat) { } else if (note1 == 0xFFFE) { // STP disablePaulaChannel(ch); } else if (note1 != 0) { - setPaulaChannelPeriod(ch, note1); + setChannelPeriod(ch, note1); enablePaulaChannel(ch); } } @@ -256,39 +252,17 @@ void SoundFx::handleTick() { } } -void SoundFx::startPaula() { - _playing = true; - _end = false; -} - -void SoundFx::stopPaula() { - _playing = false; - _end = true; -} - -void SoundFx::setPaulaChannelPeriod(uint8 channel, int16 period) { - _voice[channel].period = period; -} - -void SoundFx::setPaulaChannelVolume(uint8 channel, uint8 volume) { - _voice[channel].volume = volume; -} - void SoundFx::enablePaulaChannel(uint8 channel) { + // FIXME: Is this empty on purpose?!? } void SoundFx::disablePaulaChannel(uint8 channel) { - _voice[channel].period = 0; + setChannelPeriod(channel, 0); } void SoundFx::setupPaulaChannel(uint8 channel, const int8 *data, uint16 len, uint16 repeatPos, uint16 repeatLen) { if (data && len > 1) { - Channel *ch = &_voice[channel]; - ch->data = data; - ch->dataRepeat = data + repeatPos * 2; - ch->length = len * 2; - ch->lengthRepeat = repeatLen * 2; - ch->offset = 0; + setChannelData(channel, data, data + repeatPos * 2, len * 2, repeatLen * 2); } } diff --git a/sound/rate.cpp b/sound/rate.cpp index 6a51f3d5d5..6e8e83f9a6 100644 --- a/sound/rate.cpp +++ b/sound/rate.cpp @@ -35,15 +35,11 @@ #include "sound/audiostream.h" #include "sound/rate.h" #include "sound/mixer.h" +#include "common/frac.h" #include "common/util.h" namespace Audio { -/** - * The precision of the fractional computations used by the rate converter. - * Normally you should never have to modify this value. - */ -#define FRAC_BITS 16 /** * The size of the intermediate input cache. Bigger values may increase @@ -88,12 +84,8 @@ public: */ template<bool stereo, bool reverseStereo> SimpleRateConverter<stereo, reverseStereo>::SimpleRateConverter(st_rate_t inrate, st_rate_t outrate) { - if (inrate == outrate) { - error("Input and Output rates must be different to use rate effect"); - } - if ((inrate % outrate) != 0) { - error("Input rate must be a multiple of Output rate to use rate effect"); + error("Input rate must be a multiple of output rate to use rate effect"); } if (inrate >= 65536 || outrate >= 65536) { @@ -174,10 +166,10 @@ protected: int inLen; /** fractional position of the output stream in input stream unit */ - long opos, opos_frac; + frac_t opos; /** fractional position increment in the output stream */ - long opos_inc, opos_inc_frac; + frac_t opos_inc; /** last sample(s) in the input stream (left/right channel) */ st_sample_t ilast0, ilast1; @@ -198,24 +190,18 @@ public: */ template<bool stereo, bool reverseStereo> LinearRateConverter<stereo, reverseStereo>::LinearRateConverter(st_rate_t inrate, st_rate_t outrate) { - unsigned long incr; - - if (inrate == outrate) { - error("Input and Output rates must be different to use rate effect"); - } - if (inrate >= 65536 || outrate >= 65536) { error("rate effect can only handle rates < 65536"); } - opos_frac = 0; - opos = 1; - - /* increment */ - incr = (inrate << FRAC_BITS) / outrate; + opos = FRAC_ONE; - opos_inc_frac = incr & ((1UL << FRAC_BITS) - 1); - opos_inc = incr >> FRAC_BITS; + // Compute the linear interpolation increment. + // This will overflow if inrate >= 2^16, and underflow if outrate >= 2^16. + // Also, if the quotient of the two rate becomes too small / too big, that + // would cause problems, but since we rarely scale from 1 to 65536 Hz or vice + // versa, I think we can live with that limiation ;-). + opos_inc = (inrate << FRAC_BITS) / outrate; ilast0 = ilast1 = 0; icur0 = icur1 = 0; @@ -236,8 +222,8 @@ int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp while (obuf < oend) { - // read enough input samples so that opos <= 0 - while (0 <= opos) { + // read enough input samples so that opos < 0 + while (FRAC_ONE <= opos) { // Check if we have to refill the buffer if (inLen == 0) { inPtr = inBuf; @@ -252,17 +238,17 @@ int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp ilast1 = icur1; icur1 = *inPtr++; } - opos--; + opos -= FRAC_ONE; } // Loop as long as the outpos trails behind, and as long as there is // still space in the output buffer. - while (0 > opos && obuf < oend) { + while (opos < FRAC_ONE && obuf < oend) { // interpolate st_sample_t out0, out1; - out0 = (st_sample_t)(ilast0 + (((icur0 - ilast0) * opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS)); + out0 = (st_sample_t)(ilast0 + (((icur0 - ilast0) * opos + FRAC_HALF) >> FRAC_BITS)); out1 = (stereo ? - (st_sample_t)(ilast1 + (((icur1 - ilast1) * opos_frac + (1UL << (FRAC_BITS-1))) >> FRAC_BITS)) : + (st_sample_t)(ilast1 + (((icur1 - ilast1) * opos + FRAC_HALF) >> FRAC_BITS)) : out0); // output left channel @@ -274,9 +260,7 @@ int LinearRateConverter<stereo, reverseStereo>::flow(AudioStream &input, st_samp obuf += 2; // Increment output position - long tmp = opos_frac + opos_inc_frac; - opos += opos_inc + (tmp >> FRAC_BITS); - opos_frac = tmp & ((1UL << FRAC_BITS) - 1); + opos += opos_inc; } } return ST_SUCCESS; @@ -344,38 +328,30 @@ public: #pragma mark - - -/** - * Create and return a RateConverter object for the specified input and output rates. - */ -RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate, bool stereo, bool reverseStereo) { +template<bool stereo, bool reverseStereo> +RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate) { if (inrate != outrate) { if ((inrate % outrate) == 0) { - if (stereo) { - if (reverseStereo) - return new SimpleRateConverter<true, true>(inrate, outrate); - else - return new SimpleRateConverter<true, false>(inrate, outrate); - } else - return new SimpleRateConverter<false, false>(inrate, outrate); + return new SimpleRateConverter<stereo, reverseStereo>(inrate, outrate); } else { - if (stereo) { - if (reverseStereo) - return new LinearRateConverter<true, true>(inrate, outrate); - else - return new LinearRateConverter<true, false>(inrate, outrate); - } else - return new LinearRateConverter<false, false>(inrate, outrate); - } + return new LinearRateConverter<stereo, reverseStereo>(inrate, outrate); + } } else { - if (stereo) { - if (reverseStereo) - return new CopyRateConverter<true, true>(); - else - return new CopyRateConverter<true, false>(); - } else - return new CopyRateConverter<false, false>(); + return new CopyRateConverter<stereo, reverseStereo>(); } } +/** + * Create and return a RateConverter object for the specified input and output rates. + */ +RateConverter *makeRateConverter(st_rate_t inrate, st_rate_t outrate, bool stereo, bool reverseStereo) { + if (stereo) { + if (reverseStereo) + return makeRateConverter<true, true>(inrate, outrate); + else + return makeRateConverter<true, false>(inrate, outrate); + } else + return makeRateConverter<false, false>(inrate, outrate); +} + } // End of namespace Audio diff --git a/sound/rate_arm.cpp b/sound/rate_arm.cpp index 694e213dce..ad8f0519c6 100644 --- a/sound/rate_arm.cpp +++ b/sound/rate_arm.cpp @@ -50,13 +50,18 @@ #include "sound/mixer.h" #include "common/util.h" +//#define DEBUG_RATECONV + namespace Audio { /** * The precision of the fractional computations used by the rate converter. * Normally you should never have to modify this value. + * This stuff is defined in common/frac.h, but we redefine it here as the + * ARM routine we call doesn't respect those definitions. */ #define FRAC_BITS 16 +#define FRAC_ONE (1<<FRAC_BITS) /** * The size of the intermediate input cache. Bigger values may increase @@ -152,6 +157,10 @@ extern "C" void ARM_SimpleRate_R(AudioStream &input, extern "C" int SimpleRate_readFudge(Audio::AudioStream &input, int16 *a, int b) { +#ifdef DEBUG_RATECONV + fprintf(stderr, "Reading ptr=%x n%d\n", a, b); + fflush(stderr); +#endif return input.readBuffer(a, b); } @@ -197,7 +206,7 @@ typedef struct { int inLen; /** position of how far output is ahead of input */ - /** Holds what would have been opos-ipos */ + /** Holds what would have been opos-ipos<<16 + opos_frac */ long opos; /** integer position increment in the output stream */ @@ -206,13 +215,8 @@ typedef struct { /** current sample(s) in the input stream (left/right channel) */ st_sample_t icur[2]; /** last sample(s) in the input stream (left/right channel) */ - st_sample_t ilast[2]; - - /** fractional position in the output stream */ - long opos_frac; - - /** fractional position increment in the output stream */ - long opos_inc_frac; + /** Note, these are deliberately ints, not st_sample_t's */ + int32 ilast[2]; st_sample_t inBuf[INTERMEDIATE_BUFFER_SIZE]; } LinearRateDetails; @@ -270,16 +274,14 @@ LinearRateConverter<stereo, reverseStereo>::LinearRateConverter(st_rate_t inrate error("rate effect can only handle rates < 65536"); } - lr.opos_frac = 0; - lr.opos = 1; + lr.opos = FRAC_ONE; /* increment */ incr = (inrate << FRAC_BITS) / outrate; - lr.opos_inc_frac = incr & ((1UL << FRAC_BITS) - 1); - lr.opos_inc = incr >> FRAC_BITS; + lr.opos_inc = incr; - lr.ilast[0] = lr.ilast[1] = 0; + lr.ilast[0] = lr.ilast[1] = 32768; lr.icur[0] = lr.icur[1] = 0; lr.inLen = 0; diff --git a/sound/rate_arm_asm.s b/sound/rate_arm_asm.s index 709d343c6c..5a9cf5717f 100644 --- a/sound/rate_arm_asm.s +++ b/sound/rate_arm_asm.s @@ -396,6 +396,7 @@ ARM_LinearRate_M: LDMIA r2,{r0,r1,r8} @ r0 = inPtr @ r1 = inLen @ r8 = opos + MOV r10,#0 CMP r11,#0 @ if (osamp <= 0) BLE LinearRate_M_end @ bale ORR r12,r12,r12,LSL #8 @ r12= vol_l as 16 bits @@ -408,29 +409,23 @@ LinearRate_M_loop: SUBS r1, r1, #1 @ r1 = inLen -= 1 BLT LinearRate_M_read LinearRate_M_read_return: - LDR r10,[r2, #16] @ r10= icur[0,1] + LDRH r4, [r2, #16] @ r4 = icur[0] LDRSH r5, [r0],#2 @ r5 = tmp1 = *inPtr++ - SUBS r8, r8, #1 @ r8 = opos-- - STR r10,[r2,#20] @ ilast[0,1] = icur[0,1] + SUBS r8, r8, #65536 @ r8 = opos-- + STRH r4, [r2,#22] @ ilast[0] = icur[0] STRH r5, [r2,#16] @ icur[0] = tmp1 BGE LinearRate_M_loop @ part2 - form output samples LinearRate_M_part2: @ We are guaranteed that opos < 0 here - LDRSH r6, [r2,#20] @ r6 = ilast[0] + LDR r6, [r2,#20] @ r6 = ilast[0]<<16 + 32768 LDRSH r5, [r2,#16] @ r5 = icur[0] - LDRH r4, [r2,#24] @ r4 = opos_frac - LDR r10,[r2,#28] @ r10= opos_frac_inc - MOV r6, r6, LSL #16 @ r6 = ilast[0]<<16 + MOV r4, r8, LSL #16 + MOV r4, r4, LSR #16 SUB r5, r5, r6, ASR #16 @ r5 = icur[0] - ilast[0] - ADD r6, r6, #1<<15 @ r6 = ilast[0]+1<<(FRAC_BITS-1) MLA r6, r4, r5, r6 @ r6 = (icur[0]-ilast[0])*opos_frac+ilast[0] - ADD r4, r4, r10 @ r4 = tmp = opos_frac+opos_inc_frac - STRH r4,[r2,#24] @ opos_frac &= 65535 - ADD r8, r8, r4, LSR #16 @ opos += (tmp>>FRAC_BITS) - LDRSH r4, [r3] @ r4 = obuf[0] LDRSH r5, [r3,#2] @ r5 = obuf[1] MOV r6, r6, ASR #16 @ r6 = tmp0 = tmp1 >>= 16 @@ -438,10 +433,9 @@ LinearRate_M_part2: MUL r6, r14,r6 @ r6 = tmp1*vol_r ADDS r7, r7, r4, LSL #16 @ r7 = obuf[0]<<16 + tmp0*vol_l - MOV r4, #0 - RSCVS r7, r4, #1<<31 @ Clamp r7 + RSCVS r7, r10, #1<<31 @ Clamp r7 ADDS r6, r6, r5, LSL #16 @ r6 = obuf[1]<<16 + tmp1*vol_r - RSCVS r6, r4, #1<<31 @ Clamp r6 + RSCVS r6, r10, #1<<31 @ Clamp r6 MOV r7, r7, LSR #16 @ Shift back to halfword MOV r6, r6, LSR #16 @ Shift back to halfword @@ -449,7 +443,7 @@ LinearRate_M_part2: LDR r5, [r2,#12] @ r5 = opos_inc STRH r7, [r3],#2 @ Store output value STRH r6, [r3],#2 @ Store output value - SUBS r11, r11,#1 @ opos-- + SUBS r11, r11,#1 @ osamp-- BLE LinearRate_M_end @ end if needed ADDS r8, r8, r5 @ r8 = opos += opos_inc @@ -460,7 +454,7 @@ LinearRate_M_end: STMIA r2,{r0,r1,r8} LDMFD r13!,{r4-r11,PC} LinearRate_M_read: - ADD r0, r2, #32 @ r0 = inPtr = inBuf + ADD r0, r2, #28 @ r0 = inPtr = inBuf STMFD r13!,{r0,r2-r3,r12,r14} MOV r1, r0 @ r1 = inBuf @@ -508,43 +502,37 @@ LinearRate_S_read_return: LDR r10,[r2, #16] @ r10= icur[0,1] LDRSH r5, [r0],#2 @ r5 = tmp0 = *inPtr++ LDRSH r6, [r0],#2 @ r5 = tmp1 = *inPtr++ - SUBS r8, r8, #1 @ r8 = opos-- - STR r10,[r2,#20] @ ilast[0,1] = icur[0,1] + SUBS r8, r8, #65536 @ r8 = opos-- + STRH r10,[r2,#22] @ ilast[0] = icur[0] + MOV r10,r10,LSR #16 + STRH r10,[r2,#26] @ ilast[1] = icur[1] STRH r5, [r2,#16] @ icur[0] = tmp0 - STRH r6, [r2,#16] @ icur[1] = tmp1 + STRH r6, [r2,#18] @ icur[1] = tmp1 BGE LinearRate_S_loop @ part2 - form output samples LinearRate_S_part2: @ We are guaranteed that opos < 0 here - LDRSH r6, [r2,#20] @ r6 = ilast[0] + LDR r6, [r2,#20] @ r6 = ilast[0]<<16 + 32768 LDRSH r5, [r2,#16] @ r5 = icur[0] - LDRH r4, [r2,#24] @ r4 = opos_frac - MOV r6, r6, LSL #16 @ r6 = ilast[0]<<16 + MOV r4, r8, LSL #16 + MOV r4, r4, LSR #16 SUB r5, r5, r6, ASR #16 @ r5 = icur[0] - ilast[0] - ADD r6, r6, #1<<15 @ r6 = ilast[0]+1<<(FRAC_BITS-1) MLA r6, r4, r5, r6 @ r6 = (icur[0]-ilast[0])*opos_frac+ilast[0] - LDRSH r7, [r2,#22] @ r6 = ilast[1] + LDR r7, [r2,#24] @ r7 = ilast[1]<<16 + 32768 LDRSH r5, [r2,#18] @ r5 = icur[1] - LDR r10,[r2,#28] @ r10= opos_frac_inc - MOV r7, r7, LSL #16 @ r7 = ilast[1]<<16 + LDRSH r10,[r3] @ r10= obuf[0] + MOV r6, r6, ASR #16 @ r6 = tmp1 >>= 16 SUB r5, r5, r7, ASR #16 @ r5 = icur[1] - ilast[1] - ADD r7, r7, #1<<15 @ r6 = ilast[1]+1<<(FRAC_BITS-1) - MLA r7, r4, r5, r7 @ r6 = (icur[1]-ilast[1])*opos_frac+ilast[1] - - ADD r4, r4, r10 @ r4 = tmp = opos_frac+opos_inc_frac - STRH r4,[r2,#24] @ opos_frac &= 65535 - ADD r8, r8, r4, LSR #16 @ opos += (tmp>>FRAC_BITS) + MLA r7, r4, r5, r7 @ r7 = (icur[1]-ilast[1])*opos_frac+ilast[1] - LDRSH r4, [r3] @ r4 = obuf[0] LDRSH r5, [r3,#2] @ r5 = obuf[1] MOV r7, r7, ASR #16 @ r7 = tmp0 >>= 16 - MOV r6, r6, ASR #16 @ r6 = tmp1 >>= 16 MUL r7, r12,r7 @ r7 = tmp0*vol_l MUL r6, r14,r6 @ r6 = tmp1*vol_r - ADDS r7, r7, r4, LSL #16 @ r7 = obuf[0]<<16 + tmp0*vol_l + ADDS r7, r7, r10, LSL #16 @ r7 = obuf[0]<<16 + tmp0*vol_l MOV r4, #0 RSCVS r7, r4, #1<<31 @ Clamp r7 ADDS r6, r6, r5, LSL #16 @ r6 = obuf[1]<<16 + tmp1*vol_r @@ -556,7 +544,7 @@ LinearRate_S_part2: LDR r5, [r2,#12] @ r5 = opos_inc STRH r7, [r3],#2 @ Store output value STRH r6, [r3],#2 @ Store output value - SUBS r11, r11,#1 @ opos-- + SUBS r11, r11,#1 @ osamp-- BLE LinearRate_S_end @ and loop ADDS r8, r8, r5 @ r8 = opos += opos_inc @@ -567,7 +555,7 @@ LinearRate_S_end: STMIA r2,{r0,r1,r8} LDMFD r13!,{r4-r11,PC} LinearRate_S_read: - ADD r0, r2, #32 @ r0 = inPtr = inBuf + ADD r0, r2, #28 @ r0 = inPtr = inBuf STMFD r13!,{r0,r2-r3,r12,r14} MOV r1, r0 @ r1 = inBuf @@ -615,43 +603,37 @@ LinearRate_R_read_return: LDR r10,[r2, #16] @ r10= icur[0,1] LDRSH r5, [r0],#2 @ r5 = tmp0 = *inPtr++ LDRSH r6, [r0],#2 @ r5 = tmp1 = *inPtr++ - SUBS r8, r8, #1 @ r8 = opos-- - STR r10,[r2,#20] @ ilast[0,1] = icur[0,1] + SUBS r8, r8, #65536 @ r8 = opos-- + STRH r10,[r2,#22] @ ilast[0] = icur[0] + MOV r10,r10,LSR #16 + STRH r10,[r2,#22] @ ilast[1] = icur[1] STRH r5, [r2,#16] @ icur[0] = tmp0 - STRH r6, [r2,#16] @ icur[1] = tmp1 + STRH r6, [r2,#18] @ icur[1] = tmp1 BGE LinearRate_R_loop @ part2 - form output samples LinearRate_R_part2: @ We are guaranteed that opos < 0 here - LDRSH r6, [r2,#20] @ r6 = ilast[0] + LDR r6, [r2,#20] @ r6 = ilast[0] LDRSH r5, [r2,#16] @ r5 = icur[0] - LDRH r4, [r2,#24] @ r4 = opos_frac - MOV r6, r6, LSL #16 @ r6 = ilast[0]<<16 + MOV r4, r8, LSL #16 + MOV r4, r4, LSR #16 SUB r5, r5, r6, ASR #16 @ r5 = icur[0] - ilast[0] - ADD r6, r6, #1<<15 @ r6 = ilast[0]+1<<(FRAC_BITS-1) MLA r6, r4, r5, r6 @ r6 = (icur[0]-ilast[0])*opos_frac+ilast[0] - LDRSH r7, [r2,#22] @ r6 = ilast[1] + LDR r7, [r2,#24] @ r7 = ilast[1] LDRSH r5, [r2,#18] @ r5 = icur[1] - LDR r10,[r2,#28] @ r10= opos_frac_inc - MOV r7, r7, LSL #16 @ r7 = ilast[1]<<16 + LDR r10,[r3] @ r10= obuf[0] + MOV r6, r6, ASR #16 @ r6 = tmp1 >>= 16 SUB r5, r5, r7, ASR #16 @ r5 = icur[1] - ilast[1] - ADD r7, r7, #1<<15 @ r6 = ilast[1]+1<<(FRAC_BITS-1) - MLA r7, r4, r5, r7 @ r6 = (icur[1]-ilast[1])*opos_frac+ilast[1] + MLA r7, r4, r5, r7 @ r7 = (icur[1]-ilast[1])*opos_frac+ilast[1] - ADD r4, r4, r10 @ r4 = tmp = opos_frac+opos_inc_frac - STRH r4,[r2,#24] @ opos_frac &= 65535 - ADD r8, r8, r4, LSR #16 @ opos += (tmp>>FRAC_BITS) - - LDRSH r4, [r3] @ r4 = obuf[0] LDRSH r5, [r3,#2] @ r5 = obuf[1] MOV r7, r7, ASR #16 @ r7 = tmp0 >>= 16 - MOV r6, r6, ASR #16 @ r6 = tmp1 >>= 16 MUL r7, r12,r7 @ r7 = tmp0*vol_l MUL r6, r14,r6 @ r6 = tmp1*vol_r - ADDS r7, r7, r4, LSL #16 @ r7 = obuf[0]<<16 + tmp0*vol_l + ADDS r7, r7, r10, LSL #16 @ r7 = obuf[0]<<16 + tmp0*vol_l MOV r4, #0 RSCVS r7, r4, #1<<31 @ Clamp r7 ADDS r6, r6, r5, LSL #16 @ r6 = obuf[1]<<16 + tmp1*vol_r @@ -663,7 +645,7 @@ LinearRate_R_part2: LDR r5, [r2,#12] @ r5 = opos_inc STRH r6, [r3],#2 @ Store output value STRH r7, [r3],#2 @ Store output value - SUBS r11, r11,#1 @ opos-- + SUBS r11, r11,#1 @ osamp-- BLE LinearRate_R_end @ and loop ADDS r8, r8, r5 @ r8 = opos += opos_inc @@ -674,7 +656,7 @@ LinearRate_R_end: STMIA r2,{r0,r1,r8} LDMFD r13!,{r4-r11,PC} LinearRate_R_read: - ADD r0, r2, #32 @ r0 = inPtr = inBuf + ADD r0, r2, #28 @ r0 = inPtr = inBuf STMFD r13!,{r0,r2-r3,r12,r14} MOV r1, r0 @ r1 = inBuf diff --git a/sound/softsynth/ym2612.cpp b/sound/softsynth/ym2612.cpp index 5d36c9ec28..e3aa9d2528 100644 --- a/sound/softsynth/ym2612.cpp +++ b/sound/softsynth/ym2612.cpp @@ -129,7 +129,7 @@ void Operator2612::frequency(int freq) { value *= 127 - _specifiedTotalLevel; value /= 127; } - _attackTime = (int32) value; // 1 Éà == (1 << 12) + _attackTime = (int32) value; // 1 ?? == (1 << 12) if (_attackTime > 0) _attackTime = (1 << (12+10)) / (_owner->_rate * _attackTime); @@ -295,7 +295,7 @@ Voice2612::~Voice2612() { void Voice2612::velocity(int velo) { _velocity = velo; #if 0 - int v = (velo * _control7) >> 7; // ¤³¤ì¤À¤ÈÀºÅÙÎɤ¯¤Ê¤¤¤Ç¤¹¤Í + int v = (velo * _control7) >> 7; #else int v = velo + (_control7 - 127) * 4; #endif diff --git a/sound/voc.h b/sound/voc.h index ebd343f05d..fd19a29c5a 100644 --- a/sound/voc.h +++ b/sound/voc.h @@ -43,14 +43,14 @@ struct VocFileHeader { uint16 datablock_offset; uint16 version; uint16 id; -}; +} PACKED_STRUCT; struct VocBlockHeader { uint8 blocktype; uint8 size[3]; uint8 sr; uint8 pack; -}; +} PACKED_STRUCT; #include "common/pack-end.h" // END STRUCT PACKING diff --git a/test/common/pack.h b/test/common/pack.h index 68254db187..76086b05ca 100644 --- a/test/common/pack.h +++ b/test/common/pack.h @@ -12,7 +12,7 @@ struct TestStruct { uint16 z; uint32 a; byte b; -}; +} PACKED_STRUCT; #include <common/pack-end.h> // END STRUCT PACKING diff --git a/tools/credits.pl b/tools/credits.pl index acdbe03797..7a1bebbed3 100755 --- a/tools/credits.pl +++ b/tools/credits.pl @@ -624,6 +624,7 @@ begin_credits("Credits"); begin_section("Miscellaneous"); add_person("Jerome Fisher", "KingGuppy", "MT-32 emulator"); add_person("Jochen Hoenicke", "hoenicke", "Speaker & PCjr sound support, Adlib work"); + add_person("Robin Watts", "robinwatts", "ARM assembly routines for nice speedups on several ports; improvements to the sound mixer"); end_section(); end_section(); @@ -752,7 +753,6 @@ begin_credits("Credits"); add_person("Edward Rudd", "urkle", "Fixes for playing MP3 versions of MI1/Loom audio"); add_person("Daniel Schepler", "dschepler", "Final MI1 CD music support, initial Ogg Vorbis support"); add_person("André Souza", "luke_br", "SDL-based OpenGL renderer"); - add_person("Robin Watts", "robinwatts", "ARM assembly routines for the Windows CE port"); end_persons(); end_section(); diff --git a/tools/scumm-md5.txt b/tools/scumm-md5.txt index 468bb6b6ce..f97785cbe0 100644 --- a/tools/scumm-md5.txt +++ b/tools/scumm-md5.txt @@ -122,22 +122,23 @@ indy3 Indiana Jones and the Last Crusade 157367c3c21e0d03a0cba44361b4cf65 -1 en Atari No Adlib EGA - Andreas Bylund 0f9c7a76657f0840b8f7ccb5bffeb9f4 -1 fr Atari No Adlib EGA - Andreas Bylund 5fbe557049892eb4b709d90916ec97ca 5361 en DOS EGA EGA v1.0, 7/09/89 Fingolfin - 6b3ec67da214f558dc5ceaa2acd47453 -1 en DOS EGA EGA v1.3 from 14 Aug 89 tsuteiuQ, Andrea Petrucci, Peter Eckerlein + 6b3ec67da214f558dc5ceaa2acd47453 -1 en DOS EGA EGA v1.3, 14 Aug 89 tsuteiuQ, Andrea Petrucci, Peter Eckerlein 6508fd55530e6915507e1cc37f7f045d -1 en DOS EGA EGA v1.3, 8/14/89 (5.25\") Zer02 - 66236cd1aec24e1d4aff4c4cc93b7e18 -1 fr DOS EGA EGA v1.3 from 25 Aug 89 Andrea Petrucci, Peter Eckerlein - 89cfc425566003ff74b7dc7b3e6fd469 -1 fr DOS EGA EGA v1.3, 25 Aug 89 Jorpho + 66236cd1aec24e1d4aff4c4cc93b7e18 -1 fr DOS EGA EGA ?? v1.3, 25 Aug 89 Andrea Petrucci, Peter Eckerlein + 89cfc425566003ff74b7dc7b3e6fd469 -1 fr DOS EGA EGA ?? v1.3, 25 Aug 89 Jorpho + 69d70269fafc4445adbb0d223e4f9a3f 5361 en DOS EGA EGA v1.4, 11/07/89 (5.25\") Petr Maruska 6f6ef668c608c7f534fea6e6d3878dde -1 de DOS EGA EGA v1.4 from 19 Oct 89 dhewg, Peter Eckerlein d62d248c3df6ec177405e2cb23d923b2 -1 it DOS EGA EGA v1.4 from 25 Nov 89 Andrea Petrucci, Peter Eckerlein 86be8ada36371d4fdc35659d0e912a26 -1 es DOS EGA EGA ?? v1.4b from 7 May 90 Andrea Petrucci, Peter Eckerlein ce7fd0c382389a6791fc3e199c117ef4 -1 es DOS EGA EGA ?? v1.4b from 7 May 90 abnog, Peter Eckerlein - 1dd7aa088e09f96d06818aa9a9deabe0 5361 en Mac No Adlib EGA - Fingolfin + 1dd7aa088e09f96d06818aa9a9deabe0 5361 en Mac No Adlib EGA v1.7, 8/17/90 Fingolfin 1875b90fade138c9253a8e967007031a 6295 en DOS VGA VGA IBM 256 color v2.0 from 3 May 90 Peter Eckerlein, Fingolfin 399b217b0c8d65d0398076da486363a9 6295 de DOS VGA VGA VGA v1.02 from 7 Nov 91 Peter Eckerlein, Fingolfin 17b5d5e6af4ae89d62631641d66d5a05 -1 it DOS VGA VGA IBM 256 color v2.1 from 3 May 01 Andrea Petrucci, Peter Eckerlein 3cce1913a3bc586b51a75c3892ff18dd -1 ru DOS VGA VGA VGA - 04687cdf7f975a89d2474929f7b80946 7552 en FM-TOWNS FM-TOWNS - - Fingolfin + 04687cdf7f975a89d2474929f7b80946 7552 en FM-TOWNS FM-TOWNS - v1.00 1/23/91 Fingolfin 3a0c35f3c147b98a2bdf8d400cfc4ab5 -1 jp FM-TOWNS FM-TOWNS - - Paul Priest, Andrea Petrucci b597e0403cc0002f69170e6caba7edd9 5361 en DOS EGA EGA Demo non-interactive Fingolfin @@ -163,7 +164,7 @@ loom Loom 187d315f6b5168f68680dfe8c3d76a3e -1 hb DOS EGA EGA - c3df37df9d3b481b45f75283a9907c47 -1 it DOS EGA EGA - Andrea Petrucci 2a208ffbcd0e83e86f4356e6f64aa6e1 -1 es DOS EGA EGA v1.2 Espanol from 31 Aug 90 abnog, Andrea Petrucci, Peter Eckerlein - 6f0be328c64d689bb606d22a389e1b0f 5748 en Mac No Adlib EGA - Fingolfin + 6f0be328c64d689bb606d22a389e1b0f 5748 en Mac No Adlib EGA v1.2 25 Jan 91 Fingolfin 5d88b9d6a88e6f8e90cded9d01b7f082 8307 en DOS VGA VGA CD Version v1.0 from 10. Feb 92 (Talkie) Peter Eckerlein, Fingolfin @@ -186,7 +187,7 @@ monkey The Secret of Monkey Island 910e31cffb28226bd68c569668a0d6b4 -1 es DOS EGA EGA 8 disk Andrea Petrucci 1d05cd189e4908f79b57e78a4402f292 -1 en DOS EGA EGA 4 disk Andrea Petrucci ce6a4cef315b20fef58a95bc40a2d8d3 -1 fr DOS EGA EGA 4 disk Matthieu Milan - aa7a07d94ae853f6460be4ce0a1bf530 -1 fr DOS EGA EGA 4 disk v1.0,9/7/90 II Parazythum + aa7a07d94ae853f6460be4ce0a1bf530 -1 fr DOS EGA EGA 4 disk v1.0, 9/7/90 II Parazythum e98b982ceaf9d253d730bde8903233d6 -1 de DOS EGA EGA 4 disk Joachim Eberhard 477dbafbd66a53c98416dc01aef019ad -1 it DOS EGA EGA 4 disk Andrea Petrucci @@ -199,16 +200,16 @@ monkey The Secret of Monkey Island c7890e038806df2bb5c0c8c6f1986ea2 -1 en DOS VGA VGA 8 disk Andrea Petrucci 15e03ffbfeddb9c2aebc13dcb2a4a8f4 8357 en DOS VGA VGA 4 disk 08656dd9698ddf1023ba9bf8a195e37b -1 en DOS VGA VGA V1.1 crossbow777 - d0b531227a27c6662018d2bd05aac52a 8357 de DOS VGA VGA 4 disk Fingolfin + d0b531227a27c6662018d2bd05aac52a 8357 de DOS VGA VGA 4 disk v1.1, 14.Feb.91 Fingolfin 66fd5ff9a810dfeb6d6bdada18221140 -1 it DOS VGA VGA 4 disk Andrea Petrucci 45152f7cf2ba8f43cf8a8ea2e740ae09 8357 es DOS VGA VGA 4 disk Fingolfin - 2d1e891fe52df707c30185e52c50cd92 8955 en DOS CD CD - Fingolfin - aa8a0cb65f3afbbe2c14c3f9f92775a3 8955 fr DOS CD CD - Fingolfin, Andrej Sinicyn, Andrea Petrucci - 305d3dd57c96c65b017bc70c8c7cfb5e 8955 de DOS CD CD - Fingolfin - da6269b18fcb08189c0aa9c95533cce2 8955 it DOS CD CD - Fingolfin, Andrej Sinicyn, Andrea Petrucci - f049e38c1f8302b5db6170f1872af89a 8955 es DOS CD CD - Fingolfin, Andrej Sinicyn, Andrea Petrucci - 2ccd8891ce4d3f1a334d21bff6a88ca2 9455 en Mac CD - - Fingolfin, Lars Næsbye Christensen + 2d1e891fe52df707c30185e52c50cd92 8955 en DOS CD CD CD-ROM v2.3 Fingolfin + aa8a0cb65f3afbbe2c14c3f9f92775a3 8955 fr DOS CD CD CD-ROM v2.3 Fingolfin, Andrej Sinicyn, Andrea Petrucci + 305d3dd57c96c65b017bc70c8c7cfb5e 8955 de DOS CD CD CD-ROM v2.3 Fingolfin + da6269b18fcb08189c0aa9c95533cce2 8955 it DOS CD CD CD-ROM v2.3 Fingolfin, Andrej Sinicyn, Andrea Petrucci + f049e38c1f8302b5db6170f1872af89a 8955 es DOS CD CD CD-ROM v2.3 Fingolfin, Andrej Sinicyn, Andrea Petrucci + 2ccd8891ce4d3f1a334d21bff6a88ca2 9455 en Mac CD - Mac v2.4 Fingolfin, Lars Næsbye Christensen b9ba19ce376efc69be78ef3baef8d2b9 -1 en Mac CD - alt? Grant Yeager c13225cb1bbd3bc9fe578301696d8021 -1 en SEGA SEGA - - @@ -220,7 +221,7 @@ monkey The Secret of Monkey Island 54a936ad06161ff7bfefcb96200f7bff -1 en Amiga VGA VGA Demo - khalek pass Passport to Adventure - e6cd81b25ab1453a8a6d3482118c391e 7857 en DOS - - - Fingolfin + e6cd81b25ab1453a8a6d3482118c391e 7857 en DOS - - v1.0 9/14/90 Fingolfin zak Misc FM-TOWNS demos 2d388339d6050d8ccaa757b64633954e 7520 en FM-TOWNS FM-TOWNS Demo indy/loom (non-interactive) khalek @@ -228,21 +229,21 @@ zak Misc FM-TOWNS demos 3938ee1aa4433fca9d9308c9891172b1 -1 en FM-TOWNS FM-TOWNS Demo indy/zak (non-interactive) khalek monkey2 Monkey Island 2: LeChuck's Revenge - 132bff65e6367c09cc69318ce1b59333 11155 en Amiga - - - Fingolfin + 132bff65e6367c09cc69318ce1b59333 11155 en Amiga - - v1.0 4/8/92 Fingolfin c30ef068add4277104243c31ce46c12b -1 fr Amiga - - - Andreas Bylund da669b20271b85182e9c17a2a37ea02e -1 de Amiga - - - Andreas Bylund, Norbert Lange 11ddf1fde76e3156eb3a38da213f484e -1 it Amiga - - - Andrea Petrucci 6ea966b4d660c870b9ee790d1fbfc535 -1 es Amiga - - - Andreas Bylund 3686cf8f89e102ececf4366e1d2c8126 11135 en DOS - - - 8e4ee4db46954bfe2912e259a16fad82 -1 fr DOS - - - Nicolas Sauzède, Andrea Petrucci - 6886e5d08cee329b1f2e743ae2e3ceed 11135 de DOS - - - Fingolfin + 6886e5d08cee329b1f2e743ae2e3ceed 11135 de DOS - - v1.0D 17Feb92 Fingolfin 69ea626f1f87eecb78ea0d6c6b983a1d -1 it DOS - - - Andrea Petrucci bd126753de619a495f9f22adc951c8d5 -1 it DOS - - alt? Andrea Petrucci 7974365d3dc0f43a2748c975f91ff042 -1 es DOS - - - Andrea Petrucci - 4cb9c3618f71668f8e4346c8f323fa82 10700 en Mac - - - Fingolfin + 4cb9c3618f71668f8e4346c8f323fa82 10700 en Mac - - v1.0 11/5/92 Fingolfin e246e02db9630533a40d99c9f54a8e01 -1 en Mac - - alt? Lars Næsbye Christensen - da09e666fc8f5b78d7b0ac65d1a3b56e -1 en FM-TOWNS - - - dhewg, Andrea Petrucci + da09e666fc8f5b78d7b0ac65d1a3b56e 11135 en FM-TOWNS - - - dhewg, Andrea Petrucci 430bc518017b6fac046f58bab6baad5d -1 jp FM-TOWNS - - - Antti Leimi, Andrea Petrucci 387a544b8b10b26912d8413bab63a853 -1 en DOS - Demo non-interactive khalek diff --git a/tools/skycpt/AsciiCptCompile.cpp b/tools/skycpt/AsciiCptCompile.cpp index 9df29f8b44..df5f1dfd30 100644 --- a/tools/skycpt/AsciiCptCompile.cpp +++ b/tools/skycpt/AsciiCptCompile.cpp @@ -1,4 +1,4 @@ -// AsciiCptCompile.cpp : Definiert den Einstiegspunkt für die Konsolenanwendung. +// AsciiCptCompile.cpp // #include "stdafx.h" diff --git a/tools/skycpt/stdafx.cpp b/tools/skycpt/stdafx.cpp index 22a7f25f57..fd4f341c7b 100644 --- a/tools/skycpt/stdafx.cpp +++ b/tools/skycpt/stdafx.cpp @@ -1,8 +1 @@ -// stdafx.cpp : Quelltextdatei, die nur die Standard-Includes einbindet -// AsciiCptCompile.pch ist der vorcompilierte Header -// stdafx.obj enthält die vorcompilierte Typinformation - #include "stdafx.h" - -// TODO: Verweisen Sie auf zusätzliche Header, die in STDAFX.H -// und nicht in dieser Datei erforderlich sind. |