Initial commit

This commit is contained in:
2026-02-02 04:50:13 +01:00
commit 5b11698731
22592 changed files with 7677434 additions and 0 deletions

View File

@@ -0,0 +1,199 @@
/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "ags/plugins/ags_waves/ags_waves.h"
#include "ags/plugins/serializer.h"
#include "ags/ags.h"
#include "ags/globals.h"
namespace AGS3 {
namespace Plugins {
namespace AGSWaves {
AGSWaves::AGSWaves() : PluginBase(), Vars() {
_mixer = ::AGS::g_vm->_mixer;
}
const char *AGSWaves::AGS_GetPluginName() {
return "AGS Waves";
}
void AGSWaves::AGS_EngineStartup(IAGSEngine *engine) {
PluginBase::AGS_EngineStartup(engine);
if (_engine->version < 13)
_engine->AbortGame("Engine interface is too old, need newer version of AGS.");
StartingValues();
Character_GetX = _engine->GetScriptFunctionAddress("Character::get_X");
Character_GetY = _engine->GetScriptFunctionAddress("Character::get_Y");
Character_ID = _engine->GetScriptFunctionAddress("Character::ID");
// Newer versions (after the 2025/04 update) no longer use the plugin to play sounds, so these
// bindings are not needed
if (_G(loaded_game_file_version) < 3060021) {
SCRIPT_METHOD(SFX_Play, AGSWaves::SFX_Play);
SCRIPT_METHOD(SFX_SetVolume, AGSWaves::SFX_SetVolume);
SCRIPT_METHOD(SFX_GetVolume, AGSWaves::SFX_GetVolume);
SCRIPT_METHOD(Music_Play, AGSWaves::Music_Play);
SCRIPT_METHOD(Music_GetVolume, AGSWaves::Music_GetVolume);
SCRIPT_METHOD(Music_SetVolume, AGSWaves::Music_SetVolume);
SCRIPT_METHOD(SFX_Stop, AGSWaves::SFX_Stop);
SCRIPT_METHOD(SFX_SetPosition, AGSWaves::SFX_SetPosition);
SCRIPT_METHOD(SFX_SetGlobalVolume, AGSWaves::SFX_SetGlobalVolume);
SCRIPT_METHOD(Load_SFX, AGSWaves::Load_SFX);
SCRIPT_METHOD(Audio_Apply_Filter, AGSWaves::Audio_Apply_Filter);
SCRIPT_METHOD(Audio_Remove_Filter, AGSWaves::Audio_Remove_Filter);
SCRIPT_METHOD(SFX_AllowOverlap, AGSWaves::SFX_AllowOverlap);
SCRIPT_METHOD(SFX_Filter, AGSWaves::SFX_Filter);
}
SCRIPT_METHOD(DrawScreenEffect, AGSWaves::DrawScreenEffect);
SCRIPT_METHOD(DrawBlur, AGSWaves::DrawBlur);
SCRIPT_METHOD(DrawTunnel, AGSWaves::DrawTunnel);
SCRIPT_METHOD(DrawCylinder, AGSWaves::DrawCylinder);
SCRIPT_METHOD(DrawForceField, AGSWaves::DrawForceField);
SCRIPT_METHOD(Grayscale, AGSWaves::Grayscale);
SCRIPT_METHOD(ReadWalkBehindIntoSprite, AGSWaves::ReadWalkBehindIntoSprite);
SCRIPT_METHOD(AdjustSpriteFont, AGSWaves::AdjustSpriteFont);
SCRIPT_METHOD(SpriteGradient, AGSWaves::SpriteGradient);
SCRIPT_METHOD(Outline, AGSWaves::Outline);
SCRIPT_METHOD(OutlineOnly, AGSWaves::OutlineOnly);
SCRIPT_METHOD(SaveVariable, AGSWaves::SaveVariable);
SCRIPT_METHOD(ReadVariable, AGSWaves::ReadVariable);
SCRIPT_METHOD(GameDoOnceOnly, AGSWaves::GameDoOnceOnly);
SCRIPT_METHOD(SetGDState, AGSWaves::SetGDState);
SCRIPT_METHOD(GetGDState, AGSWaves::GetGDState);
SCRIPT_METHOD(ResetAllGD, AGSWaves::ResetAllGD);
SCRIPT_METHOD(SpriteSkew, AGSWaves::SpriteSkew);
SCRIPT_METHOD(FireUpdate, AGSWaves::FireUpdate);
SCRIPT_METHOD(WindUpdate, AGSWaves::WindUpdate);
SCRIPT_METHOD(SetWindValues, AGSWaves::SetWindValues);
SCRIPT_METHOD(ReturnWidth, AGSWaves::ReturnWidth);
SCRIPT_METHOD(ReturnHeight, AGSWaves::ReturnHeight);
SCRIPT_METHOD(ReturnNewHeight, AGSWaves::ReturnNewHeight);
SCRIPT_METHOD(ReturnNewWidth, AGSWaves::ReturnNewWidth);
SCRIPT_METHOD(Warper, AGSWaves::Warper);
SCRIPT_METHOD(SetWarper, AGSWaves::SetWarper);
SCRIPT_METHOD(RainUpdate, AGSWaves::RainUpdate);
SCRIPT_METHOD(BlendTwoSprites, AGSWaves::BlendTwoSprites);
SCRIPT_METHOD(Blend, AGSWaves::Blend);
SCRIPT_METHOD(Dissolve, AGSWaves::Dissolve);
SCRIPT_METHOD(ReverseTransparency, AGSWaves::ReverseTransparency);
SCRIPT_METHOD(NoiseCreator, AGSWaves::NoiseCreator);
SCRIPT_METHOD(TintProper, AGSWaves::TintProper);
SCRIPT_METHOD(GetWalkbehindBaserine, AGSWaves::GetWalkbehindBaserine);
SCRIPT_METHOD(SetWalkbehindBaserine, AGSWaves::SetWalkbehindBaserine);
engine->RequestEventHook(AGSE_PREGUIDRAW);
engine->RequestEventHook(AGSE_PRESCREENDRAW);
engine->RequestEventHook(AGSE_SAVEGAME);
engine->RequestEventHook(AGSE_RESTOREGAME);
engine->RequestEventHook(AGSE_ENTERROOM);
}
AGSWaves::~AGSWaves() {
stopAllSounds();
}
void AGS_EngineShutdown() {
}
int64 AGSWaves::AGS_EngineOnEvent(int event, NumberPtr data) {
switch (event) {
case AGSE_PREGUIDRAW:
// Update();
break;
case AGSE_RESTOREGAME: {
stopAllSounds();
Serializer s(_engine, data, true);
for (int j = 0; j < 500 - 1; ++j) {
s.syncAsInt(SFX[j]._repeat);
s.syncAsInt(SFX[j]._volume);
s.syncAsInt(SFX[j]._playing);
}
break;
}
case AGSE_SAVEGAME: {
Serializer s(_engine, data, true);
for (int j = 0; j < 500 - 1; ++j) {
SFX[j]._playing = _mixer->isSoundHandleActive(SFX[j]._soundHandle);
s.syncAsInt(SFX[j]._repeat);
s.syncAsInt(SFX[j]._volume);
s.syncAsInt(SFX[j]._playing);
}
break;
}
case AGSE_PRESCREENDRAW:
// Get screen size once here.
_engine->GetScreenDimensions(&screen_width, &screen_height, &screen_color_depth);
//_engine->UnrequestEventHook(AGSE_SAVEGAME);
//_engine->UnrequestEventHook(AGSE_RESTOREGAME);
break;
case AGSE_ENTERROOM:
// The original unloads sfx that are not playing and are not on repeat
// I don't think we need to do anything here.
break;
default:
break;
}
return 0;
}
void AGSWaves::StartingValues() {
GeneralAudio.NumOfChannels = 0;
GeneralAudio.Initialized = false;
GeneralAudio.Disabled = false;
GeneralAudio.FilterFrequency = 10;
GeneralAudio.SoundValue = 0;
MFXStream.ID = 0;
MFXStream.Channel = -1;
MFXStream.Switch = false;
MFXStream.FadeTime = 0;
MFXStream.FadeRate = 0.0;
MFXStream.FadeVolume = 0.0;
MFXStream.HaltedZero = false;
MFXStream.HaltedOne = false;
int j = 0;
while (j < 2) {
globalStream[j].Filename = nullptr;
globalStream[j].repeat = 0;
globalStream[j].volume = 0;
globalStream[j].Vorbis = nullptr;
globalStream[j].fix_click = false;
j++;
}
}
} // namespace AGSWaves
} // namespace Plugins
} // namespace AGS3

