diff options
78 files changed, 3387 insertions, 2431 deletions
@@ -106,6 +106,10 @@ ScummVM Team Scott Thomas Jordi Vilalta Prat + Hopkins: + Arnaud Boutonne + Paul Gilbert + Hugo: Arnaud Boutonne Oystein Eftevaag @@ -311,6 +315,8 @@ ScummVM Team Benjamin Haisch - Heavily improved de-/encoder for DXA videos Jochen Hoenicke - Speaker & PCjr sound support, AdLib work (retired) + Daniel ter Laan - Restoring original Drascula tracks, and + writing convert_dxa.bat Chris Page - Return to launcher, savestate improvements, leak fixes, ... (GSoC 2008 task) (retired) Robin Watts - ARM assembly routines for nice speedups on @@ -6,6 +6,7 @@ For a more comprehensive changelog of the latest experimental code, see: - Added support for 3 Skulls of the Toltecs. - Added support for Eye of the Beholder. - Added support for Eye of the Beholder II: The Legend of Darkmoon. + - Added support for Tony Tough and the Night of Roasted Moths General: - Added a new save/load chooser based on a grid of thumbnails. This is only @@ -29,6 +30,10 @@ For a more comprehensive changelog of the latest experimental code, see: Now music fades out slowly instead of stopping immediately. Sound effects are now properly panned, when requested by the game. + CGE: + - Soltys contains a puzzle requiring the ALT key to be pressed while clicking + on an object. This puzzle has been disabled on devices not using this key. + Drascula: - Resolved multiple UI issues with the original save/load screen. - Added advanced savegame functionality, including savegame timestamps and diff --git a/audio/softsynth/mt32/AReverbModel.cpp b/audio/softsynth/mt32/AReverbModel.cpp index 595b286a31..1d63832157 100644 --- a/audio/softsynth/mt32/AReverbModel.cpp +++ b/audio/softsynth/mt32/AReverbModel.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011, 2012 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/AReverbModel.h b/audio/softsynth/mt32/AReverbModel.h index be1ca4916b..c992478907 100644 --- a/audio/softsynth/mt32/AReverbModel.h +++ b/audio/softsynth/mt32/AReverbModel.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011, 2012 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/BReverbModel.cpp b/audio/softsynth/mt32/BReverbModel.cpp index 2570424187..cc0219b741 100644 --- a/audio/softsynth/mt32/BReverbModel.cpp +++ b/audio/softsynth/mt32/BReverbModel.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011, 2012 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/BReverbModel.h b/audio/softsynth/mt32/BReverbModel.h index f728d1a99c..d6fcb73c13 100644 --- a/audio/softsynth/mt32/BReverbModel.h +++ b/audio/softsynth/mt32/BReverbModel.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011, 2012 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/DelayReverb.cpp b/audio/softsynth/mt32/DelayReverb.cpp index bf925f8419..d80c98acbc 100644 --- a/audio/softsynth/mt32/DelayReverb.cpp +++ b/audio/softsynth/mt32/DelayReverb.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/DelayReverb.h b/audio/softsynth/mt32/DelayReverb.h index 1abb49f128..c8003832b5 100644 --- a/audio/softsynth/mt32/DelayReverb.h +++ b/audio/softsynth/mt32/DelayReverb.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/FreeverbModel.cpp b/audio/softsynth/mt32/FreeverbModel.cpp index 2ed302fddc..bd9c70b6f4 100644 --- a/audio/softsynth/mt32/FreeverbModel.cpp +++ b/audio/softsynth/mt32/FreeverbModel.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/FreeverbModel.h b/audio/softsynth/mt32/FreeverbModel.h index bf1102b14a..5ea11f1f40 100644 --- a/audio/softsynth/mt32/FreeverbModel.h +++ b/audio/softsynth/mt32/FreeverbModel.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/LA32Ramp.cpp b/audio/softsynth/mt32/LA32Ramp.cpp index 4e4d6b4f30..b4ac6f1d46 100644 --- a/audio/softsynth/mt32/LA32Ramp.cpp +++ b/audio/softsynth/mt32/LA32Ramp.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -82,9 +82,13 @@ void LA32Ramp::startRamp(Bit8u target, Bit8u increment) { if (increment == 0) { largeIncrement = 0; } else { - // Using integer argument here, no precision loss: + // Three bits in the fractional part, no need to interpolate // (unsigned int)(EXP2F(((increment & 0x7F) + 24) / 8.0f) + 0.125f) - largeIncrement = (unsigned int)(EXP2I(((increment & 0x7F) + 24) << 9) + 0.125f); + Bit32u expArg = increment & 0x7F; + largeIncrement = 8191 - Tables::getInstance().exp9[~(expArg << 6) & 511]; + largeIncrement <<= expArg >> 3; + largeIncrement += 64; + largeIncrement >>= 9; } descending = (increment & 0x80) != 0; if (descending) { diff --git a/audio/softsynth/mt32/LA32Ramp.h b/audio/softsynth/mt32/LA32Ramp.h index ae937eb7e1..8f55941a12 100644 --- a/audio/softsynth/mt32/LA32Ramp.h +++ b/audio/softsynth/mt32/LA32Ramp.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/LA32WaveGenerator.cpp b/audio/softsynth/mt32/LA32WaveGenerator.cpp new file mode 100644 index 0000000000..5b2c9001b8 --- /dev/null +++ b/audio/softsynth/mt32/LA32WaveGenerator.cpp @@ -0,0 +1,419 @@ +/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +//#include <cmath> +#include "mt32emu.h" +#include "mmath.h" +#include "LA32WaveGenerator.h" + +#if MT32EMU_ACCURATE_WG == 0 + +namespace MT32Emu { + +static const Bit32u SINE_SEGMENT_RELATIVE_LENGTH = 1 << 18; +static const Bit32u MIDDLE_CUTOFF_VALUE = 128 << 18; +static const Bit32u RESONANCE_DECAY_THRESHOLD_CUTOFF_VALUE = 144 << 18; +static const Bit32u MAX_CUTOFF_VALUE = 240 << 18; +static const LogSample SILENCE = {65535, LogSample::POSITIVE}; + +Bit16u LA32Utilites::interpolateExp(const Bit16u fract) { + Bit16u expTabIndex = fract >> 3; + Bit16u extraBits = fract & 7; + Bit16u expTabEntry2 = 8191 - Tables::getInstance().exp9[expTabIndex]; + Bit16u expTabEntry1 = expTabIndex == 0 ? 8191 : (8191 - Tables::getInstance().exp9[expTabIndex - 1]); + return expTabEntry1 + (((expTabEntry2 - expTabEntry1) * extraBits) >> 3); +} + +Bit16s LA32Utilites::unlog(const LogSample &logSample) { + //Bit16s sample = (Bit16s)EXP2F(13.0f - logSample.logValue / 1024.0f); + Bit32u intLogValue = logSample.logValue >> 12; + Bit16u fracLogValue = logSample.logValue & 4095; + Bit16s sample = interpolateExp(fracLogValue) >> intLogValue; + return logSample.sign == LogSample::POSITIVE ? sample : -sample; +} + +void LA32Utilites::addLogSamples(LogSample &logSample1, const LogSample &logSample2) { + Bit32u logSampleValue = logSample1.logValue + logSample2.logValue; + logSample1.logValue = logSampleValue < 65536 ? (Bit16u)logSampleValue : 65535; + logSample1.sign = logSample1.sign == logSample2.sign ? LogSample::POSITIVE : LogSample::NEGATIVE; +} + +Bit32u LA32WaveGenerator::getSampleStep() { + // sampleStep = EXP2F(pitch / 4096.0f + 4.0f) + Bit32u sampleStep = LA32Utilites::interpolateExp(~pitch & 4095); + sampleStep &= ~1; + sampleStep <<= pitch >> 12; + sampleStep >>= 8; + sampleStep &= ~1; + return sampleStep; +} + +Bit32u LA32WaveGenerator::getResonanceWaveLengthFactor(Bit32u effectiveCutoffValue) { + // resonanceWaveLengthFactor = (Bit32u)EXP2F(12.0f + effectiveCutoffValue / 4096.0f); + Bit32u resonanceWaveLengthFactor = LA32Utilites::interpolateExp(~effectiveCutoffValue & 4095); + resonanceWaveLengthFactor <<= effectiveCutoffValue >> 12; + return resonanceWaveLengthFactor; +} + +Bit32u LA32WaveGenerator::getHighLinearLength(Bit32u effectiveCutoffValue) { + // Ratio of positive segment to wave length + Bit32u effectivePulseWidthValue = 0; + if (pulseWidth > 128) { + effectivePulseWidthValue = (pulseWidth - 128) << 6; + } + + Bit32u highLinearLength = 0; + // highLinearLength = EXP2F(19.0f - effectivePulseWidthValue / 4096.0f + effectiveCutoffValue / 4096.0f) - 2 * SINE_SEGMENT_RELATIVE_LENGTH; + if (effectivePulseWidthValue < effectiveCutoffValue) { + Bit32u expArg = effectiveCutoffValue - effectivePulseWidthValue; + highLinearLength = LA32Utilites::interpolateExp(~expArg & 4095); + highLinearLength <<= 7 + (expArg >> 12); + highLinearLength -= 2 * SINE_SEGMENT_RELATIVE_LENGTH; + } + return highLinearLength; +} + +void LA32WaveGenerator::computePositions(Bit32u highLinearLength, Bit32u lowLinearLength, Bit32u resonanceWaveLengthFactor) { + // Assuming 12-bit multiplication used here + squareWavePosition = resonanceSinePosition = (wavePosition >> 8) * (resonanceWaveLengthFactor >> 4); + if (squareWavePosition < SINE_SEGMENT_RELATIVE_LENGTH) { + phase = POSITIVE_RISING_SINE_SEGMENT; + return; + } + squareWavePosition -= SINE_SEGMENT_RELATIVE_LENGTH; + if (squareWavePosition < highLinearLength) { + phase = POSITIVE_LINEAR_SEGMENT; + return; + } + squareWavePosition -= highLinearLength; + if (squareWavePosition < SINE_SEGMENT_RELATIVE_LENGTH) { + phase = POSITIVE_FALLING_SINE_SEGMENT; + return; + } + squareWavePosition -= SINE_SEGMENT_RELATIVE_LENGTH; + resonanceSinePosition = squareWavePosition; + if (squareWavePosition < SINE_SEGMENT_RELATIVE_LENGTH) { + phase = NEGATIVE_FALLING_SINE_SEGMENT; + return; + } + squareWavePosition -= SINE_SEGMENT_RELATIVE_LENGTH; + if (squareWavePosition < lowLinearLength) { + phase = NEGATIVE_LINEAR_SEGMENT; + return; + } + squareWavePosition -= lowLinearLength; + phase = NEGATIVE_RISING_SINE_SEGMENT; +} + +void LA32WaveGenerator::advancePosition() { + wavePosition += getSampleStep(); + wavePosition %= 4 * SINE_SEGMENT_RELATIVE_LENGTH; + + Bit32u effectiveCutoffValue = (cutoffVal > MIDDLE_CUTOFF_VALUE) ? (cutoffVal - MIDDLE_CUTOFF_VALUE) >> 10 : 0; + Bit32u resonanceWaveLengthFactor = getResonanceWaveLengthFactor(effectiveCutoffValue); + Bit32u highLinearLength = getHighLinearLength(effectiveCutoffValue); + Bit32u lowLinearLength = (resonanceWaveLengthFactor << 8) - 4 * SINE_SEGMENT_RELATIVE_LENGTH - highLinearLength; + computePositions(highLinearLength, lowLinearLength, resonanceWaveLengthFactor); + + // resonancePhase computation hack + *(int*)&resonancePhase = ((resonanceSinePosition >> 18) + (phase > POSITIVE_FALLING_SINE_SEGMENT ? 2 : 0)) & 3; +} + +void LA32WaveGenerator::generateNextSquareWaveLogSample() { + Bit32u logSampleValue; + switch (phase) { + case POSITIVE_RISING_SINE_SEGMENT: + case NEGATIVE_FALLING_SINE_SEGMENT: + logSampleValue = Tables::getInstance().logsin9[(squareWavePosition >> 9) & 511]; + break; + case POSITIVE_FALLING_SINE_SEGMENT: + case NEGATIVE_RISING_SINE_SEGMENT: + logSampleValue = Tables::getInstance().logsin9[~(squareWavePosition >> 9) & 511]; + break; + case POSITIVE_LINEAR_SEGMENT: + case NEGATIVE_LINEAR_SEGMENT: + default: + logSampleValue = 0; + break; + } + logSampleValue <<= 2; + logSampleValue += amp >> 10; + if (cutoffVal < MIDDLE_CUTOFF_VALUE) { + logSampleValue += (MIDDLE_CUTOFF_VALUE - cutoffVal) >> 9; + } + + squareLogSample.logValue = logSampleValue < 65536 ? (Bit16u)logSampleValue : 65535; + squareLogSample.sign = phase < NEGATIVE_FALLING_SINE_SEGMENT ? LogSample::POSITIVE : LogSample::NEGATIVE; +} + +void LA32WaveGenerator::generateNextResonanceWaveLogSample() { + Bit32u logSampleValue; + if (resonancePhase == POSITIVE_FALLING_RESONANCE_SINE_SEGMENT || resonancePhase == NEGATIVE_RISING_RESONANCE_SINE_SEGMENT) { + logSampleValue = Tables::getInstance().logsin9[~(resonanceSinePosition >> 9) & 511]; + } else { + logSampleValue = Tables::getInstance().logsin9[(resonanceSinePosition >> 9) & 511]; + } + logSampleValue <<= 2; + logSampleValue += amp >> 10; + + // From the digital captures, the decaying speed of the resonance sine is found a bit different for the positive and the negative segments + Bit32u decayFactor = phase < NEGATIVE_FALLING_SINE_SEGMENT ? resAmpDecayFactor : resAmpDecayFactor + 1; + // Unsure about resonanceSinePosition here. It's possible that dedicated counter & decrement are used. Although, cutoff is finely ramped, so maybe not. + logSampleValue += resonanceAmpSubtraction + (((resonanceSinePosition >> 4) * decayFactor) >> 8); + + // To ensure the output wave has no breaks, two different windows are appied to the beginning and the ending of the resonance sine segment + if (phase == POSITIVE_RISING_SINE_SEGMENT || phase == NEGATIVE_FALLING_SINE_SEGMENT) { + // The window is synchronous sine here + logSampleValue += Tables::getInstance().logsin9[(squareWavePosition >> 9) & 511] << 2; + } else if (phase == POSITIVE_FALLING_SINE_SEGMENT || phase == NEGATIVE_RISING_SINE_SEGMENT) { + // The window is synchronous square sine here + logSampleValue += Tables::getInstance().logsin9[~(squareWavePosition >> 9) & 511] << 3; + } + + if (cutoffVal < MIDDLE_CUTOFF_VALUE) { + // For the cutoff values below the cutoff middle point, it seems the amp of the resonance wave is expotentially decayed + logSampleValue += 31743 + ((MIDDLE_CUTOFF_VALUE - cutoffVal) >> 9); + } else if (cutoffVal < RESONANCE_DECAY_THRESHOLD_CUTOFF_VALUE) { + // For the cutoff values below this point, the amp of the resonance wave is sinusoidally decayed + Bit32u sineIx = (cutoffVal - MIDDLE_CUTOFF_VALUE) >> 13; + logSampleValue += Tables::getInstance().logsin9[sineIx] << 2; + } + + // After all the amp decrements are added, it should be safe now to adjust the amp of the resonance wave to what we see on captures + logSampleValue -= 1 << 12; + + resonanceLogSample.logValue = logSampleValue < 65536 ? (Bit16u)logSampleValue : 65535; + resonanceLogSample.sign = resonancePhase < NEGATIVE_FALLING_RESONANCE_SINE_SEGMENT ? LogSample::POSITIVE : LogSample::NEGATIVE; +} + +void LA32WaveGenerator::generateNextSawtoothCosineLogSample(LogSample &logSample) const { + Bit32u sawtoothCosinePosition = wavePosition + (1 << 18); + if ((sawtoothCosinePosition & (1 << 18)) > 0) { + logSample.logValue = Tables::getInstance().logsin9[~(sawtoothCosinePosition >> 9) & 511]; + } else { + logSample.logValue = Tables::getInstance().logsin9[(sawtoothCosinePosition >> 9) & 511]; + } + logSample.logValue <<= 2; + logSample.sign = ((sawtoothCosinePosition & (1 << 19)) == 0) ? LogSample::POSITIVE : LogSample::NEGATIVE; +} + +void LA32WaveGenerator::pcmSampleToLogSample(LogSample &logSample, const Bit16s pcmSample) const { + Bit32u logSampleValue = (32787 - (pcmSample & 32767)) << 1; + logSampleValue += amp >> 10; + logSample.logValue = logSampleValue < 65536 ? (Bit16u)logSampleValue : 65535; + logSample.sign = pcmSample < 0 ? LogSample::NEGATIVE : LogSample::POSITIVE; +} + +void LA32WaveGenerator::generateNextPCMWaveLogSamples() { + // This should emulate the ladder we see in the PCM captures for pitches 01, 02, 07, etc. + // The most probable cause is the factor in the interpolation formula is one bit less + // accurate than the sample position counter + pcmInterpolationFactor = (wavePosition & 255) >> 1; + Bit32u pcmWaveTableIx = wavePosition >> 8; + pcmSampleToLogSample(firstPCMLogSample, pcmWaveAddress[pcmWaveTableIx]); + if (pcmWaveInterpolated) { + pcmWaveTableIx++; + if (pcmWaveTableIx < pcmWaveLength) { + pcmSampleToLogSample(secondPCMLogSample, pcmWaveAddress[pcmWaveTableIx]); + } else { + if (pcmWaveLooped) { + pcmWaveTableIx -= pcmWaveLength; + pcmSampleToLogSample(secondPCMLogSample, pcmWaveAddress[pcmWaveTableIx]); + } else { + secondPCMLogSample = SILENCE; + } + } + } else { + secondPCMLogSample = SILENCE; + } + // pcmSampleStep = EXP2F(pitch / 4096. - 5.); + Bit32u pcmSampleStep = LA32Utilites::interpolateExp(~pitch & 4095); + pcmSampleStep <<= pitch >> 12; + // Seeing the actual lengths of the PCM wave for pitches 00..12, + // the pcmPosition counter can be assumed to have 8-bit fractions + pcmSampleStep >>= 9; + wavePosition += pcmSampleStep; + if (wavePosition >= (pcmWaveLength << 8)) { + if (pcmWaveLooped) { + wavePosition -= pcmWaveLength << 8; + } else { + deactivate(); + } + } +} + +void LA32WaveGenerator::initSynth(const bool useSawtoothWaveform, const Bit8u usePulseWidth, const Bit8u useResonance) { + sawtoothWaveform = useSawtoothWaveform; + pulseWidth = usePulseWidth; + resonance = useResonance; + + wavePosition = 0; + + squareWavePosition = 0; + phase = POSITIVE_RISING_SINE_SEGMENT; + + resonanceSinePosition = 0; + resonancePhase = POSITIVE_RISING_RESONANCE_SINE_SEGMENT; + resonanceAmpSubtraction = (32 - resonance) << 10; + resAmpDecayFactor = Tables::getInstance().resAmpDecayFactor[resonance >> 2] << 2; + + pcmWaveAddress = NULL; + active = true; +} + +void LA32WaveGenerator::initPCM(const Bit16s * const usePCMWaveAddress, const Bit32u usePCMWaveLength, const bool usePCMWaveLooped, const bool usePCMWaveInterpolated) { + pcmWaveAddress = usePCMWaveAddress; + pcmWaveLength = usePCMWaveLength; + pcmWaveLooped = usePCMWaveLooped; + pcmWaveInterpolated = usePCMWaveInterpolated; + + wavePosition = 0; + active = true; +} + +void LA32WaveGenerator::generateNextSample(const Bit32u useAmp, const Bit16u usePitch, const Bit32u useCutoffVal) { + if (!active) { + return; + } + + amp = useAmp; + pitch = usePitch; + + if (isPCMWave()) { + generateNextPCMWaveLogSamples(); + return; + } + + // The 240 cutoffVal limit was determined via sample analysis (internal Munt capture IDs: glop3, glop4). + // More research is needed to be sure that this is correct, however. + cutoffVal = (useCutoffVal > MAX_CUTOFF_VALUE) ? MAX_CUTOFF_VALUE : useCutoffVal; + + generateNextSquareWaveLogSample(); + generateNextResonanceWaveLogSample(); + if (sawtoothWaveform) { + LogSample cosineLogSample; + generateNextSawtoothCosineLogSample(cosineLogSample); + LA32Utilites::addLogSamples(squareLogSample, cosineLogSample); + LA32Utilites::addLogSamples(resonanceLogSample, cosineLogSample); + } + advancePosition(); +} + +LogSample LA32WaveGenerator::getOutputLogSample(const bool first) const { + if (!isActive()) { + return SILENCE; + } + if (isPCMWave()) { + return first ? firstPCMLogSample : secondPCMLogSample; + } + return first ? squareLogSample : resonanceLogSample; +} + +void LA32WaveGenerator::deactivate() { + active = false; +} + +bool LA32WaveGenerator::isActive() const { + return active; +} + +bool LA32WaveGenerator::isPCMWave() const { + return pcmWaveAddress != NULL; +} + +Bit32u LA32WaveGenerator::getPCMInterpolationFactor() const { + return pcmInterpolationFactor; +} + +void LA32PartialPair::init(const bool useRingModulated, const bool useMixed) { + ringModulated = useRingModulated; + mixed = useMixed; +} + +void LA32PartialPair::initSynth(const PairType useMaster, const bool sawtoothWaveform, const Bit8u pulseWidth, const Bit8u resonance) { + if (useMaster == MASTER) { + master.initSynth(sawtoothWaveform, pulseWidth, resonance); + } else { + slave.initSynth(sawtoothWaveform, pulseWidth, resonance); + } +} + +void LA32PartialPair::initPCM(const PairType useMaster, const Bit16s *pcmWaveAddress, const Bit32u pcmWaveLength, const bool pcmWaveLooped) { + if (useMaster == MASTER) { + master.initPCM(pcmWaveAddress, pcmWaveLength, pcmWaveLooped, true); + } else { + slave.initPCM(pcmWaveAddress, pcmWaveLength, pcmWaveLooped, !ringModulated); + } +} + +void LA32PartialPair::generateNextSample(const PairType useMaster, const Bit32u amp, const Bit16u pitch, const Bit32u cutoff) { + if (useMaster == MASTER) { + master.generateNextSample(amp, pitch, cutoff); + } else { + slave.generateNextSample(amp, pitch, cutoff); + } +} + +Bit16s LA32PartialPair::unlogAndMixWGOutput(const LA32WaveGenerator &wg, const LogSample * const ringModulatingLogSample) { + if (!wg.isActive() || ((ringModulatingLogSample != NULL) && (ringModulatingLogSample->logValue == SILENCE.logValue))) { + return 0; + } + LogSample firstLogSample = wg.getOutputLogSample(true); + LogSample secondLogSample = wg.getOutputLogSample(false); + if (ringModulatingLogSample != NULL) { + LA32Utilites::addLogSamples(firstLogSample, *ringModulatingLogSample); + LA32Utilites::addLogSamples(secondLogSample, *ringModulatingLogSample); + } + Bit16s firstSample = LA32Utilites::unlog(firstLogSample); + Bit16s secondSample = LA32Utilites::unlog(secondLogSample); + if (wg.isPCMWave()) { + return Bit16s(firstSample + ((Bit32s(secondSample - firstSample) * wg.getPCMInterpolationFactor()) >> 7)); + } + return firstSample + secondSample; +} + +Bit16s LA32PartialPair::nextOutSample() { + if (ringModulated) { + LogSample slaveFirstLogSample = slave.getOutputLogSample(true); + LogSample slaveSecondLogSample = slave.getOutputLogSample(false); + Bit16s sample = unlogAndMixWGOutput(master, &slaveFirstLogSample); + if (!slave.isPCMWave()) { + sample += unlogAndMixWGOutput(master, &slaveSecondLogSample); + } + if (mixed) { + sample += unlogAndMixWGOutput(master, NULL); + } + return sample; + } + return unlogAndMixWGOutput(master, NULL) + unlogAndMixWGOutput(slave, NULL); +} + +void LA32PartialPair::deactivate(const PairType useMaster) { + if (useMaster == MASTER) { + master.deactivate(); + } else { + slave.deactivate(); + } +} + +bool LA32PartialPair::isActive(const PairType useMaster) const { + return useMaster == MASTER ? master.isActive() : slave.isActive(); +} + +} + +#endif // #if MT32EMU_ACCURATE_WG == 0 diff --git a/audio/softsynth/mt32/LA32WaveGenerator.h b/audio/softsynth/mt32/LA32WaveGenerator.h new file mode 100644 index 0000000000..37a4aead85 --- /dev/null +++ b/audio/softsynth/mt32/LA32WaveGenerator.h @@ -0,0 +1,246 @@ +/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#if MT32EMU_ACCURATE_WG == 0 + +#ifndef MT32EMU_LA32_WAVE_GENERATOR_H +#define MT32EMU_LA32_WAVE_GENERATOR_H + +namespace MT32Emu { + +/** + * LA32 performs wave generation in the log-space that allows replacing multiplications by cheap additions + * It's assumed that only low-bit multiplications occur in a few places which are unavoidable like these: + * - interpolation of exponent table (obvious, a delta value has 4 bits) + * - computation of resonance amp decay envelope (the table contains values with 1-2 "1" bits except the very first value 31 but this case can be found using inversion) + * - interpolation of PCM samples (obvious, the wave position counter is in the linear space, there is no log() table in the chip) + * and it seems to be implemented in the same way as in the Boss chip, i.e. right shifted additions which involved noticeable precision loss + * Subtraction is supposed to be replaced by simple inversion + * As the logarithmic sine is always negative, all the logarithmic values are treated as decrements + */ +struct LogSample { + // 16-bit fixed point value, includes 12-bit fractional part + // 4-bit integer part allows to present any 16-bit sample in the log-space + // Obviously, the log value doesn't contain the sign of the resulting sample + Bit16u logValue; + enum { + POSITIVE, + NEGATIVE + } sign; +}; + +class LA32Utilites { +public: + static Bit16u interpolateExp(const Bit16u fract); + static Bit16s unlog(const LogSample &logSample); + static void addLogSamples(LogSample &logSample1, const LogSample &logSample2); +}; + +/** + * LA32WaveGenerator is aimed to represent the exact model of LA32 wave generator. + * The output square wave is created by adding high / low linear segments in-between + * the rising and falling cosine segments. Basically, it’s very similar to the phase distortion synthesis. + * Behaviour of a true resonance filter is emulated by adding decaying sine wave. + * The beginning and the ending of the resonant sine is multiplied by a cosine window. + * To synthesise sawtooth waves, the resulting square wave is multiplied by synchronous cosine wave. + */ +class LA32WaveGenerator { + //*************************************************************************** + // The local copy of partial parameters below + //*************************************************************************** + + bool active; + + // True means the resulting square wave is to be multiplied by the synchronous cosine + bool sawtoothWaveform; + + // Logarithmic amp of the wave generator + Bit32u amp; + + // Logarithmic frequency of the resulting wave + Bit16u pitch; + + // Values in range [1..31] + // Value 1 correspong to the minimum resonance + Bit8u resonance; + + // Processed value in range [0..255] + // Values in range [0..128] have no effect and the resulting wave remains symmetrical + // Value 255 corresponds to the maximum possible asymmetric of the resulting wave + Bit8u pulseWidth; + + // Composed of the base cutoff in range [78..178] left-shifted by 18 bits and the TVF modifier + Bit32u cutoffVal; + + // Logarithmic PCM sample start address + const Bit16s *pcmWaveAddress; + + // Logarithmic PCM sample length + Bit32u pcmWaveLength; + + // true for looped logarithmic PCM samples + bool pcmWaveLooped; + + // false for slave PCM partials in the structures with the ring modulation + bool pcmWaveInterpolated; + + //*************************************************************************** + // Internal variables below + //*************************************************************************** + + // Relative position within either the synth wave or the PCM sampled wave + // 0 - start of the positive rising sine segment of the square wave or start of the PCM sample + // 1048576 (2^20) - end of the negative rising sine segment of the square wave + // For PCM waves, the address of the currently playing sample equals (wavePosition / 256) + Bit32u wavePosition; + + // Relative position within a square wave phase: + // 0 - start of the phase + // 262144 (2^18) - end of a sine phase in the square wave + Bit32u squareWavePosition; + + // Relative position within the positive or negative wave segment: + // 0 - start of the corresponding positive or negative segment of the square wave + // 262144 (2^18) - corresponds to end of the first sine phase in the square wave + // The same increment sampleStep is used to indicate the current position + // since the length of the resonance wave is always equal to four square wave sine segments. + Bit32u resonanceSinePosition; + + // The amp of the resonance sine wave grows with the resonance value + // As the resonance value cannot change while the partial is active, it is initialised once + Bit32u resonanceAmpSubtraction; + + // The decay speed of resonance sine wave, depends on the resonance value + Bit32u resAmpDecayFactor; + + // Fractional part of the pcmPosition + Bit32u pcmInterpolationFactor; + + // Current phase of the square wave + enum { + POSITIVE_RISING_SINE_SEGMENT, + POSITIVE_LINEAR_SEGMENT, + POSITIVE_FALLING_SINE_SEGMENT, + NEGATIVE_FALLING_SINE_SEGMENT, + NEGATIVE_LINEAR_SEGMENT, + NEGATIVE_RISING_SINE_SEGMENT + } phase; + + // Current phase of the resonance wave + enum { + POSITIVE_RISING_RESONANCE_SINE_SEGMENT, + POSITIVE_FALLING_RESONANCE_SINE_SEGMENT, + NEGATIVE_FALLING_RESONANCE_SINE_SEGMENT, + NEGATIVE_RISING_RESONANCE_SINE_SEGMENT + } resonancePhase; + + // Resulting log-space samples of the square and resonance waves + LogSample squareLogSample; + LogSample resonanceLogSample; + + // Processed neighbour log-space samples of the PCM wave + LogSample firstPCMLogSample; + LogSample secondPCMLogSample; + + //*************************************************************************** + // Internal methods below + //*************************************************************************** + + Bit32u getSampleStep(); + Bit32u getResonanceWaveLengthFactor(Bit32u effectiveCutoffValue); + Bit32u getHighLinearLength(Bit32u effectiveCutoffValue); + + void computePositions(Bit32u highLinearLength, Bit32u lowLinearLength, Bit32u resonanceWaveLengthFactor); + void advancePosition(); + + void generateNextSquareWaveLogSample(); + void generateNextResonanceWaveLogSample(); + void generateNextSawtoothCosineLogSample(LogSample &logSample) const; + + void pcmSampleToLogSample(LogSample &logSample, const Bit16s pcmSample) const; + void generateNextPCMWaveLogSamples(); + +public: + // Initialise the WG engine for generation of synth partial samples and set up the invariant parameters + void initSynth(const bool sawtoothWaveform, const Bit8u pulseWidth, const Bit8u resonance); + + // Initialise the WG engine for generation of PCM partial samples and set up the invariant parameters + void initPCM(const Bit16s * const pcmWaveAddress, const Bit32u pcmWaveLength, const bool pcmWaveLooped, const bool pcmWaveInterpolated); + + // Update parameters with respect to TVP, TVA and TVF, and generate next sample + void generateNextSample(const Bit32u amp, const Bit16u pitch, const Bit32u cutoff); + + // WG output in the log-space consists of two components which are to be added (or ring modulated) in the linear-space afterwards + LogSample getOutputLogSample(const bool first) const; + + // Deactivate the WG engine + void deactivate(); + + // Return active state of the WG engine + bool isActive() const; + + // Return true if the WG engine generates PCM wave samples + bool isPCMWave() const; + + // Return current PCM interpolation factor + Bit32u getPCMInterpolationFactor() const; +}; + +// LA32PartialPair contains a structure of two partials being mixed / ring modulated +class LA32PartialPair { + LA32WaveGenerator master; + LA32WaveGenerator slave; + bool ringModulated; + bool mixed; + + static Bit16s unlogAndMixWGOutput(const LA32WaveGenerator &wg, const LogSample * const ringModulatingLogSample); + +public: + enum PairType { + MASTER, + SLAVE + }; + + // ringModulated should be set to false for the structures with mixing or stereo output + // ringModulated should be set to true for the structures with ring modulation + // mixed is used for the structures with ring modulation and indicates whether the master partial output is mixed to the ring modulator output + void init(const bool ringModulated, const bool mixed); + + // Initialise the WG engine for generation of synth partial samples and set up the invariant parameters + void initSynth(const PairType master, const bool sawtoothWaveform, const Bit8u pulseWidth, const Bit8u resonance); + + // Initialise the WG engine for generation of PCM partial samples and set up the invariant parameters + void initPCM(const PairType master, const Bit16s * const pcmWaveAddress, const Bit32u pcmWaveLength, const bool pcmWaveLooped); + + // Update parameters with respect to TVP, TVA and TVF, and generate next sample + void generateNextSample(const PairType master, const Bit32u amp, const Bit16u pitch, const Bit32u cutoff); + + // Perform mixing / ring modulation and return the result + Bit16s nextOutSample(); + + // Deactivate the WG engine + void deactivate(const PairType master); + + // Return active state of the WG engine + bool isActive(const PairType master) const; +}; + +} // namespace MT32Emu + +#endif // #ifndef MT32EMU_LA32_WAVE_GENERATOR_H + +#endif // #if MT32EMU_ACCURATE_WG == 0 diff --git a/audio/softsynth/mt32/LegacyWaveGenerator.cpp b/audio/softsynth/mt32/LegacyWaveGenerator.cpp new file mode 100644 index 0000000000..35ca975018 --- /dev/null +++ b/audio/softsynth/mt32/LegacyWaveGenerator.cpp @@ -0,0 +1,347 @@ +/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +//#include <cmath> +#include "mt32emu.h" +#include "mmath.h" +#include "LegacyWaveGenerator.h" + +#if MT32EMU_ACCURATE_WG == 1 + +namespace MT32Emu { + +static const float MIDDLE_CUTOFF_VALUE = 128.0f; +static const float RESONANCE_DECAY_THRESHOLD_CUTOFF_VALUE = 144.0f; +static const float MAX_CUTOFF_VALUE = 240.0f; + +float LA32WaveGenerator::getPCMSample(unsigned int position) { + if (position >= pcmWaveLength) { + if (!pcmWaveLooped) { + return 0; + } + position = position % pcmWaveLength; + } + Bit16s pcmSample = pcmWaveAddress[position]; + float sampleValue = EXP2F(((pcmSample & 32767) - 32787.0f) / 2048.0f); + return ((pcmSample & 32768) == 0) ? sampleValue : -sampleValue; +} + +void LA32WaveGenerator::initSynth(const bool sawtoothWaveform, const Bit8u pulseWidth, const Bit8u resonance) { + this->sawtoothWaveform = sawtoothWaveform; + this->pulseWidth = pulseWidth; + this->resonance = resonance; + + wavePos = 0.0f; + lastFreq = 0.0f; + + pcmWaveAddress = NULL; + active = true; +} + +void LA32WaveGenerator::initPCM(const Bit16s * const pcmWaveAddress, const Bit32u pcmWaveLength, const bool pcmWaveLooped, const bool pcmWaveInterpolated) { + this->pcmWaveAddress = pcmWaveAddress; + this->pcmWaveLength = pcmWaveLength; + this->pcmWaveLooped = pcmWaveLooped; + this->pcmWaveInterpolated = pcmWaveInterpolated; + + pcmPosition = 0.0f; + active = true; +} + +float LA32WaveGenerator::generateNextSample(const Bit32u ampVal, const Bit16u pitch, const Bit32u cutoffRampVal) { + if (!active) { + return 0.0f; + } + + this->amp = amp; + this->pitch = pitch; + + float sample = 0.0f; + + // SEMI-CONFIRMED: From sample analysis: + // (1) Tested with a single partial playing PCM wave 77 with pitchCoarse 36 and no keyfollow, velocity follow, etc. + // This gives results within +/- 2 at the output (before any DAC bitshifting) + // when sustaining at levels 156 - 255 with no modifiers. + // (2) Tested with a special square wave partial (internal capture ID tva5) at TVA envelope levels 155-255. + // This gives deltas between -1 and 0 compared to the real output. Note that this special partial only produces + // positive amps, so negative still needs to be explored, as well as lower levels. + // + // Also still partially unconfirmed is the behaviour when ramping between levels, as well as the timing. + + float amp = EXP2F(ampVal / -1024.0f / 4096.0f); + float freq = EXP2F(pitch / 4096.0f - 16.0f) * SAMPLE_RATE; + + if (isPCMWave()) { + // Render PCM waveform + int len = pcmWaveLength; + int intPCMPosition = (int)pcmPosition; + if (intPCMPosition >= len && !pcmWaveLooped) { + // We're now past the end of a non-looping PCM waveform so it's time to die. + deactivate(); + return 0.0f; + } + float positionDelta = freq * 2048.0f / SAMPLE_RATE; + + // Linear interpolation + float firstSample = getPCMSample(intPCMPosition); + // We observe that for partial structures with ring modulation the interpolation is not applied to the slave PCM partial. + // It's assumed that the multiplication circuitry intended to perform the interpolation on the slave PCM partial + // is borrowed by the ring modulation circuit (or the LA32 chip has a similar lack of resources assigned to each partial pair). + if (pcmWaveInterpolated) { + sample = firstSample + (getPCMSample(intPCMPosition + 1) - firstSample) * (pcmPosition - intPCMPosition); + } else { + sample = firstSample; + } + + float newPCMPosition = pcmPosition + positionDelta; + if (pcmWaveLooped) { + newPCMPosition = fmod(newPCMPosition, (float)pcmWaveLength); + } + pcmPosition = newPCMPosition; + } else { + // Render synthesised waveform + wavePos *= lastFreq / freq; + lastFreq = freq; + + float resAmp = EXP2F(1.0f - (32 - resonance) / 4.0f); + { + //static const float resAmpFactor = EXP2F(-7); + //resAmp = EXP2I(resonance << 10) * resAmpFactor; + } + + // The cutoffModifier may not be supposed to be directly added to the cutoff - + // it may for example need to be multiplied in some way. + // The 240 cutoffVal limit was determined via sample analysis (internal Munt capture IDs: glop3, glop4). + // More research is needed to be sure that this is correct, however. + float cutoffVal = cutoffRampVal / 262144.0f; + if (cutoffVal > MAX_CUTOFF_VALUE) { + cutoffVal = MAX_CUTOFF_VALUE; + } + + // Wave length in samples + float waveLen = SAMPLE_RATE / freq; + + // Init cosineLen + float cosineLen = 0.5f * waveLen; + if (cutoffVal > MIDDLE_CUTOFF_VALUE) { + cosineLen *= EXP2F((cutoffVal - MIDDLE_CUTOFF_VALUE) / -16.0f); // found from sample analysis + } + + // Start playing in center of first cosine segment + // relWavePos is shifted by a half of cosineLen + float relWavePos = wavePos + 0.5f * cosineLen; + if (relWavePos > waveLen) { + relWavePos -= waveLen; + } + + // Ratio of positive segment to wave length + float pulseLen = 0.5f; + if (pulseWidth > 128) { + pulseLen = EXP2F((64 - pulseWidth) / 64.0f); + //static const float pulseLenFactor = EXP2F(-192 / 64); + //pulseLen = EXP2I((256 - pulseWidthVal) << 6) * pulseLenFactor; + } + pulseLen *= waveLen; + + float hLen = pulseLen - cosineLen; + + // Ignore pulsewidths too high for given freq + if (hLen < 0.0f) { + hLen = 0.0f; + } + + // Ignore pulsewidths too high for given freq and cutoff + float lLen = waveLen - hLen - 2 * cosineLen; + if (lLen < 0.0f) { + lLen = 0.0f; + } + + // Correct resAmp for cutoff in range 50..66 + if ((cutoffVal >= 128.0f) && (cutoffVal < 144.0f)) { + resAmp *= sin(FLOAT_PI * (cutoffVal - 128.0f) / 32.0f); + } + + // Produce filtered square wave with 2 cosine waves on slopes + + // 1st cosine segment + if (relWavePos < cosineLen) { + sample = -cos(FLOAT_PI * relWavePos / cosineLen); + } else + + // high linear segment + if (relWavePos < (cosineLen + hLen)) { + sample = 1.f; + } else + + // 2nd cosine segment + if (relWavePos < (2 * cosineLen + hLen)) { + sample = cos(FLOAT_PI * (relWavePos - (cosineLen + hLen)) / cosineLen); + } else { + + // low linear segment + sample = -1.f; + } + + if (cutoffVal < 128.0f) { + + // Attenuate samples below cutoff 50 + // Found by sample analysis + sample *= EXP2F(-0.125f * (128.0f - cutoffVal)); + } else { + + // Add resonance sine. Effective for cutoff > 50 only + float resSample = 1.0f; + + // Resonance decay speed factor + float resAmpDecayFactor = Tables::getInstance().resAmpDecayFactor[resonance >> 2]; + + // Now relWavePos counts from the middle of first cosine + relWavePos = wavePos; + + // negative segments + if (!(relWavePos < (cosineLen + hLen))) { + resSample = -resSample; + relWavePos -= cosineLen + hLen; + + // From the digital captures, the decaying speed of the resonance sine is found a bit different for the positive and the negative segments + resAmpDecayFactor += 0.25f; + } + + // Resonance sine WG + resSample *= sin(FLOAT_PI * relWavePos / cosineLen); + + // Resonance sine amp + float resAmpFadeLog2 = -0.125f * resAmpDecayFactor * (relWavePos / cosineLen); // seems to be exact + float resAmpFade = EXP2F(resAmpFadeLog2); + + // Now relWavePos set negative to the left from center of any cosine + relWavePos = wavePos; + + // negative segment + if (!(wavePos < (waveLen - 0.5f * cosineLen))) { + relWavePos -= waveLen; + } else + + // positive segment + if (!(wavePos < (hLen + 0.5f * cosineLen))) { + relWavePos -= cosineLen + hLen; + } + + // To ensure the output wave has no breaks, two different windows are appied to the beginning and the ending of the resonance sine segment + if (relWavePos < 0.5f * cosineLen) { + float syncSine = sin(FLOAT_PI * relWavePos / cosineLen); + if (relWavePos < 0.0f) { + // The window is synchronous square sine here + resAmpFade *= syncSine * syncSine; + } else { + // The window is synchronous sine here + resAmpFade *= syncSine; + } + } + + sample += resSample * resAmp * resAmpFade; + } + + // sawtooth waves + if (sawtoothWaveform) { + sample *= cos(FLOAT_2PI * wavePos / waveLen); + } + + wavePos++; + + // wavePos isn't supposed to be > waveLen + if (wavePos > waveLen) { + wavePos -= waveLen; + } + } + + // Multiply sample with current TVA value + sample *= amp; + return sample; +} + +void LA32WaveGenerator::deactivate() { + active = false; +} + +bool LA32WaveGenerator::isActive() const { + return active; +} + +bool LA32WaveGenerator::isPCMWave() const { + return pcmWaveAddress != NULL; +} + +void LA32PartialPair::init(const bool ringModulated, const bool mixed) { + this->ringModulated = ringModulated; + this->mixed = mixed; + masterOutputSample = 0.0f; + slaveOutputSample = 0.0f; +} + +void LA32PartialPair::initSynth(const PairType useMaster, const bool sawtoothWaveform, const Bit8u pulseWidth, const Bit8u resonance) { + if (useMaster == MASTER) { + master.initSynth(sawtoothWaveform, pulseWidth, resonance); + } else { + slave.initSynth(sawtoothWaveform, pulseWidth, resonance); + } +} + +void LA32PartialPair::initPCM(const PairType useMaster, const Bit16s *pcmWaveAddress, const Bit32u pcmWaveLength, const bool pcmWaveLooped) { + if (useMaster == MASTER) { + master.initPCM(pcmWaveAddress, pcmWaveLength, pcmWaveLooped, true); + } else { + slave.initPCM(pcmWaveAddress, pcmWaveLength, pcmWaveLooped, !ringModulated); + } +} + +void LA32PartialPair::generateNextSample(const PairType useMaster, const Bit32u amp, const Bit16u pitch, const Bit32u cutoff) { + if (useMaster == MASTER) { + masterOutputSample = master.generateNextSample(amp, pitch, cutoff); + } else { + slaveOutputSample = slave.generateNextSample(amp, pitch, cutoff); + } +} + +Bit16s LA32PartialPair::nextOutSample() { + float outputSample; + if (ringModulated) { + float ringModulatedSample = masterOutputSample * slaveOutputSample; + outputSample = mixed ? masterOutputSample + ringModulatedSample : ringModulatedSample; + } else { + outputSample = masterOutputSample + slaveOutputSample; + } + return Bit16s(outputSample * 8192.0f); +} + +void LA32PartialPair::deactivate(const PairType useMaster) { + if (useMaster == MASTER) { + master.deactivate(); + masterOutputSample = 0.0f; + } else { + slave.deactivate(); + slaveOutputSample = 0.0f; + } +} + +bool LA32PartialPair::isActive(const PairType useMaster) const { + return useMaster == MASTER ? master.isActive() : slave.isActive(); +} + +} + +#endif // #if MT32EMU_ACCURATE_WG == 1 diff --git a/audio/softsynth/mt32/LegacyWaveGenerator.h b/audio/softsynth/mt32/LegacyWaveGenerator.h new file mode 100644 index 0000000000..81c1b9c713 --- /dev/null +++ b/audio/softsynth/mt32/LegacyWaveGenerator.h @@ -0,0 +1,146 @@ +/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#if MT32EMU_ACCURATE_WG == 1 + +#ifndef MT32EMU_LA32_WAVE_GENERATOR_H +#define MT32EMU_LA32_WAVE_GENERATOR_H + +namespace MT32Emu { + +/** + * LA32WaveGenerator is aimed to represent the exact model of LA32 wave generator. + * The output square wave is created by adding high / low linear segments in-between + * the rising and falling cosine segments. Basically, it’s very similar to the phase distortion synthesis. + * Behaviour of a true resonance filter is emulated by adding decaying sine wave. + * The beginning and the ending of the resonant sine is multiplied by a cosine window. + * To synthesise sawtooth waves, the resulting square wave is multiplied by synchronous cosine wave. + */ +class LA32WaveGenerator { + //*************************************************************************** + // The local copy of partial parameters below + //*************************************************************************** + + bool active; + + // True means the resulting square wave is to be multiplied by the synchronous cosine + bool sawtoothWaveform; + + // Logarithmic amp of the wave generator + Bit32u amp; + + // Logarithmic frequency of the resulting wave + Bit16u pitch; + + // Values in range [1..31] + // Value 1 correspong to the minimum resonance + Bit8u resonance; + + // Processed value in range [0..255] + // Values in range [0..128] have no effect and the resulting wave remains symmetrical + // Value 255 corresponds to the maximum possible asymmetric of the resulting wave + Bit8u pulseWidth; + + // Composed of the base cutoff in range [78..178] left-shifted by 18 bits and the TVF modifier + Bit32u cutoffVal; + + // Logarithmic PCM sample start address + const Bit16s *pcmWaveAddress; + + // Logarithmic PCM sample length + Bit32u pcmWaveLength; + + // true for looped logarithmic PCM samples + bool pcmWaveLooped; + + // false for slave PCM partials in the structures with the ring modulation + bool pcmWaveInterpolated; + + //*************************************************************************** + // Internal variables below + //*************************************************************************** + + float wavePos; + float lastFreq; + float pcmPosition; + + float getPCMSample(unsigned int position); + +public: + // Initialise the WG engine for generation of synth partial samples and set up the invariant parameters + void initSynth(const bool sawtoothWaveform, const Bit8u pulseWidth, const Bit8u resonance); + + // Initialise the WG engine for generation of PCM partial samples and set up the invariant parameters + void initPCM(const Bit16s * const pcmWaveAddress, const Bit32u pcmWaveLength, const bool pcmWaveLooped, const bool pcmWaveInterpolated); + + // Update parameters with respect to TVP, TVA and TVF, and generate next sample + float generateNextSample(const Bit32u amp, const Bit16u pitch, const Bit32u cutoff); + + // Deactivate the WG engine + void deactivate(); + + // Return active state of the WG engine + bool isActive() const; + + // Return true if the WG engine generates PCM wave samples + bool isPCMWave() const; +}; + +// LA32PartialPair contains a structure of two partials being mixed / ring modulated +class LA32PartialPair { + LA32WaveGenerator master; + LA32WaveGenerator slave; + bool ringModulated; + bool mixed; + float masterOutputSample; + float slaveOutputSample; + +public: + enum PairType { + MASTER, + SLAVE + }; + + // ringModulated should be set to false for the structures with mixing or stereo output + // ringModulated should be set to true for the structures with ring modulation + // mixed is used for the structures with ring modulation and indicates whether the master partial output is mixed to the ring modulator output + void init(const bool ringModulated, const bool mixed); + + // Initialise the WG engine for generation of synth partial samples and set up the invariant parameters + void initSynth(const PairType master, const bool sawtoothWaveform, const Bit8u pulseWidth, const Bit8u resonance); + + // Initialise the WG engine for generation of PCM partial samples and set up the invariant parameters + void initPCM(const PairType master, const Bit16s * const pcmWaveAddress, const Bit32u pcmWaveLength, const bool pcmWaveLooped); + + // Update parameters with respect to TVP, TVA and TVF, and generate next sample + void generateNextSample(const PairType master, const Bit32u amp, const Bit16u pitch, const Bit32u cutoff); + + // Perform mixing / ring modulation and return the result + Bit16s nextOutSample(); + + // Deactivate the WG engine + void deactivate(const PairType master); + + // Return active state of the WG engine + bool isActive(const PairType master) const; +}; + +} // namespace MT32Emu + +#endif // #ifndef MT32EMU_LA32_WAVE_GENERATOR_H + +#endif // #if MT32EMU_ACCURATE_WG == 1 diff --git a/audio/softsynth/mt32/Part.cpp b/audio/softsynth/mt32/Part.cpp index cd385898e1..62ba346c35 100644 --- a/audio/softsynth/mt32/Part.cpp +++ b/audio/softsynth/mt32/Part.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/Part.h b/audio/softsynth/mt32/Part.h index e5be41ff10..b6585880fe 100644 --- a/audio/softsynth/mt32/Part.h +++ b/audio/softsynth/mt32/Part.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/Partial.cpp b/audio/softsynth/mt32/Partial.cpp index a4d1ab03fa..a0aec90ec4 100644 --- a/audio/softsynth/mt32/Partial.cpp +++ b/audio/softsynth/mt32/Partial.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -35,7 +35,12 @@ static const float PAN_NUMERATOR_MASTER[] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, static const float PAN_NUMERATOR_SLAVE[] = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 7.0f, 7.0f, 7.0f, 7.0f, 7.0f, 7.0f, 7.0f}; Partial::Partial(Synth *useSynth, int useDebugPartialNum) : - synth(useSynth), debugPartialNum(useDebugPartialNum), sampleNum(0), tva(new TVA(this, &Ramp)), tvp(new TVP(this)), tvf(new TVF(this, &cutoffModifierRamp)) { + synth(useSynth), debugPartialNum(useDebugPartialNum), sampleNum(0) { + // Initialisation of tva, tvp and tvf uses 'this' pointer + // and thus should not be in the initializer list to avoid a compiler warning + tva = new TVA(this, &Ramp); + tvp = new TVP(this); + tvf = new TVF(this, &cutoffModifierRamp); ownerPart = -1; poly = NULL; pair = NULL; @@ -81,27 +86,23 @@ void Partial::deactivate() { ownerPart = -1; if (poly != NULL) { poly->partialDeactivated(this); - if (pair != NULL) { - pair->pair = NULL; - } } synth->partialStateChanged(this, tva->getPhase(), TVA_PHASE_DEAD); #if MT32EMU_MONITOR_PARTIALS > 2 synth->printDebug("[+%lu] [Partial %d] Deactivated", sampleNum, debugPartialNum); synth->printPartialUsage(sampleNum); #endif -} - -// DEPRECATED: This should probably go away eventually, it's currently only used as a kludge to protect our old assumptions that -// rhythm part notes were always played as key MIDDLEC. -int Partial::getKey() const { - if (poly == NULL) { - return -1; - } else if (ownerPart == 8) { - // FIXME: Hack, should go away after new pitch stuff is committed (and possibly some TVF changes) - return MIDDLEC; + if (isRingModulatingSlave()) { + pair->la32Pair.deactivate(LA32PartialPair::SLAVE); } else { - return poly->getKey(); + la32Pair.deactivate(LA32PartialPair::MASTER); + if (hasRingModulatingSlave()) { + pair->deactivate(); + pair = NULL; + } + } + if (pair != NULL) { + pair->pair = NULL; } } @@ -164,8 +165,6 @@ void Partial::startPartial(const Part *part, Poly *usePoly, const PatchCache *us pcmWave = &synth->pcmWaves[pcmNum]; } else { pcmWave = NULL; - wavePos = 0.0f; - lastFreq = 0.0; } // CONFIRMED: pulseWidthVal calculation is based on information from Mok @@ -176,26 +175,65 @@ void Partial::startPartial(const Part *part, Poly *usePoly, const PatchCache *us pulseWidthVal = 255; } - pcmPosition = 0.0f; pair = pairPartial; alreadyOutputed = false; tva->reset(part, patchCache->partialParam, rhythmTemp); tvp->reset(part, patchCache->partialParam); tvf->reset(patchCache->partialParam, tvp->getBasePitch()); + + LA32PartialPair::PairType pairType; + LA32PartialPair *useLA32Pair; + if (isRingModulatingSlave()) { + pairType = LA32PartialPair::SLAVE; + useLA32Pair = &pair->la32Pair; + } else { + pairType = LA32PartialPair::MASTER; + la32Pair.init(hasRingModulatingSlave(), mixType == 1); + useLA32Pair = &la32Pair; + } + if (isPCM()) { + useLA32Pair->initPCM(pairType, &synth->pcmROMData[pcmWave->addr], pcmWave->len, pcmWave->loop); + } else { + useLA32Pair->initSynth(pairType, (patchCache->waveform & 1) != 0, pulseWidthVal, patchCache->srcPartial.tvf.resonance + 1); + } + if (!hasRingModulatingSlave()) { + la32Pair.deactivate(LA32PartialPair::SLAVE); + } + // Temporary integration hack + stereoVolume.leftVol /= 8192.0f; + stereoVolume.rightVol /= 8192.0f; } -float Partial::getPCMSample(unsigned int position) { - if (position >= pcmWave->len) { - if (!pcmWave->loop) { - return 0; - } - position = position % pcmWave->len; +Bit32u Partial::getAmpValue() { + // SEMI-CONFIRMED: From sample analysis: + // (1) Tested with a single partial playing PCM wave 77 with pitchCoarse 36 and no keyfollow, velocity follow, etc. + // This gives results within +/- 2 at the output (before any DAC bitshifting) + // when sustaining at levels 156 - 255 with no modifiers. + // (2) Tested with a special square wave partial (internal capture ID tva5) at TVA envelope levels 155-255. + // This gives deltas between -1 and 0 compared to the real output. Note that this special partial only produces + // positive amps, so negative still needs to be explored, as well as lower levels. + // + // Also still partially unconfirmed is the behaviour when ramping between levels, as well as the timing. + // TODO: The tests above were performed using the float model, to be refined + Bit32u ampRampVal = 67117056 - ampRamp.nextValue(); + if (ampRamp.checkInterrupt()) { + tva->handleInterrupt(); } - return synth->pcmROMData[pcmWave->addr + position]; + return ampRampVal; } -unsigned long Partial::generateSamples(float *partialBuf, unsigned long length) { - const Tables &tables = Tables::getInstance(); +Bit32u Partial::getCutoffValue() { + if (isPCM()) { + return 0; + } + Bit32u cutoffModifierRampVal = cutoffModifierRamp.nextValue(); + if (cutoffModifierRamp.checkInterrupt()) { + tvf->handleInterrupt(); + } + return (tvf->getBaseCutoff() << 18) + cutoffModifierRampVal; +} + +unsigned long Partial::generateSamples(Bit16s *partialBuf, unsigned long length) { if (!isActive() || alreadyOutputed) { return 0; } @@ -203,310 +241,31 @@ unsigned long Partial::generateSamples(float *partialBuf, unsigned long length) synth->printDebug("[Partial %d] *** ERROR: poly is NULL at Partial::generateSamples()!", debugPartialNum); return 0; } - alreadyOutputed = true; - // Generate samples - for (sampleNum = 0; sampleNum < length; sampleNum++) { - float sample = 0; - Bit32u ampRampVal = ampRamp.nextValue(); - if (ampRamp.checkInterrupt()) { - tva->handleInterrupt(); - } - if (!tva->isPlaying()) { + if (!tva->isPlaying() || !la32Pair.isActive(LA32PartialPair::MASTER)) { deactivate(); break; } - - Bit16u pitch = tvp->nextPitch(); - - // SEMI-CONFIRMED: From sample analysis: - // (1) Tested with a single partial playing PCM wave 77 with pitchCoarse 36 and no keyfollow, velocity follow, etc. - // This gives results within +/- 2 at the output (before any DAC bitshifting) - // when sustaining at levels 156 - 255 with no modifiers. - // (2) Tested with a special square wave partial (internal capture ID tva5) at TVA envelope levels 155-255. - // This gives deltas between -1 and 0 compared to the real output. Note that this special partial only produces - // positive amps, so negative still needs to be explored, as well as lower levels. - // - // Also still partially unconfirmed is the behaviour when ramping between levels, as well as the timing. - -#if MT32EMU_ACCURATE_WG == 1 - float amp = EXP2F((32772 - ampRampVal / 2048) / -2048.0f); - float freq = EXP2F(pitch / 4096.0f - 16.0f) * SAMPLE_RATE; -#else - static const float ampFactor = EXP2F(32772 / -2048.0f); - float amp = EXP2I(ampRampVal >> 10) * ampFactor; - - static const float freqFactor = EXP2F(-16.0f) * SAMPLE_RATE; - float freq = EXP2I(pitch) * freqFactor; -#endif - - if (patchCache->PCMPartial) { - // Render PCM waveform - int len = pcmWave->len; - int intPCMPosition = (int)pcmPosition; - if (intPCMPosition >= len && !pcmWave->loop) { - // We're now past the end of a non-looping PCM waveform so it's time to die. - deactivate(); - break; - } - Bit32u pcmAddr = pcmWave->addr; - float positionDelta = freq * 2048.0f / SAMPLE_RATE; - - // Linear interpolation - float firstSample = synth->pcmROMData[pcmAddr + intPCMPosition]; - // We observe that for partial structures with ring modulation the interpolation is not applied to the slave PCM partial. - // It's assumed that the multiplication circuitry intended to perform the interpolation on the slave PCM partial - // is borrowed by the ring modulation circuit (or the LA32 chip has a similar lack of resources assigned to each partial pair). - if (pair == NULL || mixType == 0 || structurePosition == 0) { - sample = firstSample + (getPCMSample(intPCMPosition + 1) - firstSample) * (pcmPosition - intPCMPosition); - } else { - sample = firstSample; - } - - float newPCMPosition = pcmPosition + positionDelta; - if (pcmWave->loop) { - newPCMPosition = fmod(newPCMPosition, (float)pcmWave->len); - } - pcmPosition = newPCMPosition; - } else { - // Render synthesised waveform - wavePos *= lastFreq / freq; - lastFreq = freq; - - Bit32u cutoffModifierRampVal = cutoffModifierRamp.nextValue(); - if (cutoffModifierRamp.checkInterrupt()) { - tvf->handleInterrupt(); - } - float cutoffModifier = cutoffModifierRampVal / 262144.0f; - - // res corresponds to a value set in an LA32 register - Bit8u res = patchCache->srcPartial.tvf.resonance + 1; - - float resAmp; - { - // resAmp = EXP2F(1.0f - (32 - res) / 4.0f); - static const float resAmpFactor = EXP2F(-7); - resAmp = EXP2I(res << 10) * resAmpFactor; - } - - // The cutoffModifier may not be supposed to be directly added to the cutoff - - // it may for example need to be multiplied in some way. - // The 240 cutoffVal limit was determined via sample analysis (internal Munt capture IDs: glop3, glop4). - // More research is needed to be sure that this is correct, however. - float cutoffVal = tvf->getBaseCutoff() + cutoffModifier; - if (cutoffVal > 240.0f) { - cutoffVal = 240.0f; - } - - // Wave length in samples - float waveLen = SAMPLE_RATE / freq; - - // Init cosineLen - float cosineLen = 0.5f * waveLen; - if (cutoffVal > 128.0f) { -#if MT32EMU_ACCURATE_WG == 1 - cosineLen *= EXP2F((cutoffVal - 128.0f) / -16.0f); // found from sample analysis -#else - static const float cosineLenFactor = EXP2F(128.0f / -16.0f); - cosineLen *= EXP2I(Bit32u((256.0f - cutoffVal) * 256.0f)) * cosineLenFactor; -#endif - } - - // Start playing in center of first cosine segment - // relWavePos is shifted by a half of cosineLen - float relWavePos = wavePos + 0.5f * cosineLen; - if (relWavePos > waveLen) { - relWavePos -= waveLen; - } - - // Ratio of positive segment to wave length - float pulseLen = 0.5f; - if (pulseWidthVal > 128) { - // pulseLen = EXP2F((64 - pulseWidthVal) / 64); - static const float pulseLenFactor = EXP2F(-192 / 64); - pulseLen = EXP2I((256 - pulseWidthVal) << 6) * pulseLenFactor; - } - pulseLen *= waveLen; - - float hLen = pulseLen - cosineLen; - - // Ignore pulsewidths too high for given freq - if (hLen < 0.0f) { - hLen = 0.0f; - } - - // Ignore pulsewidths too high for given freq and cutoff - float lLen = waveLen - hLen - 2 * cosineLen; - if (lLen < 0.0f) { - lLen = 0.0f; - } - - // Correct resAmp for cutoff in range 50..66 - if ((cutoffVal >= 128.0f) && (cutoffVal < 144.0f)) { -#if MT32EMU_ACCURATE_WG == 1 - resAmp *= sinf(FLOAT_PI * (cutoffVal - 128.0f) / 32.0f); -#else - resAmp *= tables.sinf10[Bit32u(64 * (cutoffVal - 128.0f))]; -#endif - } - - // Produce filtered square wave with 2 cosine waves on slopes - - // 1st cosine segment - if (relWavePos < cosineLen) { -#if MT32EMU_ACCURATE_WG == 1 - sample = -cosf(FLOAT_PI * relWavePos / cosineLen); -#else - sample = -tables.sinf10[Bit32u(2048.0f * relWavePos / cosineLen) + 1024]; -#endif - } else - - // high linear segment - if (relWavePos < (cosineLen + hLen)) { - sample = 1.f; - } else - - // 2nd cosine segment - if (relWavePos < (2 * cosineLen + hLen)) { -#if MT32EMU_ACCURATE_WG == 1 - sample = cosf(FLOAT_PI * (relWavePos - (cosineLen + hLen)) / cosineLen); -#else - sample = tables.sinf10[Bit32u(2048.0f * (relWavePos - (cosineLen + hLen)) / cosineLen) + 1024]; -#endif - } else { - - // low linear segment - sample = -1.f; - } - - if (cutoffVal < 128.0f) { - - // Attenuate samples below cutoff 50 - // Found by sample analysis -#if MT32EMU_ACCURATE_WG == 1 - sample *= EXP2F(-0.125f * (128.0f - cutoffVal)); -#else - static const float cutoffAttenuationFactor = EXP2F(-0.125f * 128.0f); - sample *= EXP2I(Bit32u(512.0f * cutoffVal)) * cutoffAttenuationFactor; -#endif - } else { - - // Add resonance sine. Effective for cutoff > 50 only - float resSample = 1.0f; - - // Now relWavePos counts from the middle of first cosine - relWavePos = wavePos; - - // negative segments - if (!(relWavePos < (cosineLen + hLen))) { - resSample = -resSample; - relWavePos -= cosineLen + hLen; + la32Pair.generateNextSample(LA32PartialPair::MASTER, getAmpValue(), tvp->nextPitch(), getCutoffValue()); + if (hasRingModulatingSlave()) { + la32Pair.generateNextSample(LA32PartialPair::SLAVE, pair->getAmpValue(), pair->tvp->nextPitch(), pair->getCutoffValue()); + if (!pair->tva->isPlaying() || !la32Pair.isActive(LA32PartialPair::SLAVE)) { + pair->deactivate(); + if (mixType == 2) { + deactivate(); + break; } - - // Resonance sine WG -#if MT32EMU_ACCURATE_WG == 1 - resSample *= sinf(FLOAT_PI * relWavePos / cosineLen); -#else - resSample *= tables.sinf10[Bit32u(2048.0f * relWavePos / cosineLen) & 4095]; -#endif - - // Resonance sine amp - float resAmpFadeLog2 = -tables.resAmpFadeFactor[res >> 2] * (relWavePos / cosineLen); // seems to be exact -#if MT32EMU_ACCURATE_WG == 1 - float resAmpFade = EXP2F(resAmpFadeLog2); -#else - static const float resAmpFadeFactor = EXP2F(-30.0f); - float resAmpFade = (resAmpFadeLog2 < -30.0f) ? 0.0f : EXP2I(Bit32u((30.0f + resAmpFadeLog2) * 4096.0f)) * resAmpFadeFactor; -#endif - - // Now relWavePos set negative to the left from center of any cosine - relWavePos = wavePos; - - // negative segment - if (!(wavePos < (waveLen - 0.5f * cosineLen))) { - relWavePos -= waveLen; - } else - - // positive segment - if (!(wavePos < (hLen + 0.5f * cosineLen))) { - relWavePos -= cosineLen + hLen; - } - - // Fading to zero while within cosine segments to avoid jumps in the wave - // Sample analysis suggests that this window is very close to cosine - if (relWavePos < 0.5f * cosineLen) { -#if MT32EMU_ACCURATE_WG == 1 - resAmpFade *= 0.5f * (1.0f - cosf(FLOAT_PI * relWavePos / (0.5f * cosineLen))); -#else - resAmpFade *= 0.5f * (1.0f + tables.sinf10[Bit32s(2048.0f * relWavePos / (0.5f * cosineLen)) + 3072]); -#endif - } - - sample += resSample * resAmp * resAmpFade; - } - - // sawtooth waves - if ((patchCache->waveform & 1) != 0) { -#if MT32EMU_ACCURATE_WG == 1 - sample *= cosf(FLOAT_2PI * wavePos / waveLen); -#else - sample *= tables.sinf10[(Bit32u(4096.0f * wavePos / waveLen) & 4095) + 1024]; -#endif - } - - wavePos++; - - // wavePos isn't supposed to be > waveLen - if (wavePos > waveLen) { - wavePos -= waveLen; } } - - // Multiply sample with current TVA value - sample *= amp; - *partialBuf++ = sample; + *partialBuf++ = la32Pair.nextOutSample(); } unsigned long renderedSamples = sampleNum; sampleNum = 0; return renderedSamples; } -float *Partial::mixBuffersRingMix(float *buf1, float *buf2, unsigned long len) { - if (buf1 == NULL) { - return NULL; - } - if (buf2 == NULL) { - return buf1; - } - - while (len--) { - // FIXME: At this point we have no idea whether this is remotely correct... - *buf1 = *buf1 * *buf2 + *buf1; - buf1++; - buf2++; - } - return buf1; -} - -float *Partial::mixBuffersRing(float *buf1, float *buf2, unsigned long len) { - if (buf1 == NULL) { - return NULL; - } - if (buf2 == NULL) { - return NULL; - } - - while (len--) { - // FIXME: At this point we have no idea whether this is remotely correct... - *buf1 = *buf1 * *buf2; - buf1++; - buf2++; - } - return buf1; -} - bool Partial::hasRingModulatingSlave() const { return pair != NULL && structurePosition == 0 && (mixType == 1 || mixType == 2); } @@ -538,53 +297,14 @@ bool Partial::produceOutput(float *leftBuf, float *rightBuf, unsigned long lengt synth->printDebug("[Partial %d] *** ERROR: poly is NULL at Partial::produceOutput()!", debugPartialNum); return false; } - - float *partialBuf = &myBuffer[0]; - unsigned long numGenerated = generateSamples(partialBuf, length); - if (mixType == 1 || mixType == 2) { - float *pairBuf; - unsigned long pairNumGenerated; - if (pair == NULL) { - pairBuf = NULL; - pairNumGenerated = 0; - } else { - pairBuf = &pair->myBuffer[0]; - pairNumGenerated = pair->generateSamples(pairBuf, numGenerated); - // pair will have been set to NULL if it deactivated within generateSamples() - if (pair != NULL) { - if (!isActive()) { - pair->deactivate(); - pair = NULL; - } else if (!pair->isActive()) { - pair = NULL; - } - } - } - if (pairNumGenerated > 0) { - if (mixType == 1) { - mixBuffersRingMix(partialBuf, pairBuf, pairNumGenerated); - } else { - mixBuffersRing(partialBuf, pairBuf, pairNumGenerated); - } - } - if (numGenerated > pairNumGenerated) { - if (mixType == 2) { - numGenerated = pairNumGenerated; - deactivate(); - } - } - } - - for (unsigned int i = 0; i < numGenerated; i++) { - *leftBuf++ = partialBuf[i] * stereoVolume.leftVol; - } + unsigned long numGenerated = generateSamples(myBuffer, length); for (unsigned int i = 0; i < numGenerated; i++) { - *rightBuf++ = partialBuf[i] * stereoVolume.rightVol; + *leftBuf++ = myBuffer[i] * stereoVolume.leftVol; + *rightBuf++ = myBuffer[i] * stereoVolume.rightVol; } - while (numGenerated < length) { + for (; numGenerated < length; numGenerated++) { *leftBuf++ = 0.0f; *rightBuf++ = 0.0f; - numGenerated++; } return true; } diff --git a/audio/softsynth/mt32/Partial.h b/audio/softsynth/mt32/Partial.h index 5e250769ec..21b1bfe376 100644 --- a/audio/softsynth/mt32/Partial.h +++ b/audio/softsynth/mt32/Partial.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -44,12 +44,7 @@ private: int structurePosition; // 0 or 1 of a structure pair StereoVolume stereoVolume; - // Distance in (possibly fractional) samples from the start of the current pulse - float wavePos; - - float lastFreq; - - float myBuffer[MAX_SAMPLES_PER_RUN]; + Bit16s myBuffer[MAX_SAMPLES_PER_RUN]; // Only used for PCM partials int pcmNum; @@ -60,17 +55,16 @@ private: // Range: 0-255 int pulseWidthVal; - float pcmPosition; - Poly *poly; LA32Ramp ampRamp; LA32Ramp cutoffModifierRamp; - float *mixBuffersRingMix(float *buf1, float *buf2, unsigned long len); - float *mixBuffersRing(float *buf1, float *buf2, unsigned long len); + // TODO: This should be owned by PartialPair + LA32PartialPair la32Pair; - float getPCMSample(unsigned int position); + Bit32u getAmpValue(); + Bit32u getCutoffValue(); public: const PatchCache *patchCache; @@ -90,7 +84,6 @@ public: unsigned long debugGetSampleNum() const; int getOwnerPart() const; - int getKey() const; const Poly *getPoly() const; bool isActive() const; void activate(int part); @@ -111,7 +104,7 @@ public: bool produceOutput(float *leftBuf, float *rightBuf, unsigned long length); // This function writes mono sample output to the provided buffer, and returns the number of samples written - unsigned long generateSamples(float *partialBuf, unsigned long length); + unsigned long generateSamples(Bit16s *partialBuf, unsigned long length); }; } diff --git a/audio/softsynth/mt32/PartialManager.cpp b/audio/softsynth/mt32/PartialManager.cpp index f8c2dbcd48..436e7a353e 100644 --- a/audio/softsynth/mt32/PartialManager.cpp +++ b/audio/softsynth/mt32/PartialManager.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/PartialManager.h b/audio/softsynth/mt32/PartialManager.h index bb78672457..a1c9266ea1 100644 --- a/audio/softsynth/mt32/PartialManager.h +++ b/audio/softsynth/mt32/PartialManager.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/Poly.cpp b/audio/softsynth/mt32/Poly.cpp index 46e30c0f02..46574f8967 100644 --- a/audio/softsynth/mt32/Poly.cpp +++ b/audio/softsynth/mt32/Poly.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/Poly.h b/audio/softsynth/mt32/Poly.h index e25b6d8993..068cf73d35 100644 --- a/audio/softsynth/mt32/Poly.h +++ b/audio/softsynth/mt32/Poly.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/ROMInfo.cpp b/audio/softsynth/mt32/ROMInfo.cpp index 514bc23496..9d05420874 100644 --- a/audio/softsynth/mt32/ROMInfo.cpp +++ b/audio/softsynth/mt32/ROMInfo.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/ROMInfo.h b/audio/softsynth/mt32/ROMInfo.h index 2ffd2b72c6..1d837dc5ee 100644 --- a/audio/softsynth/mt32/ROMInfo.h +++ b/audio/softsynth/mt32/ROMInfo.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/Structures.h b/audio/softsynth/mt32/Structures.h index cbce89ae18..43d2d1f226 100644 --- a/audio/softsynth/mt32/Structures.h +++ b/audio/softsynth/mt32/Structures.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/Synth.cpp b/audio/softsynth/mt32/Synth.cpp index 7f4ba44999..b7af992b99 100644 --- a/audio/softsynth/mt32/Synth.cpp +++ b/audio/softsynth/mt32/Synth.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -345,17 +345,7 @@ bool Synth::loadPCMROM(const ROMImage &pcmROMImage) { } log = log | (short)(bit << (15 - u)); } - bool negative = log < 0; - log &= 0x7FFF; - - // CONFIRMED from sample analysis to be 99.99%+ accurate with current TVA multiplier - float lin = EXP2F((32787 - log) / -2048.0f); - - if (negative) { - lin = -lin; - } - - pcmROMData[i] = lin; + pcmROMData[i] = log; } delete[] buffer; @@ -462,7 +452,7 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage) { // 1MB PCM ROM for CM-32L, LAPC-I, CM-64, CM-500 // Note that the size below is given in samples (16-bit), not bytes pcmROMSize = controlROMMap->pcmCount == 256 ? 512 * 1024 : 256 * 1024; - pcmROMData = new float[pcmROMSize]; + pcmROMData = new Bit16s[pcmROMSize]; #if MT32EMU_MONITOR_INIT printDebug("Loading PCM ROM"); diff --git a/audio/softsynth/mt32/Synth.h b/audio/softsynth/mt32/Synth.h index 91375c0fc0..56e88e6156 100644 --- a/audio/softsynth/mt32/Synth.h +++ b/audio/softsynth/mt32/Synth.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -283,7 +283,7 @@ private: const ControlROMMap *controlROMMap; Bit8u controlROMData[CONTROL_ROM_SIZE]; - float *pcmROMData; + Bit16s *pcmROMData; size_t pcmROMSize; // This is in 16-bit samples, therefore half the number of bytes in the ROM Bit8s chantable[32]; diff --git a/audio/softsynth/mt32/TVA.cpp b/audio/softsynth/mt32/TVA.cpp index 19a01cfc73..65e5256048 100644 --- a/audio/softsynth/mt32/TVA.cpp +++ b/audio/softsynth/mt32/TVA.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/TVA.h b/audio/softsynth/mt32/TVA.h index a104fe4c1f..e6e5cc4bc7 100644 --- a/audio/softsynth/mt32/TVA.h +++ b/audio/softsynth/mt32/TVA.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/TVF.cpp b/audio/softsynth/mt32/TVF.cpp index 47c4917632..49a0d85c9e 100644 --- a/audio/softsynth/mt32/TVF.cpp +++ b/audio/softsynth/mt32/TVF.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/TVF.h b/audio/softsynth/mt32/TVF.h index 490d8de504..22d81da7b0 100644 --- a/audio/softsynth/mt32/TVF.h +++ b/audio/softsynth/mt32/TVF.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/TVP.cpp b/audio/softsynth/mt32/TVP.cpp index 5dc4ca6b66..c3e64c18d0 100644 --- a/audio/softsynth/mt32/TVP.cpp +++ b/audio/softsynth/mt32/TVP.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/TVP.h b/audio/softsynth/mt32/TVP.h index f6f62f8d39..cd5fb4cdc7 100644 --- a/audio/softsynth/mt32/TVP.h +++ b/audio/softsynth/mt32/TVP.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by diff --git a/audio/softsynth/mt32/Tables.cpp b/audio/softsynth/mt32/Tables.cpp index 5353a74079..743820b1f8 100644 --- a/audio/softsynth/mt32/Tables.cpp +++ b/audio/softsynth/mt32/Tables.cpp @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -72,24 +72,25 @@ Tables::Tables() { //synth->printDebug("%d: %d", i, pulseWidth100To255[i]); } - // The LA32 chip presumably has such a table inside as the internal computaions seem to be performed using fixed point math with 12-bit fractions - for (int i = 0; i < 4096; i++) { - exp2[i] = EXP2F(i / 4096.0f); + // The LA32 chip contains an exponent table inside. The table contains 12-bit integer values. + // The actual table size is 512 rows. The 9 higher bits of the fractional part of the argument are used as a lookup address. + // To improve the precision of computations, the lower bits are supposed to be used for interpolation as the LA32 chip also + // contains another 512-row table with inverted differences between the main table values. + for (int i = 0; i < 512; i++) { + exp9[i] = Bit16u(8191.5f - EXP2F(13.0f + ~i / 512.0f)); } - // found from sample analysis - resAmpFadeFactor[7] = 1.0f / 8.0f; - resAmpFadeFactor[6] = 2.0f / 8.0f; - resAmpFadeFactor[5] = 3.0f / 8.0f; - resAmpFadeFactor[4] = 5.0f / 8.0f; - resAmpFadeFactor[3] = 8.0f / 8.0f; - resAmpFadeFactor[2] = 12.0f / 8.0f; - resAmpFadeFactor[1] = 16.0f / 8.0f; - resAmpFadeFactor[0] = 31.0f / 8.0f; - - for (int i = 0; i < 5120; i++) { - sinf10[i] = sin(FLOAT_PI * i / 2048.0f); + // There is a logarithmic sine table inside the LA32 chip. The table contains 13-bit integer values. + for (int i = 1; i < 512; i++) { + logsin9[i] = Bit16u(0.5f - LOG2F(sin((i + 0.5f) / 1024.0f * FLOAT_PI)) * 1024.0f); } + + // The very first value is clamped to the maximum possible 13-bit integer + logsin9[0] = 8191; + + // found from sample analysis + static const Bit8u resAmpDecayFactorTable[] = {31, 16, 12, 8, 5, 3, 2, 1}; + resAmpDecayFactor = resAmpDecayFactorTable; } } diff --git a/audio/softsynth/mt32/Tables.h b/audio/softsynth/mt32/Tables.h index c3e80e7e9b..8b4580df0e 100644 --- a/audio/softsynth/mt32/Tables.h +++ b/audio/softsynth/mt32/Tables.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -56,9 +56,10 @@ public: // CONFIRMED: Bit8u pulseWidth100To255[101]; - float exp2[4096]; - float resAmpFadeFactor[8]; - float sinf10[5120]; + Bit16u exp9[512]; + Bit16u logsin9[512]; + + const Bit8u *resAmpDecayFactor; }; } diff --git a/audio/softsynth/mt32/mmath.h b/audio/softsynth/mt32/mmath.h index 25c79d57a9..ee6a652c36 100644 --- a/audio/softsynth/mt32/mmath.h +++ b/audio/softsynth/mt32/mmath.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -52,10 +52,6 @@ static inline float EXP2F(float x) { #endif } -static inline float EXP2I(unsigned int i) { - return float(1 << (i >> 12)) * Tables::getInstance().exp2[i & 0x0FFF]; -} - static inline float EXP10F(float x) { return exp(FLOAT_LN_10 * x); } diff --git a/audio/softsynth/mt32/module.mk b/audio/softsynth/mt32/module.mk index ed6b0d33ed..e7afdfd2b4 100644 --- a/audio/softsynth/mt32/module.mk +++ b/audio/softsynth/mt32/module.mk @@ -6,6 +6,8 @@ MODULE_OBJS := \ DelayReverb.o \ FreeverbModel.o \ LA32Ramp.o \ + LA32WaveGenerator.o \ + LegacyWaveGenerator.o \ Part.o \ Partial.o \ PartialManager.o \ diff --git a/audio/softsynth/mt32/mt32emu.h b/audio/softsynth/mt32/mt32emu.h index ae5f4955b1..971a0886d5 100644 --- a/audio/softsynth/mt32/mt32emu.h +++ b/audio/softsynth/mt32/mt32emu.h @@ -1,5 +1,5 @@ /* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher - * Copyright (C) 2011 Dean Beeler, Jerome Fisher, Sergey V. Mikayev + * Copyright (C) 2011, 2012, 2013 Dean Beeler, Jerome Fisher, Sergey V. Mikayev * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by @@ -59,18 +59,6 @@ #define MT32EMU_MONITOR_TVA 0 #define MT32EMU_MONITOR_TVF 0 -// The WG algorithm involves dozens of transcendent maths, e.g. exponents and trigonometry. -// Unfortunately, the majority of systems perform such computations inefficiently, -// standard math libs and FPUs make no optimisations for single precision floats, -// and use no LUTs to speedup computing internal taylor series. Though, there're rare exceptions, -// and there's a hope it will become common soon. -// So, this is the crucial point of speed optimisations. We have now eliminated all the transcendent maths -// within the critical path and use LUTs instead. -// Besides, since the LA32 chip is assumed to use similar LUTs inside, the overall emulation accuracy should be better. -// 0: Use LUTs to speedup WG. Most common setting. You can expect about 50% performance boost. -// 1: Use precise float math. Use this setting to achieve more accurate wave generator. If your system performs better with this setting, it is really notable. :) -#define MT32EMU_ACCURATE_WG 0 - // Configuration // The maximum number of partials playing simultaneously #define MT32EMU_MAX_PARTIALS 32 @@ -87,6 +75,10 @@ // 2: Use Bit-perfect Boss Reverb model aka BReverb (for developers, not much practical use) #define MT32EMU_USE_REVERBMODEL 1 +// 0: Use refined wave generator based on logarithmic fixed-point computations and LUTs +// 1: Use legacy accurate wave generator based on float computations +#define MT32EMU_ACCURATE_WG 0 + namespace MT32Emu { // The higher this number, the more memory will be used, but the more samples can be processed in one run - @@ -110,6 +102,8 @@ const unsigned int MAX_PRERENDER_SAMPLES = 1024; #include "Tables.h" #include "Poly.h" #include "LA32Ramp.h" +#include "LA32WaveGenerator.h" +#include "LegacyWaveGenerator.h" #include "TVA.h" #include "TVP.h" #include "TVF.h" diff --git a/devtools/credits.pl b/devtools/credits.pl index 28c3139bfd..06df7fa50e 100755 --- a/devtools/credits.pl +++ b/devtools/credits.pl @@ -65,6 +65,7 @@ sub html_entities_to_ascii { # ø -> o # ö -> o / oe # ä -> a + # ë -> e # ü -> ue # å -> aa # & -> & @@ -82,6 +83,7 @@ sub html_entities_to_ascii { $text =~ s/å/aa/g; $text =~ s/ä/a/g; + $text =~ s/ë/e/g; $text =~ s/ü/ue/g; # HACK: Torbj*o*rn but G*oe*ffringmann and R*oe*ver and J*oe*rg $text =~ s/Torbjörn/Torbjorn/g; @@ -108,6 +110,7 @@ sub html_entities_to_cpp { $text =~ s/å/\\345/g; $text =~ s/ä/\\344/g; + $text =~ s/ë/\\353/g; $text =~ s/ö/\\366/g; $text =~ s/ü/\\374/g; @@ -133,6 +136,7 @@ sub html_entities_to_rtf { # Back to hex numbers $text =~ s/ä/\\'8a/g; + $text =~ s/ë/\\'eb/g; $text =~ s/ö/\\'9a/g; $text =~ s/ü/\\'9f/g; @@ -156,6 +160,7 @@ sub html_entities_to_tex { $text =~ s/ä/\\"a/g; $text =~ s/ö/\\"o/g; + $text =~ s/ë/\\"e/g; $text =~ s/ü/\\"u/g; $text =~ s/&/\\&/g; @@ -590,6 +595,11 @@ begin_credits("Credits"); add_person("Jordi Vilalta Prat", "jvprat", ""); end_section(); + begin_section("Hopkins"); + add_person("Arnaud Boutonné", "Strangerke", ""); + add_person("Paul Gilbert", "dreammaster", ""); + end_section(); + begin_section("Hugo"); add_person("Arnaud Boutonné", "Strangerke", ""); add_person("Oystein Eftevaag", "vinterstum", ""); @@ -836,6 +846,7 @@ begin_credits("Credits"); add_person("Jerome Fisher", "KingGuppy", "MT-32 emulator"); add_person("Benjamin Haisch", "john_doe", "Heavily improved de-/encoder for DXA videos"); add_person("Jochen Hoenicke", "hoenicke", "Speaker & PCjr sound support, AdLib work (retired)"); + add_person("Daniël ter Laan", "NoiZe", "Restoring original Drascula tracks, and writing convert_dxa.bat"); add_person("Chris Page", "cp88", "Return to launcher, savestate improvements, leak fixes, ... (GSoC 2008 task) (retired)"); add_person("Robin Watts", "robinwatts", "ARM assembly routines for nice speedups on several ports; improvements to the sound mixer"); end_section(); diff --git a/engines/configure.engines b/engines/configure.engines index 3ac287e23f..e0ec1ae80b 100644 --- a/engines/configure.engines +++ b/engines/configure.engines @@ -16,7 +16,7 @@ add_engine dreamweb "Dreamweb" yes add_engine gob "Gobli*ns" yes add_engine groovie "Groovie" yes "groovie2" "7th Guest" add_engine groovie2 "Groovie 2 games" no -add_engine hopkins "Hopkins FBI" no +add_engine hopkins "Hopkins FBI" no "" "" "16bit" add_engine hugo "Hugo Trilogy" yes add_engine kyra "Kyra" yes "lol eob" "Legend of Kyrandia 1-3" add_engine lol "Lands of Lore" yes diff --git a/engines/dreamweb/dreamweb.h b/engines/dreamweb/dreamweb.h index eb35a73f66..5746568e4e 100644 --- a/engines/dreamweb/dreamweb.h +++ b/engines/dreamweb/dreamweb.h @@ -513,6 +513,7 @@ public: void dirCom(); void useMon(); bool execCommand(); + int findCommand(const char *const cmdList[]); // from newplace.cpp void getUnderCentre(); diff --git a/engines/dreamweb/monitor.cpp b/engines/dreamweb/monitor.cpp index b6922cba51..8dba506ca6 100644 --- a/engines/dreamweb/monitor.cpp +++ b/engines/dreamweb/monitor.cpp @@ -104,15 +104,66 @@ void DreamWebEngine::useMon() { redrawMainScrn(); workToScreenM(); } + +int DreamWebEngine::findCommand(const char *const cmdList[]) { + // Loop over all commands in the list and see if we get a match + int cmd = 0; + while (cmdList[cmd] != NULL) { + const char *cmdStr = cmdList[cmd]; + const char *inputStr = _inputLine; + // Compare the command, char by char, to see if we get a match. + // We only care about the prefix matching, though. + char inputChar, cmdChar; + do { + inputChar = *inputStr; inputStr += 2; + cmdChar = *cmdStr++; + if (cmdChar == 0) + return cmd; + } while (inputChar == cmdChar); + ++cmd; + } + return -1; +} bool DreamWebEngine::execCommand() { - static const char *comlist[] = { + static const char *const comlist[] = { "EXIT", "HELP", "LIST", "READ", "LOGON", - "KEYS" + "KEYS", + NULL + }; + + static const char *const comlistFR[] = { + "SORTIR", + "AIDE", + "LISTE", + "LIRE", + "CONNEXION", + "TOUCHES", // should be CLES but it is translated as TOUCHES in the game... + NULL + }; + + static const char *const comlistDE[] = { + "ENDE", + "HILFE", + "LISTE", + "LIES", + "ZUGRIFF", + "DATEN", + NULL + }; + + static const char *const comlistIT[] = { + "ESCI", + "AIUTO", + "ELENCA", + "LEGGI", + "ACCEDI", + "CHIAVI", + NULL }; if (_inputLine[0] == 0) { @@ -121,26 +172,23 @@ bool DreamWebEngine::execCommand() { return false; } - int cmd; - bool done = false; - // Loop over all commands in the list and see if we get a match - for (cmd = 0; cmd < ARRAYSIZE(comlist); ++cmd) { - const char *cmdStr = comlist[cmd]; - const char *inputStr = _inputLine; - // Compare the command, char by char, to see if we get a match. - // We only care about the prefix matching, though. - char inputChar, cmdChar; - do { - inputChar = *inputStr; inputStr += 2; - cmdChar = *cmdStr++; - if (cmdChar == 0) { - done = true; - break; - } - } while (inputChar == cmdChar); - - if (done) + int cmd = findCommand(comlist); + if (cmd == -1) { + // This did not match an english command. Try to find a localized one. + switch (getLanguage()) { + case Common::FR_FRA: + cmd = findCommand(comlistFR); + break; + case Common::DE_DEU: + cmd = findCommand(comlistDE); break; + case Common::IT_ITA: + cmd = findCommand(comlistIT); + break; + case Common::ES_ESP: + default: + break; + } } // Execute the selected command @@ -154,7 +202,21 @@ bool DreamWebEngine::execCommand() { // this extra text is wrapped around the common copy protection check, // to keep it faithful to the original, if requested. if (!_copyProtection) { - monPrint("VALID COMMANDS ARE EXIT, HELP, LIST, READ, LOGON, KEYS"); + switch (getLanguage()) { + case Common::FR_FRA: + monPrint("LES COMMANDES VALIDES SONT SORTIR, AIDE, LISTE, LIRE, CONNEXION, TOUCHES"); + break; + case Common::DE_DEU: + monPrint("G\232LTIGE BEFEHLE SIND ENDE, HILFE, LISTE, LIES, ZUGRIFF, DATEN"); + break; + case Common::IT_ITA: + monPrint("I COMANDI VALIDI SONO ESCI, AIUTO, ELENCA, LEGGI, ACCEDI, CHIAVI"); + break; + case Common::ES_ESP: + default: + monPrint("VALID COMMANDS ARE EXIT, HELP, LIST, READ, LOGON, KEYS"); + break; + } } break; case 2: @@ -177,7 +239,6 @@ bool DreamWebEngine::execCommand() { } - void DreamWebEngine::monitorLogo() { if (_logoNum != _oldLogoNum) { _oldLogoNum = _logoNum; diff --git a/engines/hopkins/anim.cpp b/engines/hopkins/anim.cpp index 89672e81b5..ac15139cbd 100644 --- a/engines/hopkins/anim.cpp +++ b/engines/hopkins/anim.cpp @@ -100,9 +100,9 @@ void AnimationManager::playAnim(const Common::String &filename, uint32 rate1, ui else _vm->_graphicsManager.m_scroll16(screenP, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); _vm->_graphicsManager.unlockScreen(); - _vm->_graphicsManager.addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); - _vm->_graphicsManager.DD_VBL(); + _vm->_graphicsManager.addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + _vm->_graphicsManager.updateScreen(); } _vm->_eventsManager._rateCounter = 0; _vm->_eventsManager._escKeyFl = false; @@ -157,9 +157,9 @@ void AnimationManager::playAnim(const Common::String &filename, uint32 rate1, ui _vm->_graphicsManager.copyVideoVbe16(screenP); } _vm->_graphicsManager.unlockScreen(); - _vm->_graphicsManager.addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); - _vm->_graphicsManager.DD_VBL(); + _vm->_graphicsManager.addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + _vm->_graphicsManager.updateScreen(); _vm->_soundManager.checkSoundEnd(); } } @@ -262,7 +262,7 @@ void AnimationManager::playAnim2(const Common::String &filename, uint32 rate1, u _vm->_graphicsManager.clearPalette(); oldScrollPosX = _vm->_graphicsManager._scrollPosX; - _vm->_graphicsManager.SCANLINE(SCREEN_WIDTH); + _vm->_graphicsManager.setScreenWidth(SCREEN_WIDTH); _vm->_graphicsManager.scrollScreen(0); _vm->_graphicsManager.lockScreen(); _vm->_graphicsManager.clearScreen(); @@ -287,8 +287,9 @@ void AnimationManager::playAnim2(const Common::String &filename, uint32 rate1, u _vm->_graphicsManager.m_scroll16(screenP, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); _vm->_graphicsManager.unlockScreen(); + _vm->_graphicsManager.addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); - _vm->_graphicsManager.DD_VBL(); + _vm->_graphicsManager.updateScreen(); } _vm->_eventsManager._rateCounter = 0; _vm->_eventsManager._escKeyFl = false; @@ -336,8 +337,9 @@ void AnimationManager::playAnim2(const Common::String &filename, uint32 rate1, u } } _vm->_graphicsManager.unlockScreen(); + _vm->_graphicsManager.addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); - _vm->_graphicsManager.DD_VBL(); + _vm->_graphicsManager.updateScreen(); _vm->_soundManager.checkSoundEnd(); } @@ -397,12 +399,12 @@ void AnimationManager::playAnim2(const Common::String &filename, uint32 rate1, u _vm->_graphicsManager._scrollPosX = oldScrollPosX; _vm->_graphicsManager.scrollScreen(oldScrollPosX); if (_vm->_graphicsManager._largeScreenFl) { - _vm->_graphicsManager.SCANLINE(2 * SCREEN_WIDTH); + _vm->_graphicsManager.setScreenWidth(2 * SCREEN_WIDTH); _vm->_graphicsManager._maxX = 2 * SCREEN_WIDTH; _vm->_graphicsManager.lockScreen(); _vm->_graphicsManager.m_scroll16(_vm->_graphicsManager._vesaBuffer, _vm->_eventsManager._startPos.x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); } else { - _vm->_graphicsManager.SCANLINE(SCREEN_WIDTH); + _vm->_graphicsManager.setScreenWidth(SCREEN_WIDTH); _vm->_graphicsManager._maxX = SCREEN_WIDTH; _vm->_graphicsManager.lockScreen(); _vm->_graphicsManager.clearScreen(); @@ -412,7 +414,7 @@ void AnimationManager::playAnim2(const Common::String &filename, uint32 rate1, u _vm->_graphicsManager.addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); _vm->_graphicsManager.fadeInShort(); - _vm->_graphicsManager.DD_VBL(); + _vm->_graphicsManager.updateScreen(); _vm->_eventsManager.mouseOn(); } @@ -615,7 +617,7 @@ void AnimationManager::playSequence(const Common::String &file, uint32 rate1, ui bool hasScreenCopy = false; _vm->_eventsManager._mouseFl = false; if (!NO_COUL) { - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); if (_vm->_graphicsManager._lineNbr == SCREEN_WIDTH) _vm->_saveLoadManager.saveFile("TEMP.SCR", _vm->_graphicsManager._vesaScreen, 307200); @@ -659,9 +661,9 @@ void AnimationManager::playSequence(const Common::String &file, uint32 rate1, ui else _vm->_graphicsManager.m_scroll16(screenP, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); _vm->_graphicsManager.unlockScreen(); - _vm->_graphicsManager.addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); - _vm->_graphicsManager.DD_VBL(); + _vm->_graphicsManager.addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + _vm->_graphicsManager.updateScreen(); } bool skipFl = false; if (_vm->getIsDemo()) { @@ -741,9 +743,9 @@ void AnimationManager::playSequence(const Common::String &file, uint32 rate1, ui _vm->_graphicsManager.copyVideoVbe16a(screenP); } _vm->_graphicsManager.unlockScreen(); - _vm->_graphicsManager.addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); - _vm->_graphicsManager.DD_VBL(); + _vm->_graphicsManager.addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + _vm->_graphicsManager.updateScreen(); _vm->_soundManager.checkSoundEnd(); } } @@ -823,9 +825,9 @@ void AnimationManager::playSequence2(const Common::String &file, uint32 rate1, u else _vm->_graphicsManager.m_scroll16(screenP, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); _vm->_graphicsManager.unlockScreen(); - _vm->_graphicsManager.addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); - _vm->_graphicsManager.DD_VBL(); + _vm->_graphicsManager.addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); + _vm->_graphicsManager.updateScreen(); } _vm->_eventsManager._rateCounter = 0; _vm->_eventsManager._escKeyFl = false; @@ -871,9 +873,9 @@ void AnimationManager::playSequence2(const Common::String &file, uint32 rate1, u _vm->_graphicsManager.copyVideoVbe16a(screenP); } _vm->_graphicsManager.unlockScreen(); + _vm->_graphicsManager.addRefreshRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); - - _vm->_graphicsManager.DD_VBL(); + _vm->_graphicsManager.updateScreen(); _vm->_soundManager.checkSoundEnd(); } } diff --git a/engines/hopkins/computer.cpp b/engines/hopkins/computer.cpp index 4872f91eb3..4e9ed83e99 100644 --- a/engines/hopkins/computer.cpp +++ b/engines/hopkins/computer.cpp @@ -263,21 +263,21 @@ void ComputerManager::showComputer(ComputerEnum mode) { _vm->_graphicsManager.lockScreen(); _vm->_graphicsManager.clearScreen(); _vm->_graphicsManager.unlockScreen(); - _vm->_graphicsManager.DD_VBL(); + _vm->_graphicsManager.updateScreen(); restoreFBIRoom(); } else { // Password doesn't match - Access Denied setTextColor(4); setTextPosition(16, 25); outText(Common::String(_menuText[5]._line)); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); _vm->_eventsManager.delay(1000); memset(_vm->_graphicsManager._vesaBuffer, 0, 307199); _vm->_graphicsManager.lockScreen(); _vm->_graphicsManager.clearScreen(); _vm->_graphicsManager.unlockScreen(); - _vm->_graphicsManager.DD_VBL(); + _vm->_graphicsManager.updateScreen(); restoreFBIRoom(); _vm->_eventsManager.mouseOff(); } @@ -440,13 +440,13 @@ void ComputerManager::displayMessage(int xp, int yp, int textIdx) { ++textIndex; x1 += _vm->_fontManager._fontFixedWidth; } - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (textIndex != textIdx && curChar != 13); _vm->_graphicsManager.Copy_Mem(_vm->_graphicsManager._vesaScreen, x1, yp, _vm->_fontManager._fontFixedWidth, 12, _vm->_graphicsManager._vesaBuffer, x1, yp); _vm->_graphicsManager.addDirtyRect(x1, yp, _vm->_fontManager._fontFixedWidth + x1, yp + 12); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); _inputBuf[textIndex] = 0; _vm->_eventsManager._mouseFl = oldMouseFlag; } @@ -515,7 +515,7 @@ void ComputerManager::readText(int idx) { outText(curStr); ++lineNum; - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); curStr = ""; } else if (curChar != '%') { curStr += curChar; @@ -614,7 +614,7 @@ void ComputerManager::setModeVGA256() { _vm->_graphicsManager.clearScreen(); _vm->_graphicsManager.unlockScreen(); _vm->_graphicsManager.clearPalette(); - _vm->_graphicsManager.SCANLINE(320); + _vm->_graphicsManager.setScreenWidth(320); } /** @@ -731,8 +731,9 @@ void ComputerManager::playBreakout() { _ballPosition = Common::Point(_padPositionX + 14, 187); _vm->_objectsManager.setSpriteY(1, 187); _vm->_objectsManager.setSpriteX(1, _ballPosition.x); + _vm->_graphicsManager.resetDirtyRects(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); _vm->_graphicsManager.fadeInBreakout(); // Wait for mouse press to start playing @@ -745,7 +746,7 @@ void ComputerManager::playBreakout() { _vm->_objectsManager.setSpriteX(0, _padPositionX); _vm->_objectsManager.setSpriteX(1, _padPositionX + 14); _vm->_objectsManager.setSpriteY(1, 187); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (!_vm->shouldQuit() && _vm->_eventsManager.getMouseButton() != 1); _breakoutSpeed = 1; @@ -764,7 +765,7 @@ void ComputerManager::playBreakout() { _padPositionX = 282; _vm->_objectsManager.setSpriteX(0, _padPositionX); lastBreakoutEvent = moveBall(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (!_vm->shouldQuit() && !lastBreakoutEvent); if (lastBreakoutEvent != 1) break; @@ -846,7 +847,7 @@ int ComputerManager::displayHiscores() { else if (_vm->_eventsManager.getMouseButton() == 1 && ABS(xp - 583) <= 32 && ABS(yp - 396) <= 13) buttonIndex = 2; - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (!buttonIndex && !_vm->shouldQuit()); _vm->_eventsManager.mouseOff(); @@ -879,7 +880,7 @@ void ComputerManager::getScoreName() { displayHiscoreLine(ptr, 9 * strPos + 140, 78, curChar); for (int idx = 0; idx < 12; ++idx) - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } _score[5]._score = " "; diff --git a/engines/hopkins/dialogs.cpp b/engines/hopkins/dialogs.cpp index f45e58644a..9056101f76 100644 --- a/engines/hopkins/dialogs.cpp +++ b/engines/hopkins/dialogs.cpp @@ -59,7 +59,7 @@ void DialogsManager::setParent(HopkinsEngine *vm) { void DialogsManager::showOptionsDialog() { _vm->_eventsManager.changeMouseCursor(0); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); Common::String filename; if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS) filename = "OPTION.SPR"; @@ -75,6 +75,7 @@ void DialogsManager::showOptionsDialog() { _vm->_globals._optionDialogSpr = _vm->_fileManager.loadFile(filename); _vm->_globals._optionDialogFl = true; + int scrollOffset = _vm->_graphicsManager._scrollOffset; bool doneFlag = false; do { if (_vm->_eventsManager.getMouseButton()) { @@ -83,7 +84,7 @@ void DialogsManager::showOptionsDialog() { mousePos.y = _vm->_eventsManager.getMouseY(); if (!_vm->_soundManager._musicOffFl) { - if (mousePos.x >= _vm->_graphicsManager._scrollOffset + 300 && mousePos.y > 113 && mousePos.x <= _vm->_graphicsManager._scrollOffset + 327 && mousePos.y <= 138) { + if (mousePos.x >= scrollOffset + 300 && mousePos.y > 113 && mousePos.x <= scrollOffset + 327 && mousePos.y <= 138) { // Change the music volume ++_vm->_soundManager._musicVolume; @@ -96,7 +97,7 @@ void DialogsManager::showOptionsDialog() { _vm->_soundManager.updateScummVMSoundSettings(); } - if (!_vm->_soundManager._musicOffFl && mousePos.x >= _vm->_graphicsManager._scrollOffset + 331 && mousePos.y > 113 && mousePos.x <= _vm->_graphicsManager._scrollOffset + 358 && mousePos.y <= 138) { + if (!_vm->_soundManager._musicOffFl && mousePos.x >= scrollOffset + 331 && mousePos.y > 113 && mousePos.x <= scrollOffset + 358 && mousePos.y <= 138) { --_vm->_soundManager._musicVolume; if (_vm->_soundManager._musicVolume >= 0) _vm->_soundManager.playSoundFile("bruit2.wav"); @@ -109,7 +110,8 @@ void DialogsManager::showOptionsDialog() { } } if (!_vm->_soundManager._soundOffFl) { - if (mousePos.x >= _vm->_graphicsManager._scrollOffset + 300 && mousePos.y > 140 && mousePos.x <= _vm->_graphicsManager._scrollOffset + 327 && mousePos.y <= 165) { + // increase volume + if (mousePos.x >= scrollOffset + 300 && mousePos.y > 140 && mousePos.x <= scrollOffset + 327 && mousePos.y <= 165) { ++_vm->_soundManager._soundVolume; if (_vm->_soundManager._soundVolume <= 16) _vm->_soundManager.playSoundFile("bruit2.wav"); @@ -120,7 +122,8 @@ void DialogsManager::showOptionsDialog() { _vm->_soundManager.updateScummVMSoundSettings(); } - if (!_vm->_soundManager._soundOffFl && mousePos.x >= _vm->_graphicsManager._scrollOffset + 331 && mousePos.y > 140 && mousePos.x <= _vm->_graphicsManager._scrollOffset + 358 && mousePos.y <= 165) { + // Decrease volume + if (!_vm->_soundManager._soundOffFl && mousePos.x >= scrollOffset + 331 && mousePos.y > 140 && mousePos.x <= scrollOffset + 358 && mousePos.y <= 165) { --_vm->_soundManager._soundVolume; if (_vm->_soundManager._soundVolume >= 0) _vm->_soundManager.playSoundFile("bruit2.wav"); @@ -133,7 +136,7 @@ void DialogsManager::showOptionsDialog() { } if (!_vm->_soundManager._voiceOffFl) { - if (mousePos.x >= _vm->_graphicsManager._scrollOffset + 300 && mousePos.y > 167 && mousePos.x <= _vm->_graphicsManager._scrollOffset + 327 && mousePos.y <= 192) { + if (mousePos.x >= scrollOffset + 300 && mousePos.y > 167 && mousePos.x <= scrollOffset + 327 && mousePos.y <= 192) { ++_vm->_soundManager._voiceVolume; if (_vm->_soundManager._voiceVolume <= 16) @@ -145,7 +148,7 @@ void DialogsManager::showOptionsDialog() { _vm->_soundManager.updateScummVMSoundSettings(); } - if (!_vm->_soundManager._voiceOffFl && mousePos.x >= _vm->_graphicsManager._scrollOffset + 331 && mousePos.y > 167 && mousePos.x <= _vm->_graphicsManager._scrollOffset + 358 && mousePos.y <= 192) { + if (!_vm->_soundManager._voiceOffFl && mousePos.x >= scrollOffset + 331 && mousePos.y > 167 && mousePos.x <= scrollOffset + 358 && mousePos.y <= 192) { --_vm->_soundManager._voiceVolume; if (_vm->_soundManager._voiceVolume >= 0) _vm->_soundManager.playSoundFile("bruit2.wav"); @@ -157,18 +160,18 @@ void DialogsManager::showOptionsDialog() { } } - if (mousePos.x >= _vm->_graphicsManager._scrollOffset + 431) { - if (mousePos.y > 194 && mousePos.x <= _vm->_graphicsManager._scrollOffset + 489 && mousePos.y <= 219) + if (mousePos.x >= scrollOffset + 431) { + if (mousePos.y > 194 && mousePos.x <= scrollOffset + 489 && mousePos.y <= 219) _vm->_soundManager._textOffFl = !_vm->_soundManager._textOffFl; - if (mousePos.x >= _vm->_graphicsManager._scrollOffset + 431) { - if (mousePos.y > 167 && mousePos.x <= _vm->_graphicsManager._scrollOffset + 489 && mousePos.y <= 192) { + if (mousePos.x >= scrollOffset + 431) { + if (mousePos.y > 167 && mousePos.x <= scrollOffset + 489 && mousePos.y <= 192) { _vm->_soundManager._voiceOffFl = !_vm->_soundManager._voiceOffFl; _vm->_soundManager.updateScummVMSoundSettings(); } - if (mousePos.x >= _vm->_graphicsManager._scrollOffset + 431) { - if (mousePos.y > 113 && mousePos.x <= _vm->_graphicsManager._scrollOffset + 489 && mousePos.y <= 138) { + if (mousePos.x >= scrollOffset + 431) { + if (mousePos.y > 113 && mousePos.x <= scrollOffset + 489 && mousePos.y <= 138) { if (_vm->_soundManager._musicOffFl) { _vm->_soundManager._musicOffFl = false; _vm->_soundManager.setMODMusicVolume(_vm->_soundManager._musicVolume); @@ -180,7 +183,7 @@ void DialogsManager::showOptionsDialog() { _vm->_soundManager.updateScummVMSoundSettings(); } - if (mousePos.x >= _vm->_graphicsManager._scrollOffset + 431 && mousePos.y > 140 && mousePos.x <= _vm->_graphicsManager._scrollOffset + 489 && mousePos.y <= 165) { + if (mousePos.x >= scrollOffset + 431 && mousePos.y > 140 && mousePos.x <= scrollOffset + 489 && mousePos.y <= 165) { _vm->_soundManager._soundOffFl = !_vm->_soundManager._soundOffFl; _vm->_soundManager.updateScummVMSoundSettings(); @@ -189,13 +192,13 @@ void DialogsManager::showOptionsDialog() { } } - if (mousePos.x >= _vm->_graphicsManager._scrollOffset + 175 && mousePos.y > 285 && mousePos.x <= _vm->_graphicsManager._scrollOffset + 281 && mousePos.y <= 310) { + if (mousePos.x >= scrollOffset + 175 && mousePos.y > 285 && mousePos.x <= scrollOffset + 281 && mousePos.y <= 310) { _vm->_globals._exitId = 300; doneFlag = true; } - if (mousePos.x >= _vm->_graphicsManager._scrollOffset + 355 && mousePos.y > 285 && mousePos.x <= _vm->_graphicsManager._scrollOffset + 490 && mousePos.y <= 310) + if (mousePos.x >= scrollOffset + 355 && mousePos.y > 285 && mousePos.x <= scrollOffset + 490 && mousePos.y <= 310) doneFlag = true; - if (mousePos.x >= _vm->_graphicsManager._scrollOffset + 300 && mousePos.y > 194 && mousePos.x <= _vm->_graphicsManager._scrollOffset + 358 && mousePos.y <= 219) { + if (mousePos.x >= scrollOffset + 300 && mousePos.y > 194 && mousePos.x <= scrollOffset + 358 && mousePos.y <= 219) { switch (_vm->_graphicsManager._scrollSpeed) { case 1: _vm->_graphicsManager._scrollSpeed = 2; @@ -237,7 +240,7 @@ void DialogsManager::showOptionsDialog() { //if (mousePos.x >= _vm->_graphicsManager.ofscroll + 348 && mousePos.y > 248 && mousePos.x <= _vm->_graphicsManager.ofscroll + 394 && mousePos.y <= 273) // _vm->_globals._speed = 2; - if ( mousePos.x < _vm->_graphicsManager._scrollOffset + 165 || mousePos.x > _vm->_graphicsManager._scrollOffset + 496 + if ( mousePos.x < scrollOffset + 165 || mousePos.x > scrollOffset + 496 || mousePos.y < 107 || mousePos.y > 318) doneFlag = true; } @@ -295,13 +298,12 @@ void DialogsManager::showOptionsDialog() { break; } - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (!doneFlag); - _vm->_graphicsManager.copySurface(_vm->_graphicsManager._vesaScreen, _vm->_graphicsManager._scrollOffset + 164, - 107, 335, 215, _vm->_graphicsManager._vesaBuffer, _vm->_graphicsManager._scrollOffset + 164, 107); - _vm->_graphicsManager.addDirtyRect(_vm->_graphicsManager._scrollOffset + 164, 107, - _vm->_graphicsManager._scrollOffset + 498, 320); + _vm->_graphicsManager.copySurface(_vm->_graphicsManager._vesaScreen, scrollOffset + 164, + 107, 335, 215, _vm->_graphicsManager._vesaBuffer, scrollOffset + 164, 107); + _vm->_graphicsManager.addDirtyRect(scrollOffset + 164, 107, scrollOffset + 498, 320); _vm->_globals._optionDialogSpr = _vm->_globals.freeMemory(_vm->_globals._optionDialogSpr); _vm->_globals._optionDialogFl = false; @@ -318,7 +320,7 @@ void DialogsManager::showInventory() { inventAnim(); _vm->_eventsManager.getMouseX(); _vm->_eventsManager.getMouseY(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } _inventWin1 = g_PTRNUL; @@ -413,15 +415,15 @@ void DialogsManager::showInventory() { break; _vm->_scriptManager._tempObjectFl = true; - _vm->_globals._saveData->_data[svField3] = _vm->_objectsManager._curObjectIndex; - _vm->_globals._saveData->_data[svField8] = _vm->_globals._inventory[newInventoryItem]; - _vm->_globals._saveData->_data[svField9] = _vm->_eventsManager._mouseCursorId; + _vm->_globals._saveData->_data[svLastObjectIndex] = _vm->_objectsManager._curObjectIndex; + _vm->_globals._saveData->_data[svLastInventoryItem] = _vm->_globals._inventory[newInventoryItem]; + _vm->_globals._saveData->_data[svLastInvMouseCursor] = _vm->_eventsManager._mouseCursorId; _vm->_objectsManager.OPTI_OBJET(); _vm->_scriptManager._tempObjectFl = false; if (_vm->_soundManager._voiceOffFl) { do - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); while (!_vm->_globals._exitId && _vm->_eventsManager.getMouseButton() != 1); _vm->_fontManager.hideText(9); } @@ -441,7 +443,7 @@ void DialogsManager::showInventory() { } if (_removeInventFl) break; - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); if (_vm->_globals._screenId >= 35 && _vm->_globals._screenId <= 40) _vm->_objectsManager.handleSpecialGames(); } @@ -564,13 +566,13 @@ void DialogsManager::testDialogOpening() { * Load Game dialog */ void DialogsManager::showLoadGame() { - _vm->_eventsManager.VBL(); - showSaveLoad(2); + _vm->_eventsManager.refreshScreenAndEvents(); + showSaveLoad(MODE_LOAD); int slotNumber; do { slotNumber = searchSavegames(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (!_vm->shouldQuit() && (!slotNumber || _vm->_eventsManager.getMouseButton() != 1)); _vm->_objectsManager._saveLoadFl = false; _vm->_graphicsManager.copySurface(_vm->_graphicsManager._vesaScreen, _vm->_eventsManager._startPos.x + 183, 60, 274, 353, _vm->_graphicsManager._vesaBuffer, _vm->_eventsManager._startPos.x + 183, 60); @@ -592,13 +594,13 @@ void DialogsManager::showLoadGame() { * Save Game dialog */ void DialogsManager::showSaveGame() { - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); - showSaveLoad(1); + showSaveLoad(MODE_SAVE); int slotNumber; do { slotNumber = searchSavegames(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (!_vm->shouldQuit() && (!slotNumber || _vm->_eventsManager.getMouseButton() != 1)); _vm->_objectsManager._saveLoadFl = false; @@ -622,7 +624,7 @@ void DialogsManager::showSaveGame() { /** * Load/Save dialog */ -void DialogsManager::showSaveLoad(int a1) { +void DialogsManager::showSaveLoad(SaveLoadMode mode) { Common::String filename; if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS) @@ -646,14 +648,14 @@ void DialogsManager::showSaveLoad(int a1) { _vm->_graphicsManager.Sprite_Vesa(_vm->_graphicsManager._vesaBuffer, _vm->_objectsManager._saveLoadSprite, _vm->_eventsManager._startPos.x + 483, 360, 0); if (_vm->_globals._language == LANG_FR) { - if (a1 == 1) + if (mode == MODE_SAVE) _vm->_graphicsManager.Sprite_Vesa(_vm->_graphicsManager._vesaBuffer, _vm->_objectsManager._saveLoadSprite, _vm->_eventsManager._startPos.x + 525, 375, 1); - else if (a1 == 2) + else if (mode == MODE_LOAD) _vm->_graphicsManager.Sprite_Vesa(_vm->_graphicsManager._vesaBuffer, _vm->_objectsManager._saveLoadSprite, _vm->_eventsManager._startPos.x + 515, 375, 2); } else { - if (a1 == 1) + if (mode == MODE_SAVE) _vm->_graphicsManager.Sprite_Vesa(_vm->_graphicsManager._vesaBuffer, _vm->_objectsManager._saveLoadSprite, _vm->_eventsManager._startPos.x + 535, 372, 1); - else if (a1 == 2) + else if (mode == MODE_LOAD) _vm->_graphicsManager.Sprite_Vesa(_vm->_graphicsManager._vesaBuffer, _vm->_objectsManager._saveLoadSprite, _vm->_eventsManager._startPos.x + 539, 372, 2); } diff --git a/engines/hopkins/dialogs.h b/engines/hopkins/dialogs.h index fd35eca687..4fa80913c4 100644 --- a/engines/hopkins/dialogs.h +++ b/engines/hopkins/dialogs.h @@ -31,6 +31,8 @@ namespace Hopkins { class HopkinsEngine; +enum SaveLoadMode { MODE_SAVE = 1, MODE_LOAD = 2 }; + /** * Class for manging game dialogs */ @@ -38,7 +40,7 @@ class DialogsManager { private: HopkinsEngine *_vm; - void showSaveLoad(int a1); + void showSaveLoad(SaveLoadMode mode); int searchSavegames(); public: byte *_inventWin1; diff --git a/engines/hopkins/events.cpp b/engines/hopkins/events.cpp index 09a19a24ee..506cb68b56 100644 --- a/engines/hopkins/events.cpp +++ b/engines/hopkins/events.cpp @@ -334,12 +334,12 @@ int EventsManager::waitKeyPress() { else if (_keyState[(byte)' ']) foundChar = ' '; - VBL(); + refreshScreenAndEvents(); } // Wait for keypress release while (_keyState[(byte)foundChar] && !_vm->shouldQuit()) { - VBL(); + refreshScreenAndEvents(); g_system->delayMillis(10); } @@ -347,7 +347,7 @@ int EventsManager::waitKeyPress() { return foundChar; } -void EventsManager::VBL() { +void EventsManager::refreshScreenAndEvents() { int bottom = 0; int right = 0; int height = 0; diff --git a/engines/hopkins/events.h b/engines/hopkins/events.h index d4759dfe1b..52b9c25cd8 100644 --- a/engines/hopkins/events.h +++ b/engines/hopkins/events.h @@ -87,7 +87,7 @@ public: void mouseOff(); void setMouseOn(); - void VBL(); + void refreshScreenAndEvents(); }; } // End of namespace Hopkins diff --git a/engines/hopkins/files.cpp b/engines/hopkins/files.cpp index e0cd1a3995..5a15c1d68d 100644 --- a/engines/hopkins/files.cpp +++ b/engines/hopkins/files.cpp @@ -96,7 +96,7 @@ bool FileManager::fileExists(const Common::String &file) { /** * Search file in Cat file */ -byte *FileManager::searchCat(const Common::String &file, int a2) { +byte *FileManager::searchCat(const Common::String &file, CatMode mode) { byte *ptr = NULL; Common::File f; @@ -104,8 +104,8 @@ byte *FileManager::searchCat(const Common::String &file, int a2) { Common::String secondaryFilename = ""; filename.toUppercase(); - switch (a2) { - case 1: + switch (mode) { + case RES_INI: if (!f.exists("RES_INI.CAT")) return g_PTRNUL; @@ -113,7 +113,7 @@ byte *FileManager::searchCat(const Common::String &file, int a2) { secondaryFilename = "RES_INI.RES"; break; - case 2: + case RES_REP: if (!f.exists("RES_REP.CAT")) return g_PTRNUL; @@ -121,7 +121,7 @@ byte *FileManager::searchCat(const Common::String &file, int a2) { secondaryFilename = "RES_REP.RES"; break; - case 3: + case RES_LIN: if (!f.exists("RES_LIN.CAT")) return g_PTRNUL; @@ -129,7 +129,7 @@ byte *FileManager::searchCat(const Common::String &file, int a2) { secondaryFilename = "RES_LIN.RES"; break; - case 4: + case RES_ANI: if (!f.exists("RES_ANI.CAT")) return g_PTRNUL; @@ -137,7 +137,7 @@ byte *FileManager::searchCat(const Common::String &file, int a2) { secondaryFilename = "RES_ANI.RES"; break; - case 5: + case RES_PER: if (!f.exists("RES_PER.CAT")) return g_PTRNUL; @@ -145,28 +145,28 @@ byte *FileManager::searchCat(const Common::String &file, int a2) { secondaryFilename = "RES_PER.RES"; break; - case 6: + case RES_PIC: if (!f.exists("PIC.CAT")) return g_PTRNUL; ptr = loadFile("PIC.CAT"); break; - case 7: + case RES_SAN: if (!f.exists("RES_SAN.CAT")) return g_PTRNUL; ptr = loadFile("RES_SAN.CAT"); break; - case 8: + case RES_SLI: if (!f.exists("RES_SLI.CAT")) return g_PTRNUL; ptr = loadFile("RES_SLI.CAT"); break; - case 9: { + case RES_VOI: { Common::String tmpFilename; if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS) tmpFilename = "ENG_VOI.CAT"; diff --git a/engines/hopkins/files.h b/engines/hopkins/files.h index 55a57955b2..461bd22bf2 100644 --- a/engines/hopkins/files.h +++ b/engines/hopkins/files.h @@ -32,6 +32,11 @@ namespace Hopkins { class HopkinsEngine; +// CHECKME: RES_ANI looks unused +enum CatMode { RES_INI = 1, RES_REP = 2, RES_LIN = 3, RES_ANI = 4, + RES_PER = 5, RES_PIC = 6, RES_SAN = 7, RES_SLI = 8, + RES_VOI = 9 }; + class FileManager { public: HopkinsEngine *_vm; @@ -43,7 +48,7 @@ public: byte *loadFile(const Common::String &file); int readStream(Common::ReadStream &stream, void *buf, size_t nbytes); void initCensorship(); - byte *searchCat(const Common::String &file, int a2); + byte *searchCat(const Common::String &file, CatMode mode); uint32 fileSize(const Common::String &filename); }; diff --git a/engines/hopkins/font.cpp b/engines/hopkins/font.cpp index 62ce7f2a68..864da4fd8d 100644 --- a/engines/hopkins/font.cpp +++ b/engines/hopkins/font.cpp @@ -40,12 +40,27 @@ FontManager::FontManager() { FontManager::~FontManager() { _vm->_globals.freeMemory(_font); + _vm->_globals.freeMemory(_zoneText); } void FontManager::setParent(HopkinsEngine *vm) { _vm = vm; } +void FontManager::loadZoneText() { + switch (_vm->_globals._language) { + case LANG_EN: + _zoneText = _vm->_fileManager.loadFile("ZONEAN.TXT"); + break; + case LANG_FR: + _zoneText = _vm->_fileManager.loadFile("ZONE01.TXT"); + break; + case LANG_SP: + _zoneText = _vm->_fileManager.loadFile("ZONEES.TXT"); + break; + } +} + void FontManager::clearAll() { _font = g_PTRNUL; _fontFixedHeight = 0; @@ -71,13 +86,14 @@ void FontManager::clearAll() { _index[idx] = 0; _tempText = g_PTRNUL; + _zoneText = g_PTRNUL; } void FontManager::initData() { _font = _vm->_fileManager.loadFile("FONTE3.SPR"); _fontFixedWidth = 12; _fontFixedHeight = 21; - + loadZoneText(); } /** * Display Text @@ -209,8 +225,8 @@ void FontManager::box(int idx, int messageId, const Common::String &filename, in bufSize = 100; _tempText = _vm->_globals.allocMemory(110); Common::fill(&_tempText[0], &_tempText[110], 0); - memcpy(_tempText, _vm->_globals.BUF_ZONE + _index[messageId], 96); - WRITE_LE_UINT16((uint16 *)_tempText + 48, READ_LE_INT16(_vm->_globals.BUF_ZONE + _index[messageId] + 96)); + memcpy(_tempText, _zoneText + _index[messageId], 96); + WRITE_LE_UINT16((uint16 *)_tempText + 48, READ_LE_INT16(_zoneText + _index[messageId] + 96)); } byte *curTempTextPtr = _tempText; for (int i = 0; i < bufSize; i++) { @@ -466,10 +482,10 @@ void FontManager::renderTextDisplay(int xp, int yp, const Common::String &msg, i _vm->_graphicsManager.addDirtyRect(charStartPosX, yp, charEndPosX, yp + 12); if (_vm->_eventsManager._escKeyFl) { _vm->_globals.iRegul = 1; - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } else { _vm->_globals.iRegul = 4; - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); _vm->_globals.iRegul = 1; } } diff --git a/engines/hopkins/font.h b/engines/hopkins/font.h index 837539dd2f..1a27efbd82 100644 --- a/engines/hopkins/font.h +++ b/engines/hopkins/font.h @@ -67,7 +67,9 @@ private: Common::String _indexName; int _index[4048]; byte *_tempText; + byte *_zoneText; + void loadZoneText(); public: byte *_font; int _fontFixedWidth; diff --git a/engines/hopkins/globals.cpp b/engines/hopkins/globals.cpp index a9a39e2b50..fd474c510c 100644 --- a/engines/hopkins/globals.cpp +++ b/engines/hopkins/globals.cpp @@ -143,7 +143,6 @@ Globals::Globals() { // Initialize pointers for (int i = 0; i < 6; ++i) _hidingItemData[i] = g_PTRNUL; - BUF_ZONE = NULL; SPRITE_ECRAN = NULL; _saveData = NULL; _answerBuffer = g_PTRNUL; @@ -175,7 +174,6 @@ Globals::Globals() { } Globals::~Globals() { - freeMemory(BUF_ZONE); for (int idx = 0; idx < 6; ++idx) _hidingItemData[idx] = freeMemory(_hidingItemData[idx]); freeMemory(SPRITE_ECRAN); @@ -247,14 +245,14 @@ void Globals::clearAll() { _vm->_dialogsManager._inventBuf2 = g_PTRNUL; _answerBuffer = g_PTRNUL; SPRITE_ECRAN = g_PTRNUL; - _saveData = (Sauvegarde *)g_PTRNUL; + _saveData = (Savegame *)g_PTRNUL; _vm->_objectsManager._curObjectIndex = 0; _vm->_linesManager.clearAll(); _vm->_objectsManager.clearAll(); - _saveData = (Sauvegarde *)malloc(sizeof(Sauvegarde)); - memset(_saveData, 0, sizeof(Sauvegarde)); + _saveData = (Savegame *)malloc(sizeof(Savegame)); + memset(_saveData, 0, sizeof(Savegame)); _boxWidth = 240; diff --git a/engines/hopkins/globals.h b/engines/hopkins/globals.h index 9986abb810..c3e0190653 100644 --- a/engines/hopkins/globals.h +++ b/engines/hopkins/globals.h @@ -118,69 +118,59 @@ struct CharacterLocation { }; enum SauvegardeOffset { - svField1 = 1 - , svField2 = 2 - , svField3 = 3 - , svField4 = 4 - , svField5 = 5 - , svField6 = 6 - , svField8 = 8 - , svField9 = 9 - , svField10 = 10 - , svField13 = 13 - , svField80 = 80 + svLastMouseCursor = 1 + , svLastZoneNum = 2 + , svLastObjectIndex = 3 + , svDialogField4 = 4 + , svLastScreenId = 5 + , svLastPrevScreenId = 6 + , svLastInventoryItem = 8 + , svLastInvMouseCursor = 9 + , svLastSavegameSlot = 10 + , svFreedHostageFl = 80 , svField94 = 94 , svField95 = 95 - , svField113 = 113 - , svField117 = 117 - , svField121 = 121 - , svField122 = 122 - , svField123 = 123 + , svForestAvailableFl = 113 + , svHutBurningFl = 117 + , svHopkinsCloneFl = 121 + , svAlternateSpriteFl = 122 + , svHeavenGuardGoneFl = 123 , svField132 = 132 , svField133 = 133 - , svField135 = 135 - , svField166 = 166 - , svField167 = 167 - , svField170 = 170 - , svField171 = 171 - , svField172 = 172 + , svGameWonFl = 135 + , svCinemaCurtainCond1 = 166 + , svCinemaCurtainCond2 = 167 + , svBankAttackAnimPlayedFl = 170 + , svCopCall1PlayedFl = 171 + , svCopCall2PlayedFl = 172 , svField173 = 173 , svField176 = 176 - , svField177 = 177 - , svField180 = 180 - , svField181 = 181 - , svField182 = 182 + , svPoolDogGoneFl = 177 + , svCinemaDogGoneFl = 181 , svField183 = 183 , svField184 = 184 - , svField185 = 185 , svField186 = 186 - , svField187 = 187 , svField188 = 188 - , svField189 = 189 - , svField190 = 190 - , svField191 = 191 - , svField192 = 192 - , svField193 = 193 - , svField194 = 194 - , svField220 = 220 - , svField225 = 225 + , svField200 = 200 + , svField214 = 214 + , svBombBoxOpenedFl = 220 + , svBombDisarmedFl = 225 , svField228 = 228 , svField231 = 231 , svField253 = 253 , svField261 = 261 , svField270 = 270 , svField300 = 300 - , svField311 = 311 - , svField312 = 312 - , svField318 = 318 + , svBaseElevatorCond1 = 311 + , svBaseFireFl = 312 + , svSecondElevatorAvailableFl = 318 , svField320 = 320 - , svField330 = 330 + , svEscapeLeftJailFl = 330 , svField333 = 333 , svField338 = 338 , svField339 = 339 , svField340 = 340 , svField341 = 341 - , svField349 = 349 , svField352 = 352 , svField353 = 353 , svField354 = 354 @@ -192,7 +182,7 @@ enum SauvegardeOffset { }; // TODO: Sauvegrade1 fields should really be mapped into data array -struct Sauvegarde { +struct Savegame { byte _data[2050]; CharacterLocation _cloneHopkins; CharacterLocation _realHopkins; @@ -269,7 +259,7 @@ public: int _characterType; uint _speed; byte *_answerBuffer; - Sauvegarde *_saveData; + Savegame *_saveData; Language _language; HopkinsItem _hopkinsItem[70]; SortItem _sortedDisplay[51]; @@ -315,7 +305,6 @@ public: Common::String _textFilename; int iRegul; - byte *BUF_ZONE; byte *SPRITE_ECRAN; byte *PERSO; ListeItem Liste[6]; diff --git a/engines/hopkins/graphics.cpp b/engines/hopkins/graphics.cpp index 798b350fcd..09fe2f1f2a 100644 --- a/engines/hopkins/graphics.cpp +++ b/engines/hopkins/graphics.cpp @@ -174,13 +174,13 @@ void GraphicsManager::loadImage(const Common::String &file) { * Load VGA Image */ void GraphicsManager::loadVgaImage(const Common::String &file) { - SCANLINE(SCREEN_WIDTH); + setScreenWidth(SCREEN_WIDTH); lockScreen(); clearScreen(); unlockScreen(); loadPCX320(_vesaScreen, file, _palette); memcpy(_vesaBuffer, _vesaScreen, 64000); - SCANLINE(320); + setScreenWidth(320); _maxX = 320; lockScreen(); @@ -199,7 +199,7 @@ void GraphicsManager::loadScreen(const Common::String &file) { assert(!_videoPtr); bool flag = true; - if (_vm->_fileManager.searchCat(file, 6) == g_PTRNUL) { + if (_vm->_fileManager.searchCat(file, RES_PIC) == g_PTRNUL) { if (!f.open(file)) error("loadScreen - %s", file.c_str()); @@ -216,14 +216,14 @@ void GraphicsManager::loadScreen(const Common::String &file) { clearPalette(); if (!_largeScreenFl) { - SCANLINE(SCREEN_WIDTH); + setScreenWidth(SCREEN_WIDTH); _maxX = SCREEN_WIDTH; lockScreen(); clearScreen(); m_scroll16(_vesaScreen, 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); unlockScreen(); } else { - SCANLINE(SCREEN_WIDTH * 2); + setScreenWidth(SCREEN_WIDTH * 2); _maxX = SCREEN_WIDTH * 2; lockScreen(); clearScreen(); @@ -408,7 +408,7 @@ void GraphicsManager::clearPalette() { SD_PIXELS[0] = 0; } -void GraphicsManager::SCANLINE(int pitch) { +void GraphicsManager::setScreenWidth(int pitch) { _lineNbr = _lineNbr2 = pitch; } @@ -568,7 +568,7 @@ void GraphicsManager::fadeIn(const byte *palette, int step, const byte *surface) // Set the transition palette and refresh the screen setPaletteVGA256(palData2); m_scroll16(surface, _vm->_eventsManager._startPos.x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); - DD_VBL(); + updateScreen(); // Added a delay in order to see the fading _vm->_eventsManager.delay(20); @@ -579,7 +579,7 @@ void GraphicsManager::fadeIn(const byte *palette, int step, const byte *surface) // Refresh the screen m_scroll16(surface, _vm->_eventsManager._startPos.x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); - DD_VBL(); + updateScreen(); } /** @@ -598,7 +598,7 @@ void GraphicsManager::fadeOut(const byte *palette, int step, const byte *surface setPaletteVGA256(palData); m_scroll16(surface, _vm->_eventsManager._startPos.x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); - DD_VBL(); + updateScreen(); _vm->_eventsManager.delay(20); } @@ -610,7 +610,8 @@ void GraphicsManager::fadeOut(const byte *palette, int step, const byte *surface setPaletteVGA256(palData); m_scroll16(surface, _vm->_eventsManager._startPos.x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); - DD_VBL(); + + updateScreen(); } /** @@ -669,7 +670,7 @@ void GraphicsManager::fadeInBreakout() { lockScreen(); copy16bFromSurfaceScaleX2(_vesaBuffer); unlockScreen(); - DD_VBL(); + updateScreen(); } /** @@ -684,7 +685,7 @@ void GraphicsManager::fadeOutBreakout() { lockScreen(); copy16bFromSurfaceScaleX2(_vesaBuffer); unlockScreen(); - DD_VBL(); + updateScreen(); } void GraphicsManager::setPaletteVGA256(const byte *palette) { @@ -694,7 +695,7 @@ void GraphicsManager::setPaletteVGA256(const byte *palette) { void GraphicsManager::setPaletteVGA256WithRefresh(const byte *palette, const byte *surface) { changePalette(palette); m_scroll16(surface, _vm->_eventsManager._startPos.x, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, 0); - DD_VBL(); + updateScreen(); } void GraphicsManager::SETCOLOR3(int palIndex, int r, int g, int b) { @@ -732,7 +733,8 @@ uint16 GraphicsManager::mapRGB(byte r, byte g, byte b) { | (b >> format.bLoss) << format.bShift; } -void GraphicsManager::DD_VBL() { +void GraphicsManager::updateScreen() { + // TODO: Is this okay here? // Display any aras of the screen that need refreshing displayDirtyRects(); displayRefreshRects(); @@ -1067,8 +1069,8 @@ void GraphicsManager::endDisplayBob() { _vm->_objectsManager.hideBob(idx); } - _vm->_eventsManager.VBL(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); + _vm->_eventsManager.refreshScreenAndEvents(); for (int idx = 1; idx <= 20; ++idx) { if (_vm->_globals._animBqe[idx]._enabledFl) @@ -1742,7 +1744,7 @@ void GraphicsManager::displayFont(byte *surface, const byte *spriteData, int xp, void GraphicsManager::initScreen(const Common::String &file, int mode, bool initializeScreen) { Common::String filename = file + ".ini"; - byte *ptr = _vm->_fileManager.searchCat(filename, 1); + byte *ptr = _vm->_fileManager.searchCat(filename, RES_INI); if (ptr == g_PTRNUL) { ptr = _vm->_fileManager.loadFile(filename); @@ -1751,7 +1753,7 @@ void GraphicsManager::initScreen(const Common::String &file, int mode, bool init filename = file + ".spr"; _vm->_globals.SPRITE_ECRAN = _vm->_globals.freeMemory(_vm->_globals.SPRITE_ECRAN); if (initializeScreen) { - _vm->_globals.SPRITE_ECRAN = _vm->_fileManager.searchCat(filename, 8); + _vm->_globals.SPRITE_ECRAN = _vm->_fileManager.searchCat(filename, RES_SLI); if (_vm->_globals.SPRITE_ECRAN) { _vm->_globals.SPRITE_ECRAN = _vm->_fileManager.loadFile(filename); } else { @@ -1760,7 +1762,7 @@ void GraphicsManager::initScreen(const Common::String &file, int mode, bool init } } if (READ_BE_UINT24(ptr) != MKTAG24('I', 'N', 'I')) { - error("Error, file not ini"); + error("Invalid INI File %s", file.c_str()); } else { bool doneFlag = false; int dataOffset = 1; @@ -1786,7 +1788,7 @@ void GraphicsManager::initScreen(const Common::String &file, int mode, bool init _vm->_globals._answerBuffer = _vm->_globals.freeMemory(_vm->_globals._answerBuffer); filename = file + ".rep"; - byte *dataP = _vm->_fileManager.searchCat(filename, 2); + byte *dataP = _vm->_fileManager.searchCat(filename, RES_REP); if (dataP == g_PTRNUL) dataP = _vm->_fileManager.loadFile(filename); @@ -1809,7 +1811,7 @@ void GraphicsManager::NB_SCREEN(bool initPalette) { unlockScreen(); memcpy(_vesaScreen, _vesaBuffer, 614399); - DD_VBL(); + updateScreen(); } void GraphicsManager::copyWinscanVbe(const byte *src, byte *dest) { @@ -1841,7 +1843,7 @@ void GraphicsManager::copyWinscanVbe(const byte *src, byte *dest) { } // Reduce Screen -void GraphicsManager::Reduc_Ecran(const byte *srcSurface, byte *destSurface, int xp, int yp, int width, int height, int zoom) { +void GraphicsManager::reduceScreenPart(const byte *srcSurface, byte *destSurface, int xp, int yp, int width, int height, int zoom) { const byte *srcP = xp + _lineNbr2 * yp + srcSurface; byte *destP = destSurface; Red = zoom; diff --git a/engines/hopkins/graphics.h b/engines/hopkins/graphics.h index cdf9962400..eb1a79d707 100644 --- a/engines/hopkins/graphics.h +++ b/engines/hopkins/graphics.h @@ -164,20 +164,20 @@ public: void initScreen(const Common::String &file, int mode, bool initializeScreen); void displayAllBob(); void endDisplayBob(); + void updateScreen(); + void reduceScreenPart(const byte *srcSruface, byte *destSurface, int xp, int yp, int width, int height, int zoom); void SETCOLOR3(int palIndex, int r, int g, int b); void SETCOLOR4(int palIndex, int r, int g, int b); void AFFICHE_SPEEDVGA(const byte *objectData, int xp, int yp, int idx, bool addSegment = true); - void DD_VBL(); void Affiche_Perfect(byte *surface, const byte *srcData, int xp300, int yp300, int frameIndex, int zoom1, int zoom2, bool flipFl); void Copy_Mem(const byte *srcSurface, int x1, int y1, uint16 width, int height, byte *destSurface, int destX, int destY); - void SCANLINE(int pitch); + void setScreenWidth(int pitch); void Sprite_Vesa(byte *surface, const byte *spriteData, int xp, int yp, int spriteIndex); void m_scroll16(const byte *surface, int xs, int ys, int width, int height, int destX, int destY); void m_scroll16A(const byte *surface, int xs, int ys, int width, int height, int destX, int destY); void Trans_bloc2(byte *surface, byte *col, int size); void NB_SCREEN(bool initPalette); - void Reduc_Ecran(const byte *srcSruface, byte *destSurface, int xp, int yp, int width, int height, int zoom); }; } // End of namespace Hopkins diff --git a/engines/hopkins/hopkins.cpp b/engines/hopkins/hopkins.cpp index ce4f0f5049..2821746232 100644 --- a/engines/hopkins/hopkins.cpp +++ b/engines/hopkins/hopkins.cpp @@ -139,7 +139,7 @@ bool HopkinsEngine::runWin95Demo() { for (int i = 1; i < 50; i++) { _graphicsManager.copySurface(_graphicsManager._vesaScreen, 0, 0, 640, 440, _graphicsManager._vesaBuffer, 0, 0); - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); } _globals.iRegul = 0; @@ -183,7 +183,7 @@ bool HopkinsEngine::runWin95Demo() { break; case 3: - if (!_globals._saveData->_data[svField170]) { + if (!_globals._saveData->_data[svBankAttackAnimPlayedFl]) { _soundManager.playSound(3); if (getPlatform() == Common::kPlatformOS2 || getPlatform() == Common::kPlatformBeOS) _graphicsManager.loadImage("fond"); @@ -214,7 +214,7 @@ bool HopkinsEngine::runWin95Demo() { _soundManager.removeSample(3); _soundManager.removeSample(4); _graphicsManager.fadeOutLong(); - _globals._saveData->_data[svField170] = 1; + _globals._saveData->_data[svBankAttackAnimPlayedFl] = 1; } _linesManager.setMaxLineIdx(5); _globals._characterMaxPosY = 450; @@ -231,8 +231,8 @@ bool HopkinsEngine::runWin95Demo() { _linesManager.setMaxLineIdx(5); _globals._characterMaxPosY = 455; - if (_globals._saveData->_data[svField80]) { - if (_globals._saveData->_data[svField80] == 1) + if (_globals._saveData->_data[svFreedHostageFl]) { + if (_globals._saveData->_data[svFreedHostageFl] == 1) _objectsManager.PERSONAGE2("IM05", "IM05A", "ANIM05B", "IM05", 3, false); } else { _objectsManager.PERSONAGE2("IM05", "IM05", "ANIM05", "IM05", 3, false); @@ -246,7 +246,7 @@ bool HopkinsEngine::runWin95Demo() { break; case 7: - if (_globals._saveData->_data[svField220]) + if (_globals._saveData->_data[svBombBoxOpenedFl]) _objectsManager.PERSONAGE("BOMBEB", "BOMBE", "BOMBE", "BOMBE", 2, true); else _objectsManager.PERSONAGE("BOMBEA", "BOMBE", "BOMBE", "BOMBE", 2, true); @@ -261,7 +261,7 @@ bool HopkinsEngine::runWin95Demo() { case 9: _globals._characterMaxPosY = 440; _linesManager.setMaxLineIdx(20); - if (_globals._saveData->_data[svField225]) + if (_globals._saveData->_data[svBombDisarmedFl]) _objectsManager.PERSONAGE2("IM09", "IM09", "ANIM09", "IM09", 10, true); else bombExplosion(); @@ -280,7 +280,7 @@ bool HopkinsEngine::runWin95Demo() { case 12: _globals._characterMaxPosY = 450; _linesManager.setMaxLineIdx(20); - if (_globals._saveData->_data[svField225]) { + if (_globals._saveData->_data[svBombDisarmedFl]) { if (_globals._language == LANG_FR) _graphicsManager.loadImage("ENDFR"); else @@ -288,12 +288,12 @@ bool HopkinsEngine::runWin95Demo() { _graphicsManager.fadeInLong(); _eventsManager.mouseOn(); do - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); while (_eventsManager.getMouseButton() != 1); _graphicsManager.fadeOutLong(); restoreSystem(); - } - bombExplosion(); + } else + bombExplosion(); break; case 13: @@ -332,14 +332,14 @@ bool HopkinsEngine::runWin95Demo() { case 113: _globals._exitId = 0; _globals._prevScreenId = _globals._screenId; - _globals._saveData->_data[svField6] = _globals._screenId; + _globals._saveData->_data[svLastPrevScreenId] = _globals._screenId; _globals._screenId = 113; - _globals._saveData->_data[svField5] = _globals._screenId; + _globals._saveData->_data[svLastScreenId] = _globals._screenId; _computerManager.showComputer(COMPUTER_HOPKINS); _graphicsManager.lockScreen(); _graphicsManager.clearScreen(); _graphicsManager.unlockScreen(); - _graphicsManager.DD_VBL(); + _graphicsManager.updateScreen(); memset(_graphicsManager._vesaBuffer, 0, 307200); memset(_graphicsManager._vesaScreen, 0, 307200); _graphicsManager.clearPalette(); @@ -348,9 +348,9 @@ bool HopkinsEngine::runWin95Demo() { case 114: _globals._prevScreenId = _globals._screenId; - _globals._saveData->_data[svField6] = _globals._screenId; + _globals._saveData->_data[svLastPrevScreenId] = _globals._screenId; _globals._screenId = 114; - _globals._saveData->_data[svField5] = _globals._screenId; + _globals._saveData->_data[svLastScreenId] = _globals._screenId; _globals._exitId = 0; _computerManager.showComputer(COMPUTER_SAMANTHA); _graphicsManager.lockScreen(); @@ -361,9 +361,9 @@ bool HopkinsEngine::runWin95Demo() { case 115: _globals._exitId = 0; _globals._prevScreenId = _globals._screenId; - _globals._saveData->_data[svField6] = _globals._screenId; + _globals._saveData->_data[svLastPrevScreenId] = _globals._screenId; _globals._screenId = 115; - _globals._saveData->_data[svField5] = _globals._screenId; + _globals._saveData->_data[svLastScreenId] = _globals._screenId; _computerManager.showComputer(COMPUTER_PUBLIC); _graphicsManager.lockScreen(); _graphicsManager.clearScreen(); @@ -488,7 +488,7 @@ bool HopkinsEngine::runLinuxDemo() { break; case 3: - if (!_globals._saveData->_data[svField170]) { + if (!_globals._saveData->_data[svBankAttackAnimPlayedFl]) { _soundManager.playSound(3); if (getPlatform() == Common::kPlatformOS2 || getPlatform() == Common::kPlatformBeOS) _graphicsManager.loadImage("fond"); @@ -521,7 +521,7 @@ bool HopkinsEngine::runLinuxDemo() { _soundManager.removeSample(2); _soundManager.removeSample(3); _soundManager.removeSample(4); - _globals._saveData->_data[svField170] = 1; + _globals._saveData->_data[svBankAttackAnimPlayedFl] = 1; } _linesManager.setMaxLineIdx(5); @@ -538,7 +538,7 @@ bool HopkinsEngine::runLinuxDemo() { case 5: _linesManager.setMaxLineIdx(5); _globals._characterMaxPosY = 455; - if (_globals._saveData->_data[svField80] == 1) + if (_globals._saveData->_data[svFreedHostageFl] == 1) _objectsManager.PERSONAGE2("IM05", "IM05A", "ANIM05B", "IM05", 3, false); else _objectsManager.PERSONAGE2("IM05", "IM05", "ANIM05", "IM05", 3, false); @@ -551,7 +551,7 @@ bool HopkinsEngine::runLinuxDemo() { break; case 7: - if (_globals._saveData->_data[svField220]) + if (_globals._saveData->_data[svBombBoxOpenedFl]) _objectsManager.PERSONAGE("BOMBEB", "BOMBE", "BOMBE", "BOMBE", 2, true); else _objectsManager.PERSONAGE("BOMBEA", "BOMBE", "BOMBE", "BOMBE", 2, true); @@ -567,10 +567,10 @@ bool HopkinsEngine::runLinuxDemo() { _linesManager.setMaxLineIdx(20); _globals._characterMaxPosY = 440; - if (!_globals._saveData->_data[svField225]) + if (!_globals._saveData->_data[svBombDisarmedFl]) bombExplosion(); - - _objectsManager.PERSONAGE2("IM09", "IM09", "ANIM09", "IM09", 10, true); + else + _objectsManager.PERSONAGE2("IM09", "IM09", "ANIM09", "IM09", 10, true); break; case 10: @@ -586,7 +586,7 @@ bool HopkinsEngine::runLinuxDemo() { case 12: _linesManager.setMaxLineIdx(20); _globals._characterMaxPosY = 450; - if (_globals._saveData->_data[svField225]) + if (_globals._saveData->_data[svBombDisarmedFl]) _objectsManager.PERSONAGE2("IM12", "IM12", "ANIM12", "IM12", 1, false); else bombExplosion(); @@ -612,9 +612,9 @@ bool HopkinsEngine::runLinuxDemo() { _linesManager.setMaxLineIdx(5); _globals._characterMaxPosY = 450; - if (_globals._saveData->_data[svField113] == 1) { + if (_globals._saveData->_data[svForestAvailableFl] == 1) { _objectsManager.PERSONAGE2("IM16", "IM16A", "ANIM16", "IM16", 7, true); - } else if (!_globals._saveData->_data[svField113]) { + } else if (!_globals._saveData->_data[svForestAvailableFl]) { _objectsManager.PERSONAGE2("IM16", "IM16", "ANIM16", "IM16", 7, true); } break; @@ -649,15 +649,15 @@ bool HopkinsEngine::runLinuxDemo() { case 113: _globals._exitId = 0; _globals._prevScreenId = _globals._screenId; - _globals._saveData->_data[svField6] = _globals._screenId; + _globals._saveData->_data[svLastPrevScreenId] = _globals._screenId; _globals._screenId = 113; - _globals._saveData->_data[svField5] = 113; + _globals._saveData->_data[svLastScreenId] = 113; _computerManager.showComputer(COMPUTER_HOPKINS); _graphicsManager.lockScreen(); _graphicsManager.clearScreen(); _graphicsManager.unlockScreen(); - _graphicsManager.DD_VBL(); + _graphicsManager.updateScreen(); memset(_graphicsManager._vesaBuffer, 0, 307200); memset(_graphicsManager._vesaScreen, 0, 307200); _graphicsManager.clearPalette(); @@ -667,9 +667,9 @@ bool HopkinsEngine::runLinuxDemo() { case 114: _globals._exitId = 0; _globals._prevScreenId = _globals._screenId; - _globals._saveData->_data[svField6] = _globals._screenId; + _globals._saveData->_data[svLastPrevScreenId] = _globals._screenId; _globals._screenId = 114; - _globals._saveData->_data[svField5] = 114; + _globals._saveData->_data[svLastScreenId] = 114; _computerManager.showComputer(COMPUTER_SAMANTHA); _graphicsManager.lockScreen(); _graphicsManager.clearScreen(); @@ -679,9 +679,9 @@ bool HopkinsEngine::runLinuxDemo() { case 115: _globals._exitId = 0; _globals._prevScreenId = _globals._screenId; - _globals._saveData->_data[svField6] = _globals._screenId; + _globals._saveData->_data[svLastPrevScreenId] = _globals._screenId; _globals._screenId = 115; - _globals._saveData->_data[svField5] = 115; + _globals._saveData->_data[svLastScreenId] = 115; _computerManager.showComputer(COMPUTER_PUBLIC); _graphicsManager.lockScreen(); _graphicsManager.clearScreen(); @@ -833,7 +833,7 @@ bool HopkinsEngine::runFull() { break; case 3: - if (!_globals._saveData->_data[svField170]) { + if (!_globals._saveData->_data[svBankAttackAnimPlayedFl]) { _soundManager.playSound(3); if (getPlatform() == Common::kPlatformOS2 || getPlatform() == Common::kPlatformBeOS) _graphicsManager.loadImage("fond"); @@ -872,7 +872,7 @@ bool HopkinsEngine::runFull() { _soundManager.removeSample(4); if (getPlatform() != Common::kPlatformLinux) _graphicsManager.fadeOutLong(); - _globals._saveData->_data[svField170] = 1; + _globals._saveData->_data[svBankAttackAnimPlayedFl] = 1; } _linesManager.setMaxLineIdx(5); _globals._characterMaxPosY = 450; @@ -888,7 +888,7 @@ bool HopkinsEngine::runFull() { case 5: _linesManager.setMaxLineIdx(5); _globals._characterMaxPosY = 455; - if (_globals._saveData->_data[svField80] == 1) + if (_globals._saveData->_data[svFreedHostageFl] == 1) _objectsManager.PERSONAGE2("IM05", "IM05A", "ANIM05B", "IM05", 3, false); else _objectsManager.PERSONAGE2("IM05", "IM05", "ANIM05", "IM05", 3, false); @@ -901,7 +901,7 @@ bool HopkinsEngine::runFull() { break; case 7: - if (_globals._saveData->_data[svField220]) + if (_globals._saveData->_data[svBombBoxOpenedFl]) _objectsManager.PERSONAGE("BOMBEB", "BOMBE", "BOMBE", "BOMBE", 2, true); else _objectsManager.PERSONAGE("BOMBEA", "BOMBE", "BOMBE", "BOMBE", 2, true); @@ -916,7 +916,7 @@ bool HopkinsEngine::runFull() { case 9: _linesManager.setMaxLineIdx(20); _globals._characterMaxPosY = 440; - if (_globals._saveData->_data[svField225]) + if (_globals._saveData->_data[svBombDisarmedFl]) _objectsManager.PERSONAGE2("IM09", "IM09", "ANIM09", "IM09", 10, true); else bombExplosion(); @@ -935,7 +935,7 @@ bool HopkinsEngine::runFull() { case 12: _linesManager.setMaxLineIdx(20); _globals._characterMaxPosY = 450; - if (_globals._saveData->_data[svField225]) + if (_globals._saveData->_data[svBombDisarmedFl]) _objectsManager.PERSONAGE2("IM12", "IM12", "ANIM12", "IM12", 1, false); else bombExplosion(); @@ -963,7 +963,7 @@ bool HopkinsEngine::runFull() { case 16: _linesManager.setMaxLineIdx(5); _globals._characterMaxPosY = 450; - if (_globals._saveData->_data[svField113] == 1) + if (_globals._saveData->_data[svForestAvailableFl] == 1) _objectsManager.PERSONAGE2("IM16", "IM16A", "ANIM16", "IM16", 7, true); else _objectsManager.PERSONAGE2("IM16", "IM16", "ANIM16", "IM16", 7, true); @@ -972,9 +972,9 @@ bool HopkinsEngine::runFull() { case 17: _linesManager.setMaxLineIdx(40); _globals._characterMaxPosY = 440; - if (_globals._saveData->_data[svField117] == 1) + if (_globals._saveData->_data[svHutBurningFl] == 1) _objectsManager.PERSONAGE2("IM17", "IM17A", "ANIM17", "IM17", 11, true); - else if (!_globals._saveData->_data[svField117]) + else if (!_globals._saveData->_data[svHutBurningFl]) _objectsManager.PERSONAGE2("IM17", "IM17", "ANIM17", "IM17", 11, true); if (_globals._exitId == 18) { _globals.iRegul = 1; @@ -1012,7 +1012,7 @@ bool HopkinsEngine::runFull() { case 19: _linesManager.setMaxLineIdx(40); _globals._characterMaxPosY = 440; - if (_globals._saveData->_data[svField123]) + if (_globals._saveData->_data[svHeavenGuardGoneFl]) _objectsManager.PERSONAGE2("IM19", "IM19A", "ANIM19", "IM19", 6, true); else _objectsManager.PERSONAGE2("IM19", "IM19", "ANIM19", "IM19", 6, true); @@ -1054,7 +1054,7 @@ bool HopkinsEngine::runFull() { case 24: _linesManager.setMaxLineIdx(5); _globals._characterMaxPosY = 450; - if (_globals._saveData->_data[svField181] == 1) + if (_globals._saveData->_data[svCinemaDogGoneFl] == 1) _objectsManager.PERSONAGE2("IM24", "IM24A", "ANIM24", "IM24", 1, true); else _objectsManager.PERSONAGE2("IM24", "IM24", "ANIM24", "IM24", 1, true); @@ -1081,7 +1081,7 @@ bool HopkinsEngine::runFull() { case 27: _linesManager.setMaxLineIdx(15); _globals._characterMaxPosY = 440; - if (_globals._saveData->_data[svField177] == 1) + if (_globals._saveData->_data[svPoolDogGoneFl] == 1) _objectsManager.PERSONAGE2("IM27", "IM27A", "ANIM27", "IM27", 27, true); else _objectsManager.PERSONAGE2("IM27", "IM27", "ANIM27", "IM27", 27, true); @@ -1090,7 +1090,7 @@ bool HopkinsEngine::runFull() { case 28: _linesManager.setMaxLineIdx(5); _globals._characterMaxPosY = 450; - if (_globals._saveData->_data[svField166] != 1 || _globals._saveData->_data[svField167] != 1) + if (_globals._saveData->_data[svCinemaCurtainCond1] != 1 || _globals._saveData->_data[svCinemaCurtainCond2] != 1) _objectsManager.PERSONAGE2("IM28", "IM28", "ANIM28", "IM28", 1, false); else _objectsManager.PERSONAGE2("IM28A", "IM28", "ANIM28", "IM28", 1, false); @@ -1153,7 +1153,7 @@ bool HopkinsEngine::runFull() { } case 50: - displayPlane(); + playPlaneCutscene(); _globals._exitId = 51; break; @@ -1212,7 +1212,7 @@ bool HopkinsEngine::runFull() { break; case 61: - if (_globals._saveData->_data[svField311] == 1 && !_globals._saveData->_data[svField312]) + if (_globals._saveData->_data[svBaseElevatorCond1] == 1 && !_globals._saveData->_data[svBaseFireFl]) handleConflagration(); _objectsManager.PERSONAGE("IM61", "IM61", "ANIM61", "IM61", 21, false); break; @@ -1280,14 +1280,14 @@ bool HopkinsEngine::runFull() { case 73: _linesManager.setMaxLineIdx(15); _globals._characterMaxPosY = 445; - if (_globals._saveData->_data[svField318] == 1) + if (_globals._saveData->_data[svSecondElevatorAvailableFl] == 1) _objectsManager.PERSONAGE2("IM73", "IM73A", "ANIM73", "IM73", 21, true); else _objectsManager.PERSONAGE2("IM73", "IM73", "ANIM73", "IM73", 21, true); break; case 75: - BASE(); + playSubmarineCutscene(); break; case 77: @@ -1343,7 +1343,7 @@ bool HopkinsEngine::runFull() { break; case 90: - BASED(); + playUnderwaterBaseCutscene(); break; case 91: @@ -1353,7 +1353,7 @@ bool HopkinsEngine::runFull() { case 93: _linesManager.setMaxLineIdx(5); _globals._characterMaxPosY = 445; - if (_globals._saveData->_data[svField330]) { + if (_globals._saveData->_data[svEscapeLeftJailFl]) { if (getPlatform() == Common::kPlatformLinux || getPlatform() == Common::kPlatformWindows) _objectsManager.PERSONAGE2("IM93", "IM93C", "ANIM93", "IM93", 29, true); else @@ -1429,14 +1429,14 @@ bool HopkinsEngine::runFull() { case 113: _globals._prevScreenId = _globals._screenId; _globals._screenId = 113; - _globals._saveData->_data[svField6] = _globals._prevScreenId; - _globals._saveData->_data[svField5] = _globals._screenId; + _globals._saveData->_data[svLastPrevScreenId] = _globals._prevScreenId; + _globals._saveData->_data[svLastScreenId] = _globals._screenId; _globals._exitId = 0; _computerManager.showComputer(COMPUTER_HOPKINS); _graphicsManager.lockScreen(); _graphicsManager.clearScreen(); _graphicsManager.unlockScreen(); - _graphicsManager.DD_VBL(); + _graphicsManager.updateScreen(); memset(_graphicsManager._vesaBuffer, 0, 307200); memset(_graphicsManager._vesaScreen, 0, 307200); _graphicsManager.clearPalette(); @@ -1447,8 +1447,8 @@ bool HopkinsEngine::runFull() { _globals._exitId = 0; _globals._prevScreenId = _globals._screenId; _globals._screenId = 114; - _globals._saveData->_data[svField6] = _globals._prevScreenId; - _globals._saveData->_data[svField5] = _globals._screenId; + _globals._saveData->_data[svLastPrevScreenId] = _globals._prevScreenId; + _globals._saveData->_data[svLastScreenId] = _globals._screenId; _computerManager.showComputer(COMPUTER_SAMANTHA); _graphicsManager.lockScreen(); _graphicsManager.clearScreen(); @@ -1458,8 +1458,8 @@ bool HopkinsEngine::runFull() { case 115: _globals._prevScreenId = _globals._screenId; _globals._screenId = 115; - _globals._saveData->_data[svField6] = _globals._prevScreenId; - _globals._saveData->_data[svField5] = _globals._screenId; + _globals._saveData->_data[svLastPrevScreenId] = _globals._prevScreenId; + _globals._saveData->_data[svLastScreenId] = _globals._screenId; _globals._exitId = 0; _computerManager.showComputer(COMPUTER_PUBLIC); _graphicsManager.lockScreen(); @@ -1572,18 +1572,6 @@ void HopkinsEngine::initializeSystem() { _dialogsManager._inventoryIcons = _fileManager.loadFile("ICONE.SPR"); _objectsManager._headSprites = _fileManager.loadFile("TETE.SPR"); - switch (_globals._language) { - case LANG_EN: - _globals.BUF_ZONE = _fileManager.loadFile("ZONEAN.TXT"); - break; - case LANG_FR: - _globals.BUF_ZONE = _fileManager.loadFile("ZONE01.TXT"); - break; - case LANG_SP: - _globals.BUF_ZONE = _fileManager.loadFile("ZONEES.TXT"); - break; - } - _eventsManager.setMouseOn(); _eventsManager._mouseFl = false; @@ -1605,10 +1593,10 @@ void HopkinsEngine::playIntro() { byte paletteData2[PALETTE_EXT_BLOCK_SIZE]; memset(&paletteData, 0, PALETTE_EXT_BLOCK_SIZE); - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); _eventsManager._mouseFl = false; _globals.iRegul = 1; - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); _soundManager.playSound(16); _animationManager._clearAnimationFl = true; _animationManager.playAnim("J1.anm", 12, 12, 50); @@ -1632,7 +1620,7 @@ void HopkinsEngine::playIntro() { _graphicsManager.clearScreen(); _graphicsManager.unlockScreen(); _graphicsManager.clearPalette(); - _graphicsManager.DD_VBL(); + _graphicsManager.updateScreen(); _soundManager.playSound(11); _graphicsManager.loadImage("intro1"); _graphicsManager.scrollScreen(0); @@ -1642,7 +1630,7 @@ void HopkinsEngine::playIntro() { _graphicsManager.SETCOLOR3(251, 100, 100, 100); _graphicsManager.SETCOLOR3(254, 0, 0, 0); for (int i = 0; i <= 4; i++) - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); _globals.iRegul = 1; _graphicsManager.fadeInLong(); @@ -1660,10 +1648,10 @@ void HopkinsEngine::playIntro() { if (_eventsManager.getMouseX() < _graphicsManager._scrollPosX + 10) _eventsManager.setMouseXY(_eventsManager._mousePos.x + 4, _eventsManager.getMouseY()); - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); } while (!shouldQuit() && !loopCond && _graphicsManager._scrollPosX != SCREEN_WIDTH); - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); _graphicsManager._scrollStatus = 0; if (shouldQuit()) @@ -1687,17 +1675,17 @@ void HopkinsEngine::playIntro() { _graphicsManager.SETCOLOR3(254, 0, 0, 0); for (int i = 0; i <= 4; i++) - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); _globals.iRegul = 1; _graphicsManager.fadeInLong(); for (uint i = 0; i < 200 / _globals._speed; ++i) - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); _objectsManager.setBobAnimation(3); _soundManager.mixVoice(5, 3); _objectsManager.stopBobAnimation(3); - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); memcpy(&paletteData2, _graphicsManager._palette, 796); _graphicsManager.setPaletteVGA256WithRefresh(paletteData, _graphicsManager._vesaBuffer); @@ -1729,7 +1717,7 @@ void HopkinsEngine::playIntro() { _graphicsManager.SETCOLOR3(254, 0, 0, 0); for (int i = 0; i <= 3; i++) - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); _globals.iRegul = 1; _graphicsManager.setPaletteVGA256WithRefresh(paletteData2, _graphicsManager._vesaBuffer); @@ -1738,9 +1726,9 @@ void HopkinsEngine::playIntro() { while (!shouldQuit() && !_eventsManager._escKeyFl) { if (introIndex == 12) { _objectsManager.setBobAnimation(3); - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); _soundManager.mixVoice(6, 3); - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); _objectsManager.stopBobAnimation(3); } @@ -1754,28 +1742,28 @@ void HopkinsEngine::playIntro() { _graphicsManager.setPaletteVGA256WithRefresh(_graphicsManager._palette, _graphicsManager._vesaBuffer); for (int i = 1; i < 2 * introIndex; i++) - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); _graphicsManager.setPaletteVGA256WithRefresh(paletteData2, _graphicsManager._vesaBuffer); for (int i = 1; i < 20 - introIndex; i++) - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); introIndex += 2; if (introIndex > 15) { _graphicsManager.setPaletteVGA256WithRefresh(paletteData, _graphicsManager._vesaBuffer); for (uint j = 1; j < 100 / _globals._speed; ++j) - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); _objectsManager.setBobAnimation(3); _soundManager.mixVoice(7, 3); _objectsManager.stopBobAnimation(3); for (uint k = 1; k < 60 / _globals._speed; ++k) - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); _objectsManager.setBobAnimation(5); for (uint l = 0; l < 20 / _globals._speed; ++l) - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); Common::copy(&paletteData2[0], &paletteData2[PALETTE_BLOCK_SIZE], &_graphicsManager._palette[0]); _graphicsManager.setPaletteVGA256WithRefresh(_graphicsManager._palette, _graphicsManager._vesaBuffer); @@ -1787,7 +1775,7 @@ void HopkinsEngine::playIntro() { _objectsManager.stopBobAnimation(3); } - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); } _graphicsManager.fadeOutLong(); @@ -1862,7 +1850,7 @@ void HopkinsEngine::displayEndDemo() { void HopkinsEngine::bombExplosion() { _graphicsManager._lineNbr = SCREEN_WIDTH; - _graphicsManager.SCANLINE(SCREEN_WIDTH); + _graphicsManager.setScreenWidth(SCREEN_WIDTH); _graphicsManager.lockScreen(); _graphicsManager.clearScreen(); _graphicsManager.unlockScreen(); @@ -1879,14 +1867,14 @@ void HopkinsEngine::bombExplosion() { _objectsManager.stopBobAnimation(7); for (int idx = 0; idx < 5; ++idx) { - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); } _graphicsManager.fadeInLong(); _eventsManager.mouseOff(); for (int idx = 0; idx < 20; ++idx) { - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); } _globals._introSpeechOffFl = true; @@ -1895,7 +1883,7 @@ void HopkinsEngine::bombExplosion() { _objectsManager.setBobAnimation(7); for (int idx = 0; idx < 100; ++idx) { - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); } _graphicsManager.fadeOutLong(); @@ -1926,7 +1914,7 @@ void HopkinsEngine::endLinuxDemo() { bool mouseClicked = false; do { - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); if (_eventsManager.getMouseButton() == 1) mouseClicked = true; @@ -1950,28 +1938,28 @@ void HopkinsEngine::handleConflagration() { _graphicsManager.displayAllBob(); for (int cpt = 0; cpt <= 4; cpt++) - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); _graphicsManager.fadeInLong(); _globals.iRegul = 1; for (int cpt = 0; cpt <= 249; cpt++) - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); _globals._introSpeechOffFl = true; _talkManager.startAnimatedCharacterDialogue("SVGARD1.pe2"); _globals._introSpeechOffFl = false; for (int cpt = 0; cpt <= 49; cpt++) - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); _graphicsManager.fadeOutLong(); _graphicsManager.endDisplayBob(); - _globals._saveData->_data[svField312] = 1; + _globals._saveData->_data[svBaseFireFl] = 1; _globals._disableInventFl = false; } -void HopkinsEngine::BASE() { +void HopkinsEngine::playSubmarineCutscene() { _globals.iRegul = 1; _graphicsManager._lineNbr = SCREEN_WIDTH; _graphicsManager.lockScreen(); @@ -2012,7 +2000,7 @@ void HopkinsEngine::BASE() { _globals._exitId = 85; } -void HopkinsEngine::BASED() { +void HopkinsEngine::playUnderwaterBaseCutscene() { _graphicsManager.lockScreen(); _graphicsManager.clearScreen(); _graphicsManager.unlockScreen(); @@ -2031,13 +2019,13 @@ void HopkinsEngine::BASED() { _objectsManager.loadLinkFile("IM92"); for (int cpt = 0; cpt <= 4; cpt++) - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); _graphicsManager.fadeInLong(); _globals.enableHiding(); do - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); while (_objectsManager.getBobAnimDataIdx(8) != 22); _graphicsManager.fadeOutLong(); @@ -2074,13 +2062,13 @@ void HopkinsEngine::playEnding() { _eventsManager.changeMouseCursor(0); for (int cpt = 0; cpt <= 4; cpt++) - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); _graphicsManager.fadeInLong(); _globals.iRegul = 1; do - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); while (_objectsManager.getBobAnimDataIdx(6) != 54); _globals._introSpeechOffFl = true; @@ -2092,13 +2080,13 @@ void HopkinsEngine::playEnding() { _objectsManager.setBobAnimation(7); do - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); while (_objectsManager.getBobAnimDataIdx(7) != 54); _soundManager.playSample(1); do - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); while (_objectsManager.getBobAnimDataIdx(7) != 65); _globals._introSpeechOffFl = true; @@ -2107,25 +2095,25 @@ void HopkinsEngine::playEnding() { _globals._disableInventFl = true; do - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); while (_objectsManager.getBobAnimDataIdx(7) != 72); _globals._introSpeechOffFl = true; _talkManager.startAnimatedCharacterDialogue("DUELH1.PE2"); do - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); while (_objectsManager.getBobAnimDataIdx(7) != 81); _globals._introSpeechOffFl = true; _talkManager.startAnimatedCharacterDialogue("DUELB5.PE2"); do - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); while (_objectsManager.getBobAnimDataIdx(7) != 120); _objectsManager.stopBobAnimation(7); - if (_globals._saveData->_data[svField135] == 1) { + if (_globals._saveData->_data[svGameWonFl] == 1) { _soundManager._specialSoundNum = 200; _soundManager._skipRefreshFl = true; _graphicsManager.FADE_LINUX = 2; @@ -2173,13 +2161,13 @@ void HopkinsEngine::playEnding() { _globals._disableInventFl = true; do - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); while (_objectsManager.getBobAnimDataIdx(8) != 5); _soundManager.directPlayWav("SOUND41.WAV"); do - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); while (_objectsManager.getBobAnimDataIdx(8) != 21); _graphicsManager.fadeOutLong(); @@ -2199,7 +2187,7 @@ void HopkinsEngine::playEnding() { _globals.iRegul = 0; } -void HopkinsEngine::displayPlane() { +void HopkinsEngine::playPlaneCutscene() { _soundManager.playSound(28); _globals.iRegul = 1; _graphicsManager.lockScreen(); @@ -2339,7 +2327,7 @@ int HopkinsEngine::handleBaseMap() { _eventsManager.changeMouseCursor(0); _graphicsManager.SETCOLOR4(251, 100, 100, 100); } - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); if ((mouseButton == 1) && zone) loopCond = true; } while (!loopCond); @@ -2507,10 +2495,10 @@ void HopkinsEngine::displayCredits() { } --_globals._creditsPosY; if (_globals._creditsStartX != -1 || _globals._creditsEndX != -1 || _globals._creditsStartY != -1 || _globals._creditsEndY != -1) { - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); _graphicsManager.copySurface(_graphicsManager._vesaScreen, 60, 50, 520, 380, _graphicsManager._vesaBuffer, 60, 50); } else { - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); } if (_globals._creditsItem[_globals._creditsLineNumb - 1]._linePosY <= 39) { _globals._creditsPosY = 440; @@ -2546,13 +2534,13 @@ void HopkinsEngine::handleOceanMouseEvents() { case 1: switch (_globals._oceanDirection) { case DIR_UP: - _objectsManager.SPACTION(_globals.PERSO, "27,26,25,24,23,22,21,20,19,18,-1,", 0, 0, 6, false); + _objectsManager.SPACTION(_globals.PERSO, "27,26,25,24,23,22,21,20,19,18,-1,", 6, false); break; case DIR_RIGHT: - _objectsManager.SPACTION(_globals.PERSO, "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,-1,", 0, 0, 6, false); + _objectsManager.SPACTION(_globals.PERSO, "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,-1,", 6, false); break; case DIR_DOWN: - _objectsManager.SPACTION(_globals.PERSO, "9,10,11,12,13,14,15,16,17,18,-1,", 0, 0, 6, false); + _objectsManager.SPACTION(_globals.PERSO, "9,10,11,12,13,14,15,16,17,18,-1,", 6, false); break; default: break; @@ -2570,7 +2558,7 @@ void HopkinsEngine::handleOceanMouseEvents() { oldX -= 6; _objectsManager.setSpriteX(0, oldX); setSubmarineSprites(); - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); if (_eventsManager.getMouseButton() == 1 && oldPosX == _eventsManager.getMouseX() && _eventsManager.getMouseY() == oldPosY) { displAnim = true; break; @@ -2583,13 +2571,13 @@ void HopkinsEngine::handleOceanMouseEvents() { case 2: switch (_globals._oceanDirection) { case DIR_UP: - _objectsManager.SPACTION(_globals.PERSO, "27,28,29,30,31,32,33,34,35,36,-1,", 0, 0, 6, false); + _objectsManager.SPACTION(_globals.PERSO, "27,28,29,30,31,32,33,34,35,36,-1,", 6, false); break; case DIR_DOWN: - _objectsManager.SPACTION(_globals.PERSO, "9,8,7,6,5,4,3,2,1,0,-1,", 0, 0, 6, false); + _objectsManager.SPACTION(_globals.PERSO, "9,8,7,6,5,4,3,2,1,0,-1,", 6, false); break; case DIR_LEFT: - _objectsManager.SPACTION(_globals.PERSO, "18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,-1,", 0, 0, 6, false); + _objectsManager.SPACTION(_globals.PERSO, "18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,-1,", 6, false); break; default: break; @@ -2606,7 +2594,7 @@ void HopkinsEngine::handleOceanMouseEvents() { oldX += 6; _objectsManager.setSpriteX(0, oldX); setSubmarineSprites(); - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); if (_eventsManager.getMouseButton() == 1 && oldPosX == _eventsManager.getMouseX() && _eventsManager.getMouseY() == oldPosY) { displAnim = true; break; @@ -2628,17 +2616,17 @@ void HopkinsEngine::handleOceanMouseEvents() { oldX += 6; _objectsManager.setSpriteX(0, oldX); setSubmarineSprites(); - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); if (_eventsManager.getMouseButton() == 1 && oldPosX == _eventsManager.getMouseX() && _eventsManager.getMouseY() == oldPosY) { displAnim = true; break; } } while (oldX <= 235); if (!displAnim) - _objectsManager.SPACTION(_globals.PERSO, "36,35,34,33,32,31,30,29,28,27,-1,", 0, 0, 6, false); + _objectsManager.SPACTION(_globals.PERSO, "36,35,34,33,32,31,30,29,28,27,-1,", 6, false); break; case DIR_DOWN: - _objectsManager.SPACTION(_globals.PERSO, "9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,-1,", 0, 0, 6, false); + _objectsManager.SPACTION(_globals.PERSO, "9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,-1,", 6, false); break; case DIR_LEFT: oldX = _objectsManager.getSpriteX(0); @@ -2651,14 +2639,14 @@ void HopkinsEngine::handleOceanMouseEvents() { oldX -= 6; _objectsManager.setSpriteX(0, oldX); setSubmarineSprites(); - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); if (_eventsManager.getMouseButton() == 1 && oldPosX == _eventsManager.getMouseX() && _eventsManager.getMouseY() == oldPosY) { displAnim = true; break; } } while (oldX > 236); if (!displAnim) - _objectsManager.SPACTION(_globals.PERSO, "18,19,20,21,22,23,24,25,26,27,-1,", 0, 0, 6, false); + _objectsManager.SPACTION(_globals.PERSO, "18,19,20,21,22,23,24,25,26,27,-1,", 6, false); break; default: break; @@ -2669,7 +2657,7 @@ void HopkinsEngine::handleOceanMouseEvents() { case 4: switch (_globals._oceanDirection) { case DIR_UP: - _objectsManager.SPACTION(_globals.PERSO, "27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,-1,", 0, 0, 6, false); + _objectsManager.SPACTION(_globals.PERSO, "27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,-1,", 6, false); break; case DIR_RIGHT: oldX = _objectsManager.getSpriteX(0); @@ -2682,14 +2670,14 @@ void HopkinsEngine::handleOceanMouseEvents() { oldX += 6; _objectsManager.setSpriteX(0, oldX); setSubmarineSprites(); - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); if (_eventsManager.getMouseButton() == 1 && oldPosX == _eventsManager.getMouseX() && _eventsManager.getMouseY() == oldPosY) { displAnim = true; break; } } while (oldX <= 235); if (!displAnim) - _objectsManager.SPACTION(_globals.PERSO, "0,1,2,3,4,5,6,7,8,9,-1,", 0, 0, 6, false); + _objectsManager.SPACTION(_globals.PERSO, "0,1,2,3,4,5,6,7,8,9,-1,", 6, false); break; case DIR_LEFT: oldX = _objectsManager.getSpriteX(0); @@ -2702,13 +2690,13 @@ void HopkinsEngine::handleOceanMouseEvents() { oldX -= 6; _objectsManager.setSpriteX(0, oldX); setSubmarineSprites(); - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); if (_eventsManager.getMouseButton() == 1 && oldPosX == _eventsManager.getMouseX() && _eventsManager.getMouseY() == oldPosY) break; if (oldX <= 236) { if (!displAnim) - _objectsManager.SPACTION(_globals.PERSO, "18,17,16,15,14,13,12,11,10,9,-1,", 0, 0, 6, false); + _objectsManager.SPACTION(_globals.PERSO, "18,17,16,15,14,13,12,11,10,9,-1,", 6, false); break; } } @@ -2805,7 +2793,7 @@ void HopkinsEngine::handleOceanMaze(int16 curExitId, Common::String backgroundFi _eventsManager.changeMouseCursor(4); for (int cpt = 0; cpt <= 4; cpt++) - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); if (!_graphicsManager._noFadingFl) _graphicsManager.fadeInLong(); @@ -2818,7 +2806,8 @@ void HopkinsEngine::handleOceanMaze(int16 curExitId, Common::String backgroundFi handleOceanMouseEvents(); _linesManager.checkZone(); setSubmarineSprites(); - _eventsManager.VBL(); + + _eventsManager.refreshScreenAndEvents(); if (_globals._exitId || shouldQuit()) break; } @@ -2874,7 +2863,7 @@ bool HopkinsEngine::displayAdultDisclaimer() { else if (xp >= 424 && xp <= 602 && yp >= 406 && yp <= 445) buttonIndex = 1; - _eventsManager.VBL(); + _eventsManager.refreshScreenAndEvents(); } while (!shouldQuit() && (buttonIndex == 0 || _eventsManager.getMouseButton() != 1)); _globals._disableInventFl = false; diff --git a/engines/hopkins/hopkins.h b/engines/hopkins/hopkins.h index 324d36bbea..3b215ba30e 100644 --- a/engines/hopkins/hopkins.h +++ b/engines/hopkins/hopkins.h @@ -99,10 +99,10 @@ private: void displayEndDemo(); void bombExplosion(); void handleConflagration(); - void BASE(); - void BASED(); + void playSubmarineCutscene(); + void playUnderwaterBaseCutscene(); + void playPlaneCutscene(); void playEnding(); - void displayPlane(); /** * Displays the map screen in the underground base. diff --git a/engines/hopkins/lines.cpp b/engines/hopkins/lines.cpp index ebf48a7d21..e23c53ff18 100644 --- a/engines/hopkins/lines.cpp +++ b/engines/hopkins/lines.cpp @@ -84,9 +84,9 @@ LinesManager::LinesManager() { _lastLine = 0; _maxLineIdx = 0; _pathFindingMaxDepth = 0; - essai0 = NULL; - essai1 = NULL; - essai2 = NULL; + _testRoute0 = NULL; + _testRoute1 = NULL; + _testRoute2 = NULL; _lineBuf = (int16 *)g_PTRNUL; _route = (RouteItem *)g_PTRNUL; _currentSegmentId = 0; @@ -188,49 +188,49 @@ int LinesManager::checkInventoryHotspotsRow(int posX, int minZoneNum, bool lastR /** * Add Zone Line */ -void LinesManager::addZoneLine(int idx, int a2, int a3, int a4, int a5, int bobZoneIdx) { +void LinesManager::addZoneLine(int idx, int fromX, int fromY, int destX, int destY, int bobZoneIdx) { int16 *zoneData; - if (a2 == a3 && a3 == a4 && a3 == a5) { + if (fromX == fromY && fromY == destX && fromY == destY) { BOBZONE_FLAG[bobZoneIdx] = true; - BOBZONE[bobZoneIdx] = a3; + BOBZONE[bobZoneIdx] = fromY; } else { assert (idx <= MAX_LINES); _zoneLine[idx]._zoneData = (int16 *)_vm->_globals.freeMemory((byte *)_zoneLine[idx]._zoneData); - int v8 = abs(a2 - a4); - int v9 = abs(a3 - a5); - int v20 = 1; - if (v8 <= v9) - v20 += v9; + int distX = abs(fromX - destX); + int distY = abs(fromY - destY); + int maxDist = 1; + if (distX <= distY) + maxDist += distY; else - v20 += v8; + maxDist += distX; - zoneData = (int16 *)_vm->_globals.allocMemory(2 * sizeof(int16) * v20 + (4 * sizeof(int16))); + zoneData = (int16 *)_vm->_globals.allocMemory(2 * sizeof(int16) * maxDist + (4 * sizeof(int16))); assert(zoneData != (int16 *)g_PTRNUL); _zoneLine[idx]._zoneData = zoneData; int16 *dataP = zoneData; - int v23 = 1000 * v8 / v20; - int v22 = 1000 * v9 / v20; - if (a4 < a2) - v23 = -v23; - if (a5 < a3) - v22 = -v22; - int v13 = 1000 * a2; - int v16 = 1000 * a3; - for (int i = 0; i < v20; i++) { - *dataP++ = v13 / 1000; - *dataP++ = v16 / 1000; - - v13 += v23; - v16 += v22; + int stepX = 1000 * distX / maxDist; + int stepY = 1000 * distY / maxDist; + if (destX < fromX) + stepX = -stepX; + if (destY < fromY) + stepY = -stepY; + int smoothPosX = 1000 * fromX; + int smoothPosY = 1000 * fromY; + for (int i = 0; i < maxDist; i++) { + *dataP++ = smoothPosX / 1000; + *dataP++ = smoothPosY / 1000; + + smoothPosX += stepX; + smoothPosY += stepY; } *dataP++ = -1; *dataP++ = -1; - _zoneLine[idx]._count = v20; + _zoneLine[idx]._count = maxDist; _zoneLine[idx]._bobZoneIdx = bobZoneIdx; } } @@ -238,122 +238,113 @@ void LinesManager::addZoneLine(int idx, int a2, int a3, int a4, int a5, int bobZ /** * Add Line */ -void LinesManager::addLine(int idx, Directions direction, int a3, int a4, int a5, int a6) { - assert (idx <= MAX_LINES); +void LinesManager::addLine(int lineIdx, Directions direction, int fromX, int fromY, int destX, int destY) { + assert (lineIdx <= MAX_LINES); - if (_linesNumb < idx) - _linesNumb = idx; + if (_linesNumb < lineIdx) + _linesNumb = lineIdx; - _lineItem[idx]._lineData = (int16 *)_vm->_globals.freeMemory((byte *)_lineItem[idx]._lineData); - int v8 = abs(a3 - a5) + 1; - int v34 = abs(a4 - a6) + 1; - int v33 = v34; - if (v8 > v34) - v34 = v8; - - byte *v10 = _vm->_globals.allocMemory(4 * v34 + 8); - assert (v10 != g_PTRNUL); - - Common::fill(v10, v10 + 4 * v34 + 8, 0); - _lineItem[idx]._lineData = (int16 *)v10; - - int16 *v32 = _lineItem[idx]._lineData; - int v36 = 1000 * v8; - int v39 = 1000 * v8 / (v34 - 1); - int v37 = 1000 * v33 / (v34 - 1); - if (a5 < a3) - v39 = -v39; - if (a6 < a4) - v37 = -v37; - int v11 = (int)v39 / 1000; - int v12 = (int)v37 / 1000; - if (!v11) { - if (v12 == -1) { - _lineItem[idx]._directionRouteInc = DIR_UP; - _lineItem[idx]._directionRouteDec = DIR_DOWN; - } - if (v12 == 1) { - _lineItem[idx]._directionRouteInc = DIR_DOWN; - _lineItem[idx]._directionRouteDec = DIR_UP; - } - } - if (v11 == 1) { - if (v12 == -1) { - _lineItem[idx]._directionRouteInc = DIR_UP_RIGHT; - _lineItem[idx]._directionRouteDec = DIR_DOWN_LEFT; - } - if (!v12) { - _lineItem[idx]._directionRouteInc = DIR_RIGHT; - _lineItem[idx]._directionRouteDec = DIR_LEFT; - } - if (v12 == 1) { - _lineItem[idx]._directionRouteInc = DIR_DOWN_RIGHT; - _lineItem[idx]._directionRouteDec = DIR_UP_LEFT; - } - } - if (v11 == -1) { - if (v12 == 1) { - _lineItem[idx]._directionRouteInc = DIR_DOWN_LEFT; - _lineItem[idx]._directionRouteDec = DIR_UP_RIGHT; - } - if (!v12) { - _lineItem[idx]._directionRouteInc = DIR_LEFT; - _lineItem[idx]._directionRouteDec = DIR_RIGHT; - } - if (v12 == -1) { - _lineItem[idx]._directionRouteInc = DIR_UP_LEFT; - _lineItem[idx]._directionRouteDec = DIR_DOWN_RIGHT; - } - } - if (v11 == 1 && v37 > 250 && v37 <= 999) { - _lineItem[idx]._directionRouteInc = DIR_DOWN_RIGHT; - _lineItem[idx]._directionRouteDec = DIR_UP_LEFT; - } - if (v11 == -1 && v37 > 250 && v37 <= 999) { - _lineItem[idx]._directionRouteInc = DIR_DOWN_LEFT; - _lineItem[idx]._directionRouteDec = DIR_UP_RIGHT; - } - if (v11 == 1 && v37 < -250 && v37 > -1000) { - _lineItem[idx]._directionRouteInc = DIR_UP_RIGHT; - _lineItem[idx]._directionRouteDec = DIR_DOWN_LEFT; - } - // This condition is impossible to meet! - // Code present in the Linux and BeOS executables - // CHECKME: maybe it should be checking negative values? - if (v11 == -1 && v37 <= 249 && v37 > 1000) { - _lineItem[idx]._directionRouteInc = DIR_UP_LEFT; - _lineItem[idx]._directionRouteDec = DIR_DOWN_RIGHT; - } - int v40 = v36 / v34; - int v38 = 1000 * v33 / v34; - if (a5 < a3) - v40 = -v40; - if (a6 < a4) - v38 = -v38; - int v24 = 1000 * a3; - int v25 = 1000 * a4; - int v31 = 1000 * a3 / 1000; - int v30 = 1000 * a4 / 1000; - int v35 = v34 - 1; - for (int v26 = 0; v26 < v35; v26++) { - v32[0] = v31; - v32[1] = v30; - v32 += 2; - - v24 += v40; - v25 += v38; - v31 = v24 / 1000; - v30 = v25 / 1000; - } - v32[0] = a5; - v32[1] = a6; - - v32 += 2; - v32[0] = -1; - v32[1] = -1; - - _lineItem[idx]._lineDataEndIdx = v35 + 1; - _lineItem[idx]._direction = direction; + _lineItem[lineIdx]._lineData = (int16 *)_vm->_globals.freeMemory((byte *)_lineItem[lineIdx]._lineData); + int distX = abs(fromX - destX) + 1; + int distY = abs(fromY - destY) + 1; + int maxDist = distY; + if (distX > maxDist) + maxDist = distX; + + byte *zoneData = _vm->_globals.allocMemory(4 * maxDist + 8); + assert (zoneData != g_PTRNUL); + + Common::fill(zoneData, zoneData + 4 * maxDist + 8, 0); + _lineItem[lineIdx]._lineData = (int16 *)zoneData; + + int16 *curLineData = _lineItem[lineIdx]._lineData; + int stepX = 1000 * distX / (maxDist - 1); + int stepY = 1000 * distY / (maxDist - 1); + if (destX < fromX) + stepX = -stepX; + if (destY < fromY) + stepY = -stepY; + int dirX = (int)stepX / 1000; // -1: Left, 0: None, 1: Right + int dirY = (int)stepY / 1000; // -1: Up, 0: None, 1: Right + if (!dirX) { + if (dirY == -1) { + _lineItem[lineIdx]._directionRouteInc = DIR_UP; + _lineItem[lineIdx]._directionRouteDec = DIR_DOWN; + } else if (dirY == 1) { + _lineItem[lineIdx]._directionRouteInc = DIR_DOWN; + _lineItem[lineIdx]._directionRouteDec = DIR_UP; + } + // If dirY == 0, no move + } else if (dirX == 1) { + if (dirY == -1) { + _lineItem[lineIdx]._directionRouteInc = DIR_UP_RIGHT; + _lineItem[lineIdx]._directionRouteDec = DIR_DOWN_LEFT; + } else if (!dirY) { + _lineItem[lineIdx]._directionRouteInc = DIR_RIGHT; + _lineItem[lineIdx]._directionRouteDec = DIR_LEFT; + } else if (dirY == 1) { + _lineItem[lineIdx]._directionRouteInc = DIR_DOWN_RIGHT; + _lineItem[lineIdx]._directionRouteDec = DIR_UP_LEFT; + } + } else if (dirX == -1) { + if (dirY == 1) { + _lineItem[lineIdx]._directionRouteInc = DIR_DOWN_LEFT; + _lineItem[lineIdx]._directionRouteDec = DIR_UP_RIGHT; + } else if (!dirY) { + _lineItem[lineIdx]._directionRouteInc = DIR_LEFT; + _lineItem[lineIdx]._directionRouteDec = DIR_RIGHT; + } else if (dirY == -1) { + _lineItem[lineIdx]._directionRouteInc = DIR_UP_LEFT; + _lineItem[lineIdx]._directionRouteDec = DIR_DOWN_RIGHT; + } + } + + // Second pass to soften cases where dirY == 0 + if (dirX == 1) { + if (stepY > 250 && stepY <= 999) { + _lineItem[lineIdx]._directionRouteInc = DIR_DOWN_RIGHT; + _lineItem[lineIdx]._directionRouteDec = DIR_UP_LEFT; + } else if (stepY < -250 && stepY > -1000) { + _lineItem[lineIdx]._directionRouteInc = DIR_UP_RIGHT; + _lineItem[lineIdx]._directionRouteDec = DIR_DOWN_LEFT; + } + } else if (dirX == -1) { + if (stepY > 250 && stepY <= 999) { + _lineItem[lineIdx]._directionRouteInc = DIR_DOWN_LEFT; + _lineItem[lineIdx]._directionRouteDec = DIR_UP_RIGHT; + } else if (stepY < -250 && stepY > -1000) { + // In the original code, the test was on positive values and + // was impossible to meet. + _lineItem[lineIdx]._directionRouteInc = DIR_UP_LEFT; + _lineItem[lineIdx]._directionRouteDec = DIR_DOWN_RIGHT; + } + } + + stepX = 1000 * distX / maxDist; + stepY = 1000 * distY / maxDist; + if (destX < fromX) + stepX = -stepX; + if (destY < fromY) + stepY = -stepY; + int smoothPosX = 1000 * fromX; + int smoothPosY = 1000 * fromY; + for (int i = 0; i < maxDist - 1; i++) { + curLineData[0] = smoothPosX / 1000; + curLineData[1] = smoothPosY / 1000; + curLineData += 2; + + smoothPosX += stepX; + smoothPosY += stepY; + } + curLineData[0] = destX; + curLineData[1] = destY; + + curLineData += 2; + curLineData[0] = -1; + curLineData[1] = -1; + + _lineItem[lineIdx]._lineDataEndIdx = maxDist; + _lineItem[lineIdx]._direction = direction; ++_linesNumb; } @@ -454,98 +445,98 @@ void LinesManager::initRoute() { } // Avoid -int LinesManager::CONTOURNE(int a1, int a2, int a3, int a4, int a5, RouteItem *route) { - int v36 = a1; - int v7 = a2; - int v8 = a3; - if (a1 < a4) { - v8 = _lineItem[a1].appendToRouteInc(a2, -1, route, v8); - - for (int i = a1 + 1; i < a4; i++) - v8 = _lineItem[i].appendToRouteInc(0, -1, route, v8); - - v7 = 0; - v36 = a4; - } - if (v36 > a4) { - v8 = _lineItem[v36].appendToRouteDec(v7, 0, route, v8); - for (int i = v36 - 1; i > a4; i--) - v8 = _lineItem[i].appendToRouteDec(-1, 0, route, v8); - v7 = _lineItem[a4]._lineDataEndIdx - 1; - v36 = a4; - } - if (v36 == a4) { - if (a5 >= v7) { - v8 = _lineItem[a4].appendToRouteInc(v7, a5, route, v8); +int LinesManager::CONTOURNE(int lineIdx, int lineDataIdx, int routeIdx, int destLineIdx, int destLineDataIdx, RouteItem *route) { + int curLineIdx = lineIdx; + int curLineDataIdx = lineDataIdx; + int curRouteIdx = routeIdx; + if (lineIdx < destLineIdx) { + curRouteIdx = _lineItem[lineIdx].appendToRouteInc(lineDataIdx, -1, route, curRouteIdx); + + for (int i = lineIdx + 1; i < destLineIdx; i++) + curRouteIdx = _lineItem[i].appendToRouteInc(0, -1, route, curRouteIdx); + + curLineDataIdx = 0; + curLineIdx = destLineIdx; + } + if (curLineIdx > destLineIdx) { + curRouteIdx = _lineItem[curLineIdx].appendToRouteDec(curLineDataIdx, 0, route, curRouteIdx); + for (int i = curLineIdx - 1; i > destLineIdx; i--) + curRouteIdx = _lineItem[i].appendToRouteDec(-1, 0, route, curRouteIdx); + curLineDataIdx = _lineItem[destLineIdx]._lineDataEndIdx - 1; + curLineIdx = destLineIdx; + } + if (curLineIdx == destLineIdx) { + if (destLineDataIdx >= curLineDataIdx) { + curRouteIdx = _lineItem[destLineIdx].appendToRouteInc(curLineDataIdx, destLineDataIdx, route, curRouteIdx); } else { - v8 = _lineItem[a4].appendToRouteDec(v7, a5, route, v8); + curRouteIdx = _lineItem[destLineIdx].appendToRouteDec(curLineDataIdx, destLineDataIdx, route, curRouteIdx); } } - return v8; + return curRouteIdx; } // Avoid 1 -int LinesManager::CONTOURNE1(int a1, int a2, int a3, int a4, int a5, RouteItem *route, int a8, int a9) { - int v9 = a1; - int v10 = a2; - int v40 = a3; - if (a4 < a1) { - v40 = _lineItem[a1].appendToRouteInc(a2, -1, route, v40); - int v15 = a1 + 1; - if (v15 == a9 + 1) - v15 = a8; - while (a4 != v15) { - v40 = _lineItem[v15].appendToRouteInc(0, -1, route, v40); - ++v15; - if (a9 + 1 == v15) - v15 = a8; - } - v10 = 0; - v9 = a4; - } - if (a4 > v9) { - v40 = _lineItem[v9].appendToRouteDec(v10, 0, route, v40); - int v24 = v9 - 1; - if (v24 == a8 - 1) - v24 = a9; - while (a4 != v24) { - v40 = _lineItem[v24].appendToRouteDec(-1, 0, route, v40); - --v24; - if (a8 - 1 == v24) - v24 = a9; - } - v10 = _lineItem[a4]._lineDataEndIdx - 1; - v9 = a4; - } - if (a4 == v9) { - if (a5 >= v10) { - v40 = _lineItem[a4].appendToRouteInc(v10, a5, route, v40); +int LinesManager::CONTOURNE1(int lineIdx, int lineDataIdx, int routeIdx, int destLineIdx, int destLineDataIdx, RouteItem *route, int a8, int a9) { + int curLineIdx = lineIdx; + int curLineDataIdx = lineDataIdx; + int curRouteIdx = routeIdx; + if (destLineIdx < lineIdx) { + curRouteIdx = _lineItem[lineIdx].appendToRouteInc(lineDataIdx, -1, route, curRouteIdx); + int wrkLineIdx = lineIdx + 1; + if (wrkLineIdx == a9 + 1) + wrkLineIdx = a8; + while (destLineIdx != wrkLineIdx) { + curRouteIdx = _lineItem[wrkLineIdx].appendToRouteInc(0, -1, route, curRouteIdx); + ++wrkLineIdx; + if (a9 + 1 == wrkLineIdx) + wrkLineIdx = a8; + } + curLineDataIdx = 0; + curLineIdx = destLineIdx; + } + if (destLineIdx > curLineIdx) { + curRouteIdx = _lineItem[curLineIdx].appendToRouteDec(curLineDataIdx, 0, route, curRouteIdx); + int wrkLineIdx = curLineIdx - 1; + if (wrkLineIdx == a8 - 1) + wrkLineIdx = a9; + while (destLineIdx != wrkLineIdx) { + curRouteIdx = _lineItem[wrkLineIdx].appendToRouteDec(-1, 0, route, curRouteIdx); + --wrkLineIdx; + if (a8 - 1 == wrkLineIdx) + wrkLineIdx = a9; + } + curLineDataIdx = _lineItem[destLineIdx]._lineDataEndIdx - 1; + curLineIdx = destLineIdx; + } + if (destLineIdx == curLineIdx) { + if (destLineDataIdx >= curLineDataIdx) { + curRouteIdx = _lineItem[destLineIdx].appendToRouteInc(curLineDataIdx, destLineDataIdx, route, curRouteIdx); } else { - v40 = _lineItem[a4].appendToRouteDec(v10, a5, route, v40); + curRouteIdx = _lineItem[destLineIdx].appendToRouteDec(curLineDataIdx, destLineDataIdx, route, curRouteIdx); } } - return v40; + return curRouteIdx; } -bool LinesManager::MIRACLE(int fromX, int fromY, int a3, int a4, int a5) { - int v35 = 0; - int v36 = 0; - int v42 = 0; - int v43 = 0; - int v44 = 0; - int v45 = 0; - int v46 = 0; - int v47 = 0; - int v48 = 0; - int v49 = 0; +bool LinesManager::MIRACLE(int fromX, int fromY, int lineIdx, int destLineIdx, int routeIdx) { + int newLinesDataIdx = 0; + int newLinesIdx = 0; + int lineIdxLeft = 0; + int lineDataIdxLeft = 0; + int lineIdxRight = 0; + int lineDataIdxRight = 0; + int linesIdxUp = 0; + int linesDataIdxUp = 0; + int lineIdxDown = 0; + int lineDataIdxDown = 0; int curX = fromX; int curY = fromY; - int v50 = a3; - int v7 = a5; - int v51; - if (checkCollisionLine(fromX, fromY, &v51, &v50, 0, _linesNumb)) { - switch (_lineItem[v50]._direction) { + int curLineIdx = lineIdx; + int tmpRouteIdx = routeIdx; + int dummyDataIdx; + if (checkCollisionLine(fromX, fromY, &dummyDataIdx, &curLineIdx, 0, _linesNumb)) { + switch (_lineItem[curLineIdx]._direction) { case DIR_UP: curY -= 2; break; @@ -578,195 +569,187 @@ bool LinesManager::MIRACLE(int fromX, int fromY, int a3, int a4, int a5) { break; } } - int v41 = curX; - int v40 = curY; - int v9 = 0; - int v10 = v40; - for (int i = v40; v40 + 200 > v10; i = v10) { - if (checkCollisionLine(v41, i, &v49, &v48, 0, _lastLine) == 1 && v48 <= _lastLine) - break; - v49 = 0; - v48 = -1; - ++v9; - ++v10; - } - int v37 = v9; - int v12 = 0; - int v13 = v40; - for (int j = v40; v40 - 200 < v13; j = v13) { - if (checkCollisionLine(v41, j, &v47, &v46, 0, _lastLine) == 1 && v46 <= _lastLine) - break; - v47 = 0; - v46 = -1; - ++v12; - --v13; - } - int v39 = v12; - int v15 = 0; - int v16 = v41; - for (int k = v41; v41 + 200 > v16; k = v16) { - if (checkCollisionLine(k, v40, &v45, &v44, 0, _lastLine) == 1 && v44 <= _lastLine) - break; - v45 = 0; - v44 = -1; - ++v15; - ++v16; - } - int v38 = v15; - int v18 = 0; - int v19 = v41; - for (int l = v41; v41 - 200 < v19; l = v19) { - if (checkCollisionLine(l, v40, &v43, &v42, 0, _lastLine) == 1 && v42 <= _lastLine) - break; - v43 = 0; - v42 = -1; - ++v18; - --v19; - } - if (a4 > v50) { - if (v46 != -1 && v46 <= v50) - v46 = -1; - if (v44 != -1 && v50 >= v44) - v44 = -1; - if (v48 != -1 && v50 >= v48) - v48 = -1; - if (v42 != -1 && v50 >= v42) - v42 = -1; - if (v46 != -1 && a4 < v46) - v46 = -1; - if (v44 != -1 && a4 < v44) - v44 = -1; - if (v48 != -1 && a4 < v48) - v48 = -1; - if (v42 != -1 && a4 < v42) - v42 = -1; - } else if (a4 < v50) { - if (v46 != -1 && v46 >= v50) - v46 = -1; - if (v44 != -1 && v50 <= v44) - v44 = -1; - if (v48 != -1 && v50 <= v48) - v48 = -1; - if (v42 != -1 && v50 <= v42) - v42 = -1; - if (v46 != -1 && a4 > v46) - v46 = -1; - if (v44 != -1 && a4 > v44) - v44 = -1; - if (v48 != -1 && a4 > v48) - v48 = -1; - if (v42 != -1 && a4 > v42) - v42 = -1; - } - if (v46 != -1 || v44 != -1 || v48 != -1 || v42 != -1) { + + int stepVertIncCount = 0; + for (int i = curY; curY + 200 > i; i++) { + if (checkCollisionLine(curX, i, &lineDataIdxDown, &lineIdxDown, 0, _lastLine) == 1 && lineIdxDown <= _lastLine) + break; + lineDataIdxDown = 0; + lineIdxDown = -1; + ++stepVertIncCount; + } + + int stepVertDecCount = 0; + for (int i = curY; curY - 200 < i; i--) { + if (checkCollisionLine(curX, i, &linesDataIdxUp, &linesIdxUp, 0, _lastLine) == 1 && linesIdxUp <= _lastLine) + break; + linesDataIdxUp = 0; + linesIdxUp = -1; + ++stepVertDecCount; + } + + int stepHoriIncCount = 0; + for (int i = curX; curX + 200 > i; i++) { + if (checkCollisionLine(i, curY, &lineDataIdxRight, &lineIdxRight, 0, _lastLine) == 1 && lineIdxRight <= _lastLine) + break; + lineDataIdxRight = 0; + lineIdxRight = -1; + ++stepHoriIncCount; + } + + int stepHoriDecCount = 0; + for (int i = curX; curX - 200 < i; i--) { + if (checkCollisionLine(i, curY, &lineDataIdxLeft, &lineIdxLeft, 0, _lastLine) == 1 && lineIdxLeft <= _lastLine) + break; + lineDataIdxLeft = 0; + lineIdxLeft = -1; + ++stepHoriDecCount; + } + + if (destLineIdx > curLineIdx) { + if (linesIdxUp != -1 && linesIdxUp <= curLineIdx) + linesIdxUp = -1; + if (lineIdxRight != -1 && curLineIdx >= lineIdxRight) + lineIdxRight = -1; + if (lineIdxDown != -1 && curLineIdx >= lineIdxDown) + lineIdxDown = -1; + if (lineIdxLeft != -1 && curLineIdx >= lineIdxLeft) + lineIdxLeft = -1; + if (linesIdxUp != -1 && destLineIdx < linesIdxUp) + linesIdxUp = -1; + if (lineIdxRight != -1 && destLineIdx < lineIdxRight) + lineIdxRight = -1; + if (lineIdxDown != -1 && destLineIdx < lineIdxDown) + lineIdxDown = -1; + if (lineIdxLeft != -1 && destLineIdx < lineIdxLeft) + lineIdxLeft = -1; + } else if (destLineIdx < curLineIdx) { + if (linesIdxUp != -1 && linesIdxUp >= curLineIdx) + linesIdxUp = -1; + if (lineIdxRight != -1 && curLineIdx <= lineIdxRight) + lineIdxRight = -1; + if (lineIdxDown != -1 && curLineIdx <= lineIdxDown) + lineIdxDown = -1; + if (lineIdxLeft != -1 && curLineIdx <= lineIdxLeft) + lineIdxLeft = -1; + if (linesIdxUp != -1 && destLineIdx > linesIdxUp) + linesIdxUp = -1; + if (lineIdxRight != -1 && destLineIdx > lineIdxRight) + lineIdxRight = -1; + if (lineIdxDown != -1 && destLineIdx > lineIdxDown) + lineIdxDown = -1; + if (lineIdxLeft != -1 && destLineIdx > lineIdxLeft) + lineIdxLeft = -1; + } + if (linesIdxUp != -1 || lineIdxRight != -1 || lineIdxDown != -1 || lineIdxLeft != -1) { Directions newDir = DIR_NONE; - if (a4 > v50) { - if (v48 <= v46 && v44 <= v46 && v42 <= v46 && v46 > v50) + if (destLineIdx > curLineIdx) { + if (lineIdxDown <= linesIdxUp && lineIdxRight <= linesIdxUp && lineIdxLeft <= linesIdxUp && linesIdxUp > curLineIdx) newDir = DIR_UP; - if (v48 <= v44 && v46 <= v44 && v42 <= v44 && v50 < v44) + if (lineIdxDown <= lineIdxRight && linesIdxUp <= lineIdxRight && lineIdxLeft <= lineIdxRight && curLineIdx < lineIdxRight) newDir = DIR_RIGHT; - if (v46 <= v48 && v44 <= v48 && v42 <= v48 && v50 < v48) + if (linesIdxUp <= lineIdxDown && lineIdxRight <= lineIdxDown && lineIdxLeft <= lineIdxDown && curLineIdx < lineIdxDown) newDir = DIR_DOWN; - if (v48 <= v42 && v44 <= v42 && v46 <= v42 && v50 < v42) + if (lineIdxDown <= lineIdxLeft && lineIdxRight <= lineIdxLeft && linesIdxUp <= lineIdxLeft && curLineIdx < lineIdxLeft) newDir = DIR_LEFT; - } else if (a4 < v50) { - if (v46 == -1) - v46 = 1300; - if (v44 == -1) - v44 = 1300; - if (v48 == -1) - v48 = 1300; - if (v42 == -1) - v42 = 1300; - if (v46 != 1300 && v48 >= v46 && v44 >= v46 && v42 >= v46 && v46 < v50) + } else if (destLineIdx < curLineIdx) { + if (linesIdxUp == -1) + linesIdxUp = INVALID_LINE_VALUE; + if (lineIdxRight == -1) + lineIdxRight = INVALID_LINE_VALUE; + if (lineIdxDown == -1) + lineIdxDown = INVALID_LINE_VALUE; + if (lineIdxLeft == -1) + lineIdxLeft = INVALID_LINE_VALUE; + if (linesIdxUp != INVALID_LINE_VALUE && lineIdxDown >= linesIdxUp && lineIdxRight >= linesIdxUp && lineIdxLeft >= linesIdxUp && linesIdxUp < curLineIdx) newDir = DIR_UP; - if (v44 != 1300 && v48 >= v44 && v46 >= v44 && v42 >= v44 && v50 > v44) + if (lineIdxRight != INVALID_LINE_VALUE && lineIdxDown >= lineIdxRight && linesIdxUp >= lineIdxRight && lineIdxLeft >= lineIdxRight && curLineIdx > lineIdxRight) newDir = DIR_RIGHT; - if (v48 != 1300 && v46 >= v48 && v44 >= v48 && v42 >= v48 && v50 > v48) + if (lineIdxDown != INVALID_LINE_VALUE && linesIdxUp >= lineIdxDown && lineIdxRight >= lineIdxDown && lineIdxLeft >= lineIdxDown && curLineIdx > lineIdxDown) newDir = DIR_DOWN; - if (v42 != 1300 && v48 >= v42 && v44 >= v42 && v46 >= v42 && v50 > v42) + if (lineIdxLeft != INVALID_LINE_VALUE && lineIdxDown >= lineIdxLeft && lineIdxRight >= lineIdxLeft && linesIdxUp >= lineIdxLeft && curLineIdx > lineIdxLeft) newDir = DIR_LEFT; } switch(newDir) { case DIR_UP: - v36 = v46; - v35 = v47; - for (int v22 = 0; v22 < v39; v22++) { - if (checkCollisionLine(v41, v40 - v22, &v47, &v46, _lastLine + 1, _linesNumb) && _lastLine < v46) { - int v23 = GENIAL(v46, v47, v41, v40 - v22, v41, v40 - v39, v7, &_bestRoute[0]); - if (v23 == -1) + newLinesIdx = linesIdxUp; + newLinesDataIdx = linesDataIdxUp; + for (int i = 0; i < stepVertDecCount; i++) { + if (checkCollisionLine(curX, curY - i, &linesDataIdxUp, &linesIdxUp, _lastLine + 1, _linesNumb) && _lastLine < linesIdxUp) { + int tmpRouteIdxUp = GENIAL(linesIdxUp, linesDataIdxUp, curX, curY - i, curX, curY - stepVertDecCount, tmpRouteIdx, &_bestRoute[0]); + if (tmpRouteIdxUp == -1) return false; - v7 = v23; + tmpRouteIdx = tmpRouteIdxUp; if (_newPosY != -1) - v22 = _newPosY - v40; + i = _newPosY - curY; } - _bestRoute[v7].set(v41, v40 - v22, DIR_UP); - v7++; + _bestRoute[tmpRouteIdx].set(curX, curY - i, DIR_UP); + tmpRouteIdx++; } - _newLineIdx = v36; - _newLineDataIdx = v35; - _newRouteIdx = v7; + _newLineIdx = newLinesIdx; + _newLineDataIdx = newLinesDataIdx; + _newRouteIdx = tmpRouteIdx; return true; break; case DIR_RIGHT: - v36 = v44; - v35 = v45; - for (int v31 = 0; v31 < v38; v31++) { - if (checkCollisionLine(v31 + v41, v40, &v47, &v46, _lastLine + 1, _linesNumb) && _lastLine < v46) { - int v32 = GENIAL(v46, v47, v31 + v41, v40, v38 + v41, v40, v7, &_bestRoute[0]); - if (v32 == -1) + newLinesIdx = lineIdxRight; + newLinesDataIdx = lineDataIdxRight; + for (int i = 0; i < stepHoriIncCount; i++) { + if (checkCollisionLine(i + curX, curY, &linesDataIdxUp, &linesIdxUp, _lastLine + 1, _linesNumb) && _lastLine < linesIdxUp) { + int tmpRouteIdxRight = GENIAL(linesIdxUp, linesDataIdxUp, i + curX, curY, stepHoriIncCount + curX, curY, tmpRouteIdx, &_bestRoute[0]); + if (tmpRouteIdxRight == -1) return false; - v7 = v32; + tmpRouteIdx = tmpRouteIdxRight; if (_newPosX != -1) - v31 = _newPosX - v41; + i = _newPosX - curX; } - _bestRoute[v7].set(v31 + v41, v40, DIR_RIGHT); - v7++; + _bestRoute[tmpRouteIdx].set(i + curX, curY, DIR_RIGHT); + tmpRouteIdx++; } - _newLineIdx = v36; - _newLineDataIdx = v35; - _newRouteIdx = v7; + _newLineIdx = newLinesIdx; + _newLineDataIdx = newLinesDataIdx; + _newRouteIdx = tmpRouteIdx; return true; break; case DIR_DOWN: - v36 = v48; - v35 = v49; - for (int v25 = 0; v25 < v37; v25++) { - if (checkCollisionLine(v41, v25 + v40, &v47, &v46, _lastLine + 1, _linesNumb) && _lastLine < v46) { - int v26 = GENIAL(v46, v47, v41, v25 + v40, v41, v37 + v40, v7, &_bestRoute[0]); - if (v26 == -1) + newLinesIdx = lineIdxDown; + newLinesDataIdx = lineDataIdxDown; + for (int i = 0; i < stepVertIncCount; i++) { + if (checkCollisionLine(curX, i + curY, &linesDataIdxUp, &linesIdxUp, _lastLine + 1, _linesNumb) && _lastLine < linesIdxUp) { + int tmpRouteIdxDown = GENIAL(linesIdxUp, linesDataIdxUp, curX, i + curY, curX, stepVertIncCount + curY, tmpRouteIdx, &_bestRoute[0]); + if (tmpRouteIdxDown == -1) return false; - v7 = v26; + tmpRouteIdx = tmpRouteIdxDown; if (_newPosY != -1) - v25 = v40 - _newPosY; + i = curY - _newPosY; } - _bestRoute[v7].set(v41, v25 + v40, DIR_DOWN); - v7++; + _bestRoute[tmpRouteIdx].set(curX, i + curY, DIR_DOWN); + tmpRouteIdx++; } - _newLineIdx = v36; - _newLineDataIdx = v35; - _newRouteIdx = v7; + _newLineIdx = newLinesIdx; + _newLineDataIdx = newLinesDataIdx; + _newRouteIdx = tmpRouteIdx; return true; break; case DIR_LEFT: - v36 = v42; - v35 = v43; - for (int v28 = 0; v28 < v18; v28++) { - if (checkCollisionLine(v41 - v28, v40, &v47, &v46, _lastLine + 1, _linesNumb) && _lastLine < v46) { - int v29 = GENIAL(v46, v47, v41 - v28, v40, v41 - v18, v40, v7, &_bestRoute[0]); - if (v29 == -1) + newLinesIdx = lineIdxLeft; + newLinesDataIdx = lineDataIdxLeft; + for (int i = 0; i < stepHoriDecCount; i++) { + if (checkCollisionLine(curX - i, curY, &linesDataIdxUp, &linesIdxUp, _lastLine + 1, _linesNumb) && _lastLine < linesIdxUp) { + int tmpRouteIdxLeft = GENIAL(linesIdxUp, linesDataIdxUp, curX - i, curY, curX - stepHoriDecCount, curY, tmpRouteIdx, &_bestRoute[0]); + if (tmpRouteIdxLeft == -1) return false; - v7 = v29; + tmpRouteIdx = tmpRouteIdxLeft; if (_newPosX != -1) - v28 = v41 - _newPosX; + i = curX - _newPosX; } - _bestRoute[v7].set(v41 - v28, v40, DIR_LEFT); - v7++; + _bestRoute[tmpRouteIdx].set(curX - i, curY, DIR_LEFT); + tmpRouteIdx++; } - _newLineIdx = v36; - _newLineDataIdx = v35; - _newRouteIdx = v7; + _newLineIdx = newLinesIdx; + _newLineDataIdx = newLinesDataIdx; + _newRouteIdx = tmpRouteIdx; return true; break; default: @@ -776,35 +759,34 @@ bool LinesManager::MIRACLE(int fromX, int fromY, int a3, int a4, int a5) { return false; } -int LinesManager::GENIAL(int lineIdx, int dataIdx, int a3, int a4, int a5, int a6, int a7, RouteItem *route) { - int result = a7; +int LinesManager::GENIAL(int lineIdx, int dataIdx, int fromX, int fromY, int destX, int destY, int routerIdx, RouteItem *route) { + int result = routerIdx; int v80 = -1; ++_pathFindingMaxDepth; if (_pathFindingMaxDepth > 10) { warning("PathFinding - Max depth reached"); - route[a7].invalidate(); + route[routerIdx].invalidate(); return -1; } - int16 *v10 = _lineItem[lineIdx]._lineData; - int v98 = v10[0]; - int v97 = v10[1]; - int v92 = lineIdx; + int lineX = _lineItem[lineIdx]._lineData[0]; + int lineY = _lineItem[lineIdx]._lineData[1]; + int startLineIdx = lineIdx; - int v65; + int curLineDataEndIdx; bool loopCond = false; for (;;) { - int v86 = v92 - 1; - int v11 = 2 * _lineItem[v92 - 1]._lineDataEndIdx; + int v86 = startLineIdx - 1; + int v11 = 2 * _lineItem[startLineIdx - 1]._lineDataEndIdx; - int16 *v12 = _lineItem[v92 - 1]._lineData; - if (v12 == (int16 *)g_PTRNUL) + int16 *lineData = _lineItem[startLineIdx - 1]._lineData; + if (lineData == (int16 *)g_PTRNUL) break; - while (v12[v11 - 2] != v98 || v97 != v12[v11 - 1]) { + while (lineData[v11 - 2] != lineX || lineY != lineData[v11 - 1]) { --v86; if (_lastLine - 1 != v86) { v11 = 2 * _lineItem[v86]._lineDataEndIdx; - v12 = _lineItem[v86]._lineData; - if (v12 != (int16 *)g_PTRNUL) + lineData = _lineItem[v86]._lineData; + if (lineData != (int16 *)g_PTRNUL) continue; } loopCond = true; @@ -813,35 +795,33 @@ int LinesManager::GENIAL(int lineIdx, int dataIdx, int a3, int a4, int a5, int a if (loopCond) break; - v92 = v86; - v98 = v12[0]; - v97 = v12[1]; + startLineIdx = v86; + lineX = lineData[0]; + lineY = lineData[1]; } - int16 *v13 = _lineItem[lineIdx]._lineData; - int v95 = v13[2 * _lineItem[lineIdx]._lineDataEndIdx - 2]; - int v93 = v13[2 * _lineItem[lineIdx]._lineDataEndIdx - 1]; - int v91 = lineIdx; + int lastIdx = _lineItem[lineIdx]._lineDataEndIdx - 1; + int lastPosX = _lineItem[lineIdx]._lineData[(2 * lastIdx)]; + int lastPosY = _lineItem[lineIdx]._lineData[(2 * lastIdx) + 1]; + int endLineIdx = lineIdx; int foundLineIdx, foundDataIdx; loopCond = false; for (;;) { - int v87 = v91 + 1; - int v15 = 2 * _lineItem[v91 + 1]._lineDataEndIdx; - int16 *v16 = _lineItem[v91 + 1]._lineData; - if (v16 == (int16 *)g_PTRNUL) + int curLineIdx = endLineIdx + 1; + int nextLineDataEndIdx = 2 * _lineItem[curLineIdx]._lineDataEndIdx; + int16 *lineData = _lineItem[curLineIdx]._lineData; + if (lineData == (int16 *)g_PTRNUL) break; - int v17; for (;;) { - v65 = v15; - v17 = v16[v15 - 2]; - if (v16[0] == v95 && v93 == v16[1]) + curLineDataEndIdx = nextLineDataEndIdx; + if (lineData[0] == lastPosX && lastPosY == lineData[1]) break; - ++v87; - if (v87 != _linesNumb + 1) { - v15 = 2 * _lineItem[v87]._lineDataEndIdx; - v16 = _lineItem[v87]._lineData; - if (v16 != (int16 *)g_PTRNUL) + ++curLineIdx; + if (curLineIdx != _linesNumb + 1) { + nextLineDataEndIdx = 2 * _lineItem[curLineIdx]._lineDataEndIdx; + lineData = _lineItem[curLineIdx]._lineData; + if (lineData != (int16 *)g_PTRNUL) continue; } loopCond = true; @@ -850,189 +830,179 @@ int LinesManager::GENIAL(int lineIdx, int dataIdx, int a3, int a4, int a5, int a if (loopCond) break; - v91 = v87; - v95 = v17; - v93 = v16[v65 - 1]; - } - - int v58 = abs(a3 - a5) + 1; - int v85 = abs(a4 - a6) + 1; - int v20 = v85; - if (v58 > v20) - v85 = v58; - int v84 = 1000 * v58 / v85; - int v83 = 1000 * v20 / v85; - int v21 = 1000 * a3; - int v22 = 1000 * a4; - int v82 = a3; - int v81 = a4; - if (a5 < a3) - v84 = -v84; - if (a6 < a4) - v83 = -v83; - if (v85 > 800) - v85 = 800; + endLineIdx = curLineIdx; + lastPosX = lineData[curLineDataEndIdx - 2]; + lastPosY = lineData[curLineDataEndIdx - 1]; + } + + int distX = abs(fromX - destX) + 1; + int distY = abs(fromY - destY) + 1; + int maxDist = distY; + if (distX > distY) + maxDist = distX; + int stepX = 1000 * distX / maxDist; + int stepY = 1000 * distY / maxDist; + int smoothPosX = 1000 * fromX; + int smoothPosY = 1000 * fromY; + if (destX < fromX) + stepX = -stepX; + if (destY < fromY) + stepY = -stepY; + if (maxDist > 800) + maxDist = 800; Common::fill(&_lineBuf[0], &_lineBuf[1000], 0); int bugLigIdx = 0; - for (int v88 = 0; v88 < v85 + 1; v88++) { - _lineBuf[bugLigIdx] = v82; - _lineBuf[bugLigIdx + 1] = v81; - v21 += v84; - v22 += v83; - v82 = v21 / 1000; - v81 = v22 / 1000; + for (int i = 0; i < maxDist + 1; i++) { + _lineBuf[bugLigIdx] = smoothPosX / 1000; + _lineBuf[bugLigIdx + 1] = smoothPosY / 1000; + smoothPosX += stepX; + smoothPosY += stepY; bugLigIdx += 2; } bugLigIdx -= 2; int v77 = 0; - int v78 = 0; - int v79 = 0; - for (int v89 = v85 + 1; v89 > 0; v89--) { - if (checkCollisionLine(_lineBuf[bugLigIdx], _lineBuf[bugLigIdx + 1], &foundDataIdx, &foundLineIdx, v92, v91) && _lastLine < foundLineIdx) { + int bufX = 0; + int bufY = 0; + for (int v89 = maxDist + 1; v89 > 0; v89--) { + if (checkCollisionLine(_lineBuf[bugLigIdx], _lineBuf[bugLigIdx + 1], &foundDataIdx, &foundLineIdx, startLineIdx, endLineIdx) && _lastLine < foundLineIdx) { v80 = foundLineIdx; v77 = foundDataIdx; - v78 = _lineBuf[bugLigIdx]; - v79 = _lineBuf[bugLigIdx + 1]; + bufX = _lineBuf[bugLigIdx]; + bufY = _lineBuf[bugLigIdx + 1]; break; } bugLigIdx -= 2; } - int v66 = 0; - int v68 = 0; - int v70 = 0; - int v72 = 0; - for (int i = v92; i <= v91; ++i) { + int maxLineX = 0; + int minLineX = 0; + int maxLineY = 0; + int minLineY = 0; + for (int i = startLineIdx; i <= endLineIdx; ++i) { int16 *lineData = _lineItem[i]._lineData; if (lineData == (int16 *)g_PTRNUL) error("error in genial routine"); - if (i == v92) { - v72 = lineData[2 * _lineItem[i]._lineDataEndIdx - 1]; - if (lineData[1] <= lineData[2 * _lineItem[i]._lineDataEndIdx - 1]) - v72 = lineData[1]; - v70 = lineData[2 * _lineItem[i]._lineDataEndIdx - 1]; - if (lineData[1] >= lineData[2 * _lineItem[i]._lineDataEndIdx - 1]) - v70 = lineData[1]; - v68 = lineData[2 * _lineItem[i]._lineDataEndIdx - 2]; - if (lineData[0] <= lineData[2 * _lineItem[i]._lineDataEndIdx - 2]) - v68 = lineData[0]; - v66 = lineData[2 * _lineItem[i]._lineDataEndIdx - 2]; - if (lineData[0] >= lineData[2 * _lineItem[i]._lineDataEndIdx - 2]) - v66 = lineData[0]; + if (i == startLineIdx) { + minLineY = MIN(lineData[1], lineData[2 * _lineItem[i]._lineDataEndIdx - 1]); + maxLineY = MAX(lineData[1], lineData[2 * _lineItem[i]._lineDataEndIdx - 1]); + + minLineX = MIN(lineData[0], lineData[2 * _lineItem[i]._lineDataEndIdx - 2]); + maxLineX = MAX(lineData[0], lineData[2 * _lineItem[i]._lineDataEndIdx - 2]); } else { - if (lineData[1] < lineData[2 * _lineItem[i]._lineDataEndIdx - 1] && lineData[1] < v72) - v72 = lineData[1]; - if (lineData[2 * _lineItem[i]._lineDataEndIdx - 1] < lineData[1] && lineData[2 * _lineItem[i]._lineDataEndIdx - 1] < v72) - v72 = lineData[2 * _lineItem[i]._lineDataEndIdx - 1]; - if (lineData[1] > lineData[2 * _lineItem[i]._lineDataEndIdx - 1] && lineData[1] > v70) - v70 = lineData[1]; - if (lineData[2 * _lineItem[i]._lineDataEndIdx - 1] > lineData[1] && lineData[2 * _lineItem[i]._lineDataEndIdx - 1] > v70) - v70 = lineData[2 * _lineItem[i]._lineDataEndIdx - 1]; - if (lineData[0] < lineData[2 * _lineItem[i]._lineDataEndIdx - 2] && v68 > lineData[0]) - v68 = lineData[0]; - if (lineData[2 * _lineItem[i]._lineDataEndIdx - 2] < lineData[0] && v68 > lineData[2 * _lineItem[i]._lineDataEndIdx - 2]) - v68 = lineData[2 * _lineItem[i]._lineDataEndIdx - 2]; - if (lineData[0] > lineData[2 * _lineItem[i]._lineDataEndIdx - 2] && v66 < lineData[0]) - v66 = lineData[0]; - if (lineData[2 * _lineItem[i]._lineDataEndIdx - 2] > lineData[0] && v66 < lineData[2 * _lineItem[i]._lineDataEndIdx - 2]) - v66 = lineData[2 * _lineItem[i]._lineDataEndIdx - 2]; - } - } - int v69 = v68 - 2; - int v73 = v72 - 2; - int v67 = v66 + 2; - int v71 = v70 + 2; - if (a5 >= v69 && a5 <= v67 && a6 >= v73 && a6 <= v71) { - int v34 = a6; - int v76 = -1; + if (lineData[1] < lineData[2 * _lineItem[i]._lineDataEndIdx - 1] && lineData[1] < minLineY) + minLineY = lineData[1]; + if (lineData[2 * _lineItem[i]._lineDataEndIdx - 1] < lineData[1] && lineData[2 * _lineItem[i]._lineDataEndIdx - 1] < minLineY) + minLineY = lineData[2 * _lineItem[i]._lineDataEndIdx - 1]; + if (lineData[1] > lineData[2 * _lineItem[i]._lineDataEndIdx - 1] && lineData[1] > maxLineY) + maxLineY = lineData[1]; + if (lineData[2 * _lineItem[i]._lineDataEndIdx - 1] > lineData[1] && lineData[2 * _lineItem[i]._lineDataEndIdx - 1] > maxLineY) + maxLineY = lineData[2 * _lineItem[i]._lineDataEndIdx - 1]; + if (lineData[0] < lineData[2 * _lineItem[i]._lineDataEndIdx - 2] && minLineX > lineData[0]) + minLineX = lineData[0]; + if (lineData[2 * _lineItem[i]._lineDataEndIdx - 2] < lineData[0] && minLineX > lineData[2 * _lineItem[i]._lineDataEndIdx - 2]) + minLineX = lineData[2 * _lineItem[i]._lineDataEndIdx - 2]; + if (lineData[0] > lineData[2 * _lineItem[i]._lineDataEndIdx - 2] && maxLineX < lineData[0]) + maxLineX = lineData[0]; + if (lineData[2 * _lineItem[i]._lineDataEndIdx - 2] > lineData[0] && maxLineX < lineData[2 * _lineItem[i]._lineDataEndIdx - 2]) + maxLineX = lineData[2 * _lineItem[i]._lineDataEndIdx - 2]; + } + } + + minLineX -= 2; + minLineY -= 2; + maxLineX += 2; + maxLineY += 2; + if (destX >= minLineX && destX <= maxLineX && destY >= minLineY && destY <= maxLineY) { + int curY = destY; + int linesIdxUp = -1; for (;;) { - --v34; - if (!checkCollisionLine(a5, v34, &foundDataIdx, &foundLineIdx, v92, v91)) + --curY; + if (!checkCollisionLine(destX, curY, &foundDataIdx, &foundLineIdx, startLineIdx, endLineIdx)) break; - v76 = foundLineIdx; - if (!v34 || v73 > v34) + linesIdxUp = foundLineIdx; + if (!curY || minLineY > curY) break; } - int v35 = a6; - int v75 = -1; + curY = destY; + int lineIdxDown = -1; for (;;) { - ++v35; - if (!checkCollisionLine(a5, v35, &foundDataIdx, &foundLineIdx, v92, v91)) + ++curY; + if (!checkCollisionLine(destX, curY, &foundDataIdx, &foundLineIdx, startLineIdx, endLineIdx)) break; - v75 = foundLineIdx; - if (_vm->_globals._characterMaxPosY <= v35 || v71 <= v35) + lineIdxDown = foundLineIdx; + if (_vm->_globals._characterMaxPosY <= curY || maxLineY <= curY) break; } - int v36 = a5; - int v74 = -1; + int curX = destX; + int lineIdxRight = -1; for (;;) { - ++v36; - if (!checkCollisionLine(v36, a6, &foundDataIdx, &foundLineIdx, v92, v91)) + ++curX; + if (!checkCollisionLine(curX, destY, &foundDataIdx, &foundLineIdx, startLineIdx, endLineIdx)) break; - v74 = foundLineIdx; + lineIdxRight = foundLineIdx; - if (_vm->_graphicsManager._maxX <= v36 || v67 <= v36) + if (_vm->_graphicsManager._maxX <= curX || maxLineX <= curX) break; } - int v37 = a5; - int v38 = -1; + curX = destX; + int lineIdxLeft = -1; for(;;) { - --v37; - if (!checkCollisionLine(v37, a6, &foundDataIdx, &foundLineIdx, v92, v91)) + --curX; + if (!checkCollisionLine(curX, destY, &foundDataIdx, &foundLineIdx, startLineIdx, endLineIdx)) + break; + lineIdxLeft = foundLineIdx; + if (curX <= 0 || minLineX >= curX) break; - v38 = foundLineIdx; - if (v37 <= 0 || v69 >= v37) - break;; } - if (v74 != -1 && v38 != -1 && v76 != -1 && v75 != -1) { - route[a7].invalidate(); + if (lineIdxRight != -1 && lineIdxLeft != -1 && linesIdxUp != -1 && lineIdxDown != -1) { + route[routerIdx].invalidate(); return -1; } } - if (v78 < a3 - 1 || v78 > a3 + 1 || v79 < a4 - 1 || v79 > a4 + 1) { - _newPosX = v78; - _newPosY = v79; + if (bufX < fromX - 1 || bufX > fromX + 1 || bufY < fromY - 1 || bufY > fromY + 1) { + _newPosX = bufX; + _newPosY = bufY; if (lineIdx < v80) { int v43 = 0; int v42 = lineIdx; do { - if (v42 == v92 - 1) - v42 = v91; + if (v42 == startLineIdx - 1) + v42 = endLineIdx; ++v43; --v42; - if (v42 == v92 - 1) - v42 = v91; + if (v42 == startLineIdx - 1) + v42 = endLineIdx; } while (v80 != v42); if (abs(v80 - lineIdx) == v43) { if (dataIdx > abs(_lineItem[lineIdx]._lineDataEndIdx / 2)) { - result = CONTOURNE(lineIdx, dataIdx, a7, v80, v77, route); + result = CONTOURNE(lineIdx, dataIdx, routerIdx, v80, v77, route); } else { - result = CONTOURNE1(lineIdx, dataIdx, a7, v80, v77, route, v92, v91); + result = CONTOURNE1(lineIdx, dataIdx, routerIdx, v80, v77, route, startLineIdx, endLineIdx); } } if (abs(v80 - lineIdx) < v43) result = CONTOURNE(lineIdx, dataIdx, result, v80, v77, route); if (v43 < abs(v80 - lineIdx)) - result = CONTOURNE1(lineIdx, dataIdx, result, v80, v77, route, v92, v91); + result = CONTOURNE1(lineIdx, dataIdx, result, v80, v77, route, startLineIdx, endLineIdx); } if (lineIdx > v80) { int v45 = abs(lineIdx - v80); int v47 = lineIdx; int v48 = 0; do { - if (v47 == v91 + 1) - v47 = v92; + if (v47 == endLineIdx + 1) + v47 = startLineIdx; ++v48; ++v47; - if (v47 == v91 + 1) - v47 = v92; + if (v47 == endLineIdx + 1) + v47 = startLineIdx; } while (v80 != v47); if (v45 == v48) { if (dataIdx > abs(_lineItem[lineIdx]._lineDataEndIdx / 2)) { - result = CONTOURNE1(lineIdx, dataIdx, result, v80, v77, route, v92, v91); + result = CONTOURNE1(lineIdx, dataIdx, result, v80, v77, route, startLineIdx, endLineIdx); } else { result = CONTOURNE(lineIdx, dataIdx, result, v80, v77, route); } @@ -1040,7 +1010,7 @@ int LinesManager::GENIAL(int lineIdx, int dataIdx, int a3, int a4, int a5, int a if (v45 < v48) result = CONTOURNE(lineIdx, dataIdx, result, v80, v77, route); if (v48 < v45) - result = CONTOURNE1(lineIdx, dataIdx, result, v80, v77, route, v92, v91); + result = CONTOURNE1(lineIdx, dataIdx, result, v80, v77, route, startLineIdx, endLineIdx); } if (lineIdx == v80) result = CONTOURNE(lineIdx, dataIdx, result, lineIdx, v77, route); @@ -1094,8 +1064,8 @@ RouteItem *LinesManager::PARCOURS2(int fromX, int fromY, int destX, int destY) { int foundDataIdx; int curLineY = 0; int curLineX = 0; - int v126[9]; - int v131[9]; + int stepArr[9]; + int deltaArr[9]; int collLineDataIdxArr[9]; int collLineIdxArr[9]; @@ -1106,7 +1076,6 @@ RouteItem *LinesManager::PARCOURS2(int fromX, int fromY, int destX, int destY) { int lineIdx = 0; int lineDataIdx = 0; Directions newDir = DIR_NONE; - int v111 = 0; if (destY <= 24) clipDestY = 25; if (!_vm->_globals._checkDistanceFl) { @@ -1143,199 +1112,201 @@ RouteItem *LinesManager::PARCOURS2(int fromX, int fromY, int destX, int destY) { for (int i = 0; i <= 8; ++i) { collLineIdxArr[i] = -1; collLineDataIdxArr[i] = 0; - v131[i] = 1300; - v126[i] = 1300; + deltaArr[i] = INVALID_LINE_VALUE; + stepArr[i] = INVALID_LINE_VALUE; } if (characterRoute(fromX, fromY, clipDestX, clipDestY, -1, -1, 0) == 1) return _bestRoute; - int v14 = 0; - for (int tmpY = clipDestY; tmpY < _vm->_graphicsManager._maxY; tmpY++, v14++) { - if (checkCollisionLine(clipDestX, tmpY, &collLineDataIdxArr[5], &collLineIdxArr[5], 0, _lastLine) && collLineIdxArr[5] <= _lastLine) + int tmpDelta = 0; + for (int tmpY = clipDestY; tmpY < _vm->_graphicsManager._maxY; tmpY++, tmpDelta++) { + if (checkCollisionLine(clipDestX, tmpY, &collLineDataIdxArr[DIR_DOWN], &collLineIdxArr[DIR_DOWN], 0, _lastLine) && collLineIdxArr[DIR_DOWN] <= _lastLine) break; - collLineDataIdxArr[5] = 0; - collLineIdxArr[5] = -1; + collLineDataIdxArr[DIR_DOWN] = 0; + collLineIdxArr[DIR_DOWN] = -1; } - v131[5] = v14; + deltaArr[DIR_DOWN] = tmpDelta; - v14 = 0; - for (int tmpY = clipDestY; tmpY > _vm->_graphicsManager._minY; tmpY--, v14++) { - if (checkCollisionLine(clipDestX, tmpY, &collLineDataIdxArr[1], &collLineIdxArr[1], 0, _lastLine) && collLineIdxArr[1] <= _lastLine) + tmpDelta = 0; + for (int tmpY = clipDestY; tmpY > _vm->_graphicsManager._minY; tmpY--, tmpDelta++) { + if (checkCollisionLine(clipDestX, tmpY, &collLineDataIdxArr[DIR_UP], &collLineIdxArr[DIR_UP], 0, _lastLine) && collLineIdxArr[DIR_UP] <= _lastLine) break; - collLineDataIdxArr[1] = 0; - collLineIdxArr[1] = -1; - if (v131[5] < v14 && collLineIdxArr[5] != -1) + collLineDataIdxArr[DIR_UP] = 0; + collLineIdxArr[DIR_UP] = -1; + if (deltaArr[DIR_DOWN] < tmpDelta && collLineIdxArr[DIR_DOWN] != -1) break; } - v131[1] = v14; + deltaArr[DIR_UP] = tmpDelta; - v14 = 0; + tmpDelta = 0; for (int tmpX = clipDestX; tmpX < _vm->_graphicsManager._maxX; tmpX++) { - if (checkCollisionLine(tmpX, clipDestY, &collLineDataIdxArr[3], &collLineIdxArr[3], 0, _lastLine) && collLineIdxArr[3] <= _lastLine) + if (checkCollisionLine(tmpX, clipDestY, &collLineDataIdxArr[DIR_RIGHT], &collLineIdxArr[DIR_RIGHT], 0, _lastLine) && collLineIdxArr[DIR_RIGHT] <= _lastLine) break; - collLineDataIdxArr[3] = 0; - collLineIdxArr[3] = -1; - ++v14; - if (v131[1] < v14 && collLineIdxArr[1] != -1) + collLineDataIdxArr[DIR_RIGHT] = 0; + collLineIdxArr[DIR_RIGHT] = -1; + ++tmpDelta; + if (deltaArr[DIR_UP] < tmpDelta && collLineIdxArr[DIR_UP] != -1) break; - if (v131[5] < v14 && collLineIdxArr[5] != -1) + if (deltaArr[DIR_DOWN] < tmpDelta && collLineIdxArr[DIR_DOWN] != -1) break; } - v131[3] = v14; + deltaArr[DIR_RIGHT] = tmpDelta; - v14 = 0; + tmpDelta = 0; for (int tmpX = clipDestX; tmpX > _vm->_graphicsManager._minX; tmpX--) { - if (checkCollisionLine(tmpX, clipDestY, &collLineDataIdxArr[7], &collLineIdxArr[7], 0, _lastLine) && collLineIdxArr[7] <= _lastLine) - break; - collLineDataIdxArr[7] = 0; - collLineIdxArr[7] = -1; - ++v14; - if (v131[1] < v14 && collLineIdxArr[1] != -1) - break; - if (v131[5] < v14 && collLineIdxArr[5] != -1) - break; - if (v131[3] < v14 && collLineIdxArr[3] != -1) - break; - } - v131[7] = v14; - - if (collLineIdxArr[1] < 0 || _lastLine < collLineIdxArr[1]) - collLineIdxArr[1] = -1; - if (collLineIdxArr[3] < 0 || _lastLine < collLineIdxArr[3]) - collLineIdxArr[3] = -1; - if (collLineIdxArr[5] < 0 || _lastLine < collLineIdxArr[5]) - collLineIdxArr[5] = -1; - if (collLineIdxArr[7] < 0 || _lastLine < collLineIdxArr[7]) - collLineIdxArr[7] = -1; - if (collLineIdxArr[1] < 0) - v131[1] = 1300; - if (collLineIdxArr[3] < 0) - v131[3] = 1300; - if (collLineIdxArr[5] < 0) - v131[5] = 1300; - if (collLineIdxArr[7] < 0) - v131[7] = 1300; - if (collLineIdxArr[1] == -1 && collLineIdxArr[3] == -1 && collLineIdxArr[5] == -1 && collLineIdxArr[7] == -1) + if (checkCollisionLine(tmpX, clipDestY, &collLineDataIdxArr[DIR_LEFT], &collLineIdxArr[DIR_LEFT], 0, _lastLine) && collLineIdxArr[DIR_LEFT] <= _lastLine) + break; + collLineDataIdxArr[DIR_LEFT] = 0; + collLineIdxArr[DIR_LEFT] = -1; + ++tmpDelta; + if (deltaArr[DIR_UP] < tmpDelta && collLineIdxArr[DIR_UP] != -1) + break; + if (deltaArr[DIR_DOWN] < tmpDelta && collLineIdxArr[DIR_DOWN] != -1) + break; + if (deltaArr[DIR_RIGHT] < tmpDelta && collLineIdxArr[DIR_RIGHT] != -1) + break; + } + deltaArr[DIR_LEFT] = tmpDelta; + + if (collLineIdxArr[DIR_UP] < 0 || _lastLine < collLineIdxArr[DIR_UP]) + collLineIdxArr[DIR_UP] = -1; + if (collLineIdxArr[DIR_RIGHT] < 0 || _lastLine < collLineIdxArr[DIR_RIGHT]) + collLineIdxArr[DIR_RIGHT] = -1; + if (collLineIdxArr[DIR_DOWN] < 0 || _lastLine < collLineIdxArr[DIR_DOWN]) + collLineIdxArr[DIR_DOWN] = -1; + if (collLineIdxArr[DIR_LEFT] < 0 || _lastLine < collLineIdxArr[DIR_LEFT]) + collLineIdxArr[DIR_LEFT] = -1; + if (collLineIdxArr[DIR_UP] < 0) + deltaArr[DIR_UP] = INVALID_LINE_VALUE; + if (collLineIdxArr[DIR_RIGHT] < 0) + deltaArr[DIR_RIGHT] = INVALID_LINE_VALUE; + if (collLineIdxArr[DIR_DOWN] < 0) + deltaArr[DIR_DOWN] = INVALID_LINE_VALUE; + if (collLineIdxArr[DIR_LEFT] < 0) + deltaArr[DIR_LEFT] = INVALID_LINE_VALUE; + if (collLineIdxArr[DIR_UP] == -1 && collLineIdxArr[DIR_RIGHT] == -1 && collLineIdxArr[DIR_DOWN] == -1 && collLineIdxArr[DIR_LEFT] == -1) return (RouteItem *)g_PTRNUL; - if (collLineIdxArr[5] != -1 && v131[1] >= v131[5] && v131[3] >= v131[5] && v131[7] >= v131[5]) { - curLineIdx = collLineIdxArr[5]; - curLineDataIdx = collLineDataIdxArr[5]; - } else if (collLineIdxArr[1] != -1 && v131[5] >= v131[1] && v131[3] >= v131[1] && v131[7] >= v131[1]) { - curLineIdx = collLineIdxArr[1]; - curLineDataIdx = collLineDataIdxArr[1]; - } else if (collLineIdxArr[3] != -1 && v131[1] >= v131[3] && v131[5] >= v131[3] && v131[7] >= v131[3]) { - curLineIdx = collLineIdxArr[3]; - curLineDataIdx = collLineDataIdxArr[3]; - } else if (collLineIdxArr[7] != -1 && v131[5] >= v131[7] && v131[3] >= v131[7] && v131[1] >= v131[7]) { - curLineIdx = collLineIdxArr[7]; - curLineDataIdx = collLineDataIdxArr[7]; + if (collLineIdxArr[DIR_DOWN] != -1 && deltaArr[DIR_UP] >= deltaArr[DIR_DOWN] && deltaArr[DIR_RIGHT] >= deltaArr[DIR_DOWN] && deltaArr[DIR_LEFT] >= deltaArr[DIR_DOWN]) { + curLineIdx = collLineIdxArr[DIR_DOWN]; + curLineDataIdx = collLineDataIdxArr[DIR_DOWN]; + } else if (collLineIdxArr[DIR_UP] != -1 && deltaArr[DIR_DOWN] >= deltaArr[DIR_UP] && deltaArr[DIR_RIGHT] >= deltaArr[DIR_UP] && deltaArr[DIR_LEFT] >= deltaArr[DIR_UP]) { + curLineIdx = collLineIdxArr[DIR_UP]; + curLineDataIdx = collLineDataIdxArr[DIR_UP]; + } else if (collLineIdxArr[DIR_RIGHT] != -1 && deltaArr[DIR_UP] >= deltaArr[DIR_RIGHT] && deltaArr[DIR_DOWN] >= deltaArr[DIR_RIGHT] && deltaArr[DIR_LEFT] >= deltaArr[DIR_RIGHT]) { + curLineIdx = collLineIdxArr[DIR_RIGHT]; + curLineDataIdx = collLineDataIdxArr[DIR_RIGHT]; + } else if (collLineIdxArr[DIR_LEFT] != -1 && deltaArr[DIR_DOWN] >= deltaArr[DIR_LEFT] && deltaArr[DIR_RIGHT] >= deltaArr[DIR_LEFT] && deltaArr[DIR_UP] >= deltaArr[DIR_LEFT]) { + curLineIdx = collLineIdxArr[DIR_LEFT]; + curLineDataIdx = collLineDataIdxArr[DIR_LEFT]; } for (int i = 0; i <= 8; ++i) { collLineIdxArr[i] = -1; collLineDataIdxArr[i] = 0; - v131[i] = 1300; - v126[i] = 1300; + deltaArr[i] = INVALID_LINE_VALUE; + stepArr[i] = INVALID_LINE_VALUE; } - v14 = 0; - for (int tmpY = fromY; tmpY < _vm->_graphicsManager._maxY; tmpY++, v14++) { - if (checkCollisionLine(fromX, tmpY, &collLineDataIdxArr[5], &collLineIdxArr[5], 0, _lastLine) && collLineIdxArr[5] <= _lastLine) + tmpDelta = 0; + for (int tmpY = fromY; tmpY < _vm->_graphicsManager._maxY; tmpY++, tmpDelta++) { + if (checkCollisionLine(fromX, tmpY, &collLineDataIdxArr[DIR_DOWN], &collLineIdxArr[DIR_DOWN], 0, _lastLine) && collLineIdxArr[DIR_DOWN] <= _lastLine) break; - collLineDataIdxArr[5] = 0; - collLineIdxArr[5] = -1; + collLineDataIdxArr[DIR_DOWN] = 0; + collLineIdxArr[DIR_DOWN] = -1; } - v131[5] = v14 + 1; + deltaArr[DIR_DOWN] = tmpDelta + 1; - v14 = 0; + tmpDelta = 0; for (int tmpY = fromY; tmpY > _vm->_graphicsManager._minY; tmpY--) { - if (checkCollisionLine(fromX, tmpY, &collLineDataIdxArr[1], &collLineIdxArr[1], 0, _lastLine) && collLineIdxArr[1] <= _lastLine) + if (checkCollisionLine(fromX, tmpY, &collLineDataIdxArr[DIR_UP], &collLineIdxArr[DIR_UP], 0, _lastLine) && collLineIdxArr[DIR_UP] <= _lastLine) break; - collLineDataIdxArr[1] = 0; - collLineIdxArr[1] = -1; - ++v14; - if (collLineIdxArr[5] != -1 && v14 > 80) + collLineDataIdxArr[DIR_UP] = 0; + collLineIdxArr[DIR_UP] = -1; + ++tmpDelta; + if (collLineIdxArr[DIR_DOWN] != -1 && tmpDelta > 80) break; } - v131[1] = v14 + 1; + deltaArr[DIR_UP] = tmpDelta + 1; - v14 = 0; + tmpDelta = 0; for (int tmpX = fromX; tmpX < _vm->_graphicsManager._maxX; tmpX++) { - if (checkCollisionLine(tmpX, fromY, &collLineDataIdxArr[3], &collLineIdxArr[3], 0, _lastLine) && collLineIdxArr[3] <= _lastLine) + if (checkCollisionLine(tmpX, fromY, &collLineDataIdxArr[DIR_RIGHT], &collLineIdxArr[DIR_RIGHT], 0, _lastLine) && collLineIdxArr[DIR_RIGHT] <= _lastLine) break; - collLineDataIdxArr[3] = 0; - collLineIdxArr[3] = -1; - ++v14; - if ((collLineIdxArr[5] != -1 || collLineIdxArr[1] != -1) && (v14 > 100)) + collLineDataIdxArr[DIR_RIGHT] = 0; + collLineIdxArr[DIR_RIGHT] = -1; + ++tmpDelta; + if ((collLineIdxArr[DIR_DOWN] != -1 || collLineIdxArr[DIR_UP] != -1) && (tmpDelta > 100)) break; } - v131[3] = v14 + 1; + deltaArr[DIR_RIGHT] = tmpDelta + 1; - v14 = 0; + tmpDelta = 0; for (int tmpX = fromX; tmpX > _vm->_graphicsManager._minX; tmpX--) { - if (checkCollisionLine(tmpX, fromY, &collLineDataIdxArr[7], &collLineIdxArr[7], 0, _lastLine) && collLineIdxArr[7] <= _lastLine) + if (checkCollisionLine(tmpX, fromY, &collLineDataIdxArr[DIR_LEFT], &collLineIdxArr[DIR_LEFT], 0, _lastLine) && collLineIdxArr[DIR_LEFT] <= _lastLine) break; - collLineDataIdxArr[7] = 0; - collLineIdxArr[7] = -1; - ++v14; - if ((collLineIdxArr[5] != -1 || collLineIdxArr[1] != -1 || collLineIdxArr[3] != -1) && (v14 > 100)) + collLineDataIdxArr[DIR_LEFT] = 0; + collLineIdxArr[DIR_LEFT] = -1; + ++tmpDelta; + if ((collLineIdxArr[DIR_DOWN] != -1 || collLineIdxArr[DIR_UP] != -1 || collLineIdxArr[DIR_RIGHT] != -1) && (tmpDelta > 100)) break; } - v131[7] = v14 + 1; + deltaArr[DIR_LEFT] = tmpDelta + 1; - if (collLineIdxArr[1] != -1) - v126[1] = abs(collLineIdxArr[1] - curLineIdx); + if (collLineIdxArr[DIR_UP] != -1) + stepArr[DIR_UP] = abs(collLineIdxArr[DIR_UP] - curLineIdx); - if (collLineIdxArr[3] != -1) - v126[3] = abs(collLineIdxArr[3] - curLineIdx); + if (collLineIdxArr[DIR_RIGHT] != -1) + stepArr[DIR_RIGHT] = abs(collLineIdxArr[DIR_RIGHT] - curLineIdx); - if (collLineIdxArr[5] != -1) - v126[5] = abs(collLineIdxArr[5] - curLineIdx); + if (collLineIdxArr[DIR_DOWN] != -1) + stepArr[DIR_DOWN] = abs(collLineIdxArr[DIR_DOWN] - curLineIdx); - if (collLineIdxArr[7] != -1) - v126[7] = abs(collLineIdxArr[7] - curLineIdx); + if (collLineIdxArr[DIR_LEFT] != -1) + stepArr[DIR_LEFT] = abs(collLineIdxArr[DIR_LEFT] - curLineIdx); - if (collLineIdxArr[1] == -1 && collLineIdxArr[3] == -1 && collLineIdxArr[5] == -1 && collLineIdxArr[7] == -1) + if (collLineIdxArr[DIR_UP] == -1 && collLineIdxArr[DIR_RIGHT] == -1 && collLineIdxArr[DIR_DOWN] == -1 && collLineIdxArr[DIR_LEFT] == -1) error("Nearest point not found"); - if (collLineIdxArr[1] != -1 && v126[3] >= v126[1] && v126[5] >= v126[1] && v126[7] >= v126[1]) { - lineIdx = collLineIdxArr[1]; - v111 = v131[1]; + int delta = 0; + if (collLineIdxArr[DIR_UP] != -1 && stepArr[DIR_RIGHT] >= stepArr[DIR_UP] && stepArr[DIR_DOWN] >= stepArr[DIR_UP] && stepArr[DIR_LEFT] >= stepArr[DIR_UP]) { + lineIdx = collLineIdxArr[DIR_UP]; + delta = deltaArr[DIR_UP]; newDir = DIR_UP; - lineDataIdx = collLineDataIdxArr[1]; - } else if (collLineIdxArr[5] != -1 && v126[3] >= v126[5] && v126[1] >= v126[5] && v126[7] >= v126[5]) { - lineIdx = collLineIdxArr[5]; - v111 = v131[5]; + lineDataIdx = collLineDataIdxArr[DIR_UP]; + } else if (collLineIdxArr[DIR_DOWN] != -1 && stepArr[DIR_RIGHT] >= stepArr[DIR_DOWN] && stepArr[DIR_UP] >= stepArr[DIR_DOWN] && stepArr[DIR_LEFT] >= stepArr[DIR_DOWN]) { + lineIdx = collLineIdxArr[DIR_DOWN]; + delta = deltaArr[DIR_DOWN]; newDir = DIR_DOWN; - lineDataIdx = collLineDataIdxArr[5]; - } else if (collLineIdxArr[3] != -1 && v126[1] >= v126[3] && v126[5] >= v126[3] && v126[7] >= v126[3]) { - lineIdx = collLineIdxArr[3]; - v111 = v131[3]; + lineDataIdx = collLineDataIdxArr[DIR_DOWN]; + } else if (collLineIdxArr[DIR_RIGHT] != -1 && stepArr[DIR_UP] >= stepArr[DIR_RIGHT] && stepArr[DIR_DOWN] >= stepArr[DIR_RIGHT] && stepArr[DIR_LEFT] >= stepArr[DIR_RIGHT]) { + lineIdx = collLineIdxArr[DIR_RIGHT]; + delta = deltaArr[DIR_RIGHT]; newDir = DIR_RIGHT; - lineDataIdx = collLineDataIdxArr[3]; - } else if (collLineIdxArr[7] != -1 && v126[1] >= v126[7] && v126[5] >= v126[7] && v126[3] >= v126[7]) { - lineIdx = collLineIdxArr[7]; - v111 = v131[7]; + lineDataIdx = collLineDataIdxArr[DIR_RIGHT]; + } else if (collLineIdxArr[DIR_LEFT] != -1 && stepArr[DIR_UP] >= stepArr[DIR_LEFT] && stepArr[DIR_DOWN] >= stepArr[DIR_LEFT] && stepArr[DIR_RIGHT] >= stepArr[DIR_LEFT]) { + lineIdx = collLineIdxArr[DIR_LEFT]; + delta = deltaArr[DIR_LEFT]; newDir = DIR_LEFT; - lineDataIdx = collLineDataIdxArr[7]; + lineDataIdx = collLineDataIdxArr[DIR_LEFT]; } - int v55 = characterRoute(fromX, fromY, clipDestX, clipDestY, lineIdx, curLineIdx, 0); + int bestRouteNum = characterRoute(fromX, fromY, clipDestX, clipDestY, lineIdx, curLineIdx, 0); - if (v55 == 1) + if (bestRouteNum == 1) return _bestRoute; - if (v55 == 2) { + if (bestRouteNum == 2) { lineIdx = _newLineIdx; lineDataIdx = _newLineDataIdx; routeIdx = _newRouteIdx; } else { - if (newDir == DIR_UP) { - for (int deltaY = 0; deltaY < v111; deltaY++) { + switch (newDir) { + case DIR_UP: + for (int deltaY = 0; deltaY < delta; deltaY++) { if (checkCollisionLine(fromX, fromY - deltaY, &foundDataIdx, &foundLineIdx, _lastLine + 1, _linesNumb) && _lastLine < foundLineIdx) { - int tmpRouteIdx = GENIAL(foundLineIdx, foundDataIdx, fromX, fromY - deltaY, fromX, fromY - v111, routeIdx, _bestRoute); + int tmpRouteIdx = GENIAL(foundLineIdx, foundDataIdx, fromX, fromY - deltaY, fromX, fromY - delta, routeIdx, _bestRoute); if (tmpRouteIdx == -1) { _bestRoute[routeIdx].invalidate(); return &_bestRoute[0]; @@ -1347,12 +1318,12 @@ RouteItem *LinesManager::PARCOURS2(int fromX, int fromY, int destX, int destY) { _bestRoute[routeIdx].set(fromX, fromY - deltaY, DIR_UP); routeIdx++; } - } - if (newDir == DIR_DOWN) { - for (int deltaY = 0; deltaY < v111; deltaY++) { + break; + case DIR_DOWN: + for (int deltaY = 0; deltaY < delta; deltaY++) { if (checkCollisionLine(fromX, deltaY + fromY, &foundDataIdx, &foundLineIdx, _lastLine + 1, _linesNumb) && _lastLine < foundLineIdx) { - int tmpRouteIdx = GENIAL(foundLineIdx, foundDataIdx, fromX, deltaY + fromY, fromX, v111 + fromY, routeIdx, &_bestRoute[0]); + int tmpRouteIdx = GENIAL(foundLineIdx, foundDataIdx, fromX, deltaY + fromY, fromX, delta + fromY, routeIdx, &_bestRoute[0]); if (tmpRouteIdx == -1) { _bestRoute[routeIdx].invalidate(); return &_bestRoute[0]; @@ -1364,11 +1335,11 @@ RouteItem *LinesManager::PARCOURS2(int fromX, int fromY, int destX, int destY) { _bestRoute[routeIdx].set(fromX, fromY + deltaY, DIR_DOWN); routeIdx++; } - } - if (newDir == DIR_LEFT) { - for (int deltaX = 0; deltaX < v111; deltaX++) { + break; + case DIR_LEFT: + for (int deltaX = 0; deltaX < delta; deltaX++) { if (checkCollisionLine(fromX - deltaX, fromY, &foundDataIdx, &foundLineIdx, _lastLine + 1, _linesNumb) && _lastLine < foundLineIdx) { - int tmpRouteIdx = GENIAL(foundLineIdx, foundDataIdx, fromX - deltaX, fromY, fromX - v111, fromY, routeIdx, &_bestRoute[0]); + int tmpRouteIdx = GENIAL(foundLineIdx, foundDataIdx, fromX - deltaX, fromY, fromX - delta, fromY, routeIdx, &_bestRoute[0]); if (tmpRouteIdx == -1) { _bestRoute[routeIdx].invalidate(); return &_bestRoute[0]; @@ -1380,11 +1351,11 @@ RouteItem *LinesManager::PARCOURS2(int fromX, int fromY, int destX, int destY) { _bestRoute[routeIdx].set(fromX - deltaX, fromY, DIR_LEFT); routeIdx++; } - } - if (newDir == DIR_RIGHT) { - for (int deltaX = 0; deltaX < v111; deltaX++) { + break; + case DIR_RIGHT: + for (int deltaX = 0; deltaX < delta; deltaX++) { if (checkCollisionLine(deltaX + fromX, fromY, &foundDataIdx, &foundLineIdx, _lastLine + 1, _linesNumb) && _lastLine < foundLineIdx) { - int tmpRouteIdx = GENIAL(foundLineIdx, foundDataIdx, deltaX + fromX, fromY, v111 + fromX, fromY, routeIdx, &_bestRoute[0]); + int tmpRouteIdx = GENIAL(foundLineIdx, foundDataIdx, deltaX + fromX, fromY, delta + fromX, fromY, routeIdx, &_bestRoute[0]); if (tmpRouteIdx == -1) { _bestRoute[routeIdx].invalidate(); return &_bestRoute[0]; @@ -1396,10 +1367,12 @@ RouteItem *LinesManager::PARCOURS2(int fromX, int fromY, int destX, int destY) { _bestRoute[routeIdx].set(fromX + deltaX, fromY, DIR_RIGHT); routeIdx++; } + break; + default: + break; } } - bool loopCond; do { loopCond = false; @@ -1417,10 +1390,10 @@ RouteItem *LinesManager::PARCOURS2(int fromX, int fromY, int destX, int destY) { _bestRoute[routeIdx].set(_lineItem[idx]._lineData[2 * dataIdx], _lineItem[idx]._lineData[2 * dataIdx + 1], _lineItem[idx]._directionRouteInc); routeIdx++; if (_lineItem[idx]._lineDataEndIdx > 30 && dataIdx == _lineItem[idx]._lineDataEndIdx / 2) { - int v78 = characterRoute(_lineItem[idx]._lineData[2 * dataIdx], _lineItem[idx]._lineData[2 * dataIdx + 1], clipDestX, clipDestY, idx, curLineIdx, routeIdx); - if (v78 == 1) + bestRouteNum = characterRoute(_lineItem[idx]._lineData[2 * dataIdx], _lineItem[idx]._lineData[2 * dataIdx + 1], clipDestX, clipDestY, idx, curLineIdx, routeIdx); + if (bestRouteNum == 1) return &_bestRoute[0]; - if (v78 == 2 || MIRACLE(curLineX, curLineY, idx, curLineIdx, routeIdx)) { + if (bestRouteNum == 2 || MIRACLE(curLineX, curLineY, idx, curLineIdx, routeIdx)) { lineIdx = _newLineIdx; lineDataIdx = _newLineDataIdx; routeIdx = _newRouteIdx; @@ -1433,10 +1406,10 @@ RouteItem *LinesManager::PARCOURS2(int fromX, int fromY, int destX, int destY) { if (loopCond) break; - int v79 = characterRoute(curLineX, curLineY, clipDestX, clipDestY, idx, curLineIdx, routeIdx); - if (v79 == 1) + bestRouteNum = characterRoute(curLineX, curLineY, clipDestX, clipDestY, idx, curLineIdx, routeIdx); + if (bestRouteNum == 1) return &_bestRoute[0]; - if (v79 == 2 || MIRACLE(curLineX, curLineY, idx, curLineIdx, routeIdx)) { + if (bestRouteNum == 2 || MIRACLE(curLineX, curLineY, idx, curLineIdx, routeIdx)) { lineIdx = _newLineIdx; lineDataIdx = _newLineDataIdx; routeIdx = _newRouteIdx; @@ -1458,17 +1431,17 @@ RouteItem *LinesManager::PARCOURS2(int fromX, int fromY, int destX, int destY) { _bestRoute[routeIdx].set(_lineItem[lineIdx]._lineData[2 * dataIdx], _lineItem[lineIdx]._lineData[2 * dataIdx + 1], _lineItem[lineIdx]._directionRouteDec); routeIdx++; } - for (int v117 = lineIdx - 1; v117 > curLineIdx; v117--) { - for (int dataIdx = _lineItem[v117]._lineDataEndIdx - 1; dataIdx > -1; dataIdx--) { - curLineX = _lineItem[v117]._lineData[2 * dataIdx]; - curLineY = _lineItem[v117]._lineData[2 * dataIdx + 1]; - _bestRoute[routeIdx].set(_lineItem[v117]._lineData[2 * dataIdx], _lineItem[v117]._lineData[2 * dataIdx + 1], _lineItem[v117]._directionRouteDec); + for (int i = lineIdx - 1; i > curLineIdx; i--) { + for (int dataIdx = _lineItem[i]._lineDataEndIdx - 1; dataIdx > -1; dataIdx--) { + curLineX = _lineItem[i]._lineData[2 * dataIdx]; + curLineY = _lineItem[i]._lineData[2 * dataIdx + 1]; + _bestRoute[routeIdx].set(_lineItem[i]._lineData[2 * dataIdx], _lineItem[i]._lineData[2 * dataIdx + 1], _lineItem[i]._directionRouteDec); routeIdx++; - if (_lineItem[v117]._lineDataEndIdx > 30 && dataIdx == _lineItem[v117]._lineDataEndIdx / 2) { - int v88 = characterRoute(curLineX, curLineY, clipDestX, clipDestY, v117, curLineIdx, routeIdx); - if (v88 == 1) + if (_lineItem[i]._lineDataEndIdx > 30 && dataIdx == _lineItem[i]._lineDataEndIdx / 2) { + bestRouteNum = characterRoute(curLineX, curLineY, clipDestX, clipDestY, i, curLineIdx, routeIdx); + if (bestRouteNum == 1) return &_bestRoute[0]; - if (v88 == 2 || MIRACLE(curLineX, curLineY, v117, curLineIdx, routeIdx)) { + if (bestRouteNum == 2 || MIRACLE(curLineX, curLineY, i, curLineIdx, routeIdx)) { lineIdx = _newLineIdx; lineDataIdx = _newLineDataIdx; routeIdx = _newRouteIdx; @@ -1481,10 +1454,10 @@ RouteItem *LinesManager::PARCOURS2(int fromX, int fromY, int destX, int destY) { if (loopCond) break; - int v89 = characterRoute(curLineX, curLineY, clipDestX, clipDestY, v117, curLineIdx, routeIdx); - if (v89 == 1) + bestRouteNum = characterRoute(curLineX, curLineY, clipDestX, clipDestY, i, curLineIdx, routeIdx); + if (bestRouteNum == 1) return &_bestRoute[0]; - if (v89 == 2 || MIRACLE(curLineX, curLineY, v117, curLineIdx, routeIdx)) { + if (bestRouteNum == 2 || MIRACLE(curLineX, curLineY, i, curLineIdx, routeIdx)) { lineIdx = _newLineIdx; lineDataIdx = _newLineDataIdx; routeIdx = _newRouteIdx; @@ -1501,11 +1474,10 @@ RouteItem *LinesManager::PARCOURS2(int fromX, int fromY, int destX, int destY) { } while (loopCond); if (lineIdx == curLineIdx) { - if (lineDataIdx <= curLineDataIdx) { + if (lineDataIdx <= curLineDataIdx) routeIdx = _lineItem[curLineIdx].appendToRouteInc(lineDataIdx, curLineDataIdx, _bestRoute, routeIdx); - } else { + else routeIdx = _lineItem[curLineIdx].appendToRouteDec(lineDataIdx, curLineDataIdx, _bestRoute, routeIdx); - } } if (characterRoute(_bestRoute[routeIdx - 1]._x, _bestRoute[routeIdx - 1]._y, clipDestX, clipDestY, -1, -1, routeIdx) != 1) { _bestRoute[routeIdx].invalidate(); @@ -1514,55 +1486,51 @@ RouteItem *LinesManager::PARCOURS2(int fromX, int fromY, int destX, int destY) { return &_bestRoute[0]; } -int LinesManager::characterRoute(int fromX, int fromY, int destX, int destY, int a5, int a6, int a7) { - int v18; - int v19; - int v20; - int v21; - int v22; - int v23; - int v24; - int v33; - bool v45; - int v54; - int v55; - Directions newDirection; - int v92; - int v93; - int v94; - int v95; - int v96; - int v97; - int v98; - int v99; - int v100; - int v101; - int v102; - int v103; - int v104; - int v105; - int v106; - int v107; - int v108; - int v109; - int v111; - int v114; - int v115; - int v117; - int collLineIdx; - int collDataIdx = 0; - int v140; - int v142; +void LinesManager::_useRoute0(int idx, int curRouteIdx) { + if (idx) { + int i = 0; + do { + assert(curRouteIdx <= 8000); + _bestRoute[curRouteIdx++] = _testRoute0[i++]; + } while (_testRoute0[i].isValid()); + } + _bestRoute[curRouteIdx].invalidate(); +} + +void LinesManager::useRoute1(int idx, int curRouteIdx) { + if (idx) { + int i = 0; + do { + assert(curRouteIdx <= 8000); + _bestRoute[curRouteIdx++] = _testRoute1[i++]; + } while (_testRoute1[i].isValid()); + } + _bestRoute[curRouteIdx].invalidate(); +} + +void LinesManager::useRoute2(int idx, int curRouteIdx) { + if (idx) { + int i = 0; + do { + assert(curRouteIdx <= 8000); + _bestRoute[curRouteIdx++] = _testRoute2[i++]; + } while (_testRoute2[i].isValid()); + } + _bestRoute[curRouteIdx].invalidate(); +} + +int LinesManager::characterRoute(int fromX, int fromY, int destX, int destY, int startLineIdx, int endLineIdx, int routeIdx) { + int collDataIdxRoute2 = 0; bool colResult = false; int curX = fromX; int curY = fromY; - int v137 = a7; - bool v136 = false; - if (a5 == -1 && a6 == -1) - v136 = true; + int curRouteIdx = routeIdx; + bool dummyLineFl = false; + if (startLineIdx == -1 && endLineIdx == -1) + dummyLineFl = true; int foundDataIdx; - int foundLineIdx = a5; + int foundLineIdx = startLineIdx; if (checkCollisionLine(fromX, fromY, &foundDataIdx, &foundLineIdx, 0, _linesNumb)) { switch (_lineItem[foundLineIdx]._direction) { case DIR_UP: @@ -1596,64 +1564,66 @@ int LinesManager::characterRoute(int fromX, int fromY, int destX, int destY, int break; } } - v98 = curX; - v97 = curY; - v115 = 0; - v142 = -1; - v140 = -1; - collLineIdx = -1; + int oldX = curX; + int oldY = curY; + int idxRoute0 = 0; + int collLineIdxRoute0 = -1; + int collLineIdxRoute1 = -1; + int collLineIdxRoute2 = -1; - int distX, v10, distY, v12, v13, v14; + int distX, distY; int repeatFlag = 0; - int v143 = 0; - int v141 = 0; + int collDataIdxRoute0 = 0; + int collDataIdxRoute1 = 0; for (;;) { - v111 = curX; - v109 = curY; + int newX = curX; + int newY = curY; if (destX >= curX - 2 && destX <= curX + 2 && destY >= curY - 2 && destY <= curY + 2) { - essai0[v115].invalidate(); - goto retLABEL_essai0; - } - distX = abs(curX - destX); - v10 = distX + 1; - distY = abs(curY - destY); - v107 = distY + 1; - if (v10 > v107) - v107 = v10; - v12 = v107 - 1; - assert(v12 != 0); - v101 = 1000 * v10 / v12; - v99 = 1000 * (distY + 1) / v12; + _testRoute0[idxRoute0].invalidate(); + _useRoute0(idxRoute0, curRouteIdx); + return 1; + } + distX = abs(curX - destX) + 1; + distY = abs(curY - destY) + 1; + int maxDist; + if (distX > distY) + maxDist = distX; + else + maxDist = distY; + maxDist--; + assert(maxDist != 0); + int stepX = 1000 * distX / maxDist; + int stepY = 1000 * distY / maxDist; if (destX < curX) - v101 = -v101; + stepX = -stepX; if (destY < curY) - v99 = -v99; - v13 = (int16)v101 / 1000; - v94 = (int16)v99 / 1000; - newDirection = DIR_NONE; - if (v94 == -1 && (v101 >= 0 && v101 <= 150)) + stepY = -stepY; + int vertDirection = (int16)stepX / 1000; + int horzDirection = (int16)stepY / 1000; + Directions newDirection = DIR_NONE; + if (horzDirection == -1 && (stepX >= 0 && stepX <= 150)) newDirection = DIR_UP; - if (v13 == 1 && (v99 >= -1 && v99 <= 150)) + if (vertDirection == 1 && (stepY >= -1 && stepY <= 150)) newDirection = DIR_RIGHT; - if (v94 == 1 && (v101 >= -150 && v101 <= 150)) + if (horzDirection == 1 && (stepX >= -150 && stepX <= 150)) newDirection = DIR_DOWN; - if (v13 == -1 && (v99 >= -150 && v99 <= 150)) + if (vertDirection == -1 && (stepY >= -150 && stepY <= 150)) newDirection = DIR_LEFT; - if (v94 == -1 && (v101 >= -150 && v101 <= 0)) + if (horzDirection == -1 && (stepX >= -150 && stepX <= 0)) newDirection = DIR_UP; - if (newDirection == DIR_NONE && !checkSmoothMove(curX, v109, destX, destY) && !makeSmoothMove(curX, v109, destX, destY)) { + if (newDirection == DIR_NONE && !checkSmoothMove(curX, newY, destX, destY) && !makeSmoothMove(curX, newY, destX, destY)) { newDirection = _smoothMoveDirection; - v14 = 0; - for (v14 = 0; _smoothRoute[v14]._posX != -1 && _smoothRoute[v14]._posY != -1; ++v14) { - if (checkCollisionLine(_smoothRoute[v14]._posX, _smoothRoute[v14]._posY, &v143, &v142, 0, _linesNumb)) { - if (v142 > _lastLine) - v142 = -1; + int smoothRouteIdx = 0; + for (smoothRouteIdx = 0; _smoothRoute[smoothRouteIdx]._posX != -1 && _smoothRoute[smoothRouteIdx]._posY != -1; ++smoothRouteIdx) { + if (checkCollisionLine(_smoothRoute[smoothRouteIdx]._posX, _smoothRoute[smoothRouteIdx]._posY, &collDataIdxRoute0, &collLineIdxRoute0, 0, _linesNumb)) { + if (collLineIdxRoute0 > _lastLine) + collLineIdxRoute0 = -1; break; } - essai0[v115].set(_smoothRoute[v14]._posX, _smoothRoute[v14]._posY, newDirection); - v115++; + _testRoute0[idxRoute0].set(_smoothRoute[smoothRouteIdx]._posX, _smoothRoute[smoothRouteIdx]._posY, newDirection); + idxRoute0++; if (repeatFlag == 1) { repeatFlag = 2; @@ -1661,368 +1631,342 @@ int LinesManager::characterRoute(int fromX, int fromY, int destX, int destY, int } } - if (repeatFlag != 2 && _smoothRoute[v14]._posX != -1 && _smoothRoute[v14]._posY != -1) + if (repeatFlag != 2 && _smoothRoute[smoothRouteIdx]._posX != -1 && _smoothRoute[smoothRouteIdx]._posY != -1) break; repeatFlag = 1; - v18 = v14 - 1; - v111 = _smoothRoute[v18]._posX; - v109 = _smoothRoute[v18]._posY; - } - v19 = abs(v111 - destX); - v20 = v19 + 1; - v95 = abs(v109 - destY); - v108 = v95 + 1; - if (v20 > (v95 + 1)) - v108 = v20; - if (v108 <= 10) { - essai0[v115].invalidate(); - goto retLABEL_essai0; - } - v21 = v108 - 1; - v102 = 1000 * v20 / v21; - v100 = 1000 * (v95 + 1) / v21; - if (destX < v111) - v102 = -v102; - if (destY < v109) - v100 = -v100; - v22 = v102 / 1000; - v96 = v100 / 1000; - v106 = 1000 * v111; - v105 = 1000 * v109; - v104 = 1000 * v111 / 1000; - v103 = v105 / 1000; - if (!(v102 / 1000) && v96 == -1) + newX = _smoothRoute[smoothRouteIdx - 1]._posX; + newY = _smoothRoute[smoothRouteIdx - 1]._posY; + } + int newDistX = abs(newX - destX) + 1; + int newDistY = abs(newY - destY) + 1; + int newMaxDist = newDistY; + if (newDistX > newDistY) + newMaxDist = newDistX; + if (newMaxDist <= 10) { + _testRoute0[idxRoute0].invalidate(); + _useRoute0(idxRoute0, curRouteIdx); + return 1; + } + int newStepX = 1000 * newDistX / (newMaxDist - 1); + int newStepY = 1000 * newDistY / (newMaxDist - 1); + if (destX < newX) + newStepX = -newStepX; + if (destY < newY) + newStepY = -newStepY; + int newVertDirection = newStepX / 1000; + int newHorzDirection = newStepY / 1000; + int newSmoothX = 1000 * newX; + int newSmoothY = 1000 * newY; + int curPosX = newSmoothX / 1000; + int curPosY = newSmoothY / 1000; + if (!(newStepX / 1000) && newHorzDirection == -1) newDirection = DIR_UP; - if (v22 == 1) { - if (v96 == -1) + if (newVertDirection == 1) { + if (newHorzDirection == -1) newDirection = DIR_UP_RIGHT; - if (!v96) + if (!newHorzDirection) newDirection = DIR_RIGHT; - if (v96 == 1) + if (newHorzDirection == 1) newDirection = DIR_DOWN_RIGHT; } - if (!v22 && v96 == 1) + if (!newVertDirection && newHorzDirection == 1) newDirection = DIR_DOWN; - if ((v22 != -1) && (v96 == -1)) { - if (v102 >= 0 && v102 < 510) + if ((newVertDirection != -1) && (newHorzDirection == -1)) { + if (newStepX >= 0 && newStepX < 510) newDirection = DIR_UP; - else if (v102 >= 510 && v102 <= 1000) + else if (newStepX >= 510 && newStepX <= 1000) newDirection = DIR_UP_RIGHT; } else { - if (v96 == 1) + if (newHorzDirection == 1) newDirection = DIR_DOWN_LEFT; - else if (!v96) + else if (!newHorzDirection) newDirection = DIR_LEFT; - else if (v96 == -1) { - if (v102 >= 0 && v102 < 510) + else if (newHorzDirection == -1) { + if (newStepX >= 0 && newStepX < 510) newDirection = DIR_UP; - else if (v102 >= 510 && v102 <= 1000) + else if (newStepX >= 510 && newStepX <= 1000) newDirection = DIR_UP_RIGHT; else newDirection = DIR_UP_LEFT; } } - if (v22 == 1) { - if (v100 >= -1000 && v100 <= -510) + if (newVertDirection == 1) { + if (newStepY >= -1000 && newStepY <= -510) newDirection = DIR_UP_RIGHT; - if (v100 >= -510 && v100 <= 510) + if (newStepY >= -510 && newStepY <= 510) newDirection = DIR_RIGHT; - if (v100 >= 510 && v100 <= 1000) + if (newStepY >= 510 && newStepY <= 1000) newDirection = DIR_DOWN_RIGHT; } - if (v96 == 1) { - if (v102 >= 510 && v102 <= 1000) + if (newHorzDirection == 1) { + if (newStepX >= 510 && newStepX <= 1000) newDirection = DIR_DOWN_RIGHT; - if (v102 >= -510 && v102 <= 510) + if (newStepX >= -510 && newStepX <= 510) newDirection = DIR_DOWN; - if (v102 >= -1000 && v102 <= -510) + if (newStepX >= -1000 && newStepX <= -510) newDirection = DIR_DOWN_LEFT; } - if (v22 == -1) { - if (v100 >= 510 && v100 <= 1000) + if (newVertDirection == -1) { + if (newStepY >= 510 && newStepY <= 1000) newDirection = DIR_DOWN_LEFT; - if (v100 >= -510 && v100 <= 510) + if (newStepY >= -510 && newStepY <= 510) newDirection = DIR_LEFT; - if (v100 >= -1000 && v100 <= -510) + if (newStepY >= -1000 && newStepY <= -510) newDirection = DIR_UP_LEFT; } - if (v96 == -1) { - if (v102 >= -1000 && v102 <= -510) + if (newHorzDirection == -1) { + if (newStepX >= -1000 && newStepX <= -510) newDirection = DIR_UP_LEFT; - if (v102 >= -510 && v102 <= 0) + if (newStepX >= -510 && newStepX <= 0) newDirection = DIR_UP; } - v23 = 0; - if (v108 + 1 <= 0) { - essai0[v115].invalidate(); - goto retLABEL_essai0; - } - while (!checkCollisionLine(v104, v103, &v143, &v142, 0, _linesNumb)) { - essai0[v115].set(v104, v103, newDirection); - v106 += v102; - v105 += v100; - v104 = v106 / 1000; - v103 = v105 / 1000; - v115++; - ++v23; - if (v23 >= v108 + 1) { - essai0[v115].invalidate(); - goto retLABEL_essai0; + if (newMaxDist + 1 <= 0) { + _testRoute0[idxRoute0].invalidate(); + _useRoute0(idxRoute0, curRouteIdx); + return 1; + } + int curDist = 0; + while (!checkCollisionLine(curPosX, curPosY, &collDataIdxRoute0, &collLineIdxRoute0, 0, _linesNumb)) { + _testRoute0[idxRoute0].set(curPosX, curPosY, newDirection); + newSmoothX += newStepX; + newSmoothY += newStepY; + curPosX = newSmoothX / 1000; + curPosY = newSmoothY / 1000; + idxRoute0++; + ++curDist; + if (curDist >= newMaxDist + 1) { + _testRoute0[idxRoute0].invalidate(); + _useRoute0(idxRoute0, curRouteIdx); + return 1; } } - if (_lastLine >= v142) + if (_lastLine >= collLineIdxRoute0) break; - v24 = GENIAL(v142, v143, v104, v103, destX, destY, v115, essai0); - if (v24 == -1) - goto retLABEL_essai0; - v115 = v24; + int tmpRouteIdx = GENIAL(collLineIdxRoute0, collDataIdxRoute0, curPosX, curPosY, destX, destY, idxRoute0, _testRoute0); + if (tmpRouteIdx == -1) { + _useRoute0(idxRoute0, curRouteIdx); + return 1; + } + idxRoute0 = tmpRouteIdx; if (_newPosX != -1 || _newPosY != -1) { - v142 = -1; + collLineIdxRoute0 = -1; break; } curX = -1; curY = -1; } - essai0[v115].invalidate(); + _testRoute0[idxRoute0].invalidate(); - v117 = 0; - v33 = v98; - v92 = v97; + int idxRoute1 = 0; + int posXRoute1 = oldX; + int posYRoute1 = oldY; while (true) { - if (destX >= v33 - 2 && destX <= v33 + 2 && destY >= v92 - 2 && destY <= v92 + 2) { - essai1[v117].invalidate(); - goto retLABEL_essai1; + if (destX >= posXRoute1 - 2 && destX <= posXRoute1 + 2 && destY >= posYRoute1 - 2 && destY <= posYRoute1 + 2) { + _testRoute1[idxRoute1].invalidate(); + useRoute1(idxRoute1, curRouteIdx); + return 1; } - while (v33 != destX) { - if (checkCollisionLine(v33, v92, &v141, &v140, 0, _linesNumb)) { - if (v140 > _lastLine) - v140 = -1; + while (posXRoute1 != destX) { + if (checkCollisionLine(posXRoute1, posYRoute1, &collDataIdxRoute1, &collLineIdxRoute1, 0, _linesNumb)) { + if (collLineIdxRoute1 > _lastLine) + collLineIdxRoute1 = -1; break; } - if (v33 < destX) - essai1[v117++].set(v33++, v92, DIR_RIGHT); + if (posXRoute1 < destX) + _testRoute1[idxRoute1++].set(posXRoute1++, posYRoute1, DIR_RIGHT); else - essai1[v117++].set(v33--, v92, DIR_LEFT); + _testRoute1[idxRoute1++].set(posXRoute1--, posYRoute1, DIR_LEFT); } - if (v33 != destX) + if (posXRoute1 != destX) break; - int v43 = v92; - while (v43 != destY) { - if (checkCollisionLine(destX, v43, &v141, &v140, 0, _linesNumb)) { - if (v140 <= _lastLine) + int curPosY = posYRoute1; + while (curPosY != destY) { + if (checkCollisionLine(destX, curPosY, &collDataIdxRoute1, &collLineIdxRoute1, 0, _linesNumb)) { + if (collLineIdxRoute1 <= _lastLine) break; - int v44 = GENIAL(v140, v141, destX, v43, destX, destY, v117, essai1); - if (v44 == -1) - goto retLABEL_essai1; - v117 = v44; + int tmpRouteIdx = GENIAL(collLineIdxRoute1, collDataIdxRoute1, destX, curPosY, destX, destY, idxRoute1, _testRoute1); + if (tmpRouteIdx == -1) { + useRoute1(idxRoute1, curRouteIdx); + return 1; + } + idxRoute1 = tmpRouteIdx; if (_newPosX != -1 && _newPosY != -1) break; } - if (v43 < destY) - essai1[v117++].set(destX, v43++, DIR_DOWN); + if (curPosY < destY) + _testRoute1[idxRoute1++].set(destX, curPosY++, DIR_DOWN); else - essai1[v117++].set(destX, v43--, DIR_UP); + _testRoute1[idxRoute1++].set(destX, curPosY--, DIR_UP); } - if (v43 == destY) { - essai1[v117].invalidate(); - goto retLABEL_essai1; + if (curPosY == destY) { + _testRoute1[idxRoute1].invalidate(); + useRoute1(idxRoute1, curRouteIdx); + return 1; } - if (v140 <= _lastLine) + if (collLineIdxRoute1 <= _lastLine) break; - v33 = _newPosX; - v92 = _newPosY; - v45 = checkCollisionLine(_newPosX, _newPosY, &v141, &v140, 0, _lastLine); - if (v45 && v140 <= _lastLine) + posXRoute1 = _newPosX; + posYRoute1 = _newPosY; + bool colRes = checkCollisionLine(_newPosX, _newPosY, &collDataIdxRoute1, &collLineIdxRoute1, 0, _lastLine); + if (colRes && collLineIdxRoute1 <= _lastLine) break; } - essai1[v117].invalidate(); - v117 = 0; - v54 = v98; - v93 = v97; + _testRoute1[idxRoute1].invalidate(); + idxRoute1 = 0; + int posXRoute2 = oldX; + int posYRoute2 = oldY; while (true) { - int v61; - v114 = v54; - if (destX >= v54 - 2 && destX <= v54 + 2 && destY >= v93 - 2 && destY <= v93 + 2) { - essai2[v117].invalidate(); - goto retLABEL_essai2; - } - - v55 = v93; - while (v55 != destY) { - if (checkCollisionLine(v114, v55, &collDataIdx, &collLineIdx, 0, _linesNumb)) { - if (collLineIdx > _lastLine) - collLineIdx = -1; + int curPosX; + if (destX >= posXRoute2 - 2 && destX <= posXRoute2 + 2 && destY >= posYRoute2 - 2 && destY <= posYRoute2 + 2) { + _testRoute2[idxRoute1].invalidate(); + useRoute2(idxRoute1, curRouteIdx); + return 1; + } + + int curPosYRoute2 = posYRoute2; + while (curPosYRoute2 != destY) { + if (checkCollisionLine(posXRoute2, curPosYRoute2, &collDataIdxRoute2, &collLineIdxRoute2, 0, _linesNumb)) { + if (collLineIdxRoute2 > _lastLine) + collLineIdxRoute2 = -1; break; } - if (v55 < destY) - essai2[v117++].set(v114, v55++, DIR_DOWN); + if (curPosYRoute2 < destY) + _testRoute2[idxRoute1++].set(posXRoute2, curPosYRoute2++, DIR_DOWN); else - essai2[v117++].set(v114, v55--, DIR_UP); + _testRoute2[idxRoute1++].set(posXRoute2, curPosYRoute2--, DIR_UP); } - if (v55 != destY) + if (curPosYRoute2 != destY) break; - v61 = v114; - while (v61 != destX) { - if (checkCollisionLine(v61, destY, &collDataIdx, &collLineIdx, 0, _linesNumb)) { - if (collLineIdx <= _lastLine) + curPosX = posXRoute2; + while (curPosX != destX) { + if (checkCollisionLine(curPosX, destY, &collDataIdxRoute2, &collLineIdxRoute2, 0, _linesNumb)) { + if (collLineIdxRoute2 <= _lastLine) break; - int v62 = GENIAL(collLineIdx, collDataIdx, v61, destY, destX, destY, v117, essai2); - if (v62 == -1) { - // CHECKME: This goto was to retLABEL_essai1... - goto retLABEL_essai2; + int tmpRouteIdx = GENIAL(collLineIdxRoute2, collDataIdxRoute2, curPosX, destY, destX, destY, idxRoute1, _testRoute2); + if (tmpRouteIdx == -1) { + useRoute2(idxRoute1, curRouteIdx); + return 1; } - v117 = v62; + idxRoute1 = tmpRouteIdx; if (_newPosX != -1 && _newPosY != -1) break; } - if (v61 < destX) - essai2[v117++].set(v61++, destY, DIR_RIGHT); + if (curPosX < destX) + _testRoute2[idxRoute1++].set(curPosX++, destY, DIR_RIGHT); else - essai2[v117++].set(v61--, destY, DIR_LEFT); + _testRoute2[idxRoute1++].set(curPosX--, destY, DIR_LEFT); } - if (v61 == destX) { - collLineIdx = -1; - essai2[v117].invalidate(); - goto retLABEL_essai2; + if (curPosX == destX) { + collLineIdxRoute2 = -1; + _testRoute2[idxRoute1].invalidate(); + useRoute2(idxRoute1, curRouteIdx); + return 1; } - if (collLineIdx <= _lastLine) + if (collLineIdxRoute2 <= _lastLine) break; - v54 = _newPosX; - v93 = _newPosY; - colResult = checkCollisionLine(_newPosX, _newPosY, &collDataIdx, &collLineIdx, 0, _lastLine); - if (colResult && collLineIdx <= _lastLine) + posXRoute2 = _newPosX; + posYRoute2 = _newPosY; + colResult = checkCollisionLine(_newPosX, _newPosY, &collDataIdxRoute2, &collLineIdxRoute2, 0, _lastLine); + if (colResult && collLineIdxRoute2 <= _lastLine) break; } - essai2[v117].invalidate(); + _testRoute2[idxRoute1].invalidate(); - if (!v136) { - if (a6 > foundLineIdx) { - if (essai0[0]._x != -1 && v142 > foundLineIdx && v140 <= v142 && collLineIdx <= v142 && a6 >= v142) { - _newLineIdx = v142; - _newLineDataIdx = v143; + if (!dummyLineFl) { + if (endLineIdx > foundLineIdx) { + if (_testRoute0[0]._x != -1 && collLineIdxRoute0 > foundLineIdx && collLineIdxRoute1 <= collLineIdxRoute0 && collLineIdxRoute2 <= collLineIdxRoute0 && endLineIdx >= collLineIdxRoute0) { + _newLineIdx = collLineIdxRoute0; + _newLineDataIdx = collDataIdxRoute0; int i = 0; do { - assert(v137 <= 8000); - _bestRoute[v137++] = essai0[i++]; - } while (essai0[i].isValid()); - _newRouteIdx = v137; + assert(curRouteIdx <= 8000); + _bestRoute[curRouteIdx++] = _testRoute0[i++]; + } while (_testRoute0[i].isValid()); + _newRouteIdx = curRouteIdx; return 2; } - if (essai1[0]._x != -1 && foundLineIdx < v140 && collLineIdx <= v140 && v142 <= v140 && a6 >= v140) { - _newLineIdx = v140; - _newLineDataIdx = v141; + if (_testRoute1[0]._x != -1 && foundLineIdx < collLineIdxRoute1 && collLineIdxRoute2 <= collLineIdxRoute1 && collLineIdxRoute0 <= collLineIdxRoute1 && endLineIdx >= collLineIdxRoute1) { + _newLineIdx = collLineIdxRoute1; + _newLineDataIdx = collDataIdxRoute1; int i = 0; do { - assert(v137 <= 8000); - _bestRoute[v137++] = essai1[i++]; - } while (essai1[i].isValid()); - _newRouteIdx = v137; + assert(curRouteIdx <= 8000); + _bestRoute[curRouteIdx++] = _testRoute1[i++]; + } while (_testRoute1[i].isValid()); + _newRouteIdx = curRouteIdx; return 2; } - if (essai2[0]._x != -1 && foundLineIdx < collLineIdx && v140 < collLineIdx && v142 < collLineIdx && a6 >= collLineIdx) { - _newLineIdx = collLineIdx; - _newLineDataIdx = collDataIdx; + if (_testRoute2[0]._x != -1 && foundLineIdx < collLineIdxRoute2 && collLineIdxRoute1 < collLineIdxRoute2 && collLineIdxRoute0 < collLineIdxRoute2 && endLineIdx >= collLineIdxRoute2) { + _newLineIdx = collLineIdxRoute2; + _newLineDataIdx = collDataIdxRoute2; int i = 0; do { - assert(v137 <= 8000); - _bestRoute[v137++] = essai2[i++]; - } while (essai2[i].isValid()); - _newRouteIdx = v137; + assert(curRouteIdx <= 8000); + _bestRoute[curRouteIdx++] = _testRoute2[i++]; + } while (_testRoute2[i].isValid()); + _newRouteIdx = curRouteIdx; return 2; } } - if (a6 < foundLineIdx) { - if (v142 == -1) - v142 = 1300; - if (v140 == -1) - v142 = 1300; - if (collLineIdx == -1) - v142 = 1300; - if (essai1[0]._x != -1 && v140 < foundLineIdx && collLineIdx >= v140 && v142 >= v140 && a6 <= v140) { - _newLineIdx = v140; - _newLineDataIdx = v141; + if (endLineIdx < foundLineIdx) { + if (collLineIdxRoute0 == -1) + collLineIdxRoute0 = INVALID_LINE_VALUE; + if (collLineIdxRoute1 == -1) + collLineIdxRoute0 = INVALID_LINE_VALUE; + if (collLineIdxRoute2 == -1) + collLineIdxRoute0 = INVALID_LINE_VALUE; + if (_testRoute1[0]._x != -1 && collLineIdxRoute1 < foundLineIdx && collLineIdxRoute2 >= collLineIdxRoute1 && collLineIdxRoute0 >= collLineIdxRoute1 && endLineIdx <= collLineIdxRoute1) { + _newLineIdx = collLineIdxRoute1; + _newLineDataIdx = collDataIdxRoute1; int i = 0; do { - assert(v137 <= 8000); - _bestRoute[v137++] = essai1[i++]; - } while (essai1[i].isValid()); - _newRouteIdx = v137; + assert(curRouteIdx <= 8000); + _bestRoute[curRouteIdx++] = _testRoute1[i++]; + } while (_testRoute1[i].isValid()); + _newRouteIdx = curRouteIdx; return 2; } - if (essai2[0]._x != -1 && foundLineIdx > collLineIdx && v140 >= collLineIdx && v142 >= collLineIdx && a6 <= collLineIdx) { - _newLineIdx = collLineIdx; - _newLineDataIdx = collDataIdx; + if (_testRoute2[0]._x != -1 && foundLineIdx > collLineIdxRoute2 && collLineIdxRoute1 >= collLineIdxRoute2 && collLineIdxRoute0 >= collLineIdxRoute2 && endLineIdx <= collLineIdxRoute2) { + _newLineIdx = collLineIdxRoute2; + _newLineDataIdx = collDataIdxRoute2; int i = 0; do { - assert(v137 <= 8000); - _bestRoute[v137++] = essai2[i++]; - } while (essai2[i].isValid()); - _newRouteIdx = v137; + assert(curRouteIdx <= 8000); + _bestRoute[curRouteIdx++] = _testRoute2[i++]; + } while (_testRoute2[i].isValid()); + _newRouteIdx = curRouteIdx; return 2; } // CHECKME: Checking essai0[0]._X might make more sense here? - if (essai1[0]._x != -1 && foundLineIdx > v142 && v140 >= v142 && collLineIdx >= v142 && a6 <= v142) { - _newLineIdx = v142; - _newLineDataIdx = v143; + if (_testRoute1[0]._x != -1 && foundLineIdx > collLineIdxRoute0 && collLineIdxRoute1 >= collLineIdxRoute0 && collLineIdxRoute2 >= collLineIdxRoute0 && endLineIdx <= collLineIdxRoute0) { + _newLineIdx = collLineIdxRoute0; + _newLineDataIdx = collDataIdxRoute0; int i = 0; do { - assert(v137 <= 8000); - _bestRoute[v137++] = essai0[i++]; - } while (essai0[i].isValid()); - _newRouteIdx = v137; + assert(curRouteIdx <= 8000); + _bestRoute[curRouteIdx++] = _testRoute0[i++]; + } while (_testRoute0[i].isValid()); + _newRouteIdx = curRouteIdx; return 2; } } } return 0; - -retLABEL_essai0: - if (v115) { - int i = 0; - do { - assert(v137 <= 8000); - _bestRoute[v137++] = essai0[i++]; - } while (essai0[i].isValid()); - } - _bestRoute[v137].invalidate(); - return 1; - -retLABEL_essai1: - if (v117) { - int i = 0; - do { - assert(v137 <= 8000); - _bestRoute[v137++] = essai1[i++]; - } while (essai1[i].isValid()); - } - _bestRoute[v137].invalidate(); - return 1; - -retLABEL_essai2: - if (v117) { - int i = 0; - do { - assert(v137 <= 8000); - _bestRoute[v137++] = essai2[i++]; - } while (essai2[i].isValid()); - } - _bestRoute[v137].invalidate(); - return 1; } RouteItem *LinesManager::cityMapCarRoute(int x1, int y1, int x2, int y2) { @@ -2045,124 +1989,118 @@ RouteItem *LinesManager::cityMapCarRoute(int x1, int y1, int x2, int y2) { int delta = 0; for (delta = 0; clipY2 + delta < _vm->_graphicsManager._maxY; delta++) { - if (checkCollisionLine(clipX2, clipY2 + delta, &arrDataIdx[5], &arrLineIdx[5], 0, _lastLine) && arrLineIdx[5] <= _lastLine) + if (checkCollisionLine(clipX2, clipY2 + delta, &arrDataIdx[DIR_DOWN], &arrLineIdx[DIR_DOWN], 0, _lastLine) && arrLineIdx[DIR_DOWN] <= _lastLine) break; - arrDataIdx[5] = 0; - arrLineIdx[5] = -1; + arrDataIdx[DIR_DOWN] = 0; + arrLineIdx[DIR_DOWN] = -1; } - arrDelta[5] = delta; + arrDelta[DIR_DOWN] = delta; for (delta = 0; clipY2 - delta > _vm->_graphicsManager._minY; delta++) { - if (checkCollisionLine(clipX2, clipY2 - delta , &arrDataIdx[1], &arrLineIdx[1], 0, _lastLine) && arrLineIdx[1] <= _lastLine) + if (checkCollisionLine(clipX2, clipY2 - delta , &arrDataIdx[DIR_UP], &arrLineIdx[DIR_UP], 0, _lastLine) && arrLineIdx[DIR_UP] <= _lastLine) break; - arrDataIdx[1] = 0; - arrLineIdx[1] = -1; - if (arrDelta[5] < delta && arrLineIdx[5] != -1) + arrDataIdx[DIR_UP] = 0; + arrLineIdx[DIR_UP] = -1; + if (arrDelta[DIR_DOWN] < delta && arrLineIdx[DIR_DOWN] != -1) break; } - arrDelta[1] = delta; + arrDelta[DIR_UP] = delta; for (delta = 0; clipX2 + delta < _vm->_graphicsManager._maxX; delta++) { - if (checkCollisionLine(clipX2 + delta, clipY2, &arrDataIdx[3], &arrLineIdx[3], 0, _lastLine) && arrLineIdx[3] <= _lastLine) + if (checkCollisionLine(clipX2 + delta, clipY2, &arrDataIdx[DIR_UP], &arrLineIdx[DIR_UP], 0, _lastLine) && arrLineIdx[DIR_UP] <= _lastLine) break; - arrDataIdx[3] = 0; - arrLineIdx[3] = -1; - if (arrDelta[1] <= delta && arrLineIdx[1] != -1) + arrDataIdx[DIR_UP] = 0; + arrLineIdx[DIR_UP] = -1; + if (arrDelta[DIR_UP] <= delta && arrLineIdx[DIR_UP] != -1) break; - if (arrDelta[5] <= delta && arrLineIdx[5] != -1) + if (arrDelta[DIR_DOWN] <= delta && arrLineIdx[DIR_DOWN] != -1) break; } - arrDelta[3] = delta; + arrDelta[DIR_UP] = delta; for (delta = 0; clipX2 - delta > _vm->_graphicsManager._minX; delta++) { - if (checkCollisionLine(clipX2 - delta, clipY2, &arrDataIdx[7], &arrLineIdx[7], 0, _lastLine) && arrLineIdx[7] <= _lastLine) - break; - arrDataIdx[7] = 0; - arrLineIdx[7] = -1; - if ((arrDelta[1] <= delta && arrLineIdx[1] != -1) || (arrDelta[3] <= delta && arrLineIdx[3] != -1) || (arrDelta[5] <= delta && arrLineIdx[5] != -1)) - break; - } - arrDelta[7] = delta; - - int v68 = 0; - int v69 = 0; - int v72 = 0; - int v73 = 0; - - if (arrLineIdx[1] == -1) - arrDelta[1] = 1300; - if (arrLineIdx[3] == -1) - arrDelta[3] = 1300; - if (arrLineIdx[5] == -1) - arrDelta[5] = 1300; - if (arrLineIdx[7] == -1) - arrDelta[7] = 1300; - if (arrLineIdx[1] != -1 || arrLineIdx[3] != -1 || arrLineIdx[5] != -1 || arrLineIdx[7] != -1) { - bool v23 = false; - if (arrLineIdx[5] != -1 && arrDelta[1] >= arrDelta[5] && arrDelta[3] >= arrDelta[5] && arrDelta[7] >= arrDelta[5]) { - v73 = arrLineIdx[5]; - v72 = arrDataIdx[5]; - v23 = true; - } - if (arrLineIdx[1] != -1 && !v23 && arrDelta[5] >= arrDelta[1] && arrDelta[3] >= arrDelta[1] && arrDelta[7] >= arrDelta[1]) { - v73 = arrLineIdx[1]; - v72 = arrDataIdx[1]; - v23 = true; - } - if (arrLineIdx[3] != -1 && !v23 && arrDelta[1] >= arrDelta[3] && arrDelta[5] >= arrDelta[3] && arrDelta[7] >= arrDelta[3]) { - v73 = arrLineIdx[3]; - v72 = arrDataIdx[3]; - v23 = true; - } - if (arrLineIdx[7] != -1 && !v23 && arrDelta[5] >= arrDelta[7] && arrDelta[3] >= arrDelta[7] && arrDelta[1] >= arrDelta[7]) { - v73 = arrLineIdx[7]; - v72 = arrDataIdx[7]; - } - for (int v24 = 0; v24 <= 8; v24++) { - arrLineIdx[v24] = -1; - arrDataIdx[v24] = 0; - arrDelta[v24] = 1300; - } - if (checkCollisionLine(x1, y1, &arrDataIdx[1], &arrLineIdx[1], 0, _lastLine)) { - v69 = arrLineIdx[1]; - v68 = arrDataIdx[1]; - } else if (checkCollisionLine(x1, y1, &arrDataIdx[1], &arrLineIdx[1], 0, _linesNumb)) { - int v27 = 0; - int v28; + if (checkCollisionLine(clipX2 - delta, clipY2, &arrDataIdx[DIR_LEFT], &arrLineIdx[DIR_LEFT], 0, _lastLine) && arrLineIdx[DIR_LEFT] <= _lastLine) + break; + arrDataIdx[DIR_LEFT] = 0; + arrLineIdx[DIR_LEFT] = -1; + if ((arrDelta[DIR_UP] <= delta && arrLineIdx[DIR_UP] != -1) || (arrDelta[DIR_UP] <= delta && arrLineIdx[DIR_UP] != -1) || (arrDelta[DIR_DOWN] <= delta && arrLineIdx[DIR_DOWN] != -1)) + break; + } + arrDelta[DIR_LEFT] = delta; + + int curRouteDataIdx = 0; + int curRouteLineIdx = 0; + int curLineDataIdx = 0; + int curLineIdx = 0; + + if (arrLineIdx[DIR_UP] == -1) + arrDelta[DIR_UP] = INVALID_LINE_VALUE; + if (arrLineIdx[DIR_UP] == -1) + arrDelta[DIR_UP] = INVALID_LINE_VALUE; + if (arrLineIdx[DIR_DOWN] == -1) + arrDelta[DIR_DOWN] = INVALID_LINE_VALUE; + if (arrLineIdx[DIR_LEFT] == -1) + arrDelta[DIR_LEFT] = INVALID_LINE_VALUE; + if (arrLineIdx[DIR_UP] != -1 || arrLineIdx[DIR_UP] != -1 || arrLineIdx[DIR_DOWN] != -1 || arrLineIdx[DIR_LEFT] != -1) { + if (arrLineIdx[DIR_DOWN] != -1 && arrDelta[DIR_UP] >= arrDelta[DIR_DOWN] && arrDelta[DIR_UP] >= arrDelta[DIR_DOWN] && arrDelta[DIR_LEFT] >= arrDelta[DIR_DOWN]) { + curLineIdx = arrLineIdx[DIR_DOWN]; + curLineDataIdx = arrDataIdx[DIR_DOWN]; + } else if (arrLineIdx[DIR_UP] != -1 && arrDelta[DIR_DOWN] >= arrDelta[DIR_UP] && arrDelta[DIR_UP] >= arrDelta[DIR_UP] && arrDelta[DIR_LEFT] >= arrDelta[DIR_UP]) { + curLineIdx = arrLineIdx[DIR_UP]; + curLineDataIdx = arrDataIdx[DIR_UP]; + } else if (arrLineIdx[DIR_UP] != -1 && arrDelta[DIR_UP] >= arrDelta[DIR_UP] && arrDelta[DIR_DOWN] >= arrDelta[DIR_UP] && arrDelta[DIR_LEFT] >= arrDelta[DIR_UP]) { + curLineIdx = arrLineIdx[DIR_UP]; + curLineDataIdx = arrDataIdx[DIR_UP]; + } else if (arrLineIdx[DIR_LEFT] != -1 && arrDelta[DIR_DOWN] >= arrDelta[DIR_LEFT] && arrDelta[DIR_UP] >= arrDelta[DIR_LEFT] && arrDelta[DIR_UP] >= arrDelta[DIR_LEFT]) { + curLineIdx = arrLineIdx[DIR_LEFT]; + curLineDataIdx = arrDataIdx[DIR_LEFT]; + } + + for (int i = 0; i <= 8; i++) { + arrLineIdx[i] = -1; + arrDataIdx[i] = 0; + arrDelta[i] = INVALID_LINE_VALUE; + } + if (checkCollisionLine(x1, y1, &arrDataIdx[DIR_UP], &arrLineIdx[DIR_UP], 0, _lastLine)) { + curRouteLineIdx = arrLineIdx[DIR_UP]; + curRouteDataIdx = arrDataIdx[DIR_UP]; + } else if (checkCollisionLine(x1, y1, &arrDataIdx[DIR_UP], &arrLineIdx[DIR_UP], 0, _linesNumb)) { + int curRouteIdx = 0; + int curRouteX; for (;;) { - v28 = essai2[v27]._x; - int v29 = essai2[v27]._y; - Directions v66 = essai2[v27]._dir; - v27++; + curRouteX = _testRoute2[curRouteIdx]._x; + int curRouteY = _testRoute2[curRouteIdx]._y; + Directions v66 = _testRoute2[curRouteIdx]._dir; + curRouteIdx++; - if (checkCollisionLine(v28, v29, &arrDataIdx[1], &arrLineIdx[1], 0, _lastLine)) + if (checkCollisionLine(curRouteX, curRouteY, &arrDataIdx[DIR_UP], &arrLineIdx[DIR_UP], 0, _lastLine)) break; - _bestRoute[superRouteIdx].set(v28, v29, v66); + _bestRoute[superRouteIdx].set(curRouteX, curRouteY, v66); - essai0[superRouteIdx].set(v28, v29, v66); + _testRoute0[superRouteIdx].set(curRouteX, curRouteY, v66); superRouteIdx++; - if (v28 == -1) + if (curRouteX == -1) break;; } - if (v28 != -1) { - v69 = arrLineIdx[1]; - v68 = arrDataIdx[1]; + if (curRouteX != -1) { + curRouteLineIdx = arrLineIdx[DIR_UP]; + curRouteDataIdx = arrDataIdx[DIR_UP]; } } else { - v69 = 1; - v68 = 1; + curRouteLineIdx = 1; + curRouteDataIdx = 1; superRouteIdx = 0; } bool loopFl = true; while (loopFl) { loopFl = false; - if (v69 < v73) { - superRouteIdx = _lineItem[v69].appendToRouteInc(v68, _lineItem[v69]._lineDataEndIdx - 2, _bestRoute, superRouteIdx); - for (int j = v69 + 1; j < v73; ++j) { - if (PLAN_TEST(_lineItem[j]._lineData[0], _lineItem[j]._lineData[1], superRouteIdx, j, v73)) { - v69 = _newLineIdx; - v68 = _newLineDataIdx; + if (curRouteLineIdx < curLineIdx) { + superRouteIdx = _lineItem[curRouteLineIdx].appendToRouteInc(curRouteDataIdx, _lineItem[curRouteLineIdx]._lineDataEndIdx - 2, _bestRoute, superRouteIdx); + for (int j = curRouteLineIdx + 1; j < curLineIdx; ++j) { + if (PLAN_TEST(_lineItem[j]._lineData[0], _lineItem[j]._lineData[1], superRouteIdx, j, curLineIdx)) { + curRouteLineIdx = _newLineIdx; + curRouteDataIdx = _newLineDataIdx; superRouteIdx = _newRouteIdx; loopFl = true; break; @@ -2173,15 +2111,15 @@ RouteItem *LinesManager::cityMapCarRoute(int x1, int y1, int x2, int y2) { } if (loopFl) continue; - v68 = 0; - v69 = v73; + curRouteDataIdx = 0; + curRouteLineIdx = curLineIdx; } - if (v69 > v73) { - superRouteIdx = _lineItem[v69].appendToRouteDec(v68, 0, _bestRoute, superRouteIdx); - for (int l = v69 - 1; l > v73; --l) { - if (PLAN_TEST(_lineItem[l]._lineData[2 * _lineItem[l]._lineDataEndIdx - 2], _lineItem[l]._lineData[2 * _lineItem[l]._lineDataEndIdx - 1], superRouteIdx, l, v73)) { - v69 = _newLineIdx; - v68 = _newLineDataIdx; + if (curRouteLineIdx > curLineIdx) { + superRouteIdx = _lineItem[curRouteLineIdx].appendToRouteDec(curRouteDataIdx, 0, _bestRoute, superRouteIdx); + for (int l = curRouteLineIdx - 1; l > curLineIdx; --l) { + if (PLAN_TEST(_lineItem[l]._lineData[2 * _lineItem[l]._lineDataEndIdx - 2], _lineItem[l]._lineData[2 * _lineItem[l]._lineDataEndIdx - 1], superRouteIdx, l, curLineIdx)) { + curRouteLineIdx = _newLineIdx; + curRouteDataIdx = _newLineDataIdx; superRouteIdx = _newRouteIdx; loopFl = true; break; @@ -2192,14 +2130,14 @@ RouteItem *LinesManager::cityMapCarRoute(int x1, int y1, int x2, int y2) { if (loopFl) continue; - v68 = _lineItem[v73]._lineDataEndIdx - 1; - v69 = v73; + curRouteDataIdx = _lineItem[curLineIdx]._lineDataEndIdx - 1; + curRouteLineIdx = curLineIdx; } - if (v69 == v73) { - if (v68 <= v72) { - superRouteIdx = _lineItem[v73].appendToRouteInc(v68, v72, _bestRoute, superRouteIdx); + if (curRouteLineIdx == curLineIdx) { + if (curRouteDataIdx <= curLineDataIdx) { + superRouteIdx = _lineItem[curLineIdx].appendToRouteInc(curRouteDataIdx, curLineDataIdx, _bestRoute, superRouteIdx); } else { - superRouteIdx = _lineItem[v73].appendToRouteDec(v68, v72, _bestRoute, superRouteIdx); + superRouteIdx = _lineItem[curLineIdx].appendToRouteDec(curRouteDataIdx, curLineDataIdx, _bestRoute, superRouteIdx); } } } @@ -2212,9 +2150,6 @@ RouteItem *LinesManager::cityMapCarRoute(int x1, int y1, int x2, int y2) { } bool LinesManager::checkSmoothMove(int fromX, int fromY, int destX, int destY) { - int foundLineIdx; - int foundDataIdx; - int distX = abs(fromX - destX) + 1; int distY = abs(fromY - destY) + 1; if (distX > distY) @@ -2236,6 +2171,8 @@ bool LinesManager::checkSmoothMove(int fromX, int fromY, int destX, int destY) { if (distY + 1 > 0) { int stepCount = 0; + int foundLineIdx; + int foundDataIdx; while (!checkCollisionLine(newPosX, newPosY, &foundDataIdx, &foundLineIdx, 0, _linesNumb) || foundLineIdx > _lastLine) { smoothPosX += stepX; smoothPosY += stepY; @@ -2258,20 +2195,20 @@ bool LinesManager::makeSmoothMove(int fromX, int fromY, int destX, int destY) { int smoothIdx = 0; int stepCount = 0; while (curX > destX && destY > curY) { - int v25 = _vm->_globals._hopkinsItem[hopkinsIdx]._speedX; - int v40 = _vm->_globals._hopkinsItem[hopkinsIdx]._speedY; + int realSpeedX = _vm->_globals._hopkinsItem[hopkinsIdx]._speedX; + int realSpeedY = _vm->_globals._hopkinsItem[hopkinsIdx]._speedY; int spriteSize = _vm->_globals._spriteSize[curY]; if (spriteSize < 0) { - v25 = _vm->_graphicsManager.zoomOut(v25, -spriteSize); - v40 = _vm->_graphicsManager.zoomOut(v40, -spriteSize); + realSpeedX = _vm->_graphicsManager.zoomOut(realSpeedX, -spriteSize); + realSpeedY = _vm->_graphicsManager.zoomOut(realSpeedY, -spriteSize); } else if (spriteSize > 0) { - v25 = _vm->_graphicsManager.zoomIn(v25, spriteSize); - v40 = _vm->_graphicsManager.zoomIn(v40, spriteSize); + realSpeedX = _vm->_graphicsManager.zoomIn(realSpeedX, spriteSize); + realSpeedY = _vm->_graphicsManager.zoomIn(realSpeedY, spriteSize); } - for (int i = 0; i < v25; i++) { + for (int i = 0; i < realSpeedX; i++) { --curX; _smoothRoute[smoothIdx]._posX = curX; - if (curY != curY + v40) + if (curY != curY + realSpeedY) curY++; _smoothRoute[smoothIdx]._posY = curY; smoothIdx++; @@ -2292,20 +2229,20 @@ bool LinesManager::makeSmoothMove(int fromX, int fromY, int destX, int destY) { int smoothIdx = 0; int stepCount = 0; while (curX < destX && destY > curY) { - int v14 = _vm->_globals._hopkinsItem[hopkinsIdx]._speedX; - int v39 = _vm->_globals._hopkinsItem[hopkinsIdx]._speedY; + int realSpeedX = _vm->_globals._hopkinsItem[hopkinsIdx]._speedX; + int realSpeedY = _vm->_globals._hopkinsItem[hopkinsIdx]._speedY; int spriteSize = _vm->_globals._spriteSize[curY]; if (spriteSize < 0) { - v14 = _vm->_graphicsManager.zoomOut(v14, -spriteSize); - v39 = _vm->_graphicsManager.zoomOut(v39, -spriteSize); + realSpeedX = _vm->_graphicsManager.zoomOut(realSpeedX, -spriteSize); + realSpeedY = _vm->_graphicsManager.zoomOut(realSpeedY, -spriteSize); } else if (spriteSize > 0) { - v14 = _vm->_graphicsManager.zoomIn(v14, spriteSize); - v39 = _vm->_graphicsManager.zoomIn(v39, spriteSize); + realSpeedX = _vm->_graphicsManager.zoomIn(realSpeedX, spriteSize); + realSpeedY = _vm->_graphicsManager.zoomIn(realSpeedY, spriteSize); } - for (int i = 0; i < v14; i++) { + for (int i = 0; i < realSpeedX; i++) { ++curX; _smoothRoute[smoothIdx]._posX = curX; - if (curY != curY + v39) + if (curY != curY + realSpeedY) curY++; _smoothRoute[smoothIdx]._posY = curY; smoothIdx++; @@ -2326,13 +2263,13 @@ bool LinesManager::makeSmoothMove(int fromX, int fromY, int destX, int destY) { int smoothIdx = 0; int stepCount = 0; while (curX > destX && destY < curY) { - int v11 = _vm->_graphicsManager.zoomOut(_vm->_globals._hopkinsItem[hopkinsIdx]._speedX, 25); - int v38 = _vm->_graphicsManager.zoomOut(_vm->_globals._hopkinsItem[hopkinsIdx]._speedY, 25); + int realSpeedX = _vm->_graphicsManager.zoomOut(_vm->_globals._hopkinsItem[hopkinsIdx]._speedX, 25); + int realSpeedY = _vm->_graphicsManager.zoomOut(_vm->_globals._hopkinsItem[hopkinsIdx]._speedY, 25); int oldY = curY; - for (int v12 = 0; v12 < v11; v12++) { + for (int i = 0; i < realSpeedX; i++) { --curX; _smoothRoute[smoothIdx]._posX = curX; - if ((uint16)curY != (uint16)oldY + v38) + if ((uint16)curY != (uint16)oldY + realSpeedY) curY--; _smoothRoute[smoothIdx]._posY = curY; smoothIdx++; @@ -2354,12 +2291,12 @@ bool LinesManager::makeSmoothMove(int fromX, int fromY, int destX, int destY) { int stepCount = 0; while (curX < destX && destY < curY) { int oldY = curY; - int v7 = _vm->_graphicsManager.zoomOut(_vm->_globals._hopkinsItem[hopkinsIdx]._speedX, 25); - int v37 = _vm->_graphicsManager.zoomOut(_vm->_globals._hopkinsItem[hopkinsIdx]._speedY, 25); - for (int i = 0; i < v7; i++) { + int realSpeedX = _vm->_graphicsManager.zoomOut(_vm->_globals._hopkinsItem[hopkinsIdx]._speedX, 25); + int realSpeedY = _vm->_graphicsManager.zoomOut(_vm->_globals._hopkinsItem[hopkinsIdx]._speedY, 25); + for (int i = 0; i < realSpeedX; i++) { ++curX; _smoothRoute[smoothIdx]._posX = curX; - if ((uint16)curY != (uint16)oldY + v37) + if ((uint16)curY != (uint16)oldY + realSpeedY) curY--; _smoothRoute[smoothIdx]._posY = curY; smoothIdx++; @@ -2380,101 +2317,102 @@ bool LinesManager::makeSmoothMove(int fromX, int fromY, int destX, int destY) { return true; } -bool LinesManager::PLAN_TEST(int paramX, int paramY, int a3, int a4, int a5) { - int v42; - int v43; - int v44; - int v45; - int dataIdxTestUp; - int dataIdxTestDown; - int dataIdxTestLeft; - int dataIdxTestRight; +bool LinesManager::PLAN_TEST(int paramX, int paramY, int superRouteIdx, int paramStartLineIdx, int paramEndLineIdx) { + int sideTestUp; + int sideTestDown; + int sideTestLeft; + int sideTestRight; int lineIdxTestUp; int lineIdxTestDown; int lineIdxTestLeft; int lineIdxTestRight; + int dataIdxTestUp; + int dataIdxTestDown; + int dataIdxTestLeft; + int dataIdxTestRight; - int idxTestUp = testLine(paramX, paramY - 2, &v42, &lineIdxTestUp, &dataIdxTestUp); - int idxTestDown = testLine(paramX, paramY + 2, &v43, &lineIdxTestDown, &dataIdxTestDown); - int idxTestLeft = testLine(paramX - 2, paramY, &v44, &lineIdxTestLeft, &dataIdxTestLeft); - int idxTestRight = testLine(paramX + 2, paramY, &v45, &lineIdxTestRight, &dataIdxTestRight); + int idxTestUp = testLine(paramX, paramY - 2, &sideTestUp, &lineIdxTestUp, &dataIdxTestUp); + int idxTestDown = testLine(paramX, paramY + 2, &sideTestDown, &lineIdxTestDown, &dataIdxTestDown); + int idxTestLeft = testLine(paramX - 2, paramY, &sideTestLeft, &lineIdxTestLeft, &dataIdxTestLeft); + int idxTestRight = testLine(paramX + 2, paramY, &sideTestRight, &lineIdxTestRight, &dataIdxTestRight); if (idxTestUp == -1 && idxTestDown == -1 && idxTestLeft == -1 && idxTestRight == -1) return false; - int v8; - if (a4 == -1 || a5 == -1) { + // Direction: 1 = Up, 2 = Down, 3 = Left, 4 = Right + int direction; + if (paramStartLineIdx == -1 || paramEndLineIdx == -1) { if (idxTestUp != -1) - v8 = 1; + direction = 1; else if (idxTestDown != -1) - v8 = 2; + direction = 2; else if (idxTestLeft != -1) - v8 = 3; + direction = 3; else if (idxTestRight != -1) - v8 = 4; + direction = 4; else return false; } else { - int v28 = 100; - int v7 = 100; - int v35 = 100; - int v27 = 100; - int v36 = abs(a4 - a5); + int stepCountUp = 100; + int stepCountDown = 100; + int stepCountLeft = 100; + int stepCountRight = 100; + int paramStepCount = abs(paramStartLineIdx - paramEndLineIdx); if (idxTestUp != -1) { - v28 = abs(lineIdxTestUp - a5); + stepCountUp = abs(lineIdxTestUp - paramEndLineIdx); } if (idxTestDown != -1) { - v7 = abs(lineIdxTestDown - a5); + stepCountDown = abs(lineIdxTestDown - paramEndLineIdx); } if (idxTestLeft != -1) { - v35 = abs(lineIdxTestLeft - a5); + stepCountLeft = abs(lineIdxTestLeft - paramEndLineIdx); } if (idxTestRight != -1) { - v27 = abs(lineIdxTestRight - a5); + stepCountRight = abs(lineIdxTestRight - paramEndLineIdx); } - if (v28 < v36 && v28 <= v7 && v28 <= v35 && v28 <= v27) - v8 = 1; - else if (v36 > v7 && v28 >= v7 && v35 >= v7 && v27 >= v7) - v8 = 2; - else if (v35 < v36 && v35 <= v28 && v35 <= v7 && v35 <= v27) - v8 = 3; - else if (v27 < v36 && v27 <= v28 && v27 <= v7 && v27 <= v35) - v8 = 4; + if (stepCountUp < paramStepCount && stepCountUp <= stepCountDown && stepCountUp <= stepCountLeft && stepCountUp <= stepCountRight) + direction = 1; + else if (paramStepCount > stepCountDown && stepCountUp >= stepCountDown && stepCountLeft >= stepCountDown && stepCountRight >= stepCountDown) + direction = 2; + else if (stepCountLeft < paramStepCount && stepCountLeft <= stepCountUp && stepCountLeft <= stepCountDown && stepCountLeft <= stepCountRight) + direction = 3; + else if (stepCountRight < paramStepCount && stepCountRight <= stepCountUp && stepCountRight <= stepCountDown && stepCountRight <= stepCountLeft) + direction = 4; else return false; } - int v33 = 0; + int sideTest = 0; int idxTest = 0; - if (v8 == 1) { + if (direction == 1) { idxTest = idxTestUp; - v33 = v42; + sideTest = sideTestUp; _newLineIdx = lineIdxTestUp; _newLineDataIdx = dataIdxTestUp; - } else if (v8 == 2) { + } else if (direction == 2) { idxTest = idxTestDown; - v33 = v43; + sideTest = sideTestDown; _newLineIdx = lineIdxTestDown; _newLineDataIdx = dataIdxTestDown; - } else if (v8 == 3) { + } else if (direction == 3) { idxTest = idxTestLeft; - v33 = v44; + sideTest = sideTestLeft; _newLineIdx = lineIdxTestLeft; _newLineDataIdx = dataIdxTestLeft; - } else if (v8 == 4) { + } else if (direction == 4) { idxTest = idxTestRight; - v33 = v45; + sideTest = sideTestRight; _newLineIdx = lineIdxTestRight; _newLineDataIdx = dataIdxTestRight; } - int superRouteIdx = a3; - if (v33 == 1) { - superRouteIdx = _lineItem[idxTest].appendToRouteInc(0, -1, _bestRoute, superRouteIdx); - } else if (v33 == 2) { - superRouteIdx = _lineItem[idxTest].appendToRouteDec(-1, -1, _bestRoute, superRouteIdx); + int routeIdx = superRouteIdx; + if (sideTest == 1) { + routeIdx = _lineItem[idxTest].appendToRouteInc(0, -1, _bestRoute, routeIdx); + } else if (sideTest == 2) { + routeIdx = _lineItem[idxTest].appendToRouteDec(-1, -1, _bestRoute, routeIdx); } - _newRouteIdx = superRouteIdx; + _newRouteIdx = routeIdx; return true; } @@ -2690,31 +2628,29 @@ int LinesManager::checkCollision(int xp, int yp) { int yMin = yp - 4; do { - int16 *dataP = _zoneLine[curZoneLineIdx]._zoneData; + LigneZoneItem *curZoneLine = &_zoneLine[curZoneLineIdx]; + int16 *dataP = curZoneLine->_zoneData; if (dataP != (int16 *)g_PTRNUL) { - int count = _zoneLine[curZoneLineIdx]._count; - int v1 = dataP[0]; - int v2 = dataP[1]; - int v3 = dataP[count * 2 - 2]; - int v4 = dataP[count * 2 - 1]; + int count = curZoneLine->_count; + int startX = dataP[0]; + int startY = dataP[1]; + int destX = dataP[count * 2 - 2]; + int destY = dataP[count * 2 - 1]; bool flag = true; - if (v1 < v3 && (xMax < v1 || xMin > v3)) - flag = false; - if (v1 >= v3 && (xMin > v1 || xMax < v3)) - flag = false; - if (v2 < v4 && (yMax < v2 || yMin > v4)) - flag = false; - if (v2 >= v4 && (yMin > v2 || yMax < v4)) + if ((startX < destX && (xMax < startX || xMin > destX)) || + (startX >= destX && (xMin > startX || xMax < destX)) || + (startY < destY && (yMax < startY || yMin > destY)) || + (startY >= destY && (yMin > startY || yMax < destY))) flag = false; - if (flag && _zoneLine[curZoneLineIdx]._count > 0) { + if (flag && curZoneLine->_count > 0) { for (int i = 0; i < count; ++i) { int xCheck = *dataP++; int yCheck = *dataP++; if ((xp == xCheck || (xp + 1) == xCheck) && (yp == yCheck)) - return _zoneLine[curZoneLineIdx]._bobZoneIdx; + return curZoneLine->_bobZoneIdx; } } } @@ -2727,14 +2663,15 @@ int LinesManager::checkCollision(int xp, int yp) { // Square Zone void LinesManager::CARRE_ZONE() { for (int idx = 0; idx < 100; ++idx) { - _squareZone[idx]._enabledFl = false; - _squareZone[idx]._squareZoneFl = false; - _squareZone[idx]._left = 1280; - _squareZone[idx]._right = 0; - _squareZone[idx]._top = 460; - _squareZone[idx]._bottom = 0; - _squareZone[idx]._minZoneLineIdx = 401; - _squareZone[idx]._maxZoneLineIdx = 0; + SquareZoneItem *curZone = &_squareZone[idx]; + curZone->_enabledFl = false; + curZone->_squareZoneFl = false; + curZone->_left = 1280; + curZone->_right = 0; + curZone->_top = 460; + curZone->_bottom = 0; + curZone->_minZoneLineIdx = 401; + curZone->_maxZoneLineIdx = 0; } for (int idx = 0; idx < MAX_LINES; ++idx) { @@ -2742,25 +2679,25 @@ void LinesManager::CARRE_ZONE() { if (dataP == (int16 *)g_PTRNUL) continue; - int carreZoneId = _zoneLine[idx]._bobZoneIdx; - _squareZone[carreZoneId]._enabledFl = true; - if (_squareZone[carreZoneId]._maxZoneLineIdx < idx) - _squareZone[carreZoneId]._maxZoneLineIdx = idx; - if (_squareZone[carreZoneId]._minZoneLineIdx > idx) - _squareZone[carreZoneId]._minZoneLineIdx = idx; + SquareZoneItem *curZone = &_squareZone[_zoneLine[idx]._bobZoneIdx]; + curZone->_enabledFl = true; + if (curZone->_maxZoneLineIdx < idx) + curZone->_maxZoneLineIdx = idx; + if (curZone->_minZoneLineIdx > idx) + curZone->_minZoneLineIdx = idx; for (int i = 0; i < _zoneLine[idx]._count; i++) { int zoneX = *dataP++; int zoneY = *dataP++; - if (_squareZone[carreZoneId]._left >= zoneX) - _squareZone[carreZoneId]._left = zoneX; - if (_squareZone[carreZoneId]._right <= zoneX) - _squareZone[carreZoneId]._right = zoneX; - if (_squareZone[carreZoneId]._top >= zoneY) - _squareZone[carreZoneId]._top = zoneY; - if (_squareZone[carreZoneId]._bottom <= zoneY) - _squareZone[carreZoneId]._bottom = zoneY; + if (curZone->_left >= zoneX) + curZone->_left = zoneX; + if (curZone->_right <= zoneX) + curZone->_right = zoneX; + if (curZone->_top >= zoneY) + curZone->_top = zoneY; + if (curZone->_bottom <= zoneY) + curZone->_bottom = zoneY; } } @@ -2779,9 +2716,9 @@ void LinesManager::clearAll() { ZONEP[idx]._spriteIndex = 0; } - essai0 = (RouteItem *)g_PTRNUL; - essai1 = (RouteItem *)g_PTRNUL; - essai2 = (RouteItem *)g_PTRNUL; + _testRoute0 = (RouteItem *)g_PTRNUL; + _testRoute1 = (RouteItem *)g_PTRNUL; + _testRoute2 = (RouteItem *)g_PTRNUL; _lineBuf = (int16 *)g_PTRNUL; _route = (RouteItem *)g_PTRNUL; @@ -2801,15 +2738,15 @@ void LinesManager::clearAll() { _squareZone[idx]._enabledFl = false; // FIXME: Delete these somewhere - _vm->_linesManager.essai0 = new RouteItem[8334]; - _vm->_linesManager.essai1 = new RouteItem[8334]; - _vm->_linesManager.essai2 = new RouteItem[8334]; - if (!_vm->_linesManager.essai0) - _vm->_linesManager.essai0 = (RouteItem*)g_PTRNUL; - if (!_vm->_linesManager.essai1) - _vm->_linesManager.essai1 = (RouteItem*)g_PTRNUL; - if (!_vm->_linesManager.essai2) - _vm->_linesManager.essai2 = (RouteItem*)g_PTRNUL; + _vm->_linesManager._testRoute0 = new RouteItem[8334]; + _vm->_linesManager._testRoute1 = new RouteItem[8334]; + _vm->_linesManager._testRoute2 = new RouteItem[8334]; + if (!_vm->_linesManager._testRoute0) + _vm->_linesManager._testRoute0 = (RouteItem*)g_PTRNUL; + if (!_vm->_linesManager._testRoute1) + _vm->_linesManager._testRoute1 = (RouteItem*)g_PTRNUL; + if (!_vm->_linesManager._testRoute2) + _vm->_linesManager._testRoute2 = (RouteItem*)g_PTRNUL; _largeBuf = _vm->_globals.allocMemory(10000); _vm->_linesManager._lineBuf = (int16 *)(_largeBuf); diff --git a/engines/hopkins/lines.h b/engines/hopkins/lines.h index 3d07aea91c..5d31aa6fd6 100644 --- a/engines/hopkins/lines.h +++ b/engines/hopkins/lines.h @@ -38,6 +38,8 @@ struct LigneZoneItem { int16 *_zoneData; }; +#define INVALID_LINE_VALUE 1300 + struct RouteItem; struct LigneItem { @@ -121,8 +123,8 @@ private: int _newPosY; byte *_largeBuf; - RouteItem *essai0; - RouteItem *essai1; + RouteItem *_testRoute0; + RouteItem *_testRoute1; int16 *_lineBuf; LigneItem _lineItem[400]; RouteItem _bestRoute[8001]; @@ -134,19 +136,22 @@ private: bool checkCollisionLine(int xp, int yp, int *foundDataIdx, int *foundLineIdx, int startLineIdx, int endLineIdx); bool checkSmoothMove(int fromX, int fromY, int destX, int destY); bool makeSmoothMove(int fromX, int fromY, int destX, int destY); - int characterRoute(int fromX, int fromY, int destX, int destY, int a5, int a6, int a7); + int characterRoute(int fromX, int fromY, int destX, int destY, int startLineIdx, int endLineIdx, int routeIdx); int testLine(int paramX, int paramY, int *a3, int *foundLineIdx, int *foundDataIdx); + void _useRoute0(int idx, int curRouteIdx); + void useRoute1(int idx, int curRouteIdx); + void useRoute2(int idx, int curRouteIdx); int CALC_PROPRE(int idx); - int CONTOURNE1(int a1, int a2, int a3, int a4, int a5, RouteItem *route, int a8, int a9); - int CONTOURNE(int a1, int a2, int a3, int a4, int a5, RouteItem *route); - bool MIRACLE(int fromX, int fromY, int a3, int a4, int a5); - int GENIAL(int lineIdx, int dataIdx, int a3, int a4, int a5, int a6, int a7, RouteItem *route); - bool PLAN_TEST(int paramX, int paramY, int a3, int a4, int a5); + int CONTOURNE(int lineIdx, int lineDataIdx, int routeIdx, int destLineIdx, int destLineDataIdx, RouteItem *route); + int CONTOURNE1(int lineIdx, int lineDataIdx, int routeIdx, int destLineIdx, int destLineDataIdx, RouteItem *route, int a8, int a9); + bool MIRACLE(int fromX, int fromY, int lineIdx, int destLineIdx, int routeIdx); + int GENIAL(int lineIdx, int dataIdx, int fromX, int fromY, int destX, int destY, int routerIdx, RouteItem *route); + bool PLAN_TEST(int paramX, int paramY, int superRouteIdx, int paramStartLineIdx, int paramEndLineIdx); public: RouteItem *_route; - RouteItem *essai2; + RouteItem *_testRoute2; int BOBZONE[105]; bool BOBZONE_FLAG[105]; @@ -159,9 +164,9 @@ public: void setMaxLineIdx(int idx); int checkInventoryHotspots(int posX, int posY); - void addZoneLine(int idx, int a2, int a3, int a4, int a5, int bobZoneIdx); + void addZoneLine(int idx, int fromX, int fromY, int destX, int destY, int bobZoneIdx); void loadLines(const Common::String &file); - void addLine(int idx, Directions direction, int a3, int a4, int a5, int a6); + void addLine(int lineIdx, Directions direction, int fromX, int fromY, int destX, int destY); void initRoute(); RouteItem *cityMapCarRoute(int x1, int y1, int x2, int y2); void clearAllZones(); diff --git a/engines/hopkins/menu.cpp b/engines/hopkins/menu.cpp index 20b531ff7e..e2e4859c55 100644 --- a/engines/hopkins/menu.cpp +++ b/engines/hopkins/menu.cpp @@ -125,7 +125,7 @@ int MenuManager::menu() { _vm->_graphicsManager.fastDisplay(spriteData, 230, 322, frameIndex[2] + 4); _vm->_graphicsManager.fastDisplay(spriteData, 230, 354, frameIndex[3] + 6); _vm->_graphicsManager.fastDisplay(spriteData, 230, 386, frameIndex[4] + 8); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); if (_vm->_eventsManager.getMouseButton() == 1 && menuIndex != MENU_NONE) selectionMade = true; @@ -133,7 +133,7 @@ int MenuManager::menu() { if (menuIndex > MENU_NONE) { _vm->_graphicsManager.fastDisplay(spriteData, 230, 259 + 32 * (menuIndex - 1), 10 + (menuIndex - 1)); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); _vm->_eventsManager.delay(200); } diff --git a/engines/hopkins/objects.cpp b/engines/hopkins/objects.cpp index 26c0d1c2a8..4c1b5949dc 100644 --- a/engines/hopkins/objects.cpp +++ b/engines/hopkins/objects.cpp @@ -278,7 +278,7 @@ void ObjectsManager::addObject(int objIndex) { for (;;) { ++arrIndex; if ((!_vm->_globals._inventory[arrIndex]) || (arrIndex == 32)) - break;; + break; } _vm->_globals._inventory[arrIndex] = objIndex; @@ -620,7 +620,7 @@ void ObjectsManager::hideBob(int idx) { _bob[idx].field0++; } -void ObjectsManager::BOB_OFFSET(int idx, int offset) { +void ObjectsManager::setBobOffset(int idx, int offset) { _bob[idx]._oldX2 = offset; } @@ -838,9 +838,9 @@ void ObjectsManager::computeSprite(int idx) { offY = getOffsetY(spr->_spriteData, spr->_spriteIndex, false); } - int tmpX = spr->field12 + offX; + int tmpX = spr->_deltaX + offX; int deltaX = tmpX; - int tmpY = spr->field14 + offY; + int tmpY = spr->_deltaY + offY; int deltaY = tmpY; int zoomPercent = 0; int reducePercent = 0; @@ -927,10 +927,7 @@ void ObjectsManager::displayBobAnim() { continue; _bob[idx].field1C = false; - int v1 = _bob[idx].field20; - if (v1 == -1) - v1 = 50; - if (_bob[idx]._animData == g_PTRNUL || _bob[idx]._disabledAnimationFl || v1 <= 0) { + if (_bob[idx]._animData == g_PTRNUL || _bob[idx]._disabledAnimationFl || _bob[idx].field20 == 0 || _bob[idx].field20 < -1) { if (_bob[idx].field1E == 1 || _bob[idx].field1E == 2) _bob[idx].field1C = true; continue; @@ -964,11 +961,9 @@ void ObjectsManager::displayBobAnim() { _bob[idx]._flipFl = (dataPtr[2 * dataIdx + 9] != 0); _bob[idx]._animDataIdx += 5; - int v5 = _bob[idx].field12; - if (v5 > 0) { - int v6 = v5 / _vm->_globals._speed; - _bob[idx].field12 = v5 / _vm->_globals._speed; - if (v6 > 0) { + if (_bob[idx].field12 > 0) { + _bob[idx].field12 /= _vm->_globals._speed; + if (_bob[idx].field12 > 0) { _bob[idx].field14 = 1; if (_bob[idx].field1E == 1 || _bob[idx].field1E == 2) _bob[idx].field1C = true; @@ -998,13 +993,11 @@ void ObjectsManager::displayBobAnim() { _bob[idx]._frameIndex = v21[8]; _bob[idx]._flipFl = (v21[9] != 0); _bob[idx]._animDataIdx += 5; - int v10 = _bob[idx].field12; - if (v10 > 0) { - int v11 = v10 / _vm->_globals._speed; - _bob[idx].field12 = v11; + if (_bob[idx].field12 > 0) { + _bob[idx].field12 /= _vm->_globals._speed; // Original code. It can't be negative, so the check is on == 0 - if (v11 <= 0) + if (_bob[idx].field12 <= 0) _bob[idx].field12 = 1; } } @@ -1058,13 +1051,13 @@ void ObjectsManager::displayBobAnim() { _bob[i]._oldY = 0; if (_bob[i].field0 == 10 && !_bob[i]._disabledAnimationFl && _bob[i].field1C) { CALCUL_BOB(i); - int v19 = _bob[i]._oldX2 + _bob[i]._oldHeight + _bob[i]._oldY; + int priority = _bob[i]._oldX2 + _bob[i]._oldHeight + _bob[i]._oldY; - if (v19 > 450) - v19 = 600; + if (priority > 450) + priority = 600; if (_bob[i]._activeFl) - beforeSort(SORT_BOB, i, v19); + beforeSort(SORT_BOB, i, priority); } } } @@ -1194,7 +1187,7 @@ void ObjectsManager::animateSprite(int idx) { _sprite[idx]._animationType = 1; } -void ObjectsManager::addStaticSprite(const byte *spriteData, Common::Point pos, int idx, int spriteIndex, int zoomFactor, bool flipFl, int a8, int a9) { +void ObjectsManager::addStaticSprite(const byte *spriteData, Common::Point pos, int idx, int spriteIndex, int zoomFactor, bool flipFl, int deltaX, int deltaY) { assert (idx <= MAX_SPRITE); SpriteItem *spr = &_sprite[idx]; @@ -1203,8 +1196,8 @@ void ObjectsManager::addStaticSprite(const byte *spriteData, Common::Point pos, spr->_spriteIndex = spriteIndex; spr->_zoomFactor = zoomFactor; spr->_flipFl = flipFl; - spr->field12 = a8; - spr->field14 = a9; + spr->_deltaX = deltaX; + spr->_deltaY = deltaY; spr->_animationType = 0; if (READ_BE_UINT24(spriteData) == MKTAG24('R', 'L', 'E')) { @@ -1296,7 +1289,7 @@ void ObjectsManager::GOHOME() { _vm->_globals._actionDirection = DIR_NONE; int zoneId; if (_vm->_globals._actionMoveTo) - zoneId = _vm->_globals._saveData->_data[svField2]; + zoneId = _vm->_globals._saveData->_data[svLastZoneNum]; else zoneId = _zoneNum; _vm->_linesManager._route = (RouteItem *)g_PTRNUL; @@ -1514,7 +1507,7 @@ void ObjectsManager::GOHOME() { if (newPosX == -1 && newPosY == -1) { int zoneId; if (_vm->_globals._actionMoveTo) - zoneId = _vm->_globals._saveData->_data[svField2]; + zoneId = _vm->_globals._saveData->_data[svLastZoneNum]; else zoneId = _zoneNum; setSpriteIndex(0, _vm->_globals._oldDirection + 59); @@ -1766,7 +1759,7 @@ void ObjectsManager::handleCityMap() { _vm->_graphicsManager.SETCOLOR3(254, 0, 0, 0); for (int i = 0; i <= 4; i++) - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); _vm->_globals.iRegul = 1; _vm->_graphicsManager.fadeInLong(); @@ -1777,15 +1770,17 @@ void ObjectsManager::handleCityMap() { do { int mouseButton = _vm->_eventsManager.getMouseButton(); if (mouseButton) { - if (_vm->_globals._saveData->_data[svField170] == 1 && !_vm->_globals._saveData->_data[svField171]) { - _vm->_globals._saveData->_data[svField171] = 1; + // First cop call : Go to the bank and free the hostages + if (_vm->_globals._saveData->_data[svBankAttackAnimPlayedFl] == 1 && !_vm->_globals._saveData->_data[svCopCall1PlayedFl]) { + _vm->_globals._saveData->_data[svCopCall1PlayedFl] = 1; _vm->_globals._introSpeechOffFl = true; _vm->_talkManager.startAnimatedCharacterDialogue("APPEL1.pe2"); _vm->_globals._introSpeechOffFl = false; mouseButton = 0; } - if (_vm->_globals._saveData->_data[svField80] == 1 && !_vm->_globals._saveData->_data[svField172]) { - _vm->_globals._saveData->_data[svField172] = 1; + // Second cop call: Helico has been found in the empty lot + if (_vm->_globals._saveData->_data[svFreedHostageFl] == 1 && !_vm->_globals._saveData->_data[svCopCall2PlayedFl]) { + _vm->_globals._saveData->_data[svCopCall2PlayedFl] = 1; _vm->_globals._introSpeechOffFl = true; _vm->_talkManager.startAnimatedCharacterDialogue("APPEL2.pe2"); _vm->_globals._introSpeechOffFl = false; @@ -1801,7 +1796,7 @@ void ObjectsManager::handleCityMap() { if (_vm->_linesManager._route == (RouteItem *)g_PTRNUL && _vm->_globals._actionMoveTo) PARADISE(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); if (_vm->_globals._exitId) loopCond = true; @@ -1869,18 +1864,18 @@ void ObjectsManager::handleLeftButton() { return; int routeIdx = 0; do { - _vm->_linesManager.essai2[routeIdx] = _vm->_linesManager._route[routeIdx]; + _vm->_linesManager._testRoute2[routeIdx] = _vm->_linesManager._route[routeIdx]; ++routeIdx; } while (_vm->_linesManager._route[routeIdx]._x != -1); - _vm->_linesManager.essai2[routeIdx].invalidate();; + _vm->_linesManager._testRoute2[routeIdx].invalidate(); } if (_vm->_globals._actionMoveTo) { _vm->_linesManager.checkZone(); _vm->_globals._actionMoveTo = false; - _vm->_globals._saveData->_data[svField1] = 0; - _vm->_globals._saveData->_data[svField2] = 0; + _vm->_globals._saveData->_data[svLastMouseCursor] = 0; + _vm->_globals._saveData->_data[svLastZoneNum] = 0; } if (_vm->_globals._cityMapEnabledFl && (_vm->_eventsManager._mouseCursorId != 4 || _zoneNum <= 0)) @@ -1937,14 +1932,14 @@ void ObjectsManager::handleLeftButton() { if (_zoneNum != -1 && _zoneNum != 0) { if (_vm->_eventsManager._mouseCursorId == 23) - _vm->_globals._saveData->_data[svField1] = 5; + _vm->_globals._saveData->_data[svLastMouseCursor] = 5; else - _vm->_globals._saveData->_data[svField1] = _vm->_eventsManager._mouseCursorId; + _vm->_globals._saveData->_data[svLastMouseCursor] = _vm->_eventsManager._mouseCursorId; if (_vm->_globals._cityMapEnabledFl) - _vm->_globals._saveData->_data[svField1] = 6; - _vm->_globals._saveData->_data[svField2] = _zoneNum; - _vm->_globals._saveData->_data[svField3] = _curObjectIndex; + _vm->_globals._saveData->_data[svLastMouseCursor] = 6; + _vm->_globals._saveData->_data[svLastZoneNum] = _zoneNum; + _vm->_globals._saveData->_data[svLastObjectIndex] = _curObjectIndex; _vm->_globals._actionMoveTo = true; } _vm->_fontManager.hideText(5); @@ -1960,8 +1955,8 @@ void ObjectsManager::handleLeftButton() { } void ObjectsManager::PARADISE() { - char result = _vm->_globals._saveData->_data[svField1]; - if (result && _vm->_globals._saveData->_data[svField2] && result != 4 && result > 3) { + char result = _vm->_globals._saveData->_data[svLastMouseCursor]; + if (result && _vm->_globals._saveData->_data[svLastZoneNum] && result != 4 && result > 3) { _vm->_fontManager.hideText(5); if (!_forestFl || _zoneNum < 20 || _zoneNum > 23) { if (_vm->_graphicsManager._largeScreenFl) { @@ -1981,7 +1976,7 @@ void ObjectsManager::PARADISE() { if (_vm->_eventsManager.getMouseX() > _vm->_graphicsManager._scrollPosX + 620) _vm->_eventsManager.setMouseXY(_vm->_eventsManager._mousePos.x - 4, _vm->_eventsManager.getMouseY()); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (!loopCond && _vm->_eventsManager._startPos.x > getSpriteX(0) - 320); } else if (_vm->_eventsManager._startPos.x + 320 - getSpriteX(0) < -160) { bool loopCond = false; @@ -1998,30 +1993,30 @@ void ObjectsManager::PARADISE() { if (_vm->_eventsManager.getMouseX() < _vm->_graphicsManager._scrollPosX + 10) _vm->_eventsManager.setMouseXY(_vm->_eventsManager._mousePos.x + 4, _vm->_eventsManager.getMouseY()); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (!loopCond && _vm->_eventsManager._startPos.x < getSpriteX(0) - 320); } if (_vm->_eventsManager.getMouseX() > _vm->_graphicsManager._scrollPosX + 620) _vm->_eventsManager.setMouseXY(_vm->_graphicsManager._scrollPosX + 610, 0); if (_vm->_eventsManager.getMouseX() < _vm->_graphicsManager._scrollPosX + 10) _vm->_eventsManager.setMouseXY(_vm->_graphicsManager._scrollPosX + 10, 0); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); _vm->_graphicsManager._scrollStatus = 0; } - _vm->_talkManager.REPONSE(_vm->_globals._saveData->_data[svField2], _vm->_globals._saveData->_data[svField1]); + _vm->_talkManager.REPONSE(_vm->_globals._saveData->_data[svLastZoneNum], _vm->_globals._saveData->_data[svLastMouseCursor]); } else { - _vm->_talkManager.REPONSE2(_vm->_globals._saveData->_data[svField2], _vm->_globals._saveData->_data[svField1]); + _vm->_talkManager.REPONSE2(_vm->_globals._saveData->_data[svLastZoneNum], _vm->_globals._saveData->_data[svLastMouseCursor]); } _vm->_eventsManager.changeMouseCursor(4); if (_zoneNum != -1 && _zoneNum != 0 && !_vm->_linesManager.ZONEP[_zoneNum]._enabledFl) { _zoneNum = -1; _forceZoneFl = true; } - if (_zoneNum != _vm->_globals._saveData->_data[svField2] || _zoneNum == -1 || _zoneNum == 0) { + if (_zoneNum != _vm->_globals._saveData->_data[svLastZoneNum] || _zoneNum == -1 || _zoneNum == 0) { _vm->_eventsManager._mouseCursorId = 4; _changeVerbFl = false; } else { - _vm->_eventsManager._mouseCursorId = _vm->_globals._saveData->_data[svField1]; + _vm->_eventsManager._mouseCursorId = _vm->_globals._saveData->_data[svLastMouseCursor]; if (_changeVerbFl) { nextVerbIcon(); _changeVerbFl = false; @@ -2032,8 +2027,8 @@ void ObjectsManager::PARADISE() { if (_vm->_eventsManager._mouseCursorId != 23) _vm->_eventsManager.changeMouseCursor(_vm->_eventsManager._mouseCursorId); _zoneNum = 0; - _vm->_globals._saveData->_data[svField1] = 0; - _vm->_globals._saveData->_data[svField2] = 0; + _vm->_globals._saveData->_data[svLastMouseCursor] = 0; + _vm->_globals._saveData->_data[svLastZoneNum] = 0; } if (_vm->_globals._cityMapEnabledFl) { _vm->_eventsManager._mouseCursorId = 0; @@ -2075,8 +2070,8 @@ void ObjectsManager::clearScreen() { _vm->_globals.SPRITE_ECRAN = _vm->_globals.freeMemory(_vm->_globals.SPRITE_ECRAN); _vm->_eventsManager._startPos.x = 0; _vm->_eventsManager._mouseSpriteId = 0; - _vm->_globals._saveData->_data[svField1] = 0; - _vm->_globals._saveData->_data[svField2] = 0; + _vm->_globals._saveData->_data[svLastMouseCursor] = 0; + _vm->_globals._saveData->_data[svLastZoneNum] = 0; _vm->_globals._actionMoveTo = false; _forceZoneFl = true; _changeVerbFl = false; @@ -2181,21 +2176,21 @@ void ObjectsManager::changeCharacterHead(PlayerCharacter oldCharacter, PlayerCha switch (newCharacter) { case CHARACTER_HOPKINS: - _vm->_globals._saveData->_data[svField121] = 0; + _vm->_globals._saveData->_data[svHopkinsCloneFl] = 0; _vm->_globals._saveData->_data[svField354] = 0; _vm->_globals._saveData->_data[svField356] = 0; _vm->_globals._saveData->_data[svField357] = 1; _vm->_globals._exitId = _vm->_globals._saveData->_realHopkins._location; break; case CHARACTER_HOPKINS_CLONE: - _vm->_globals._saveData->_data[svField121] = 1; + _vm->_globals._saveData->_data[svHopkinsCloneFl] = 1; _vm->_globals._saveData->_data[svField354] = 1; _vm->_globals._saveData->_data[svField356] = 0; _vm->_globals._saveData->_data[svField357] = 0; _vm->_globals._exitId = _vm->_globals._saveData->_cloneHopkins._location; break; case CHARACTER_SAMANTHA: - _vm->_globals._saveData->_data[svField121] = 0; + _vm->_globals._saveData->_data[svHopkinsCloneFl] = 0; _vm->_globals._saveData->_data[svField354] = 0; _vm->_globals._saveData->_data[svField356] = 1; _vm->_globals._saveData->_data[svField357] = 0; @@ -2535,7 +2530,7 @@ void ObjectsManager::OPTI_OBJET() { int lastOpcodeResult = 1; file = "OBJET1.ini"; - data = _vm->_fileManager.searchCat(file, 1); + data = _vm->_fileManager.searchCat(file, RES_INI); if (data == g_PTRNUL) { data = _vm->_fileManager.loadFile(file); if (data == g_PTRNUL) @@ -2613,7 +2608,7 @@ void ObjectsManager::handleSpecialGames() { memcpy(_vm->_graphicsManager._vesaBuffer, _vm->_graphicsManager._vesaScreen, 614399); _vm->_graphicsManager._scrollStatus = 0; - _vm->_graphicsManager.DD_VBL(); + _vm->_graphicsManager.updateScreen(); break; case 20: _vm->_globals._saveData->_data[svField132] = (getSpriteX(0) > 65 && getSpriteX(0) <= 124 && getSpriteY(0) > 372 && getSpriteY(0) <= 398) ? 1 : 0; @@ -2685,7 +2680,7 @@ void ObjectsManager::handleSpecialGames() { _vm->_globals._disableInventFl = true; do - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); while (getBobAnimDataIdx(8) != 3); _vm->_globals._introSpeechOffFl = true; _vm->_talkManager.startAnimatedCharacterDialogue("GM3.PE2"); @@ -2757,34 +2752,34 @@ void ObjectsManager::doActionBack(int idx) { switch (idx) { case 1: - ACTION(_gestureBuf, "0,1,2,3,4,5,6,7,8,8,8,8,8,8,7,6,5,4,3,2,1,0,-1,", 0, 0, 8, false); + ACTION(_gestureBuf, "0,1,2,3,4,5,6,7,8,8,8,8,8,8,7,6,5,4,3,2,1,0,-1,", 8, false); break; case 2: - SPACTION(_gestureBuf, "0,1,2,3,4,5,6,7,8,9,10,11,12,13,-1,", 0, 0, 8, false); + SPACTION(_gestureBuf, "0,1,2,3,4,5,6,7,8,9,10,11,12,13,-1,", 8, false); break; case 3: - SPACTION1(_gestureBuf, "12,11,10,9,8,7,6,5,4,3,2,1,0,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "12,11,10,9,8,7,6,5,4,3,2,1,0,-1,", 8); break; case 4: - ACTION(_gestureBuf, "0,1,2,3,4,5,6,7,8,8,8,8,8,8,9,10,11,12,13,12,11,12,13,12,11,12,13,12,11,10,9,8,7,6,5,4,3,2,1,0,-1,", 0, 0, 8, false); + ACTION(_gestureBuf, "0,1,2,3,4,5,6,7,8,8,8,8,8,8,9,10,11,12,13,12,11,12,13,12,11,12,13,12,11,10,9,8,7,6,5,4,3,2,1,0,-1,", 8, false); break; case 5: - SPACTION(_gestureBuf, "15,16,17,18,19,20,21,-1,", 0, 0, 8, false); + SPACTION(_gestureBuf, "15,16,17,18,19,20,21,-1,", 8, false); break; case 6: - SPACTION1(_gestureBuf, "20,19,18,17,16,15,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "20,19,18,17,16,15,-1,", 8); break; case 7: - SPACTION(_gestureBuf, "15,16,17,18,19,20,21,22,23,24,-1,", 0, 0, 8, false); + SPACTION(_gestureBuf, "15,16,17,18,19,20,21,22,23,24,-1,", 8, false); break; case 8: - SPACTION1(_gestureBuf, "23,22,21,20,19,18,17,16,15,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "23,22,21,20,19,18,17,16,15,-1,", 8); break; case 9: - SPACTION(_gestureBuf, "15,16,17,18,19,20,21,22,23,24,-1,", 0, 0, 8, false); + SPACTION(_gestureBuf, "15,16,17,18,19,20,21,22,23,24,-1,", 8, false); break; case 10: - SPACTION1(_gestureBuf, "23,22,21,20,19,18,17,16,15,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "23,22,21,20,19,18,17,16,15,-1,", 8); break; } } @@ -2798,34 +2793,34 @@ void ObjectsManager::doActionRight(int idx) { switch (idx) { case 1: - ACTION(_gestureBuf, "20,19,18,17,16,15,14,13,13,13,13,13,14,15,16,17,18,19,20,-1,", 0, 0, 8, false); + ACTION(_gestureBuf, "20,19,18,17,16,15,14,13,13,13,13,13,14,15,16,17,18,19,20,-1,", 8, false); break; case 2: - SPACTION(_gestureBuf, "1,2,3,4,5,6,7,8,-1,", 0, 0, 8, false); + SPACTION(_gestureBuf, "1,2,3,4,5,6,7,8,-1,", 8, false); break; case 3: - SPACTION1(_gestureBuf, "9,10,11,12,13,14,15,16,17,18,19,20,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "9,10,11,12,13,14,15,16,17,18,19,20,-1,", 8); break; case 4: - ACTION(_gestureBuf, "1,2,3,4,5,6,7,8,8,7,6,5,4,3,2,1,-1,", 0, 0, 8, false); + ACTION(_gestureBuf, "1,2,3,4,5,6,7,8,8,7,6,5,4,3,2,1,-1,", 8, false); break; case 5: - SPACTION(_gestureBuf, "23,24,25,-1,", 0, 0, 8, false); + SPACTION(_gestureBuf, "23,24,25,-1,", 8, false); break; case 6: - SPACTION1(_gestureBuf, "24,,23,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "24,,23,-1,", 8); break; case 7: - SPACTION(_gestureBuf, "23,24,25,26,27,-1,", 0, 0, 8, false); + SPACTION(_gestureBuf, "23,24,25,26,27,-1,", 8, false); break; case 8: - SPACTION1(_gestureBuf, "26,25,24,23,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "26,25,24,23,-1,", 8); break; case 9: - SPACTION(_gestureBuf, "23,24,25,26,27,28,29,-1,", 0, 0, 8, false); + SPACTION(_gestureBuf, "23,24,25,26,27,28,29,-1,", 8, false); break; case 10: - SPACTION1(_gestureBuf, "28,27,26,25,24,23,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "28,27,26,25,24,23,-1,", 8); break; } } @@ -2839,34 +2834,34 @@ void ObjectsManager::doActionDiagRight(int idx) { switch (idx) { case 1: - ACTION(_gestureBuf, "0,1,2,3,4,5,6,7,8,8,8,8,8,7,6,5,4,3,2,1,0,-1,", 0, 0, 8, false); + ACTION(_gestureBuf, "0,1,2,3,4,5,6,7,8,8,8,8,8,7,6,5,4,3,2,1,0,-1,", 8, false); break; case 2: - SPACTION(_gestureBuf, "0,1,2,3,4,5,6,7,8,9,10,11,12,-1,", 0, 0, 8, false); + SPACTION(_gestureBuf, "0,1,2,3,4,5,6,7,8,9,10,11,12,-1,", 8, false); break; case 3: - SPACTION1(_gestureBuf, "11,10,9,8,7,6,5,4,3,2,1,0,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "11,10,9,8,7,6,5,4,3,2,1,0,-1,", 8); break; case 4: - ACTION(_gestureBuf, "0,1,2,3,4,5,6,7,8,9,10,11,12,11,12,11,12,11,12,11,10,9,8,7,6,5,4,3,2,1,0,-1,", 0, 0, 8, false); + ACTION(_gestureBuf, "0,1,2,3,4,5,6,7,8,9,10,11,12,11,12,11,12,11,12,11,10,9,8,7,6,5,4,3,2,1,0,-1,", 8, false); break; case 5: - SPACTION(_gestureBuf, "15,16,17,18,-1,", 0, 0, 8, false); + SPACTION(_gestureBuf, "15,16,17,18,-1,", 8, false); break; case 6: - SPACTION1(_gestureBuf, "17,16,15,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "17,16,15,-1,", 8); break; case 7: - SPACTION(_gestureBuf, "15,16,17,18,19,20-1,", 0, 0, 8, false); + SPACTION(_gestureBuf, "15,16,17,18,19,20-1,", 8, false); break; case 8: - SPACTION1(_gestureBuf, "19,18,17,16,15,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "19,18,17,16,15,-1,", 8); break; case 9: - SPACTION(_gestureBuf, "15,16,17,18,19,20,21,-1,", 0, 0, 8, false); + SPACTION(_gestureBuf, "15,16,17,18,19,20,21,-1,", 8, false); break; case 10: - SPACTION1(_gestureBuf, "20,19,18,17,15,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "20,19,18,17,15,-1,", 8); break; } } @@ -2880,16 +2875,16 @@ void ObjectsManager::doActionFront(int idx) { switch (idx) { case 1: - ACTION(_gestureBuf, "0,1,2,3,4,5,6,7,9,9,9,9,9,9,7,6,5,4,3,2,1,0,-1,", 0, 0, 8, false); + ACTION(_gestureBuf, "0,1,2,3,4,5,6,7,9,9,9,9,9,9,7,6,5,4,3,2,1,0,-1,", 8, false); break; case 2: - SPACTION(_gestureBuf, "0,1,2,3,4,5,6,7,9,10,11,12,13,14,15,-1,", 0, 0, 8, false); + SPACTION(_gestureBuf, "0,1,2,3,4,5,6,7,9,10,11,12,13,14,15,-1,", 8, false); break; case 3: - SPACTION1(_gestureBuf, "14,13,12,11,10,9,7,6,5,4,3,2,1,0,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "14,13,12,11,10,9,7,6,5,4,3,2,1,0,-1,", 8); break; case 4: - ACTION(_gestureBuf, "0,1,2,3,4,5,6,7,9,10,11,12,13,14,13,12,11,10,9,7,6,5,4,3,2,1,0,-1,", 0, 0, 8, false); + ACTION(_gestureBuf, "0,1,2,3,4,5,6,7,9,10,11,12,13,14,13,12,11,10,9,7,6,5,4,3,2,1,0,-1,", 8, false); break; } } @@ -2903,34 +2898,34 @@ void ObjectsManager::doActionDiagLeft(int idx) { switch (idx) { case 1: - ACTION(_gestureBuf, "0,1,2,3,4,5,6,7,8,8,8,8,8,7,6,5,4,3,2,1,0,-1,", 0, 0, 8, true); + ACTION(_gestureBuf, "0,1,2,3,4,5,6,7,8,8,8,8,8,7,6,5,4,3,2,1,0,-1,", 8, true); break; case 2: - SPACTION(_gestureBuf, "0,1,2,3,4,5,6,7,8,9,10,11,12,-1,", 0, 0, 8, true); + SPACTION(_gestureBuf, "0,1,2,3,4,5,6,7,8,9,10,11,12,-1,", 8, true); break; case 3: - SPACTION1(_gestureBuf, "11,10,9,8,7,6,5,4,3,2,1,0,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "11,10,9,8,7,6,5,4,3,2,1,0,-1,", 8); break; case 4: - ACTION(_gestureBuf, "0,1,2,3,4,5,6,7,8,9,10,11,12,11,12,11,12,11,12,11,10,9,8,7,6,5,4,3,2,1,0,-1,", 0, 0, 8, true); + ACTION(_gestureBuf, "0,1,2,3,4,5,6,7,8,9,10,11,12,11,12,11,12,11,12,11,10,9,8,7,6,5,4,3,2,1,0,-1,", 8, true); break; case 5: - SPACTION(_gestureBuf, "15,16,17,18,-1,", 0, 0, 8, true); + SPACTION(_gestureBuf, "15,16,17,18,-1,", 8, true); break; case 6: - SPACTION1(_gestureBuf, "17,16,15,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "17,16,15,-1,", 8); break; case 7: - SPACTION(_gestureBuf, "15,16,17,18,19,20,-1,", 0, 0, 8, true); + SPACTION(_gestureBuf, "15,16,17,18,19,20,-1,", 8, true); break; case 8: - SPACTION1(_gestureBuf, "19,18,17,16,15,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "19,18,17,16,15,-1,", 8); break; case 9: - SPACTION(_gestureBuf, "15,16,17,18,19,20,21,-1,", 0, 0, 8, true); + SPACTION(_gestureBuf, "15,16,17,18,19,20,21,-1,", 8, true); break; case 10: - SPACTION1(_gestureBuf, "20,19,18,17,15,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "20,19,18,17,15,-1,", 8); break; } } @@ -2944,34 +2939,34 @@ void ObjectsManager::doActionLeft(int idx) { switch (idx) { case 1: - ACTION(_gestureBuf, "20,19,18,17,16,15,14,13,13,13,13,13,14,15,16,17,18,19,20,-1,", 0, 0, 8, true); + ACTION(_gestureBuf, "20,19,18,17,16,15,14,13,13,13,13,13,14,15,16,17,18,19,20,-1,", 8, true); break; case 2: - SPACTION(_gestureBuf, "1,2,3,4,5,6,7,8,-1,", 0, 0, 8, true); + SPACTION(_gestureBuf, "1,2,3,4,5,6,7,8,-1,", 8, true); break; case 3: - SPACTION1(_gestureBuf, "9,10,11,12,13,14,15,16,17,18,19,20,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "9,10,11,12,13,14,15,16,17,18,19,20,-1,", 8); break; case 4: - ACTION(_gestureBuf, "1,2,3,4,5,6,7,8,8,7,6,5,4,3,2,1,-1,", 0, 0, 8, true); + ACTION(_gestureBuf, "1,2,3,4,5,6,7,8,8,7,6,5,4,3,2,1,-1,", 8, true); break; case 5: - SPACTION(_gestureBuf, "23,24,25,-1,", 0, 0, 8, true); + SPACTION(_gestureBuf, "23,24,25,-1,", 8, true); break; case 6: - SPACTION1(_gestureBuf, "24,,23,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "24,,23,-1,", 8); break; case 7: - SPACTION(_gestureBuf, "23,24,25,26,27,-1,", 0, 0, 8, true); + SPACTION(_gestureBuf, "23,24,25,26,27,-1,", 8, true); break; case 8: - SPACTION1(_gestureBuf, "26,25,24,23,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "26,25,24,23,-1,", 8); break; case 9: - SPACTION(_gestureBuf, "23,24,25,26,27,28,29,-1,", 0, 0, 8, true); + SPACTION(_gestureBuf, "23,24,25,26,27,28,29,-1,", 8, true); break; case 10: - SPACTION1(_gestureBuf, "28,27,26,25,24,23,-1,", 0, 0, 8); + SPACTION1(_gestureBuf, "28,27,26,25,24,23,-1,", 8); break; } } @@ -2985,7 +2980,7 @@ void ObjectsManager::OPTI_ONE(int idx, int animIdx, int destPosi, int animAction // Make Hopkins walk to the expected place do { - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (destPosi != getBobAnimDataIdx(idx)); if (!animAction) @@ -2994,7 +2989,7 @@ void ObjectsManager::OPTI_ONE(int idx, int animIdx, int destPosi, int animAction _vm->_graphicsManager.fastDisplay(_bob[idx]._spriteData, _bob[idx]._oldX, _bob[idx]._oldY, _bob[idx]._frameIndex); stopBobAnimation(idx); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } } @@ -3047,7 +3042,7 @@ int ObjectsManager::getBobFrameIndex(int idx) { void ObjectsManager::loadLinkFile(const Common::String &file) { Common::File f; Common::String filename = file + ".LNK"; - byte *ptr = _vm->_fileManager.searchCat(filename, 3); + byte *ptr = _vm->_fileManager.searchCat(filename, RES_LIN); size_t nbytes = _vm->_globals._catalogSize; if (ptr == g_PTRNUL) { if (!f.open(filename)) @@ -3068,7 +3063,7 @@ void ObjectsManager::loadLinkFile(const Common::String &file) { Common::String filename2 = Common::String((const char *)ptr + 1000); if (!filename2.empty()) { - _vm->_globals._hidingItemData[1] = _vm->_fileManager.searchCat(filename2, 8); + _vm->_globals._hidingItemData[1] = _vm->_fileManager.searchCat(filename2, RES_SLI); if (_vm->_globals._hidingItemData[1] || _vm->_globals._hidingItemData[1] == g_PTRNUL) { _vm->_globals._hidingItemData[1] = _vm->_fileManager.loadFile(filename2); @@ -3152,22 +3147,23 @@ void ObjectsManager::loadLinkFile(const Common::String &file) { } int curLineIdx = 0; - int v28; - do { - v28 = READ_LE_INT16(curDataPtr + 2 * curDataIdx); - if (v28 != -1) { + for (;;) { + int bobZoneId = READ_LE_INT16(curDataPtr + 2 * curDataIdx); + if (bobZoneId != -1) { _vm->_linesManager.addZoneLine( curLineIdx, READ_LE_INT16(curDataPtr + 2 * curDataIdx + 2), READ_LE_INT16(curDataPtr + 2 * curDataIdx + 4), READ_LE_INT16(curDataPtr + 2 * curDataIdx + 6), READ_LE_INT16(curDataPtr + 2 * curDataIdx + 8), - v28); - _vm->_linesManager.ZONEP[v28]._enabledFl = true; + bobZoneId); + _vm->_linesManager.ZONEP[bobZoneId]._enabledFl = true; } curDataIdx += 5; ++curLineIdx; - } while (v28 != -1); + if (bobZoneId == -1) + break; + } for (int i = 1; i <= 100; i++) { _vm->_linesManager.ZONEP[i]._destX = READ_LE_INT16(curDataPtr + 2 * curDataIdx); _vm->_linesManager.ZONEP[i]._destY = READ_LE_INT16(curDataPtr + 2 * curDataIdx + 2); @@ -3201,7 +3197,7 @@ void ObjectsManager::loadLinkFile(const Common::String &file) { _vm->_globals.freeMemory(ptr); } -void ObjectsManager::SPECIAL_INI() { +void ObjectsManager::sceneSpecialIni() { switch (_vm->_globals._screenId) { case 17: if (_vm->_globals._prevScreenId == 20) { @@ -3211,11 +3207,11 @@ void ObjectsManager::SPECIAL_INI() { _vm->_graphicsManager.SETCOLOR3(251, 100, 100, 100); _vm->_graphicsManager.SETCOLOR3(254, 0, 0, 0); for (int i = 0; i <= 4; i++) - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); _vm->_graphicsManager.fadeInLong(); animateSprite(0); for (int i = 0; i <= 4; i++) - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); VBOB(_vm->_globals.SPRITE_ECRAN, 5, 15, 28, 1); _vm->_fontManager.hideText(9); bool displayedTxtFl = false; @@ -3231,12 +3227,12 @@ void ObjectsManager::SPECIAL_INI() { _vm->_globals._saveData->_data[svField320] = 1; if (_vm->_soundManager._voiceOffFl) { for (int i = 0; i <= 199; i++) - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } _vm->_fontManager.hideText(9); VBOB_OFF(5); for (int i = 0; i <= 3; i++) - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); _vm->_graphicsManager._noFadingFl = true; _vm->_globals._disableInventFl = false; } @@ -3246,7 +3242,7 @@ void ObjectsManager::SPECIAL_INI() { if (_vm->_globals._prevScreenId == 17) { _vm->_eventsManager._mouseSpriteId = 4; for (int i = 0; i <= 4; i++) - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); _vm->_graphicsManager.fadeInLong(); _vm->_globals.iRegul = 1; _vm->_globals._disableInventFl = false; @@ -3281,14 +3277,14 @@ void ObjectsManager::SPECIAL_INI() { _vm->_linesManager.ZONEP[21]._messageId = 30; _vm->_linesManager.ZONEP[22]._messageId = 30; _vm->_linesManager.ZONEP[23]._messageId = 30; - for (int i = 200; i <= 214; i++) { + for (int i = svField200; i <= svField214; i++) { if (_vm->_globals._saveData->_data[i] != 2) _vm->_globals._saveData->_data[i] = 0; } break; case 73: - if (!_vm->_globals._saveData->_data[svField318]) { + if (!_vm->_globals._saveData->_data[svSecondElevatorAvailableFl]) { _vm->_globals.resetHidingUseCount(0); _vm->_globals.resetHidingUseCount(1); } @@ -3316,7 +3312,7 @@ void ObjectsManager::OPTI_BOBON(int idx1, int idx2, int idx3, int anim1Idx, int setBobAnimDataIdx(idx3, anim3Idx); } -void ObjectsManager::SCI_OPTI_ONE(int idx, int animIdx, int a3, int a4) { +void ObjectsManager::SCI_OPTI_ONE(int idx, int animIdx, int animDataIdx, int a4) { _vm->_eventsManager._curMouseButton = 0; _vm->_eventsManager._mouseButton = 0; @@ -3326,10 +3322,10 @@ void ObjectsManager::SCI_OPTI_ONE(int idx, int animIdx, int a3, int a4) { } do { - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); if (_vm->_eventsManager._curMouseButton) break; - } while (a3 != getBobAnimDataIdx(idx)); + } while (animDataIdx != getBobAnimDataIdx(idx)); if (!a4) stopBobAnimation(idx); } @@ -3444,7 +3440,7 @@ void ObjectsManager::enableVerb(int idx, int a2) { } } -void ObjectsManager::ACTION(const byte *spriteData, const Common::String &actionStr, int a3, int a4, int speed, bool flipFl) { +void ObjectsManager::ACTION(const byte *spriteData, const Common::String &actionStr, int speed, bool flipFl) { Common::String tmpStr = ""; int realSpeed = speed; if (_vm->_globals._speed == 2) @@ -3454,8 +3450,6 @@ void ObjectsManager::ACTION(const byte *spriteData, const Common::String &action const byte *oldSpriteData = _sprite[0]._spriteData; int spriteIndex = _sprite[0]._spriteIndex; bool oldFlipFl = _sprite[0]._flipFl; - _sprite[0].field12 += a3; - _sprite[0].field14 += a4; _sprite[0]._flipFl = flipFl; int idx = 0; @@ -3474,22 +3468,20 @@ void ObjectsManager::ACTION(const byte *spriteData, const Common::String &action if (idx == -1) { _sprite[0]._spriteData = oldSpriteData; _sprite[0]._spriteIndex = spriteIndex; - _sprite[0].field12 -= a3; - _sprite[0].field14 -= a4; _sprite[0]._flipFl = oldFlipFl; } else { _sprite[0]._spriteData = spriteData; _sprite[0]._spriteIndex = idx; } for (int i = 0; i < realSpeed; i++) - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); if (idx == -1) break; } } } -void ObjectsManager::SPACTION(byte *spriteData, const Common::String &animationSeq, int a3, int a4, int speed, bool flipFl) { +void ObjectsManager::SPACTION(byte *spriteData, const Common::String &animationSeq, int speed, bool flipFl) { Common::String tmpStr = ""; int realSpeed = speed; @@ -3501,8 +3493,6 @@ void ObjectsManager::SPACTION(byte *spriteData, const Common::String &animationS _oldSpriteData = _sprite[0]._spriteData; _oldSpriteIndex = _sprite[0]._spriteIndex; _oldFlipFl = _sprite[0]._flipFl; - _sprite[0].field12 += a3; - _sprite[0].field14 += a4; _sprite[0]._flipFl = flipFl; uint strPos = 0; @@ -3529,11 +3519,11 @@ void ObjectsManager::SPACTION(byte *spriteData, const Common::String &animationS _sprite[0]._spriteIndex = spriteIndex; } for (int i = 0; i < realSpeed; i++) - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (spriteIndex != -1); } -void ObjectsManager::SPACTION1(byte *spriteData, const Common::String &animString, int a3, int a4, int speed) { +void ObjectsManager::SPACTION1(byte *spriteData, const Common::String &animString, int speed) { Common::String tmpStr = ""; int realSpeed = speed; if (_vm->_globals._speed == 2) @@ -3560,8 +3550,6 @@ void ObjectsManager::SPACTION1(byte *spriteData, const Common::String &animStrin if (spriteIndex == -1) { _sprite[0]._spriteData = _oldSpriteData; _sprite[0]._spriteIndex = _oldSpriteIndex; - _sprite[0].field12 -= a3; - _sprite[0].field14 -= a4; _sprite[0]._flipFl = _oldFlipFl; } else { _sprite[0]._spriteData = spriteData; @@ -3569,7 +3557,7 @@ void ObjectsManager::SPACTION1(byte *spriteData, const Common::String &animStrin } for (int i = 0; i < realSpeed; i++) - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); if (spriteIndex == -1) break; @@ -3708,7 +3696,7 @@ void ObjectsManager::PERSONAGE(const Common::String &backgroundFile, const Commo _vm->_graphicsManager.SETCOLOR3(254, 0, 0, 0); _vm->_eventsManager.changeMouseCursor(4); for (int i = 0; i <= 4; i++) - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); _vm->_graphicsManager.fadeInLong(); if (_vm->_globals._screenId == 61) { _vm->_animationManager.playSequence("OUVRE.SEQ", 10, 4, 10); @@ -3722,7 +3710,7 @@ void ObjectsManager::PERSONAGE(const Common::String &backgroundFile, const Commo _vm->_globals._checkDistanceFl = true; do { GOHOME(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_linesManager._route != (RouteItem *)g_PTRNUL); setSpriteIndex(0, 64); } @@ -3738,7 +3726,7 @@ void ObjectsManager::PERSONAGE(const Common::String &backgroundFile, const Commo if (_vm->_globals._actionMoveTo) PARADISE(); if (!_vm->_globals._exitId) - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); if (_vm->_globals._exitId) break; @@ -3793,17 +3781,16 @@ void ObjectsManager::PERSONAGE2(const Common::String &backgroundFile, const Comm _vm->_graphicsManager.SETCOLOR3(251, 100, 100, 100); _vm->_graphicsManager.SETCOLOR3(254, 0, 0, 0); if (_vm->_globals._characterType) { - if (!_vm->_globals._saveData->_data[svField122] && !_vm->_globals._saveData->_data[svField356]) { + if (!_vm->_globals._saveData->_data[svAlternateSpriteFl] && !_vm->_globals._saveData->_data[svField356]) { _vm->_globals.PERSO = _vm->_fileManager.loadFile("PERSO.SPR"); _vm->_globals._characterType = 0; } } - if (!_vm->_globals._characterType) { - if (_vm->_globals._saveData->_data[svField122] == 1) { - _vm->_globals.PERSO = _vm->_fileManager.loadFile("HOPFEM.SPR"); - _vm->_globals._characterType = 1; - } + if (!_vm->_globals._characterType && _vm->_globals._saveData->_data[svAlternateSpriteFl] == 1) { + _vm->_globals.PERSO = _vm->_fileManager.loadFile("HOPFEM.SPR"); + _vm->_globals._characterType = 1; } + if (_vm->_globals._characterType != 2 && _vm->_globals._saveData->_data[svField356] == 1) { _vm->_globals.PERSO = _vm->_fileManager.loadFile("PSAMAN.SPR"); _vm->_globals._characterType = 2; @@ -3828,7 +3815,7 @@ void ObjectsManager::PERSONAGE2(const Common::String &backgroundFile, const Comm _vm->_globals.enableHiding(); _vm->_linesManager._route = (RouteItem *)g_PTRNUL; computeAndSetSpriteSize(); - SPECIAL_INI(); + sceneSpecialIni(); _vm->_eventsManager._mouseSpriteId = 4; _oldCharacterPosX = _characterPos.x; _oldCharacterPosY = _characterPos.y; @@ -3836,7 +3823,7 @@ void ObjectsManager::PERSONAGE2(const Common::String &backgroundFile, const Comm _vm->_globals.Compteur = 0; for (int idx = 0; idx < 5; ++idx) - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); _vm->_globals.iRegul = 1; if (!_vm->_graphicsManager._noFadingFl) @@ -3879,7 +3866,7 @@ void ObjectsManager::PERSONAGE2(const Common::String &backgroundFile, const Comm PARADISE(); } handleSpecialGames(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); if (!_vm->_globals._exitId) continue; } diff --git a/engines/hopkins/objects.h b/engines/hopkins/objects.h index 1c82ab0662..a1ea0dd6b1 100644 --- a/engines/hopkins/objects.h +++ b/engines/hopkins/objects.h @@ -39,8 +39,8 @@ struct SpriteItem { int _zoomFactor; bool _flipFl; int _spriteIndex; - int field12; - int field14; + int _deltaX; + int _deltaY; bool _rleFl; bool _activeFl; int _destX; @@ -127,8 +127,8 @@ private: int getBobFrameIndex(int idx); void handleForest(int screenId, int minX, int maxX, int minY, int maxY, int idx); - void SPECIAL_INI(); - void ACTION(const byte *spriteData, const Common::String &actionStr, int a3, int a4, int speed, bool flipFl); + void sceneSpecialIni(); + void ACTION(const byte *spriteData, const Common::String &actionStr, int speed, bool flipFl); public: bool _disableFl; bool _forestFl; @@ -174,7 +174,7 @@ public: int getHeight(const byte *objectData, int idx); byte *loadSprite(const Common::String &file); void loadLinkFile(const Common::String &file); - void addStaticSprite(const byte *spriteData, Common::Point pos, int idx, int spriteIndex, int zoomFactor, bool flipFl, int a8, int a9); + void addStaticSprite(const byte *spriteData, Common::Point pos, int idx, int spriteIndex, int zoomFactor, bool flipFl, int deltaX, int deltaY); void animateSprite(int idx); void removeSprite(int idx); void setSpriteX(int idx, int xp); @@ -197,6 +197,9 @@ public: void removeObject(int objIndex); void resetBob(int idx); + void hideBob(int idx); + void displayBob(int idx); + void setBobOffset(int idx, int offset); void setBobAnimDataIdx(int idx, int animIdx); void setBobAnimation(int idx); void stopBobAnimation(int idx); @@ -226,18 +229,15 @@ public: const Common::String &animFile, const Common::String &s4, int soundNum, bool initializeScreen); byte *loadObjectFromFile(int objIndex, bool mode); void OPTI_OBJET(); - void hideBob(int idx); - void displayBob(int idx); - void SPACTION(byte *spriteData, const Common::String &animationSeq, int a3, int a4, int speed, bool flipFl); + void SPACTION(byte *spriteData, const Common::String &animationSeq, int speed, bool flipFl); void BOB_VIVANT(int idx); void VBOB(byte *src, int idx, int xp, int yp, int frameIndex); void VBOB_OFF(int idx); void OPTI_ONE(int idx, int animIdx, int destPosi, int animAction); - void SCI_OPTI_ONE(int idx, int animIdx, int a3, int a4); + void SCI_OPTI_ONE(int idx, int animIdx, int animDataIdx, int a4); void GOHOME(); void OPTI_BOBON(int idx1, int idx2, int idx3, int anim1Idx, int anim2Idx, int anim3Idx); - void BOB_OFFSET(int idx, int offset); - void SPACTION1(byte *spriteData, const Common::String &animString, int a3, int a4, int speed); + void SPACTION1(byte *spriteData, const Common::String &animString, int speed); void PARADISE(); }; diff --git a/engines/hopkins/saveload.cpp b/engines/hopkins/saveload.cpp index f934c4c018..3fbe241f30 100644 --- a/engines/hopkins/saveload.cpp +++ b/engines/hopkins/saveload.cpp @@ -142,7 +142,7 @@ void SaveLoadManager::writeSavegameHeader(Common::OutSaveFile *out, hopkinsSaveg Common::Error SaveLoadManager::saveGame(int slot, const Common::String &saveName) { /* Pack any necessary data into the savegame data structure */ // Set the selected slot number - _vm->_globals._saveData->_data[svField10] = slot; + _vm->_globals._saveData->_data[svLastSavegameSlot] = slot; // Set up the inventory for (int i = 0; i < 35; ++i) @@ -203,9 +203,9 @@ Common::Error SaveLoadManager::loadGame(int slot) { _vm->_globals._inventory[i] = _vm->_globals._saveData->_inventory[i]; // Set variables from loaded data as necessary - _vm->_globals._saveData->_data[svField10] = slot; - _vm->_globals._exitId = _vm->_globals._saveData->_data[svField5]; - _vm->_globals._saveData->_data[svField6] = 0; + _vm->_globals._saveData->_data[svLastSavegameSlot] = slot; + _vm->_globals._exitId = _vm->_globals._saveData->_data[svLastScreenId]; + _vm->_globals._saveData->_data[svLastPrevScreenId] = 0; _vm->_globals._screenId = 0; _vm->_objectsManager._mapCarPosX = _vm->_globals._saveData->_mapCarPosX; _vm->_objectsManager._mapCarPosY = _vm->_globals._saveData->_mapCarPosY; @@ -234,7 +234,7 @@ void SaveLoadManager::createThumbnail(Graphics::Surface *s) { Graphics::Surface thumb8; thumb8.create(w, h, Graphics::PixelFormat::createFormatCLUT8()); - _vm->_graphicsManager.Reduc_Ecran(_vm->_graphicsManager._vesaBuffer, (byte *)thumb8.pixels, + _vm->_graphicsManager.reduceScreenPart(_vm->_graphicsManager._vesaBuffer, (byte *)thumb8.pixels, _vm->_eventsManager._startPos.x, 20, SCREEN_WIDTH, SCREEN_HEIGHT - 40, 80); // Convert the 8-bit pixel to 16 bit surface diff --git a/engines/hopkins/script.cpp b/engines/hopkins/script.cpp index c9413c15a7..a81a48174a 100644 --- a/engines/hopkins/script.cpp +++ b/engines/hopkins/script.cpp @@ -129,7 +129,7 @@ int ScriptManager::handleOpcode(byte *dataP) { do { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_soundManager._soundFl); } bool displayedTxtFl = false; @@ -196,7 +196,7 @@ int ScriptManager::handleOpcode(byte *dataP) { return -1; // Exiting game --v4; - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (v4); } } @@ -266,8 +266,8 @@ int ScriptManager::handleOpcode(byte *dataP) { case MKTAG24('S', 'T', 'E'): if (!_vm->_objectsManager._disableFl) { _vm->_globals._prevScreenId = _vm->_globals._screenId; - _vm->_globals._saveData->_data[svField6] = _vm->_globals._screenId; - _vm->_globals._screenId = _vm->_globals._saveData->_data[svField5] = dataP[5]; + _vm->_globals._saveData->_data[svLastPrevScreenId] = _vm->_globals._screenId; + _vm->_globals._screenId = _vm->_globals._saveData->_data[svLastScreenId] = dataP[5]; vbobFrameIndex = dataP[6]; } opcodeType = 1; @@ -279,7 +279,7 @@ int ScriptManager::handleOpcode(byte *dataP) { break; case MKTAG24('P', 'E', 'R'): { int specialOpcode = READ_LE_INT16(dataP + 5); - if (!_vm->_globals._saveData->_data[svField122] && !_vm->_globals._saveData->_data[svField356]) { + if (!_vm->_globals._saveData->_data[svAlternateSpriteFl] && !_vm->_globals._saveData->_data[svField356]) { vbobFrameIndex = 0; switch (specialOpcode) { @@ -469,7 +469,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } opcodeType = 1; break; @@ -538,8 +538,8 @@ int ScriptManager::handleOpcode(byte *dataP) { case 12: _vm->_fontManager.hideText(9); - _vm->_eventsManager.VBL(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); + _vm->_eventsManager.refreshScreenAndEvents(); _vm->_talkManager.startAnimatedCharacterDialogue("bqetueur.pe2"); break; @@ -570,7 +570,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } _vm->_eventsManager.mouseOff(); @@ -579,7 +579,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(3) != 100); _vm->_graphicsManager.fadeOutDefaultLength(_vm->_graphicsManager._vesaBuffer); _vm->_graphicsManager.endDisplayBob(); @@ -600,7 +600,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } _vm->_eventsManager.mouseOff(); @@ -683,7 +683,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_soundManager._soundFl); } _vm->_talkManager.startAnimatedCharacterDialogue("PTLAB.pe2"); @@ -761,7 +761,7 @@ int ScriptManager::handleOpcode(byte *dataP) { return -1; // Exiting game _vm->_objectsManager.GOHOME(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_linesManager._route != (RouteItem *)g_PTRNUL); _vm->_objectsManager.removeSprite(0); _vm->_globals._checkDistanceFl = true; @@ -815,7 +815,7 @@ int ScriptManager::handleOpcode(byte *dataP) { _vm->_graphicsManager.fastDisplay(_vm->_globals.SPRITE_ECRAN, 513, 249, 2); if (_vm->_objectsManager.getBobAnimDataIdx(10) == 34) _vm->_graphicsManager.fastDisplay(_vm->_globals.SPRITE_ECRAN, 513, 249, 3); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(9) != 36); _vm->_objectsManager.animateSprite(0); _vm->_objectsManager.stopBobAnimation(9); @@ -863,7 +863,7 @@ int ScriptManager::handleOpcode(byte *dataP) { } if (_vm->_objectsManager.getBobAnimDataIdx(10) == 12) v20 = 0; - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(9) != v19); if (v19 == 12) { _vm->_objectsManager.animateSprite(0); @@ -900,7 +900,7 @@ int ScriptManager::handleOpcode(byte *dataP) { _vm->_soundManager.playWav(1); v52 = true; } - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(12) != 34); _vm->_objectsManager.stopBobAnimation(2); _vm->_graphicsManager.fadeOutLong(); @@ -935,20 +935,20 @@ int ScriptManager::handleOpcode(byte *dataP) { case 56: _vm->_globals.PERSO = _vm->_fileManager.loadFile("HOPFEM.SPR"); _vm->_globals._characterType = 1; - _vm->_globals._saveData->_data[svField122] = 1; + _vm->_globals._saveData->_data[svAlternateSpriteFl] = 1; _vm->_globals.loadCharacterData(); - _vm->_objectsManager._sprite[0].field12 = 28; - _vm->_objectsManager._sprite[0].field14 = 155; + _vm->_objectsManager._sprite[0]._deltaX = 28; + _vm->_objectsManager._sprite[0]._deltaY = 155; _vm->_objectsManager.computeAndSetSpriteSize(); break; case 57: _vm->_globals.PERSO = _vm->_fileManager.loadFile("PERSO.SPR"); _vm->_globals._characterType = 0; - _vm->_globals._saveData->_data[svField122] = 0; + _vm->_globals._saveData->_data[svAlternateSpriteFl] = 0; _vm->_globals.loadCharacterData(); - _vm->_objectsManager._sprite[0].field12 = 34; - _vm->_objectsManager._sprite[0].field14 = 190; + _vm->_objectsManager._sprite[0]._deltaX = 34; + _vm->_objectsManager._sprite[0]._deltaY = 190; _vm->_objectsManager.computeAndSetSpriteSize(); break; @@ -973,7 +973,7 @@ int ScriptManager::handleOpcode(byte *dataP) { return -1; // Exiting game _vm->_objectsManager.GOHOME(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_linesManager._route != (RouteItem *)g_PTRNUL); _vm->_objectsManager.removeSprite(0); _vm->_objectsManager.setBobAnimation(7); @@ -998,7 +998,7 @@ int ScriptManager::handleOpcode(byte *dataP) { v18 = 0; if (_vm->_objectsManager.getBobAnimDataIdx(7) == 19) _vm->_objectsManager.setBobAnimation(3); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(3) != 48); _vm->_soundManager.removeSample(1); _vm->_objectsManager.setSpriteIndex(0, 62); @@ -1049,7 +1049,7 @@ int ScriptManager::handleOpcode(byte *dataP) { _vm->_objectsManager.setBobAnimDataIdx(4, 0); _vm->_objectsManager.setBobAnimDataIdx(13, 0); } - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(4) != 16); _vm->_objectsManager.stopBobAnimation(12); _vm->_objectsManager.stopBobAnimation(4); @@ -1073,7 +1073,7 @@ int ScriptManager::handleOpcode(byte *dataP) { return -1; // Exiting game _vm->_objectsManager.GOHOME(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_linesManager._route != (RouteItem *)g_PTRNUL); _vm->_objectsManager.removeSprite(0); _vm->_objectsManager.setBobAnimation(11); @@ -1100,7 +1100,7 @@ int ScriptManager::handleOpcode(byte *dataP) { } if (_vm->_objectsManager.getBobAnimDataIdx(8) == 12) v24 = 0; - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(8) != 32); _vm->_graphicsManager.fastDisplay(_vm->_globals.SPRITE_ECRAN, 201, 14, 1); _vm->_objectsManager.animateSprite(0); @@ -1115,7 +1115,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(5) != 74); _vm->_objectsManager.stopBobAnimation(5); _vm->_objectsManager.stopBobAnimation(6); @@ -1142,7 +1142,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(5) != 6); _vm->_objectsManager.stopBobAnimation(5); _vm->_objectsManager.setBobAnimation(6); @@ -1204,7 +1204,7 @@ int ScriptManager::handleOpcode(byte *dataP) { } if (_vm->_objectsManager.getBobAnimDataIdx(1) == 8) v25 = 0; - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(1) != 9); _vm->_objectsManager.stopBobAnimation(1); _vm->_objectsManager.stopBobAnimation(2); @@ -1246,7 +1246,7 @@ int ScriptManager::handleOpcode(byte *dataP) { } if (_vm->_objectsManager.getBobAnimDataIdx(1) == 8) v26 = 0; - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(1) != 9); _vm->_objectsManager.stopBobAnimation(1); _vm->_objectsManager.stopBobAnimation(3); @@ -1326,7 +1326,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(9) != 15); _vm->_objectsManager.stopBobAnimation(9); _vm->_objectsManager.animateSprite(0); @@ -1335,7 +1335,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(12) != 117); _vm->_graphicsManager.fastDisplay(_vm->_globals.SPRITE_ECRAN, 830, 122, 0); _vm->_objectsManager.stopBobAnimation(12); @@ -1363,9 +1363,9 @@ int ScriptManager::handleOpcode(byte *dataP) { _vm->_talkManager.startAnimatedCharacterDialogue("tourist1.pe2"); _vm->_globals._introSpeechOffFl = false; _vm->_animationManager.playAnim2("T421.ANM", 100, 14, 500); - _vm->_eventsManager.VBL(); - _vm->_eventsManager.VBL(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); + _vm->_eventsManager.refreshScreenAndEvents(); + _vm->_eventsManager.refreshScreenAndEvents(); _vm->_globals._introSpeechOffFl = true; _vm->_talkManager.startAnimatedCharacterDialogue("tourist2.pe2"); _vm->_globals._introSpeechOffFl = false; @@ -1398,7 +1398,7 @@ int ScriptManager::handleOpcode(byte *dataP) { return -1; // Exiting game _vm->_objectsManager.GOHOME(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_linesManager._route != (RouteItem *)g_PTRNUL); _vm->_objectsManager.removeSprite(0); _vm->_objectsManager.setSpriteIndex(0, 60); @@ -1428,7 +1428,7 @@ int ScriptManager::handleOpcode(byte *dataP) { } if (_vm->_objectsManager.getBobAnimDataIdx(4) == 56) v33 = 0; - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(4) != 72); _vm->_objectsManager.stopBobAnimation(4); } @@ -1457,7 +1457,7 @@ int ScriptManager::handleOpcode(byte *dataP) { } if (_vm->_objectsManager.getBobAnimDataIdx(6) == 56) v34 = 0; - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(6) != 72); _vm->_objectsManager.stopBobAnimation(6); } @@ -1486,7 +1486,7 @@ int ScriptManager::handleOpcode(byte *dataP) { } if (_vm->_objectsManager.getBobAnimDataIdx(5) == 56) v35 = 0; - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(5) != 72); _vm->_objectsManager.stopBobAnimation(5); } @@ -1506,28 +1506,28 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(4) != 10); _vm->_soundManager.playWav(1); do { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(4) != 18); _vm->_soundManager.playWav(2); do { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(4) != 62); _vm->_soundManager.playWav(3); do { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(4) != 77); _vm->_objectsManager.stopBobAnimation(4); _vm->_objectsManager.animateSprite(0); @@ -1544,28 +1544,28 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(5) != 10); _vm->_soundManager.playWav(1); do { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(5) != 18); _vm->_soundManager.playWav(2); do { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(5) != 38); _vm->_soundManager.playWav(3); do { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(5) != 53); _vm->_objectsManager.stopBobAnimation(5); _vm->_objectsManager.animateSprite(0); @@ -1639,7 +1639,7 @@ int ScriptManager::handleOpcode(byte *dataP) { return -1; // Exiting game _vm->_objectsManager.GOHOME(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_linesManager._route != (RouteItem *)g_PTRNUL); _vm->_globals._exitId = 59; break; @@ -1667,7 +1667,7 @@ int ScriptManager::handleOpcode(byte *dataP) { return -1; // Exiting game _vm->_objectsManager.GOHOME(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_linesManager._route != (RouteItem *)g_PTRNUL); _vm->_globals._exitId = 59; break; @@ -1682,13 +1682,13 @@ int ScriptManager::handleOpcode(byte *dataP) { _vm->_objectsManager.removeSprite(0); _vm->_objectsManager.setBobAnimation(9); _vm->_objectsManager.setBobAnimation(10); - _vm->_objectsManager.BOB_OFFSET(10, 300); + _vm->_objectsManager.setBobOffset(10, 300); _vm->_soundManager.playSoundFile("SOUND44.WAV"); do { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(10) != 7); _vm->_objectsManager.setBobAnimation(6); _vm->_objectsManager.stopBobAnimation(3); @@ -1696,7 +1696,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(6) != 10); _vm->_soundManager.playSoundFile("SOUND71.WAV"); _vm->_objectsManager.setBobAnimation(7); @@ -1705,7 +1705,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(7) != 15); _vm->_objectsManager.stopBobAnimation(5); _vm->_objectsManager.setBobAnimation(8); @@ -1714,7 +1714,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(8) != 76); _vm->_objectsManager.stopBobAnimation(6); _vm->_objectsManager.stopBobAnimation(7); @@ -1748,7 +1748,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(3) != 18); _vm->_objectsManager.stopBobAnimation(3); _vm->_objectsManager.setBobAnimation(4); @@ -1767,7 +1767,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); if (_vm->_objectsManager.getBobAnimDataIdx(4) == 18) _vm->_graphicsManager.fastDisplay(_vm->_globals.SPRITE_ECRAN, 18, 334, 0, false); } while (_vm->_objectsManager.getBobAnimDataIdx(4) != 26); @@ -1790,7 +1790,7 @@ int ScriptManager::handleOpcode(byte *dataP) { } if (_vm->_objectsManager.getBobAnimDataIdx(3) == 11) v41 = 0; - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(3) != 50); _vm->_objectsManager.stopBobAnimation(3); _vm->_objectsManager.animateSprite(0); @@ -1812,7 +1812,7 @@ int ScriptManager::handleOpcode(byte *dataP) { } if (_vm->_objectsManager.getBobAnimDataIdx(4) == 11) v42 = 0; - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(4) != 24); _vm->_objectsManager.stopBobAnimation(4); _vm->_objectsManager.animateSprite(0); @@ -1825,7 +1825,7 @@ int ScriptManager::handleOpcode(byte *dataP) { case 208: { _vm->_globals._disableInventFl = true; - if (_vm->_globals._saveData->_data[svField6] != _vm->_globals._saveData->_data[svField401]) { + if (_vm->_globals._saveData->_data[svLastPrevScreenId] != _vm->_globals._saveData->_data[svField401]) { _vm->_soundManager._specialSoundNum = 208; _vm->_animationManager.playSequence("SORT.SEQ", 10, 4, 10, true); _vm->_soundManager._specialSoundNum = 0; @@ -1840,7 +1840,7 @@ int ScriptManager::handleOpcode(byte *dataP) { return -1; // Exiting game _vm->_objectsManager.GOHOME(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_linesManager._route != (RouteItem *)g_PTRNUL); _vm->_objectsManager.setSpriteIndex(0, 64); _vm->_globals._exitId = _vm->_globals._saveData->_data[svField401]; @@ -1858,7 +1858,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(1) != 9); _vm->_objectsManager.stopBobAnimation(1); _vm->_linesManager._route = (RouteItem *)g_PTRNUL; @@ -1871,7 +1871,7 @@ int ScriptManager::handleOpcode(byte *dataP) { return -1; // Exiting game _vm->_objectsManager.GOHOME(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_linesManager._route != (RouteItem *)g_PTRNUL); _vm->_objectsManager.setSpriteIndex(0, 64); _vm->_objectsManager.setBobAnimation(2); @@ -1880,7 +1880,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(2) != 10); _vm->_objectsManager.stopBobAnimation(2); _vm->_objectsManager.setBobAnimation(4); @@ -1922,7 +1922,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } _vm->_graphicsManager.SETCOLOR4(252, 100, 100, 100); @@ -1968,7 +1968,7 @@ int ScriptManager::handleOpcode(byte *dataP) { return -1; // Exiting game _vm->_objectsManager.GOHOME(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_linesManager._route != (RouteItem *)g_PTRNUL); _vm->_objectsManager.removeSprite(0); int v45 = 0; @@ -1981,7 +1981,7 @@ int ScriptManager::handleOpcode(byte *dataP) { v45 = 1; _vm->_soundManager.playSoundFile("SOUND81.WAV"); } - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(7) != 15); _vm->_objectsManager.stopBobAnimation(7); _vm->_objectsManager.setSpriteX(0, 476); @@ -2003,7 +2003,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(12) != 6); _vm->_globals._introSpeechOffFl = true; _vm->_talkManager.startAnimatedCharacterDialogue("PRMORT.pe2"); @@ -2012,7 +2012,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(12) != 12); _vm->_objectsManager.animateSprite(0); _vm->_objectsManager.stopBobAnimation(12); @@ -2028,7 +2028,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); if (_vm->_objectsManager.getBobAnimDataIdx(11) == 10 && !v46) v46 = 1; } while (_vm->_objectsManager.getBobAnimDataIdx(11) != 13); @@ -2039,7 +2039,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (_vm->_objectsManager.getBobAnimDataIdx(13) != 48); _vm->_globals._introSpeechOffFl = true; _vm->_talkManager.startAnimatedCharacterDialogue("HRADIO.PE2"); @@ -2082,29 +2082,38 @@ int ScriptManager::handleOpcode(byte *dataP) { } case 237: { - char v48 = _vm->_globals._saveData->_data[svField341]; - if (v48) { - if (v48 == 2) - vbobFrameIndex = 5; - if (v48 == 3) - vbobFrameIndex = 4; - if (v48 == 1) - vbobFrameIndex = 6; + switch (_vm->_globals._saveData->_data[svField341]) { + case 1: + vbobFrameIndex = 6; + break; + case 2: + vbobFrameIndex = 5; + break; + case 3: + vbobFrameIndex = 4; + break; + } + + if (_vm->_globals._saveData->_data[svField341]) { _vm->_soundManager.playSoundFile("SOUND83.WAV"); _vm->_objectsManager.OPTI_ONE(vbobFrameIndex, 26, 50, 0); - if (_vm->_globals._saveData->_data[svField341] == 1) + + switch (_vm->_globals._saveData->_data[svField341]) { + case 1: _vm->_graphicsManager.fastDisplay(_vm->_globals.SPRITE_ECRAN, 27, 117, 0); - if (_vm->_globals._saveData->_data[svField341] == 2) - _vm->_graphicsManager.fastDisplay(_vm->_globals.SPRITE_ECRAN, 145, 166, 2); - if (_vm->_globals._saveData->_data[svField341] == 3) - _vm->_graphicsManager.fastDisplay(_vm->_globals.SPRITE_ECRAN, 296, 212, 4); - if (_vm->_globals._saveData->_data[svField341] == 1) _vm->_globals._saveData->_data[svField338] = 0; - if (_vm->_globals._saveData->_data[svField341] == 2) + break; + case 2: + _vm->_graphicsManager.fastDisplay(_vm->_globals.SPRITE_ECRAN, 145, 166, 2); _vm->_globals._saveData->_data[svField339] = 0; - if (_vm->_globals._saveData->_data[svField341] == 3) + break; + case 3: + _vm->_graphicsManager.fastDisplay(_vm->_globals.SPRITE_ECRAN, 296, 212, 4); _vm->_globals._saveData->_data[svField340] = 0; + break; + } } + _vm->_soundManager.playSoundFile("SOUND83.WAV"); _vm->_objectsManager.OPTI_ONE(5, 0, 23, 0); _vm->_graphicsManager.fastDisplay(_vm->_globals.SPRITE_ECRAN, 145, 166, 3); @@ -2112,28 +2121,35 @@ int ScriptManager::handleOpcode(byte *dataP) { } case 238: { - char v49 = _vm->_globals._saveData->_data[svField341]; - if (v49) { - if (v49 == 2) - vbobFrameIndex = 5; - else if (v49 == 3) - vbobFrameIndex = 4; - else if (v49 == 1) - vbobFrameIndex = 6; + switch (_vm->_globals._saveData->_data[svField341]) { + case 1: + vbobFrameIndex = 6; + break; + case 2: + vbobFrameIndex = 5; + break; + case 3: + vbobFrameIndex = 4; + break; + } + + if (_vm->_globals._saveData->_data[svField341]) { _vm->_soundManager.playSoundFile("SOUND83.WAV"); _vm->_objectsManager.OPTI_ONE(vbobFrameIndex, 26, 50, 0); - if (_vm->_globals._saveData->_data[svField341] == 1) + switch (_vm->_globals._saveData->_data[svField341]) { + case 1: _vm->_graphicsManager.fastDisplay(_vm->_globals.SPRITE_ECRAN, 27, 117, 0); - if (_vm->_globals._saveData->_data[svField341] == 2) - _vm->_graphicsManager.fastDisplay(_vm->_globals.SPRITE_ECRAN, 145, 166, 2); - if (_vm->_globals._saveData->_data[svField341] == 3) - _vm->_graphicsManager.fastDisplay(_vm->_globals.SPRITE_ECRAN, 296, 212, 4); - if (_vm->_globals._saveData->_data[svField341] == 1) _vm->_globals._saveData->_data[svField338] = 0; - if (_vm->_globals._saveData->_data[svField341] == 2) + break; + case 2: + _vm->_graphicsManager.fastDisplay(_vm->_globals.SPRITE_ECRAN, 145, 166, 2); _vm->_globals._saveData->_data[svField339] = 0; - if (_vm->_globals._saveData->_data[svField341] == 3) + break; + case 3: + _vm->_graphicsManager.fastDisplay(_vm->_globals.SPRITE_ECRAN, 296, 212, 4); _vm->_globals._saveData->_data[svField340] = 0; + break; + } } _vm->_soundManager.playSoundFile("SOUND83.WAV"); _vm->_objectsManager.OPTI_ONE(4, 0, 23, 0); @@ -2154,7 +2170,7 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); if (_vm->_objectsManager.getBobAnimDataIdx(1) == 12 && !soundFlag) { _vm->_soundManager.playSoundFile("SOUND86.WAV"); soundFlag = true; @@ -2183,14 +2199,14 @@ int ScriptManager::handleOpcode(byte *dataP) { if (_vm->shouldQuit()) return -1; // Exiting game - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } CharacterLocation *v51 = &_vm->_globals._saveData->_realHopkins; v51->_pos.x = _vm->_objectsManager.getSpriteX(0); v51->_pos.y = _vm->_objectsManager.getSpriteY(0); v51->_startSpriteIndex = 57; v51->_location = 97; - _vm->_globals._saveData->_data[svField121] = 1; + _vm->_globals._saveData->_data[svHopkinsCloneFl] = 1; _vm->_globals._saveData->_data[svField352] = 1; _vm->_globals._saveData->_data[svField353] = 1; _vm->_globals._saveData->_data[svField354] = 1; @@ -2394,7 +2410,7 @@ int ScriptManager::handleOpcode(byte *dataP) { break; case MKTAG24('B', 'O', 'S'): opcodeType = 1; - _vm->_objectsManager.BOB_OFFSET(READ_LE_INT16(dataP + 5), READ_LE_INT16(dataP + 7)); + _vm->_objectsManager.setBobOffset(READ_LE_INT16(dataP + 5), READ_LE_INT16(dataP + 7)); break; case MKTAG24('V', 'O', 'N'): _vm->_objectsManager.enableVerb(READ_LE_INT16(dataP + 5), READ_LE_INT16(dataP + 7)); @@ -2437,44 +2453,41 @@ int ScriptManager::handleGoto(const byte *dataP) { return READ_LE_INT16(dataP + 5); } -int ScriptManager::handleIf(const byte *dataP, int a2) { - int v20; - int v2 = a2; +int ScriptManager::handleIf(const byte *dataP, int offset) { + int newOffset; + int curOffset = offset; bool loopFl; do { loopFl = false; - int v3 = v2; + int tmpOffset = curOffset; int opcodeType; do { if (_vm->shouldQuit()) return 0; // Exiting game - ++v3; - opcodeType = checkOpcode(dataP + 20 * v3); - if (v3 > 400) + ++tmpOffset; + if (tmpOffset > 400) error("Control if failed"); + opcodeType = checkOpcode(dataP + 20 * tmpOffset); } while (opcodeType != 4); // EIF - v20 = v3; - int v6 = v2; - bool v7 = false; + newOffset = tmpOffset; + tmpOffset = curOffset; do { if (_vm->shouldQuit()) return 0; // Exiting game - ++v6; - if (checkOpcode(dataP + 20 * v6) == 3) // IIF - v7 = true; - if (v6 > 400) + ++tmpOffset; + if (tmpOffset > 400) error("Control if failed "); - if (v7) { - v2 = v20; + if (checkOpcode(dataP + 20 * tmpOffset) == 3) { // IIF + curOffset = newOffset; loopFl = true; break; } - } while (v20 != v6); + } while (newOffset != tmpOffset); } while (loopFl); - const byte *buf = dataP + 20 * a2; + const byte *buf = dataP + 20 * offset; byte oper = buf[13]; byte oper2 = buf[14]; byte operType = buf[15]; @@ -2503,14 +2516,14 @@ int ScriptManager::handleIf(const byte *dataP, int a2) { } if ((operType == 3) && check1Fl) { - return (a2 + 1); + return (offset + 1); } else if ((operType == 1) && check1Fl && check2Fl) { - return (a2 + 1); + return (offset + 1); } else if ((operType == 2) && (check1Fl || check2Fl)) { - return (a2 + 1); + return (offset + 1); } - return (v20 + 1); + return (newOffset + 1); } int ScriptManager::checkOpcode(const byte *dataP) { diff --git a/engines/hopkins/script.h b/engines/hopkins/script.h index cf719f52ce..3eba8d5167 100644 --- a/engines/hopkins/script.h +++ b/engines/hopkins/script.h @@ -42,7 +42,7 @@ public: void setParent(HopkinsEngine *vm); int handleOpcode(byte *dataP); - int handleIf(const byte *dataP, int a2); + int handleIf(const byte *dataP, int offset); int handleGoto(const byte *dataP); }; diff --git a/engines/hopkins/sound.cpp b/engines/hopkins/sound.cpp index 0ea33cd218..62504dadfd 100644 --- a/engines/hopkins/sound.cpp +++ b/engines/hopkins/sound.cpp @@ -35,7 +35,7 @@ #include "audio/mods/protracker.h" #include "audio/decoders/raw.h" -namespace Audio { +namespace Hopkins { class APC_ADPCMStream : public Audio::DVI_ADPCMStream { public: @@ -70,7 +70,7 @@ Audio::RewindableAudioStream *makeAPCStream(Common::SeekableReadStream *stream, return new APC_ADPCMStream(stream, disposeAfterUse, rate, stereo ? 2 : 1); } -class TwaAudioStream : public AudioStream { +class TwaAudioStream : public Audio::AudioStream { public: TwaAudioStream(Common::String name, Common::SeekableReadStream *stream) { _name = name; @@ -152,7 +152,7 @@ protected: Common::File *file = new Common::File(); if (file->open(filename + ".APC")) { - _cueStream = Audio::makeAPCStream(file, DisposeAfterUse::YES); + _cueStream = makeAPCStream(file, DisposeAfterUse::YES); return true; } @@ -184,12 +184,6 @@ Audio::AudioStream *makeTwaStream(Common::String name, Common::SeekableReadStrea return new TwaAudioStream(name, stream); } -} - -/*------------------------------------------------------------------------*/ - -namespace Hopkins { - SoundManager::SoundManager() { _specialSoundNum = 0; _soundVolume = 0; @@ -436,7 +430,7 @@ void SoundManager::loadMusic(const Common::String &file) { if (!f.open(filename)) error("Error opening file %s", filename.c_str()); - Audio::AudioStream *twaStream = Audio::makeTwaStream(file.c_str(), &f); + Audio::AudioStream *twaStream = makeTwaStream(file.c_str(), &f); _vm->_mixer->playStream(Audio::Mixer::kMusicSoundType, &_musicHandle, twaStream); f.close(); } @@ -526,7 +520,7 @@ bool SoundManager::mixVoice(int voiceId, int voiceMode, bool dispTxtFl) { filename = Common::String::format("%s%d", prefix.c_str(), mappedFileNumber); - if (!_vm->_fileManager.searchCat(filename + ".WAV", 9)) { + if (!_vm->_fileManager.searchCat(filename + ".WAV", RES_VOI)) { if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS) filename = "ENG_VOI.RES"; // Win95 and Linux versions uses another set of names @@ -539,7 +533,7 @@ bool SoundManager::mixVoice(int voiceId, int voiceMode, bool dispTxtFl) { catPos = _vm->_globals._catalogPos; catLen = _vm->_globals._catalogSize; - } else if (!_vm->_fileManager.searchCat(filename + ".APC", 9)) { + } else if (!_vm->_fileManager.searchCat(filename + ".APC", RES_VOI)) { if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS) filename = "ENG_VOI.RES"; // Win95 and Linux versions uses another set of names @@ -552,7 +546,7 @@ bool SoundManager::mixVoice(int voiceId, int voiceMode, bool dispTxtFl) { catPos = _vm->_globals._catalogPos; catLen = _vm->_globals._catalogSize; - } else if (!_vm->_fileManager.searchCat(filename + ".RAW", 9)) { + } else if (!_vm->_fileManager.searchCat(filename + ".RAW", RES_VOI)) { if (_vm->getPlatform() == Common::kPlatformOS2 || _vm->getPlatform() == Common::kPlatformBeOS) filename = "ENG_VOI.RES"; // Win95 and Linux versions uses another set of names @@ -589,7 +583,7 @@ bool SoundManager::mixVoice(int voiceId, int voiceMode, bool dispTxtFl) { // Reduce music volume during speech if (!_musicOffFl && _musicVolume > 2) { - _musicVolume = (signed int)((long double)_musicVolume - (long double)_musicVolume / 100.0 * 45.0); + _musicVolume -= _musicVolume * 9 / 20; setMODMusicVolume(_musicVolume); } } @@ -601,7 +595,7 @@ bool SoundManager::mixVoice(int voiceId, int voiceMode, bool dispTxtFl) { breakFlag = false; do { if (_specialSoundNum != 4 && !_skipRefreshFl) - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); if (_vm->_eventsManager.getMouseButton()) break; _vm->_eventsManager.refreshEvents(); @@ -897,7 +891,7 @@ void SoundManager::updateScummVMSoundSettings() { */ Audio::RewindableAudioStream *SoundManager::makeSoundStream(Common::SeekableReadStream *stream) { if (_vm->getPlatform() == Common::kPlatformWindows) - return Audio::makeAPCStream(stream, DisposeAfterUse::YES); + return makeAPCStream(stream, DisposeAfterUse::YES); else if (_vm->getPlatform() == Common::kPlatformLinux) return Audio::makeWAVStream(stream, DisposeAfterUse::YES); else diff --git a/engines/hopkins/talk.cpp b/engines/hopkins/talk.cpp index d3c60a056e..e90f0f84aa 100644 --- a/engines/hopkins/talk.cpp +++ b/engines/hopkins/talk.cpp @@ -54,18 +54,18 @@ void TalkManager::startAnimatedCharacterDialogue(const Common::String &filename) _vm->_fontManager.hideText(5); _vm->_fontManager.hideText(9); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); _vm->_graphicsManager._scrollStatus = 1; bool oldDisableInventFl = _vm->_globals._disableInventFl; _vm->_globals._disableInventFl = true; - _characterBuffer = _vm->_fileManager.searchCat(filename, 5); + _characterBuffer = _vm->_fileManager.searchCat(filename, RES_PER); _characterSize = _vm->_globals._catalogSize; if (_characterBuffer == g_PTRNUL) { _characterBuffer = _vm->_fileManager.loadFile(filename); _characterSize = _vm->_fileManager.fileSize(filename); } - // CHECKME:_data[svField4] is useless? - _vm->_globals._saveData->_data[svField4] = 0; + + _vm->_globals._saveData->_data[svDialogField4] = 0; getStringFromBuffer(40, spriteFilename, (const char *)_characterBuffer); getStringFromBuffer(0, _questionsFilename, (const char *)_characterBuffer); @@ -79,7 +79,7 @@ void TalkManager::startAnimatedCharacterDialogue(const Common::String &filename) } _dialogueMesgId1 = READ_LE_INT16((uint16 *)_characterBuffer + 40); _paletteBufferIdx = 20 * READ_LE_INT16((uint16 *)_characterBuffer + 42) + 110; - _characterSprite = _vm->_fileManager.searchCat(spriteFilename, 7); + _characterSprite = _vm->_fileManager.searchCat(spriteFilename, RES_SAN); if (_characterSprite) { _characterSprite = _vm->_objectsManager.loadSprite(spriteFilename); } else { @@ -113,7 +113,7 @@ void TalkManager::startAnimatedCharacterDialogue(const Common::String &filename) answer = dialogAnswer(dlgAnswer, false); if (answer == -1) dlgAnswer = _dialogueMesgId4; - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (dlgAnswer != _dialogueMesgId4); } if (_vm->_globals._introSpeechOffFl) { @@ -148,9 +148,9 @@ void TalkManager::startAnimatedCharacterDialogue(const Common::String &filename) _vm->_graphicsManager.unlockScreen(); memcpy(_vm->_graphicsManager._vesaBuffer, _vm->_graphicsManager._vesaScreen, 614399); _vm->_globals._disableInventFl = oldDisableInventFl; - _vm->_graphicsManager.DD_VBL(); + _vm->_graphicsManager.updateScreen(); for (int i = 0; i <= 4; i++) - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); _vm->_graphicsManager._scrollStatus = 0; } @@ -158,15 +158,14 @@ void TalkManager::startStaticCharacterDialogue(const Common::String &filename) { // TODO: The original disables the mouse cursor here bool oldDisableInventFl = _vm->_globals._disableInventFl; _vm->_globals._disableInventFl = true; - _characterBuffer = _vm->_fileManager.searchCat(filename, 5); + _characterBuffer = _vm->_fileManager.searchCat(filename, RES_PER); _characterSize = _vm->_globals._catalogSize; if (_characterBuffer == g_PTRNUL) { _characterBuffer = _vm->_fileManager.loadFile(filename); _characterSize = _vm->_fileManager.fileSize(filename); } - // CHECKME:_data[svField4] is useless? - _vm->_globals._saveData->_data[svField4] = 0; + _vm->_globals._saveData->_data[svDialogField4] = 0; getStringFromBuffer(0, _questionsFilename, (const char *)_characterBuffer); getStringFromBuffer(20, _answersFilename, (const char *)_characterBuffer); @@ -287,7 +286,7 @@ int TalkManager::dialogQuestion(bool animatedFl) { retVal = _dialogueMesgId4; } - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); if (_vm->_eventsManager.getMouseButton()) loopCond = true; if (retVal == -1) @@ -326,7 +325,7 @@ int TalkManager::dialogQuestion(bool animatedFl) { dialogTalk(); } - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); return retVal; } @@ -348,10 +347,9 @@ int TalkManager::dialogAnswer(int idx, bool animatedFl) { _dialogueMesgId3 = READ_LE_INT16((uint16 *)charBuf + 7); int frameNumb = READ_LE_INT16((uint16 *)charBuf + 8); - // CHECKME:_data[svField4] is useless? int v7 = READ_LE_INT16((uint16 *)charBuf + 9); if (v7) - _vm->_globals._saveData->_data[svField4] = v7; + _vm->_globals._saveData->_data[svDialogField4] = v7; if (!frameNumb) frameNumb = 10; @@ -392,11 +390,11 @@ int TalkManager::dialogAnswer(int idx, bool animatedFl) { if (_vm->getIsDemo()) { for (int i = 0; i < frameNumb; i++) { - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } } else { for (int i = 0; i < frameNumb; i++) { - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); if (_vm->_eventsManager._mouseButton || _vm->_eventsManager._curMouseButton) break; if (_vm->_eventsManager.getMouseButton() && i + 1 > abs(frameNumb / 5)) @@ -498,8 +496,8 @@ void TalkManager::dialogEndTalk() { _vm->_objectsManager.hideBob(idx); } - _vm->_eventsManager.VBL(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); + _vm->_eventsManager.refreshScreenAndEvents(); for (int idx = 21; idx <= 25; ++idx) { if (_vm->_globals._animBqe[idx]._enabledFl) @@ -606,19 +604,19 @@ void TalkManager::BOB_VISU_PARLE(int idx) { _vm->_objectsManager._priorityFl = true; if (!_vm->_objectsManager._bob[idx].field0) { _vm->_objectsManager.resetBob(idx); - byte *v5 = _vm->_globals._animBqe[idx]._data; - int v4 = READ_LE_INT16(v5 + 2); - if (!v4) - v4 = 1; - if (READ_LE_INT16(v5 + 24)) { + byte *bqeData = _vm->_globals._animBqe[idx]._data; + int newField1E = READ_LE_INT16(bqeData + 2); + if (!newField1E) + newField1E = 1; + if (READ_LE_INT16(bqeData + 24)) { _vm->_objectsManager._bob[idx]._isSpriteFl = true; _vm->_objectsManager._bob[idx]._zoomFactor = 0; _vm->_objectsManager._bob[idx]._flipFl = false; _vm->_objectsManager._bob[idx]._animData = _vm->_globals._animBqe[idx]._data; _vm->_objectsManager._bob[idx].field0 = 10; - v5 = _characterSprite; + bqeData = _characterSprite; _vm->_objectsManager._bob[idx]._spriteData = _characterSprite; - _vm->_objectsManager._bob[idx].field1E = v4; + _vm->_objectsManager._bob[idx].field1E = newField1E; _vm->_objectsManager._bob[idx].field20 = -1; _vm->_objectsManager._bob[idx].field22 = 0; } @@ -640,14 +638,14 @@ void TalkManager::startCharacterAnim0(int startIdx, bool readOnlyFl) { _characterAnim = _characterBuffer + animIdx + 25; if (!readOnlyFl) { int idx = 0; - int v7; do { - v7 = READ_LE_INT16(&_characterAnim[2 * idx + 4]); - if (v7 && _vm->_globals._speed != 501) + if (!READ_LE_INT16(&_characterAnim[2 * idx + 4])) + break; + if (_vm->_globals._speed != 501) _vm->_graphicsManager.fastDisplay(_characterSprite, _vm->_eventsManager._startPos.x + READ_LE_INT16(&_characterAnim[2 * idx]), READ_LE_INT16(&_characterAnim[2 * idx + 2]), _characterAnim[2 * idx + 8]); idx += 5; - } while (_vm->_globals._speed != 501 && v7); + } while (_vm->_globals._speed != 501); } } @@ -794,35 +792,35 @@ void TalkManager::REPONSE(int zone, int verb) { ptr = _vm->_globals.allocMemory(620); assert(ptr != g_PTRNUL); memset(ptr, 0, 620); - uint16 v7 = 0; - int v12 = 0; + uint16 curAnswerIdx = 0; + int idx = 0; bool innerLoopCond = false; do { tagFound = false; - if (READ_BE_UINT16(&curAnswerBuf[v7]) == MKTAG16('F', 'C')) { - ++v12; - assert(v12 < (620 / 20)); + if (READ_BE_UINT16(&curAnswerBuf[curAnswerIdx]) == MKTAG16('F', 'C')) { + ++idx; + assert(idx < (620 / 20)); - byte *v8 = (ptr + 20 * v12); + byte *answerBuf = (ptr + 20 * idx); uint16 anwerIdx = 0; do { assert(anwerIdx < 20); - v8[anwerIdx++] = curAnswerBuf[v7++]; - if (READ_BE_UINT16(&curAnswerBuf[v7]) == MKTAG16('F', 'F')) { + answerBuf[anwerIdx++] = curAnswerBuf[curAnswerIdx++]; + if (READ_BE_UINT16(&curAnswerBuf[curAnswerIdx]) == MKTAG16('F', 'F')) { tagFound = true; - v8[anwerIdx] = 'F'; - v8[anwerIdx + 1] = 'F'; - ++v7; + answerBuf[anwerIdx] = 'F'; + answerBuf[anwerIdx + 1] = 'F'; + ++curAnswerIdx; } } while (!tagFound); } if (!tagFound) { - uint32 signature24 = READ_BE_UINT24(&curAnswerBuf[v7]); + uint32 signature24 = READ_BE_UINT24(&curAnswerBuf[curAnswerIdx]); if (signature24 == MKTAG24('C', 'O', 'D') || signature24 == MKTAG24('F', 'I', 'N')) innerLoopCond = true; } - curAnswerBuf += v7 + 1; - v7 = 0; + curAnswerBuf += curAnswerIdx + 1; + curAnswerIdx = 0; } while (!innerLoopCond); innerLoopCond = false; int lastOpcodeResult = 1; @@ -858,19 +856,19 @@ void TalkManager::REPONSE(int zone, int verb) { } while (!innerLoopCond); } while (outerLoopFl); _vm->_globals.freeMemory(ptr); - _vm->_globals._saveData->_data[svField2] = 0; + _vm->_globals._saveData->_data[svLastZoneNum] = 0; return; } void TalkManager::REPONSE2(int zone, int verb) { int indx = 0; - if (verb != 5 || _vm->_globals._saveData->_data[svField3] != 4) + if (verb != 5 || _vm->_globals._saveData->_data[svLastObjectIndex] != 4) return; if (zone == 22 || zone == 23) { _vm->_objectsManager.setFlipSprite(0, false); _vm->_objectsManager.setSpriteIndex(0, 62); - _vm->_objectsManager.SPACTION(_vm->_objectsManager._forestSprite, "2,3,4,5,6,7,8,9,10,11,12,-1,", 0, 0, 4, false); + _vm->_objectsManager.SPACTION(_vm->_objectsManager._forestSprite, "2,3,4,5,6,7,8,9,10,11,12,-1,", 4, false); if (zone == 22) { _vm->_objectsManager.lockAnimX(6, _vm->_objectsManager.getBobPosX(3)); _vm->_objectsManager.lockAnimX(8, _vm->_objectsManager.getBobPosX(3)); @@ -882,9 +880,9 @@ void TalkManager::REPONSE2(int zone, int verb) { _vm->_objectsManager.stopBobAnimation(4); _vm->_objectsManager.setBobAnimation(6); _vm->_soundManager.playSample(1); - _vm->_objectsManager.SPACTION1(_vm->_objectsManager._forestSprite, "13,14,15,14,13,12,13,14,15,16,-1,", 0, 0, 4); + _vm->_objectsManager.SPACTION1(_vm->_objectsManager._forestSprite, "13,14,15,14,13,12,13,14,15,16,-1,", 4); do - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); while (_vm->_objectsManager.getBobAnimDataIdx(6) < 12); _vm->_objectsManager.stopBobAnimation(6); _vm->_objectsManager.setBobAnimation(8); @@ -918,7 +916,7 @@ void TalkManager::REPONSE2(int zone, int verb) { } else if (zone == 20 || zone == 21) { _vm->_objectsManager.setFlipSprite(0, true); _vm->_objectsManager.setSpriteIndex(0, 62); - _vm->_objectsManager.SPACTION(_vm->_objectsManager._forestSprite, "2,3,4,5,6,7,8,9,10,11,12,-1,", 0, 0, 4, true); + _vm->_objectsManager.SPACTION(_vm->_objectsManager._forestSprite, "2,3,4,5,6,7,8,9,10,11,12,-1,", 4, true); if (zone == 20) { _vm->_objectsManager.lockAnimX(5, _vm->_objectsManager.getBobPosX(1)); _vm->_objectsManager.lockAnimX(7, _vm->_objectsManager.getBobPosX(1)); @@ -930,9 +928,9 @@ void TalkManager::REPONSE2(int zone, int verb) { _vm->_objectsManager.stopBobAnimation(2); _vm->_objectsManager.setBobAnimation(5); _vm->_soundManager.playSample(1); - _vm->_objectsManager.SPACTION1(_vm->_objectsManager._forestSprite, "13,14,15,14,13,12,13,14,15,16,-1,", 0, 0, 4); + _vm->_objectsManager.SPACTION1(_vm->_objectsManager._forestSprite, "13,14,15,14,13,12,13,14,15,16,-1,", 4); do - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); while (_vm->_objectsManager.getBobAnimDataIdx(5) < 12); _vm->_objectsManager.stopBobAnimation(5); _vm->_objectsManager.setBobAnimation(7); @@ -965,10 +963,10 @@ void TalkManager::REPONSE2(int zone, int verb) { } } -void TalkManager::animateObject(const Common::String &a2) { +void TalkManager::animateObject(const Common::String &filename) { _vm->_fontManager.hideText(5); _vm->_fontManager.hideText(9); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); _vm->_graphicsManager._scrollStatus = 1; _vm->_linesManager.clearAllZones(); _vm->_linesManager.resetLines(); @@ -980,11 +978,11 @@ void TalkManager::animateObject(const Common::String &a2) { _vm->_objectsManager._zoneNum = -1; _vm->_eventsManager._mouseCursorId = 4; _vm->_eventsManager.changeMouseCursor(0); - _characterBuffer = _vm->_fileManager.searchCat(a2, 5); + _characterBuffer = _vm->_fileManager.searchCat(filename, RES_PER); _characterSize = _vm->_globals._catalogSize; if (_characterBuffer == g_PTRNUL) { - _characterBuffer = _vm->_fileManager.loadFile(a2); - _characterSize = _vm->_fileManager.fileSize(a2); + _characterBuffer = _vm->_fileManager.loadFile(filename); + _characterSize = _vm->_fileManager.fileSize(filename); } Common::String screenFilename; Common::String spriteFilename; @@ -996,7 +994,7 @@ void TalkManager::animateObject(const Common::String &a2) { if (curScreenFilename == "NULL") curScreenFilename = Common::String::format("IM%d", _vm->_globals._screenId); - _characterSprite = _vm->_fileManager.searchCat(spriteFilename, 7); + _characterSprite = _vm->_fileManager.searchCat(spriteFilename, RES_SAN); if (_characterSprite) _characterSprite = _vm->_objectsManager.loadSprite(spriteFilename); else @@ -1039,7 +1037,7 @@ void TalkManager::animateObject(const Common::String &a2) { _vm->_linesManager.checkZone(); if (_vm->_globals._actionMoveTo) _vm->_objectsManager.PARADISE(); - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); } while (!_vm->_globals._exitId); dialogEndTalk(); dialogTalk(); @@ -1084,9 +1082,9 @@ void TalkManager::animateObject(const Common::String &a2) { _vm->_graphicsManager.setPaletteVGA256(_vm->_graphicsManager._palette); memcpy(_vm->_graphicsManager._vesaBuffer, _vm->_graphicsManager._vesaScreen, 614399); _vm->_globals._disableInventFl = false; - _vm->_graphicsManager.DD_VBL(); + _vm->_graphicsManager.updateScreen(); for (int i = 0; i <= 4; i++) - _vm->_eventsManager.VBL(); + _vm->_eventsManager.refreshScreenAndEvents(); _vm->_graphicsManager._scrollStatus = 0; } diff --git a/engines/hopkins/talk.h b/engines/hopkins/talk.h index e93c47fd38..c8985343b9 100644 --- a/engines/hopkins/talk.h +++ b/engines/hopkins/talk.h @@ -70,7 +70,7 @@ public: void startStaticCharacterDialogue(const Common::String &filename); void startAnimatedCharacterDialogue(const Common::String &filename); - void animateObject(const Common::String &a2); + void animateObject(const Common::String &filename); void REPONSE(int zone, int verb); void REPONSE2(int zone, int verb); diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h index fc7dfce9bb..87635bfc6a 100644 --- a/engines/mohawk/detection_tables.h +++ b/engines/mohawk/detection_tables.h @@ -239,6 +239,24 @@ static const MohawkGameDescription gameDescriptions[] = { 0, }, + // Myst Masterpiece Edition + // Polish Windows + // From pykman (Included in "Myst: Antologia") + { + { + "myst", + "Masterpiece Edition", + AD_ENTRY1("MYST.DAT", "4a05771b60f4a69869838d01e85c9e80"), + Common::PL_POL, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO1(GUIO_NOASPECT) + }, + GType_MYST, + GF_ME, + 0, + }, + // Riven: The Sequel to Myst // Version 1.0 (5CD) // From clone2727 @@ -348,6 +366,24 @@ static const MohawkGameDescription gameDescriptions[] = { }, // Riven: The Sequel to Myst + // Version 1.02 (DVD, From "Myst: Antologia") + // From pykman + { + { + "riven", + "", + AD_ENTRY1("a_Data.MHK", "733a710cf5f848b441ec72d988ab8a3d"), + Common::PL_POL, + Common::kPlatformWindows, + ADGF_UNSTABLE, + GUIO1(GUIO_NOASPECT) + }, + GType_RIVEN, + GF_DVD, + 0, + }, + + // Riven: The Sequel to Myst // Version ? (Demo, From "Prince of Persia Collector's Edition") // From Clone2727 { diff --git a/engines/pegasus/neighborhood/mars/mars.cpp b/engines/pegasus/neighborhood/mars/mars.cpp index 34c9e3d0f8..959eaa0a70 100644 --- a/engines/pegasus/neighborhood/mars/mars.cpp +++ b/engines/pegasus/neighborhood/mars/mars.cpp @@ -2643,7 +2643,7 @@ void Mars::startUpFromSpaceChase() { // Open the spot sounds movie again... _spotSounds.initFromQuickTime(getSoundSpotsName()); - _spotSounds.setVolume(_vm->getSoundFXLevel());; + _spotSounds.setVolume(_vm->getSoundFXLevel()); initOnePicture(&_shuttleInterface1, "Images/Mars/MCmain1.pict", kShuttleBackgroundOrder, kShuttle1Left, kShuttle1Top, true); diff --git a/engines/toltecs/screen.cpp b/engines/toltecs/screen.cpp index be91130c0a..1cd2373b43 100644 --- a/engines/toltecs/screen.cpp +++ b/engines/toltecs/screen.cpp @@ -494,6 +494,14 @@ int16 Screen::getTalkTextDuration() { return _talkTextItems[_talkTextItemNum].duration; } +void Screen::finishTalkTextItem(int16 slotIndex) { + for (int16 i = 0; i <= _talkTextItemNum; i++) { + if (_talkTextItems[i].slotIndex == slotIndex) { + _talkTextItems[i].duration = 0; + } + } +} + void Screen::finishTalkTextItems() { for (int16 i = 0; i <= _talkTextItemNum; i++) { _talkTextItems[i].duration = 0; diff --git a/engines/toltecs/screen.h b/engines/toltecs/screen.h index ee565e1882..52f412251e 100644 --- a/engines/toltecs/screen.h +++ b/engines/toltecs/screen.h @@ -183,6 +183,7 @@ public: void addTalkTextItemsToRenderQueue(); int16 getTalkTextDuration(); bool isTalkTextActive(int16 slotIndex); + void finishTalkTextItem(int16 slotIndex); void finishTalkTextItems(); void keepTalkTextItemsAlive(); diff --git a/engines/toltecs/script.cpp b/engines/toltecs/script.cpp index 9ea95a2cd1..07d74ac369 100644 --- a/engines/toltecs/script.cpp +++ b/engines/toltecs/script.cpp @@ -170,6 +170,18 @@ void ScriptInterpreter::setupScriptFunctions() { } void ScriptInterpreter::loadScript(uint resIndex, uint slotIndex) { + if (_slots[slotIndex].resIndex && _slots[slotIndex].resIndex != resIndex && _vm->_screen->isTalkTextActive(slotIndex)) { + // WORKAROUND: This happens when examining the assembled + // pickaxe. It could lead to random characters being printed, + // or possibly even crashes, when subtitles are enabled. + // + // According to johndoe and he said there may be some bug or + // missing feature that causes this situation to happen at all, + // but he was ok with this workaround for now. + warning("Possible script bug: Loading script %d into slot %d that has an active talk text, probably for script %d", resIndex, slotIndex, _slots[slotIndex].resIndex); + _vm->_screen->finishTalkTextItem(slotIndex); + } + delete[] _slots[slotIndex].data; _slots[slotIndex].resIndex = resIndex; diff --git a/gui/credits.h b/gui/credits.h index 42e515dd70..81d46b2b73 100644 --- a/gui/credits.h +++ b/gui/credits.h @@ -129,6 +129,11 @@ static const char *credits[] = { "C0""Scott Thomas", "C0""Jordi Vilalta Prat", "", +"C1""Hopkins", +"A0""Arnaud Boutonne", +"C0""Arnaud Boutonn\351", +"C0""Paul Gilbert", +"", "C1""Hugo", "A0""Arnaud Boutonne", "C0""Arnaud Boutonn\351", @@ -375,6 +380,9 @@ static const char *credits[] = { "C2""Heavily improved de-/encoder for DXA videos", "C0""Jochen Hoenicke", "C2""Speaker & PCjr sound support, AdLib work (retired)", +"A0""Daniel ter Laan", +"C0""Dani\353l ter Laan", +"C2""Restoring original Drascula tracks, and writing convert_dxa.bat", "C0""Chris Page", "C2""Return to launcher, savestate improvements, leak fixes, ... (GSoC 2008 task) (retired)", "C0""Robin Watts", @@ -86,6 +86,12 @@ endif cp $(srcdir)/dists/iphone/icon.png $(bundle_name)/ cp $(srcdir)/dists/iphone/icon-72.png $(bundle_name)/ cp $(srcdir)/dists/iphone/Default.png $(bundle_name)/ + # Binary patch workaround for Iphone 5/IPad 4 "Illegal instruction: 4" toolchain issue (http://code.google.com/p/iphone-gcc-full/issues/detail?id=6) + cp scummvm scummvm-iph5 + sed -i'' 's/\x00\x30\x93\xe4/\x00\x30\x93\xe5/g;s/\x00\x30\xd3\xe4/\x00\x30\xd3\xe5/g;' scummvm-iph5 + ldid -S scummvm-iph5 + chmod 755 scummvm-iph5 + cp scummvm-iph5 $(bundle_name)/ScummVM-iph5 # Location of static libs for the iPhone ifneq ($(BACKEND), iphone) |