mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-02 23:26:44 +00:00
Merge branch 'master' into zvision
This commit is contained in:
commit
49d67caa31
3
NEWS
3
NEWS
@ -2,6 +2,9 @@ For a more comprehensive changelog of the latest experimental code, see:
|
||||
https://github.com/scummvm/scummvm/commits/
|
||||
|
||||
1.7.0 (????-??-??)
|
||||
General:
|
||||
- Updated MT-32 emulation code to version 1.3.0.
|
||||
|
||||
Gob:
|
||||
- Improved video quality in Urban Runner
|
||||
|
||||
|
@ -44,7 +44,8 @@ _centerPitchWheelOnUnload(false),
|
||||
_sendSustainOffOnNotesOff(false),
|
||||
_numTracks(0),
|
||||
_activeTrack(255),
|
||||
_abortParse(0) {
|
||||
_abortParse(false),
|
||||
_jumpingToTick(false) {
|
||||
memset(_activeNotes, 0, sizeof(_activeNotes));
|
||||
memset(_tracks, 0, sizeof(_tracks));
|
||||
_nextEvent.start = NULL;
|
||||
@ -204,49 +205,22 @@ void MidiParser::onTimer() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (info.event == 0xF0) {
|
||||
// SysEx event
|
||||
// Check for trailing 0xF7 -- if present, remove it.
|
||||
if (info.ext.data[info.length-1] == 0xF7)
|
||||
_driver->sysEx(info.ext.data, (uint16)info.length-1);
|
||||
if (info.command() == 0x8) {
|
||||
activeNote(info.channel(), info.basic.param1, false);
|
||||
} else if (info.command() == 0x9) {
|
||||
if (info.length > 0)
|
||||
hangingNote(info.channel(), info.basic.param1, info.length * _psecPerTick - (endTime - eventTime));
|
||||
else
|
||||
_driver->sysEx(info.ext.data, (uint16)info.length);
|
||||
} else if (info.event == 0xFF) {
|
||||
// META event
|
||||
if (info.ext.type == 0x2F) {
|
||||
// End of Track must be processed by us,
|
||||
// as well as sending it to the output device.
|
||||
if (_autoLoop) {
|
||||
jumpToTick(0);
|
||||
parseNextEvent(_nextEvent);
|
||||
} else {
|
||||
stopPlaying();
|
||||
_driver->metaEvent(info.ext.type, info.ext.data, (uint16)info.length);
|
||||
}
|
||||
return;
|
||||
} else if (info.ext.type == 0x51) {
|
||||
if (info.length >= 3) {
|
||||
setTempo(info.ext.data[0] << 16 | info.ext.data[1] << 8 | info.ext.data[2]);
|
||||
}
|
||||
}
|
||||
_driver->metaEvent(info.ext.type, info.ext.data, (uint16)info.length);
|
||||
} else {
|
||||
if (info.command() == 0x8) {
|
||||
activeNote(info.channel(), info.basic.param1, false);
|
||||
} else if (info.command() == 0x9) {
|
||||
if (info.length > 0)
|
||||
hangingNote(info.channel(), info.basic.param1, info.length * _psecPerTick - (endTime - eventTime));
|
||||
else
|
||||
activeNote(info.channel(), info.basic.param1, true);
|
||||
}
|
||||
sendToDriver(info.event, info.basic.param1, info.basic.param2);
|
||||
activeNote(info.channel(), info.basic.param1, true);
|
||||
}
|
||||
|
||||
processEvent(info);
|
||||
|
||||
if (!_abortParse) {
|
||||
_position._lastEventTime = eventTime;
|
||||
parseNextEvent(_nextEvent);
|
||||
}
|
||||
if (_abortParse)
|
||||
break;
|
||||
|
||||
_position._lastEventTime = eventTime;
|
||||
parseNextEvent(_nextEvent);
|
||||
}
|
||||
|
||||
if (!_abortParse) {
|
||||
@ -255,6 +229,45 @@ void MidiParser::onTimer() {
|
||||
}
|
||||
}
|
||||
|
||||
void MidiParser::processEvent(const EventInfo &info, bool fireEvents) {
|
||||
if (info.event == 0xF0) {
|
||||
// SysEx event
|
||||
// Check for trailing 0xF7 -- if present, remove it.
|
||||
if (fireEvents) {
|
||||
if (info.ext.data[info.length-1] == 0xF7)
|
||||
_driver->sysEx(info.ext.data, (uint16)info.length-1);
|
||||
else
|
||||
_driver->sysEx(info.ext.data, (uint16)info.length);
|
||||
}
|
||||
} else if (info.event == 0xFF) {
|
||||
// META event
|
||||
if (info.ext.type == 0x2F) {
|
||||
// End of Track must be processed by us,
|
||||
// as well as sending it to the output device.
|
||||
if (_autoLoop) {
|
||||
jumpToTick(0);
|
||||
parseNextEvent(_nextEvent);
|
||||
} else {
|
||||
stopPlaying();
|
||||
if (fireEvents)
|
||||
_driver->metaEvent(info.ext.type, info.ext.data, (uint16)info.length);
|
||||
}
|
||||
_abortParse = true;
|
||||
return;
|
||||
} else if (info.ext.type == 0x51) {
|
||||
if (info.length >= 3) {
|
||||
setTempo(info.ext.data[0] << 16 | info.ext.data[1] << 8 | info.ext.data[2]);
|
||||
}
|
||||
}
|
||||
if (fireEvents)
|
||||
_driver->metaEvent(info.ext.type, info.ext.data, (uint16)info.length);
|
||||
} else {
|
||||
if (fireEvents)
|
||||
sendToDriver(info.event, info.basic.param1, info.basic.param2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MidiParser::allNotesOff() {
|
||||
if (!_driver)
|
||||
return;
|
||||
@ -370,6 +383,9 @@ bool MidiParser::jumpToTick(uint32 tick, bool fireEvents, bool stopNotes, bool d
|
||||
if (_activeTrack >= _numTracks)
|
||||
return false;
|
||||
|
||||
assert(!_jumpingToTick); // This function is not re-entrant
|
||||
_jumpingToTick = true;
|
||||
|
||||
Tracker currentPos(_position);
|
||||
EventInfo currentEvent(_nextEvent);
|
||||
|
||||
@ -390,34 +406,19 @@ bool MidiParser::jumpToTick(uint32 tick, bool fireEvents, bool stopNotes, bool d
|
||||
_position._playTick = _position._lastEventTick;
|
||||
_position._playTime = _position._lastEventTime;
|
||||
|
||||
if (info.event == 0xFF) {
|
||||
if (info.ext.type == 0x2F) { // End of track
|
||||
_position = currentPos;
|
||||
_nextEvent = currentEvent;
|
||||
return false;
|
||||
} else {
|
||||
if (info.ext.type == 0x51 && info.length >= 3) // Tempo
|
||||
setTempo(info.ext.data[0] << 16 | info.ext.data[1] << 8 | info.ext.data[2]);
|
||||
if (fireEvents)
|
||||
_driver->metaEvent(info.ext.type, info.ext.data, (uint16) info.length);
|
||||
}
|
||||
} else if (fireEvents) {
|
||||
if (info.event == 0xF0) {
|
||||
if (info.ext.data[info.length-1] == 0xF7)
|
||||
_driver->sysEx(info.ext.data, (uint16)info.length-1);
|
||||
else
|
||||
_driver->sysEx(info.ext.data, (uint16)info.length);
|
||||
} else {
|
||||
// The note on sending code is used by the SCUMM engine. Other engine using this code
|
||||
// (such as SCI) have issues with this, as all the notes sent can be heard when a song
|
||||
// is fast-forwarded. Thus, if the engine requests it, don't send note on events.
|
||||
if (info.command() == 0x9 && dontSendNoteOn) {
|
||||
// Don't send note on; doing so creates a "warble" with some instruments on the MT-32.
|
||||
// Refer to patch #3117577
|
||||
} else {
|
||||
sendToDriver(info.event, info.basic.param1, info.basic.param2);
|
||||
}
|
||||
}
|
||||
// Some special processing for the fast-forward case
|
||||
if (info.command() == 0x9 && dontSendNoteOn) {
|
||||
// Don't send note on; doing so creates a "warble" with
|
||||
// some instruments on the MT-32. Refer to patch #3117577
|
||||
} else if (info.event == 0xFF && info.ext.type == 0x2F) {
|
||||
// End of track
|
||||
// This means that we failed to find the right tick.
|
||||
_position = currentPos;
|
||||
_nextEvent = currentEvent;
|
||||
_jumpingToTick = false;
|
||||
return false;
|
||||
} else {
|
||||
processEvent(info, fireEvents);
|
||||
}
|
||||
|
||||
parseNextEvent(_nextEvent);
|
||||
@ -441,6 +442,7 @@ bool MidiParser::jumpToTick(uint32 tick, bool fireEvents, bool stopNotes, bool d
|
||||
}
|
||||
|
||||
_abortParse = true;
|
||||
_jumpingToTick = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -105,8 +105,8 @@ struct EventInfo {
|
||||
///< will occur, and the MidiParser will have to generate one itself.
|
||||
///< For all other events, this value should always be zero.
|
||||
|
||||
byte channel() { return event & 0x0F; } ///< Separates the MIDI channel from the event.
|
||||
byte command() { return event >> 4; } ///< Separates the command code from the event.
|
||||
byte channel() const { return event & 0x0F; } ///< Separates the MIDI channel from the event.
|
||||
byte command() const { return event >> 4; } ///< Separates the command code from the event.
|
||||
};
|
||||
|
||||
/**
|
||||
@ -287,12 +287,14 @@ protected:
|
||||
///< so each event is parsed only once; this permits
|
||||
///< simulated events in certain formats.
|
||||
bool _abortParse; ///< If a jump or other operation interrupts parsing, flag to abort.
|
||||
bool _jumpingToTick; ///< True if currently inside jumpToTick
|
||||
|
||||
protected:
|
||||
static uint32 readVLQ(byte * &data);
|
||||
virtual void resetTracking();
|
||||
virtual void allNotesOff();
|
||||
virtual void parseNextEvent(EventInfo &info) = 0;
|
||||
virtual void processEvent(const EventInfo &info, bool fireEvents = true);
|
||||
|
||||
void activeNote(byte channel, byte note, bool active);
|
||||
void hangingNote(byte channel, byte note, uint32 ticksLeft, bool recycle = true);
|
||||
|
@ -315,15 +315,29 @@ void LA32PartialPair::generateNextSample(const PairType useMaster, const Bit32u
|
||||
}
|
||||
}
|
||||
|
||||
float LA32PartialPair::nextOutSample() {
|
||||
float outputSample;
|
||||
if (ringModulated) {
|
||||
float ringModulatedSample = masterOutputSample * slaveOutputSample;
|
||||
outputSample = mixed ? masterOutputSample + ringModulatedSample : ringModulatedSample;
|
||||
} else {
|
||||
outputSample = masterOutputSample + slaveOutputSample;
|
||||
static inline float produceDistortedSample(float sample) {
|
||||
if (sample < -1.0f) {
|
||||
return sample + 2.0f;
|
||||
} else if (1.0f < sample) {
|
||||
return sample - 2.0f;
|
||||
}
|
||||
return outputSample;
|
||||
return sample;
|
||||
}
|
||||
|
||||
float LA32PartialPair::nextOutSample() {
|
||||
if (!ringModulated) {
|
||||
return masterOutputSample + slaveOutputSample;
|
||||
}
|
||||
/*
|
||||
* SEMI-CONFIRMED: Ring modulation model derived from sample analysis of specially constructed patches which exploit distortion.
|
||||
* LA32 ring modulator found to produce distorted output in case if the absolute value of maximal amplitude of one of the input partials exceeds 8191.
|
||||
* This is easy to reproduce using synth partials with resonance values close to the maximum. It looks like an integer overflow happens in this case.
|
||||
* As the distortion is strictly bound to the amplitude of the complete mixed square + resonance wave in the linear space,
|
||||
* it is reasonable to assume the ring modulation is performed also in the linear space by sample multiplication.
|
||||
* Most probably the overflow is caused by limited precision of the multiplication circuit as the very similar distortion occurs with panning.
|
||||
*/
|
||||
float ringModulatedSample = produceDistortedSample(masterOutputSample) * produceDistortedSample(slaveOutputSample);
|
||||
return mixed ? masterOutputSample + ringModulatedSample : ringModulatedSample;
|
||||
}
|
||||
|
||||
void LA32PartialPair::deactivate(const PairType useMaster) {
|
||||
|
@ -370,18 +370,12 @@ void LA32PartialPair::generateNextSample(const PairType useMaster, const Bit32u
|
||||
}
|
||||
}
|
||||
|
||||
Bit16s LA32PartialPair::unlogAndMixWGOutput(const LA32WaveGenerator &wg, const LogSample * const ringModulatingLogSample) {
|
||||
if (!wg.isActive() || ((ringModulatingLogSample != NULL) && (ringModulatingLogSample->logValue == SILENCE.logValue))) {
|
||||
Bit16s LA32PartialPair::unlogAndMixWGOutput(const LA32WaveGenerator &wg) {
|
||||
if (!wg.isActive()) {
|
||||
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);
|
||||
Bit16s firstSample = LA32Utilites::unlog(wg.getOutputLogSample(true));
|
||||
Bit16s secondSample = LA32Utilites::unlog(wg.getOutputLogSample(false));
|
||||
if (wg.isPCMWave()) {
|
||||
return Bit16s(firstSample + ((Bit32s(secondSample - firstSample) * wg.getPCMInterpolationFactor()) >> 7));
|
||||
}
|
||||
@ -389,19 +383,32 @@ Bit16s LA32PartialPair::unlogAndMixWGOutput(const LA32WaveGenerator &wg, const L
|
||||
}
|
||||
|
||||
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;
|
||||
if (!ringModulated) {
|
||||
return unlogAndMixWGOutput(master) + unlogAndMixWGOutput(slave);
|
||||
}
|
||||
return unlogAndMixWGOutput(master, NULL) + unlogAndMixWGOutput(slave, NULL);
|
||||
|
||||
/*
|
||||
* SEMI-CONFIRMED: Ring modulation model derived from sample analysis of specially constructed patches which exploit distortion.
|
||||
* LA32 ring modulator found to produce distorted output in case if the absolute value of maximal amplitude of one of the input partials exceeds 8191.
|
||||
* This is easy to reproduce using synth partials with resonance values close to the maximum. It looks like an integer overflow happens in this case.
|
||||
* As the distortion is strictly bound to the amplitude of the complete mixed square + resonance wave in the linear space,
|
||||
* it is reasonable to assume the ring modulation is performed also in the linear space by sample multiplication.
|
||||
* Most probably the overflow is caused by limited precision of the multiplication circuit as the very similar distortion occurs with panning.
|
||||
*/
|
||||
Bit16s nonOverdrivenMasterSample = unlogAndMixWGOutput(master); // Store master partial sample for further mixing
|
||||
Bit16s masterSample = nonOverdrivenMasterSample << 2;
|
||||
masterSample >>= 2;
|
||||
|
||||
/* SEMI-CONFIRMED from sample analysis:
|
||||
* 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).
|
||||
*/
|
||||
Bit16s slaveSample = slave.isPCMWave() ? LA32Utilites::unlog(slave.getOutputLogSample(true)) : unlogAndMixWGOutput(slave);
|
||||
slaveSample <<= 2;
|
||||
slaveSample >>= 2;
|
||||
Bit16s ringModulatedSample = Bit16s(((Bit32s)masterSample * (Bit32s)slaveSample) >> 13);
|
||||
return mixed ? nonOverdrivenMasterSample + ringModulatedSample : ringModulatedSample;
|
||||
}
|
||||
|
||||
void LA32PartialPair::deactivate(const PairType useMaster) {
|
||||
|
@ -209,7 +209,7 @@ class LA32PartialPair {
|
||||
bool ringModulated;
|
||||
bool mixed;
|
||||
|
||||
static Bit16s unlogAndMixWGOutput(const LA32WaveGenerator &wg, const LogSample * const ringModulatingLogSample);
|
||||
static Bit16s unlogAndMixWGOutput(const LA32WaveGenerator &wg);
|
||||
|
||||
public:
|
||||
enum PairType {
|
||||
|
@ -24,15 +24,10 @@
|
||||
|
||||
namespace MT32Emu {
|
||||
|
||||
#ifdef INACCURATE_SMOOTH_PAN
|
||||
// Mok wanted an option for smoother panning, and we love Mok.
|
||||
static const float PAN_NUMERATOR_NORMAL[] = {0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 4.5f, 5.0f, 5.5f, 6.0f, 6.5f, 7.0f};
|
||||
#else
|
||||
// CONFIRMED by Mok: These NUMERATOR values (as bytes, not floats, obviously) are sent exactly like this to the LA32.
|
||||
static const float PAN_NUMERATOR_NORMAL[] = {0.0f, 0.0f, 1.0f, 1.0f, 2.0f, 2.0f, 3.0f, 3.0f, 4.0f, 4.0f, 5.0f, 5.0f, 6.0f, 6.0f, 7.0f};
|
||||
#endif
|
||||
static const float PAN_NUMERATOR_MASTER[] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.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};
|
||||
static const Bit8u PAN_NUMERATOR_MASTER[] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7};
|
||||
static const Bit8u PAN_NUMERATOR_SLAVE[] = {0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7};
|
||||
|
||||
static const Bit32s PAN_FACTORS[] = {0, 18, 37, 55, 73, 91, 110, 128, 146, 165, 183, 201, 219, 238, 256};
|
||||
|
||||
Partial::Partial(Synth *useSynth, int useDebugPartialNum) :
|
||||
synth(useSynth), debugPartialNum(useDebugPartialNum), sampleNum(0) {
|
||||
@ -116,24 +111,30 @@ void Partial::startPartial(const Part *part, Poly *usePoly, const PatchCache *us
|
||||
structurePosition = patchCache->structurePosition;
|
||||
|
||||
Bit8u panSetting = rhythmTemp != NULL ? rhythmTemp->panpot : part->getPatchTemp()->panpot;
|
||||
float panVal;
|
||||
if (mixType == 3) {
|
||||
if (structurePosition == 0) {
|
||||
panVal = PAN_NUMERATOR_MASTER[panSetting];
|
||||
panSetting = PAN_NUMERATOR_MASTER[panSetting] << 1;
|
||||
} else {
|
||||
panVal = PAN_NUMERATOR_SLAVE[panSetting];
|
||||
panSetting = PAN_NUMERATOR_SLAVE[panSetting] << 1;
|
||||
}
|
||||
// Do a normal mix independent of any pair partial.
|
||||
mixType = 0;
|
||||
pairPartial = NULL;
|
||||
} else {
|
||||
panVal = PAN_NUMERATOR_NORMAL[panSetting];
|
||||
// Mok wanted an option for smoother panning, and we love Mok.
|
||||
#ifndef INACCURATE_SMOOTH_PAN
|
||||
// CONFIRMED by Mok: exactly bytes like this (right shifted?) are sent to the LA32.
|
||||
panSetting &= 0x0E;
|
||||
#endif
|
||||
}
|
||||
|
||||
// FIXME: Sample analysis suggests that the use of panVal is linear, but there are some some quirks that still need to be resolved.
|
||||
// FIXME: I suppose this should be panVal / 8 and undoubtly integer, clarify ASAP
|
||||
stereoVolume.leftVol = panVal / 7.0f;
|
||||
stereoVolume.rightVol = 1.0f - stereoVolume.leftVol;
|
||||
leftPanValue = synth->reversedStereoEnabled ? 14 - panSetting : panSetting;
|
||||
rightPanValue = 14 - leftPanValue;
|
||||
|
||||
#if !MT32EMU_USE_FLOAT_SAMPLES
|
||||
leftPanValue = PAN_FACTORS[leftPanValue];
|
||||
rightPanValue = PAN_FACTORS[rightPanValue];
|
||||
#endif
|
||||
|
||||
// SEMI-CONFIRMED: From sample analysis:
|
||||
// Found that timbres with 3 or 4 partials (i.e. one using two partial pairs) are mixed in two different ways.
|
||||
@ -150,8 +151,8 @@ void Partial::startPartial(const Part *part, Poly *usePoly, const PatchCache *us
|
||||
// For my personal taste, this behaviour rather enriches the sounding and should be emulated.
|
||||
// Also, the current partial allocator model probably needs to be refined.
|
||||
if (debugPartialNum & 8) {
|
||||
stereoVolume.leftVol = -stereoVolume.leftVol;
|
||||
stereoVolume.rightVol = -stereoVolume.rightVol;
|
||||
leftPanValue = -leftPanValue;
|
||||
rightPanValue = -rightPanValue;
|
||||
}
|
||||
|
||||
if (patchCache->PCMPartial) {
|
||||
@ -230,39 +231,6 @@ Bit32u Partial::getCutoffValue() {
|
||||
return (tvf->getBaseCutoff() << 18) + cutoffModifierRampVal;
|
||||
}
|
||||
|
||||
unsigned long Partial::generateSamples(Sample *partialBuf, unsigned long length) {
|
||||
if (!isActive() || alreadyOutputed) {
|
||||
return 0;
|
||||
}
|
||||
if (poly == NULL) {
|
||||
synth->printDebug("[Partial %d] *** ERROR: poly is NULL at Partial::generateSamples()!", debugPartialNum);
|
||||
return 0;
|
||||
}
|
||||
alreadyOutputed = true;
|
||||
|
||||
for (sampleNum = 0; sampleNum < length; sampleNum++) {
|
||||
if (!tva->isPlaying() || !la32Pair.isActive(LA32PartialPair::MASTER)) {
|
||||
deactivate();
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
*(partialBuf++) = la32Pair.nextOutSample();
|
||||
}
|
||||
unsigned long renderedSamples = sampleNum;
|
||||
sampleNum = 0;
|
||||
return renderedSamples;
|
||||
}
|
||||
|
||||
bool Partial::hasRingModulatingSlave() const {
|
||||
return pair != NULL && structurePosition == 0 && (mixType == 1 || mixType == 2);
|
||||
}
|
||||
@ -305,19 +273,52 @@ bool Partial::produceOutput(Sample *leftBuf, Sample *rightBuf, unsigned long len
|
||||
synth->printDebug("[Partial %d] *** ERROR: poly is NULL at Partial::produceOutput()!", debugPartialNum);
|
||||
return false;
|
||||
}
|
||||
Sample buffer[MAX_SAMPLES_PER_RUN];
|
||||
unsigned long numGenerated = generateSamples(buffer, length);
|
||||
for (unsigned int i = 0; i < numGenerated; i++) {
|
||||
alreadyOutputed = true;
|
||||
|
||||
for (sampleNum = 0; sampleNum < length; sampleNum++) {
|
||||
if (!tva->isPlaying() || !la32Pair.isActive(LA32PartialPair::MASTER)) {
|
||||
deactivate();
|
||||
break;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Although, LA32 applies panning itself, we assume here it is applied in the mixer, not within a pair.
|
||||
// Applying the pan value in the log-space looks like a waste of unlog resources. Though, it needs clarification.
|
||||
Sample sample = la32Pair.nextOutSample();
|
||||
|
||||
// FIXME: Sample analysis suggests that the use of panVal is linear, but there are some quirks that still need to be resolved.
|
||||
#if MT32EMU_USE_FLOAT_SAMPLES
|
||||
*(leftBuf++) += buffer[i] * stereoVolume.leftVol;
|
||||
*(rightBuf++) += buffer[i] * stereoVolume.rightVol;
|
||||
Sample leftOut = (sample * (float)leftPanValue) / 14.0f;
|
||||
Sample rightOut = (sample * (float)rightPanValue) / 14.0f;
|
||||
*(leftBuf++) += leftOut;
|
||||
*(rightBuf++) += rightOut;
|
||||
#else
|
||||
*leftBuf = Synth::clipBit16s((Bit32s)*leftBuf + Bit32s(buffer[i] * stereoVolume.leftVol));
|
||||
*rightBuf = Synth::clipBit16s((Bit32s)*rightBuf + Bit32s(buffer[i] * stereoVolume.rightVol));
|
||||
// FIXME: Dividing by 7 (or by 14 in a Mok-friendly way) looks of course pointless. Need clarification.
|
||||
// FIXME2: LA32 may produce distorted sound in case if the absolute value of maximal amplitude of the input exceeds 8191
|
||||
// when the panning value is non-zero. Most probably the distortion occurs in the same way it does with ring modulation,
|
||||
// and it seems to be caused by limited precision of the common multiplication circuit.
|
||||
// From analysis of this overflow, it is obvious that the right channel output is actually found
|
||||
// by subtraction of the left channel output from the input.
|
||||
// Though, it is unknown whether this overflow is exploited somewhere.
|
||||
Sample leftOut = Sample((sample * leftPanValue) >> 8);
|
||||
Sample rightOut = Sample((sample * rightPanValue) >> 8);
|
||||
*leftBuf = Synth::clipBit16s((Bit32s)*leftBuf + (Bit32s)leftOut);
|
||||
*rightBuf = Synth::clipBit16s((Bit32s)*rightBuf + (Bit32s)rightOut);
|
||||
leftBuf++;
|
||||
rightBuf++;
|
||||
#endif
|
||||
}
|
||||
sampleNum = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -25,24 +25,22 @@ class Part;
|
||||
class TVA;
|
||||
struct ControlROMPCMStruct;
|
||||
|
||||
struct StereoVolume {
|
||||
float leftVol;
|
||||
float rightVol;
|
||||
};
|
||||
|
||||
// A partial represents one of up to four waveform generators currently playing within a poly.
|
||||
class Partial {
|
||||
private:
|
||||
Synth *synth;
|
||||
const int debugPartialNum; // Only used for debugging
|
||||
// Number of the sample currently being rendered by generateSamples(), or 0 if no run is in progress
|
||||
// Number of the sample currently being rendered by produceOutput(), or 0 if no run is in progress
|
||||
// This is only kept available for debugging purposes.
|
||||
unsigned long sampleNum;
|
||||
|
||||
// Actually, this is a 4-bit register but we abuse this to emulate inverted mixing.
|
||||
// Also we double the value to enable INACCURATE_SMOOTH_PAN, with respect to MoK.
|
||||
Bit32s leftPanValue, rightPanValue;
|
||||
|
||||
int ownerPart; // -1 if unassigned
|
||||
int mixType;
|
||||
int structurePosition; // 0 or 1 of a structure pair
|
||||
StereoVolume stereoVolume;
|
||||
|
||||
// Only used for PCM partials
|
||||
int pcmNum;
|
||||
@ -103,9 +101,6 @@ public:
|
||||
// This function (unlike the one below it) returns processed stereo samples
|
||||
// made from combining this single partial with its pair, if it has one.
|
||||
bool produceOutput(Sample *leftBuf, Sample *rightBuf, unsigned long length);
|
||||
|
||||
// This function writes mono sample output to the provided buffer, and returns the number of samples written
|
||||
unsigned long generateSamples(Sample *partialBuf, unsigned long length);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -76,6 +76,7 @@ Synth::Synth(ReportHandler *useReportHandler) {
|
||||
isOpen = false;
|
||||
reverbEnabled = true;
|
||||
reverbOverridden = false;
|
||||
partialCount = DEFAULT_MAX_PARTIALS;
|
||||
|
||||
if (useReportHandler == NULL) {
|
||||
reportHandler = new ReportHandler;
|
||||
@ -95,6 +96,7 @@ Synth::Synth(ReportHandler *useReportHandler) {
|
||||
setMIDIDelayMode(MIDIDelayMode_DELAY_SHORT_MESSAGES_ONLY);
|
||||
setOutputGain(1.0f);
|
||||
setReverbOutputGain(1.0f);
|
||||
setReversedStereoEnabled(false);
|
||||
partialManager = NULL;
|
||||
midiQueue = NULL;
|
||||
lastReceivedMIDIEventTimestamp = 0;
|
||||
@ -172,6 +174,8 @@ MIDIDelayMode Synth::getMIDIDelayMode() const {
|
||||
return midiDelayMode;
|
||||
}
|
||||
|
||||
#if MT32EMU_USE_FLOAT_SAMPLES
|
||||
|
||||
void Synth::setOutputGain(float newOutputGain) {
|
||||
outputGain = newOutputGain;
|
||||
}
|
||||
@ -188,6 +192,39 @@ float Synth::getReverbOutputGain() const {
|
||||
return reverbOutputGain;
|
||||
}
|
||||
|
||||
#else // #if MT32EMU_USE_FLOAT_SAMPLES
|
||||
|
||||
void Synth::setOutputGain(float newOutputGain) {
|
||||
if (newOutputGain < 0.0f) newOutputGain = -newOutputGain;
|
||||
if (256.0f < newOutputGain) newOutputGain = 256.0f;
|
||||
outputGain = int(newOutputGain * 256.0f);
|
||||
}
|
||||
|
||||
float Synth::getOutputGain() const {
|
||||
return outputGain / 256.0f;
|
||||
}
|
||||
|
||||
void Synth::setReverbOutputGain(float newReverbOutputGain) {
|
||||
if (newReverbOutputGain < 0.0f) newReverbOutputGain = -newReverbOutputGain;
|
||||
float maxValue = 256.0f / CM32L_REVERB_TO_LA32_ANALOG_OUTPUT_GAIN_FACTOR;
|
||||
if (maxValue < newReverbOutputGain) newReverbOutputGain = maxValue;
|
||||
reverbOutputGain = int(newReverbOutputGain * 256.0f);
|
||||
}
|
||||
|
||||
float Synth::getReverbOutputGain() const {
|
||||
return reverbOutputGain / 256.0f;
|
||||
}
|
||||
|
||||
#endif // #if MT32EMU_USE_FLOAT_SAMPLES
|
||||
|
||||
void Synth::setReversedStereoEnabled(bool enabled) {
|
||||
reversedStereoEnabled = enabled;
|
||||
}
|
||||
|
||||
bool Synth::isReversedStereoEnabled() {
|
||||
return reversedStereoEnabled;
|
||||
}
|
||||
|
||||
bool Synth::loadControlROM(const ROMImage &controlROMImage) {
|
||||
if (&controlROMImage == NULL) return false;
|
||||
Common::File *file = controlROMImage.getFile();
|
||||
@ -1445,16 +1482,19 @@ void Synth::convertSamplesToOutput(Sample *target, const Sample *source, Bit32u
|
||||
*(target++) = *(source++) * gain;
|
||||
}
|
||||
#else
|
||||
float gain = reverb ? reverbOutputGain * CM32L_REVERB_TO_LA32_ANALOG_OUTPUT_GAIN_FACTOR : outputGain;
|
||||
if (!reverb) {
|
||||
int gain;
|
||||
if (reverb) {
|
||||
gain = int(reverbOutputGain * CM32L_REVERB_TO_LA32_ANALOG_OUTPUT_GAIN_FACTOR);
|
||||
} else {
|
||||
gain = outputGain;
|
||||
switch (dacInputMode) {
|
||||
case DACInputMode_NICE:
|
||||
// Since we're not shooting for accuracy here, don't worry about the rounding mode.
|
||||
gain *= 2.0f;
|
||||
gain <<= 1;
|
||||
break;
|
||||
case DACInputMode_GENERATION1:
|
||||
while (len--) {
|
||||
*target = clipBit16s(Bit32s(*source * gain));
|
||||
*target = clipBit16s(Bit32s((*source * gain) >> 8));
|
||||
*target = (*target & 0x8000) | ((*target << 1) & 0x7FFE);
|
||||
source++;
|
||||
target++;
|
||||
@ -1462,7 +1502,7 @@ void Synth::convertSamplesToOutput(Sample *target, const Sample *source, Bit32u
|
||||
return;
|
||||
case DACInputMode_GENERATION2:
|
||||
while (len--) {
|
||||
*target = clipBit16s(Bit32s(*source * gain));
|
||||
*target = clipBit16s(Bit32s((*source * gain) >> 8));
|
||||
*target = (*target & 0x8000) | ((*target << 1) & 0x7FFE) | ((*target >> 14) & 0x0001);
|
||||
source++;
|
||||
target++;
|
||||
@ -1473,7 +1513,7 @@ void Synth::convertSamplesToOutput(Sample *target, const Sample *source, Bit32u
|
||||
}
|
||||
}
|
||||
while (len--) {
|
||||
*(target++) = clipBit16s(Bit32s(*(source++) * gain));
|
||||
*(target++) = clipBit16s(Bit32s((*(source++) * gain) >> 8));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -343,8 +343,16 @@ private:
|
||||
|
||||
MIDIDelayMode midiDelayMode;
|
||||
DACInputMode dacInputMode;
|
||||
|
||||
#if MT32EMU_USE_FLOAT_SAMPLES
|
||||
float outputGain;
|
||||
float reverbOutputGain;
|
||||
#else
|
||||
int outputGain;
|
||||
int reverbOutputGain;
|
||||
#endif
|
||||
|
||||
bool reversedStereoEnabled;
|
||||
|
||||
bool isOpen;
|
||||
|
||||
@ -477,6 +485,9 @@ public:
|
||||
void setReverbOutputGain(float);
|
||||
float getReverbOutputGain() const;
|
||||
|
||||
void setReversedStereoEnabled(bool enabled);
|
||||
bool isReversedStereoEnabled();
|
||||
|
||||
// Renders samples to the specified output stream.
|
||||
// The length is in frames, not bytes (in 16-bit stereo,
|
||||
// one frame is 4 bytes).
|
||||
|
@ -54,6 +54,8 @@ DefaultEventManager::DefaultEventManager(Common::EventSource *boss) :
|
||||
_currentKeyDown.ascii = 0;
|
||||
_currentKeyDown.flags = 0;
|
||||
|
||||
_keyRepeatTime = 0;
|
||||
|
||||
#ifdef ENABLE_VKEYBD
|
||||
_vk = new Common::VirtualKeyboard();
|
||||
#endif
|
||||
|
@ -129,4 +129,12 @@ const char *gScummVMFeatures = ""
|
||||
#ifdef USE_FREETYPE2
|
||||
"FreeType2 "
|
||||
#endif
|
||||
|
||||
#ifdef USE_JPEG
|
||||
"JPEG "
|
||||
#endif
|
||||
|
||||
#ifdef USE_PNG
|
||||
"PNG "
|
||||
#endif
|
||||
;
|
||||
|
@ -128,7 +128,7 @@ public:
|
||||
*/
|
||||
#define CORO_BEGIN_CONTEXT \
|
||||
struct CoroContextTag : Common::CoroBaseContext { \
|
||||
CoroContextTag() : CoroBaseContext(SCUMMVM_CURRENT_FUNCTION) {} \
|
||||
CoroContextTag() : CoroBaseContext(SCUMMVM_CURRENT_FUNCTION) { DUMMY = 0; } \
|
||||
int DUMMY
|
||||
|
||||
/**
|
||||
@ -146,6 +146,7 @@ public:
|
||||
#define CORO_BEGIN_CODE(x) \
|
||||
if (&coroParam == &Common::nullContext) assert(!Common::nullContext); \
|
||||
if (!x) { coroParam = x = new CoroContextTag(); } \
|
||||
x->DUMMY = 0; \
|
||||
Common::CoroContextHolder tmpHolder(coroParam); \
|
||||
switch (coroParam->_line) { case 0:;
|
||||
|
||||
|
@ -371,12 +371,14 @@ bool DecompressorDCL::unpack(ReadStream *src, byte *dest, uint32 nPacked, uint32
|
||||
debug(8, "\nCOPY(%d from %d)\n", val_length, val_distance);
|
||||
|
||||
if (val_length + _dwWrote > _szUnpacked) {
|
||||
warning("DCL-INFLATE Error: Write out of bounds while copying %d bytes", val_length);
|
||||
warning("DCL-INFLATE Error: Write out of bounds while copying %d bytes (declared unpacked size is %d bytes, current is %d + %d bytes)",
|
||||
val_length, _szUnpacked, _dwWrote, val_length);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_dwWrote < val_distance) {
|
||||
warning("DCL-INFLATE Error: Attempt to copy from before beginning of input stream");
|
||||
warning("DCL-INFLATE Error: Attempt to copy from before beginning of input stream (declared unpacked size is %d bytes, current is %d bytes)",
|
||||
_szUnpacked, _dwWrote);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,10 @@
|
||||
#ifndef COMMON_SCUMMSYS_H
|
||||
#define COMMON_SCUMMSYS_H
|
||||
|
||||
#ifndef __has_feature // Optional of course.
|
||||
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
|
||||
#endif
|
||||
|
||||
// This is a convenience macro to test whether the compiler used is a GCC
|
||||
// version, which is at least major.minor.
|
||||
#define GCC_ATLEAST(major, minor) (defined(__GNUC__) && (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))))
|
||||
|
62
configure
vendored
62
configure
vendored
@ -115,6 +115,7 @@ _timidity=auto
|
||||
_zlib=auto
|
||||
_mpeg2=auto
|
||||
_sparkle=auto
|
||||
_jpeg=auto
|
||||
_png=auto
|
||||
_theoradec=auto
|
||||
_faad=auto
|
||||
@ -166,7 +167,7 @@ _windres=windres
|
||||
_stagingpath="staging"
|
||||
_win32path="c:/scummvm"
|
||||
_aos4path="Games:ScummVM"
|
||||
_staticlibpath=/sw
|
||||
_staticlibpath=
|
||||
_sdlconfig=sdl-config
|
||||
_freetypeconfig=freetype-config
|
||||
_sdlpath="$PATH"
|
||||
@ -188,6 +189,7 @@ add_feature faad "libfaad" "_faad"
|
||||
add_feature flac "FLAC" "_flac"
|
||||
add_feature freetype2 "FreeType2" "_freetype2"
|
||||
add_feature mad "MAD" "_mad"
|
||||
add_feature jpeg "JPEG" "_jpeg"
|
||||
add_feature png "PNG" "_png"
|
||||
add_feature theoradec "libtheoradec" "_theoradec"
|
||||
add_feature vorbis "Vorbis file support" "_vorbis _tremor"
|
||||
@ -936,6 +938,9 @@ Optional Libraries:
|
||||
--with-opengl-prefix=DIR Prefix where OpenGL (ES) is installed (optional)
|
||||
--disable-opengl disable OpenGL (ES) support [autodetect]
|
||||
|
||||
--with-jpeg-prefix=DIR Prefix where libjpeg is installed (optional)
|
||||
--disable-jpeg disable JPEG decoder [autodetect]
|
||||
|
||||
--with-png-prefix=DIR Prefix where libpng is installed (optional)
|
||||
--disable-png disable PNG decoder [autodetect]
|
||||
|
||||
@ -1015,6 +1020,8 @@ for ac_option in $@; do
|
||||
--disable-nasm) _nasm=no ;;
|
||||
--enable-mpeg2) _mpeg2=yes ;;
|
||||
--disable-mpeg2) _mpeg2=no ;;
|
||||
--disable-jpeg) _jpeg=no ;;
|
||||
--enable-jpeg) _jpeg=yes ;;
|
||||
--disable-png) _png=no ;;
|
||||
--enable-png) _png=yes ;;
|
||||
--disable-theoradec) _theoradec=no ;;
|
||||
@ -1096,6 +1103,11 @@ for ac_option in $@; do
|
||||
MAD_CFLAGS="-I$arg/include"
|
||||
MAD_LIBS="-L$arg/lib"
|
||||
;;
|
||||
--with-jpeg-prefix=*)
|
||||
arg=`echo $ac_option | cut -d '=' -f 2`
|
||||
JPEG_CFLAGS="-I$arg/include"
|
||||
JPEG_LIBS="-L$arg/lib"
|
||||
;;
|
||||
--with-png-prefix=*)
|
||||
arg=`echo $ac_option | cut -d '=' -f 2`
|
||||
PNG_CFLAGS="-I$arg/include"
|
||||
@ -2103,6 +2115,24 @@ case $_host_os in
|
||||
|
||||
LDFLAGS="-L${macport_prefix}/lib $LDFLAGS"
|
||||
CXXFLAGS="-I${macport_prefix}/include $CXXFLAGS"
|
||||
|
||||
if test -z "$_staticlibpath"; then
|
||||
_staticlibpath=${macport_prefix}
|
||||
echo "Set staticlib-prefix to ${_staticlibpath}"
|
||||
fi
|
||||
fi
|
||||
# If _staticlibpath is not set yet try first /sw (fink) then /usr/local
|
||||
# (the macports case is handled above).
|
||||
if test -z "$_staticlibpath"; then
|
||||
if test -d "/sw"; then
|
||||
_staticlibpath=/sw
|
||||
echo "Set staticlib-prefix to ${_staticlibpath}"
|
||||
elif test -d "/usr/local"; then
|
||||
_staticlibpath=/usr/local
|
||||
echo "Set staticlib-prefix to ${_staticlibpath}"
|
||||
else
|
||||
echo "Could not determine prefix for static libraries"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
dreamcast)
|
||||
@ -3338,6 +3368,32 @@ fi
|
||||
define_in_config_h_if_yes "$_alsa" 'USE_ALSA'
|
||||
echo "$_alsa"
|
||||
|
||||
#
|
||||
# Check for libjpeg
|
||||
#
|
||||
echocheck "libjpeg >= v6b"
|
||||
if test "$_jpeg" = auto ; then
|
||||
_jpeg=no
|
||||
cat > $TMPC << EOF
|
||||
#include <stdio.h>
|
||||
#include <jpeglib.h>
|
||||
int main(void) {
|
||||
#if JPEG_LIB_VERSION >= 62
|
||||
#else
|
||||
syntax error
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
cc_check $JPEG_CFLAGS $JPEG_LIBS -ljpeg && _jpeg=yes
|
||||
fi
|
||||
if test "$_jpeg" = yes ; then
|
||||
LIBS="$LIBS $JPEG_LIBS -ljpeg"
|
||||
INCLUDES="$INCLUDES $JPEG_CFLAGS"
|
||||
fi
|
||||
define_in_config_if_yes "$_jpeg" 'USE_JPEG'
|
||||
echo "$_jpeg"
|
||||
|
||||
#
|
||||
# Check for PNG
|
||||
#
|
||||
@ -3354,10 +3410,10 @@ int main(void) {
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
cc_check $PNG_CFLAGS $PNG_LIBS -lpng && _png=yes
|
||||
cc_check $PNG_CFLAGS $PNG_LIBS -lpng -lz && _png=yes
|
||||
fi
|
||||
if test "$_png" = yes ; then
|
||||
LIBS="$LIBS $PNG_LIBS -lpng"
|
||||
LIBS="$LIBS $PNG_LIBS -lpng -lz"
|
||||
INCLUDES="$INCLUDES $PNG_CFLAGS"
|
||||
fi
|
||||
define_in_config_if_yes "$_png" 'USE_PNG'
|
||||
|
@ -20,6 +20,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __has_feature // Optional of course.
|
||||
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
|
||||
#endif
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
|
@ -33,10 +33,6 @@
|
||||
#undef main
|
||||
#endif // main
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common/endian.h"
|
||||
#include "create_mortdat.h"
|
||||
#include "enginetext.h"
|
||||
|
@ -30,8 +30,8 @@
|
||||
#undef main
|
||||
#endif // main
|
||||
|
||||
#include <vector>
|
||||
#include "create_neverhood.h"
|
||||
#include <vector>
|
||||
#include "md5.h"
|
||||
#include "tables.h"
|
||||
|
||||
|
@ -64,6 +64,11 @@ std::string processLibraryName(std::string name) {
|
||||
if (pos != std::string::npos)
|
||||
return name.replace(pos, 7, "");
|
||||
|
||||
// Remove "-static" in lib name
|
||||
pos = name.find("-static");
|
||||
if (pos != std::string::npos)
|
||||
return name.replace(pos, 7, "");
|
||||
|
||||
// Replace "zlib" by "libz"
|
||||
if (name == "zlib")
|
||||
return "libz";
|
||||
|
@ -845,6 +845,7 @@ const Feature s_features[] = {
|
||||
{ "mpeg2", "USE_MPEG2", "libmpeg2", false, "MPEG-2 support" },
|
||||
{ "theora", "USE_THEORADEC", "libtheora_static", true, "Theora decoding support" },
|
||||
{"freetype", "USE_FREETYPE2", "freetype", true, "FreeType support" },
|
||||
{ "jpeg", "USE_JPEG", "jpeg-static", true, "libjpeg support" },
|
||||
|
||||
// Feature flags
|
||||
{ "bink", "USE_BINK", "", true, "Bink video support" },
|
||||
|
@ -23,6 +23,10 @@
|
||||
#ifndef TOOLS_CREATE_PROJECT_H
|
||||
#define TOOLS_CREATE_PROJECT_H
|
||||
|
||||
#ifndef __has_feature // Optional of course.
|
||||
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
|
||||
#endif
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
@ -22,6 +22,8 @@
|
||||
* The generated files is used by ScummVM to propose translation of its GUI.
|
||||
*/
|
||||
|
||||
#include "create_translations.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -34,7 +36,6 @@
|
||||
#undef main
|
||||
#endif // main
|
||||
|
||||
#include "create_translations.h"
|
||||
#include "po_parser.h"
|
||||
#include "cp_parser.h"
|
||||
|
||||
|
@ -28,4 +28,8 @@ typedef unsigned short uint16;
|
||||
typedef unsigned int uint32;
|
||||
typedef signed short int16;
|
||||
|
||||
#ifndef __has_feature // Optional of course.
|
||||
#define __has_feature(x) 0 // Compatibility with non-clang compilers.
|
||||
#endif
|
||||
|
||||
#endif /* CREATE_TRANSLATIONS_H */
|
||||
|
@ -598,6 +598,7 @@ catalog Humongous Interactive Catalog
|
||||
a56e8d9d4281c53c3f63c9bd22a59e21 10978342 en All HE CUP Preview George Kormendi
|
||||
74da3494fbe1a7d20213b0afe0954755 10841544 fr All HE CUP Preview - George Kormendi
|
||||
4c4820518e16e1a0e3616a3b021a04f3 10927456 de All HE CUP Preview - Kirben
|
||||
288fb75b24389733c29fa107fe8d44e8 10795148 us All HE CUP Preview - Kirben
|
||||
|
||||
airport Let's Explore the Airport with Buzzy
|
||||
d6334a5a9b61afe18c368540fdf522ca -1 en Mac - - - Joachim Eberhard
|
||||
|
@ -13,10 +13,10 @@ add_engine cruise "Cinematique evo 2" yes
|
||||
add_engine draci "Dragon History" yes
|
||||
add_engine drascula "Drascula: The Vampire Strikes Back" yes
|
||||
add_engine dreamweb "Dreamweb" yes
|
||||
add_engine fullpipe "Full Pipe" yes
|
||||
add_engine fullpipe "Full Pipe" no
|
||||
add_engine gob "Gobli*ns" yes
|
||||
add_engine groovie "Groovie" yes "groovie2" "7th Guest"
|
||||
add_engine groovie2 "Groovie 2 games" no
|
||||
add_engine groovie2 "Groovie 2 games" no "" "" "jpeg"
|
||||
add_engine hopkins "Hopkins FBI" yes "" "" "16bit"
|
||||
add_engine hugo "Hugo Trilogy" yes
|
||||
add_engine kyra "Kyra" yes "lol eob" "Legend of Kyrandia 1-3"
|
||||
@ -52,5 +52,5 @@ add_engine touche "Touche: The Adventures of the Fifth Musketeer" yes
|
||||
add_engine tony "Tony Tough and the Night of Roasted Moths" yes "" "" "16bit"
|
||||
add_engine tsage "TsAGE" yes
|
||||
add_engine tucker "Bud Tucker in Double Trouble" yes
|
||||
add_engine wintermute "Wintermute" no "" "" "png zlib vorbis 16bit"
|
||||
add_engine wintermute "Wintermute" no "" "" "jpeg png zlib vorbis 16bit"
|
||||
add_engine zvision "ZVision" no
|
||||
|
@ -48,17 +48,17 @@ void BehaviorManager::clear() {
|
||||
_behaviors.clear();
|
||||
}
|
||||
|
||||
void BehaviorManager::initBehavior(Scene *sc, CGameVar *var) {
|
||||
void BehaviorManager::initBehavior(Scene *sc, GameVar *var) {
|
||||
clear();
|
||||
_scene = sc;
|
||||
|
||||
BehaviorInfo *behinfo;
|
||||
|
||||
CGameVar *behvar = var->getSubVarByName("BEHAVIOR");
|
||||
GameVar *behvar = var->getSubVarByName("BEHAVIOR");
|
||||
if (!behvar)
|
||||
return;
|
||||
|
||||
for (CGameVar *subvar = behvar->_subVars; subvar; subvar = subvar->_nextVarObj) {
|
||||
for (GameVar *subvar = behvar->_subVars; subvar; subvar = subvar->_nextVarObj) {
|
||||
if (!strcmp(subvar->_varName, "AMBIENT")) {
|
||||
behinfo = new BehaviorInfo;
|
||||
behinfo->initAmbientBehavior(subvar, sc);
|
||||
@ -191,7 +191,7 @@ void BehaviorInfo::clear() {
|
||||
_bheItems.clear();
|
||||
}
|
||||
|
||||
void BehaviorInfo::initAmbientBehavior(CGameVar *var, Scene *sc) {
|
||||
void BehaviorInfo::initAmbientBehavior(GameVar *var, Scene *sc) {
|
||||
debug(0, "BehaviorInfo::initAmbientBehavior(%s)", transCyrillic((byte *)var->_varName));
|
||||
|
||||
clear();
|
||||
@ -215,7 +215,7 @@ void BehaviorInfo::initAmbientBehavior(CGameVar *var, Scene *sc) {
|
||||
}
|
||||
}
|
||||
|
||||
void BehaviorInfo::initObjectBehavior(CGameVar *var, Scene *sc, StaticANIObject *ani) {
|
||||
void BehaviorInfo::initObjectBehavior(GameVar *var, Scene *sc, StaticANIObject *ani) {
|
||||
debug(0, "BehaviorInfo::initObjectBehavior(%s)", transCyrillic((byte *)var->_varName));
|
||||
|
||||
clear();
|
||||
@ -227,7 +227,7 @@ void BehaviorInfo::initObjectBehavior(CGameVar *var, Scene *sc, StaticANIObject
|
||||
if (strcmp(var->_value.stringValue, "ROOT"))
|
||||
break;
|
||||
|
||||
CGameVar *v1 = g_fullpipe->getGameLoaderGameVar()->getSubVarByName("BEHAVIOR")->getSubVarByName(ani->getName());
|
||||
GameVar *v1 = g_fullpipe->getGameLoaderGameVar()->getSubVarByName("BEHAVIOR")->getSubVarByName(ani->getName());
|
||||
if (v1 == var)
|
||||
return;
|
||||
|
||||
@ -255,7 +255,7 @@ BehaviorEntry::BehaviorEntry() {
|
||||
_items = 0;
|
||||
}
|
||||
|
||||
BehaviorEntry::BehaviorEntry(CGameVar *var, Scene *sc, StaticANIObject *ani, int *minDelay) {
|
||||
BehaviorEntry::BehaviorEntry(GameVar *var, Scene *sc, StaticANIObject *ani, int *minDelay) {
|
||||
_staticsId = 0;
|
||||
_itemsCount = 0;
|
||||
|
||||
@ -274,7 +274,7 @@ BehaviorEntry::BehaviorEntry(CGameVar *var, Scene *sc, StaticANIObject *ani, int
|
||||
_items = (BehaviorEntryInfo**)calloc(_itemsCount, sizeof(BehaviorEntryInfo *));
|
||||
|
||||
for (int i = 0; i < _itemsCount; i++) {
|
||||
CGameVar *subvar = var->getSubVarByIndex(i);
|
||||
GameVar *subvar = var->getSubVarByIndex(i);
|
||||
int delay;
|
||||
|
||||
_items[i] = new BehaviorEntryInfo(subvar, sc, &delay);
|
||||
@ -289,14 +289,14 @@ BehaviorEntry::BehaviorEntry(CGameVar *var, Scene *sc, StaticANIObject *ani, int
|
||||
}
|
||||
}
|
||||
|
||||
BehaviorEntryInfo::BehaviorEntryInfo(CGameVar *subvar, Scene *sc, int *delay) {
|
||||
BehaviorEntryInfo::BehaviorEntryInfo(GameVar *subvar, Scene *sc, int *delay) {
|
||||
_messageQueue = 0;
|
||||
_delay = 0;
|
||||
_percent = 0;
|
||||
_flags = 0;
|
||||
_messageQueue = sc->getMessageQueueByName(subvar->_varName);
|
||||
|
||||
CGameVar *vart = subvar->getSubVarByName("dwDelay");
|
||||
GameVar *vart = subvar->getSubVarByName("dwDelay");
|
||||
if (vart)
|
||||
_delay = vart->_value.intValue;
|
||||
|
||||
|
@ -31,7 +31,7 @@ struct BehaviorEntryInfo {
|
||||
uint32 _percent;
|
||||
int _flags;
|
||||
|
||||
BehaviorEntryInfo(CGameVar *subvar, Scene *sc, int *delay);
|
||||
BehaviorEntryInfo(GameVar *subvar, Scene *sc, int *delay);
|
||||
};
|
||||
|
||||
struct BehaviorEntry {
|
||||
@ -41,7 +41,7 @@ struct BehaviorEntry {
|
||||
BehaviorEntryInfo **_items;
|
||||
|
||||
BehaviorEntry();
|
||||
BehaviorEntry(CGameVar *var, Scene *sc, StaticANIObject *ani, int *minDelay);
|
||||
BehaviorEntry(GameVar *var, Scene *sc, StaticANIObject *ani, int *minDelay);
|
||||
};
|
||||
|
||||
struct BehaviorInfo {
|
||||
@ -57,8 +57,8 @@ struct BehaviorInfo {
|
||||
BehaviorInfo() { clear(); }
|
||||
|
||||
void clear();
|
||||
void initAmbientBehavior(CGameVar *var, Scene *sc);
|
||||
void initObjectBehavior(CGameVar *var, Scene *sc, StaticANIObject *ani);
|
||||
void initAmbientBehavior(GameVar *var, Scene *sc);
|
||||
void initObjectBehavior(GameVar *var, Scene *sc, StaticANIObject *ani);
|
||||
};
|
||||
|
||||
class BehaviorManager : public CObject {
|
||||
@ -72,7 +72,7 @@ class BehaviorManager : public CObject {
|
||||
|
||||
void clear();
|
||||
|
||||
void initBehavior(Scene *scene, CGameVar *var);
|
||||
void initBehavior(Scene *scene, GameVar *var);
|
||||
|
||||
void updateBehaviors();
|
||||
void updateBehavior(BehaviorInfo *behaviorInfo, BehaviorEntry *entry);
|
||||
|
@ -236,7 +236,7 @@ void FullpipeEngine::updateEvents() {
|
||||
_modalObject->update();
|
||||
} else {
|
||||
_modalObject->saveload();
|
||||
CBaseModalObject *obj = _modalObject->_parentObj;
|
||||
BaseModalObject *obj = _modalObject->_parentObj;
|
||||
if (obj)
|
||||
delete _modalObject;
|
||||
_modalObject = obj;
|
||||
@ -260,7 +260,7 @@ void FullpipeEngine::updateEvents() {
|
||||
}
|
||||
|
||||
ex = new ExCommand(0, 17, 36, 0, 0, 0, 1, 0, 0, 0);
|
||||
ex->_keyCode = 83;
|
||||
ex->_keyCode = event.kbd.keycode;
|
||||
ex->_excFlags |= 3;
|
||||
ex->handle();
|
||||
break;
|
||||
@ -360,7 +360,7 @@ void FullpipeEngine::updateScreen() {
|
||||
_modalObject->update();
|
||||
} else {
|
||||
_modalObject->saveload();
|
||||
CBaseModalObject *tmp = _modalObject->_parentObj;
|
||||
BaseModalObject *tmp = _modalObject->_parentObj;
|
||||
|
||||
delete _modalObject;
|
||||
|
||||
@ -389,7 +389,7 @@ void FullpipeEngine::updateScreen() {
|
||||
}
|
||||
|
||||
int FullpipeEngine::getObjectEnumState(const char *name, const char *state) {
|
||||
CGameVar *var = _gameLoader->_gameVar->getSubVarByName("OBJSTATES");
|
||||
GameVar *var = _gameLoader->_gameVar->getSubVarByName("OBJSTATES");
|
||||
|
||||
if (!var) {
|
||||
var = _gameLoader->_gameVar->addSubVarAsInt("OBJSTATES", 0);
|
||||
@ -406,7 +406,7 @@ int FullpipeEngine::getObjectEnumState(const char *name, const char *state) {
|
||||
}
|
||||
|
||||
int FullpipeEngine::getObjectState(const char *objname) {
|
||||
CGameVar *var = _gameLoader->_gameVar->getSubVarByName("OBJSTATES");
|
||||
GameVar *var = _gameLoader->_gameVar->getSubVarByName("OBJSTATES");
|
||||
|
||||
if (var)
|
||||
return var->getSubVarAsInt(objname);
|
||||
@ -415,7 +415,7 @@ int FullpipeEngine::getObjectState(const char *objname) {
|
||||
}
|
||||
|
||||
void FullpipeEngine::setObjectState(const char *name, int state) {
|
||||
CGameVar *var = _gameLoader->_gameVar->getSubVarByName("OBJSTATES");
|
||||
GameVar *var = _gameLoader->_gameVar->getSubVarByName("OBJSTATES");
|
||||
|
||||
if (!var) {
|
||||
var = _gameLoader->_gameVar->addSubVarAsInt("OBJSTATES", 0);
|
||||
|
@ -44,11 +44,11 @@ enum FullpipeGameFeatures {
|
||||
};
|
||||
|
||||
class BehaviorManager;
|
||||
class CBaseModalObject;
|
||||
class CGameLoader;
|
||||
class CGameVar;
|
||||
class CInputController;
|
||||
class CInventory2;
|
||||
class BaseModalObject;
|
||||
class GameLoader;
|
||||
class GameVar;
|
||||
class InputController;
|
||||
class Inventory2;
|
||||
struct CursorInfo;
|
||||
struct EntranceInfo;
|
||||
class ExCommand;
|
||||
@ -98,12 +98,12 @@ public:
|
||||
|
||||
Graphics::Surface _backgroundSurface;
|
||||
|
||||
CGameLoader *_gameLoader;
|
||||
GameLoader *_gameLoader;
|
||||
GameProject *_gameProject;
|
||||
bool loadGam(const char *fname, int scene = 0);
|
||||
|
||||
CGameVar *getGameLoaderGameVar();
|
||||
CInputController *getGameLoaderInputController();
|
||||
GameVar *getGameLoaderGameVar();
|
||||
InputController *getGameLoaderInputController();
|
||||
|
||||
int _gameProjectVersion;
|
||||
int _pictureScale;
|
||||
@ -124,7 +124,7 @@ public:
|
||||
StaticANIObject *_aniMan2;
|
||||
byte *_globalPalette;
|
||||
|
||||
CInputController *_inputController;
|
||||
InputController *_inputController;
|
||||
bool _inputDisabled;
|
||||
|
||||
int _currentCheat;
|
||||
@ -190,14 +190,14 @@ public:
|
||||
int32 _mapTable[200];
|
||||
|
||||
Scene *_inventoryScene;
|
||||
CInventory2 *_inventory;
|
||||
Inventory2 *_inventory;
|
||||
int _currSelectedInventoryItemId;
|
||||
|
||||
int32 _updateTicks;
|
||||
int32 _lastInputTicks;
|
||||
int32 _lastButtonUpTicks;
|
||||
|
||||
CBaseModalObject *_modalObject;
|
||||
BaseModalObject *_modalObject;
|
||||
|
||||
int (*_updateScreenCallback)();
|
||||
int (*_updateCursorCallback)();
|
||||
@ -218,7 +218,7 @@ public:
|
||||
|
||||
bool sceneSwitcher(EntranceInfo *entrance);
|
||||
Scene *accessScene(int sceneId);
|
||||
void setSceneMusicParameters(CGameVar *var);
|
||||
void setSceneMusicParameters(GameVar *var);
|
||||
|
||||
NGIArchive *_currArchive;
|
||||
|
||||
|
@ -31,25 +31,25 @@
|
||||
|
||||
namespace Fullpipe {
|
||||
|
||||
CInventory2 *getGameLoaderInventory() {
|
||||
Inventory2 *getGameLoaderInventory() {
|
||||
return &g_fullpipe->_gameLoader->_inventory;
|
||||
}
|
||||
|
||||
CMctlCompound *getSc2MctlCompoundBySceneId(int16 sceneId) {
|
||||
MctlCompound *getSc2MctlCompoundBySceneId(int16 sceneId) {
|
||||
for (uint i = 0; i < g_fullpipe->_gameLoader->_sc2array.size(); i++)
|
||||
if (g_fullpipe->_gameLoader->_sc2array[i]._sceneId == sceneId)
|
||||
return (CMctlCompound *)g_fullpipe->_gameLoader->_sc2array[i]._motionController;
|
||||
return (MctlCompound *)g_fullpipe->_gameLoader->_sc2array[i]._motionController;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CInteractionController *getGameLoaderInteractionController() {
|
||||
InteractionController *getGameLoaderInteractionController() {
|
||||
return g_fullpipe->_gameLoader->_interactionController;
|
||||
}
|
||||
|
||||
CGameLoader::CGameLoader() {
|
||||
_interactionController = new CInteractionController();
|
||||
_inputController = new CInputController();
|
||||
GameLoader::GameLoader() {
|
||||
_interactionController = new InteractionController();
|
||||
_inputController = new InputController();
|
||||
|
||||
_gameProject = 0;
|
||||
_gameName = 0;
|
||||
@ -74,15 +74,15 @@ CGameLoader::CGameLoader() {
|
||||
g_fullpipe->_msgId = 0;
|
||||
}
|
||||
|
||||
CGameLoader::~CGameLoader() {
|
||||
GameLoader::~GameLoader() {
|
||||
free(_gameName);
|
||||
delete _gameProject;
|
||||
delete _interactionController;
|
||||
delete _inputController;
|
||||
}
|
||||
|
||||
bool CGameLoader::load(MfcArchive &file) {
|
||||
debug(5, "CGameLoader::load()");
|
||||
bool GameLoader::load(MfcArchive &file) {
|
||||
debug(5, "GameLoader::load()");
|
||||
|
||||
_gameName = file.readPascalString();
|
||||
debug(6, "_gameName: %s", _gameName);
|
||||
@ -124,12 +124,12 @@ bool CGameLoader::load(MfcArchive &file) {
|
||||
_field_FA = file.readUint16LE();
|
||||
_field_F8 = file.readUint16LE();
|
||||
|
||||
_gameVar = (CGameVar *)file.readClass();
|
||||
_gameVar = (GameVar *)file.readClass();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGameLoader::loadScene(int sceneId) {
|
||||
bool GameLoader::loadScene(int sceneId) {
|
||||
SceneTag *st;
|
||||
|
||||
int idx = getSceneTagBySceneId(sceneId, &st);
|
||||
@ -155,7 +155,7 @@ bool CGameLoader::loadScene(int sceneId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CGameLoader::gotoScene(int sceneId, int entranceId) {
|
||||
bool GameLoader::gotoScene(int sceneId, int entranceId) {
|
||||
SceneTag *st;
|
||||
|
||||
int sc2idx = getSceneTagBySceneId(sceneId, &st);
|
||||
@ -181,7 +181,7 @@ bool CGameLoader::gotoScene(int sceneId, int entranceId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CGameVar *sg = _gameVar->getSubVarByName("OBJSTATES")->getSubVarByName("SAVEGAME");
|
||||
GameVar *sg = _gameVar->getSubVarByName("OBJSTATES")->getSubVarByName("SAVEGAME");
|
||||
|
||||
if (sg || (sg = _gameVar->getSubVarByName("OBJSTATES")->addSubVarAsInt("SAVEGAME", 0)) != 0)
|
||||
sg->setSubVarAsInt("Entrance", entranceId);
|
||||
@ -234,7 +234,7 @@ bool preloadCallback(const PreloadItem &pre, int flag) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGameLoader::preloadScene(int sceneId, int entranceId) {
|
||||
bool GameLoader::preloadScene(int sceneId, int entranceId) {
|
||||
debug(0, "preloadScene(%d, %d), ", sceneId, entranceId);
|
||||
|
||||
if (_preloadSceneId != sceneId || _preloadEntranceId != entranceId) {
|
||||
@ -289,7 +289,7 @@ bool CGameLoader::preloadScene(int sceneId, int entranceId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CGameLoader::unloadScene(int sceneId) {
|
||||
bool GameLoader::unloadScene(int sceneId) {
|
||||
SceneTag *tag;
|
||||
int sceneTag = getSceneTagBySceneId(sceneId, &tag);
|
||||
|
||||
@ -310,7 +310,7 @@ bool CGameLoader::unloadScene(int sceneId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int CGameLoader::getSceneTagBySceneId(int sceneId, SceneTag **st) {
|
||||
int GameLoader::getSceneTagBySceneId(int sceneId, SceneTag **st) {
|
||||
if (_sc2array.size() > 0 && _gameProject->_sceneTagList->size() > 0) {
|
||||
for (uint i = 0; i < _sc2array.size(); i++) {
|
||||
if (_sc2array[i]._sceneId == sceneId) {
|
||||
@ -329,11 +329,11 @@ int CGameLoader::getSceneTagBySceneId(int sceneId, SceneTag **st) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
void CGameLoader::applyPicAniInfos(Scene *sc, PicAniInfo **picAniInfo, int picAniInfoCount) {
|
||||
void GameLoader::applyPicAniInfos(Scene *sc, PicAniInfo **picAniInfo, int picAniInfoCount) {
|
||||
if (picAniInfoCount <= 0)
|
||||
return;
|
||||
|
||||
debug(0, "CGameLoader::applyPicAniInfos(sc, ptr, %d)", picAniInfoCount);
|
||||
debug(0, "GameLoader::applyPicAniInfos(sc, ptr, %d)", picAniInfoCount);
|
||||
|
||||
PictureObject *pict;
|
||||
StaticANIObject *ani;
|
||||
@ -381,11 +381,11 @@ void CGameLoader::applyPicAniInfos(Scene *sc, PicAniInfo **picAniInfo, int picAn
|
||||
}
|
||||
}
|
||||
|
||||
void CGameLoader::saveScenePicAniInfos(int sceneId) {
|
||||
warning("STUB: CGameLoader::saveScenePicAniInfos(%d)", sceneId);
|
||||
void GameLoader::saveScenePicAniInfos(int sceneId) {
|
||||
warning("STUB: GameLoader::saveScenePicAniInfos(%d)", sceneId);
|
||||
}
|
||||
|
||||
void CGameLoader::updateSystems(int counterdiff) {
|
||||
void GameLoader::updateSystems(int counterdiff) {
|
||||
if (g_fullpipe->_currentScene) {
|
||||
g_fullpipe->_currentScene->update(counterdiff);
|
||||
|
||||
@ -425,7 +425,7 @@ bool Sc2::load(MfcArchive &file) {
|
||||
|
||||
_sceneId = file.readUint16LE();
|
||||
|
||||
_motionController = (CMotionController *)file.readClass();
|
||||
_motionController = (MotionController *)file.readClass();
|
||||
|
||||
_count1 = file.readUint32LE();
|
||||
debug(4, "count1: %d", _count1);
|
||||
@ -496,14 +496,14 @@ bool PreloadItems::load(MfcArchive &file) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CGameVar *FullpipeEngine::getGameLoaderGameVar() {
|
||||
GameVar *FullpipeEngine::getGameLoaderGameVar() {
|
||||
if (_gameLoader)
|
||||
return _gameLoader->_gameVar;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
CInputController *FullpipeEngine::getGameLoaderInputController() {
|
||||
InputController *FullpipeEngine::getGameLoaderInputController() {
|
||||
if (_gameLoader)
|
||||
return _gameLoader->_inputController;
|
||||
else
|
||||
|
@ -30,17 +30,17 @@
|
||||
namespace Fullpipe {
|
||||
|
||||
class SceneTag;
|
||||
class CMctlCompound;
|
||||
class CInputController;
|
||||
class CInteractionController;
|
||||
class CMotionController;
|
||||
class MctlCompound;
|
||||
class InputController;
|
||||
class InteractionController;
|
||||
class MotionController;
|
||||
|
||||
class Sc2 : public CObject {
|
||||
public:
|
||||
int16 _sceneId;
|
||||
int16 _field_2;
|
||||
Scene *_scene;
|
||||
CMotionController *_motionController;
|
||||
MotionController *_motionController;
|
||||
int32 *_data1; // FIXME, could be a struct
|
||||
int _count1;
|
||||
PicAniInfo **_defPicAniInfos;
|
||||
@ -72,10 +72,10 @@ class PreloadItems : public Common::Array<PreloadItem *>, public CObject {
|
||||
virtual bool load(MfcArchive &file);
|
||||
};
|
||||
|
||||
class CGameLoader : public CObject {
|
||||
class GameLoader : public CObject {
|
||||
public:
|
||||
CGameLoader();
|
||||
virtual ~CGameLoader();
|
||||
GameLoader();
|
||||
virtual ~GameLoader();
|
||||
|
||||
virtual bool load(MfcArchive &file);
|
||||
bool loadScene(int sceneId);
|
||||
@ -90,9 +90,9 @@ class CGameLoader : public CObject {
|
||||
void saveScenePicAniInfos(int sceneId);
|
||||
|
||||
GameProject *_gameProject;
|
||||
CInteractionController *_interactionController;
|
||||
CInputController *_inputController;
|
||||
CInventory2 _inventory;
|
||||
InteractionController *_interactionController;
|
||||
InputController *_inputController;
|
||||
Inventory2 _inventory;
|
||||
Sc2Array _sc2array;
|
||||
void *_sceneSwitcher;
|
||||
bool (*_preloadCallback)(const PreloadItem &pre, int flag);
|
||||
@ -100,7 +100,7 @@ class CGameLoader : public CObject {
|
||||
int16 _field_F8;
|
||||
int16 _field_FA;
|
||||
PreloadItems _preloadItems;
|
||||
CGameVar *_gameVar;
|
||||
GameVar *_gameVar;
|
||||
char *_gameName;
|
||||
ExCommand _exCommand;
|
||||
int _updateCounter;
|
||||
@ -108,9 +108,9 @@ class CGameLoader : public CObject {
|
||||
int _preloadEntranceId;
|
||||
};
|
||||
|
||||
CInventory2 *getGameLoaderInventory();
|
||||
CInteractionController *getGameLoaderInteractionController();
|
||||
CMctlCompound *getSc2MctlCompoundBySceneId(int16 sceneId);
|
||||
Inventory2 *getGameLoaderInventory();
|
||||
InteractionController *getGameLoaderInteractionController();
|
||||
MctlCompound *getSc2MctlCompoundBySceneId(int16 sceneId);
|
||||
|
||||
} // End of namespace Fullpipe
|
||||
|
||||
|
@ -171,7 +171,7 @@ bool PictureObject::load(MfcArchive &file, bool bigPicture) {
|
||||
|
||||
_picture->load(file);
|
||||
|
||||
_pictureObject2List = new CPtrList();
|
||||
_pictureObject2List = new PtrList();
|
||||
|
||||
int count = file.readUint16LE();
|
||||
|
||||
@ -325,7 +325,7 @@ void GameObject::setOXY(int x, int y) {
|
||||
_oy = y;
|
||||
}
|
||||
|
||||
void GameObject::renumPictures(CPtrList *lst) {
|
||||
void GameObject::renumPictures(PtrList *lst) {
|
||||
int *buf = (int *)calloc(lst->size() + 2, sizeof(int));
|
||||
|
||||
for (uint i = 0; i < lst->size(); i++) {
|
||||
|
@ -137,7 +137,7 @@ class GameObject : public CObject {
|
||||
|
||||
virtual bool load(MfcArchive &file);
|
||||
void setOXY(int x, int y);
|
||||
void renumPictures(CPtrList *lst);
|
||||
void renumPictures(PtrList *lst);
|
||||
void setFlags(int16 flags) { _flags = flags; }
|
||||
void clearFlags() { _flags = 0; }
|
||||
const char *getName() { return _objectName; }
|
||||
@ -149,7 +149,7 @@ class GameObject : public CObject {
|
||||
class PictureObject : public GameObject {
|
||||
public:
|
||||
Picture *_picture;
|
||||
CPtrList *_pictureObject2List;
|
||||
PtrList *_pictureObject2List;
|
||||
int _ox2;
|
||||
int _oy2;
|
||||
|
||||
@ -169,7 +169,7 @@ class PictureObject : public GameObject {
|
||||
|
||||
class Background : public CObject {
|
||||
public:
|
||||
CPtrList _picObjList;
|
||||
PtrList _picObjList;
|
||||
|
||||
char *_bgname;
|
||||
int _x;
|
||||
|
@ -123,7 +123,7 @@ void FullpipeEngine::initObjectStates() {
|
||||
}
|
||||
|
||||
void FullpipeEngine::setLevelStates() {
|
||||
CGameVar *v = _gameLoader->_gameVar->getSubVarByName("OBJSTATES")->getSubVarByName(sO_LiftButtons);
|
||||
GameVar *v = _gameLoader->_gameVar->getSubVarByName("OBJSTATES")->getSubVarByName(sO_LiftButtons);
|
||||
|
||||
if (v) {
|
||||
v->setSubVarAsInt(sO_Level0, 2833);
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
namespace Fullpipe {
|
||||
|
||||
CInputController::CInputController() {
|
||||
InputController::InputController() {
|
||||
g_fullpipe->_inputController = this;
|
||||
|
||||
_flag = 0;
|
||||
@ -52,13 +52,13 @@ CInputController::CInputController() {
|
||||
_cursorItemPicture = 0;
|
||||
}
|
||||
|
||||
CInputController::~CInputController() {
|
||||
InputController::~InputController() {
|
||||
removeMessageHandler(126, -1);
|
||||
|
||||
g_fullpipe->_inputController = 0;
|
||||
}
|
||||
|
||||
void CInputController::setInputDisabled(bool state) {
|
||||
void InputController::setInputDisabled(bool state) {
|
||||
_flag = state;
|
||||
g_fullpipe->_inputDisabled = state;
|
||||
}
|
||||
@ -67,7 +67,7 @@ void setInputDisabled(bool state) {
|
||||
g_fullpipe->_inputController->setInputDisabled(state);
|
||||
}
|
||||
|
||||
void CInputController::addCursor(CursorInfo *cursor) {
|
||||
void InputController::addCursor(CursorInfo *cursor) {
|
||||
CursorInfo *newc = new CursorInfo(cursor);
|
||||
Common::Point p;
|
||||
|
||||
@ -82,14 +82,14 @@ void CInputController::addCursor(CursorInfo *cursor) {
|
||||
_cursorsArray.push_back(newc);
|
||||
}
|
||||
|
||||
void CInputController::setCursorMode(bool enabled) {
|
||||
void InputController::setCursorMode(bool enabled) {
|
||||
if (enabled)
|
||||
_inputFlags |= 1;
|
||||
else
|
||||
_inputFlags &= ~1;
|
||||
}
|
||||
|
||||
void CInputController::drawCursor(int x, int y) {
|
||||
void InputController::drawCursor(int x, int y) {
|
||||
if (_cursorIndex == -1)
|
||||
return;
|
||||
|
||||
@ -105,7 +105,7 @@ void CInputController::drawCursor(int x, int y) {
|
||||
_cursorBounds.top + _cursorsArray[_cursorIndex]->itemPictureOffsY, 0, 0);
|
||||
}
|
||||
|
||||
void CInputController::setCursor(int cursorId) {
|
||||
void InputController::setCursor(int cursorId) {
|
||||
if (_cursorIndex == -1 || _cursorsArray[_cursorIndex]->pictureId != cursorId) {
|
||||
_cursorIndex = -1;
|
||||
|
||||
@ -165,7 +165,6 @@ void FullpipeEngine::defHandleKeyDown(int key) {
|
||||
return;
|
||||
}
|
||||
|
||||
warning("%d %d", _currentCheat, _currentCheatPos);
|
||||
if (toupper(key) != input_cheats[_currentCheat][_currentCheatPos]) {
|
||||
_currentCheat = -1;
|
||||
|
||||
@ -173,7 +172,6 @@ void FullpipeEngine::defHandleKeyDown(int key) {
|
||||
}
|
||||
|
||||
_currentCheatPos++;
|
||||
warning("%d %d", _currentCheat, _currentCheatPos);
|
||||
|
||||
if (!input_cheats[_currentCheat][_currentCheatPos]) {
|
||||
switch (_currentCheat) {
|
||||
|
@ -45,7 +45,7 @@ struct CursorInfo {
|
||||
|
||||
typedef Common::Array<CursorInfo *> CursorsArray;
|
||||
|
||||
class CInputController {
|
||||
class InputController {
|
||||
//CObject obj;
|
||||
int _flag;
|
||||
int _inputFlags;
|
||||
@ -59,8 +59,8 @@ class CInputController {
|
||||
Picture *_cursorItemPicture;
|
||||
|
||||
public:
|
||||
CInputController();
|
||||
~CInputController();
|
||||
InputController();
|
||||
~InputController();
|
||||
|
||||
void setInputDisabled(bool state);
|
||||
void addCursor(CursorInfo *cursor);
|
||||
|
@ -39,9 +39,9 @@ bool canInteractAny(GameObject *obj1, GameObject *obj2, int invId) {
|
||||
if (g_fullpipe->_currentScene)
|
||||
sceneId = g_fullpipe->_currentScene->_sceneId;
|
||||
|
||||
CInteractionController *intC = getGameLoaderInteractionController();
|
||||
for (CObList::iterator i = intC->_interactions.begin(); i != intC->_interactions.end(); ++i) {
|
||||
CInteraction *intr = (CInteraction *)*i;
|
||||
InteractionController *intC = getGameLoaderInteractionController();
|
||||
for (ObList::iterator i = intC->_interactions.begin(); i != intC->_interactions.end(); ++i) {
|
||||
Interaction *intr = (Interaction *)*i;
|
||||
|
||||
if (intr->_sceneId > 0 && intr->_sceneId != sceneId)
|
||||
break;
|
||||
@ -55,17 +55,17 @@ bool canInteractAny(GameObject *obj1, GameObject *obj2, int invId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CInteractionController::load(MfcArchive &file) {
|
||||
debug(5, "CInteractionController::load()");
|
||||
bool InteractionController::load(MfcArchive &file) {
|
||||
debug(5, "InteractionController::load()");
|
||||
|
||||
return _interactions.load(file);
|
||||
}
|
||||
|
||||
int static_compSceneId = 0;
|
||||
|
||||
bool CInteractionController::compareInteractions(const void *p1, const void *p2) {
|
||||
const CInteraction *i1 = (const CInteraction *)p1;
|
||||
const CInteraction *i2 = (const CInteraction *)p2;
|
||||
bool InteractionController::compareInteractions(const void *p1, const void *p2) {
|
||||
const Interaction *i1 = (const Interaction *)p1;
|
||||
const Interaction *i2 = (const Interaction *)p2;
|
||||
|
||||
if (i2->_sceneId < i1->_sceneId) {
|
||||
if (i1->_sceneId != static_compSceneId)
|
||||
@ -89,13 +89,13 @@ bool CInteractionController::compareInteractions(const void *p1, const void *p2)
|
||||
return true;
|
||||
}
|
||||
|
||||
void CInteractionController::sortInteractions(int sceneId) {
|
||||
void InteractionController::sortInteractions(int sceneId) {
|
||||
static_compSceneId = sceneId;
|
||||
|
||||
Common::sort(_interactions.begin(), _interactions.end(), CInteractionController::compareInteractions);
|
||||
Common::sort(_interactions.begin(), _interactions.end(), InteractionController::compareInteractions);
|
||||
}
|
||||
|
||||
bool CInteractionController::handleInteraction(StaticANIObject *subj, GameObject *obj, int invId) {
|
||||
bool InteractionController::handleInteraction(StaticANIObject *subj, GameObject *obj, int invId) {
|
||||
if (subj) {
|
||||
if (!subj->isIdle() || (subj->_flags & 0x100))
|
||||
return false;
|
||||
@ -104,16 +104,16 @@ bool CInteractionController::handleInteraction(StaticANIObject *subj, GameObject
|
||||
if (!_interactions.size())
|
||||
return false;
|
||||
|
||||
CInteraction *inter = 0;
|
||||
CInteraction *previnter = 0;
|
||||
Interaction *inter = 0;
|
||||
Interaction *previnter = 0;
|
||||
int dur = 0;
|
||||
int mindur = 0xFFFF;
|
||||
|
||||
MessageQueue *mq;
|
||||
ExCommand *ex;
|
||||
|
||||
for (CObList::iterator i = _interactions.begin(); i != _interactions.end(); ++i) {
|
||||
CInteraction *cinter = (CInteraction *)*i;
|
||||
for (ObList::iterator i = _interactions.begin(); i != _interactions.end(); ++i) {
|
||||
Interaction *cinter = (Interaction *)*i;
|
||||
|
||||
if (!cinter->canInteract(subj, obj, invId))
|
||||
continue;
|
||||
@ -394,7 +394,7 @@ LABEL_38:
|
||||
return true;
|
||||
}
|
||||
|
||||
CInteraction::CInteraction() {
|
||||
Interaction::Interaction() {
|
||||
_objectId1 = 0;
|
||||
_objectId2 = 0;
|
||||
_staticsId1 = 0;
|
||||
@ -411,8 +411,8 @@ CInteraction::CInteraction() {
|
||||
_actionName = 0;
|
||||
}
|
||||
|
||||
bool CInteraction::load(MfcArchive &file) {
|
||||
debug(5, "CInteraction::load()");
|
||||
bool Interaction::load(MfcArchive &file) {
|
||||
debug(5, "Interaction::load()");
|
||||
|
||||
_objectId1 = file.readUint16LE();
|
||||
_objectId2 = file.readUint16LE();
|
||||
@ -432,7 +432,7 @@ bool CInteraction::load(MfcArchive &file) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CInteraction::canInteract(GameObject *obj1, GameObject *obj2, int invId) {
|
||||
bool Interaction::canInteract(GameObject *obj1, GameObject *obj2, int invId) {
|
||||
if (_sceneId > 0 && g_fullpipe->_currentScene && g_fullpipe->_currentScene->_sceneId != _sceneId)
|
||||
return false;
|
||||
|
||||
@ -489,7 +489,7 @@ bool CInteraction::canInteract(GameObject *obj1, GameObject *obj2, int invId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CInteraction::isOverlapping(StaticANIObject *subj, GameObject *obj) {
|
||||
bool Interaction::isOverlapping(StaticANIObject *subj, GameObject *obj) {
|
||||
StaticANIObject *ani = (StaticANIObject *)obj;
|
||||
|
||||
if (abs(_xOffs + obj->_ox - subj->_ox) <= 1
|
||||
|
@ -35,7 +35,7 @@ int handleObjectInteraction(StaticANIObject *subject, GameObject *object, int in
|
||||
bool canInteractAny(GameObject *obj1, GameObject *obj2, int invId);
|
||||
|
||||
|
||||
class CInteraction : public CObject {
|
||||
class Interaction : public CObject {
|
||||
public:
|
||||
int16 _objectId1;
|
||||
int16 _objectId2;
|
||||
@ -53,15 +53,15 @@ class CInteraction : public CObject {
|
||||
char *_actionName;
|
||||
|
||||
public:
|
||||
CInteraction();
|
||||
Interaction();
|
||||
virtual bool load(MfcArchive &file);
|
||||
bool canInteract(GameObject *obj1, GameObject *obj2, int invId);
|
||||
bool isOverlapping(StaticANIObject *subj, GameObject *obj);
|
||||
};
|
||||
|
||||
class CInteractionController : public CObject {
|
||||
class InteractionController : public CObject {
|
||||
public:
|
||||
CObList _interactions;
|
||||
ObList _interactions;
|
||||
int16 _field_20;
|
||||
bool _flag24;
|
||||
|
||||
@ -69,7 +69,7 @@ class CInteractionController : public CObject {
|
||||
static bool compareInteractions(const void *p1, const void *p2);
|
||||
|
||||
public:
|
||||
CInteractionController() : _field_20(0), _flag24(true) {}
|
||||
InteractionController() : _field_20(0), _flag24(true) {}
|
||||
|
||||
virtual bool load(MfcArchive &file);
|
||||
|
||||
|
@ -30,8 +30,8 @@
|
||||
|
||||
namespace Fullpipe {
|
||||
|
||||
bool CInventory::load(MfcArchive &file) {
|
||||
debug(5, "CInventory::load()");
|
||||
bool Inventory::load(MfcArchive &file) {
|
||||
debug(5, "Inventory::load()");
|
||||
|
||||
_sceneId = file.readUint16LE();
|
||||
int numInvs = file.readUint32LE();
|
||||
@ -52,7 +52,7 @@ bool CInventory::load(MfcArchive &file) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int CInventory::getInventoryPoolItemIndexById(int itemId) {
|
||||
int Inventory::getInventoryPoolItemIndexById(int itemId) {
|
||||
if (_itemsPool.size() <= 0)
|
||||
return -1;
|
||||
|
||||
@ -64,7 +64,7 @@ int CInventory::getInventoryPoolItemIndexById(int itemId) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CInventory::setItemFlags(int itemId, int flags) {
|
||||
bool Inventory::setItemFlags(int itemId, int flags) {
|
||||
int idx = getInventoryPoolItemIndexById(itemId);
|
||||
|
||||
if (idx < 0)
|
||||
@ -75,7 +75,7 @@ bool CInventory::setItemFlags(int itemId, int flags) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CInventory2::CInventory2() {
|
||||
Inventory2::Inventory2() {
|
||||
_selectedId = -1;
|
||||
_field_48 = -1;
|
||||
_scene = 0;
|
||||
@ -85,7 +85,7 @@ CInventory2::CInventory2() {
|
||||
_topOffset = -65;
|
||||
}
|
||||
|
||||
bool CInventory2::loadPartial(MfcArchive &file) { // CInventory2_SerializePartially
|
||||
bool Inventory2::loadPartial(MfcArchive &file) { // Inventory2_SerializePartially
|
||||
int numInvs = file.readUint32LE();
|
||||
|
||||
for (int i = 0; i < numInvs; i++) {
|
||||
@ -98,27 +98,27 @@ bool CInventory2::loadPartial(MfcArchive &file) { // CInventory2_SerializePartia
|
||||
return true;
|
||||
}
|
||||
|
||||
void CInventory2::addItem(int itemId, int count) {
|
||||
void Inventory2::addItem(int itemId, int count) {
|
||||
if (getInventoryPoolItemIndexById(itemId) >= 0)
|
||||
_inventoryItems.push_back(new InventoryItem(itemId, count));
|
||||
}
|
||||
|
||||
void CInventory2::addItem2(StaticANIObject *obj) {
|
||||
void Inventory2::addItem2(StaticANIObject *obj) {
|
||||
if (getInventoryPoolItemIndexById(obj->_id) >= 0 && getInventoryPoolItemFieldCById(obj->_id) != 2) {
|
||||
addItem(obj->_id, 1);
|
||||
obj->hide();
|
||||
}
|
||||
}
|
||||
|
||||
void CInventory2::removeItem(int itemId, int count) {
|
||||
warning("STUB: CInventory2::removeItem(%d, %d)", itemId, count);
|
||||
void Inventory2::removeItem(int itemId, int count) {
|
||||
warning("STUB: Inventory2::removeItem(%d, %d)", itemId, count);
|
||||
}
|
||||
|
||||
void CInventory2::removeItem2(Scene *sceneObj, int itemId, int x, int y, int priority) {
|
||||
void Inventory2::removeItem2(Scene *sceneObj, int itemId, int x, int y, int priority) {
|
||||
warning("STUB: void removeItem2(sc, %d, %d, %d, %d)", itemId, x, y, priority);
|
||||
}
|
||||
|
||||
int CInventory2::getCountItemsWithId(int itemId) {
|
||||
int Inventory2::getCountItemsWithId(int itemId) {
|
||||
int res = 0;
|
||||
|
||||
for (uint i = 0; i < _inventoryItems.size(); i++) {
|
||||
@ -129,7 +129,7 @@ int CInventory2::getCountItemsWithId(int itemId) {
|
||||
return res;
|
||||
}
|
||||
|
||||
int CInventory2::getInventoryItemIndexById(int itemId) {
|
||||
int Inventory2::getInventoryItemIndexById(int itemId) {
|
||||
for (uint i = 0; i < _inventoryItems.size(); i++) {
|
||||
if (_inventoryItems[i]->itemId == itemId)
|
||||
return i;
|
||||
@ -138,11 +138,11 @@ int CInventory2::getInventoryItemIndexById(int itemId) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int CInventory2::getInventoryPoolItemIdAtIndex(int itemId) {
|
||||
int Inventory2::getInventoryPoolItemIdAtIndex(int itemId) {
|
||||
return _itemsPool[itemId]->id;
|
||||
}
|
||||
|
||||
int CInventory2::getInventoryPoolItemFieldCById(int itemId) {
|
||||
int Inventory2::getInventoryPoolItemFieldCById(int itemId) {
|
||||
for (uint i = 0; i < _itemsPool.size(); i++) {
|
||||
if (_itemsPool[i]->id == itemId)
|
||||
return _itemsPool[i]->field_C;
|
||||
@ -151,7 +151,7 @@ int CInventory2::getInventoryPoolItemFieldCById(int itemId) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CInventory2::getItemFlags(int itemId) {
|
||||
int Inventory2::getItemFlags(int itemId) {
|
||||
int idx = getInventoryPoolItemIndexById(itemId);
|
||||
|
||||
if (idx < 0)
|
||||
@ -160,7 +160,7 @@ int CInventory2::getItemFlags(int itemId) {
|
||||
return _itemsPool[idx]->flags;
|
||||
}
|
||||
|
||||
void CInventory2::rebuildItemRects() {
|
||||
void Inventory2::rebuildItemRects() {
|
||||
_scene = g_fullpipe->accessScene(_sceneId);
|
||||
|
||||
if (!_scene)
|
||||
@ -222,7 +222,7 @@ void CInventory2::rebuildItemRects() {
|
||||
}
|
||||
}
|
||||
|
||||
void CInventory2::draw() {
|
||||
void Inventory2::draw() {
|
||||
if (!_scene)
|
||||
return;
|
||||
|
||||
@ -295,7 +295,7 @@ reset:
|
||||
|
||||
}
|
||||
|
||||
void CInventory2::slideIn() {
|
||||
void Inventory2::slideIn() {
|
||||
_isInventoryOut = false;
|
||||
|
||||
ExCommand *ex = new ExCommand(0, 17, 65, 0, 0, 0, 1, 0, 0, 0);
|
||||
@ -307,7 +307,7 @@ void CInventory2::slideIn() {
|
||||
ex->postMessage();
|
||||
}
|
||||
|
||||
void CInventory2::slideOut() {
|
||||
void Inventory2::slideOut() {
|
||||
_isInventoryOut = true;
|
||||
|
||||
ExCommand *ex = new ExCommand(0, 17, 65, 0, 0, 0, 1, 0, 0, 0);
|
||||
@ -319,7 +319,7 @@ void CInventory2::slideOut() {
|
||||
ex->postMessage();
|
||||
}
|
||||
|
||||
bool CInventory2::handleLeftClick(ExCommand *cmd) {
|
||||
bool Inventory2::handleLeftClick(ExCommand *cmd) {
|
||||
if (!_isInventoryOut)
|
||||
return false;
|
||||
|
||||
@ -353,7 +353,7 @@ bool CInventory2::handleLeftClick(ExCommand *cmd) {
|
||||
return res;
|
||||
}
|
||||
|
||||
int CInventory2::selectItem(int itemId) {
|
||||
int Inventory2::selectItem(int itemId) {
|
||||
if (getInventoryItemIndexById(itemId) < 0)
|
||||
return -1;
|
||||
|
||||
@ -371,7 +371,7 @@ int CInventory2::selectItem(int itemId) {
|
||||
return _selectedId;
|
||||
}
|
||||
|
||||
bool CInventory2::unselectItem(bool flag) {
|
||||
bool Inventory2::unselectItem(bool flag) {
|
||||
if (_selectedId < 0)
|
||||
return false;
|
||||
|
||||
@ -387,7 +387,7 @@ bool CInventory2::unselectItem(bool flag) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int CInventory2::getHoveredItem(Common::Point *point) {
|
||||
int Inventory2::getHoveredItem(Common::Point *point) {
|
||||
int selId = getSelectedItemId();
|
||||
|
||||
if (point->y <= 20 && !_isInventoryOut && !_isLocked)
|
||||
@ -422,7 +422,7 @@ int CInventory2::getHoveredItem(Common::Point *point) {
|
||||
}
|
||||
|
||||
void FullpipeEngine::getAllInventory() {
|
||||
CInventory2 *inv = getGameLoaderInventory();
|
||||
Inventory2 *inv = getGameLoaderInventory();
|
||||
|
||||
for (uint i = 0; i < inv->getItemsPoolCount(); ++i ) {
|
||||
int id = inv->getInventoryPoolItemIdAtIndex(i);
|
||||
|
@ -42,13 +42,13 @@ struct InventoryPoolItem {
|
||||
|
||||
typedef Common::Array<InventoryPoolItem *> InventoryPoolItems;
|
||||
|
||||
class CInventory : public CObject {
|
||||
class Inventory : public CObject {
|
||||
protected:
|
||||
int16 _sceneId;
|
||||
InventoryPoolItems _itemsPool;
|
||||
|
||||
public:
|
||||
CInventory() { _sceneId = 0; }
|
||||
Inventory() { _sceneId = 0; }
|
||||
virtual bool load(MfcArchive &file);
|
||||
|
||||
int getInventoryPoolItemIndexById(int itemId);
|
||||
@ -83,7 +83,7 @@ struct InventoryIcon {
|
||||
|
||||
typedef Common::Array<InventoryIcon *> InventoryIcons;
|
||||
|
||||
class CInventory2 : public CInventory {
|
||||
class Inventory2 : public Inventory {
|
||||
InventoryItems _inventoryItems;
|
||||
InventoryIcons _inventoryIcons;
|
||||
int _selectedId;
|
||||
@ -95,7 +95,7 @@ class CInventory2 : public CInventory {
|
||||
BigPicture *_picture;
|
||||
|
||||
public:
|
||||
CInventory2();
|
||||
Inventory2();
|
||||
bool loadPartial(MfcArchive &file);
|
||||
void addItem(int itemId, int count);
|
||||
void addItem2(StaticANIObject *obj);
|
||||
|
@ -169,13 +169,13 @@ Message::Message(int16 parentId, int messageKind, int x, int y, int a6, int a7,
|
||||
_field_34 = 0;
|
||||
}
|
||||
|
||||
CObjstateCommand::CObjstateCommand() {
|
||||
ObjstateCommand::ObjstateCommand() {
|
||||
_value = 0;
|
||||
_objCommandName = 0;
|
||||
}
|
||||
|
||||
bool CObjstateCommand::load(MfcArchive &file) {
|
||||
debug(5, "CObjStateCommand::load()");
|
||||
bool ObjstateCommand::load(MfcArchive &file) {
|
||||
debug(5, "ObjStateCommand::load()");
|
||||
|
||||
_objtype = kObjTypeObjstateCommand;
|
||||
|
||||
@ -196,6 +196,9 @@ MessageQueue::MessageQueue() {
|
||||
_isFinished = 0;
|
||||
_flags = 0;
|
||||
_queueName = 0;
|
||||
_counter = 0;
|
||||
_field_38 = 0;
|
||||
_flag1 = 0;
|
||||
}
|
||||
|
||||
MessageQueue::MessageQueue(MessageQueue *src, int parId, int field_38) {
|
||||
@ -222,6 +225,7 @@ MessageQueue::MessageQueue(MessageQueue *src, int parId, int field_38) {
|
||||
g_fullpipe->_globalMessageQueueList->addMessageQueue(this);
|
||||
|
||||
_isFinished = 0;
|
||||
_flag1 = 0;
|
||||
}
|
||||
|
||||
MessageQueue::~MessageQueue() {
|
||||
|
@ -82,14 +82,14 @@ class ExCommand2 : public ExCommand {
|
||||
int _pointsSize;
|
||||
};
|
||||
|
||||
class CObjstateCommand : public CObject {
|
||||
class ObjstateCommand : public CObject {
|
||||
public:
|
||||
ExCommand _cmd;
|
||||
char *_objCommandName;
|
||||
int _value;
|
||||
|
||||
public:
|
||||
CObjstateCommand();
|
||||
ObjstateCommand();
|
||||
virtual bool load(MfcArchive &file);
|
||||
};
|
||||
|
||||
@ -99,7 +99,6 @@ class MessageQueue : public CObject {
|
||||
int _flags;
|
||||
char *_queueName;
|
||||
int16 _dataId;
|
||||
int16 _field_12;
|
||||
CObject *_field_14;
|
||||
Common::List<ExCommand *> _exCommands;
|
||||
int _counter;
|
||||
|
@ -28,30 +28,30 @@
|
||||
|
||||
namespace Fullpipe {
|
||||
|
||||
bool CBaseModalObject::handleMessage(ExCommand *message) {
|
||||
warning("STUB: CBaseModalObject::handleMessage()");
|
||||
bool BaseModalObject::handleMessage(ExCommand *message) {
|
||||
warning("STUB: BaseModalObject::handleMessage()");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBaseModalObject::init(int counterdiff) {
|
||||
warning("STUB: CBaseModalObject::init(%d)", counterdiff);
|
||||
bool BaseModalObject::init(int counterdiff) {
|
||||
warning("STUB: BaseModalObject::init(%d)", counterdiff);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBaseModalObject::update() {
|
||||
warning("STUB: CBaseModalObject::update()");
|
||||
bool BaseModalObject::update() {
|
||||
warning("STUB: BaseModalObject::update()");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBaseModalObject::saveload() {
|
||||
warning("STUB: CBaseModalObject::saveload()");
|
||||
void BaseModalObject::saveload() {
|
||||
warning("STUB: BaseModalObject::saveload()");
|
||||
}
|
||||
|
||||
|
||||
CModalIntro::CModalIntro() {
|
||||
ModalIntro::ModalIntro() {
|
||||
_field_8 = 0;
|
||||
_countDown = 0;
|
||||
_needRedraw = 0;
|
||||
@ -68,7 +68,7 @@ CModalIntro::CModalIntro() {
|
||||
_sfxVolume = g_fullpipe->_sfxVolume;
|
||||
}
|
||||
|
||||
bool CModalIntro::handleMessage(ExCommand *message) {
|
||||
bool ModalIntro::handleMessage(ExCommand *message) {
|
||||
if (message->_messageKind != 17)
|
||||
return false;
|
||||
|
||||
|
@ -25,14 +25,14 @@
|
||||
|
||||
namespace Fullpipe {
|
||||
|
||||
class CBaseModalObject {
|
||||
class BaseModalObject {
|
||||
public:
|
||||
|
||||
CBaseModalObject *_parentObj;
|
||||
BaseModalObject *_parentObj;
|
||||
|
||||
public:
|
||||
CBaseModalObject() : _parentObj(0) {}
|
||||
virtual ~CBaseModalObject() {}
|
||||
BaseModalObject() : _parentObj(0) {}
|
||||
virtual ~BaseModalObject() {}
|
||||
|
||||
virtual bool handleMessage(ExCommand *message);
|
||||
virtual bool init(int counterdiff);
|
||||
@ -41,7 +41,7 @@ class CBaseModalObject {
|
||||
void saveload();
|
||||
};
|
||||
|
||||
class CModalIntro : public CBaseModalObject {
|
||||
class ModalIntro : public BaseModalObject {
|
||||
int _field_8;
|
||||
int _introFlags;
|
||||
int _countDown;
|
||||
@ -49,7 +49,7 @@ class CModalIntro : public CBaseModalObject {
|
||||
int _sfxVolume;
|
||||
|
||||
public:
|
||||
CModalIntro();
|
||||
ModalIntro();
|
||||
|
||||
virtual bool handleMessage(ExCommand *message);
|
||||
};
|
||||
|
@ -27,35 +27,40 @@
|
||||
#include "common/list.h"
|
||||
|
||||
#include "fullpipe/objects.h"
|
||||
#include "fullpipe/statics.h"
|
||||
#include "fullpipe/motion.h"
|
||||
#include "fullpipe/messages.h"
|
||||
#include "fullpipe/gameloader.h"
|
||||
|
||||
namespace Fullpipe {
|
||||
|
||||
bool CMotionController::load(MfcArchive &file) {
|
||||
bool MotionController::load(MfcArchive &file) {
|
||||
// Is originally empty file.readClass();
|
||||
|
||||
debug(5, "CMotionController::load()");
|
||||
debug(5, "MotionController::load()");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMctlCompound::load(MfcArchive &file) {
|
||||
debug(5, "CMctlCompound::load()");
|
||||
bool MctlCompound::load(MfcArchive &file) {
|
||||
debug(5, "MctlCompound::load()");
|
||||
|
||||
int count = file.readUint32LE();
|
||||
|
||||
debug(6, "CMctlCompound::count = %d", count);
|
||||
debug(6, "MctlCompound::count = %d", count);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
debug(6, "CompoundArray[%d]", i);
|
||||
CMctlCompoundArrayItem *obj = (CMctlCompoundArrayItem *)file.readClass();
|
||||
MctlCompoundArrayItem *obj = new MctlCompoundArrayItem();
|
||||
|
||||
obj->_motionControllerObj = (MotionController *)file.readClass();
|
||||
|
||||
int count1 = file.readUint32LE();
|
||||
|
||||
debug(6, "ConnectionPoint::count: %d", count1);
|
||||
for (int j = 0; j < count1; j++) {
|
||||
debug(6, "ConnectionPoint[%d]", j);
|
||||
CMctlConnectionPoint *obj1 = (CMctlConnectionPoint *)file.readClass();
|
||||
MctlConnectionPoint *obj1 = (MctlConnectionPoint *)file.readClass();
|
||||
|
||||
obj->_connectionPoints.push_back(*obj1);
|
||||
}
|
||||
@ -64,57 +69,97 @@ bool CMctlCompound::load(MfcArchive &file) {
|
||||
obj->_field_24 = file.readUint32LE();
|
||||
|
||||
debug(6, "graphReact");
|
||||
obj->_movGraphReactObj = (CMovGraphReact *)file.readClass();
|
||||
obj->_movGraphReactObj = (MovGraphReact *)file.readClass();
|
||||
|
||||
_motionControllers.push_back(*obj);
|
||||
_motionControllers.push_back(obj);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMctlCompound::addObject(StaticANIObject *obj) {
|
||||
warning("STUB: CMctlCompound::addObject()");
|
||||
void MctlCompound::addObject(StaticANIObject *obj) {
|
||||
for (uint i = 0; i < _motionControllers.size(); i++)
|
||||
_motionControllers[i]->_motionControllerObj->addObject(obj);
|
||||
}
|
||||
|
||||
void CMctlCompound::initMovGraph2() {
|
||||
warning("STUB: CMctlCompound::initMovGraph2()");
|
||||
}
|
||||
|
||||
MessageQueue *CMctlCompound::method34(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId) {
|
||||
warning("STUB: CMctlCompound::method34()");
|
||||
int MctlCompound::removeObject(StaticANIObject *obj) {
|
||||
warning("STUB: MctlCompound::removeObject()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MessageQueue *CMctlCompound::method4C(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId) {
|
||||
warning("STUB: CMctlCompound::method4C()");
|
||||
void MctlCompound::initMovGraph2() {
|
||||
if (_objtype != kObjTypeMctlCompound)
|
||||
return;
|
||||
|
||||
for (uint i = 0; i < _motionControllers.size(); i++) {
|
||||
if (_motionControllers[i]->_motionControllerObj->_objtype != kObjTypeMovGraph)
|
||||
continue;
|
||||
|
||||
MovGraph *gr = (MovGraph *)_motionControllers[i]->_motionControllerObj;
|
||||
|
||||
MovGraph2 *newgr = new MovGraph2();
|
||||
|
||||
newgr->_links = gr->_links;
|
||||
newgr->_nodes = gr->_nodes;
|
||||
|
||||
gr->_links.clear();
|
||||
gr->_nodes.clear();
|
||||
|
||||
delete gr;
|
||||
|
||||
_motionControllers[i]->_motionControllerObj = newgr;
|
||||
}
|
||||
}
|
||||
|
||||
void MctlCompound::freeItems() {
|
||||
warning("STUB: MctlCompound::freeItems()");
|
||||
}
|
||||
|
||||
MessageQueue *MctlCompound::method34(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId) {
|
||||
warning("STUB: MctlCompound::method34()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CMctlCompoundArray::load(MfcArchive &file) {
|
||||
debug(5, "CMctlCompoundArray::load()");
|
||||
MessageQueue *MctlCompound::method4C(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId) {
|
||||
warning("STUB: MctlCompound::method4C()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool MctlCompoundArray::load(MfcArchive &file) {
|
||||
debug(5, "MctlCompoundArray::load()");
|
||||
|
||||
int count = file.readUint32LE();
|
||||
|
||||
debug(0, "CMctlCompoundArray::count = %d", count);
|
||||
debug(0, "MctlCompoundArray::count = %d", count);
|
||||
|
||||
assert(0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CMovGraph::CMovGraph() {
|
||||
warning("STUB: CMovGraph::CMovGraph()");
|
||||
_itemsCount = 0;
|
||||
_items = 0;
|
||||
//_callback1 = CMovGraphCallback1; // TODO
|
||||
_field_44 = 0;
|
||||
// insertMessageHandler(CMovGraph_messageHandler, getMessageHandlersCount() - 1, 129);
|
||||
int MovGraph_messageHandler(ExCommand *cmd);
|
||||
|
||||
int MovGraphCallback(int a1, int a2, int a3) {
|
||||
warning("STUB: MovgraphCallback");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CMovGraph::load(MfcArchive &file) {
|
||||
debug(5, "CMovGraph::load()");
|
||||
MovGraph::MovGraph() {
|
||||
_itemsCount = 0;
|
||||
_items = 0;
|
||||
_callback1 = MovGraphCallback;
|
||||
_field_44 = 0;
|
||||
insertMessageHandler(MovGraph_messageHandler, getMessageHandlersCount() - 1, 129);
|
||||
|
||||
_objtype = kObjTypeMovGraph;
|
||||
}
|
||||
|
||||
bool MovGraph::load(MfcArchive &file) {
|
||||
debug(5, "MovGraph::load()");
|
||||
|
||||
_links.load(file);
|
||||
_nodes.load(file);
|
||||
@ -122,11 +167,288 @@ bool CMovGraph::load(MfcArchive &file) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMovGraph::addObject(StaticANIObject *obj) {
|
||||
warning("STUB: CMovGraph::addObject()");
|
||||
void MovGraph::addObject(StaticANIObject *obj) {
|
||||
warning("STUB: MovGraph::addObject()");
|
||||
}
|
||||
|
||||
CMovGraphLink::CMovGraphLink() {
|
||||
int MovGraph::removeObject(StaticANIObject *obj) {
|
||||
warning("STUB: MovGraph::removeObject()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MovGraph::freeItems() {
|
||||
warning("STUB: MovGraph::freeItems()");
|
||||
}
|
||||
|
||||
int MovGraph::method28() {
|
||||
warning("STUB: MovGraph::method28()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MovGraph::method2C() {
|
||||
warning("STUB: MovGraph::method2C()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MessageQueue *MovGraph::method34(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId) {
|
||||
warning("STUB: MovGraph::method34()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MovGraph::changeCallback() {
|
||||
warning("STUB: MovGraph::changeCallback()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MovGraph::method3C() {
|
||||
warning("STUB: MovGraph::method3C()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MovGraph::method44() {
|
||||
warning("STUB: MovGraph::method44()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MessageQueue *MovGraph::method4C(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId) {
|
||||
warning("STUB: MovGraph::method4C()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MovGraph::method50() {
|
||||
warning("STUB: MovGraph::method50()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
double MovGraph::calcDistance(Common::Point *point, MovGraphLink *link, int flag) {
|
||||
int n1x = link->_movGraphNode1->_x;
|
||||
int n1y = link->_movGraphNode1->_y;
|
||||
int n2x = link->_movGraphNode2->_x;
|
||||
int n2y = link->_movGraphNode2->_y;
|
||||
double dist1x = (double)(point->x - n1x);
|
||||
double dist1y = (double)(n1y - point->y);
|
||||
double dist2x = (double)(n2x - n1x);
|
||||
double dist2y = (double)(n2y - n1y);
|
||||
double dist1 = sqrt(dist1y * dist1y + dist1x * dist1x);
|
||||
double dist2 = ((double)(n1y - n2y) * dist1y + dist2x * dist1x) / link->_distance / dist1;
|
||||
double distm = dist2 * dist1;
|
||||
double res = sqrt(1.0 - dist2 * dist2) * dist1;
|
||||
|
||||
if (dist2 <= 0.0 || distm >= link->_distance) {
|
||||
if (flag) {
|
||||
if (dist2 > 0.0) {
|
||||
if (distm >= link->_distance) {
|
||||
point->x = n2x;
|
||||
point->y = n2y;
|
||||
}
|
||||
} else {
|
||||
point->x = n1x;
|
||||
point->y = n1y;
|
||||
}
|
||||
} else {
|
||||
return -1.0;
|
||||
}
|
||||
} else {
|
||||
point->x = n1x + (dist2x * distm / link->_distance);
|
||||
point->y = n1y + (dist2y * distm / link->_distance);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int MovGraph2::getItemIndexByGameObjectId(int objectId) {
|
||||
for (uint i = 0; i < _items.size(); i++)
|
||||
if (_items[i]->_objectId == objectId)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool MovGraph2::initDirections(StaticANIObject *obj, MovGraph2Item *item) {
|
||||
item->_obj = obj;
|
||||
item->_objectId = obj->_id;
|
||||
|
||||
GameVar *var = g_fullpipe->getGameLoaderGameVar()->getSubVarByName(obj->_objectName);
|
||||
if (!var)
|
||||
return false;
|
||||
|
||||
var = var->getSubVarByName("Test_walk");
|
||||
|
||||
if (!var)
|
||||
return false;
|
||||
|
||||
GameVar *varD = 0;
|
||||
Common::Point point;
|
||||
|
||||
for (int dir = 0; dir < 4; dir++) {
|
||||
switch (dir) {
|
||||
case 0:
|
||||
varD = var->getSubVarByName("Right");
|
||||
break;
|
||||
case 1:
|
||||
varD = var->getSubVarByName("Left");
|
||||
break;
|
||||
case 2:
|
||||
varD = var->getSubVarByName("Up");
|
||||
break;
|
||||
case 3:
|
||||
varD = var->getSubVarByName("Down");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!varD)
|
||||
return false;
|
||||
|
||||
for (int act = 0; act < 3; act++) {
|
||||
int idx;
|
||||
|
||||
switch(act) {
|
||||
case 0:
|
||||
idx = varD->getSubVarAsInt("Start");
|
||||
break;
|
||||
case 1:
|
||||
idx = varD->getSubVarAsInt("Go");
|
||||
break;
|
||||
case 2:
|
||||
idx = varD->getSubVarAsInt("Stop");
|
||||
break;
|
||||
}
|
||||
|
||||
item->_subItems[dir]._walk[act]._movementId = idx;
|
||||
|
||||
Movement *mov = obj->getMovementById(idx);
|
||||
|
||||
item->_subItems[dir]._walk[act]._mov = mov;
|
||||
if (mov) {
|
||||
mov->calcSomeXY(point, 0);
|
||||
item->_subItems[dir]._walk[act]._mx = point.x;
|
||||
item->_subItems[dir]._walk[act]._my = point.y;
|
||||
}
|
||||
}
|
||||
|
||||
for (int act = 0; act < 4; act++) {
|
||||
int idx;
|
||||
|
||||
switch(act) {
|
||||
case 0:
|
||||
idx = varD->getSubVarAsInt("TurnR");
|
||||
break;
|
||||
case 1:
|
||||
idx = varD->getSubVarAsInt("TurnL");
|
||||
break;
|
||||
case 2:
|
||||
idx = varD->getSubVarAsInt("TurnU");
|
||||
break;
|
||||
case 3:
|
||||
idx = varD->getSubVarAsInt("TurnD");
|
||||
break;
|
||||
}
|
||||
|
||||
item->_subItems[dir]._turn[act]._movementId = idx;
|
||||
|
||||
Movement *mov = obj->getMovementById(idx);
|
||||
|
||||
item->_subItems[dir]._turn[act]._mov = mov;
|
||||
if (mov) {
|
||||
mov->calcSomeXY(point, 0);
|
||||
item->_subItems[dir]._turn[act]._mx = point.x;
|
||||
item->_subItems[dir]._turn[act]._my = point.y;
|
||||
}
|
||||
}
|
||||
|
||||
for (int act = 0; act < 4; act++) {
|
||||
int idx;
|
||||
|
||||
switch(act) {
|
||||
case 0:
|
||||
idx = varD->getSubVarAsInt("TurnSR");
|
||||
break;
|
||||
case 1:
|
||||
idx = varD->getSubVarAsInt("TurnSL");
|
||||
break;
|
||||
case 2:
|
||||
idx = varD->getSubVarAsInt("TurnSU");
|
||||
break;
|
||||
case 3:
|
||||
idx = varD->getSubVarAsInt("TurnSD");
|
||||
break;
|
||||
}
|
||||
|
||||
item->_subItems[dir]._turnS[act]._movementId = idx;
|
||||
|
||||
Movement *mov = obj->getMovementById(idx);
|
||||
|
||||
item->_subItems[dir]._turnS[act]._mov = mov;
|
||||
if (mov) {
|
||||
mov->calcSomeXY(point, 0);
|
||||
item->_subItems[dir]._turnS[act]._mx = point.x;
|
||||
item->_subItems[dir]._turnS[act]._my = point.y;
|
||||
}
|
||||
}
|
||||
|
||||
item->_subItems[dir]._staticsId1 = item->_subItems[dir]._walk[0]._mov->_staticsObj1->_staticsId;
|
||||
item->_subItems[dir]._staticsId2 = item->_subItems[dir]._walk[0]._mov->_staticsObj2->_staticsId;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MovGraph2::addObject(StaticANIObject *obj) {
|
||||
MovGraph::addObject(obj);
|
||||
|
||||
int id = getItemIndexByGameObjectId(obj->_id);
|
||||
|
||||
if (id >= 0) {
|
||||
_items[id]->_obj = obj;
|
||||
} else {
|
||||
MovGraph2Item *item = new MovGraph2Item;
|
||||
|
||||
if (initDirections(obj, item)) {
|
||||
_items.push_back(item);
|
||||
} else {
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int MovGraph2::removeObject(StaticANIObject *obj) {
|
||||
warning("STUB: MovGraph2::removeObject()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MovGraph2::freeItems() {
|
||||
warning("STUB: MovGraph2::freeItems()");
|
||||
}
|
||||
|
||||
MessageQueue *MovGraph2::method34(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId) {
|
||||
warning("STUB: MovGraph2::method34()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MessageQueue *MovGraph2::method4C(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId) {
|
||||
warning("STUB: MovGraph2::method4C()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MovGraphNode *MovGraph::calcOffset(int ox, int oy) {
|
||||
warning("STUB: MovGraph::calcOffset()");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MovGraphLink::MovGraphLink() {
|
||||
_distance = 0;
|
||||
_angle = 0;
|
||||
_flags = 0x10000000;
|
||||
@ -138,8 +460,8 @@ CMovGraphLink::CMovGraphLink() {
|
||||
_name = 0;
|
||||
}
|
||||
|
||||
bool CMovGraphLink::load(MfcArchive &file) {
|
||||
debug(5, "CMovGraphLink::load()");
|
||||
bool MovGraphLink::load(MfcArchive &file) {
|
||||
debug(5, "MovGraphLink::load()");
|
||||
|
||||
_dwordArray1.load(file);
|
||||
_dwordArray2.load(file);
|
||||
@ -147,23 +469,23 @@ bool CMovGraphLink::load(MfcArchive &file) {
|
||||
_flags = file.readUint32LE();
|
||||
|
||||
debug(8, "GraphNode1");
|
||||
_movGraphNode1 = (CMovGraphNode *)file.readClass();
|
||||
_movGraphNode1 = (MovGraphNode *)file.readClass();
|
||||
debug(8, "GraphNode2");
|
||||
_movGraphNode2 = (CMovGraphNode *)file.readClass();
|
||||
_movGraphNode2 = (MovGraphNode *)file.readClass();
|
||||
|
||||
_distance = file.readDouble();
|
||||
_angle = file.readDouble();
|
||||
|
||||
debug(8, "distance: %g, angle: %g", _distance, _angle);
|
||||
|
||||
_movGraphReact = (CMovGraphReact *)file.readClass();
|
||||
_movGraphReact = (MovGraphReact *)file.readClass();
|
||||
_name = file.readPascalString();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CMovGraphNode::load(MfcArchive &file) {
|
||||
debug(5, "CMovGraphNode::load()");
|
||||
bool MovGraphNode::load(MfcArchive &file) {
|
||||
debug(5, "MovGraphNode::load()");
|
||||
|
||||
_field_14 = file.readUint32LE();
|
||||
_x = file.readUint32LE();
|
||||
@ -173,7 +495,7 @@ bool CMovGraphNode::load(MfcArchive &file) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CReactParallel::CReactParallel() {
|
||||
ReactParallel::ReactParallel() {
|
||||
_x1 = 0;
|
||||
_x2 = 0;
|
||||
_dy = 0;
|
||||
@ -183,8 +505,8 @@ CReactParallel::CReactParallel() {
|
||||
_y2 = 0;
|
||||
}
|
||||
|
||||
bool CReactParallel::load(MfcArchive &file) {
|
||||
debug(5, "CReactParallel::load()");
|
||||
bool ReactParallel::load(MfcArchive &file) {
|
||||
debug(5, "ReactParallel::load()");
|
||||
|
||||
_x1 = file.readUint32LE();
|
||||
_y1 = file.readUint32LE();
|
||||
@ -198,7 +520,7 @@ bool CReactParallel::load(MfcArchive &file) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void CReactParallel::createRegion() {
|
||||
void ReactParallel::createRegion() {
|
||||
_points = (Common::Point **)malloc(sizeof(Common::Point *) * 4);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
@ -223,15 +545,15 @@ void CReactParallel::createRegion() {
|
||||
// GdiObject::Attach(_rgn, CreatePolygonRgn(_points, 4, 2);
|
||||
}
|
||||
|
||||
CReactPolygonal::CReactPolygonal() {
|
||||
ReactPolygonal::ReactPolygonal() {
|
||||
_field_C = 0;
|
||||
_points = 0;
|
||||
_pointCount = 0;
|
||||
_field_10 = 0;
|
||||
}
|
||||
|
||||
bool CReactPolygonal::load(MfcArchive &file) {
|
||||
debug(5, "CReactPolygonal::load()");
|
||||
bool ReactPolygonal::load(MfcArchive &file) {
|
||||
debug(5, "ReactPolygonal::load()");
|
||||
|
||||
_field_C = file.readUint32LE();
|
||||
_field_10 = file.readUint32LE();
|
||||
@ -254,7 +576,7 @@ bool CReactPolygonal::load(MfcArchive &file) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void CReactPolygonal::createRegion() {
|
||||
void ReactPolygonal::createRegion() {
|
||||
if (_points) {
|
||||
|
||||
// GdiObject::Attach(_rgn, CreatePolygonRgn(_points, _pointCount, 2);
|
||||
@ -262,7 +584,10 @@ void CReactPolygonal::createRegion() {
|
||||
}
|
||||
|
||||
int startWalkTo(int objId, int objKey, int x, int y, int a5) {
|
||||
warning("STUB: startWalkTo(%d, %d, %d, %d, %d)", objId, objKey, x, y, a5);
|
||||
MctlCompound *mc = getSc2MctlCompoundBySceneId(g_fullpipe->_currentScene->_sceneId);
|
||||
|
||||
if (mc)
|
||||
return (mc->method34(g_fullpipe->_currentScene->getStaticANIObject1ById(objId, objKey), x, y, a5, 0) != 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -29,54 +29,88 @@ int startWalkTo(int objId, int objKey, int x, int y, int a5);
|
||||
int doSomeAnimation(int objId, int objKey, int a3);
|
||||
int doSomeAnimation2(int objId, int objKey);
|
||||
|
||||
class CMotionController : public CObject {
|
||||
public:
|
||||
class MotionController : public CObject {
|
||||
public:
|
||||
int _field_4;
|
||||
bool _isEnabled;
|
||||
|
||||
public:
|
||||
CMotionController() : _isEnabled(true) {}
|
||||
public:
|
||||
MotionController() : _isEnabled(true), _field_4(0) {}
|
||||
virtual ~MotionController() {}
|
||||
virtual bool load(MfcArchive &file);
|
||||
|
||||
void setEnabled() { _isEnabled = true; }
|
||||
void clearEnabled() { _isEnabled = false; }
|
||||
|
||||
virtual void methodC() {}
|
||||
virtual void method10() {}
|
||||
virtual void clearEnabled() { _isEnabled = false; }
|
||||
virtual void setEnabled() { _isEnabled = true; }
|
||||
virtual void addObject(StaticANIObject *obj) {}
|
||||
virtual int removeObject(StaticANIObject *obj) { return 0; }
|
||||
virtual void freeItems() {}
|
||||
virtual int method28() { return 0; }
|
||||
virtual int method2C() { return 0; }
|
||||
virtual int method30() { return 0; }
|
||||
virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId) { return 0; }
|
||||
virtual int changeCallback() { return 0; }
|
||||
virtual int method3C() { return 0; }
|
||||
virtual int method40() { return 0; }
|
||||
virtual int method44() { return 0; }
|
||||
virtual int method48() { return -1; }
|
||||
virtual MessageQueue *method4C(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId) { return 0; }
|
||||
};
|
||||
|
||||
class CMctlCompoundArray : public Common::Array<CObject>, public CObject {
|
||||
class MovGraphReact : public CObject {
|
||||
// Empty
|
||||
};
|
||||
|
||||
typedef Common::Array<CObject> MctlConnectionPointsArray;
|
||||
|
||||
class MctlCompoundArrayItem : public CObject {
|
||||
friend class MctlCompound;
|
||||
|
||||
protected:
|
||||
MotionController *_motionControllerObj;
|
||||
MovGraphReact *_movGraphReactObj;
|
||||
MctlConnectionPointsArray _connectionPoints;
|
||||
int _field_20;
|
||||
int _field_24;
|
||||
int _field_28;
|
||||
|
||||
public:
|
||||
MctlCompoundArrayItem() : _movGraphReactObj(0) {}
|
||||
};
|
||||
|
||||
class MctlCompoundArray : public Common::Array<MctlCompoundArrayItem *>, public CObject {
|
||||
public:
|
||||
virtual bool load(MfcArchive &file);
|
||||
};
|
||||
|
||||
class CMctlConnectionPointsArray : public Common::Array<CObject>, public CObject {
|
||||
public:
|
||||
virtual bool load(MfcArchive &file);
|
||||
};
|
||||
|
||||
class CMctlCompound : public CMotionController {
|
||||
CMctlCompoundArray _motionControllers;
|
||||
class MctlCompound : public MotionController {
|
||||
MctlCompoundArray _motionControllers;
|
||||
|
||||
public:
|
||||
MctlCompound() { _objtype = kObjTypeMctlCompound; }
|
||||
|
||||
virtual bool load(MfcArchive &file);
|
||||
|
||||
virtual void addObject(StaticANIObject *obj);
|
||||
void initMovGraph2();
|
||||
virtual int removeObject(StaticANIObject *obj);
|
||||
virtual void freeItems();
|
||||
virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId);
|
||||
virtual MessageQueue *method4C(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId);
|
||||
|
||||
MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId);
|
||||
MessageQueue *method4C(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId);
|
||||
void initMovGraph2();
|
||||
};
|
||||
|
||||
class Unk2 : public CObject {
|
||||
public:
|
||||
int _items;
|
||||
int _count;
|
||||
|
||||
public:
|
||||
public:
|
||||
Unk2() : _items(0), _count(0) {}
|
||||
};
|
||||
|
||||
class CMovGraphNode : public CObject {
|
||||
class MovGraphNode : public CObject {
|
||||
public:
|
||||
int _x;
|
||||
int _y;
|
||||
int _distance;
|
||||
@ -84,30 +118,11 @@ class CMovGraphNode : public CObject {
|
||||
int _field_14;
|
||||
|
||||
public:
|
||||
CMovGraphNode() : _x(0), _y(0), _distance(0), _field_10(0), _field_14(0) {}
|
||||
MovGraphNode() : _x(0), _y(0), _distance(0), _field_10(0), _field_14(0) {}
|
||||
virtual bool load(MfcArchive &file);
|
||||
};
|
||||
|
||||
class CMovGraphReact : public CObject {
|
||||
// Empty
|
||||
};
|
||||
|
||||
class CMctlCompoundArrayItem : public CObject {
|
||||
friend class CMctlCompound;
|
||||
|
||||
protected:
|
||||
CMotionController *_motionControllerObj;
|
||||
CMovGraphReact *_movGraphReactObj;
|
||||
CMctlConnectionPointsArray _connectionPoints;
|
||||
int _field_20;
|
||||
int _field_24;
|
||||
int _field_28;
|
||||
|
||||
public:
|
||||
CMctlCompoundArrayItem() : _movGraphReactObj(0) {}
|
||||
};
|
||||
|
||||
class CReactParallel : public CMovGraphReact {
|
||||
class ReactParallel : public MovGraphReact {
|
||||
//CRgn _rgn;
|
||||
int _x1;
|
||||
int _y1;
|
||||
@ -118,12 +133,12 @@ class CReactParallel : public CMovGraphReact {
|
||||
Common::Point **_points;
|
||||
|
||||
public:
|
||||
CReactParallel();
|
||||
ReactParallel();
|
||||
virtual bool load(MfcArchive &file);
|
||||
void createRegion();
|
||||
};
|
||||
|
||||
class CReactPolygonal : public CMovGraphReact {
|
||||
class ReactPolygonal : public MovGraphReact {
|
||||
//CRgn _rgn;
|
||||
int _field_C;
|
||||
int _field_10;
|
||||
@ -131,32 +146,34 @@ class CReactPolygonal : public CMovGraphReact {
|
||||
Common::Point **_points;
|
||||
|
||||
public:
|
||||
CReactPolygonal();
|
||||
ReactPolygonal();
|
||||
virtual bool load(MfcArchive &file);
|
||||
void createRegion();
|
||||
};
|
||||
|
||||
class CMovGraphLink : public CObject {
|
||||
CMovGraphNode *_movGraphNode1;
|
||||
CMovGraphNode *_movGraphNode2;
|
||||
CDWordArray _dwordArray1;
|
||||
CDWordArray _dwordArray2;
|
||||
class MovGraphLink : public CObject {
|
||||
public:
|
||||
MovGraphNode *_movGraphNode1;
|
||||
MovGraphNode *_movGraphNode2;
|
||||
DWordArray _dwordArray1;
|
||||
DWordArray _dwordArray2;
|
||||
int _flags;
|
||||
int _field_38;
|
||||
int _field_3C;
|
||||
double _distance;
|
||||
double _angle;
|
||||
CMovGraphReact *_movGraphReact;
|
||||
MovGraphReact *_movGraphReact;
|
||||
char *_name;
|
||||
|
||||
public:
|
||||
CMovGraphLink();
|
||||
MovGraphLink();
|
||||
virtual bool load(MfcArchive &file);
|
||||
};
|
||||
|
||||
class CMovGraph : public CMotionController {
|
||||
CObList _nodes;
|
||||
CObList _links;
|
||||
class MovGraph : public MotionController {
|
||||
public:
|
||||
ObList _nodes;
|
||||
ObList _links;
|
||||
int _field_44;
|
||||
int _items;
|
||||
int _itemsCount;
|
||||
@ -164,13 +181,65 @@ class CMovGraph : public CMotionController {
|
||||
Unk2 _unk2;
|
||||
|
||||
public:
|
||||
CMovGraph();
|
||||
MovGraph();
|
||||
virtual bool load(MfcArchive &file);
|
||||
|
||||
virtual void addObject(StaticANIObject *obj);
|
||||
virtual int removeObject(StaticANIObject *obj);
|
||||
virtual void freeItems();
|
||||
virtual int method28();
|
||||
virtual int method2C();
|
||||
virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId);
|
||||
virtual int changeCallback();
|
||||
virtual int method3C();
|
||||
virtual int method44();
|
||||
virtual MessageQueue *method4C(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId);
|
||||
virtual int method50();
|
||||
|
||||
double calcDistance(Common::Point *point, MovGraphLink *link, int flag);
|
||||
MovGraphNode *calcOffset(int ox, int oy);
|
||||
};
|
||||
|
||||
class CMctlConnectionPoint : public CObject {
|
||||
class Movement;
|
||||
|
||||
struct MG2I {
|
||||
int _movementId;
|
||||
Movement *_mov;
|
||||
int _mx;
|
||||
int _my;
|
||||
};
|
||||
|
||||
struct MovGraph2ItemSub {
|
||||
int _staticsId2;
|
||||
int _staticsId1;
|
||||
MG2I _walk[3];
|
||||
MG2I _turn[4];
|
||||
MG2I _turnS[4];
|
||||
};
|
||||
|
||||
struct MovGraph2Item {
|
||||
int _objectId;
|
||||
StaticANIObject *_obj;
|
||||
MovGraph2ItemSub _subItems[4];
|
||||
};
|
||||
|
||||
class MovGraph2 : public MovGraph {
|
||||
public:
|
||||
Common::Array<MovGraph2Item *> _items;
|
||||
|
||||
public:
|
||||
virtual void addObject(StaticANIObject *obj);
|
||||
virtual int removeObject(StaticANIObject *obj);
|
||||
virtual void freeItems();
|
||||
virtual MessageQueue *method34(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId);
|
||||
virtual MessageQueue *method4C(StaticANIObject *subj, int xpos, int ypos, int flag, int staticsId);
|
||||
|
||||
int getItemIndexByGameObjectId(int objectId);
|
||||
bool initDirections(StaticANIObject *obj, MovGraph2Item *item);
|
||||
};
|
||||
|
||||
class MctlConnectionPoint : public CObject {
|
||||
public:
|
||||
int _connectionX;
|
||||
int _connectionY;
|
||||
int _field_C;
|
||||
|
@ -69,27 +69,27 @@ union VarValue {
|
||||
char *stringValue;
|
||||
};
|
||||
|
||||
class CGameVar : public CObject {
|
||||
class GameVar : public CObject {
|
||||
public:
|
||||
CGameVar *_nextVarObj;
|
||||
CGameVar *_prevVarObj;
|
||||
CGameVar *_parentVarObj;
|
||||
CGameVar *_subVars;
|
||||
CGameVar *_field_14;
|
||||
GameVar *_nextVarObj;
|
||||
GameVar *_prevVarObj;
|
||||
GameVar *_parentVarObj;
|
||||
GameVar *_subVars;
|
||||
GameVar *_field_14;
|
||||
char *_varName;
|
||||
VarValue _value;
|
||||
int _varType;
|
||||
|
||||
public:
|
||||
CGameVar();
|
||||
GameVar();
|
||||
virtual bool load(MfcArchive &file);
|
||||
CGameVar *getSubVarByName(const char *name);
|
||||
GameVar *getSubVarByName(const char *name);
|
||||
bool setSubVarAsInt(const char *name, int value);
|
||||
int getSubVarAsInt(const char *name);
|
||||
CGameVar *addSubVarAsInt(const char *name, int value);
|
||||
bool addSubVar(CGameVar *subvar);
|
||||
GameVar *addSubVarAsInt(const char *name, int value);
|
||||
bool addSubVar(GameVar *subvar);
|
||||
int getSubVarsCount();
|
||||
CGameVar *getSubVarByIndex(int idx);
|
||||
GameVar *getSubVarByIndex(int idx);
|
||||
};
|
||||
|
||||
} // End of namespace Fullpipe
|
||||
|
@ -72,6 +72,7 @@ SceneTag::SceneTag() {
|
||||
_field_4 = 0;
|
||||
_scene = 0;
|
||||
_tag = 0;
|
||||
_sceneId = 0;
|
||||
}
|
||||
|
||||
bool SceneTag::load(MfcArchive &file) {
|
||||
@ -259,7 +260,7 @@ void Scene::init() {
|
||||
if (_staticANIObjectList2.size() != _staticANIObjectList1.size()) {
|
||||
_staticANIObjectList2.clear();
|
||||
|
||||
for (CPtrList::iterator s = _staticANIObjectList1.begin(); s != _staticANIObjectList1.end(); ++s)
|
||||
for (PtrList::iterator s = _staticANIObjectList1.begin(); s != _staticANIObjectList1.end(); ++s)
|
||||
_staticANIObjectList2.push_back(*s);
|
||||
}
|
||||
}
|
||||
@ -273,7 +274,7 @@ StaticANIObject *Scene::getAniMan() {
|
||||
}
|
||||
|
||||
StaticANIObject *Scene::getStaticANIObject1ById(int obj, int a3) {
|
||||
for (CPtrList::iterator s = _staticANIObjectList1.begin(); s != _staticANIObjectList1.end(); ++s) {
|
||||
for (PtrList::iterator s = _staticANIObjectList1.begin(); s != _staticANIObjectList1.end(); ++s) {
|
||||
StaticANIObject *o = (StaticANIObject *)*s;
|
||||
if (o->_id == obj && (a3 == -1 || o->_okeyCode == a3))
|
||||
return o;
|
||||
@ -327,7 +328,7 @@ void Scene::setPictureObjectsFlag4() {
|
||||
}
|
||||
|
||||
PictureObject *Scene::getPictureObjectById(int objId, int flags) {
|
||||
for (uint i = 0; i < _picObjList.size(); i++) {
|
||||
for (uint i = 1; i < _picObjList.size(); i++) {
|
||||
if (((PictureObject *)_picObjList[i])->_id == objId && ((PictureObject *)_picObjList[i])->_okeyCode == flags)
|
||||
return (PictureObject *)_picObjList[i];
|
||||
}
|
||||
@ -371,16 +372,16 @@ MessageQueue *Scene::getMessageQueueByName(char *name) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Scene::preloadMovements(CGameVar *var) {
|
||||
CGameVar *preload = var->getSubVarByName("PRELOAD");
|
||||
void Scene::preloadMovements(GameVar *var) {
|
||||
GameVar *preload = var->getSubVarByName("PRELOAD");
|
||||
if (!preload)
|
||||
return;
|
||||
|
||||
for (CGameVar *i = preload->_subVars; i; i = i->_nextVarObj) {
|
||||
for (GameVar *i = preload->_subVars; i; i = i->_nextVarObj) {
|
||||
StaticANIObject *ani = getStaticANIObject1ByName(i->_varName, -1);
|
||||
|
||||
if (ani) {
|
||||
CGameVar *subVars = i->_subVars;
|
||||
GameVar *subVars = i->_subVars;
|
||||
|
||||
if (subVars) {
|
||||
for (;subVars; subVars = subVars->_nextVarObj) {
|
||||
@ -397,7 +398,7 @@ void Scene::preloadMovements(CGameVar *var) {
|
||||
}
|
||||
|
||||
void Scene::initObjectCursors(const char *varname) {
|
||||
CGameVar *cursorsVar = g_fullpipe->getGameLoaderGameVar()->getSubVarByName(varname)->getSubVarByName("CURSORS");
|
||||
GameVar *cursorsVar = g_fullpipe->getGameLoaderGameVar()->getSubVarByName(varname)->getSubVarByName("CURSORS");
|
||||
|
||||
if (!cursorsVar || !cursorsVar->_subVars)
|
||||
return;
|
||||
@ -405,7 +406,7 @@ void Scene::initObjectCursors(const char *varname) {
|
||||
int maxId = 0;
|
||||
int minId = 0xffff;
|
||||
|
||||
for (CGameVar *sub = cursorsVar->_subVars; sub; sub = sub->_nextVarObj) {
|
||||
for (GameVar *sub = cursorsVar->_subVars; sub; sub = sub->_nextVarObj) {
|
||||
GameObject *obj = getPictureObjectByName(sub->_varName, -1);
|
||||
|
||||
if (obj || (obj = getStaticANIObject1ByName(sub->_varName, -1)) != 0) {
|
||||
@ -421,7 +422,7 @@ void Scene::initObjectCursors(const char *varname) {
|
||||
|
||||
g_fullpipe->_objectIdCursors.resize(maxId - minId + 1);
|
||||
|
||||
for (CGameVar *sub = cursorsVar->_subVars; sub; sub = sub->_nextVarObj) {
|
||||
for (GameVar *sub = cursorsVar->_subVars; sub; sub = sub->_nextVarObj) {
|
||||
GameObject *obj = getPictureObjectByName(sub->_varName, -1);
|
||||
|
||||
if (!obj)
|
||||
@ -441,7 +442,7 @@ bool Scene::compareObjPriority(const void *p1, const void *p2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Scene::objectList_sortByPriority(CPtrList &list) {
|
||||
void Scene::objectList_sortByPriority(PtrList &list) {
|
||||
Common::sort(list.begin(), list.end(), Scene::compareObjPriority);
|
||||
}
|
||||
|
||||
@ -453,12 +454,12 @@ void Scene::draw() {
|
||||
|
||||
objectList_sortByPriority(_staticANIObjectList2);
|
||||
|
||||
for (CPtrList::iterator s = _staticANIObjectList2.begin(); s != _staticANIObjectList2.end(); ++s) {
|
||||
for (PtrList::iterator s = _staticANIObjectList2.begin(); s != _staticANIObjectList2.end(); ++s) {
|
||||
((StaticANIObject *)*s)->draw2();
|
||||
}
|
||||
|
||||
int priority = -1;
|
||||
for (CPtrList::iterator s = _staticANIObjectList2.begin(); s != _staticANIObjectList2.end(); ++s) {
|
||||
for (PtrList::iterator s = _staticANIObjectList2.begin(); s != _staticANIObjectList2.end(); ++s) {
|
||||
drawContent(((StaticANIObject *)*s)->_priority, priority, false);
|
||||
((StaticANIObject *)*s)->draw();
|
||||
|
||||
@ -526,7 +527,7 @@ int Scene::getPictureObjectIdAtPos(int x, int y) {
|
||||
void Scene::update(int counterdiff) {
|
||||
debug(0, "Scene::update(%d)", counterdiff);
|
||||
|
||||
for (CPtrList::iterator s = _staticANIObjectList2.begin(); s != _staticANIObjectList2.end(); ++s)
|
||||
for (PtrList::iterator s = _staticANIObjectList2.begin(); s != _staticANIObjectList2.end(); ++s)
|
||||
((StaticANIObject *)*s)->update(counterdiff);
|
||||
}
|
||||
|
||||
|
@ -31,10 +31,10 @@ class MessageQueue;
|
||||
|
||||
class Scene : public Background {
|
||||
public:
|
||||
CPtrList _staticANIObjectList1;
|
||||
CPtrList _staticANIObjectList2;
|
||||
CPtrList _messageQueueList;
|
||||
CPtrList _faObjectList;
|
||||
PtrList _staticANIObjectList1;
|
||||
PtrList _staticANIObjectList2;
|
||||
PtrList _messageQueueList;
|
||||
PtrList _faObjectList;
|
||||
Shadows *_shadows;
|
||||
SoundList *_soundList;
|
||||
int16 _sceneId;
|
||||
@ -69,7 +69,7 @@ class Scene : public Background {
|
||||
PictureObject *getPictureObjectById(int objId, int flags);
|
||||
PictureObject *getPictureObjectByName(const char *name, int keyCode);
|
||||
void deletePictureObject(PictureObject *obj);
|
||||
void preloadMovements(CGameVar *var);
|
||||
void preloadMovements(GameVar *var);
|
||||
|
||||
StaticANIObject *getStaticANIObjectAtPos(int x, int y);
|
||||
PictureObject *getPictureObjectAtPos(int x, int y);
|
||||
@ -79,7 +79,7 @@ class Scene : public Background {
|
||||
|
||||
private:
|
||||
static bool compareObjPriority(const void *p1, const void *p2);
|
||||
void objectList_sortByPriority(CPtrList &list);
|
||||
void objectList_sortByPriority(PtrList &list);
|
||||
};
|
||||
|
||||
class SceneTag : public CObject {
|
||||
@ -88,7 +88,6 @@ class SceneTag : public CObject {
|
||||
char *_tag;
|
||||
Scene *_scene;
|
||||
int16 _sceneId;
|
||||
int16 _field_12;
|
||||
|
||||
public:
|
||||
SceneTag();
|
||||
|
@ -75,7 +75,7 @@ Vars::Vars() {
|
||||
}
|
||||
|
||||
bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) {
|
||||
CGameVar *sceneVar;
|
||||
GameVar *sceneVar;
|
||||
Common::Point sceneDim;
|
||||
|
||||
Scene *scene = accessScene(entrance->_sceneId);
|
||||
@ -137,21 +137,17 @@ bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) {
|
||||
_aniMan->_statics = _aniMan->getStaticsById(ST_MAN_EMPTY);
|
||||
_aniMan->setOXY(0, 0);
|
||||
|
||||
if (_aniMan) {
|
||||
_aniMan2 = _aniMan;
|
||||
CMctlCompound *cmp = getSc2MctlCompoundBySceneId(entrance->_sceneId);
|
||||
cmp->initMovGraph2();
|
||||
cmp->addObject(_aniMan);
|
||||
cmp->setEnabled();
|
||||
getGameLoaderInteractionController()->enableFlag24();
|
||||
setInputDisabled(0);
|
||||
} else {
|
||||
_aniMan2 = 0;
|
||||
}
|
||||
_aniMan2 = _aniMan;
|
||||
MctlCompound *cmp = getSc2MctlCompoundBySceneId(entrance->_sceneId);
|
||||
cmp->initMovGraph2();
|
||||
cmp->addObject(_aniMan);
|
||||
cmp->setEnabled();
|
||||
getGameLoaderInteractionController()->enableFlag24();
|
||||
setInputDisabled(0);
|
||||
|
||||
scene->setPictureObjectsFlag4();
|
||||
|
||||
for (CPtrList::iterator s = scene->_staticANIObjectList1.begin(); s != scene->_staticANIObjectList1.end(); ++s) {
|
||||
for (PtrList::iterator s = scene->_staticANIObjectList1.begin(); s != scene->_staticANIObjectList1.end(); ++s) {
|
||||
StaticANIObject *o = (StaticANIObject *)*s;
|
||||
o->setFlags(o->_flags & 0xFE7F);
|
||||
}
|
||||
@ -657,7 +653,7 @@ bool FullpipeEngine::sceneSwitcher(EntranceInfo *entrance) {
|
||||
}
|
||||
|
||||
void setElevatorButton(const char *name, int state) {
|
||||
CGameVar *var = g_fullpipe->getGameLoaderGameVar()->getSubVarByName("OBJSTATES")->getSubVarByName(sO_LiftButtons);
|
||||
GameVar *var = g_fullpipe->getGameLoaderGameVar()->getSubVarByName("OBJSTATES")->getSubVarByName(sO_LiftButtons);
|
||||
|
||||
if (var)
|
||||
var->setSubVarAsInt(name, state);
|
||||
@ -731,6 +727,8 @@ int global_messageHandler1(ExCommand *cmd) {
|
||||
}
|
||||
break;
|
||||
case 36: // keydown
|
||||
g_fullpipe->defHandleKeyDown(cmd->_keyCode);
|
||||
|
||||
switch (cmd->_keyCode) {
|
||||
case '\x1B': // ESC
|
||||
if (g_fullpipe->_currentScene) {
|
||||
@ -768,7 +766,6 @@ int global_messageHandler1(ExCommand *cmd) {
|
||||
cmd->_messageKind = 0;
|
||||
break;
|
||||
default:
|
||||
g_fullpipe->defHandleKeyDown(cmd->_keyCode);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -1075,7 +1072,7 @@ int global_messageHandler3(ExCommand *cmd) {
|
||||
return doSomeAnimation2(cmd->_parentId, cmd->_keyCode);
|
||||
case 63:
|
||||
if (cmd->_objtype == kObjTypeObjstateCommand) {
|
||||
CObjstateCommand *c = (CObjstateCommand *)cmd;
|
||||
ObjstateCommand *c = (ObjstateCommand *)cmd;
|
||||
result = 1;
|
||||
g_fullpipe->setObjectState(c->_objCommandName, c->_value);
|
||||
}
|
||||
@ -1312,6 +1309,63 @@ int global_messageHandler4(ExCommand *cmd) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int MovGraph_messageHandler(ExCommand *cmd) {
|
||||
if (cmd->_messageKind != 17)
|
||||
return 0;
|
||||
|
||||
if (cmd->_messageNum != 33)
|
||||
return 0;
|
||||
|
||||
StaticANIObject *ani = g_fullpipe->_currentScene->getStaticANIObject1ById(g_fullpipe->_gameLoader->_field_FA, -1);
|
||||
|
||||
if (!getSc2MctlCompoundBySceneId(g_fullpipe->_currentScene->_sceneId))
|
||||
return 0;
|
||||
|
||||
if (getSc2MctlCompoundBySceneId(g_fullpipe->_currentScene->_sceneId)->_objtype != kObjTypeMovGraph || !ani)
|
||||
return 0;
|
||||
|
||||
MovGraph *gr = (MovGraph *)getSc2MctlCompoundBySceneId(g_fullpipe->_currentScene->_sceneId);
|
||||
|
||||
MovGraphLink *link = 0;
|
||||
double mindistance = 1.0e10;
|
||||
Common::Point point;
|
||||
|
||||
for (ObList::iterator i = gr->_links.begin(); i != gr->_links.end(); ++i) {
|
||||
point.x = ani->_ox;
|
||||
point.y = ani->_oy;
|
||||
|
||||
double dst = gr->calcDistance(&point, (MovGraphLink *)(*i), 0);
|
||||
if (dst >= 0.0 && dst < mindistance) {
|
||||
mindistance = dst;
|
||||
link = (MovGraphLink *)(*i);
|
||||
}
|
||||
}
|
||||
|
||||
int top;
|
||||
|
||||
if (link) {
|
||||
MovGraphNode *node = link->_movGraphNode1;
|
||||
|
||||
double sq = (ani->_oy - node->_y) * (ani->_oy - node->_y) + (ani->_ox - node->_x) * (ani->_ox - node->_x);
|
||||
int off = (node->_field_14 >> 16) & 0xFF;
|
||||
double off2 = ((link->_movGraphNode2->_field_14 >> 8) & 0xff) - off;
|
||||
|
||||
top = off + (int)(sqrt(sq) * off2 / link->_distance);
|
||||
} else {
|
||||
top = (gr->calcOffset(ani->_ox, ani->_oy)->_field_14 >> 8) & 0xff;
|
||||
}
|
||||
|
||||
if (ani->_movement) {
|
||||
ani->_movement->_currDynamicPhase->_rect->top = 255 - top;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ani->_statics)
|
||||
ani->_statics->_rect->top = 255 - top;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int defaultUpdateCursor() {
|
||||
g_fullpipe->updateCursorsCommon();
|
||||
|
||||
@ -1325,7 +1379,7 @@ int sceneIntro_updateCursor() {
|
||||
}
|
||||
|
||||
void FullpipeEngine::setSwallowedEggsState() {
|
||||
CGameVar *v = _gameLoader->_gameVar->getSubVarByName("OBJSTATES")->getSubVarByName(sO_GulpedEggs);
|
||||
GameVar *v = _gameLoader->_gameVar->getSubVarByName("OBJSTATES")->getSubVarByName(sO_GulpedEggs);
|
||||
|
||||
g_vars->swallowedEgg1 = v->getSubVarByName(sO_Egg1);
|
||||
g_vars->swallowedEgg2 = v->getSubVarByName(sO_Egg2);
|
||||
@ -1348,7 +1402,7 @@ void sceneIntro_initScene(Scene *sc) {
|
||||
if (g_fullpipe->_recordEvents || g_fullpipe->_inputArFlag)
|
||||
g_vars->sceneIntro_skipIntro = false;
|
||||
|
||||
g_fullpipe->_modalObject = new CModalIntro;
|
||||
g_fullpipe->_modalObject = new ModalIntro;
|
||||
}
|
||||
|
||||
int sceneHandlerIntro(ExCommand *cmd) {
|
||||
@ -1358,7 +1412,7 @@ int sceneHandlerIntro(ExCommand *cmd) {
|
||||
}
|
||||
|
||||
void scene01_fixEntrance() {
|
||||
CGameVar *var = g_fullpipe->getGameLoaderGameVar()->getSubVarByName("OBJSTATES")->getSubVarByName("SAVEGAME");
|
||||
GameVar *var = g_fullpipe->getGameLoaderGameVar()->getSubVarByName("OBJSTATES")->getSubVarByName("SAVEGAME");
|
||||
if (var->getSubVarAsInt("Entrance") == TrubaLeft)
|
||||
var->setSubVarAsInt("Entrance", TrubaRight);
|
||||
}
|
||||
|
@ -31,9 +31,9 @@ class Vars {
|
||||
public:
|
||||
Vars();
|
||||
|
||||
CGameVar *swallowedEgg1;
|
||||
CGameVar *swallowedEgg2;
|
||||
CGameVar *swallowedEgg3;
|
||||
GameVar *swallowedEgg1;
|
||||
GameVar *swallowedEgg2;
|
||||
GameVar *swallowedEgg3;
|
||||
|
||||
StaticANIObject *sceneIntro_aniin1man;
|
||||
bool sceneIntro_needSleep;
|
||||
|
@ -111,7 +111,7 @@ void Sound::setPanAndVolumeByStaticAni() {
|
||||
debug(3, "STUB Sound::setPanAndVolumeByStaticAni()");
|
||||
}
|
||||
|
||||
void FullpipeEngine::setSceneMusicParameters(CGameVar *var) {
|
||||
void FullpipeEngine::setSceneMusicParameters(GameVar *var) {
|
||||
warning("STUB: FullpipeEngine::setSceneMusicParameters()");
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,6 @@ class Sound : public MemoryObject {
|
||||
int _id;
|
||||
char *_description;
|
||||
int16 _objectId;
|
||||
int16 _field_32;
|
||||
int _directSoundBuffer;
|
||||
int _directSoundBuffers[7];
|
||||
byte *_soundData;
|
||||
|
@ -37,7 +37,7 @@
|
||||
namespace Fullpipe {
|
||||
|
||||
bool FullpipeEngine::loadGam(const char *fname, int scene) {
|
||||
_gameLoader = new CGameLoader();
|
||||
_gameLoader = new GameLoader();
|
||||
|
||||
if (!_gameLoader->loadFile(fname))
|
||||
return false;
|
||||
@ -54,7 +54,7 @@ bool FullpipeEngine::loadGam(const char *fname, int scene) {
|
||||
|
||||
_inventory->rebuildItemRects();
|
||||
|
||||
for (CPtrList::iterator p = _inventory->getScene()->_picObjList.begin(); p != _inventory->getScene()->_picObjList.end(); ++p) {
|
||||
for (PtrList::iterator p = _inventory->getScene()->_picObjList.begin(); p != _inventory->getScene()->_picObjList.end(); ++p) {
|
||||
((MemoryObject *)((PictureObject *)*p)->_picture)->load();
|
||||
}
|
||||
|
||||
@ -145,7 +145,7 @@ GameProject::~GameProject() {
|
||||
free(_headerFilename);
|
||||
}
|
||||
|
||||
CGameVar::CGameVar() {
|
||||
GameVar::GameVar() {
|
||||
_subVars = 0;
|
||||
_parentVarObj = 0;
|
||||
_nextVarObj = 0;
|
||||
@ -156,7 +156,7 @@ CGameVar::CGameVar() {
|
||||
_varName = 0;
|
||||
}
|
||||
|
||||
bool CGameVar::load(MfcArchive &file) {
|
||||
bool GameVar::load(MfcArchive &file) {
|
||||
_varName = file.readPascalString();
|
||||
_varType = file.readUint32LE();
|
||||
|
||||
@ -184,18 +184,18 @@ bool CGameVar::load(MfcArchive &file) {
|
||||
}
|
||||
|
||||
file.incLevel();
|
||||
_parentVarObj = (CGameVar *)file.readClass();
|
||||
_prevVarObj = (CGameVar *)file.readClass();
|
||||
_nextVarObj = (CGameVar *)file.readClass();
|
||||
_field_14 = (CGameVar *)file.readClass();
|
||||
_subVars = (CGameVar *)file.readClass();
|
||||
_parentVarObj = (GameVar *)file.readClass();
|
||||
_prevVarObj = (GameVar *)file.readClass();
|
||||
_nextVarObj = (GameVar *)file.readClass();
|
||||
_field_14 = (GameVar *)file.readClass();
|
||||
_subVars = (GameVar *)file.readClass();
|
||||
file.decLevel();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CGameVar *CGameVar::getSubVarByName(const char *name) {
|
||||
CGameVar *sv = 0;
|
||||
GameVar *GameVar::getSubVarByName(const char *name) {
|
||||
GameVar *sv = 0;
|
||||
|
||||
if (_subVars != 0) {
|
||||
sv = _subVars;
|
||||
@ -205,8 +205,8 @@ CGameVar *CGameVar::getSubVarByName(const char *name) {
|
||||
return sv;
|
||||
}
|
||||
|
||||
bool CGameVar::setSubVarAsInt(const char *name, int value) {
|
||||
CGameVar *var = getSubVarByName(name);
|
||||
bool GameVar::setSubVarAsInt(const char *name, int value) {
|
||||
GameVar *var = getSubVarByName(name);
|
||||
|
||||
if (var) {
|
||||
if (var->_varType == 0) {
|
||||
@ -217,7 +217,7 @@ bool CGameVar::setSubVarAsInt(const char *name, int value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var = new CGameVar();
|
||||
var = new GameVar();
|
||||
var->_varType = 0;
|
||||
var->_value.intValue = value;
|
||||
var->_varName = (char *)calloc(strlen(name) + 1, 1);
|
||||
@ -226,8 +226,8 @@ bool CGameVar::setSubVarAsInt(const char *name, int value) {
|
||||
return addSubVar(var);
|
||||
}
|
||||
|
||||
int CGameVar::getSubVarAsInt(const char *name) {
|
||||
CGameVar *var = getSubVarByName(name);
|
||||
int GameVar::getSubVarAsInt(const char *name) {
|
||||
GameVar *var = getSubVarByName(name);
|
||||
|
||||
if (var)
|
||||
return var->_value.intValue;
|
||||
@ -235,11 +235,11 @@ int CGameVar::getSubVarAsInt(const char *name) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
CGameVar *CGameVar::addSubVarAsInt(const char *name, int value) {
|
||||
GameVar *GameVar::addSubVarAsInt(const char *name, int value) {
|
||||
if (getSubVarByName(name)) {
|
||||
return 0;
|
||||
} else {
|
||||
CGameVar *var = new CGameVar();
|
||||
GameVar *var = new GameVar();
|
||||
|
||||
var->_varType = 0;
|
||||
var->_value.intValue = value;
|
||||
@ -251,11 +251,11 @@ CGameVar *CGameVar::addSubVarAsInt(const char *name, int value) {
|
||||
}
|
||||
}
|
||||
|
||||
bool CGameVar::addSubVar(CGameVar *subvar) {
|
||||
CGameVar *var = _subVars;
|
||||
bool GameVar::addSubVar(GameVar *subvar) {
|
||||
GameVar *var = _subVars;
|
||||
|
||||
if (var) {
|
||||
for (CGameVar *i = var->_nextVarObj; i; i = i->_nextVarObj)
|
||||
for (GameVar *i = var->_nextVarObj; i; i = i->_nextVarObj)
|
||||
var = i;
|
||||
|
||||
var->_nextVarObj = subvar;
|
||||
@ -273,9 +273,9 @@ bool CGameVar::addSubVar(CGameVar *subvar) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int CGameVar::getSubVarsCount() {
|
||||
int GameVar::getSubVarsCount() {
|
||||
int res;
|
||||
CGameVar *sub = _subVars;
|
||||
GameVar *sub = _subVars;
|
||||
|
||||
for (res = 0; sub; res++)
|
||||
sub = sub->_nextVarObj;
|
||||
@ -283,8 +283,8 @@ int CGameVar::getSubVarsCount() {
|
||||
return res;
|
||||
}
|
||||
|
||||
CGameVar *CGameVar::getSubVarByIndex(int idx) {
|
||||
CGameVar *sub = _subVars;
|
||||
GameVar *GameVar::getSubVarByIndex(int idx) {
|
||||
GameVar *sub = _subVars;
|
||||
|
||||
while (idx--) {
|
||||
sub = sub->_nextVarObj;
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
namespace Fullpipe {
|
||||
|
||||
CStepArray::CStepArray() {
|
||||
StepArray::StepArray() {
|
||||
_points = 0;
|
||||
_maxPointIndex = 0;
|
||||
_currPointIndex = 0;
|
||||
@ -41,7 +41,7 @@ CStepArray::CStepArray() {
|
||||
_isEos = 0;
|
||||
}
|
||||
|
||||
CStepArray::~CStepArray() {
|
||||
StepArray::~StepArray() {
|
||||
if (_pointsCount) {
|
||||
for (int i = 0; i < _pointsCount; i++)
|
||||
delete _points[i];
|
||||
@ -52,7 +52,7 @@ CStepArray::~CStepArray() {
|
||||
}
|
||||
}
|
||||
|
||||
void CStepArray::clear() {
|
||||
void StepArray::clear() {
|
||||
_currPointIndex = 0;
|
||||
_maxPointIndex = 0;
|
||||
_isEos = 0;
|
||||
@ -63,7 +63,7 @@ void CStepArray::clear() {
|
||||
}
|
||||
}
|
||||
|
||||
Common::Point *CStepArray::getCurrPoint(Common::Point *point) {
|
||||
Common::Point *StepArray::getCurrPoint(Common::Point *point) {
|
||||
if (_isEos || _points == 0) {
|
||||
point->x = 0;
|
||||
point->y = 0;
|
||||
@ -73,7 +73,7 @@ Common::Point *CStepArray::getCurrPoint(Common::Point *point) {
|
||||
return point;
|
||||
}
|
||||
|
||||
bool CStepArray::gotoNextPoint() {
|
||||
bool StepArray::gotoNextPoint() {
|
||||
if (_currPointIndex < _maxPointIndex) {
|
||||
_currPointIndex++;
|
||||
return true;
|
||||
@ -547,7 +547,7 @@ void StaticANIObject::draw2() {
|
||||
}
|
||||
|
||||
MovTable *StaticANIObject::countMovements() {
|
||||
CGameVar *preloadSubVar = g_fullpipe->getGameLoaderGameVar()->getSubVarByName(getName())->getSubVarByName("PRELOAD");
|
||||
GameVar *preloadSubVar = g_fullpipe->getGameLoaderGameVar()->getSubVarByName(getName())->getSubVarByName("PRELOAD");
|
||||
|
||||
if (!preloadSubVar || preloadSubVar->getSubVarsCount() == 0)
|
||||
return 0;
|
||||
@ -561,7 +561,7 @@ MovTable *StaticANIObject::countMovements() {
|
||||
GameObject *obj = (GameObject *)_movements[i];
|
||||
movTable->movs[i] = 2;
|
||||
|
||||
for (CGameVar *sub = preloadSubVar->_subVars; sub; sub = sub->_nextVarObj) {
|
||||
for (GameVar *sub = preloadSubVar->_subVars; sub; sub = sub->_nextVarObj) {
|
||||
if (scumm_stricmp(obj->getName(), sub->_varName) == 0) {
|
||||
movTable->movs[i] = 1;
|
||||
break;
|
||||
@ -573,7 +573,7 @@ MovTable *StaticANIObject::countMovements() {
|
||||
}
|
||||
|
||||
void StaticANIObject::setSpeed(int speed) {
|
||||
CGameVar *var = g_fullpipe->getGameLoaderGameVar()->getSubVarByName(getName())->getSubVarByName("SpeedUp");
|
||||
GameVar *var = g_fullpipe->getGameLoaderGameVar()->getSubVarByName(getName())->getSubVarByName("SpeedUp");
|
||||
|
||||
if (!var)
|
||||
return;
|
||||
@ -1131,6 +1131,9 @@ Movement::Movement(Movement *src, StaticANIObject *ani) {
|
||||
_currDynamicPhaseIndex = src->_currDynamicPhaseIndex;
|
||||
_field_94 = 0;
|
||||
|
||||
_field_24 = 0;
|
||||
_field_28 = 0;
|
||||
|
||||
_currMovement = src;
|
||||
_ox = src->_ox;
|
||||
_oy = src->_oy;
|
||||
@ -1242,6 +1245,41 @@ Common::Point *Movement::getCurrDynamicPhaseXY(Common::Point &p) {
|
||||
return &p;
|
||||
}
|
||||
|
||||
Common::Point *Movement::calcSomeXY(Common::Point &p, int idx) {
|
||||
int oldox = _ox;
|
||||
int oldoy = _oy;
|
||||
int oldidx = _currDynamicPhaseIndex;
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
||||
if (!idx) {
|
||||
Common::Point point;
|
||||
|
||||
_staticsObj1->getSomeXY(point);
|
||||
int y1 = _my - point.y;
|
||||
int x1 = _mx - point.x;
|
||||
|
||||
setDynamicPhaseIndex(0);
|
||||
|
||||
x = _currDynamicPhase->_someX + x1;
|
||||
y = _currDynamicPhase->_someY + y1;
|
||||
}
|
||||
|
||||
setOXY(x, y);
|
||||
|
||||
while (_currDynamicPhaseIndex != idx)
|
||||
gotoNextFrame(0, 0);
|
||||
|
||||
p.x = _ox;
|
||||
p.y = _oy;
|
||||
|
||||
setDynamicPhaseIndex(oldidx);
|
||||
setOXY(oldox, oldoy);
|
||||
|
||||
return &p;
|
||||
}
|
||||
|
||||
void Movement::setAlpha(int alpha) {
|
||||
if (_currMovement)
|
||||
for (uint i = 0; i < _currMovement->_dynamicPhases.size(); i++) {
|
||||
@ -1553,7 +1591,7 @@ bool Movement::gotoPrevFrame() {
|
||||
|
||||
_currDynamicPhaseIndex--;
|
||||
if (_currDynamicPhaseIndex < 0)
|
||||
_currDynamicPhaseIndex = _currMovement->_dynamicPhases.size() - 1;
|
||||
_currDynamicPhaseIndex = _dynamicPhases.size() - 1;
|
||||
}
|
||||
|
||||
updateCurrDynamicPhase();
|
||||
|
@ -29,7 +29,7 @@ namespace Fullpipe {
|
||||
|
||||
class ExCommand;
|
||||
|
||||
class CStepArray : public CObject {
|
||||
class StepArray : public CObject {
|
||||
int _currPointIndex;
|
||||
Common::Point **_points;
|
||||
int _maxPointIndex;
|
||||
@ -37,8 +37,8 @@ class CStepArray : public CObject {
|
||||
int _isEos;
|
||||
|
||||
public:
|
||||
CStepArray();
|
||||
~CStepArray();
|
||||
StepArray();
|
||||
~StepArray();
|
||||
void clear();
|
||||
|
||||
int getCurrPointIndex() { return _currPointIndex; }
|
||||
@ -118,7 +118,7 @@ class Movement : public GameObject {
|
||||
int _field_50;
|
||||
int _counterMax;
|
||||
int _counter;
|
||||
CPtrList _dynamicPhases;
|
||||
PtrList _dynamicPhases;
|
||||
int _field_78;
|
||||
Common::Point **_framePosOffsets;
|
||||
Movement *_currMovement;
|
||||
@ -140,6 +140,8 @@ class Movement : public GameObject {
|
||||
Common::Point *getCenter(Common::Point *p);
|
||||
Common::Point *getDimensionsOfPhase(Common::Point *p, int phaseIndex);
|
||||
|
||||
Common::Point *calcSomeXY(Common::Point &p, int idx);
|
||||
|
||||
void initStatics(StaticANIObject *ani);
|
||||
void updateCurrDynamicPhase();
|
||||
|
||||
@ -172,9 +174,9 @@ class StaticANIObject : public GameObject {
|
||||
int _initialCounter;
|
||||
int _callback1;
|
||||
void (*_callback2)(int *);
|
||||
CPtrList _movements;
|
||||
CPtrList _staticsList;
|
||||
CStepArray _stepArray;
|
||||
PtrList _movements;
|
||||
PtrList _staticsList;
|
||||
StepArray _stepArray;
|
||||
int16 _field_96;
|
||||
int _messageQueueId;
|
||||
int _messageNum;
|
||||
|
@ -44,14 +44,14 @@ bool CObject::loadFile(const char *fname) {
|
||||
return load(archive);
|
||||
}
|
||||
|
||||
bool CObList::load(MfcArchive &file) {
|
||||
debug(5, "CObList::load()");
|
||||
bool ObList::load(MfcArchive &file) {
|
||||
debug(5, "ObList::load()");
|
||||
int count = file.readCount();
|
||||
|
||||
debug(9, "CObList::count: %d:", count);
|
||||
debug(9, "ObList::count: %d:", count);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
debug(9, "CObList::[%d]", i);
|
||||
debug(9, "ObList::[%d]", i);
|
||||
CObject *t = file.readClass();
|
||||
|
||||
push_back(t);
|
||||
@ -60,8 +60,8 @@ bool CObList::load(MfcArchive &file) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CObArray::load(MfcArchive &file) {
|
||||
debug(5, "CObArray::load()");
|
||||
bool ObArray::load(MfcArchive &file) {
|
||||
debug(5, "ObArray::load()");
|
||||
int count = file.readCount();
|
||||
|
||||
resize(count);
|
||||
@ -75,11 +75,11 @@ bool CObArray::load(MfcArchive &file) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDWordArray::load(MfcArchive &file) {
|
||||
debug(5, "CWordArray::load()");
|
||||
bool DWordArray::load(MfcArchive &file) {
|
||||
debug(5, "DWordArray::load()");
|
||||
int count = file.readCount();
|
||||
|
||||
debug(9, "CDWordArray::count: %d", count);
|
||||
debug(9, "DWordArray::count: %d", count);
|
||||
|
||||
resize(count);
|
||||
|
||||
@ -262,34 +262,34 @@ double MfcArchive::readDouble() {
|
||||
|
||||
enum {
|
||||
kNullObject,
|
||||
kCInteraction,
|
||||
kInteraction,
|
||||
kMessageQueue,
|
||||
kExCommand,
|
||||
kCObjstateCommand,
|
||||
kCGameVar,
|
||||
kCMctlCompound,
|
||||
kCMovGraph,
|
||||
kCMovGraphLink,
|
||||
kCMovGraphNode,
|
||||
kCReactParallel,
|
||||
kCReactPolygonal
|
||||
kObjstateCommand,
|
||||
kGameVar,
|
||||
kMctlCompound,
|
||||
kMovGraph,
|
||||
kMovGraphLink,
|
||||
kMovGraphNode,
|
||||
kReactParallel,
|
||||
kReactPolygonal
|
||||
};
|
||||
|
||||
const struct {
|
||||
const char *name;
|
||||
int id;
|
||||
} classMap[] = {
|
||||
{ "CInteraction", kCInteraction },
|
||||
{ "CInteraction", kInteraction },
|
||||
{ "MessageQueue", kMessageQueue },
|
||||
{ "ExCommand", kExCommand },
|
||||
{ "CObjstateCommand", kCObjstateCommand },
|
||||
{ "CGameVar", kCGameVar },
|
||||
{ "CMctlCompound", kCMctlCompound },
|
||||
{ "CMovGraph", kCMovGraph },
|
||||
{ "CMovGraphLink", kCMovGraphLink },
|
||||
{ "CMovGraphNode", kCMovGraphNode },
|
||||
{ "CReactParallel", kCReactParallel },
|
||||
{ "CReactPolygonal", kCReactPolygonal },
|
||||
{ "CObjstateCommand", kObjstateCommand },
|
||||
{ "CGameVar", kGameVar },
|
||||
{ "CMctlCompound", kMctlCompound },
|
||||
{ "CMovGraph", kMovGraph },
|
||||
{ "CMovGraphLink", kMovGraphLink },
|
||||
{ "CMovGraphNode", kMovGraphNode },
|
||||
{ "CReactParallel", kReactParallel },
|
||||
{ "CReactPolygonal", kReactPolygonal },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@ -306,28 +306,28 @@ static CObject *createObject(int objectId) {
|
||||
switch (objectId) {
|
||||
case kNullObject:
|
||||
return 0;
|
||||
case kCInteraction:
|
||||
return new CInteraction();
|
||||
case kInteraction:
|
||||
return new Interaction();
|
||||
case kMessageQueue:
|
||||
return new MessageQueue();
|
||||
case kExCommand:
|
||||
return new ExCommand();
|
||||
case kCObjstateCommand:
|
||||
return new CObjstateCommand();
|
||||
case kCGameVar:
|
||||
return new CGameVar();
|
||||
case kCMctlCompound:
|
||||
return new CMctlCompound();
|
||||
case kCMovGraph:
|
||||
return new CMovGraph();
|
||||
case kCMovGraphLink:
|
||||
return new CMovGraphLink();
|
||||
case kCMovGraphNode:
|
||||
return new CMovGraphNode();
|
||||
case kCReactParallel:
|
||||
return new CReactParallel();
|
||||
case kCReactPolygonal:
|
||||
return new CReactPolygonal();
|
||||
case kObjstateCommand:
|
||||
return new ObjstateCommand();
|
||||
case kGameVar:
|
||||
return new GameVar();
|
||||
case kMctlCompound:
|
||||
return new MctlCompound();
|
||||
case kMovGraph:
|
||||
return new MovGraph();
|
||||
case kMovGraphLink:
|
||||
return new MovGraphLink();
|
||||
case kMovGraphNode:
|
||||
return new MovGraphNode();
|
||||
case kReactParallel:
|
||||
return new ReactParallel();
|
||||
case kReactPolygonal:
|
||||
return new ReactPolygonal();
|
||||
default:
|
||||
error("Unknown objectId: %d", objectId);
|
||||
}
|
||||
@ -396,6 +396,8 @@ CObject *MfcArchive::parseClass(bool *isCopyReturned) {
|
||||
if (_objectMap.size() < obTag) {
|
||||
error("Object index too big: %d at 0x%08x", obTag, pos() - 2);
|
||||
}
|
||||
debug(7, "parseClass::obTag <%s>", lookupObjectId(_objectIdMap[obTag]));
|
||||
|
||||
res = _objectMap[obTag];
|
||||
|
||||
*isCopyReturned = true;
|
||||
|
@ -68,7 +68,9 @@ enum ObjType {
|
||||
kObjTypeDefault,
|
||||
kObjTypeObjstateCommand,
|
||||
kObjTypeStaticANIObject,
|
||||
kObjTypePictureObject
|
||||
kObjTypePictureObject,
|
||||
kObjTypeMovGraph,
|
||||
kObjTypeMctlCompound
|
||||
};
|
||||
|
||||
class CObject {
|
||||
@ -82,7 +84,7 @@ class CObject {
|
||||
bool loadFile(const char *fname);
|
||||
};
|
||||
|
||||
class CObList : public Common::List<CObject *>, public CObject {
|
||||
class ObList : public Common::List<CObject *>, public CObject {
|
||||
public:
|
||||
virtual bool load(MfcArchive &file);
|
||||
};
|
||||
@ -97,9 +99,6 @@ class MemoryObject : CObject {
|
||||
int _mfield_C;
|
||||
int _mfield_10;
|
||||
char _mfield_14;
|
||||
char _mfield_15;
|
||||
char _mfield_16;
|
||||
char _mfield_17;
|
||||
byte *_data;
|
||||
int _dataSize;
|
||||
int _mflags;
|
||||
@ -134,17 +133,17 @@ class MemoryObject2 : public MemoryObject {
|
||||
void copyData(byte *src, int dataSize);
|
||||
};
|
||||
|
||||
class CObArray : public Common::Array<CObject>, public CObject {
|
||||
class ObArray : public Common::Array<CObject>, public CObject {
|
||||
public:
|
||||
virtual bool load(MfcArchive &file);
|
||||
};
|
||||
|
||||
class CDWordArray : public Common::Array<int32>, public CObject {
|
||||
class DWordArray : public Common::Array<int32>, public CObject {
|
||||
public:
|
||||
virtual bool load(MfcArchive &file);
|
||||
};
|
||||
|
||||
typedef Common::Array<void *> CPtrList;
|
||||
typedef Common::Array<void *> PtrList;
|
||||
|
||||
char *genFileName(int superId, int sceneId, const char *ext);
|
||||
byte *transCyrillic(byte *s);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "groovie/groovie.h"
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/substream.h"
|
||||
#include "common/textconsole.h"
|
||||
|
||||
#include "graphics/palette.h"
|
||||
@ -435,19 +436,20 @@ bool ROQPlayer::processBlockStill(ROQBlockHeader &blockHeader) {
|
||||
warning("Groovie::ROQ: JPEG frame (unfinished)");
|
||||
|
||||
Graphics::JPEGDecoder *jpg = new Graphics::JPEGDecoder();
|
||||
jpg->loadStream(*_file);
|
||||
const byte *y = (const byte *)jpg->getComponent(1)->getPixels();
|
||||
const byte *u = (const byte *)jpg->getComponent(2)->getPixels();
|
||||
const byte *v = (const byte *)jpg->getComponent(3)->getPixels();
|
||||
jpg->setOutputColorSpace(Graphics::JPEGDecoder::kColorSpaceYUV);
|
||||
|
||||
uint32 startPos = _file->pos();
|
||||
Common::SeekableSubReadStream subStream(_file, startPos, startPos + blockHeader.size, DisposeAfterUse::NO);
|
||||
jpg->loadStream(subStream);
|
||||
|
||||
const Graphics::Surface *srcSurf = jpg->getSurface();
|
||||
const byte *src = (const byte *)srcSurf->getPixels();
|
||||
byte *ptr = (byte *)_currBuf->getPixels();
|
||||
for (int i = 0; i < _currBuf->w * _currBuf->h; i++) {
|
||||
*ptr++ = *y++;
|
||||
*ptr++ = *u++;
|
||||
*ptr++ = *v++;
|
||||
}
|
||||
memcpy(ptr, src, _currBuf->w * _currBuf->h * srcSurf->format.bytesPerPixel);
|
||||
|
||||
delete jpg;
|
||||
|
||||
_file->seek(startPos + blockHeader.size);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -131,7 +131,8 @@ void BlbArchive::load(BlbArchiveEntry *entry, byte *buffer, uint32 size) {
|
||||
break;
|
||||
case 3: // DCL-compressed
|
||||
if (!Common::decompressDCL(&_fd, buffer, entry->diskSize, entry->size))
|
||||
error("BlbArchive::load() Error during decompression of %08X", entry->fileHash);
|
||||
error("BlbArchive::load() Error during decompression of %08X (offset: %d, disk size: %d, size: %d)",
|
||||
entry->fileHash, entry->offset, entry->diskSize, entry->size);
|
||||
break;
|
||||
default:
|
||||
error("BlbArchive::load() Unknown compression type %d", entry->comprType);
|
||||
|
@ -252,7 +252,7 @@ bool Console::Cmd_DumpResource(int argc, const char **argv) {
|
||||
if (!handle.isValid()) {
|
||||
DebugPrintf("Invalid resource hash\n");
|
||||
} else {
|
||||
_vm->_res->loadResource(handle);
|
||||
_vm->_res->loadResource(handle, _vm->applyResourceFixes());
|
||||
Common::DumpFile outFile;
|
||||
outFile.open(outFileName);
|
||||
outFile.write(handle.data(), handle.size());
|
||||
|
@ -52,6 +52,10 @@ Common::Platform NeverhoodEngine::getPlatform() const {
|
||||
return _gameDescription->desc.platform;
|
||||
}
|
||||
|
||||
Common::Language NeverhoodEngine::getLanguage() const {
|
||||
return _gameDescription->desc.language;
|
||||
}
|
||||
|
||||
uint16 NeverhoodEngine::getVersion() const {
|
||||
return _gameDescription->version;
|
||||
}
|
||||
@ -60,6 +64,10 @@ bool NeverhoodEngine::isDemo() const {
|
||||
return _gameDescription->desc.flags & ADGF_DEMO;
|
||||
}
|
||||
|
||||
bool NeverhoodEngine::applyResourceFixes() const {
|
||||
return getLanguage() == Common::RU_RUS;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static const PlainGameDescriptor neverhoodGames[] = {
|
||||
|
@ -411,7 +411,9 @@ void GameModule::checkRequests() {
|
||||
}
|
||||
if (_restoreGameRequested) {
|
||||
_restoreGameRequested = false;
|
||||
_vm->_audioResourceMan->stopAllMusic();
|
||||
_vm->_audioResourceMan->stopAllSounds();
|
||||
_vm->_soundMan->stopAllMusic();
|
||||
_vm->_soundMan->stopAllSounds();
|
||||
delete _childObject;
|
||||
delete _prevChildObject;
|
||||
|
@ -160,7 +160,8 @@ void MenuModule::updateScene() {
|
||||
createScene(MAKING_OF, -1);
|
||||
break;
|
||||
case kMainMenuToggleMusic:
|
||||
// TODO Toggle music 0048A367
|
||||
_vm->toggleMusic(!_vm->musicIsEnabled());
|
||||
_vm->_mixer->muteSoundType(Audio::Mixer::kMusicSoundType, !_vm->musicIsEnabled());
|
||||
createScene(MAIN_MENU, -1);
|
||||
break;
|
||||
case kMainMenuDeleteGame:
|
||||
@ -353,11 +354,11 @@ MainMenu::MainMenu(NeverhoodEngine *vm, Module *parentModule)
|
||||
setPalette(0x08C0020C);
|
||||
insertScreenMouse(0x00208084);
|
||||
|
||||
insertStaticSprite(0x41137051, 100);
|
||||
insertStaticSprite(0xC10B2015, 100);
|
||||
insertStaticSprite(0x41137051, 100); // "Options" header text
|
||||
insertStaticSprite(0xC10B2015, 100); // Button texts
|
||||
|
||||
// TODO Only if music is enabled
|
||||
_musicOnButton = insertStaticSprite(0x0C24C0EE, 100);
|
||||
if (!_vm->musicIsEnabled())
|
||||
insertStaticSprite(0x0C24C0EE, 100); // "Music is off" button
|
||||
|
||||
for (uint buttonIndex = 0; buttonIndex < 9; ++buttonIndex) {
|
||||
Sprite *menuButton = insertSprite<MenuButton>(this, buttonIndex,
|
||||
@ -573,6 +574,7 @@ TextEditWidget::TextEditWidget(NeverhoodEngine *vm, int16 x, int16 y, GameStateM
|
||||
|
||||
_maxVisibleChars = (_rect.x2 - _rect.x1) / _fontSurface->getCharWidth();
|
||||
_cursorPos = 0;
|
||||
_textLabelWidget = NULL;
|
||||
|
||||
SetUpdateHandler(&TextEditWidget::update);
|
||||
SetMessageHandler(&TextEditWidget::handleMessage);
|
||||
|
@ -79,7 +79,6 @@ class MainMenu : public Scene {
|
||||
public:
|
||||
MainMenu(NeverhoodEngine *vm, Module *parentModule);
|
||||
protected:
|
||||
Sprite *_musicOnButton;
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
|
@ -33,6 +33,7 @@ MODULE_OBJS = \
|
||||
modules/module2600.o \
|
||||
modules/module2700.o \
|
||||
modules/module2800.o \
|
||||
modules/module2800_sprites.o \
|
||||
modules/module2900.o \
|
||||
modules/module3000.o \
|
||||
mouse.o \
|
||||
|
@ -1012,7 +1012,7 @@ void AsScene1002VenusFlyTrap::swallowKlaymen() {
|
||||
}
|
||||
|
||||
AsScene1002OutsideDoorBackground::AsScene1002OutsideDoorBackground(NeverhoodEngine *vm)
|
||||
: AnimatedSprite(vm, 1200), _countdown(0) {
|
||||
: AnimatedSprite(vm, 1200), _countdown(0), _isDoorClosed(true) {
|
||||
|
||||
createSurface(850, 186, 212);
|
||||
_x = 320;
|
||||
|
@ -155,8 +155,6 @@ protected:
|
||||
class SsScene1201Tnt : public StaticSprite {
|
||||
public:
|
||||
SsScene1201Tnt(NeverhoodEngine *vm, uint32 elemIndex, uint32 pointIndex, int16 clipY2);
|
||||
protected:
|
||||
uint32 _elemIndex;
|
||||
};
|
||||
|
||||
class Scene1201 : public Scene {
|
||||
|
@ -630,7 +630,7 @@ void AsScene1303Balloon::stPopBalloon() {
|
||||
}
|
||||
|
||||
Scene1303::Scene1303(NeverhoodEngine *vm, Module *parentModule)
|
||||
: Scene(vm, parentModule) {
|
||||
: Scene(vm, parentModule), _asBalloon(NULL) {
|
||||
|
||||
SetMessageHandler(&Scene1303::handleMessage);
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "neverhood/modules/module2100.h"
|
||||
#include "neverhood/modules/module2200.h"
|
||||
#include "neverhood/modules/module2800.h"
|
||||
#include "neverhood/modules/module2800_sprites.h"
|
||||
#include "neverhood/diskplayerscene.h"
|
||||
|
||||
namespace Neverhood {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -70,38 +70,7 @@ protected:
|
||||
void changeTuneStatus(int prevTuneStatus, int newTuneStatus);
|
||||
};
|
||||
|
||||
class AsScene2803LightCord : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2803LightCord(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int16 x, int16 y);
|
||||
void stPulled();
|
||||
void stIdle();
|
||||
void setFileHashes(uint32 fileHash1, uint32 fileHash2);
|
||||
protected:
|
||||
Scene *_parentScene;
|
||||
uint32 _fileHash1, _fileHash2;
|
||||
bool _isPulled, _isBusy;
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
uint32 hmPulled(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2803TestTubeOne : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2803TestTubeOne(NeverhoodEngine *vm, uint32 fileHash1, uint32 fileHash2);
|
||||
protected:
|
||||
uint32 _fileHash1, _fileHash2;
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2803Rope : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2803Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x);
|
||||
protected:
|
||||
Scene *_parentScene;
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
uint32 hmReleased(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
void stReleased();
|
||||
void stHide();
|
||||
};
|
||||
class AsScene2803LightCord;
|
||||
|
||||
class Scene2803 : public Scene {
|
||||
public:
|
||||
@ -158,101 +127,8 @@ protected:
|
||||
void updatePaletteArea(bool instantly);
|
||||
};
|
||||
|
||||
class Scene2804;
|
||||
|
||||
class SsScene2804RedButton : public StaticSprite {
|
||||
public:
|
||||
SsScene2804RedButton(NeverhoodEngine *vm, Scene2804 *parentScene);
|
||||
protected:
|
||||
Scene2804 *_parentScene;
|
||||
int _countdown;
|
||||
void update();
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class SsScene2804LightCoil : public StaticSprite {
|
||||
public:
|
||||
SsScene2804LightCoil(NeverhoodEngine *vm);
|
||||
protected:
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class SsScene2804BeamCoilBody : public StaticSprite {
|
||||
public:
|
||||
SsScene2804BeamCoilBody(NeverhoodEngine *vm);
|
||||
};
|
||||
|
||||
class SsScene2804LightTarget : public StaticSprite {
|
||||
public:
|
||||
SsScene2804LightTarget(NeverhoodEngine *vm);
|
||||
protected:
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class SsScene2804Flash : public StaticSprite {
|
||||
public:
|
||||
SsScene2804Flash(NeverhoodEngine *vm);
|
||||
void show();
|
||||
};
|
||||
|
||||
class AsScene2804CrystalWaves : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2804CrystalWaves(NeverhoodEngine *vm, uint crystalIndex);
|
||||
void show();
|
||||
void hide();
|
||||
protected:
|
||||
uint _crystalIndex;
|
||||
};
|
||||
|
||||
class AsScene2804Crystal : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2804Crystal(NeverhoodEngine *vm, AsScene2804CrystalWaves *asCrystalWaves, uint crystalIndex);
|
||||
void show();
|
||||
void hide();
|
||||
void activate();
|
||||
int16 getColorNum() const { return _colorNum; }
|
||||
protected:
|
||||
AsScene2804CrystalWaves *_asCrystalWaves;
|
||||
uint _crystalIndex;
|
||||
int16 _colorNum;
|
||||
bool _isLightOn;
|
||||
bool _isShowing;
|
||||
};
|
||||
|
||||
class SsScene2804CrystalButton : public StaticSprite {
|
||||
public:
|
||||
SsScene2804CrystalButton(NeverhoodEngine *vm, Scene2804 *parentScene, AsScene2804Crystal *asCrystal, uint crystalIndex);
|
||||
protected:
|
||||
Scene2804 *_parentScene;
|
||||
AsScene2804Crystal *_asCrystal;
|
||||
uint _crystalIndex;
|
||||
int _countdown;
|
||||
void update();
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2804BeamCoil : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2804BeamCoil(NeverhoodEngine *vm, Scene *parentScene, SsScene2804BeamCoilBody *ssBeamCoilBody);
|
||||
virtual ~AsScene2804BeamCoil();
|
||||
protected:
|
||||
Scene *_parentScene;
|
||||
SsScene2804BeamCoilBody *_ssBeamCoilBody;
|
||||
int _countdown;
|
||||
void update();
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
void show();
|
||||
void hide();
|
||||
void stBeaming();
|
||||
uint32 hmBeaming(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2804BeamTarget : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2804BeamTarget(NeverhoodEngine *vm);
|
||||
protected:
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
class SsScene2804Flash;
|
||||
class AsScene2804Crystal;
|
||||
|
||||
class Scene2804 : public Scene {
|
||||
public:
|
||||
@ -284,13 +160,6 @@ protected:
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2806Spew : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2806Spew(NeverhoodEngine *vm);
|
||||
protected:
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class Scene2806 : public Scene {
|
||||
public:
|
||||
Scene2806(NeverhoodEngine *vm, Module *parentModule, int which);
|
||||
@ -315,63 +184,8 @@ protected:
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class SsScene2808Dispenser : public StaticSprite {
|
||||
public:
|
||||
SsScene2808Dispenser(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum, int testTubeIndex);
|
||||
void startCountdown(int index);
|
||||
protected:
|
||||
Scene *_parentScene;
|
||||
int _countdown;
|
||||
int _testTubeSetNum, _testTubeIndex;
|
||||
void update();
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2808TestTube : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2808TestTube(NeverhoodEngine *vm, int testTubeSetNum, int testTubeIndex, SsScene2808Dispenser *ssDispenser);
|
||||
void fill();
|
||||
void flush();
|
||||
uint32 getFillLevel() const { return _fillLevel; }
|
||||
protected:
|
||||
SsScene2808Dispenser *_ssDispenser;
|
||||
int _testTubeSetNum;
|
||||
uint32 _fillLevel;
|
||||
int _testTubeIndex;
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2808Handle : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2808Handle(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum);
|
||||
void activate();
|
||||
void stActivated();
|
||||
protected:
|
||||
Scene *_parentScene;
|
||||
int _testTubeSetNum;
|
||||
bool _isActivated;
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
uint32 hmActivating(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2808Flow : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2808Flow(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum);
|
||||
void start();
|
||||
void stKeepFlowing();
|
||||
protected:
|
||||
Scene *_parentScene;
|
||||
int _testTubeSetNum;
|
||||
uint32 hmFlowing(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2808LightEffect : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2808LightEffect(NeverhoodEngine *vm, int which);
|
||||
protected:
|
||||
int _countdown;
|
||||
void update();
|
||||
};
|
||||
class AsScene2808Flow;
|
||||
class AsScene2808TestTube;
|
||||
|
||||
class Scene2808 : public Scene {
|
||||
public:
|
||||
@ -389,13 +203,6 @@ protected:
|
||||
bool isAnyTestTubeFilled();
|
||||
};
|
||||
|
||||
class AsScene2809Spew : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2809Spew(NeverhoodEngine *vm);
|
||||
protected:
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class Scene2809 : public Scene {
|
||||
public:
|
||||
Scene2809(NeverhoodEngine *vm, Module *parentModule, int which);
|
||||
@ -413,14 +220,6 @@ protected:
|
||||
void findClosestPoint();
|
||||
};
|
||||
|
||||
class AsScene2810Rope : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2810Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x);
|
||||
protected:
|
||||
Scene *_parentScene;
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class Scene2810 : public Scene {
|
||||
public:
|
||||
Scene2810(NeverhoodEngine *vm, Module *parentModule, int which);
|
||||
@ -440,31 +239,6 @@ protected:
|
||||
void insertKlaymenLadder();
|
||||
};
|
||||
|
||||
class AsScene2812Winch : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2812Winch(NeverhoodEngine *vm);
|
||||
virtual ~AsScene2812Winch();
|
||||
protected:
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2812Rope : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2812Rope(NeverhoodEngine *vm, Scene *parentScene);
|
||||
protected:
|
||||
Scene *_parentScene;
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
uint32 hmRopingDown(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
void stRopingDown();
|
||||
};
|
||||
|
||||
class AsScene2812TrapDoor : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2812TrapDoor(NeverhoodEngine *vm);
|
||||
protected:
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class Scene2812 : public Scene {
|
||||
public:
|
||||
Scene2812(NeverhoodEngine *vm, Module *parentModule, int which);
|
||||
|
1020
engines/neverhood/modules/module2800_sprites.cpp
Normal file
1020
engines/neverhood/modules/module2800_sprites.cpp
Normal file
File diff suppressed because it is too large
Load Diff
268
engines/neverhood/modules/module2800_sprites.h
Normal file
268
engines/neverhood/modules/module2800_sprites.h
Normal file
@ -0,0 +1,268 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NEVERHOOD_MODULES_MODULE2800_SPRITES_H
|
||||
#define NEVERHOOD_MODULES_MODULE2800_SPRITES_H
|
||||
|
||||
#include "neverhood/neverhood.h"
|
||||
#include "neverhood/module.h"
|
||||
#include "neverhood/scene.h"
|
||||
|
||||
namespace Neverhood {
|
||||
|
||||
class AsScene2803LightCord : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2803LightCord(NeverhoodEngine *vm, Scene *parentScene, uint32 fileHash1, uint32 fileHash2, int16 x, int16 y);
|
||||
void stPulled();
|
||||
void stIdle();
|
||||
void setFileHashes(uint32 fileHash1, uint32 fileHash2);
|
||||
protected:
|
||||
Scene *_parentScene;
|
||||
uint32 _fileHash1, _fileHash2;
|
||||
bool _isPulled, _isBusy;
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
uint32 hmPulled(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2803TestTubeOne : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2803TestTubeOne(NeverhoodEngine *vm, uint32 fileHash1, uint32 fileHash2);
|
||||
protected:
|
||||
uint32 _fileHash1, _fileHash2;
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2803Rope : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2803Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x);
|
||||
protected:
|
||||
Scene *_parentScene;
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
uint32 hmReleased(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
void stReleased();
|
||||
void stHide();
|
||||
};
|
||||
|
||||
class Scene2804;
|
||||
|
||||
class SsScene2804RedButton : public StaticSprite {
|
||||
public:
|
||||
SsScene2804RedButton(NeverhoodEngine *vm, Scene2804 *parentScene);
|
||||
protected:
|
||||
Scene2804 *_parentScene;
|
||||
int _countdown;
|
||||
void update();
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class SsScene2804LightCoil : public StaticSprite {
|
||||
public:
|
||||
SsScene2804LightCoil(NeverhoodEngine *vm);
|
||||
protected:
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class SsScene2804BeamCoilBody : public StaticSprite {
|
||||
public:
|
||||
SsScene2804BeamCoilBody(NeverhoodEngine *vm);
|
||||
};
|
||||
|
||||
class SsScene2804LightTarget : public StaticSprite {
|
||||
public:
|
||||
SsScene2804LightTarget(NeverhoodEngine *vm);
|
||||
protected:
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class SsScene2804Flash : public StaticSprite {
|
||||
public:
|
||||
SsScene2804Flash(NeverhoodEngine *vm);
|
||||
void show();
|
||||
};
|
||||
|
||||
class AsScene2804CrystalWaves : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2804CrystalWaves(NeverhoodEngine *vm, uint crystalIndex);
|
||||
void show();
|
||||
void hide();
|
||||
protected:
|
||||
uint _crystalIndex;
|
||||
};
|
||||
|
||||
class AsScene2804Crystal : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2804Crystal(NeverhoodEngine *vm, AsScene2804CrystalWaves *asCrystalWaves, uint crystalIndex);
|
||||
void show();
|
||||
void hide();
|
||||
void activate();
|
||||
int16 getColorNum() const { return _colorNum; }
|
||||
protected:
|
||||
AsScene2804CrystalWaves *_asCrystalWaves;
|
||||
uint _crystalIndex;
|
||||
int16 _colorNum;
|
||||
bool _isLightOn;
|
||||
bool _isShowing;
|
||||
};
|
||||
|
||||
class SsScene2804CrystalButton : public StaticSprite {
|
||||
public:
|
||||
SsScene2804CrystalButton(NeverhoodEngine *vm, Scene2804 *parentScene, AsScene2804Crystal *asCrystal, uint crystalIndex);
|
||||
protected:
|
||||
Scene2804 *_parentScene;
|
||||
AsScene2804Crystal *_asCrystal;
|
||||
uint _crystalIndex;
|
||||
int _countdown;
|
||||
void update();
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2804BeamCoil : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2804BeamCoil(NeverhoodEngine *vm, Scene *parentScene, SsScene2804BeamCoilBody *ssBeamCoilBody);
|
||||
virtual ~AsScene2804BeamCoil();
|
||||
protected:
|
||||
Scene *_parentScene;
|
||||
SsScene2804BeamCoilBody *_ssBeamCoilBody;
|
||||
int _countdown;
|
||||
void update();
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
void show();
|
||||
void hide();
|
||||
void stBeaming();
|
||||
uint32 hmBeaming(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2804BeamTarget : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2804BeamTarget(NeverhoodEngine *vm);
|
||||
protected:
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2806Spew : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2806Spew(NeverhoodEngine *vm);
|
||||
protected:
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class SsScene2808Dispenser : public StaticSprite {
|
||||
public:
|
||||
SsScene2808Dispenser(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum, int testTubeIndex);
|
||||
void startCountdown(int index);
|
||||
protected:
|
||||
Scene *_parentScene;
|
||||
int _countdown;
|
||||
int _testTubeSetNum, _testTubeIndex;
|
||||
void update();
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2808TestTube : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2808TestTube(NeverhoodEngine *vm, int testTubeSetNum, int testTubeIndex, SsScene2808Dispenser *ssDispenser);
|
||||
void fill();
|
||||
void flush();
|
||||
uint32 getFillLevel() const { return _fillLevel; }
|
||||
protected:
|
||||
SsScene2808Dispenser *_ssDispenser;
|
||||
int _testTubeSetNum;
|
||||
uint32 _fillLevel;
|
||||
int _testTubeIndex;
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2808Handle : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2808Handle(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum);
|
||||
void activate();
|
||||
void stActivated();
|
||||
protected:
|
||||
Scene *_parentScene;
|
||||
int _testTubeSetNum;
|
||||
bool _isActivated;
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
uint32 hmActivating(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2808Flow : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2808Flow(NeverhoodEngine *vm, Scene *parentScene, int testTubeSetNum);
|
||||
void start();
|
||||
void stKeepFlowing();
|
||||
protected:
|
||||
Scene *_parentScene;
|
||||
int _testTubeSetNum;
|
||||
uint32 hmFlowing(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2808LightEffect : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2808LightEffect(NeverhoodEngine *vm, int which);
|
||||
protected:
|
||||
int _countdown;
|
||||
void update();
|
||||
};
|
||||
|
||||
class AsScene2809Spew : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2809Spew(NeverhoodEngine *vm);
|
||||
protected:
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2810Rope : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2810Rope(NeverhoodEngine *vm, Scene *parentScene, int16 x);
|
||||
protected:
|
||||
Scene *_parentScene;
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2812Winch : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2812Winch(NeverhoodEngine *vm);
|
||||
virtual ~AsScene2812Winch();
|
||||
protected:
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
class AsScene2812Rope : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2812Rope(NeverhoodEngine *vm, Scene *parentScene);
|
||||
protected:
|
||||
Scene *_parentScene;
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
uint32 hmRopingDown(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
void stRopingDown();
|
||||
};
|
||||
|
||||
class AsScene2812TrapDoor : public AnimatedSprite {
|
||||
public:
|
||||
AsScene2812TrapDoor(NeverhoodEngine *vm);
|
||||
protected:
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
};
|
||||
|
||||
} // End of namespace Neverhood
|
||||
|
||||
#endif /* NEVERHOOD_MODULES_MODULE2800_SPRITES_H */
|
@ -109,6 +109,7 @@ Common::Error NeverhoodEngine::run() {
|
||||
|
||||
_isSaveAllowed = true;
|
||||
_updateSound = true;
|
||||
_enableMusic = !_mixer->isSoundTypeMuted(Audio::Mixer::kMusicSoundType);
|
||||
|
||||
if (isDemo()) {
|
||||
// Adjust this navigation list for the demo version
|
||||
|
@ -72,8 +72,10 @@ public:
|
||||
uint32 getFeatures() const;
|
||||
uint16 getVersion() const;
|
||||
Common::Platform getPlatform() const;
|
||||
Common::Language getLanguage() const;
|
||||
bool hasFeature(EngineFeature f) const;
|
||||
bool isDemo() const;
|
||||
bool applyResourceFixes() const;
|
||||
Common::String getTargetName() { return _targetName; };
|
||||
|
||||
Common::RandomSource *_rnd;
|
||||
@ -135,9 +137,12 @@ public:
|
||||
NPoint getMousePos();
|
||||
|
||||
void toggleSoundUpdate(bool state) { _updateSound = state; }
|
||||
void toggleMusic(bool state) { _enableMusic = state; }
|
||||
bool musicIsEnabled() { return _enableMusic; }
|
||||
|
||||
private:
|
||||
bool _updateSound;
|
||||
bool _enableMusic;
|
||||
|
||||
};
|
||||
|
||||
|
@ -66,6 +66,11 @@ void Palette::init() {
|
||||
_status = 0;
|
||||
_palette = new byte[1024];
|
||||
_basePalette = new byte[1024];
|
||||
_palCounter = 0;
|
||||
_fadeToR = 0;
|
||||
_fadeToG = 0;
|
||||
_fadeToB = 0;
|
||||
_fadeStep = 0;
|
||||
}
|
||||
|
||||
void Palette::usePalette() {
|
||||
|
@ -53,7 +53,7 @@ bool SpriteResource::load(uint32 fileHash, bool doLoadPosition) {
|
||||
unload();
|
||||
_vm->_res->queryResource(fileHash, _resourceHandle);
|
||||
if (_resourceHandle.isValid() && _resourceHandle.type() == kResTypeBitmap) {
|
||||
_vm->_res->loadResource(_resourceHandle);
|
||||
_vm->_res->loadResource(_resourceHandle, _vm->applyResourceFixes());
|
||||
const byte *spriteData = _resourceHandle.data();
|
||||
NPoint *position = doLoadPosition ? &_position : NULL;
|
||||
parseBitmapResource(spriteData, &_rle, &_dimensions, position, NULL, &_pixels);
|
||||
@ -83,7 +83,7 @@ bool PaletteResource::load(uint32 fileHash) {
|
||||
_vm->_res->queryResource(fileHash, _resourceHandle);
|
||||
if (_resourceHandle.isValid() &&
|
||||
(_resourceHandle.type() == kResTypeBitmap || _resourceHandle.type() == kResTypePalette)) {
|
||||
_vm->_res->loadResource(_resourceHandle);
|
||||
_vm->_res->loadResource(_resourceHandle, _vm->applyResourceFixes());
|
||||
_palette = _resourceHandle.data();
|
||||
// Check if the palette is stored in a bitmap
|
||||
if (_resourceHandle.type() == kResTypeBitmap)
|
||||
@ -144,7 +144,7 @@ bool AnimResource::load(uint32 fileHash) {
|
||||
uint16 frameListStartOfs, frameCount;
|
||||
uint32 spriteDataOfs, paletteDataOfs;
|
||||
|
||||
_vm->_res->loadResource(_resourceHandle);
|
||||
_vm->_res->loadResource(_resourceHandle, _vm->applyResourceFixes());
|
||||
resourceData = _resourceHandle.data();
|
||||
|
||||
animListCount = READ_LE_UINT16(resourceData);
|
||||
@ -323,7 +323,7 @@ void TextResource::load(uint32 fileHash) {
|
||||
unload();
|
||||
_vm->_res->queryResource(fileHash, _resourceHandle);
|
||||
if (_resourceHandle.isValid() && _resourceHandle.type() == kResTypeText) {
|
||||
_vm->_res->loadResource(_resourceHandle);
|
||||
_vm->_res->loadResource(_resourceHandle, _vm->applyResourceFixes());
|
||||
_textData = _resourceHandle.data();
|
||||
_count = READ_LE_UINT32(_textData);
|
||||
}
|
||||
@ -359,7 +359,7 @@ void DataResource::load(uint32 fileHash) {
|
||||
unload();
|
||||
_vm->_res->queryResource(fileHash, _resourceHandle);
|
||||
if (_resourceHandle.isValid() && _resourceHandle.type() == kResTypeData) {
|
||||
_vm->_res->loadResource(_resourceHandle);
|
||||
_vm->_res->loadResource(_resourceHandle, _vm->applyResourceFixes());
|
||||
data = _resourceHandle.data();
|
||||
dataSize = _resourceHandle.size();
|
||||
}
|
||||
|
@ -85,7 +85,25 @@ void ResourceMan::queryResource(uint32 fileHash, ResourceHandle &resourceHandle)
|
||||
resourceHandle._extData = firstEntry ? firstEntry->archiveEntry->extData : NULL;
|
||||
}
|
||||
|
||||
void ResourceMan::loadResource(ResourceHandle &resourceHandle) {
|
||||
struct EntrySizeFix {
|
||||
uint32 fileHash;
|
||||
uint32 offset;
|
||||
uint32 diskSize;
|
||||
uint32 size;
|
||||
uint32 fixedSize;
|
||||
};
|
||||
|
||||
static const EntrySizeFix entrySizeFixes[] = {
|
||||
// fileHash offset diskSize size fixedSize
|
||||
// Fixes for the Russian "Dyadyushka Risech" version
|
||||
// TODO
|
||||
// Fixes for the Russian "Fargus" version
|
||||
// TODO
|
||||
//
|
||||
{ 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
void ResourceMan::loadResource(ResourceHandle &resourceHandle, bool applyResourceFixes) {
|
||||
resourceHandle._data = NULL;
|
||||
if (resourceHandle.isValid()) {
|
||||
const uint32 fileHash = resourceHandle.fileHash();
|
||||
@ -97,8 +115,19 @@ void ResourceMan::loadResource(ResourceHandle &resourceHandle) {
|
||||
if (resourceData->data != NULL) {
|
||||
resourceData->dataRefCount++;
|
||||
} else {
|
||||
resourceData->data = new byte[resourceHandle._resourceFileEntry->archiveEntry->size];
|
||||
resourceHandle._resourceFileEntry->archive->load(resourceHandle._resourceFileEntry->archiveEntry, resourceData->data, 0);
|
||||
BlbArchiveEntry *entry = resourceHandle._resourceFileEntry->archiveEntry;
|
||||
|
||||
// Apply fixes for broken resources in Russian versions
|
||||
if (applyResourceFixes) {
|
||||
for (const EntrySizeFix *cur = entrySizeFixes; cur->fileHash > 0; ++cur) {
|
||||
if (entry->fileHash == cur->fileHash && entry->offset == cur->offset &&
|
||||
entry->diskSize == cur->diskSize && entry->size == cur->size)
|
||||
entry->size = cur->fixedSize;
|
||||
}
|
||||
}
|
||||
|
||||
resourceData->data = new byte[entry->size];
|
||||
resourceHandle._resourceFileEntry->archive->load(entry, resourceData->data, 0);
|
||||
resourceData->dataRefCount = 1;
|
||||
}
|
||||
resourceHandle._data = resourceData->data;
|
||||
|
@ -78,7 +78,7 @@ public:
|
||||
const ResourceFileEntry& getEntry(uint index) { return _entries[index]; }
|
||||
uint getEntryCount() { return _entries.size(); }
|
||||
void queryResource(uint32 fileHash, ResourceHandle &resourceHandle);
|
||||
void loadResource(ResourceHandle &resourceHandle);
|
||||
void loadResource(ResourceHandle &resourceHandle, bool applyResourceFixes);
|
||||
void unloadResource(ResourceHandle &resourceHandle);
|
||||
void purgeResources();
|
||||
protected:
|
||||
|
@ -50,6 +50,9 @@ Scene::Scene(NeverhoodEngine *vm, Module *parentModule)
|
||||
_smackerPlayer = NULL;
|
||||
_isMessageListBusy = false;
|
||||
_messageValue = -1;
|
||||
_messageListStatus = 0;
|
||||
_messageListCount = 0;
|
||||
_messageListIndex = 0;
|
||||
|
||||
_backgroundFileHash = _cursorFileHash = 0;
|
||||
|
||||
|
@ -204,8 +204,6 @@ protected:
|
||||
// Used for debugging
|
||||
uint32 _backgroundFileHash, _cursorFileHash; // for StaticScene and all Scene* classes
|
||||
|
||||
void (Entity::*_savedUpdateHandlerCb)();
|
||||
uint32 (Entity::*_savedMessageHandlerCb)(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
int _messageValue;
|
||||
uint32 handleMessage(int messageNum, const MessageParam ¶m, Entity *sender);
|
||||
bool queryPositionSprite(int16 mouseX, int16 mouseY);
|
||||
|
@ -27,7 +27,8 @@ namespace Neverhood {
|
||||
|
||||
Screen::Screen(NeverhoodEngine *vm)
|
||||
: _vm(vm), _paletteData(NULL), _paletteChanged(false), _smackerDecoder(NULL),
|
||||
_yOffset(0), _fullRefresh(false) {
|
||||
_yOffset(0), _fullRefresh(false), _frameDelay(0), _savedSmackerDecoder(NULL),
|
||||
_savedFrameDelay(0), _savedYOffset(0) {
|
||||
|
||||
_ticks = _vm->_system->getMillis();
|
||||
|
||||
|
@ -250,13 +250,26 @@ void SoundItem::update() {
|
||||
// SoundMan
|
||||
|
||||
SoundMan::SoundMan(NeverhoodEngine *vm)
|
||||
: _vm(vm), _soundIndex1(-1), _soundIndex2(-1), _soundIndex3(-1) {
|
||||
: _vm(vm), _soundIndex1(-1), _soundIndex2(-1), _soundIndex3(-1),
|
||||
_initialCountdown(0), _playOnceAfterCountdown(false),
|
||||
_initialCountdown3(0), _playOnceAfterCountdown3(false) {
|
||||
}
|
||||
|
||||
SoundMan::~SoundMan() {
|
||||
stopAllMusic();
|
||||
stopAllSounds();
|
||||
}
|
||||
|
||||
void SoundMan::stopAllMusic() {
|
||||
for (uint i = 0; i < _musicItems.size(); ++i) {
|
||||
if (_musicItems[i]) {
|
||||
_musicItems[i]->stopMusic(0, 0);
|
||||
delete _musicItems[i];
|
||||
_musicItems[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoundMan::stopAllSounds() {
|
||||
for (uint i = 0; i < _soundItems.size(); ++i) {
|
||||
if (_soundItems[i]) {
|
||||
@ -265,13 +278,6 @@ void SoundMan::stopAllSounds() {
|
||||
_soundItems[i] = NULL;
|
||||
}
|
||||
}
|
||||
for (uint i = 0; i < _musicItems.size(); ++i) {
|
||||
if (_musicItems[i]) {
|
||||
_musicItems[i]->stopMusic(0, 0);
|
||||
delete _musicItems[i];
|
||||
_musicItems[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
_soundIndex1 = _soundIndex2 = _soundIndex3 = -1;
|
||||
}
|
||||
@ -573,7 +579,7 @@ AudioResourceManSoundItem::AudioResourceManSoundItem(NeverhoodEngine *vm, uint32
|
||||
void AudioResourceManSoundItem::loadSound() {
|
||||
if (!_data && _resourceHandle.isValid() &&
|
||||
(_resourceHandle.type() == kResTypeSound || _resourceHandle.type() == kResTypeMusic)) {
|
||||
_vm->_res->loadResource(_resourceHandle);
|
||||
_vm->_res->loadResource(_resourceHandle, _vm->applyResourceFixes());
|
||||
_data = _resourceHandle.data();
|
||||
}
|
||||
}
|
||||
@ -623,7 +629,8 @@ bool AudioResourceManSoundItem::isPlaying() {
|
||||
|
||||
AudioResourceManMusicItem::AudioResourceManMusicItem(NeverhoodEngine *vm, uint32 fileHash)
|
||||
: _vm(vm), _fileHash(fileHash), _terminate(false), _canRestart(false),
|
||||
_volume(100), _panning(50), _start(false), _isFadingIn(false), _isFadingOut(false), _isPlaying(false) {
|
||||
_volume(100), _panning(50), _start(false), _isFadingIn(false), _isFadingOut(false), _isPlaying(false),
|
||||
_fadeVolume(0), _fadeVolumeStep(0) {
|
||||
|
||||
}
|
||||
|
||||
@ -724,14 +731,7 @@ AudioResourceMan::AudioResourceMan(NeverhoodEngine *vm)
|
||||
: _vm(vm) {
|
||||
}
|
||||
|
||||
void AudioResourceMan::stopAllSounds() {
|
||||
for (uint i = 0; i < _soundItems.size(); ++i) {
|
||||
if (_soundItems[i]) {
|
||||
_soundItems[i]->stopSound();
|
||||
delete _soundItems[i];
|
||||
_soundItems[i] = NULL;
|
||||
}
|
||||
}
|
||||
void AudioResourceMan::stopAllMusic() {
|
||||
for (uint i = 0; i < _musicItems.size(); ++i) {
|
||||
if (_musicItems[i]) {
|
||||
_musicItems[i]->stopMusic(0);
|
||||
@ -741,7 +741,18 @@ void AudioResourceMan::stopAllSounds() {
|
||||
}
|
||||
}
|
||||
|
||||
void AudioResourceMan::stopAllSounds() {
|
||||
for (uint i = 0; i < _soundItems.size(); ++i) {
|
||||
if (_soundItems[i]) {
|
||||
_soundItems[i]->stopSound();
|
||||
delete _soundItems[i];
|
||||
_soundItems[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AudioResourceMan::~AudioResourceMan() {
|
||||
stopAllMusic();
|
||||
stopAllSounds();
|
||||
}
|
||||
|
||||
|
@ -129,6 +129,7 @@ public:
|
||||
SoundMan(NeverhoodEngine *vm);
|
||||
~SoundMan();
|
||||
|
||||
void stopAllMusic();
|
||||
void stopAllSounds();
|
||||
|
||||
// Music
|
||||
@ -264,6 +265,7 @@ public:
|
||||
AudioResourceMan(NeverhoodEngine *vm);
|
||||
~AudioResourceMan();
|
||||
|
||||
void stopAllMusic();
|
||||
void stopAllSounds();
|
||||
|
||||
int16 addSound(uint32 fileHash);
|
||||
|
@ -211,6 +211,12 @@ void AnimatedSprite::init() {
|
||||
_replNewColor = 0;
|
||||
_animResource.setReplEnabled(false);
|
||||
_playBackwards = false;
|
||||
_currAnimFileHash = 0;
|
||||
_lastFrameIndex = 0;
|
||||
_plLastFrameIndex = 0;
|
||||
_plFirstFrameHash = 0;
|
||||
_plLastFrameHash = 0;
|
||||
_animStatus = 0;
|
||||
}
|
||||
|
||||
void AnimatedSprite::update() {
|
||||
|
@ -3297,6 +3297,17 @@ static const struct ADGameDescription SciGameDescriptions[] = {
|
||||
AD_LISTEND},
|
||||
Common::EN_ANY, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
|
||||
|
||||
// RAMA - German Windows CD (from farmboy0, in pull request 397)
|
||||
{"rama", "", {
|
||||
{"resmap.001", 0, "f68cd73308c46977a9632dfc618e1e38", 8338},
|
||||
{"ressci.001", 0, "2a68edd064e5e4937b5e9c74b38f2082", 70595521},
|
||||
{"resmap.002", 0, "891fc2f5d9e23e7d9a9454acc7aaae52", 12082},
|
||||
{"ressci.002", 0, "2a68edd064e5e4937b5e9c74b38f2082", 128508558},
|
||||
{"resmap.003", 0, "222096000bd83a1d56577114a452cccf", 1636},
|
||||
{"ressci.003", 0, "2a68edd064e5e4937b5e9c74b38f2082", 6954219},
|
||||
AD_LISTEND},
|
||||
Common::DE_DEU, Common::kPlatformWindows, ADGF_UNSTABLE, GUIO4(GUIO_NOASPECT, GAMEOPTION_PREFER_DIGITAL_SFX, GAMEOPTION_ORIGINAL_SAVELOAD, GAMEOPTION_FB01_MIDI) },
|
||||
|
||||
// RAMA - Italian Windows CD (from glorifindel)
|
||||
// SCI interpreter version 3.000.000 (a guess?)
|
||||
{"rama", "", {
|
||||
|
@ -600,7 +600,10 @@ void MusicEntry::saveLoadWithSerializer(Common::Serializer &s) {
|
||||
s.syncAsSint16LE(dataInc);
|
||||
s.syncAsSint16LE(ticker);
|
||||
s.syncAsSint16LE(signal, VER(17));
|
||||
s.syncAsByte(priority);
|
||||
if (s.getVersion() >= 31) // FE sound/music.h -> priority
|
||||
s.syncAsSint16LE(priority);
|
||||
else
|
||||
s.syncAsByte(priority);
|
||||
s.syncAsSint16LE(loop, VER(17));
|
||||
s.syncAsByte(volume);
|
||||
s.syncAsByte(hold, VER(17));
|
||||
|
@ -37,6 +37,7 @@ struct EngineState;
|
||||
*
|
||||
* Version - new/changed feature
|
||||
* =============================
|
||||
* 31 - priority for sound effects/music is now a signed int16, instead of a byte
|
||||
* 30 - synonyms
|
||||
* 29 - system strings
|
||||
* 28 - heap
|
||||
@ -55,7 +56,7 @@ struct EngineState;
|
||||
*/
|
||||
|
||||
enum {
|
||||
CURRENT_SAVEGAME_VERSION = 30,
|
||||
CURRENT_SAVEGAME_VERSION = 31,
|
||||
MINIMUM_SAVEGAME_VERSION = 14
|
||||
};
|
||||
|
||||
|
@ -58,6 +58,58 @@ struct SciScriptSignature {
|
||||
// - if not EOS, an adjust offset and the actual bytes
|
||||
// - rinse and repeat
|
||||
|
||||
// ===========================================================================
|
||||
// Conquests of Camelot
|
||||
// At the bazaar in Jerusalem, it's possible to see a girl taking a shower.
|
||||
// If you get too close, you get warned by the father - if you don't get away,
|
||||
// he will kill you.
|
||||
// Instead of walking there manually, it's also possible to enter "look window"
|
||||
// and ego will automatically walk to the window. It seems that this is something
|
||||
// that wasn't properly implemented, because instead of getting killed, you will
|
||||
// get an "Oops" message in Sierra SCI.
|
||||
//
|
||||
// This is caused by peepingTom in script 169 not getting properly initialized.
|
||||
// peepingTom calls the object behind global b9h. This global variable is
|
||||
// properly initialized, when walking there manually (method fawaz::doit).
|
||||
// When you instead walk there automatically (method fawaz::handleEvent), that
|
||||
// global isn't initialized, which then results in the Oops-message in Sierra SCI
|
||||
// and an error message in ScummVM/SCI.
|
||||
//
|
||||
// We fix the script by patching in a jump to the proper code inside fawaz::doit.
|
||||
// Responsible method: fawaz::handleEvent
|
||||
// Fixes bug #3614969
|
||||
const byte camelotSignaturePeepingTom[] = {
|
||||
5,
|
||||
0x72, 0x7e, 0x07, // lofsa fawaz <-- start of proper initializion code
|
||||
0xa1, 0xb9, // sag b9h
|
||||
+255, 0,
|
||||
+255, 0,
|
||||
+61, 19, // skip 571 bytes
|
||||
0x39, 0x7a, // pushi 7a <-- initialization code when walking automatically
|
||||
0x78, // push1
|
||||
0x7a, // push2
|
||||
0x38, 0xa9, 0x00, // pushi 00a9 - script 169
|
||||
0x78, // push1
|
||||
0x43, 0x02, 0x04, // call kScriptID
|
||||
0x36, // push
|
||||
0x81, 0x00, // lag 00
|
||||
0x4a, 0x06, // send 06
|
||||
0x32, 0x20, 0x05, // jmp [end of fawaz::handleEvent]
|
||||
0
|
||||
};
|
||||
|
||||
const uint16 camelotPatchPeepingTom[] = {
|
||||
PATCH_ADDTOOFFSET | +576,
|
||||
0x32, 0xbd, 0xfd, // jmp to fawaz::doit / properly init peepingTom code
|
||||
PATCH_END
|
||||
};
|
||||
|
||||
// script, description, magic DWORD, adjust
|
||||
const SciScriptSignature camelotSignatures[] = {
|
||||
{ 62, "fix peepingTom Sierra bug", 1, PATCH_MAGICDWORD(0x7e, 0x07, 0xa1, 0xb9), -1, camelotSignaturePeepingTom, camelotPatchPeepingTom },
|
||||
SCI_SIGNATUREENTRY_TERMINATOR
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
// stayAndHelp::changeState (0) is called when ego swims to the left or right
|
||||
// boundaries of room 660. Normally a textbox is supposed to get on screen
|
||||
@ -741,6 +793,48 @@ const SciScriptSignature longbowSignatures[] = {
|
||||
SCI_SIGNATUREENTRY_TERMINATOR
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
// Leisure Suit Larry 2
|
||||
// On the plane, Larry is able to wear the parachute. This grants 4 points.
|
||||
// In early versions of LSL2, it was possible to get "unlimited" points by
|
||||
// simply wearing it multiple times.
|
||||
// They fixed it in later versions by remembering, if the parachute was already
|
||||
// used before.
|
||||
// But instead of adding it properly, it seems they hacked the script / forgot
|
||||
// to replace script 0 as well, which holds information about how many global
|
||||
// variables are allocated at the start of the game.
|
||||
// The script tries to read an out-of-bounds global variable, which somewhat
|
||||
// "worked" in SSCI, but ScummVM/SCI doesn't allow that.
|
||||
// That's why those points weren't granted here at all.
|
||||
// We patch the script to use global 90, which seems to be unused in the whole game.
|
||||
// Responsible method: rm63Script::handleEvent
|
||||
// Fixes bug #3614419
|
||||
const byte larry2SignatureWearParachutePoints[] = {
|
||||
16,
|
||||
0x35, 0x01, // ldi 01
|
||||
0xa1, 0x8e, // sag 8e
|
||||
0x80, 0xe0, 0x01, // lag 1e0
|
||||
0x18, // not
|
||||
0x30, 0x0f, 0x00, // bnt [don't give points]
|
||||
0x35, 0x01, // ldi 01
|
||||
0xa0, 0xe0, 0x01, // sag 1e0
|
||||
0
|
||||
};
|
||||
|
||||
const uint16 larry2PatchWearParachutePoints[] = {
|
||||
PATCH_ADDTOOFFSET | +4,
|
||||
0x80, 0x5a, 0x00, // lag 5a (global 90)
|
||||
PATCH_ADDTOOFFSET | +6,
|
||||
0xa0, 0x5a, 0x00, // sag 5a (global 90)
|
||||
PATCH_END
|
||||
};
|
||||
|
||||
// script, description, magic DWORD, adjust
|
||||
const SciScriptSignature larry2Signatures[] = {
|
||||
{ 63, "plane: no points for wearing plane", 1, PATCH_MAGICDWORD(0x8e, 0x80, 0xe0, 0x01), -3, larry2SignatureWearParachutePoints, larry2PatchWearParachutePoints },
|
||||
SCI_SIGNATUREENTRY_TERMINATOR
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
// this is called on every death dialog. Problem is at least the german
|
||||
// version of lsl6 gets title text that is far too long for the
|
||||
@ -867,6 +961,68 @@ const SciScriptSignature mothergoose256Signatures[] = {
|
||||
SCI_SIGNATUREENTRY_TERMINATOR
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
// Police Quest 1 VGA
|
||||
// When at the police station, you can put or get your gun from your locker.
|
||||
// The script, that handles this, is buggy. It disposes the gun as soon as
|
||||
// you click, but then waits 2 seconds before it also closes the locker.
|
||||
// Problem is that it's possible to click again, which then results in a
|
||||
// disposed object getting accessed. This happened to work by pure luck in
|
||||
// SSCI.
|
||||
// This patch changes the code, so that the gun is actually given away
|
||||
// when the 2 seconds have passed and the locker got closed.
|
||||
// Responsible method: putGun::changeState (script 341)
|
||||
// Fixes bug #3036933 / #3303802
|
||||
const byte pq1vgaSignaturePutGunInLockerBug[] = {
|
||||
5,
|
||||
0x35, 0x00, // ldi 00
|
||||
0x1a, // eq?
|
||||
0x31, 0x25, // bnt [next state check]
|
||||
+22, 29, // [skip 22 bytes]
|
||||
0x38, 0x5f, 0x01, // pushi 15fh
|
||||
0x78, // push1
|
||||
0x76, // push0
|
||||
0x81, 0x00, // lag 00
|
||||
0x4a, 0x06, // send 06 - ego::put(0)
|
||||
0x35, 0x02, // ldi 02
|
||||
0x65, 0x1c, // aTop 1c (set timer to 2 seconds)
|
||||
0x33, 0x0e, // jmp [end of method]
|
||||
0x3c, // dup --- next state check target
|
||||
0x35, 0x01, // ldi 01
|
||||
0x1a, // eq?
|
||||
0x31, 0x08, // bnt [end of method]
|
||||
0x39, 0x6f, // pushi 6fh
|
||||
0x76, // push0
|
||||
0x72, 0x88, 0x00, // lofsa 0088
|
||||
0x4a, 0x04, // send 04 - locker::dispose
|
||||
0
|
||||
};
|
||||
|
||||
const uint16 pq1vgaPatchPutGunInLockerBug[] = {
|
||||
PATCH_ADDTOOFFSET | +3,
|
||||
0x31, 0x1c, // bnt [next state check]
|
||||
PATCH_ADDTOOFFSET | +22,
|
||||
0x35, 0x02, // ldi 02
|
||||
0x65, 0x1c, // aTop 1c (set timer to 2 seconds)
|
||||
0x33, 0x17, // jmp [end of method]
|
||||
0x3c, // dup --- next state check target
|
||||
0x35, 0x01, // ldi 01
|
||||
0x1a, // eq?
|
||||
0x31, 0x11, // bnt [end of method]
|
||||
0x38, 0x5f, 0x01, // pushi 15fh
|
||||
0x78, // push1
|
||||
0x76, // push0
|
||||
0x81, 0x00, // lag 00
|
||||
0x4a, 0x06, // send 06 - ego::put(0)
|
||||
PATCH_END
|
||||
};
|
||||
|
||||
// script, description, magic DWORD, adjust
|
||||
const SciScriptSignature pq1vgaSignatures[] = {
|
||||
{ 341, "put gun in locker bug", 1, PATCH_MAGICDWORD(0x38, 0x5f, 0x01, 0x78), -27, pq1vgaSignaturePutGunInLockerBug, pq1vgaPatchPutGunInLockerBug },
|
||||
SCI_SIGNATUREENTRY_TERMINATOR
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
// script 215 of qfg1vga pointBox::doit actually processes button-presses
|
||||
// during fighting with monsters. It strangely also calls kGetEvent. Because
|
||||
@ -995,14 +1151,75 @@ const uint16 qfg1vgaPatchMoveToCastleGate[] = {
|
||||
PATCH_END
|
||||
};
|
||||
|
||||
// Typo in the original Sierra scripts
|
||||
// Looking at a cheetaur resulted in a text about a Saurus Rex
|
||||
// The code treats both monster types the same.
|
||||
// Responsible method: smallMonster::doVerb
|
||||
// Fixes bug #3604943.
|
||||
const byte qfg1vgaSignatureCheetaurDescription[] = {
|
||||
16,
|
||||
0x34, 0xb8, 0x01, // ldi 01b8
|
||||
0x1a, // eq?
|
||||
0x31, 0x16, // bnt 16
|
||||
0x38, 0x27, 0x01, // pushi 0127
|
||||
0x39, 0x06, // pushi 06
|
||||
0x39, 0x03, // pushi 03
|
||||
0x78, // push1
|
||||
0x39, 0x12, // pushi 12 -> monster type Saurus Rex
|
||||
0
|
||||
};
|
||||
|
||||
const uint16 qfg1vgaPatchCheetaurDescription[] = {
|
||||
PATCH_ADDTOOFFSET | +14,
|
||||
0x39, 0x11, // pushi 11 -> monster type cheetaur
|
||||
PATCH_END
|
||||
};
|
||||
|
||||
// In the "funny" room (Yorick's room) in QfG1 VGA, pulling the chain and
|
||||
// then pressing the button on the right side of the room results in
|
||||
// a broken game. This also happens in SSCI.
|
||||
// Problem is that the Sierra programmers forgot to disable the door, that
|
||||
// gets opened by pulling the chain. So when ego falls down and then
|
||||
// rolls through the door, one method thinks that the player walks through
|
||||
// it and acts that way and the other method is still doing the roll animation.
|
||||
// Local 5 of that room is a timer, that closes the door (object door11).
|
||||
// Setting it to 1 during happyFace::changeState(0) stops door11::doit from
|
||||
// calling goTo6::init, so the whole issue is stopped from happening.
|
||||
// Responsible method: happyFace::changeState, door11::doit
|
||||
// Fixes bug #3585793
|
||||
const byte qfg1vgaSignatureFunnyRoomFix[] = {
|
||||
14,
|
||||
0x65, 0x14, // aTop 14 (state)
|
||||
0x36, // push
|
||||
0x3c, // dup
|
||||
0x35, 0x00, // ldi 00
|
||||
0x1a, // eq?
|
||||
0x30, 0x25, 0x00, // bnt 0025 [-> next state]
|
||||
0x35, 0x01, // ldi 01
|
||||
0xa3, 0x4e, // sal 4e
|
||||
0
|
||||
};
|
||||
|
||||
const uint16 qfg1vgaPatchFunnyRoomFix[] = {
|
||||
PATCH_ADDTOOFFSET | +3,
|
||||
0x2e, 0x29, 0x00, // bt 0029 [-> next state] - saves 4 bytes
|
||||
0x35, 0x01, // ldi 01
|
||||
0xa3, 0x4e, // sal 4e
|
||||
0xa3, 0x05, // sal 05 (sets local 5 to 1)
|
||||
0xa3, 0x05, // and again to make absolutely sure (actually to waste 2 bytes)
|
||||
PATCH_END
|
||||
};
|
||||
|
||||
// script, description, magic DWORD, adjust
|
||||
const SciScriptSignature qfg1vgaSignatures[] = {
|
||||
{ 215, "fight event issue", 1, PATCH_MAGICDWORD(0x6d, 0x76, 0x51, 0x07), -1, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents },
|
||||
{ 216, "weapon master event issue", 1, PATCH_MAGICDWORD(0x6d, 0x76, 0x51, 0x07), -1, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents },
|
||||
{ 814, "window text temp space", 1, PATCH_MAGICDWORD(0x3f, 0xba, 0x87, 0x00), 0, qfg1vgaSignatureTempSpace, qfg1vgaPatchTempSpace },
|
||||
{ 814, "dialog header offset", 3, PATCH_MAGICDWORD(0x5b, 0x04, 0x80, 0x36), 0, qfg1vgaSignatureDialogHeader, qfg1vgaPatchDialogHeader },
|
||||
{ 331, "moving to crusher", 1, PATCH_MAGICDWORD(0x51, 0x1f, 0x36, 0x39), 0, qfg1vgaSignatureMoveToCrusher, qfg1vgaPatchMoveToCrusher },
|
||||
{ 41, "moving to castle gate", 1, PATCH_MAGICDWORD(0x51, 0x1f, 0x36, 0x39), 0, qfg1vgaSignatureMoveToCastleGate, qfg1vgaPatchMoveToCastleGate },
|
||||
{ 215, "fight event issue", 1, PATCH_MAGICDWORD(0x6d, 0x76, 0x51, 0x07), -1, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents },
|
||||
{ 216, "weapon master event issue", 1, PATCH_MAGICDWORD(0x6d, 0x76, 0x51, 0x07), -1, qfg1vgaSignatureFightEvents, qfg1vgaPatchFightEvents },
|
||||
{ 814, "window text temp space", 1, PATCH_MAGICDWORD(0x3f, 0xba, 0x87, 0x00), 0, qfg1vgaSignatureTempSpace, qfg1vgaPatchTempSpace },
|
||||
{ 814, "dialog header offset", 3, PATCH_MAGICDWORD(0x5b, 0x04, 0x80, 0x36), 0, qfg1vgaSignatureDialogHeader, qfg1vgaPatchDialogHeader },
|
||||
{ 331, "moving to crusher", 1, PATCH_MAGICDWORD(0x51, 0x1f, 0x36, 0x39), 0, qfg1vgaSignatureMoveToCrusher, qfg1vgaPatchMoveToCrusher },
|
||||
{ 41, "moving to castle gate", 1, PATCH_MAGICDWORD(0x51, 0x1f, 0x36, 0x39), 0, qfg1vgaSignatureMoveToCastleGate, qfg1vgaPatchMoveToCastleGate },
|
||||
{ 210, "cheetaur description fixed", 1, PATCH_MAGICDWORD(0x34, 0xb8, 0x01, 0x1a), 0, qfg1vgaSignatureCheetaurDescription, qfg1vgaPatchCheetaurDescription },
|
||||
{ 96, "funny room script bug fixed", 1, PATCH_MAGICDWORD(0x35, 0x01, 0xa3, 0x4e), -10, qfg1vgaSignatureFunnyRoomFix, qfg1vgaPatchFunnyRoomFix },
|
||||
SCI_SIGNATUREENTRY_TERMINATOR
|
||||
};
|
||||
|
||||
@ -1250,6 +1467,32 @@ const SciScriptSignature sq4Signatures[] = {
|
||||
SCI_SIGNATUREENTRY_TERMINATOR
|
||||
};
|
||||
|
||||
// ===========================================================================
|
||||
// When you leave Ulence Flats, another timepod is supposed to appear.
|
||||
// On fast machines, that timepod appears fully immediately and then
|
||||
// starts to appear like it should be. That first appearance is caused
|
||||
// by the scripts setting an invalid cel number and the machine being
|
||||
// so fast that there is no time for another script to actually fix
|
||||
// the cel number. On slower machines, the cel number gets fixed
|
||||
// by the cycler and that's why only fast machines are affected.
|
||||
// The same issue happens in Sierra SCI.
|
||||
// We simply set the correct starting cel number to fix the bug.
|
||||
// Responsible method: robotIntoShip::changeState(9)
|
||||
const byte sq1vgaSignatureUlenceFlatsTimepodGfxGlitch[] = {
|
||||
8,
|
||||
0x39, 0x07, // pushi 07 (ship::cel)
|
||||
0x78, // push1
|
||||
0x39, 0x0a, // pushi 0x0a (set ship::cel to 10)
|
||||
0x38, 0xa0, 0x00, // pushi 0x00a0 (ship::setLoop)
|
||||
0
|
||||
};
|
||||
|
||||
const uint16 sq1vgaPatchUlenceFlatsTimepodGfxGlitch[] = {
|
||||
PATCH_ADDTOOFFSET | +3,
|
||||
0x39, 0x09, // pushi 0x09 (set ship::cel to 9)
|
||||
PATCH_END
|
||||
};
|
||||
|
||||
const byte sq1vgaSignatureEgoShowsCard[] = {
|
||||
25,
|
||||
0x38, 0x46, 0x02, // push 0x246 (set up send frame to set timesShownID)
|
||||
@ -1267,7 +1510,8 @@ const byte sq1vgaSignatureEgoShowsCard[] = {
|
||||
0x36, // push (wrong, acc clobbered by class, above)
|
||||
0x35, 0x03, // ldi 0x03
|
||||
0x22, // lt?
|
||||
0};
|
||||
0
|
||||
};
|
||||
|
||||
// Note that this script patch is merely a reordering of the
|
||||
// instructions in the original script.
|
||||
@ -1287,13 +1531,14 @@ const uint16 sq1vgaPatchEgoShowsCard[] = {
|
||||
0x4a, 0x06, // send 0x06 (set timesShownID)
|
||||
0x35, 0x03, // ldi 0x03
|
||||
0x22, // lt?
|
||||
PATCH_END};
|
||||
PATCH_END
|
||||
};
|
||||
|
||||
|
||||
// script, description, magic DWORD, adjust
|
||||
const SciScriptSignature sq1vgaSignatures[] = {
|
||||
{ 58, "Sarien armory droid zapping ego first time", 1, PATCH_MAGICDWORD( 0x72, 0x88, 0x15, 0x36 ), -70,
|
||||
sq1vgaSignatureEgoShowsCard, sq1vgaPatchEgoShowsCard },
|
||||
{ 45, "Ulence Flats: timepod graphic glitch", 1, PATCH_MAGICDWORD( 0x07, 0x78, 0x39, 0x0a ), -1, sq1vgaSignatureUlenceFlatsTimepodGfxGlitch, sq1vgaPatchUlenceFlatsTimepodGfxGlitch },
|
||||
{ 58, "Sarien armory droid zapping ego first time", 1, PATCH_MAGICDWORD( 0x72, 0x88, 0x15, 0x36 ), -70, sq1vgaSignatureEgoShowsCard, sq1vgaPatchEgoShowsCard },
|
||||
|
||||
SCI_SIGNATUREENTRY_TERMINATOR};
|
||||
|
||||
@ -1389,6 +1634,9 @@ int32 Script::findSignature(const SciScriptSignature *signature, const byte *scr
|
||||
void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uint32 scriptSize) {
|
||||
const SciScriptSignature *signatureTable = NULL;
|
||||
switch (g_sci->getGameId()) {
|
||||
case GID_CAMELOT:
|
||||
signatureTable = camelotSignatures;
|
||||
break;
|
||||
case GID_ECOQUEST:
|
||||
signatureTable = ecoquest1Signatures;
|
||||
break;
|
||||
@ -1420,12 +1668,18 @@ void Script::matchSignatureAndPatch(uint16 scriptNr, byte *scriptData, const uin
|
||||
case GID_LONGBOW:
|
||||
signatureTable = longbowSignatures;
|
||||
break;
|
||||
case GID_LSL2:
|
||||
signatureTable = larry2Signatures;
|
||||
break;
|
||||
case GID_LSL6:
|
||||
signatureTable = larry6Signatures;
|
||||
break;
|
||||
case GID_MOTHERGOOSE256:
|
||||
signatureTable = mothergoose256Signatures;
|
||||
break;
|
||||
case GID_PQ1:
|
||||
signatureTable = pq1vgaSignatures;
|
||||
break;
|
||||
case GID_QFG1VGA:
|
||||
signatureTable = qfg1vgaSignatures;
|
||||
break;
|
||||
|
@ -286,11 +286,15 @@ void GfxScreen::putPixelOnDisplay(int x, int y, byte color) {
|
||||
* with flood fill, due to small difference in the Bresenham logic.
|
||||
*/
|
||||
void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control) {
|
||||
int16 left = startPoint.x;
|
||||
int16 top = startPoint.y;
|
||||
int16 right = endPoint.x;
|
||||
int16 bottom = endPoint.y;
|
||||
|
||||
int16 maxWidth = _width - 1;
|
||||
int16 maxHeight = _height - 1;
|
||||
// we need to clip values here, lsl3 room 620 background picture draws a line from 0, 199 t 320, 199
|
||||
// otherwise we would get heap corruption.
|
||||
int16 left = CLIP<int16>(startPoint.x, 0, maxWidth);
|
||||
int16 top = CLIP<int16>(startPoint.y, 0, maxHeight);
|
||||
int16 right = CLIP<int16>(endPoint.x, 0, maxWidth);
|
||||
int16 bottom = CLIP<int16>(endPoint.y, 0, maxHeight);
|
||||
|
||||
//set_drawing_flag
|
||||
byte drawMask = getDrawingMask(color, priority, control);
|
||||
|
||||
|
@ -20,6 +20,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sci/sci.h"
|
||||
#include "sci/engine/state.h"
|
||||
|
||||
#include "sci/engine/kernel.h"
|
||||
#include "sci/engine/state.h"
|
||||
#include "sci/sound/midiparser_sci.h"
|
||||
@ -53,11 +56,6 @@ MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion, SciMusic *music) :
|
||||
_masterVolume = 15;
|
||||
_volume = 127;
|
||||
|
||||
_signalSet = false;
|
||||
_signalToSet = 0;
|
||||
_dataincAdd = false;
|
||||
_dataincToAdd = 0;
|
||||
_jumpToHoldTick = false;
|
||||
_resetOnPause = false;
|
||||
_pSnd = 0;
|
||||
}
|
||||
@ -440,26 +438,6 @@ void MidiParser_SCI::sendToDriver(uint32 midi) {
|
||||
}
|
||||
|
||||
void MidiParser_SCI::parseNextEvent(EventInfo &info) {
|
||||
// Set signal AFTER waiting for delta, otherwise we would set signal too soon resulting in all sorts of bugs
|
||||
if (_dataincAdd) {
|
||||
_dataincAdd = false;
|
||||
_pSnd->dataInc += _dataincToAdd;
|
||||
_pSnd->signal = 0x7f + _pSnd->dataInc;
|
||||
debugC(4, kDebugLevelSound, "datainc %04x", _dataincToAdd);
|
||||
}
|
||||
if (_signalSet) {
|
||||
_signalSet = false;
|
||||
_pSnd->setSignal(_signalToSet);
|
||||
|
||||
debugC(4, kDebugLevelSound, "signal %04x", _signalToSet);
|
||||
}
|
||||
if (_jumpToHoldTick) {
|
||||
_jumpToHoldTick = false;
|
||||
_pSnd->inFastForward = true;
|
||||
jumpToTick(_loopTick, false, false);
|
||||
_pSnd->inFastForward = false;
|
||||
}
|
||||
|
||||
info.start = _position._playPos;
|
||||
info.delta = 0;
|
||||
while (*_position._playPos == 0xF8) {
|
||||
@ -481,33 +459,6 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
|
||||
case 0xC:
|
||||
info.basic.param1 = *(_position._playPos++);
|
||||
info.basic.param2 = 0;
|
||||
if (info.channel() == 0xF) {// SCI special case
|
||||
if (info.basic.param1 != kSetSignalLoop) {
|
||||
// At least in kq5/french&mac the first scene in the intro has
|
||||
// a song that sets signal to 4 immediately on tick 0. Signal
|
||||
// isn't set at that point by sierra sci and it would cause the
|
||||
// castle daventry text to get immediately removed, so we
|
||||
// currently filter it. Sierra SCI ignores them as well at that
|
||||
// time. However, this filtering should only be performed for
|
||||
// SCI1 and newer games. Signalling is done differently in SCI0
|
||||
// though, so ignoring these signals in SCI0 games will result
|
||||
// in glitches (e.g. the intro of LB1 Amiga gets stuck - bug
|
||||
// #3297883). Refer to MusicEntry::setSignal() in sound/music.cpp.
|
||||
// FIXME: SSCI doesn't start playing at the very beginning
|
||||
// of the stream, but at a fixed location a few commands later.
|
||||
// That is probably why this signal isn't triggered
|
||||
// immediately there.
|
||||
if (_soundVersion <= SCI_VERSION_0_LATE ||
|
||||
_position._playTick || info.delta) {
|
||||
if (!_pSnd->inFastForward) {
|
||||
_signalSet = true;
|
||||
_signalToSet = info.basic.param1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_loopTick = _position._playTick + info.delta;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xD:
|
||||
info.basic.param1 = *(_position._playPos++);
|
||||
@ -517,92 +468,6 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
|
||||
case 0xB:
|
||||
info.basic.param1 = *(_position._playPos++);
|
||||
info.basic.param2 = *(_position._playPos++);
|
||||
|
||||
// Reference for some events:
|
||||
// http://wiki.scummvm.org/index.php/SCI/Specifications/Sound/SCI0_Resource_Format#Status_Reference
|
||||
// Handle common special events
|
||||
switch (info.basic.param1) {
|
||||
case kSetReverb:
|
||||
if (info.basic.param2 == 127) // Set global reverb instead
|
||||
_pSnd->reverb = _music->getGlobalReverb();
|
||||
else
|
||||
_pSnd->reverb = info.basic.param2;
|
||||
|
||||
((MidiPlayer *)_driver)->setReverb(_pSnd->reverb);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Handle events sent to the SCI special channel (15)
|
||||
if (info.channel() == 0xF) {
|
||||
switch (info.basic.param1) {
|
||||
case kSetReverb:
|
||||
// Already handled above
|
||||
break;
|
||||
case kMidiHold:
|
||||
// Check if the hold ID marker is the same as the hold ID
|
||||
// marker set for that song by cmdSetSoundHold.
|
||||
// If it is, loop back, but don't stop notes when jumping.
|
||||
// We need to wait for the delta of the current event before
|
||||
// jumping, thus the jump will be performed on the next
|
||||
// parseNextEvent() call, like with the signal set events.
|
||||
// In LSL6, room 360, song 381, this ends up jumping forward
|
||||
// one tick (the hold marker occurs at playtick 27, with
|
||||
// _loopTick being 15 and the event itself having a delta of
|
||||
// 13, total = 28) - bug #3614566.
|
||||
if (info.basic.param2 == _pSnd->hold) {
|
||||
_jumpToHoldTick = true;
|
||||
}
|
||||
break;
|
||||
case kUpdateCue:
|
||||
if (!_pSnd->inFastForward) {
|
||||
_dataincAdd = true;
|
||||
switch (_soundVersion) {
|
||||
case SCI_VERSION_0_EARLY:
|
||||
case SCI_VERSION_0_LATE:
|
||||
_dataincToAdd = info.basic.param2;
|
||||
break;
|
||||
case SCI_VERSION_1_EARLY:
|
||||
case SCI_VERSION_1_LATE:
|
||||
case SCI_VERSION_2_1:
|
||||
_dataincToAdd = 1;
|
||||
break;
|
||||
default:
|
||||
error("unsupported _soundVersion");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case kResetOnPause:
|
||||
_resetOnPause = info.basic.param2;
|
||||
break;
|
||||
// Unhandled SCI commands
|
||||
case 0x46: // LSL3 - binoculars
|
||||
case 0x61: // Iceman (AdLib?)
|
||||
case 0x73: // Hoyle
|
||||
case 0xD1: // KQ4, when riding the unicorn
|
||||
// Obscure SCI commands - ignored
|
||||
break;
|
||||
// Standard MIDI commands
|
||||
case 0x01: // mod wheel
|
||||
case 0x04: // foot controller
|
||||
case 0x07: // channel volume
|
||||
case 0x0A: // pan
|
||||
case 0x0B: // expression
|
||||
case 0x40: // sustain
|
||||
case 0x79: // reset all
|
||||
case 0x7B: // notes off
|
||||
// These are all handled by the music driver, so ignore them
|
||||
break;
|
||||
case 0x4B: // voice mapping
|
||||
// TODO: is any support for this needed at the MIDI parser level?
|
||||
warning("Unhanded SCI MIDI command 0x%x - voice mapping (parameter %d)", info.basic.param1, info.basic.param2);
|
||||
break;
|
||||
default:
|
||||
warning("Unhandled SCI MIDI command 0x%x (parameter %d)", info.basic.param1, info.basic.param2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
info.length = 0;
|
||||
break;
|
||||
|
||||
@ -649,34 +514,6 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
|
||||
info.length = readVLQ(_position._playPos);
|
||||
info.ext.data = _position._playPos;
|
||||
_position._playPos += info.length;
|
||||
if (info.ext.type == 0x2F) {// end of track reached
|
||||
if (_pSnd->loop)
|
||||
_pSnd->loop--;
|
||||
// QFG3 abuses the hold flag. Its scripts call kDoSoundSetHold,
|
||||
// but sometimes there's no hold marker in the associated songs
|
||||
// (e.g. song 110, during the intro). The original interpreter
|
||||
// treats this case as an infinite loop (bug #3311911).
|
||||
if (_pSnd->loop || _pSnd->hold > 0) {
|
||||
// TODO: this jump is also vulnerable to the same lockup as
|
||||
// the MIDI hold one above. However, we can't perform the
|
||||
// jump on the next tick like with the MIDI hold jump above,
|
||||
// as there aren't any subsequent MIDI events after this one.
|
||||
// This assert is here to detect cases where the song ends
|
||||
// up jumping forward, like with bug #3614566 (see above).
|
||||
assert(_loopTick + info.delta < _position._playTick);
|
||||
|
||||
uint32 extraDelta = info.delta;
|
||||
_pSnd->inFastForward = true;
|
||||
jumpToTick(_loopTick);
|
||||
_pSnd->inFastForward = false;
|
||||
_nextEvent.delta += extraDelta;
|
||||
} else {
|
||||
_pSnd->status = kSoundStopped;
|
||||
_pSnd->setSignal(SIGNAL_OFFSET);
|
||||
|
||||
debugC(4, kDebugLevelSound, "signal EOT");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
warning(
|
||||
@ -686,6 +523,190 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) {
|
||||
}// switch (info.command())
|
||||
}
|
||||
|
||||
void MidiParser_SCI::processEvent(const EventInfo &info, bool fireEvents) {
|
||||
if (!fireEvents) {
|
||||
// We don't do any processing that should be done while skipping events
|
||||
MidiParser::processEvent(info, fireEvents);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (info.command()) {
|
||||
case 0xC:
|
||||
if (info.channel() == 0xF) {// SCI special case
|
||||
if (info.basic.param1 != kSetSignalLoop) {
|
||||
// At least in kq5/french&mac the first scene in the intro has
|
||||
// a song that sets signal to 4 immediately on tick 0. Signal
|
||||
// isn't set at that point by sierra sci and it would cause the
|
||||
// castle daventry text to get immediately removed, so we
|
||||
// currently filter it. Sierra SCI ignores them as well at that
|
||||
// time. However, this filtering should only be performed for
|
||||
// SCI1 and newer games. Signalling is done differently in SCI0
|
||||
// though, so ignoring these signals in SCI0 games will result
|
||||
// in glitches (e.g. the intro of LB1 Amiga gets stuck - bug
|
||||
// #3297883). Refer to MusicEntry::setSignal() in sound/music.cpp.
|
||||
// FIXME: SSCI doesn't start playing at the very beginning
|
||||
// of the stream, but at a fixed location a few commands later.
|
||||
// That is probably why this signal isn't triggered
|
||||
// immediately there.
|
||||
bool skipSignal = false;
|
||||
if (_soundVersion >= SCI_VERSION_1_EARLY) {
|
||||
if (!_position._playTick) {
|
||||
skipSignal = true;
|
||||
switch (g_sci->getGameId()) {
|
||||
case GID_ECOQUEST2:
|
||||
// In Eco Quest 2 room 530 - gonzales is supposed to dance
|
||||
// WORKAROUND: we need to signal in this case on tick 0
|
||||
// this whole issue is complicated and can only be properly fixed by
|
||||
// changing the whole parser to a per-channel parser. SSCI seems to
|
||||
// start each channel at offset 13 (may be 10 for us) and only
|
||||
// starting at offset 0 when the music loops to the initial position.
|
||||
if (g_sci->getEngineState()->currentRoomNumber() == 530)
|
||||
skipSignal = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!skipSignal) {
|
||||
if (!_jumpingToTick) {
|
||||
_pSnd->setSignal(info.basic.param1);
|
||||
debugC(4, kDebugLevelSound, "signal %04x", info.basic.param1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_loopTick = _position._playTick;
|
||||
}
|
||||
|
||||
// Done with this event.
|
||||
return;
|
||||
}
|
||||
|
||||
// Break to let parent handle the rest.
|
||||
break;
|
||||
case 0xB:
|
||||
// Reference for some events:
|
||||
// http://wiki.scummvm.org/index.php/SCI/Specifications/Sound/SCI0_Resource_Format#Status_Reference
|
||||
// Handle common special events
|
||||
switch (info.basic.param1) {
|
||||
case kSetReverb:
|
||||
if (info.basic.param2 == 127) // Set global reverb instead
|
||||
_pSnd->reverb = _music->getGlobalReverb();
|
||||
else
|
||||
_pSnd->reverb = info.basic.param2;
|
||||
|
||||
((MidiPlayer *)_driver)->setReverb(_pSnd->reverb);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Handle events sent to the SCI special channel (15)
|
||||
if (info.channel() == 0xF) {
|
||||
switch (info.basic.param1) {
|
||||
case kSetReverb:
|
||||
// Already handled above
|
||||
return;
|
||||
case kMidiHold:
|
||||
// Check if the hold ID marker is the same as the hold ID
|
||||
// marker set for that song by cmdSetSoundHold.
|
||||
// If it is, loop back, but don't stop notes when jumping.
|
||||
if (info.basic.param2 == _pSnd->hold) {
|
||||
jumpToTick(_loopTick, false, false);
|
||||
// Done with this event.
|
||||
return;
|
||||
}
|
||||
return;
|
||||
case kUpdateCue:
|
||||
if (!_jumpingToTick) {
|
||||
int inc;
|
||||
switch (_soundVersion) {
|
||||
case SCI_VERSION_0_EARLY:
|
||||
case SCI_VERSION_0_LATE:
|
||||
inc = info.basic.param2;
|
||||
break;
|
||||
case SCI_VERSION_1_EARLY:
|
||||
case SCI_VERSION_1_LATE:
|
||||
case SCI_VERSION_2_1:
|
||||
inc = 1;
|
||||
break;
|
||||
default:
|
||||
error("unsupported _soundVersion");
|
||||
}
|
||||
_pSnd->dataInc += inc;
|
||||
debugC(4, kDebugLevelSound, "datainc %04x", inc);
|
||||
|
||||
}
|
||||
return;
|
||||
case kResetOnPause:
|
||||
_resetOnPause = info.basic.param2;
|
||||
return;
|
||||
// Unhandled SCI commands
|
||||
case 0x46: // LSL3 - binoculars
|
||||
case 0x61: // Iceman (AdLib?)
|
||||
case 0x73: // Hoyle
|
||||
case 0xD1: // KQ4, when riding the unicorn
|
||||
// Obscure SCI commands - ignored
|
||||
return;
|
||||
// Standard MIDI commands
|
||||
case 0x01: // mod wheel
|
||||
case 0x04: // foot controller
|
||||
case 0x07: // channel volume
|
||||
case 0x0A: // pan
|
||||
case 0x0B: // expression
|
||||
case 0x40: // sustain
|
||||
case 0x79: // reset all
|
||||
case 0x7B: // notes off
|
||||
// These are all handled by the music driver, so ignore them
|
||||
break;
|
||||
case 0x4B: // voice mapping
|
||||
// TODO: is any support for this needed at the MIDI parser level?
|
||||
warning("Unhanded SCI MIDI command 0x%x - voice mapping (parameter %d)", info.basic.param1, info.basic.param2);
|
||||
return;
|
||||
default:
|
||||
warning("Unhandled SCI MIDI command 0x%x (parameter %d)", info.basic.param1, info.basic.param2);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Break to let parent handle the rest.
|
||||
break;
|
||||
case 0xF: // META event
|
||||
if (info.ext.type == 0x2F) {// end of track reached
|
||||
if (_pSnd->loop)
|
||||
_pSnd->loop--;
|
||||
// QFG3 abuses the hold flag. Its scripts call kDoSoundSetHold,
|
||||
// but sometimes there's no hold marker in the associated songs
|
||||
// (e.g. song 110, during the intro). The original interpreter
|
||||
// treats this case as an infinite loop (bug #3311911).
|
||||
if (_pSnd->loop || _pSnd->hold > 0) {
|
||||
jumpToTick(_loopTick);
|
||||
|
||||
// Done with this event.
|
||||
return;
|
||||
|
||||
} else {
|
||||
_pSnd->status = kSoundStopped;
|
||||
_pSnd->setSignal(SIGNAL_OFFSET);
|
||||
|
||||
debugC(4, kDebugLevelSound, "signal EOT");
|
||||
}
|
||||
}
|
||||
|
||||
// Break to let parent handle the rest.
|
||||
break;
|
||||
|
||||
default:
|
||||
// Break to let parent handle the rest.
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Let parent handle the rest
|
||||
MidiParser::processEvent(info, fireEvents);
|
||||
}
|
||||
|
||||
byte MidiParser_SCI::getSongReverb() {
|
||||
assert(_track);
|
||||
|
||||
|
@ -89,6 +89,7 @@ public:
|
||||
|
||||
protected:
|
||||
void parseNextEvent(EventInfo &info);
|
||||
void processEvent(const EventInfo &info, bool fireEvents = true);
|
||||
byte *midiMixChannels();
|
||||
byte *midiFilterChannels(int channelMask);
|
||||
byte midiGetNextChannel(long ticker);
|
||||
@ -106,11 +107,6 @@ protected:
|
||||
byte _masterVolume; // the overall master volume (same for all tracks)
|
||||
byte _volume; // the global volume of the current track
|
||||
|
||||
bool _signalSet;
|
||||
int16 _signalToSet;
|
||||
bool _dataincAdd;
|
||||
int16 _dataincToAdd;
|
||||
bool _jumpToHoldTick;
|
||||
bool _resetOnPause;
|
||||
|
||||
bool _channelUsed[16];
|
||||
|
@ -521,11 +521,7 @@ void SciMusic::soundPlay(MusicEntry *pSnd) {
|
||||
pSnd->pMidiParser->jumpToTick(0);
|
||||
else {
|
||||
// Fast forward to the last position and perform associated events when loading
|
||||
pSnd->inFastForward = true;
|
||||
// we set this flag, so that the midiparser doesn't set any signals for scripts
|
||||
// if we don't do this, at least accessing the debugger will reset previously set signals
|
||||
pSnd->pMidiParser->jumpToTick(pSnd->ticker, true, true, true);
|
||||
pSnd->inFastForward = false;
|
||||
}
|
||||
|
||||
// Restore looping and hold
|
||||
@ -765,7 +761,6 @@ MusicEntry::MusicEntry() {
|
||||
resourceId = 0;
|
||||
|
||||
isQueued = false;
|
||||
inFastForward = false;
|
||||
|
||||
dataInc = 0;
|
||||
ticker = 0;
|
||||
|
@ -65,12 +65,11 @@ public:
|
||||
uint16 resourceId;
|
||||
|
||||
bool isQueued; // for SCI0 only!
|
||||
bool inFastForward; // if we are currently fast-forwarding (disables any signals to scripts)
|
||||
|
||||
uint16 dataInc;
|
||||
uint16 ticker;
|
||||
uint16 signal;
|
||||
byte priority;
|
||||
int16 priority; // must be int16, at least in Laura Bow 1, main music (object conMusic) uses priority -1
|
||||
uint16 loop;
|
||||
int16 volume;
|
||||
int16 hold;
|
||||
|
@ -116,7 +116,10 @@ void SoundCommandParser::processInitSound(reg_t obj) {
|
||||
newSound->resourceId = resourceId;
|
||||
newSound->soundObj = obj;
|
||||
newSound->loop = readSelectorValue(_segMan, obj, SELECTOR(loop));
|
||||
newSound->priority = readSelectorValue(_segMan, obj, SELECTOR(priority)) & 0xFF;
|
||||
if (_soundVersion <= SCI_VERSION_0_LATE)
|
||||
newSound->priority = readSelectorValue(_segMan, obj, SELECTOR(priority));
|
||||
else
|
||||
newSound->priority = readSelectorValue(_segMan, obj, SELECTOR(priority)) & 0xFF;
|
||||
if (_soundVersion >= SCI_VERSION_1_EARLY)
|
||||
newSound->volume = CLIP<int>(readSelectorValue(_segMan, obj, SELECTOR(vol)), 0, MUSIC_VOLUME_MAX);
|
||||
newSound->reverb = -1; // initialize to SCI invalid, it'll be set correctly in soundInitSnd() below
|
||||
@ -428,7 +431,7 @@ reg_t SoundCommandParser::kDoSoundUpdate(int argc, reg_t *argv, reg_t acc) {
|
||||
int16 objVol = CLIP<int>(readSelectorValue(_segMan, obj, SELECTOR(vol)), 0, 255);
|
||||
if (objVol != musicSlot->volume)
|
||||
_music->soundSetVolume(musicSlot, objVol);
|
||||
uint32 objPrio = readSelectorValue(_segMan, obj, SELECTOR(priority));
|
||||
int16 objPrio = readSelectorValue(_segMan, obj, SELECTOR(priority));
|
||||
if (objPrio != musicSlot->priority)
|
||||
_music->soundSetPriority(musicSlot, objPrio);
|
||||
return acc;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
This file was generated by the md5table tool on Thu Aug 15 12:47:39 2013
|
||||
This file was generated by the md5table tool on Fri Sep 27 05:44:12 2013
|
||||
DO NOT EDIT MANUALLY!
|
||||
*/
|
||||
|
||||
@ -121,6 +121,7 @@ static const MD5Table md5table[] = {
|
||||
{ "2723fea3dae0cb47768c424b145ae0e7", "tentacle", "Floppy", "Floppy", 7932, Common::EN_ANY, Common::kPlatformDOS },
|
||||
{ "27b2ef1653089fe5b897d9cc89ce784f", "balloon", "HE 80", "", -1, Common::RU_RUS, Common::kPlatformWindows },
|
||||
{ "27b3a4224ad63d5b04627595c1c1a025", "zak", "V2", "V2", -1, Common::IT_ITA, Common::kPlatformAmiga },
|
||||
{ "288fb75b24389733c29fa107fe8d44e8", "catalog", "HE CUP", "Preview", 10795148, Common::EN_USA, Common::kPlatformUnknown },
|
||||
{ "28d24a33448fab6795850bc9f159a4a2", "atlantis", "FM-TOWNS", "Demo", 11170, Common::JA_JPN, Common::kPlatformFMTowns },
|
||||
{ "28ef68ee3ed76d7e2ee8ee13c15fbd5b", "loom", "EGA", "EGA", 5748, Common::EN_ANY, Common::kPlatformDOS },
|
||||
{ "28f07458f1b6c24e118a1ea056827701", "lost", "HE 99", "", -1, Common::NL_NLD, Common::kPlatformUnknown },
|
||||
|
@ -553,15 +553,15 @@ bool Animation::persist(OutputPersistenceBlock &writer) {
|
||||
writer.write(_currentFrameTime);
|
||||
writer.write(_running);
|
||||
writer.write(_finished);
|
||||
writer.write(static_cast<uint>(_direction));
|
||||
writer.write(static_cast<uint32>(_direction));
|
||||
|
||||
// Je nach Animationstyp entweder das Template oder die Ressource speichern.
|
||||
if (_animationResourcePtr) {
|
||||
uint marker = 0;
|
||||
uint32 marker = 0;
|
||||
writer.write(marker);
|
||||
writer.writeString(_animationResourcePtr->getFileName());
|
||||
} else if (_animationTemplateHandle) {
|
||||
uint marker = 1;
|
||||
uint32 marker = 1;
|
||||
writer.write(marker);
|
||||
writer.write(_animationTemplateHandle);
|
||||
} else {
|
||||
@ -574,13 +574,13 @@ bool Animation::persist(OutputPersistenceBlock &writer) {
|
||||
|
||||
// The following is only there to for compatibility with older saves
|
||||
// resp. the original engine.
|
||||
writer.write((uint)1);
|
||||
writer.write((uint32)1);
|
||||
writer.writeString("LuaLoopPointCB");
|
||||
writer.write(getHandle());
|
||||
writer.write((uint)1);
|
||||
writer.write((uint32)1);
|
||||
writer.writeString("LuaActionCB");
|
||||
writer.write(getHandle());
|
||||
writer.write((uint)1);
|
||||
writer.write((uint32)1);
|
||||
writer.writeString("LuaDeleteCB");
|
||||
writer.write(getHandle());
|
||||
|
||||
@ -605,12 +605,12 @@ bool Animation::unpersist(InputPersistenceBlock &reader) {
|
||||
reader.read(_currentFrameTime);
|
||||
reader.read(_running);
|
||||
reader.read(_finished);
|
||||
uint direction;
|
||||
uint32 direction;
|
||||
reader.read(direction);
|
||||
_direction = static_cast<Direction>(direction);
|
||||
|
||||
// Animationstyp einlesen.
|
||||
uint marker;
|
||||
uint32 marker;
|
||||
reader.read(marker);
|
||||
if (marker == 0) {
|
||||
Common::String resourceFilename;
|
||||
@ -629,9 +629,9 @@ bool Animation::unpersist(InputPersistenceBlock &reader) {
|
||||
|
||||
// The following is only there to for compatibility with older saves
|
||||
// resp. the original engine.
|
||||
uint callbackCount;
|
||||
uint32 callbackCount;
|
||||
Common::String callbackFunctionName;
|
||||
uint callbackData;
|
||||
uint32 callbackData;
|
||||
|
||||
// loop point callback
|
||||
reader.read(callbackCount);
|
||||
|
@ -159,18 +159,18 @@ private:
|
||||
BACKWARD
|
||||
};
|
||||
|
||||
int _relX;
|
||||
int _relY;
|
||||
int32 _relX;
|
||||
int32 _relY;
|
||||
float _scaleFactorX;
|
||||
float _scaleFactorY;
|
||||
uint _modulationColor;
|
||||
uint _currentFrame;
|
||||
int _currentFrameTime;
|
||||
uint32 _modulationColor;
|
||||
uint32 _currentFrame;
|
||||
int32 _currentFrameTime;
|
||||
bool _running;
|
||||
bool _finished;
|
||||
Direction _direction;
|
||||
AnimationResource *_animationResourcePtr;
|
||||
uint _animationTemplateHandle;
|
||||
uint32 _animationTemplateHandle;
|
||||
bool _framesLocked;
|
||||
|
||||
ANIMATION_CALLBACK _loopPointCallback;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user