View File

@@ -0,0 +1,189 @@
/* 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 3 of the License, or
* 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_PLUGINS_AGS_WAVES_AGS_WAVES_H
#define AGS_PLUGINS_AGS_WAVES_AGS_WAVES_H
#include "audio/mixer.h"
#include "common/fs.h"
#include "ags/plugins/ags_plugin.h"
#include "ags/plugins/ags_waves/vars.h"
namespace AGS3 {
namespace Plugins {
namespace AGSWaves {
class AGSWaves : public PluginBase, public Vars {
SCRIPT_HASH(AGSWaves)
private:
Audio::Mixer *_mixer;
private:
void DrawScreenEffect(ScriptMethodParams &params);
void SFX_Play(ScriptMethodParams &params);
void SFX_SetVolume(ScriptMethodParams &params);
void SFX_GetVolume(ScriptMethodParams &params);
void Music_Play(ScriptMethodParams &params);
void Music_GetVolume(ScriptMethodParams &params);
void Music_SetVolume(ScriptMethodParams &params);
void SFX_Stop(ScriptMethodParams &params);
void SFX_SetPosition(ScriptMethodParams &params);
void SFX_SetGlobalVolume(ScriptMethodParams &params);
void Load_SFX(ScriptMethodParams &params);
void Audio_Apply_Filter(ScriptMethodParams &params);
void Audio_Remove_Filter(ScriptMethodParams &params);
void SFX_AllowOverlap(ScriptMethodParams &params);
void SFX_Filter(ScriptMethodParams &params);
void DrawBlur(ScriptMethodParams &params);
void DrawTunnel(ScriptMethodParams &params);
void DrawCylinder(ScriptMethodParams &params);
void DrawForceField(ScriptMethodParams &params);
void Grayscale(ScriptMethodParams &params);
void ReadWalkBehindIntoSprite(ScriptMethodParams &params);
void AdjustSpriteFont(ScriptMethodParams &params);
void SpriteGradient(ScriptMethodParams &params);
void Outline(ScriptMethodParams &params);
void OutlineOnly(ScriptMethodParams &params);
void SaveVariable(ScriptMethodParams &params);
void ReadVariable(ScriptMethodParams &params);
void GameDoOnceOnly(ScriptMethodParams &params);
void SetGDState(ScriptMethodParams &params);
void GetGDState(ScriptMethodParams &params);
void ResetAllGD(ScriptMethodParams &params);
void SpriteSkew(ScriptMethodParams &params);
void FireUpdate(ScriptMethodParams &params);
void WindUpdate(ScriptMethodParams &params);
void SetWindValues(ScriptMethodParams &params);
void ReturnWidth(ScriptMethodParams &params);
void ReturnHeight(ScriptMethodParams &params);
void ReturnNewHeight(ScriptMethodParams &params);
void ReturnNewWidth(ScriptMethodParams &params);
void Warper(ScriptMethodParams &params);
void SetWarper(ScriptMethodParams &params);
void RainUpdate(ScriptMethodParams &params);
void BlendTwoSprites(ScriptMethodParams &params);
void Blend(ScriptMethodParams &params);
void Dissolve(ScriptMethodParams &params);
void ReverseTransparency(ScriptMethodParams &params);
void NoiseCreator(ScriptMethodParams &params);
void TintProper(ScriptMethodParams &params);
void GetWalkbehindBaserine(ScriptMethodParams &params);
void SetWalkbehindBaserine(ScriptMethodParams &params);
private:
void StartingValues();
void Update();
void CastWave(int delayMax, int PixelsWide, int n);
void DrawEffect(int sprite_a, int sprite_b, int id, int n);
int Random(int threshold);
inline static int getRcolor(int color) {
return ((color >> 16) & 0xFF);
}
inline static int getGcolor(int color) {
return ((color >> 8) & 0xFF);
}
inline static int getBcolor(int color) {
return ((color >> 0) & 0xFF);
}
inline static int getAcolor(int color) {
return ((color >> 24) & 0xFF);
}
static int BlendColor(int Ln, int Bn, int perc) {
return ((Ln < 128) ? (2 * Bn * Ln / perc) : (perc - 2 * (perc - Bn) * (perc - Ln) / perc));
}
static int BlendColorScreen(int Ln, int Bn, int perc) {
return (Bn == perc) ? Bn :
MIN(perc, (Ln * Ln / (perc - Bn)));
}
static int SetColorRGBA(int r, int g, int b, int a);
static int ConvertColorToGrayScale(int color);
static bool IsPixelTransparent(int color);
float noiseField(float tx, float ty, float tz);
int IntersectLines(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4);
static inline float fracts(float value) {
return value - floor(value);
}
static inline float lerp(float x, float y, float fn) {
return x * (1.0 - fn) + y * fn;
}
static inline float hasher(float n) {
return fracts(sin(n) * 153.5453123);
}
static float min4(float m1, float m2, float m3, float m4) {
return MIN(MIN(m1, m2), MIN(m3, m4));
}
static float max4(float m1, float m2, float m3, float m4) {
return MAX(MAX(m1, m2), MAX(m3, m4));
}
// Weather
void DrawLineCustom(int x1, int y1, int x2, int y2, int graphic, int setR, int setG, int setB, int setA, int TranDif);
void CreateParticle(int xx, int yy, int ForceX, int ForceY);
void CreateParticle2(int xx, int yy, int ForceX, int ForceY);
void CreateParticleF(int xx, int yy, int ForceX, int ForceY);
void CreateDustParticle(int xx, int yy);
void CreateRainParticleMid(int x, int y, int fx, int fy, int maxpart);
void CreateRainParticleFore(int x, int y, int fx, int fy, int maxpart);
void CreateRainParticleBack(int x, int y, int fx, int fy, int maxpart);
// Sound
/**
* Plays a sound from the sounds.sfx in the Sounds/ folder
* @param soundToPlay The sound to play
* @param repeat Times to repeat, -1 for indefine
*/
void PlaySFX(int SoundToPlay, int repeat);
/**
* Stops a playing sound effect
*/
void StopSFX(int sfxNum);
/**
* Loads a ScummVM OGG stream for playback
*/
Audio::AudioStream *loadOGG(const Common::ArchiveMemberPtr &member);
void playStream(Audio::Mixer::SoundType type, Audio::SoundHandle *handle, Audio::AudioStream *stream, int repeat);
void stopAllSounds();
void GlitchFix();
void ApplyFilter(int SetFrequency);
void SetFilterFrequency(int setFrequency);
void MusicPlay(int MusicToPlay, int repeat, int fadeinMS, int fadeoutMS, int pos, bool forceplay, bool fixclick);
public:
AGSWaves();
virtual ~AGSWaves();
const char *AGS_GetPluginName() override;
void AGS_EngineStartup(IAGSEngine *engine) override;
int64 AGS_EngineOnEvent(int event, NumberPtr data) override;
};
} // namespace AGSWaves
} // namespace Plugins
} // namespace AGS3
#endif

View File

@@ -0,0 +1,133 @@
/* 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 3 of the License, or
* 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/util.h"
#include "ags/plugins/ags_waves/ags_waves.h"
namespace AGS3 {
namespace Plugins {
namespace AGSWaves {
void AGSWaves::SaveVariable(ScriptMethodParams &params) {
PARAMS2(const char *, value, int, id);
if (GameDatavalue[id] != nullptr) {
free(GameDatavalue[id]);
}
if (value != nullptr) {
GameDatavalue[id] = scumm_strdup(value);
} else {
GameDatavalue[id] = nullptr;
}
}
void AGSWaves::ReadVariable(ScriptMethodParams &params) {
PARAMS1(int, id);
if (GameDatavalue[id] == nullptr) {
params._result = _engine->CreateScriptString("");
} else {
params._result = _engine->CreateScriptString(GameDatavalue[id]);
}
}
void AGSWaves::GameDoOnceOnly(ScriptMethodParams &params) {
// PARAMS1(const char *, value);
GetGDState(params);
if (params._result) {
// Set state to false
params.push_back(false);
SetGDState(params);
params._result = true;
} else {
params._result = false;
}
}
void AGSWaves::SetGDState(ScriptMethodParams &params) {
PARAMS2(const char *, value, bool, setValue);
int id = -1;
for (int i = 0; i <= usedTokens; i++) {
if (Token[i] != nullptr && strcmp(Token[i], value) == 0) {
id = i;
TokenUnUsed[i] = setValue;
i = usedTokens + 1;
}
}
if (id == -1) {
// It doesn't find it while trying to set its state
// create the thing with said state
id = usedTokens;
TokenUnUsed[id] = setValue;
if (Token[id] != nullptr)
free(Token[id]);
Token[id] = scumm_strdup(value);
usedTokens++;
}
}
void AGSWaves::GetGDState(ScriptMethodParams &params) {
PARAMS1(const char *, value);
int id = -1;
for (int i = 0; i <= usedTokens; i++) {
if (Token[i] != nullptr && strcmp(Token[i], value) == 0) {
id = i;
i = usedTokens + 1;
}
}
if (id == -1) {
params._result = true;
} else {
params._result = TokenUnUsed[id];
}
}
void AGSWaves::ResetAllGD(ScriptMethodParams &params) {
for (int i = 0; i <= usedTokens; i++) {
if (Token[i] != nullptr)
free(Token[i]);
Token[i] = nullptr;
TokenUnUsed[i] = true;
}
usedTokens = 0;
}
void AGSWaves::GetWalkbehindBaserine(ScriptMethodParams &params) {
PARAMS1(int, id);
params._result = Walkbehind[id];
}
void AGSWaves::SetWalkbehindBaserine(ScriptMethodParams &params) {
PARAMS2(int, id, int, base);
Walkbehind[id] = base;
}
} // namespace AGSWaves
} // namespace Plugins
} // namespace AGS3

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,295 @@
/* 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 3 of the License, or
* 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "audio/decoders/vorbis.h"
#include "common/util.h"
#include "ags/plugins/ags_waves/ags_waves.h"
#include "ags/shared/util/stdio_compat.h"
#include "ags/ags.h"
namespace AGS3 {
namespace Plugins {
namespace AGSWaves {
//const float PI = 3.14159265f;
void AGSWaves::SFX_Play(ScriptMethodParams &params) {
PARAMS2(int, sfxNum, int, repeat);
SoundEffect &effect = SFX[sfxNum];
if (_mixer->isSoundHandleActive(effect._soundHandle)) {
if (effect._allow == 1) {
// In this case we should start the sound on a new channel, not stopping
// the one currently playing.
warning("TODO: play overlapping sound with SFX_Play");
}
return;
}
_mixer->stopHandle(effect._soundHandle);
Common::ArchiveMemberPtr member = getFile(Common::String::format("sounds/sound%d.sfx", sfxNum).c_str());
Audio::AudioStream *sound = loadOGG(member);
if (sound != nullptr) {
effect._volume = 255;
playStream(Audio::Mixer::kSFXSoundType, &effect._soundHandle, sound, repeat);
if (OGG_Filter && effect._filter && effect._volume > 1) {
warning("TODO: Mix_RegisterEffect(grabChan, LPEffect, NULL, NULL);");
}
effect._repeat = repeat;
} else {
debug(0, "AGSWaves::SFX_Play couldn't load sfx %d", sfxNum);
}
}
void AGSWaves::SFX_SetVolume(ScriptMethodParams &params) {
PARAMS2(int, sfxNum, int, volume);
SoundEffect &effect = SFX[sfxNum];
_mixer->setChannelVolume(effect._soundHandle, volume);
effect._volume = volume;
}
void AGSWaves::SFX_GetVolume(ScriptMethodParams &params) {
PARAMS1(int, sfxNum);
SoundEffect &effect = SFX[sfxNum];
params._result = _mixer->getChannelVolume(effect._soundHandle);
}
void AGSWaves::Music_Play(ScriptMethodParams &params) {
PARAMS6(int, MFX, int, repeat, int, fadeinMS, int, fadeoutMS, int, Position, bool, fixclick);
MusicPlay(MFX, repeat, fadeinMS, fadeoutMS, Position, false, fixclick);
}
void AGSWaves::Music_SetVolume(ScriptMethodParams &params) {
PARAMS1(int, volume);
_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume);
}
void AGSWaves::Music_GetVolume(ScriptMethodParams &params) {
params._result = _mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType);
}
void AGSWaves::SFX_Stop(ScriptMethodParams &params) {
PARAMS1(int, sfxNum); //, int, fademsOUT);
StopSFX(sfxNum);
}
void AGSWaves::SFX_SetPosition(ScriptMethodParams &params) {
#if 0
PARAMS4(int, sfxNum, int, xS, int, yS, int, intensity);
SoundEffect &effect = SFX[sfxNum];
if (_mixer->isSoundHandleActive(effect._soundHandle)) {
int angle = 0;
int dist = 0;
if (xS != 0 && yS != 0) {
int pid = _engine->GetPlayerCharacter();
playerCharacter = _engine->GetCharacter(pid);
int x1 = Character_GetX((intptr_t)playerCharacter);
int y1 = Character_GetY((intptr_t)playerCharacter);
int x2 = xS;
int y2 = yS;
int defx = (x1 - x2) * (x1 - x2);
int defy = (y1 - y2) * (y1 - y2);
float SquareRoot = sqrt(float(defx + defy));
dist = int(SquareRoot) - intensity;
if (dist > 255) dist = 255;
if (dist < 0) dist = 0;
float xDiff = float(x2 - x1);
float yDiff = float(y2 - y1);
float at2 = atan2(yDiff, xDiff);
float angles = (at2 * 360.0 / PI);
angle = int(angles);//%360;
}
// TODO: Change Mix_SetPosition to ScummVM equivalent
//Mix_SetPosition(id, angle, dist);
(void)angle;
(void)dist;
}
#endif
debug(0, "TODO: SFX_Setposition positional sound not yet implemented");
}
void AGSWaves::SFX_SetGlobalVolume(ScriptMethodParams &params) {
PARAMS1(int, volume);
_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, volume);
}
void AGSWaves::Load_SFX(ScriptMethodParams &params) {
// PARAMS1(int, sfxNum);
// LoadSFX(sfxNum);
}
void AGSWaves::Audio_Apply_Filter(ScriptMethodParams &params) {
PARAMS1(int, Frequency);
GlitchFix();
ApplyFilter(Frequency);
}
void AGSWaves::Audio_Remove_Filter(ScriptMethodParams &params) {
}
void AGSWaves::SFX_AllowOverlap(ScriptMethodParams &params) {
PARAMS2(int, sfxNum, int, allow);
SFX[sfxNum]._allow = allow;
}
void AGSWaves::SFX_Filter(ScriptMethodParams &params) {
PARAMS2(int, sfxNum, int, enable);
// THIS ENABLES/DISABLES the SFX LOW PASS FILTER,
// I think by default all sound effects are affected by low pass, but there are some that i've manually disabled from being affected by it with this command
SFX[sfxNum]._filter = enable;
}
Audio::AudioStream *AGSWaves::loadOGG(const Common::ArchiveMemberPtr &member) {
#ifdef USE_VORBIS
if (member) {
Audio::AudioStream *stream = Audio::makeVorbisStream(member->createReadStream(), DisposeAfterUse::YES);
return stream;
}
#endif
return nullptr;
}
void AGSWaves::playStream(Audio::Mixer::SoundType type, Audio::SoundHandle *handle, Audio::AudioStream *stream, int repeat) {
if (!handle || !stream)
return;
if (repeat != 0) {
Audio::SeekableAudioStream *sas =
dynamic_cast<Audio::SeekableAudioStream *>(stream);
assert(sas);
// -1 for infinite, >0 number of successive repeats
Audio::LoopingAudioStream *las =
new Audio::LoopingAudioStream(sas, repeat + 1);
_mixer->playStream(type, handle, las);
} else {
_mixer->playStream(type, handle, stream);
}
}
void AGSWaves::StopSFX(int sfxNum) {
SoundEffect &effect = SFX[sfxNum];
_mixer->stopHandle(effect._soundHandle);
effect._playing = 0;
effect._repeat = 0;
effect._channel = -2;
}
void AGSWaves::stopAllSounds() {
for (int i = 0; i < 500; ++i)
StopSFX(i);
_mixer->stopHandle(MFXStream._soundHandle);
}
void AGSWaves::GlitchFix() {
// TODO: Implementation
}
void AGSWaves::ApplyFilter(int setFrequency) {
// THIS TURNS ON THE LOW PASS FILTER
OGG_Filter = true;
GeneralAudio.FilterFrequency = setFrequency;
SetFilterFrequency(setFrequency);
}
void AGSWaves::SetFilterFrequency(int setFrequency) {
// TODO: Implementation
}
void AGSWaves::MusicPlay(int MusicToPlay, int repeat, int fadeinMS, int fadeoutMS, int pos, bool forceplay, bool fixclick) {
if (GeneralAudio.Disabled) {
return;
}
// Stop any previous music
_mixer->stopHandle(MFXStream._soundHandle);
// Load OGG file for music
Common::ArchiveMemberPtr member = getFile(Common::String::format("music/music%d.mfx", MusicToPlay).c_str());
Audio::AudioStream *musicStream = loadOGG(member);
if (!musicStream)
return;
bool samefile = currentMusic != MusicToPlay;
if (forceplay)
samefile = true;
if (samefile) {
currentMusicRepeat = repeat;
currentMusicFadein = fadeinMS;
currentMusic = MusicToPlay;
if (!MFXStream.Switch) {
MFXStream.Channel = 0;
playStream(Audio::Mixer::kMusicSoundType,
&MFXStream._soundHandle, musicStream, repeat);
MFXStream.ID = MusicToPlay;
MFXStream.FadeTime = (fadeinMS / 1000) * 40;
MFXStream.FadeRate = (float)_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType)
/ (float)MFXStream.FadeTime;
MFXStream.FadeVolume = 0.0;
MFXStream.HaltedZero = false;
//MusicVolCanBeAdjusted=true;
} else {
MFXStream.HaltedOne = false;
MFXStream.Channel = 1;
playStream(Audio::Mixer::kMusicSoundType,
&MFXStream._soundHandle, musicStream, repeat);
MFXStream.ID = MusicToPlay;
MFXStream.FadeTime = (fadeoutMS / 1000) * 40;
MFXStream.FadeVolume = 0.0;//float(MusicGetVolume());
MFXStream.FadeRate = (float)_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType)
/ (float)MFXStream.FadeTime;
//MusicVolCanBeAdjusted=false;
}
MFXStream.Switch = !MFXStream.Switch;
}
}
} // namespace AGSWaves
} // namespace Plugins
} // namespace AGS3

View File

@@ -0,0 +1,225 @@
/* 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 3 of the License, or
* 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, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef AGS_PLUGINS_AGS_WAVES_VARS_H
#define AGS_PLUGINS_AGS_WAVES_VARS_H
#include "audio/audiostream.h"
namespace AGS3 {
namespace Plugins {
namespace AGSWaves {
#define texWidth 240
#define texHeight 240
#define screenWidth 640
#define screenHeight 360
// TODO: Dummy definitions that need to be fixed
typedef void *stb_vorbis;
typedef void *Mix_Chunk;
typedef int SDL_AudioSpec;
typedef int SDL_AudioDeviceID;
struct Particle {
int x;
int y;
int transp;
int life;
bool active;
int dx;
int dy;
int mlay;
int timlay;
int movedport;
int translay;
int translayHold;
int width;
int height;
int fx;
int fy;
bool doingcircle;
float angle;
float radius;
int doingCircleChance;
float angleLay;
int frame;
float anglespeed;
};
/*---------------------------------------------*/
typedef int (*SCAPI_CHARACTER_GETX)(AGSCharacter *ch);
typedef int (*SCAPI_CHARACTER_GETY)(AGSCharacter *ch);
typedef int (*SCAPI_CHARACTER_ID) (AGSCharacter *ch);
//WAVE SOUNDS FILES
struct SoundEffect {
Audio::SoundHandle _soundHandle;
int _repeat = 0;
int _volume = 0;
int _allow = 0;
int _channel = 0;
int _filter = 0;
int _playing = 0;
};
struct Aud {
int NumOfChannels = 0;
bool Initialized = false;
bool Disabled = false;
int FilterFrequency = 0;
int SoundValue = 0;
};
struct Mus {
int ID = 0;
int FadeTime = 0;
float FadeRate = 0;
float FadeVolume = 0;
int Channel = 0;
bool Switch = 0;
bool HaltedZero = 0;
bool HaltedOne = 0;
Audio::SoundHandle _soundHandle;
};
struct RainParticle {
int x = 0;
int y = 0;
int fx = 0;
int fy = 0;
int life = 0;
int trans = 0;
bool active = 0;
int translay = 0;
int transhold = 0;
};
struct MusicStream {
int volume = 0;
const char *Filename = nullptr;
int repeat = 0;
stb_vorbis *Vorbis = 0;
bool fix_click = false;
};
struct DustParticle {
int x = 0;
int y = 0;
int transp = 0;
int life = 0;
bool active = false;
int dx = 0;
int dy = 0;
int mlay = 0;
int timlay = 0;
int movedport = 0;
int translay = 0;
int translayHold = 0;
};
struct Vars {
int32 screen_width = 640;
int32 screen_height = 360;
int32 screen_color_depth = 32;
AGSCharacter *playerCharacter = nullptr;
PluginMethod Character_GetX;
PluginMethod Character_GetY;
PluginMethod Character_ID;
SoundEffect SFX[500];
RainParticle RainParticles[400];
RainParticle RainParticlesFore[400];
RainParticle RainParticlesBack[800];
Aud GeneralAudio;
Mus MFXStream;
int currentMusic = -1;
int currentMusicRepeat = -1;
int currentMusicFadein = 0;
double xv[3];
double yv[3];
double xvOGG[3];
double yvOGG[3];
Particle particles[110];
Particle particlesF[10];
Particle particles2[12];
int WForceX[400];
int WForceY[400];
int raysizeF = 4;
int dsizeF = 0;
int raysize = 100;
int dsize = 0;
int raysize2 = 12;
int dsize2 = 0;
int creationdelayf = 0;
int ww;
int hh;
int proom;
int prevroom;
bool OGG_Filter = false;
SDL_AudioSpec spec[2];
MusicStream globalStream[2];
SDL_AudioDeviceID getDevice[2];
bool AudioEnabled = false;
float ix = 0, iy = 0, ua = 0;
float b_time[5];
float d_time = 0;
// Y-coordinate first because we use horizontal scanlines
uint32 texture[texHeight][texWidth];
int distanceTable[screenHeight][screenWidth];
int angleTable[screenHeight][screenWidth];
bool generateonce = false;
DustParticle dusts[200];
int waitBy = 6;
int raysizeDust = 200;
int dsizeDust = 0;
int creationdelay = 0;
int Walkbehind[20];
char *GameDatavalue[40000];
char *Token[10000];
int TokenUnUsed[10000];
int usedTokens = 0;
int dY[30];
int tDy[30];
int direction[30];
// Warper fields
int _newWidth = 0, _newHeight = 0;
int _y2 = 0;
int _x3 = 0, _y3 = 0;
int _x4 = 0, _y4 = 0;
};
} // namespace AGSWaves
} // namespace Plugins
} // namespace AGS3
#endif

View File

@@ -0,0 +1,185 @@
/* 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 3 of the License, or
* 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, see <http://www.gnu.org/licenses/>.
*
*/
#include "common/util.h"
#include "ags/plugins/ags_waves/ags_waves.h"
namespace AGS3 {
namespace Plugins {
namespace AGSWaves {
void AGSWaves::ReturnNewHeight(ScriptMethodParams &params) {
params._result = _newHeight;
}
void AGSWaves::ReturnNewWidth(ScriptMethodParams &params) {
params._result = _newWidth;
}
void AGSWaves::Warper(ScriptMethodParams &params) {
PARAMS5(int, swarp, int, sadjust, int, x1, int, y1, int, x2);
ix = 0.0;
iy = 0.0;
ua = 0.0;
// some precautions against non-positive values for width and height
float ax = float(x1), ay = float(y1);
float bx = float(x2), by = float(_y2);
float cx = float(_x3), cy = float(_y3);
float dx = float(_x4), dy = float(_y4);
int w = int(max4(ax, bx, cx, dx)) + 1;
int h = int(max4(ay, by, cy, dy)) + 1;
BITMAP *refsrc = _engine->GetSpriteGraphic(swarp);
int32 refsrc_width = 640;
int32 refsrc_height = 360;
int32 refsrc_depth = 32;
_engine->GetBitmapDimensions(refsrc, &refsrc_width, &refsrc_height, &refsrc_depth);
unsigned int **refsprite_pixels = (unsigned int **)_engine->GetRawBitmapSurface(refsrc);
_engine->ReleaseBitmapSurface(refsrc);
// create temporary sprite holding the warped version
BITMAP *resizeb = _engine->GetSpriteGraphic(sadjust);
int32 src_width = 640;
int32 src_height = 360;
int32 src_depth = 32;
_engine->GetBitmapDimensions(resizeb, &src_width, &src_height, &src_depth);
unsigned int **sprite_pixels = (unsigned int **)_engine->GetRawBitmapSurface(resizeb);
int ow = refsrc_width, oh = refsrc_height;
int x, y; // pixel coords
float fx, fy; // original sprite's in between pixel coords
int il;
// calculate intersections of opposing sides
float orx_x, orx_y, ory_x, ory_y;
bool xp = false, yp = false; // parallel sides?
// AC and BD to get intersection of all "vertical lines"
il = IntersectLines(ax, ay, cx, cy, bx, by, dx, dy);
if (il == 0) {
// parallel sides, store directional vector
orx_x = cx - ax;
orx_y = cy - ay;
xp = true;
} else {
// store intersection of sides
orx_x = ix;
orx_y = iy;
}
// AB and CD to get intersection of all "horizontal lines"
il = IntersectLines(ax, ay, bx, by, cx, cy, dx, dy);
if (il == 0) {
// parallel sides, store directional vector
ory_x = bx - ax;
ory_y = by - ay;
yp = true;
} else {
// store intersection of sides
ory_x = ix;
ory_y = iy;
}
int xm = int(min4(ax, bx, cx, dx)); // x loop starts here
y = int(min4(ay, by, cy, dy));
while (y < h) {
x = xm;
while (x < w) {
// calculate original pixel
// x:
if (xp) il = IntersectLines(ax, ay, bx, by, float(x), float(y), float(x) + orx_x, float(y) + orx_y);
else il = IntersectLines(ax, ay, bx, by, float(x), float(y), orx_x, orx_y);
fx = float(ow - 1) * ua;
float ux = ua;
// y:
if (yp) il = IntersectLines(ax, ay, cx, cy, float(x), float(y), float(x) + ory_x, float(y) + ory_y);
else il = IntersectLines(ax, ay, cx, cy, float(x), float(y), ory_x, ory_y);
fy = float(oh - 1) * ua;
// only draw if within original sprite
if (ux >= 0.0 && ux <= 1.0 && ua >= 0.0 && ua <= 1.0) {
int refY = (int)CLIP(fy, (float)0.0, float(refsrc_height - 1));
int refX = (int)CLIP(fx, (float)0.0, float(refsrc_width - 1));
int setcolor = refsprite_pixels[refY][refX];
int setY = (int)CLIP((float)y, (float)0.0, (float)(src_height - 1));
int setX = (int)CLIP((float)x, (float)0.0, (float)(src_width - 1));
sprite_pixels[setY][setX] = setcolor;
}
x++;
}
y++;
}
_newWidth = w;
_newHeight = h;
_engine->ReleaseBitmapSurface(resizeb);
}
void AGSWaves::SetWarper(ScriptMethodParams &params) {
//PARAMS5(int, y2x, int, x3x, int, y3x, int, x4x, int, y4x);
}
int AGSWaves::IntersectLines(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) {
// check a
if (x1 == x2 && y1 == y2)
return -1;
// check b
if (x3 == x4 && y3 == y4)
return -1;
float den = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
float num12 = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);
float num34 = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3);
if (den == 0.0) { // no intersection
if (num12 == 0.0 && num34 == 0.0)
return 2;
return 0;
}
ua = num12 / den;
ix = x1 + ua * (x2 - x1);
iy = y1 + ua * (y2 - y1);
return 1;
}
} // namespace AGSWaves
} // namespace Plugins
} // namespace AGS3

File diff suppressed because it is too large Load Diff