[Scummvm-git-logs] scummvm master -> be309e97ebc76f9935bb80ee6bc9280f6655b5ac
criezy
noreply at scummvm.org
Sun Mar 12 21:07:02 UTC 2023
This automated email contains information about 78 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
8c6243052d AGS: Engine: in BitmapToVideoMem replaced if/else with a switch
0263572d1c AGS: Common: fix mismatched free
5ad85c6b42 AGS: Common: replaced GameSetupStruct::messages with an array of Strings
a32892578a AGS: Common: fail early in negative index
73d169c0e4 AGS: Common: fix warnings in directory.cpp
72592cc9e0 AGS: Engine: fixed ResolveScriptPath not handling subdirs correctly
8c6524a888 AGS: Common: fix warns and clang-tidy notices
61c7c0fcfe AGS: Engine: fixed gui controls not updated after interface is un-disabled
d372745e35 AGS: Prevent savepath manipulation in ScummVM
3ddbd08585 AGS: Engine: in render_to_screen() do at least 1 delay in case of DEVICELOST
e7e7e4a446 AGS: Engine: keep mouse speed control enabled (by default, fullscreen only)
3d45396eb6 AGS: Updated build version (3.6.0.37)
c366ce5eef AGS: Removed update_polled_stuff_if_runtime() from data loading functions
f77da38379 AGS: Engine: fixed view frames have a linked sound 0 by default
92134389e6 AGS: Common: fixed crash if slider's handle set to negative sprite id
49e61b6ea2 AGS: Engine: let use dummy frame 0 if the speech view's loop is empty
0fbdbdfcdd AGS: Engine: fixed WaitInput() incorrect handling of a type arg
ecc1d17655 AGS: Engine: register missing SetProperty script functions for plugins
416c6982cd AGS: Updated build version (3.6.0.38)
91d7299405 AGS: Engine: (again) fixed buttons not updated visually on interface enable
e0d2bc8860 AGS: Engine: Fix malloc/delete mismatch with RoomStatus::tsdata
88f0170696 AGS: Engine: Fixed RoomStatus::tsdata allocation of additional bytes
26375b823b AGS: Engine: Used std::vector for RoomStatus::tsdata
f58c4d9bdb AGS: Common: replaced couple of smart ptr arrays with std::vector
2cffebe3a5 AGS: Engine: use unique_ptr to store raw image in ObjectCache
3d4856d321 AGS: Engine: for HW renderers - don't create redundant object cache images
16658128f6 AGS: Common: revert lzwexpand to expanding to mem, for better speed
818b670561 AGS: Engine: fixed text parser could substring with negative length
afed888bb5 AGS: Engine: avoid dirty rects outside software render surface
0f86678e2d AGS: Engine: only clear _stageScreen after it's dirty
d6b03229d7 AGS: Common: move scanline safety check to assert
0813358193 AGS: Fix empty statement warnings
a76b930e87 AGS: Common: bufferedstream add default and remove unused break
8205b5b932 AGS: Allegro: remove unused bmp_unwrite_line
bfc5f63026 AGS :Engine: draw fix, true means texture don't change
2b028c586f AGS: Engine: hotfixed BitmapToVideoMem after 6804e9f
2359c13d23 AGS: Engine: moved global sprite offset & flip to the parent batch transform
b7080efc96 AGS: Engine: for hw renderers split viewport and camera in 2 sprite batches
7825fc3c63 AGS: Common: unswitch loop in indexed bitmap unpacking
7e3ffd0161 AGS: Engine: unswitch loop in Bitmap to Video memory
97d08215b5 AGS: Engine: Use a single function to send messages to editor debugger
d563f6dec9 AGS: Updated build version (3.6.0.39)
5a2405d291 AGS: Engine: debug use AppendFmt at send msg and clang-tidy fixes
48592b9eee AGS: Engine: add screen functions to plugin exports
af16689b2b AGS: Plugin: SnowRain adjust height/baseline before entering room
b828199c25 AGS: Engine: renderers support creating DDB as a render target
f0887a3b9f AGS: Engine: in gfx drivers record sprite range for each batch
711ca20dd1 AGS: Engine: abort in case failed both to switch and restore gfx mode
982abc24f3 AGS: Engine: create raw draw screens only on plugin's demand
6343759e09 AGS: Engine: changed member names in StageScreen to avoid conflicts
cd43ec26ed AGS: Common: wrong clamping in memory stream
491f59d3fe AGS: Plugin: fix pal_render logic mistakes
823eda7991 AGS: Engine: renamed "NullSpriteCallback", give more meaningful name
1e3bb9c241 AGS: Engine: support optional size and position for gfxdriver's stage screen
c6864a8a67 AGS: Engine: added _rendSpriteBatch counter to software renderer
b3a7b2e8de AGS: Updated build version (3.6.0.40) and copyright year to 2023
88a1083e0d AGS: Move strlen out of loops
da88b81fdf AGS: SnowRain: do not override user-set baselines
0f90b07118 AGS: Common: also assert in GetScanLineForWriting()
7b5bcb881a AGS: Engine: fail when reading game data should return error
26c2a748de AGS: Alfont: fix leak, release before freeing last reference
f0c18ccacb AGS: Engine: fixed GUI sorting for cases when ZOrder is equal
1bc1c49dbf AGS: Engine: fixed missing channels after restoring old save in updated game
5b7f95075e AGS: Engine: removed unused global var
e62a2c3504 AGS: Engine: don't reset batch surfaces in software driver's ResetAllBatches
43723e170a AGS: Engine: in SetMemoryBackBuffer() don't reset batch surfs during render
50d8eaddcf AGS: Engine: in IAGSEngine::SetVirtualScreen set Stage buffer, not whole VS
3d91a8835e AGS: Engine: fixed button keeps "mouse over" pic after Visible = false
89ea094df1 AGS: Engine: fixed idle_anim_speed after restoring old save in updated game
2daaef2d48 AGS: Engine: updated SavegameVersion (had few cmp changes since last one)
9a469f1e2b AGS: Engine: support fixing up RoomStatuses restored from older save formats
953356c758 AGS: Common: call OnMouseLeave on focused control in ResetOverControl()
9743b0dd6c AGS: Engine: restored GUI draw sort, where equal z is resolved with IDs
15d43b09ad AGS: Common: add AGS_PLATFORM_MOBILE for Android and iOS
9a4817653c AGS: Engine: resizable flag is necessary for fullscreen app rotation
07bbbcd233 AGS: Engine: replaced couple more shared_ptr<char> with vector<char>
bdec317f27 AGS: Updated build version (3.6.0.41)
be309e97eb AGS: Fix GCC Compiler Warnings
Commit: 8c6243052db927253c6ea2d00cb88a57bc814b2d
https://github.com/scummvm/scummvm/commit/8c6243052db927253c6ea2d00cb88a57bc814b2d
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:27Z
Commit Message:
AGS: Engine: in BitmapToVideoMem replaced if/else with a switch
This supposedly should slightly improve bitmap to texture conversion performance.
>From upstream ab213c0962df7bdec96ce38122f637f0febe4ef4
Changed paths:
engines/ags/engine/gfx/gfx_driver_base.cpp
diff --git a/engines/ags/engine/gfx/gfx_driver_base.cpp b/engines/ags/engine/gfx/gfx_driver_base.cpp
index deefc5e10d0..1da1c80b7f7 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.cpp
+++ b/engines/ags/engine/gfx/gfx_driver_base.cpp
@@ -340,9 +340,8 @@ __inline void get_pixel_if_not_transparent32(const unsigned int *pixel, unsigned
#define VMEMCOLOR_RGBA(r,g,b,a) \
( (((a) & 0xFF) << _vmem_a_shift_32) | (((r) & 0xFF) << _vmem_r_shift_32) | (((g) & 0xFF) << _vmem_g_shift_32) | (((b) & 0xFF) << _vmem_b_shift_32) )
-
void VideoMemoryGraphicsDriver::BitmapToVideoMem(const Bitmap *bitmap, const bool has_alpha, const TextureTile *tile,
- char *dst_ptr, const int dst_pitch, const bool usingLinearFiltering) {
+ char *dst_ptr, const int dst_pitch, const bool usingLinearFiltering) {
const int src_depth = bitmap->GetColorDepth();
bool lastPixelWasTransparent = false;
for (int y = 0; y < tile->height; y++) {
@@ -353,7 +352,8 @@ void VideoMemoryGraphicsDriver::BitmapToVideoMem(const Bitmap *bitmap, const boo
unsigned int *memPtrLong = (unsigned int *)dst_ptr;
for (int x = 0; x < tile->width; x++) {
- if (src_depth == 8) {
+ switch (src_depth) {
+ case 8: {
const unsigned char *srcData = (const unsigned char *)&scanline_at[(x + tile->x) * sizeof(char)];
if (*srcData == MASK_COLOR_8) {
if (!usingLinearFiltering)
@@ -385,7 +385,9 @@ void VideoMemoryGraphicsDriver::BitmapToVideoMem(const Bitmap *bitmap, const boo
lastPixelWasTransparent = false;
}
}
- } else if (src_depth == 16) {
+ break;
+ }
+ case 16: {
const unsigned short *srcData = (const unsigned short *)&scanline_at[(x + tile->x) * sizeof(short)];
if (*srcData == MASK_COLOR_16) {
if (!usingLinearFiltering)
@@ -417,7 +419,9 @@ void VideoMemoryGraphicsDriver::BitmapToVideoMem(const Bitmap *bitmap, const boo
lastPixelWasTransparent = false;
}
}
- } else if (src_depth == 32) {
+ break;
+ }
+ case 32: {
const unsigned int *srcData = (const unsigned int *)&scanline_at[(x + tile->x) * sizeof(int)];
if (*srcData == MASK_COLOR_32) {
if (!usingLinearFiltering)
@@ -451,33 +455,45 @@ void VideoMemoryGraphicsDriver::BitmapToVideoMem(const Bitmap *bitmap, const boo
lastPixelWasTransparent = false;
}
}
+ break;
+ }
+ default:
+ break;
}
}
-
dst_ptr += dst_pitch;
}
}
void VideoMemoryGraphicsDriver::BitmapToVideoMemOpaque(const Bitmap *bitmap, const bool has_alpha, const TextureTile *tile,
- char *dst_ptr, const int dst_pitch) {
+ char *dst_ptr, const int dst_pitch) {
const int src_depth = bitmap->GetColorDepth();
for (int y = 0; y < tile->height; y++) {
const uint8_t *scanline_at = bitmap->GetScanLine(y + tile->y);
unsigned int *memPtrLong = (unsigned int *)dst_ptr;
for (int x = 0; x < tile->width; x++) {
- if (src_depth == 8) {
+ switch (src_depth) {
+ case 8: {
const unsigned char *srcData = (const unsigned char *)&scanline_at[(x + tile->x) * sizeof(char)];
memPtrLong[x] = VMEMCOLOR_RGBA(algetr8(*srcData), algetg8(*srcData), algetb8(*srcData), 0xFF);
- } else if (src_depth == 16) {
+ break;
+ }
+ case 16: {
const unsigned short *srcData = (const unsigned short *)&scanline_at[(x + tile->x) * sizeof(short)];
memPtrLong[x] = VMEMCOLOR_RGBA(algetr16(*srcData), algetg16(*srcData), algetb16(*srcData), 0xFF);
- } else if (src_depth == 32) {
+ break;
+ }
+ case 32: {
const unsigned int *srcData = (const unsigned int *)&scanline_at[(x + tile->x) * sizeof(int)];
if (has_alpha)
memPtrLong[x] = VMEMCOLOR_RGBA(algetr32(*srcData), algetg32(*srcData), algetb32(*srcData), algeta32(*srcData));
else
memPtrLong[x] = VMEMCOLOR_RGBA(algetr32(*srcData), algetg32(*srcData), algetb32(*srcData), 0xFF);
+ break;
+ }
+ default:
+ break;
}
}
Commit: 0263572d1c771e9b0849e07a6222b1842692744f
https://github.com/scummvm/scummvm/commit/0263572d1c771e9b0849e07a6222b1842692744f
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:27Z
Commit Message:
AGS: Common: fix mismatched free
uses new char[] on Create method.
>From upstream ecfc238401183e210a1773c27724516f74272c8e
Changed paths:
engines/ags/engine/ac/dynobj/cc_dynamic_array.cpp
diff --git a/engines/ags/engine/ac/dynobj/cc_dynamic_array.cpp b/engines/ags/engine/ac/dynobj/cc_dynamic_array.cpp
index cd4f9c9c164..69ff8c3cc29 100644
--- a/engines/ags/engine/ac/dynobj/cc_dynamic_array.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_dynamic_array.cpp
@@ -47,7 +47,7 @@ int CCDynamicArray::Dispose(const char *address, bool force) {
}
}
- delete address;
+ delete[] address;
return 1;
}
Commit: 5ad85c6b42ee22a72c8f9857b39f251c7bf72504
https://github.com/scummvm/scummvm/commit/5ad85c6b42ee22a72c8f9857b39f251c7bf72504
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:27Z
Commit Message:
AGS: Common: replaced GameSetupStruct::messages with an array of Strings
This also fixes an allocation/deallocation mismatch found in the code.
>From upstream b47a086cbd589cd271c5fe1b3497f9b8e4ae4abf
Changed paths:
engines/ags/engine/ac/game.cpp
engines/ags/engine/game/savegame_v321.cpp
engines/ags/shared/ac/game_setup_struct.cpp
engines/ags/shared/ac/game_setup_struct.h
engines/ags/shared/ac/game_setup_struct_base.cpp
engines/ags/shared/ac/game_setup_struct_base.h
engines/ags/shared/game/main_game_file.cpp
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index f57fedb0fbd..8d5c764469b 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -1299,9 +1299,9 @@ void replace_tokens(const char *srcmes, char *destm, int maxlen) {
}
const char *get_global_message(int msnum) {
- if (_GP(game).messages[msnum - 500] == nullptr)
+ if (_GP(game).messages[msnum - 500].IsEmpty())
return "";
- return get_translation(_GP(game).messages[msnum - 500]);
+ return get_translation(_GP(game).messages[msnum - 500].GetCStr());
}
void get_message_text(int msnum, char *buffer, char giveErr) {
@@ -1311,14 +1311,14 @@ void get_message_text(int msnum, char *buffer, char giveErr) {
if (msnum >= 500) {
- if ((msnum >= MAXGLOBALMES + 500) || (_GP(game).messages[msnum - 500] == nullptr)) {
+ if ((msnum >= MAXGLOBALMES + 500) || (_GP(game).messages[msnum - 500].IsEmpty())) {
if (giveErr)
quit("!DisplayGlobalMessage: message does not exist");
buffer[0] = 0;
return;
}
buffer[0] = 0;
- replace_tokens(get_translation(_GP(game).messages[msnum - 500]), buffer, maxlen);
+ replace_tokens(get_translation(_GP(game).messages[msnum - 500].GetCStr()), buffer, maxlen);
return;
} else if (msnum < 0 || (size_t)msnum >= _GP(thisroom).MessageCount) {
if (giveErr)
diff --git a/engines/ags/engine/game/savegame_v321.cpp b/engines/ags/engine/game/savegame_v321.cpp
index efbed45c027..eac27316cea 100644
--- a/engines/ags/engine/game/savegame_v321.cpp
+++ b/engines/ags/engine/game/savegame_v321.cpp
@@ -414,7 +414,7 @@ HSaveError restore_save_data_v321(Stream *in, const PreservedParams &pp, Restore
ccScript *compsc = _GP(game).compiled_script;
CharacterInfo *chwas = _GP(game).chars;
WordsDictionary *olddict = _GP(game).dict;
- char *mesbk[MAXGLOBALMES];
+ std::vector<String> mesbk(MAXGLOBALMES);
int numchwas = _GP(game).numcharacters;
for (size_t i = 0; i < MAXGLOBALMES; ++i)
mesbk[i] = _GP(game).messages[i];
diff --git a/engines/ags/shared/ac/game_setup_struct.cpp b/engines/ags/shared/ac/game_setup_struct.cpp
index 19b5968eecd..5d2abc2c536 100644
--- a/engines/ags/shared/ac/game_setup_struct.cpp
+++ b/engines/ags/shared/ac/game_setup_struct.cpp
@@ -220,12 +220,12 @@ void GameSetupStruct::read_lipsync(Shared::Stream *in, GameDataVersion data_ver)
}
void GameSetupStruct::read_messages(Shared::Stream *in, GameDataVersion data_ver) {
- for (int ee = 0; ee < MAXGLOBALMES; ee++) {
- if (!load_messages[ee]) continue;
- messages[ee] = new char[GLOBALMESLENGTH];
-
+ char mbuf[GLOBALMESLENGTH];
+ for (int i = 0; i < MAXGLOBALMES; ++i) {
+ if (!load_messages[i])
+ continue;
if (data_ver < kGameVersion_261) { // Global messages are not encrypted on < 2.61
- char *nextchar = messages[ee];
+ char *nextchar = mbuf;
// TODO: probably this is same as fgetstring
while (1) {
@@ -234,8 +234,10 @@ void GameSetupStruct::read_messages(Shared::Stream *in, GameDataVersion data_ver
break;
nextchar++;
}
- } else
- read_string_decrypt(in, messages[ee], GLOBALMESLENGTH);
+ } else {
+ read_string_decrypt(in, mbuf, GLOBALMESLENGTH);
+ }
+ messages[i] = mbuf;
}
delete[] load_messages;
load_messages = nullptr;
@@ -340,17 +342,15 @@ void GameSetupStruct::ReadAudioClips_Aligned(Shared::Stream *in, size_t count) {
}
void GameSetupStruct::ReadFromSaveGame_v321(Stream *in, char *gswas, ccScript *compsc, CharacterInfo *chwas,
- WordsDictionary *olddict, char **mesbk) {
- int bb;
-
+ WordsDictionary *olddict, std::vector<String> &mesbk) {
ReadInvInfo_Aligned(in);
ReadMouseCursors_Aligned(in);
if (_G(loaded_game_file_version) <= kGameVersion_272) {
- for (bb = 0; bb < numinvitems; bb++)
- intrInv[bb]->ReadTimesRunFromSave_v321(in);
- for (bb = 0; bb < numcharacters; bb++)
- intrChar[bb]->ReadTimesRunFromSave_v321(in);
+ for (int i = 0; i < numinvitems; ++i)
+ intrInv[i]->ReadTimesRunFromSave_v321(in);
+ for (int i = 0; i < numcharacters; ++i)
+ intrChar[i]->ReadTimesRunFromSave_v321(in);
}
// restore pointer members
@@ -358,8 +358,8 @@ void GameSetupStruct::ReadFromSaveGame_v321(Stream *in, char *gswas, ccScript *c
compiled_script = compsc;
chars = chwas;
dict = olddict;
- for (int vv = 0; vv < MAXGLOBALMES; vv++) messages[vv] = mesbk[vv];
-
+ for (size_t i = 0; i < MAXGLOBALMES; ++i)
+ messages[i] = mesbk[i];
in->ReadArrayOfInt32(&options[0], OPT_HIGHESTOPTION_321 + 1);
options[OPT_LIPSYNCTEXT] = in->ReadByte();
diff --git a/engines/ags/shared/ac/game_setup_struct.h b/engines/ags/shared/ac/game_setup_struct.h
index b451ba22391..b8df68e0730 100644
--- a/engines/ags/shared/ac/game_setup_struct.h
+++ b/engines/ags/shared/ac/game_setup_struct.h
@@ -22,6 +22,7 @@
#ifndef AGS_SHARED_AC_GAME_SETUP_STRUCT_H
#define AGS_SHARED_AC_GAME_SETUP_STRUCT_H
+//#include "ags/lib/std/array.h"
#include "ags/lib/std/vector.h"
#include "ags/shared/ac/audio_clip_type.h"
#include "ags/shared/ac/character_info.h" // TODO: constants to separate header
@@ -159,7 +160,7 @@ struct GameSetupStruct : public GameSetupStructBase {
// Functions for reading and writing appropriate data from/to save game
void ReadFromSaveGame_v321(Shared::Stream *in, char *gswas, ccScript *compsc, CharacterInfo *chwas,
- WordsDictionary *olddict, char **mesbk);
+ WordsDictionary *olddict, std::vector<String> &mesbk);
void ReadFromSavegame(Shared::Stream *in);
void WriteForSavegame(Shared::Stream *out);
diff --git a/engines/ags/shared/ac/game_setup_struct_base.cpp b/engines/ags/shared/ac/game_setup_struct_base.cpp
index 8cd765516c9..4fd318a0d14 100644
--- a/engines/ags/shared/ac/game_setup_struct_base.cpp
+++ b/engines/ags/shared/ac/game_setup_struct_base.cpp
@@ -65,7 +65,6 @@ GameSetupStructBase::GameSetupStructBase()
memset(paluses, 0, sizeof(paluses));
memset(defpal, 0, sizeof(defpal));
memset(reserved, 0, sizeof(reserved));
- memset(messages, 0, sizeof(messages));
}
GameSetupStructBase::~GameSetupStructBase() {
@@ -74,8 +73,7 @@ GameSetupStructBase::~GameSetupStructBase() {
void GameSetupStructBase::Free() {
for (int i = 0; i < MAXGLOBALMES; ++i) {
- delete[] messages[i];
- messages[i] = nullptr;
+ messages[i].Free();
}
delete[] load_messages;
load_messages = nullptr;
@@ -224,7 +222,7 @@ void GameSetupStructBase::WriteToFile(Stream *out) {
out->WriteInt32(invhotdotsprite);
out->WriteArrayOfInt32(reserved, 17);
for (int i = 0; i < MAXGLOBALMES; ++i) {
- out->WriteInt32(messages[i] ? 1 : 0);
+ out->WriteInt32(!messages[i].IsEmpty() ? 1 : 0);
}
out->WriteInt32(dict ? 1 : 0);
out->WriteInt32(0); // globalscript
diff --git a/engines/ags/shared/ac/game_setup_struct_base.h b/engines/ags/shared/ac/game_setup_struct_base.h
index e251998847d..26a0160bbdb 100644
--- a/engines/ags/shared/ac/game_setup_struct_base.h
+++ b/engines/ags/shared/ac/game_setup_struct_base.h
@@ -70,12 +70,13 @@ struct GameSetupStructBase {
int default_lipsync_frame; // used for unknown chars
int invhotdotsprite;
int32_t reserved[NUM_INTS_RESERVED];
- char *messages[MAXGLOBALMES];
+ String messages[MAXGLOBALMES];
WordsDictionary *dict;
char *globalscript;
CharacterInfo *chars;
ccScript *compiled_script;
+ // TODO: refactor to not have this as struct members
int32_t *load_messages;
bool load_dictionary;
bool load_compiled_script;
diff --git a/engines/ags/shared/game/main_game_file.cpp b/engines/ags/shared/game/main_game_file.cpp
index 41b6255d783..187336ea71b 100644
--- a/engines/ags/shared/game/main_game_file.cpp
+++ b/engines/ags/shared/game/main_game_file.cpp
@@ -637,8 +637,8 @@ void SetDefaultGlmsg(GameSetupStruct &game, int msgnum, const char *val) {
// TODO: find out why the index should be lowered by 500
// (or rather if we may pass correct index right away)
msgnum -= 500;
- if (_GP(game).messages[msgnum] == nullptr)
- _GP(game).messages[msgnum] = ags_strdup(val);
+ if (_GP(game).messages[msgnum].IsEmpty())
+ _GP(game).messages[msgnum] = val;
}
// Sets up default global messages (these are used mainly in older games)
Commit: a32892578aee7320232212013cd2583d1943414e
https://github.com/scummvm/scummvm/commit/a32892578aee7320232212013cd2583d1943414e
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:27Z
Commit Message:
AGS: Common: fail early in negative index
from upstream 4d9f1788059b2fdadd3e957a5a260a918458595d
Changed paths:
engines/ags/shared/gui/gui_button.cpp
diff --git a/engines/ags/shared/gui/gui_button.cpp b/engines/ags/shared/gui/gui_button.cpp
index c8a77e5ca56..710c813f9de 100644
--- a/engines/ags/shared/gui/gui_button.cpp
+++ b/engines/ags/shared/gui/gui_button.cpp
@@ -108,7 +108,7 @@ Rect GUIButton::CalcGraphicRect(bool clipped) {
if (IsClippingImage())
return rc;
// Main button graphic
- if (_GP(spriteset)[CurrentImage] != nullptr)
+ if (CurrentImage >= 0 && _GP(spriteset)[CurrentImage] != nullptr)
rc = SumRects(rc, RectWH(0, 0, get_adjusted_spritewidth(CurrentImage), get_adjusted_spriteheight(CurrentImage)));
// Optionally merge with the inventory pic
if (_placeholder != kButtonPlace_None && _G(gui_inv_pic) >= 0) {
Commit: 73d169c0e420d3c846157c4e97326407d3644621
https://github.com/scummvm/scummvm/commit/73d169c0e420d3c846157c4e97326407d3644621
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:27Z
Commit Message:
AGS: Common: fix warnings in directory.cpp
- prefer empty instead of size() == 0
partially from upstream de97ab3e8c14074944c7087cc8e4bc5b15d6f4d6
Changed paths:
engines/ags/shared/util/directory.cpp
diff --git a/engines/ags/shared/util/directory.cpp b/engines/ags/shared/util/directory.cpp
index 392c870178d..7907400a17c 100644
--- a/engines/ags/shared/util/directory.cpp
+++ b/engines/ags/shared/util/directory.cpp
@@ -99,7 +99,7 @@ static bool GetFilesImpl(const String &dir_path, std::vector<String> &files, boo
Common::FSNode::kListFilesOnly);
for (uint i = 0; i < fsList.size(); ++i)
- files.push_back(fsList[i].getName());
+ files.emplace_back(fsList[i].getName());
return true;
}
@@ -164,7 +164,7 @@ FindFileRecursive FindFileRecursive::Open(const String &path, const String &wild
}
void FindFileRecursive::Close() {
- while (_fdirs.size())
+ while (!_fdirs.empty())
_fdirs.pop();
_fdir.Close();
_ffile.Close();
@@ -210,7 +210,7 @@ bool FindFileRecursive::PushDir(const String &sub) {
}
bool FindFileRecursive::PopDir() {
- if (_fdirs.size() == 0)
+ if (_fdirs.empty())
return false; // no more parent levels
// restore parent level
_fdir = std::move(_fdirs.top());
Commit: 72592cc9e08e4e08d1ab75fd317f0d86b270c38d
https://github.com/scummvm/scummvm/commit/72592cc9e08e4e08d1ab75fd317f0d86b270c38d
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:27Z
Commit Message:
AGS: Engine: fixed ResolveScriptPath not handling subdirs correctly
from upstream 8d0e0cb3c20db0beddffc36c688ed33005a43d7c
Changed paths:
engines/ags/engine/ac/file.cpp
diff --git a/engines/ags/engine/ac/file.cpp b/engines/ags/engine/ac/file.cpp
index b04d491ba9f..84cd54dc1a8 100644
--- a/engines/ags/engine/ac/file.cpp
+++ b/engines/ags/engine/ac/file.cpp
@@ -415,8 +415,12 @@ bool ResolveScriptPath(const String &orig_sc_path, bool read_only, ResolvedPath
}
#endif
- // don't allow write operations for relative paths outside game dir
+ // Create a proper ResolvedPath with FSLocation separating base location
+ // (which the engine is not allowed to create) and sub-dirs (created by the engine).
+ parent_dir = parent_dir.Concat(Path::GetDirectoryPath(child_path));
+ child_path = Path::GetFilename(child_path);
ResolvedPath test_rp = ResolvedPath(parent_dir, child_path, alt_path);
+ // don't allow write operations for relative paths outside game dir
if (!read_only) {
if (!Path::IsSameOrSubDir(test_rp.Loc.FullDir, test_rp.FullPath)) {
debug_script_warn("Attempt to access file '%s' denied (outside of game directory)", sc_path.GetCStr());
Commit: 8c6524a88830e24b5498903d96f077bdd5dce15b
https://github.com/scummvm/scummvm/commit/8c6524a88830e24b5498903d96f077bdd5dce15b
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:27Z
Commit Message:
AGS: Common: fix warns and clang-tidy notices
- using braced initializers for returned invalid objects
partially from upstream 8aeda4b67bf24ce080b09255139e0f6b907a9a8f
Changed paths:
engines/ags/shared/util/directory.cpp
diff --git a/engines/ags/shared/util/directory.cpp b/engines/ags/shared/util/directory.cpp
index 7907400a17c..91d5559724a 100644
--- a/engines/ags/shared/util/directory.cpp
+++ b/engines/ags/shared/util/directory.cpp
@@ -150,13 +150,13 @@ FindFileRecursive FindFileRecursive::Open(const String &path, const String &wild
FindFile fdir = FindFile::OpenDirs(path);
FindFile ffile = FindFile::OpenFiles(path, wildcard);
if (ffile.AtEnd() && fdir.AtEnd())
- return FindFileRecursive(); // return invalid object
+ return {}; // return invalid object
FindFileRecursive ff;
ff._fdir = std::move(fdir);
ff._ffile = std::move(ffile);
// Try get the first matching entry
if (ff._ffile.AtEnd() && !ff.Next())
- return FindFileRecursive(); // return invalid object
+ return {}; // return invalid object
ff._maxLevel = max_level;
ff._fullDir = path;
ff._curFile = ff._ffile.Current();
Commit: 61c7c0fcfe97ef10c121ebb70e1ef3fed4a6fbba
https://github.com/scummvm/scummvm/commit/61c7c0fcfe97ef10c121ebb70e1ef3fed4a6fbba
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:27Z
Commit Message:
AGS: Engine: fixed gui controls not updated after interface is un-disabled
from upstream 126a5e4c97581aabadbbd4410441b83f371e18ea
Changed paths:
engines/ags/engine/ac/gui.cpp
diff --git a/engines/ags/engine/ac/gui.cpp b/engines/ags/engine/ac/gui.cpp
index 370aff5ad4c..0ad27e68c64 100644
--- a/engines/ags/engine/ac/gui.cpp
+++ b/engines/ags/engine/ac/gui.cpp
@@ -447,9 +447,7 @@ void update_gui_disabled_status() {
if (all_buttons_was != _G(all_buttons_disabled)) {
// As controls become enabled we must notify parent GUIs
// to let them reset control-under-mouse detection
- for (int aa = 0; aa < _GP(game).numgui; aa++) {
- _GP(guis)[aa].MarkControlsChanged();
- }
+ GUI::MarkAllGUIForUpdate();
if (GUI::Options.DisabledStyle != kGuiDis_Unchanged) {
invalidate_screen();
}
Commit: d372745e35bd842826d64ae87c892fd89934ed3f
https://github.com/scummvm/scummvm/commit/d372745e35bd842826d64ae87c892fd89934ed3f
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:27Z
Commit Message:
AGS: Prevent savepath manipulation in ScummVM
Completes commit 8e77b04062d865e35bbadedce2fb7ba4971b837c.
We don't support subdirs in saves, the previous change causes some
games to be unable to save/restore
Changed paths:
engines/ags/engine/ac/file.cpp
diff --git a/engines/ags/engine/ac/file.cpp b/engines/ags/engine/ac/file.cpp
index 84cd54dc1a8..de2828122d0 100644
--- a/engines/ags/engine/ac/file.cpp
+++ b/engines/ags/engine/ac/file.cpp
@@ -413,12 +413,13 @@ bool ResolveScriptPath(const String &orig_sc_path, bool read_only, ResolvedPath
if (child_path.CompareLeftNoCase(gameTarget) != 0)
child_path = String::FromFormat("%s-%s", gameTarget.GetCStr(), child_path.GetCStr());
}
-#endif
-
+#else
// Create a proper ResolvedPath with FSLocation separating base location
// (which the engine is not allowed to create) and sub-dirs (created by the engine).
parent_dir = parent_dir.Concat(Path::GetDirectoryPath(child_path));
child_path = Path::GetFilename(child_path);
+#endif
+
ResolvedPath test_rp = ResolvedPath(parent_dir, child_path, alt_path);
// don't allow write operations for relative paths outside game dir
if (!read_only) {
Commit: 3ddbd08585d688aaf9f73c490d83906fc27e5667
https://github.com/scummvm/scummvm/commit/3ddbd08585d688aaf9f73c490d83906fc27e5667
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:27Z
Commit Message:
AGS: Engine: in render_to_screen() do at least 1 delay in case of DEVICELOST
from upstream 27306da4cd0c1fa193f984644aa1915c8a944364
Changed paths:
engines/ags/engine/ac/draw.cpp
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index cf52ebf3c5b..b278f8eace7 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -722,10 +722,10 @@ void render_to_screen() {
/*}
catch (Ali3DFullscreenLostException e) {
Debug::Printf("Renderer exception: %s", e.Message.GetCStr());
- while (_G(game_update_suspend) && (!_G(want_exit)) && (!_G(abort_engine))) {
+ do {
sys_evt_process_pending();
platform->Delay(300);
- }
+ } while (_G(game_update_suspend) && (!_G(want_exit)) && (!_G(abort_engine)));
}*/
}
}
Commit: e7e7e4a446ce031ca1dc9297da80624a50c8fe26
https://github.com/scummvm/scummvm/commit/e7e7e4a446ce031ca1dc9297da80624a50c8fe26
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:27Z
Commit Message:
AGS: Engine: keep mouse speed control enabled (by default, fullscreen only)
Partially from upstream 1f867858c46c8a2dde841022aed8631f1deeabb1
Changed paths:
engines/ags/engine/ac/game_setup.cpp
diff --git a/engines/ags/engine/ac/game_setup.cpp b/engines/ags/engine/ac/game_setup.cpp
index 5c1d7abaf3a..bc9273f6048 100644
--- a/engines/ags/engine/ac/game_setup.cpp
+++ b/engines/ags/engine/ac/game_setup.cpp
@@ -36,7 +36,7 @@ GameSetup::GameSetup() {
override_upscale = false;
mouse_speed = 1.f;
mouse_ctrl_when = kMouseCtrl_Fullscreen;
- mouse_ctrl_enabled = false;
+ mouse_ctrl_enabled = true;
mouse_speed_def = kMouseSpeed_CurrentDisplay;
RenderAtScreenRes = false;
Supersampling = 1;
Commit: 3d45396eb6a1405e558c1cbd8a0e5cb1477a82b8
https://github.com/scummvm/scummvm/commit/3d45396eb6a1405e558c1cbd8a0e5cb1477a82b8
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Updated build version (3.6.0.37)
>From upstream bbf48a8deeaefb0c577426d3a745261831d67be7
Changed paths:
engines/ags/shared/core/def_version.h
diff --git a/engines/ags/shared/core/def_version.h b/engines/ags/shared/core/def_version.h
index 3509f3f5e9f..24fc3c488fe 100644
--- a/engines/ags/shared/core/def_version.h
+++ b/engines/ags/shared/core/def_version.h
@@ -22,9 +22,9 @@
#ifndef AGS_SHARED_CORE_DEFVERSION_H
#define AGS_SHARED_CORE_DEFVERSION_H
-#define ACI_VERSION_STR "3.6.0.36"
+#define ACI_VERSION_STR "3.6.0.37"
#if defined (RC_INVOKED) // for MSVC resource compiler
-#define ACI_VERSION_MSRC_DEF 3.6.0.36
+#define ACI_VERSION_MSRC_DEF 3.6.0.37
#endif
#define SPECIAL_VERSION ""
Commit: c366ce5eefbd01435f063a4efe9d828a1d648f0c
https://github.com/scummvm/scummvm/commit/c366ce5eefbd01435f063a4efe9d828a1d648f0c
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Removed update_polled_stuff_if_runtime() from data loading functions
Leave it with a new name as `update_polled_stuff()` only in functions
related to the game update.
>From upstream 95dc139f51e704da19792e5480e69bbfe7ec27aa
Changed paths:
engines/ags/engine/ac/dialog.cpp
engines/ags/engine/ac/display.cpp
engines/ags/engine/ac/draw.cpp
engines/ags/engine/ac/drawing_surface.cpp
engines/ags/engine/ac/dynamic_sprite.cpp
engines/ags/engine/ac/event.cpp
engines/ags/engine/ac/game.cpp
engines/ags/engine/ac/global_drawing_surface.cpp
engines/ags/engine/ac/global_game.cpp
engines/ags/engine/ac/global_screen.cpp
engines/ags/engine/ac/inv_window.cpp
engines/ags/engine/ac/room.cpp
engines/ags/engine/ac/route_finder_impl_legacy.cpp
engines/ags/engine/ac/sprite.cpp
engines/ags/engine/debugging/debug.cpp
engines/ags/engine/game/savegame.cpp
engines/ags/engine/game/savegame_components.cpp
engines/ags/engine/game/savegame_v321.cpp
engines/ags/engine/gui/my_push_button.cpp
engines/ags/engine/main/engine_setup.cpp
engines/ags/engine/main/game_run.cpp
engines/ags/engine/main/game_run.h
engines/ags/engine/media/audio/audio.cpp
engines/ags/engine/media/video/video.cpp
engines/ags/plugins/ags_plugin.cpp
engines/ags/shared/ac/common.h
engines/ags/shared/game/room_file.cpp
engines/ags/shared/game/room_struct.cpp
diff --git a/engines/ags/engine/ac/dialog.cpp b/engines/ags/engine/ac/dialog.cpp
index 8f6326e7ead..fa10284709f 100644
--- a/engines/ags/engine/ac/dialog.cpp
+++ b/engines/ags/engine/ac/dialog.cpp
@@ -479,8 +479,6 @@ void DialogOptions::Prepare(int _dlgnum, bool _runGameLoopsInBackground) {
_GP(play).in_conversation ++;
- update_polled_stuff_if_runtime();
-
if (_GP(game).dialog_bullet > 0)
bullet_wid = _GP(game).SpriteInfos[_GP(game).dialog_bullet].Width + 3;
@@ -490,8 +488,6 @@ void DialogOptions::Prepare(int _dlgnum, bool _runGameLoopsInBackground) {
_G(said_text) = 0;
- update_polled_stuff_if_runtime();
-
const Rect &ui_view = _GP(play).GetUIViewport();
tempScrn = BitmapHelper::CreateBitmap(ui_view.GetWidth(), ui_view.GetHeight(), _GP(game).GetColorDepth());
@@ -770,13 +766,9 @@ void DialogOptions::Redraw() {
wantRefresh = false;
- update_polled_stuff_if_runtime();
-
subBitmap = recycle_bitmap(subBitmap,
_G(gfxDriver)->GetCompatibleBitmapFormat(tempScrn->GetColorDepth()), dirtywidth, dirtyheight);
- update_polled_stuff_if_runtime();
-
if (usingCustomRendering) {
subBitmap->Blit(tempScrn, 0, 0, 0, 0, tempScrn->GetWidth(), tempScrn->GetHeight());
invalidate_rect(dirtyx, dirtyy, dirtyx + subBitmap->GetWidth(), dirtyy + subBitmap->GetHeight(), false);
@@ -945,7 +937,7 @@ bool DialogOptions::Run() {
}
}
- update_polled_stuff_if_runtime();
+ update_polled_stuff();
if (!runGameLoopsInBackground && (_GP(play).fast_forward == 0)) { // note if runGameLoopsInBackground then it's called inside UpdateGameOnce
WaitForNextFrame();
diff --git a/engines/ags/engine/ac/display.cpp b/engines/ags/engine/ac/display.cpp
index 299330923c2..9418ec8ecb6 100644
--- a/engines/ags/engine/ac/display.cpp
+++ b/engines/ags/engine/ac/display.cpp
@@ -333,7 +333,7 @@ ScreenOverlay *_display_main(int xx, int yy, int wii, const char *text, int disp
if (do_break)
break;
- update_polled_stuff_if_runtime();
+ update_polled_stuff();
if (_GP(play).fast_forward == 0) {
WaitForNextFrame();
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index b278f8eace7..d493e51e0a5 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -1706,7 +1706,6 @@ void prepare_room_sprites() {
// and for software renderer in case there are overlapping viewports.
// Note that software DDB is just a tiny wrapper around bitmap, so overhead is negligible.
if (_G(current_background_is_dirty) || !_G(roomBackgroundBmp)) {
- update_polled_stuff_if_runtime();
_G(roomBackgroundBmp) =
recycle_ddb_bitmap(_G(roomBackgroundBmp), _GP(thisroom).BgFrames[_GP(play).bg_frame].Graphic.get(), false, true);
diff --git a/engines/ags/engine/ac/drawing_surface.cpp b/engines/ags/engine/ac/drawing_surface.cpp
index 0484e87d09e..b823f52947a 100644
--- a/engines/ags/engine/ac/drawing_surface.cpp
+++ b/engines/ags/engine/ac/drawing_surface.cpp
@@ -184,7 +184,6 @@ void DrawingSurface_DrawImageImpl(ScriptDrawingSurface *sds, Bitmap *src,
src = newPic;
needToFreeBitmap = true;
- update_polled_stuff_if_runtime();
}
ds = sds->StartDrawing();
diff --git a/engines/ags/engine/ac/dynamic_sprite.cpp b/engines/ags/engine/ac/dynamic_sprite.cpp
index 8992b0fe7b6..6955fbe3b65 100644
--- a/engines/ags/engine/ac/dynamic_sprite.cpp
+++ b/engines/ags/engine/ac/dynamic_sprite.cpp
@@ -312,8 +312,6 @@ ScriptDynamicSprite *DynamicSprite_CreateFromScreenShot(int width, int height) {
Bitmap *newPic = CopyScreenIntoBitmap(width, height);
- update_polled_stuff_if_runtime();
-
// replace the bitmap in the sprite set
add_dynamic_sprite(gotSlot, newPic);
ScriptDynamicSprite *new_spr = new ScriptDynamicSprite(gotSlot);
diff --git a/engines/ags/engine/ac/event.cpp b/engines/ags/engine/ac/event.cpp
index 14328123abb..9cb59fc8589 100644
--- a/engines/ags/engine/ac/event.cpp
+++ b/engines/ags/engine/ac/event.cpp
@@ -30,6 +30,7 @@
#include "ags/engine/ac/gui.h"
#include "ags/engine/ac/room_status.h"
#include "ags/engine/ac/screen.h"
+#include "ags/engine/main/game_run.h"
#include "ags/shared/script/cc_common.h"
#include "ags/engine/platform/base/ags_platform_driver.h"
#include "ags/plugins/ags_plugin.h"
@@ -282,7 +283,7 @@ void process_event(const EventHappened *evp) {
_G(gfxDriver)->EndSpriteBatch();
}
render_to_screen();
- update_polled_stuff_if_runtime();
+ update_polled_stuff();
WaitForNextFrame();
}
@@ -316,7 +317,7 @@ void process_event(const EventHappened *evp) {
_G(gfxDriver)->DrawSprite(0, 0, ddb);
_G(gfxDriver)->EndSpriteBatch();
render_to_screen();
- update_polled_stuff_if_runtime();
+ update_polled_stuff();
WaitForNextFrame();
}
diff --git a/engines/ags/engine/ac/game.cpp b/engines/ags/engine/ac/game.cpp
index 8d5c764469b..05a937f143d 100644
--- a/engines/ags/engine/ac/game.cpp
+++ b/engines/ags/engine/ac/game.cpp
@@ -68,6 +68,7 @@
#include "ags/shared/gui/gui_slider.h"
#include "ags/engine/gui/gui_dialog.h"
#include "ags/engine/main/engine.h"
+#include "ags/engine/main/game_run.h"
#include "ags/engine/media/audio/audio_system.h"
#include "ags/engine/media/video/video.h"
#include "ags/engine/platform/base/ags_platform_driver.h"
@@ -823,7 +824,7 @@ long write_screen_shot_for_vista(Stream *out, Bitmap *screenshot) {
Common::MemoryWriteStreamDynamic bitmap(DisposeAfterUse::YES);
screenshot->SaveToFile(bitmap, _G(palette));
- update_polled_stuff_if_runtime();
+ update_polled_stuff();
// Write the bitmap to the output stream
out->Write(bitmap.getData(), bitmap.size());
@@ -888,8 +889,6 @@ void save_game(int slotn, const char *descript) {
return;
}
- update_polled_stuff_if_runtime();
-
// Actual dynamic game data is saved here
SaveGameState(out.get());
@@ -897,7 +896,7 @@ void save_game(int slotn, const char *descript) {
int screenShotOffset = out->GetPosition() - sizeof(RICH_GAME_MEDIA_HEADER);
int screenShotSize = write_screen_shot_for_vista(out.get(), screenShot.get());
- update_polled_stuff_if_runtime();
+ update_polled_stuff(); // TODO: probably unneeded
out->Seek(12, kSeekBegin);
out->WriteInt32(screenShotOffset);
diff --git a/engines/ags/engine/ac/global_drawing_surface.cpp b/engines/ags/engine/ac/global_drawing_surface.cpp
index 42ce1547d4a..9a85b6a3ff9 100644
--- a/engines/ags/engine/ac/global_drawing_surface.cpp
+++ b/engines/ags/engine/ac/global_drawing_surface.cpp
@@ -222,8 +222,6 @@ void RawDrawImageTransparent(int xx, int yy, int slot, int legacy_transparency)
// 1 - 99 => alpha 1 - 244
//
RawDrawImageTrans(xx, yy, slot, GfxDef::LegacyTrans100ToAlpha255(legacy_transparency));
-
- update_polled_stuff_if_runtime(); // this operation can be slow so stop music skipping
}
void RawDrawImageResized(int xx, int yy, int gotSlot, int width, int height) {
if ((gotSlot < 0) || (_GP(spriteset)[gotSlot] == nullptr))
@@ -249,7 +247,6 @@ void RawDrawImageResized(int xx, int yy, int gotSlot, int width, int height) {
delete newPic;
invalidate_screen();
mark_current_background_dirty();
- update_polled_stuff_if_runtime(); // this operation can be slow so stop music skipping
RAW_END();
}
void RawDrawLine(int fromx, int fromy, int tox, int toy) {
diff --git a/engines/ags/engine/ac/global_game.cpp b/engines/ags/engine/ac/global_game.cpp
index 33b58c673cd..08a1cbd6606 100644
--- a/engines/ags/engine/ac/global_game.cpp
+++ b/engines/ags/engine/ac/global_game.cpp
@@ -169,8 +169,6 @@ int LoadSaveSlotScreenshot(int slnum, int width, int height) {
RectWH(0, 0, _GP(game).SpriteInfos[gotSlot].Width, _GP(game).SpriteInfos[gotSlot].Height),
RectWH(0, 0, width, height));
- update_polled_stuff_if_runtime();
-
// replace the bitmap in the sprite set
free_dynamic_sprite(gotSlot);
add_dynamic_sprite(gotSlot, newPic);
diff --git a/engines/ags/engine/ac/global_screen.cpp b/engines/ags/engine/ac/global_screen.cpp
index 5880fc13310..3702e583f4b 100644
--- a/engines/ags/engine/ac/global_screen.cpp
+++ b/engines/ags/engine/ac/global_screen.cpp
@@ -30,6 +30,7 @@
#include "ags/engine/ac/runtime_defines.h"
#include "ags/engine/ac/screen.h"
#include "ags/engine/debugging/debug_log.h"
+#include "ags/engine/main/game_run.h"
#include "ags/engine/platform/base/ags_platform_driver.h"
#include "ags/engine/gfx/graphics_driver.h"
#include "ags/shared/gfx/bitmap.h"
@@ -77,7 +78,7 @@ void ShakeScreen(int severe) {
render_graphics();
- update_polled_stuff_if_runtime();
+ update_polled_stuff();
}
} else {
// Optimized variant for software render: create game scene once and shake it
@@ -88,7 +89,7 @@ void ShakeScreen(int severe) {
const int yoff = hh % 2 == 0 ? 0 : severe;
_GP(play).shake_screen_yoff = yoff;
render_to_screen();
- update_polled_stuff_if_runtime();
+ update_polled_stuff();
}
clear_letterbox_borders();
render_to_screen();
diff --git a/engines/ags/engine/ac/inv_window.cpp b/engines/ags/engine/ac/inv_window.cpp
index 0faf37eddb1..ea818511c08 100644
--- a/engines/ags/engine/ac/inv_window.cpp
+++ b/engines/ags/engine/ac/inv_window.cpp
@@ -477,7 +477,7 @@ bool InventoryScreen::Run() {
}
wasonitem = isonitem;
- update_polled_stuff_if_runtime();
+ update_polled_stuff();
WaitForNextFrame();
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index f75527e8133..2af5e39bd32 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -72,6 +72,7 @@
#include "ags/engine/gfx/gfxfilter.h"
#include "ags/shared/util/math.h"
#include "ags/engine/media/audio/audio_system.h"
+#include "ags/engine/main/game_run.h"
#include "ags/shared/debugging/out.h"
#include "ags/engine/script/script_api.h"
#include "ags/engine/script/script_runtime.h"
@@ -431,8 +432,6 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
}
}
- update_polled_stuff_if_runtime();
-
// load the room from disk
_G(our_eip) = 200;
_GP(thisroom).GameID = NO_GAME_ID_IN_ROOM_FILE;
@@ -450,7 +449,6 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
convert_room_coordinates_to_data_res(&_GP(thisroom));
- update_polled_stuff_if_runtime();
_G(our_eip) = 201;
_GP(play).room_width = _GP(thisroom).Width;
@@ -474,12 +472,9 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
}
for (size_t i = 0; i < _GP(thisroom).BgFrameCount; ++i) {
- update_polled_stuff_if_runtime();
_GP(thisroom).BgFrames[i].Graphic = PrepareSpriteForUse(_GP(thisroom).BgFrames[i].Graphic, false);
}
- update_polled_stuff_if_runtime();
-
_G(our_eip) = 202;
// Update game viewports
if (_GP(game).IsLegacyLetterbox())
@@ -505,11 +500,8 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
_G(walkareabackup) = BitmapHelper::CreateBitmapCopy(_GP(thisroom).WalkAreaMask.get());
_G(our_eip) = 204;
- update_polled_stuff_if_runtime();
redo_walkable_areas();
- update_polled_stuff_if_runtime();
walkbehinds_recalc();
- update_polled_stuff_if_runtime();
_G(our_eip) = 205;
// setup objects
@@ -606,8 +598,6 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
_G(in_new_room) = 2;
}
- update_polled_stuff_if_runtime();
-
if (_GP(thisroom).EventHandlers == nullptr) {
// legacy interactions
// copy interactions from room file into our temporary struct
@@ -636,10 +626,6 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
ccAddExternalDynamicObject(_GP(thisroom).Hotspots[cc].ScriptName, &_G(scrHotspot)[cc], &_GP(ccDynamicHotspot));
}
- _G(our_eip) = 206;
-
- update_polled_stuff_if_runtime();
-
_G(our_eip) = 210;
if (IS_ANTIALIAS_SPRITES) {
// sometimes the palette has corrupt entries, which crash
@@ -682,8 +668,6 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
StopMoving(cc);
}
- update_polled_stuff_if_runtime();
-
_G(roominst) = nullptr;
if (_G(debug_flags) & DBG_NOSCRIPT) ;
else if (_GP(thisroom).CompiledScript != nullptr) {
@@ -840,7 +824,6 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
_G(color_map) = nullptr;
_G(our_eip) = 209;
- update_polled_stuff_if_runtime();
generate_light_table();
update_music_volume();
@@ -870,7 +853,7 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
setpal();
_G(our_eip) = 220;
- update_polled_stuff_if_runtime();
+ update_polled_stuff();
debug_script_log("Now in room %d", _G(displayed_room));
GUI::MarkAllGUIForUpdate();
pl_run_plugin_hooks(AGSE_ENTERROOM, _G(displayed_room));
@@ -882,8 +865,6 @@ void new_room(int newnum, CharacterInfo *forchar) {
debug_script_log("Room change requested to room %d", newnum);
- update_polled_stuff_if_runtime();
-
// we are currently running Leaves Screen scripts
_G(in_leaves_screen) = newnum;
@@ -904,7 +885,6 @@ void new_room(int newnum, CharacterInfo *forchar) {
// who is not in the new room. therefore, abort the follow
_G(playerchar)->following = -1;
}
- update_polled_stuff_if_runtime();
// change rooms
unload_old_room();
@@ -916,8 +896,6 @@ void new_room(int newnum, CharacterInfo *forchar) {
GUI::MarkAllGUIForUpdate();
}
- update_polled_stuff_if_runtime();
-
load_new_room(newnum, forchar);
// Update background frame state (it's not a part of the RoomStatus currently)
diff --git a/engines/ags/engine/ac/route_finder_impl_legacy.cpp b/engines/ags/engine/ac/route_finder_impl_legacy.cpp
index 12c45378604..02348565d4f 100644
--- a/engines/ags/engine/ac/route_finder_impl_legacy.cpp
+++ b/engines/ags/engine/ac/route_finder_impl_legacy.cpp
@@ -442,8 +442,6 @@ static int find_route_dijkstra(int fromx, int fromy, int destx, int desty) {
int totalfound = 0;
int DIRECTION_BONUS = 0;
- update_polled_stuff_if_runtime();
-
while (foundAnswer < 0) {
min = 29999;
changeiter = iteration;
@@ -548,7 +546,6 @@ static int find_route_dijkstra(int fromx, int fromy, int destx, int desty) {
}
}
if (totalfound >= 1000) {
- update_polled_stuff_if_runtime();
totalfound = 0;
}
}
diff --git a/engines/ags/engine/ac/sprite.cpp b/engines/ags/engine/ac/sprite.cpp
index af201585a94..2d851daa8b9 100644
--- a/engines/ags/engine/ac/sprite.cpp
+++ b/engines/ags/engine/ac/sprite.cpp
@@ -166,7 +166,6 @@ void initialize_sprite(int ee) {
}
pl_run_plugin_hooks(AGSE_SPRITELOAD, ee);
- update_polled_stuff_if_runtime();
_G(our_eip) = oldeip;
}
diff --git a/engines/ags/engine/debugging/debug.cpp b/engines/ags/engine/debugging/debug.cpp
index 364634d7f28..58fceec3df6 100644
--- a/engines/ags/engine/debugging/debug.cpp
+++ b/engines/ags/engine/debugging/debug.cpp
@@ -36,6 +36,7 @@
#include "ags/engine/debugging/log_file.h"
#include "ags/engine/debugging/message_buffer.h"
#include "ags/engine/main/config.h"
+#include "ags/engine/main/game_run.h"
#include "ags/engine/media/audio/audio_system.h"
#include "ags/engine/platform/base/ags_platform_driver.h"
#include "ags/engine/platform/base/sys_main.h"
@@ -469,7 +470,7 @@ void break_into_debugger() {
_G(game_paused_in_debugger) = 1;
while (_G(game_paused_in_debugger)) {
- update_polled_stuff_if_runtime();
+ update_polled_stuff();
_G(platform)->YieldCPU();
}
diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index 69c9b6ed958..366b01239d7 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -50,6 +50,7 @@
#include "ags/engine/game/savegame.h"
#include "ags/engine/game/savegame_components.h"
#include "ags/engine/game/savegame_internal.h"
+#include "ags/engine/main/game_run.h"
#include "ags/engine/main/engine.h"
#include "ags/engine/main/main.h"
#include "ags/engine/platform/base/ags_platform_driver.h"
@@ -483,16 +484,12 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
int queuedMusicSize = _GP(play).music_queue_size;
_GP(play).music_queue_size = 0;
- update_polled_stuff_if_runtime();
-
// load the room the game was saved in
if (_G(displayed_room) >= 0)
load_new_room(_G(displayed_room), nullptr);
else
set_room_placeholder();
- update_polled_stuff_if_runtime();
-
_GP(play).gscript_timer = gstimer;
// restore the correct room volume (they might have modified
// it with SetMusicVolume)
@@ -509,8 +506,6 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
sys_window_set_title(_GP(play).game_name);
- update_polled_stuff_if_runtime();
-
if (_G(displayed_room) >= 0) {
// Fixup the frame index, in case the restored room does not have enough background frames
if (_GP(play).bg_frame < 0 || static_cast<size_t>(_GP(play).bg_frame) >= _GP(thisroom).BgFrameCount)
@@ -606,7 +601,7 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
RestoreViewportsAndCameras(r_data);
_GP(play).ClearIgnoreInput(); // don't keep ignored input after save restore
- update_polled_stuff_if_runtime();
+ update_polled_stuff();
pl_run_plugin_hooks(AGSE_POSTRESTOREGAME, 0);
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index ecda89b5d0c..f1d0be3b39b 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -1253,7 +1253,6 @@ HSaveError ReadAll(Stream *in, SavegameVersion svg_version, const PreservedParam
idx, info.Name.IsEmpty() ? "unknown" : info.Name.GetCStr(), info.Version, info.Offset),
err);
}
- update_polled_stuff_if_runtime();
idx++;
} while (!in->EOS());
return new SavegameError(kSvgErr_ComponentListClosingTagMissing);
@@ -1284,7 +1283,6 @@ HSaveError WriteAllCommon(Stream *out) {
String::FromFormat("Component: (#%d) %s", type, (*g_componentHandlers)[type].Name.GetCStr()),
err);
}
- update_polled_stuff_if_runtime();
}
WriteFormatTag(out, ComponentListTag, false);
return HSaveError::None();
diff --git a/engines/ags/engine/game/savegame_v321.cpp b/engines/ags/engine/game/savegame_v321.cpp
index eac27316cea..aa9bdf8ca3e 100644
--- a/engines/ags/engine/game/savegame_v321.cpp
+++ b/engines/ags/engine/game/savegame_v321.cpp
@@ -400,8 +400,6 @@ HSaveError restore_save_data_v321(Stream *in, const PreservedParams &pp, Restore
return err;
restore_game_spriteset(in);
- update_polled_stuff_if_runtime();
-
err = restore_game_scripts(in, pp, r_data);
if (!err)
return err;
@@ -461,13 +459,7 @@ HSaveError restore_save_data_v321(Stream *in, const PreservedParams &pp, Restore
restore_game_thisroom(in, r_data);
restore_game_ambientsounds(in, r_data);
restore_game_overlays(in);
-
- update_polled_stuff_if_runtime();
-
restore_game_dynamic_surfaces(in, r_data);
-
- update_polled_stuff_if_runtime();
-
restore_game_displayed_room_status(in, r_data);
err = restore_game_globalvars(in);
if (!err)
diff --git a/engines/ags/engine/gui/my_push_button.cpp b/engines/ags/engine/gui/my_push_button.cpp
index 34503ec4b77..a952011c9d8 100644
--- a/engines/ags/engine/gui/my_push_button.cpp
+++ b/engines/ags/engine/gui/my_push_button.cpp
@@ -76,8 +76,7 @@ int MyPushButton::pressedon(int mx, int my) {
wasstat = state;
state = mouseisinarea(mx, my);
- // stop mp3 skipping if button held down
- update_polled_stuff_if_runtime();
+ update_polled_stuff();
if (wasstat != state) {
// ags_domouse(DOMOUSE_DISABLE);
draw(get_gui_screen());
diff --git a/engines/ags/engine/main/engine_setup.cpp b/engines/ags/engine/main/engine_setup.cpp
index c02f19e9481..985925b28a6 100644
--- a/engines/ags/engine/main/engine_setup.cpp
+++ b/engines/ags/engine/main/engine_setup.cpp
@@ -38,6 +38,7 @@
#include "ags/engine/gfx/graphics_driver.h"
#include "ags/shared/gui/gui_main.h"
#include "ags/shared/gui/gui_inv.h"
+#include "ags/engine/main/game_run.h"
#include "ags/engine/main/graphics_mode.h"
#include "ags/engine/main/engine_setup.h"
#include "ags/engine/media/video/video.h"
@@ -157,7 +158,7 @@ void engine_adjust_for_rotation_settings() {
// Setup gfx driver callbacks and options
void engine_post_gfxmode_driver_setup() {
- _G(gfxDriver)->SetCallbackForPolling(update_polled_stuff_if_runtime);
+ _G(gfxDriver)->SetCallbackForPolling(update_polled_stuff);
_G(gfxDriver)->SetCallbackToDrawScreen(draw_game_screen_callback, construct_engine_overlay);
_G(gfxDriver)->SetCallbackForNullSprite(GfxDriverNullSpriteCallback);
}
diff --git a/engines/ags/engine/main/game_run.cpp b/engines/ags/engine/main/game_run.cpp
index 7155b9bdc7a..e6ca01d049c 100644
--- a/engines/ags/engine/main/game_run.cpp
+++ b/engines/ags/engine/main/game_run.cpp
@@ -796,7 +796,7 @@ void UpdateGameOnce(bool checkControls, IDriverDependantBitmap *extraBitmap, int
_G(our_eip) = 7;
- update_polled_stuff_if_runtime();
+ update_polled_stuff();
if (_G(abort_engine))
return;
@@ -812,7 +812,7 @@ void UpdateGameOnce(bool checkControls, IDriverDependantBitmap *extraBitmap, int
game_loop_update_fps();
- update_polled_stuff_if_runtime();
+ update_polled_stuff();
if (_G(abort_engine))
return;
@@ -1041,7 +1041,7 @@ void RunGameUntilAborted() {
}
}
-void update_polled_stuff_if_runtime() {
+void update_polled_stuff() {
::AGS::g_events->pollEvents();
if (_G(want_exit)) {
diff --git a/engines/ags/engine/main/game_run.h b/engines/ags/engine/main/game_run.h
index 9645123d334..605b927c819 100644
--- a/engines/ags/engine/main/game_run.h
+++ b/engines/ags/engine/main/game_run.h
@@ -59,6 +59,9 @@ bool run_service_key_controls(KeyInput &kgn);
// Runs service mouse controls, returns false if mouse input was claimed by the engine,
// otherwise returns true and provides mouse button code.
bool run_service_mb_controls(eAGSMouseButton &mbut, int &mwheelz);
+// Polls few things (exit flag and debugger messages)
+// TODO: refactor this
+void update_polled_stuff();
} // namespace AGS3
diff --git a/engines/ags/engine/media/audio/audio.cpp b/engines/ags/engine/media/audio/audio.cpp
index dd7202e16f6..9a5e6d1ef48 100644
--- a/engines/ags/engine/media/audio/audio.cpp
+++ b/engines/ags/engine/media/audio/audio.cpp
@@ -762,7 +762,7 @@ void update_volume_drop_if_voiceover() {
// Update the music, and advance the crossfade on a step
// (this should only be called once per game loop)
void update_audio_system_on_game_loop() {
- update_polled_stuff_if_runtime();
+ update_polled_stuff();
process_scheduled_music_update();
diff --git a/engines/ags/engine/media/video/video.cpp b/engines/ags/engine/media/video/video.cpp
index e4124edd0c1..a9725a37d6e 100644
--- a/engines/ags/engine/media/video/video.cpp
+++ b/engines/ags/engine/media/video/video.cpp
@@ -68,7 +68,7 @@ static bool play_video(Video::VideoDecoder *decoder, const char *name, int flags
return false;
}
- update_polled_stuff_if_runtime();
+ update_polled_stuff(); // TODO: probably unneeded
Graphics::Screen scr;
bool stretchVideo = (flags & kVideo_Stretch) != 0;
@@ -78,8 +78,8 @@ static bool play_video(Video::VideoDecoder *decoder, const char *name, int flags
if (!enableAudio)
decoder->setVolume(0);
- update_polled_stuff_if_runtime();
-
+ update_polled_stuff();
+
decoder->start();
while (!SHOULD_QUIT && !decoder->endOfVideo()) {
if (decoder->needsUpdate()) {
diff --git a/engines/ags/plugins/ags_plugin.cpp b/engines/ags/plugins/ags_plugin.cpp
index 3fd36a9a923..6f624b7e51e 100644
--- a/engines/ags/plugins/ags_plugin.cpp
+++ b/engines/ags/plugins/ags_plugin.cpp
@@ -344,7 +344,7 @@ void IAGSEngine::BlitSpriteRotated(int32 x, int32 y, BITMAP *bmp, int32 angle) {
void IAGSEngine::PollSystem() {
ags_domouse();
- update_polled_stuff_if_runtime();
+ update_polled_stuff();
eAGSMouseButton mbut;
int mwheelz;
if (run_service_mb_controls(mbut, mwheelz) && mbut > kMouseNone && !_GP(play).IsIgnoringInput())
diff --git a/engines/ags/shared/ac/common.h b/engines/ags/shared/ac/common.h
index bf419bae029..23f5535ea71 100644
--- a/engines/ags/shared/ac/common.h
+++ b/engines/ags/shared/ac/common.h
@@ -30,7 +30,6 @@ namespace AGS3 {
void quit(const AGS::Shared::String &str);
void quit(const char *);
void quitprintf(const char *fmt, ...);
-void update_polled_stuff_if_runtime();
void set_our_eip(int eip);
int get_our_eip();
diff --git a/engines/ags/shared/game/room_file.cpp b/engines/ags/shared/game/room_file.cpp
index de5529dfae7..5036280879a 100644
--- a/engines/ags/shared/game/room_file.cpp
+++ b/engines/ags/shared/game/room_file.cpp
@@ -19,7 +19,6 @@
*
*/
-#include "ags/shared/ac/common.h" // update_polled_stuff
#include "ags/shared/ac/common_defines.h"
#include "ags/shared/ac/game_struct_defines.h"
#include "ags/shared/ac/words_dictionary.h" // TODO: extract string decryption
@@ -141,8 +140,6 @@ HError ReadMainBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
wallpoints[i].Read(in);
*/
- update_polled_stuff_if_runtime();
-
room->Edges.Top = in->ReadInt16();
room->Edges.Bottom = in->ReadInt16();
room->Edges.Left = in->ReadInt16();
@@ -295,7 +292,6 @@ HError ReadMainBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
room->Regions[i].Tint = in->ReadInt32();
}
- update_polled_stuff_if_runtime();
// Primary background (LZW or RLE compressed depending on format)
if (data_ver >= kRoomVersion_pre114_5)
room->BgFrames[0].Graphic.reset(
@@ -304,16 +300,12 @@ HError ReadMainBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
room->BgFrames[0].Graphic.reset(load_rle_bitmap8(in));
// Area masks
- update_polled_stuff_if_runtime();
if (data_ver >= kRoomVersion_255b)
room->RegionMask.reset(load_rle_bitmap8(in));
else if (data_ver >= kRoomVersion_114)
skip_rle_bitmap8(in); // an old version - clear the 'shadow' area into a blank regions bmp (???)
- update_polled_stuff_if_runtime();
room->WalkAreaMask.reset(load_rle_bitmap8(in));
- update_polled_stuff_if_runtime();
room->WalkBehindMask.reset(load_rle_bitmap8(in));
- update_polled_stuff_if_runtime();
room->HotspotMask.reset(load_rle_bitmap8(in));
return HError::None();
}
@@ -382,7 +374,6 @@ HError ReadAnimBgBlock(RoomStruct *room, Stream *in, RoomFileVersion data_ver) {
}
for (size_t i = 1; i < room->BgFrameCount; ++i) {
- update_polled_stuff_if_runtime();
room->BgFrames[i].Graphic.reset(
load_lzw(in, room->BackgroundBPP, &room->BgFrames[i].Palette));
}
diff --git a/engines/ags/shared/game/room_struct.cpp b/engines/ags/shared/game/room_struct.cpp
index e5cd1915e1f..d8be7209a94 100644
--- a/engines/ags/shared/game/room_struct.cpp
+++ b/engines/ags/shared/game/room_struct.cpp
@@ -19,7 +19,7 @@
*
*/
-#include "ags/shared/ac/common.h" // update_polled_stuff_if_runtime
+#include "ags/shared/ac/common.h" // quit
#include "ags/shared/game/room_file.h"
#include "ags/shared/game/room_struct.h"
#include "ags/shared/gfx/bitmap.h"
@@ -230,12 +230,9 @@ void load_room(const String &filename, RoomStruct *room, bool game_is_hires, con
room->Free();
room->InitDefaults();
- update_polled_stuff_if_runtime();
-
RoomDataSource src;
HRoomFileError err = OpenRoomFileFromAsset(filename, src);
if (err) {
- update_polled_stuff_if_runtime(); // it can take a while to load the file sometimes
err = ReadRoomData(room, src.InputStream.get(), src.DataVersion);
if (err)
err = UpdateRoomData(room, src.DataVersion, game_is_hires, sprinfos);
Commit: f77da38379e901727d8b19ff574253e1feacd93a
https://github.com/scummvm/scummvm/commit/f77da38379e901727d8b19ff574253e1feacd93a
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: fixed view frames have a linked sound 0 by default
from upstream a4a98adfcb039e0f8f213d60e8b0b639b0217f9b
Changed paths:
engines/ags/engine/ac/global_object.cpp
engines/ags/shared/ac/view.cpp
engines/ags/shared/ac/view.h
diff --git a/engines/ags/engine/ac/global_object.cpp b/engines/ags/engine/ac/global_object.cpp
index 0aad35ab0b8..df290d831d5 100644
--- a/engines/ags/engine/ac/global_object.cpp
+++ b/engines/ags/engine/ac/global_object.cpp
@@ -153,7 +153,8 @@ void SetObjectFrame(int obn, int viw, int lop, int fra) {
if (!is_valid_object(obn)) quit("!SetObjectFrame: invalid object number specified");
viw--;
if (viw < 0 || viw >= _GP(game).numviews) quitprintf("!SetObjectFrame: invalid view number used (%d, range is 0 - %d)", viw, _GP(game).numviews - 1);
- if (lop < 0 || lop >= _GP(views)[viw].numLoops) quitprintf("!SetObjectFrame: invalid loop number used (%d, range is 0 - %d)", lop, _GP(views)[viw].numLoops - 1);
+ if (_GP(views)[viw].numLoops == 0) quitprintf("!SetObjectFrame: view %d has no loops", viw);
+ if (lop < 0 || lop >= _GP(views)[viw].numLoops) quitprintf("!SetObjectFrame: invalid loop number used for view %d (%d, range is 0 - %d)", viw, lop, _GP(views)[viw].numLoops - 1);
// historically AGS let user to pass literally any positive invalid frame value by silently reassigning it to zero...
if (fra < 0 || fra >= _GP(views)[viw].loops[lop].numFrames) {
if (_GP(views)[viw].loops[lop].numFrames == 0)
diff --git a/engines/ags/shared/ac/view.cpp b/engines/ags/shared/ac/view.cpp
index fc390e489cc..d560eaeb27c 100644
--- a/engines/ags/shared/ac/view.cpp
+++ b/engines/ags/shared/ac/view.cpp
@@ -33,7 +33,7 @@ ViewFrame::ViewFrame()
, yoffs(0)
, speed(0)
, flags(0)
- , sound(0)
+ , sound(-1)
, audioclip(-1) {
reserved_for_future[0] = 0;
reserved_for_future[1] = 0;
diff --git a/engines/ags/shared/ac/view.h b/engines/ags/shared/ac/view.h
index cafcf04af63..2314be0a3c3 100644
--- a/engines/ags/shared/ac/view.h
+++ b/engines/ags/shared/ac/view.h
@@ -41,7 +41,7 @@ struct ViewFrame {
int pic;
short xoffs, yoffs;
short speed;
- int flags;
+ int flags; // VFLG_* flags
int sound; // play sound when this frame comes round
int reserved_for_future[2]; // kept only for plugin api
// not saved, set at runtime only
Commit: 92134389e6cb5b4c56fcd5ac38244fa8d64ec026
https://github.com/scummvm/scummvm/commit/92134389e6cb5b4c56fcd5ac38244fa8d64ec026
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Common: fixed crash if slider's handle set to negative sprite id
This is forbidden in the latest editor, but seems to be a possibility in
older editors (2.*).
>From upstream c1ba79d0cdb31b7704f889e953865fca4b175076
Changed paths:
engines/ags/shared/gui/gui_slider.cpp
diff --git a/engines/ags/shared/gui/gui_slider.cpp b/engines/ags/shared/gui/gui_slider.cpp
index 9c08ac2dcaa..2aa9632baf8 100644
--- a/engines/ags/shared/gui/gui_slider.cpp
+++ b/engines/ags/shared/gui/gui_slider.cpp
@@ -83,7 +83,7 @@ void GUISlider::UpdateMetrics() {
MaxValue = MinValue + 1;
Value = Math::Clamp(Value, MinValue, MaxValue);
// Test if sprite is available; // TODO: return a placeholder from spriteset instead!
- const int handle_im = _GP(spriteset)[HandleImage] ? HandleImage : 0;
+ const int handle_im = ((HandleImage > 0) && _GP(spriteset)[HandleImage]) ? HandleImage : 0;
// Depending on slider's orientation, thickness is either Height or Width
const int thickness = IsHorizontal() ? Height : Width;
@@ -179,7 +179,7 @@ void GUISlider::Draw(Bitmap *ds, int x, int y) {
}
// Test if sprite is available; // TODO: return a placeholder from spriteset instead!
- const int handle_im = _GP(spriteset)[HandleImage] ? HandleImage : 0;
+ const int handle_im = ((HandleImage > 0) && _GP(spriteset)[HandleImage]) ? HandleImage : 0;
if (handle_im > 0) // handle is a sprite
{
draw_gui_sprite(ds, handle_im, handle.Left, handle.Top, true);
Commit: 49e61b6ea2f7c717603fe19c434904a3c44082e7
https://github.com/scummvm/scummvm/commit/49e61b6ea2f7c717603fe19c434904a3c44082e7
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: let use dummy frame 0 if the speech view's loop is empty
This complements / fixes previous fix attempt 08aef03
>From upstream 95c99fc325f8550f220e7a0f67d6555bb23c8c5a
Changed paths:
engines/ags/engine/ac/character.cpp
engines/ags/engine/ac/draw.cpp
diff --git a/engines/ags/engine/ac/character.cpp b/engines/ags/engine/ac/character.cpp
index b80fc10b80a..e0db154cdcb 100644
--- a/engines/ags/engine/ac/character.cpp
+++ b/engines/ags/engine/ac/character.cpp
@@ -2414,15 +2414,12 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
if (viewWasLocked)
charFrameWas = speakingChar->frame;
- // If speech view is missing a loop or the loop does not have frames - use loop 0
- if (speakingChar->loop >= _GP(views)[speakingChar->view].numLoops ||
- _GP(views)[speakingChar->view].loops[speakingChar->loop].numFrames < 1) {
- String err = String::FromFormat("Character %s speech view %d does not have necessary loop %d or it has no frames",
- speakingChar->scrname, speakingChar->view + 1, speakingChar->loop);
- // is there even a fallback loop?
- if (_GP(views)[speakingChar->view].numLoops == 0 || _GP(views)[speakingChar->view].loops[0].numFrames == 0)
- quitprintf("!%s; and there's no valid loop to fall back.", err.GetCStr());
- debug_script_warn("WARNING: %s; switching to loop 0.", err.GetCStr());
+ if ((speakingChar->view < 0) || _GP(views)[speakingChar->view].numLoops == 0)
+ quitprintf("!Character %s current view %d is invalid, or has no loops.", speakingChar->scrname, speakingChar->view + 1);
+ // If current view is missing a loop - use loop 0
+ if (speakingChar->loop >= _GP(views)[speakingChar->view].numLoops) {
+ debug_script_warn("WARNING: Character %s current view %d does not have necessary loop %d; switching to loop 0.",
+ speakingChar->scrname, speakingChar->view + 1, speakingChar->loop);
speakingChar->loop = 0;
}
@@ -2654,15 +2651,12 @@ void _displayspeech(const char *texx, int aschar, int xx, int yy, int widd, int
speakingChar->frame = 0;
speakingChar->flags |= CHF_FIXVIEW;
- // If speech view is missing a loop or the loop does not have frames - use loop 0
- if (speakingChar->loop >= _GP(views)[speakingChar->view].numLoops ||
- _GP(views)[speakingChar->view].loops[speakingChar->loop].numFrames < 1) {
- String err = String::FromFormat("Character %s speech view %d does not have necessary loop %d or it has no frames",
- speakingChar->scrname, speakingChar->view + 1, speakingChar->loop);
- // is there even a fallback loop?
- if (_GP(views)[speakingChar->view].numLoops == 0 || _GP(views)[speakingChar->view].loops[0].numFrames == 0)
- quitprintf("!%s; and there's no valid loop to fall back.", err.GetCStr());
- debug_script_warn("WARNING: %s; switching to loop 0.", err.GetCStr());
+ if ((speakingChar->view < 0) || _GP(views)[speakingChar->view].numLoops == 0)
+ quitprintf("!Character %s speech view %d is invalid, or has no loops.", speakingChar->scrname, speakingChar->view + 1);
+ // If speech view is missing a loop - use loop 0
+ if (speakingChar->loop >= _GP(views)[speakingChar->view].numLoops) {
+ debug_script_warn("WARNING: Character %s speech view %d does not have necessary loop %d; switching to loop 0.",
+ speakingChar->scrname, speakingChar->view + 1, speakingChar->loop);
speakingChar->loop = 0;
}
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index d493e51e0a5..436510be156 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -1448,22 +1448,21 @@ void prepare_characters_for_drawing() {
CharacterInfo *chin = &_GP(game).chars[aa];
_G(our_eip) = 330;
- // if it's on but set to view -1, they're being silly
+ // Test for valid view and loop
if (chin->view < 0) {
quitprintf("!The character '%s' was turned on in the current room (room %d) but has not been assigned a view number.",
chin->name, _G(displayed_room));
}
-
+ if (chin->loop >= _GP(views)[chin->view].numLoops) {
+ quitprintf("!The character '%s' could not be displayed because there was no loop %d of view %d.",
+ chin->name, chin->loop, chin->view + 1);
+ continue; // FIXME: upstream does not break here
+ }
+ // If frame is too high -- fallback to the frame 0;
+ // there's always at least 1 dummy frame at index 0
if (chin->frame >= _GP(views)[chin->view].loops[chin->loop].numFrames)
chin->frame = 0;
- if ((chin->loop >= _GP(views)[chin->view].numLoops) ||
- (_GP(views)[chin->view].loops[chin->loop].numFrames < 1)) {
- warning("The character '%s' could not be displayed because there were no frames in loop %d of view %d.",
- chin->name, chin->loop, chin->view + 1);
- continue;
- }
-
sppic = _GP(views)[chin->view].loops[chin->loop].frames[chin->frame].pic;
if (sppic < 0)
sppic = 0; // in case it's screwed up somehow
Commit: 0fbdbdfcdd38bfc4db01c315d0b6a031b424dbe0
https://github.com/scummvm/scummvm/commit/0fbdbdfcdd38bfc4db01c315d0b6a031b424dbe0
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: fixed WaitInput() incorrect handling of a type arg
>From upstream ca6620951ec013e3627d962701c3cc25c1ac8adb
Changed paths:
engines/ags/engine/ac/global_game.cpp
diff --git a/engines/ags/engine/ac/global_game.cpp b/engines/ags/engine/ac/global_game.cpp
index 08a1cbd6606..1d87897232d 100644
--- a/engines/ags/engine/ac/global_game.cpp
+++ b/engines/ags/engine/ac/global_game.cpp
@@ -825,7 +825,7 @@ int WaitMouseKey(int nloops) {
}
int WaitInput(int input_flags, int nloops) {
- return WaitImpl(input_flags >> 16 | SKIP_AUTOTIMER, nloops);
+ return WaitImpl((input_flags >> SKIP_RESULT_TYPE_SHIFT) | SKIP_AUTOTIMER, nloops);
}
void SkipWait() {
Commit: ecc1d17655acefd8ee3a90f6421dd52a37e511cf
https://github.com/scummvm/scummvm/commit/ecc1d17655acefd8ee3a90f6421dd52a37e511cf
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: register missing SetProperty script functions for plugins
Reimplemented from upstream 96d52b258dd226bc8c2243c1a5bc95a9ceeecd2a
Changed paths:
engines/ags/engine/ac/character.h
engines/ags/engine/ac/hotspot.h
engines/ags/engine/ac/inventory_item.h
engines/ags/engine/ac/object.h
engines/ags/engine/ac/room.h
engines/ags/plugins/core/character.cpp
engines/ags/plugins/core/character.h
engines/ags/plugins/core/hotspot.cpp
engines/ags/plugins/core/hotspot.h
engines/ags/plugins/core/inventory_item.cpp
engines/ags/plugins/core/inventory_item.h
engines/ags/plugins/core/object.cpp
engines/ags/plugins/core/object.h
engines/ags/plugins/core/room.cpp
engines/ags/plugins/core/room.h
diff --git a/engines/ags/engine/ac/character.h b/engines/ags/engine/ac/character.h
index f9b701f5ea5..6b24bad1f77 100644
--- a/engines/ags/engine/ac/character.h
+++ b/engines/ags/engine/ac/character.h
@@ -70,6 +70,8 @@ ScriptOverlay *Character_SayBackground(CharacterInfo *chaa, const char *texx);
void Character_SetAsPlayer(CharacterInfo *chaa);
void Character_SetIdleView(CharacterInfo *chaa, int iview, int itime);
void Character_SetOption(CharacterInfo *chaa, int flag, int yesorno);
+bool Character_SetProperty(CharacterInfo *chaa, const char *property, int value);
+bool Character_SetTextProperty(CharacterInfo *chaa, const char *property, const char *value);
void Character_SetSpeed(CharacterInfo *chaa, int xspeed, int yspeed);
void Character_StopMoving(CharacterInfo *charp);
void Character_Tint(CharacterInfo *chaa, int red, int green, int blue, int opacity, int luminance);
diff --git a/engines/ags/engine/ac/hotspot.h b/engines/ags/engine/ac/hotspot.h
index 989381923c3..2559c5189fc 100644
--- a/engines/ags/engine/ac/hotspot.h
+++ b/engines/ags/engine/ac/hotspot.h
@@ -41,6 +41,8 @@ void Hotspot_RunInteraction(ScriptHotspot *hss, int mood);
int Hotspot_GetProperty(ScriptHotspot *hss, const char *property);
void Hotspot_GetPropertyText(ScriptHotspot *hss, const char *property, char *bufer);
const char *Hotspot_GetTextProperty(ScriptHotspot *hss, const char *property);
+bool Hotspot_SetProperty(ScriptHotspot *hss, const char *property, int value);
+bool Hotspot_SetTextProperty(ScriptHotspot *hss, const char *property, const char *value);
// Gets hotspot ID at the given room coordinates;
// if hotspot is disabled or non-existing, returns 0 (no area)
diff --git a/engines/ags/engine/ac/inventory_item.h b/engines/ags/engine/ac/inventory_item.h
index 44bf43515d3..318cc67e5d0 100644
--- a/engines/ags/engine/ac/inventory_item.h
+++ b/engines/ags/engine/ac/inventory_item.h
@@ -40,6 +40,8 @@ int InventoryItem_CheckInteractionAvailable(ScriptInvItem *iitem, int mood);
int InventoryItem_GetProperty(ScriptInvItem *scii, const char *property);
void InventoryItem_GetPropertyText(ScriptInvItem *scii, const char *property, char *bufer);
const char *InventoryItem_GetTextProperty(ScriptInvItem *scii, const char *property);
+bool InventoryItem_SetProperty(ScriptInvItem *scii, const char *property, int value);
+bool InventoryItem_SetTextProperty(ScriptInvItem *scii, const char *property, const char *value);
void set_inv_item_cursorpic(int invItemId, int piccy);
diff --git a/engines/ags/engine/ac/object.h b/engines/ags/engine/ac/object.h
index 28fe1c010e6..677d693bb80 100644
--- a/engines/ags/engine/ac/object.h
+++ b/engines/ags/engine/ac/object.h
@@ -94,6 +94,8 @@ void Object_RunInteraction(ScriptObject *objj, int mode);
int Object_GetProperty(ScriptObject *objj, const char *property);
void Object_GetPropertyText(ScriptObject *objj, const char *property, char *bufer);
const char *Object_GetTextProperty(ScriptObject *objj, const char *property);
+bool Object_SetProperty(ScriptObject *objj, const char *property, int value);
+bool Object_SetTextProperty(ScriptObject *objj, const char *property, const char *value);
void move_object(int objj, int tox, int toy, int spee, int ignwal);
void get_object_blocking_rect(int objid, int *x1, int *y1, int *width, int *y2);
diff --git a/engines/ags/engine/ac/room.h b/engines/ags/engine/ac/room.h
index 9ed38a4d1a4..bfae9f72d97 100644
--- a/engines/ags/engine/ac/room.h
+++ b/engines/ags/engine/ac/room.h
@@ -42,6 +42,8 @@ int Room_GetBottomEdge();
int Room_GetMusicOnLoad();
const char *Room_GetTextProperty(const char *property);
int Room_GetProperty(const char *property);
+bool Room_SetProperty(const char *property, int value);
+bool Room_SetTextProperty(const char *property, const char *value);
const char *Room_GetMessages(int index);
bool Room_Exists(int room);
RuntimeScriptValue Sc_Room_GetProperty(const RuntimeScriptValue *params, int32_t param_count);
diff --git a/engines/ags/plugins/core/character.cpp b/engines/ags/plugins/core/character.cpp
index 79985de9967..db604109d8d 100644
--- a/engines/ags/plugins/core/character.cpp
+++ b/engines/ags/plugins/core/character.cpp
@@ -72,6 +72,8 @@ void Character::AGS_EngineStartup(IAGSEngine *engine) {
SCRIPT_METHOD(Character::SetAsPlayer^0, Character::SetAsPlayer);
SCRIPT_METHOD(Character::SetIdleView^2, Character::SetIdleView);
//SCRIPT_METHOD(Character::SetOption^2", Character:: (void*)SetOption);
+ SCRIPT_METHOD(Character::SetProperty^2, Character::SetProperty);
+ SCRIPT_METHOD(Character::SetTextProperty^2, Character::SetTextProperty);
SCRIPT_METHOD(Character::SetWalkSpeed^2, Character::SetSpeed);
SCRIPT_METHOD(Character::StopMoving^0, Character::StopMoving);
SCRIPT_METHOD(Character::Think^101, Character::ScPl_Think);
@@ -353,6 +355,16 @@ void Character::SetIdleView(ScriptMethodParams ¶ms) {
AGS3::Character_SetIdleView(chaa, iview, itime);
}
+void Character::SetProperty(ScriptMethodParams ¶ms) {
+ PARAMS3(CharacterInfo *, chaa, const char *, property, int, value);
+ params._result = AGS3::Character_SetProperty(chaa, property, value);
+}
+
+void Character::SetTextProperty(ScriptMethodParams ¶ms) {
+ PARAMS3(CharacterInfo *, chaa, const char *, property, const char *, value);
+ params._result = AGS3::Character_SetTextProperty(chaa, property, value);
+}
+
void Character::SetSpeed(ScriptMethodParams ¶ms) {
PARAMS3(CharacterInfo *, chaa, int, xspeed, int, yspeed);
AGS3::Character_SetSpeed(chaa, xspeed, yspeed);
diff --git a/engines/ags/plugins/core/character.h b/engines/ags/plugins/core/character.h
index 46a96477398..2bd5bb6d717 100644
--- a/engines/ags/plugins/core/character.h
+++ b/engines/ags/plugins/core/character.h
@@ -70,6 +70,8 @@ public:
void SayBackground(ScriptMethodParams ¶ms);
void SetAsPlayer(ScriptMethodParams ¶ms);
void SetIdleView(ScriptMethodParams ¶ms);
+ void SetProperty(ScriptMethodParams ¶ms);
+ void SetTextProperty(ScriptMethodParams ¶ms);
void SetSpeed(ScriptMethodParams ¶ms);
void StopMoving(ScriptMethodParams ¶ms);
void ScPl_Think(ScriptMethodParams ¶ms);
diff --git a/engines/ags/plugins/core/hotspot.cpp b/engines/ags/plugins/core/hotspot.cpp
index acbacc53d69..67123231144 100644
--- a/engines/ags/plugins/core/hotspot.cpp
+++ b/engines/ags/plugins/core/hotspot.cpp
@@ -35,6 +35,8 @@ void Hotspot::AGS_EngineStartup(IAGSEngine *engine) {
SCRIPT_METHOD(Hotspot::GetProperty^1, Hotspot::GetProperty);
SCRIPT_METHOD(Hotspot::GetPropertyText^2, Hotspot::GetPropertyText);
SCRIPT_METHOD(Hotspot::GetTextProperty^1, Hotspot::GetTextProperty);
+ SCRIPT_METHOD(Hotspot::SetProperty^2, Hotspot::SetProperty);
+ SCRIPT_METHOD(Hotspot::SetTextProperty^2, Hotspot::SetTextProperty);
SCRIPT_METHOD(Hotspot::RunInteraction^1, Hotspot::RunInteraction);
SCRIPT_METHOD(Hotspot::get_Enabled, Hotspot::GetEnabled);
SCRIPT_METHOD(Hotspot::set_Enabled, Hotspot::SetEnabled);
@@ -74,6 +76,16 @@ void Hotspot::GetTextProperty(ScriptMethodParams ¶ms) {
params._result = AGS3::Hotspot_GetTextProperty(hss, property);
}
+void Hotspot::SetProperty(ScriptMethodParams ¶ms) {
+ PARAMS3(ScriptHotspot *, hss, const char *, property, int, value);
+ params._result = AGS3::Hotspot_SetProperty(hss, property, value);
+}
+
+void Hotspot::SetTextProperty(ScriptMethodParams ¶ms) {
+ PARAMS3(ScriptHotspot *, hss, const char *, property, const char *, value);
+ params._result = AGS3::Hotspot_SetTextProperty(hss, property, value);
+}
+
void Hotspot::RunInteraction(ScriptMethodParams ¶ms) {
PARAMS2(ScriptHotspot *, hss, int, mood);
AGS3::Hotspot_RunInteraction(hss, mood);
diff --git a/engines/ags/plugins/core/hotspot.h b/engines/ags/plugins/core/hotspot.h
index cf4417e247f..11e04146cc7 100644
--- a/engines/ags/plugins/core/hotspot.h
+++ b/engines/ags/plugins/core/hotspot.h
@@ -40,6 +40,8 @@ public:
void GetProperty(ScriptMethodParams ¶ms);
void GetPropertyText(ScriptMethodParams ¶ms);
void GetTextProperty(ScriptMethodParams ¶ms);
+ void SetProperty(ScriptMethodParams ¶ms);
+ void SetTextProperty(ScriptMethodParams ¶ms);
void RunInteraction(ScriptMethodParams ¶ms);
void GetEnabled(ScriptMethodParams ¶ms);
void SetEnabled(ScriptMethodParams ¶ms);
diff --git a/engines/ags/plugins/core/inventory_item.cpp b/engines/ags/plugins/core/inventory_item.cpp
index f1ae23147ad..e6f021c6bf1 100644
--- a/engines/ags/plugins/core/inventory_item.cpp
+++ b/engines/ags/plugins/core/inventory_item.cpp
@@ -35,6 +35,8 @@ void InventoryItem::AGS_EngineStartup(IAGSEngine *engine) {
SCRIPT_METHOD(InventoryItem::GetProperty ^ 1, InventoryItem::GetProperty);
SCRIPT_METHOD(InventoryItem::GetPropertyText ^ 2, InventoryItem::GetPropertyText);
SCRIPT_METHOD(InventoryItem::GetTextProperty ^ 1, InventoryItem::GetTextProperty);
+ SCRIPT_METHOD(InventoryItem::SetProperty ^ 2, InventoryItem::SetProperty);
+ SCRIPT_METHOD(InventoryItem::SetTextProperty ^ 2, InventoryItem::SetTextProperty);
SCRIPT_METHOD(InventoryItem::RunInteraction ^ 1, InventoryItem::RunInteraction);
SCRIPT_METHOD(InventoryItem::SetName ^ 1, InventoryItem::SetName);
SCRIPT_METHOD(InventoryItem::get_CursorGraphic, InventoryItem::GetCursorGraphic);
@@ -76,6 +78,16 @@ void InventoryItem::GetTextProperty(ScriptMethodParams ¶ms) {
params._result = AGS3::InventoryItem_GetTextProperty(scii, property);
}
+void InventoryItem::SetProperty(ScriptMethodParams ¶ms) {
+ PARAMS3(ScriptInvItem *, scii, const char *, property, int, value);
+ params._result = AGS3::InventoryItem_SetProperty(scii, property, value);
+}
+
+void InventoryItem::SetTextProperty(ScriptMethodParams ¶ms) {
+ PARAMS3(ScriptInvItem *, scii, const char *, property, const char *, value);
+ params._result = AGS3::InventoryItem_SetTextProperty(scii, property, value);
+}
+
void InventoryItem::RunInteraction(ScriptMethodParams ¶ms) {
PARAMS2(ScriptInvItem *, iitem, int, mood);
AGS3::InventoryItem_RunInteraction(iitem, mood);
diff --git a/engines/ags/plugins/core/inventory_item.h b/engines/ags/plugins/core/inventory_item.h
index deff3213723..3ddff343494 100644
--- a/engines/ags/plugins/core/inventory_item.h
+++ b/engines/ags/plugins/core/inventory_item.h
@@ -40,6 +40,8 @@ public:
void GetProperty(ScriptMethodParams ¶ms);
void GetPropertyText(ScriptMethodParams ¶ms);
void GetTextProperty(ScriptMethodParams ¶ms);
+ void SetProperty(ScriptMethodParams ¶ms);
+ void SetTextProperty(ScriptMethodParams ¶ms);
void RunInteraction(ScriptMethodParams ¶ms);
void SetName(ScriptMethodParams ¶ms);
void GetCursorGraphic(ScriptMethodParams ¶ms);
diff --git a/engines/ags/plugins/core/object.cpp b/engines/ags/plugins/core/object.cpp
index f00eeb7465a..3ef2887f421 100644
--- a/engines/ags/plugins/core/object.cpp
+++ b/engines/ags/plugins/core/object.cpp
@@ -35,6 +35,8 @@ void Object::AGS_EngineStartup(IAGSEngine *engine) {
SCRIPT_METHOD(Object::GetProperty^1, Object::GetProperty);
SCRIPT_METHOD(Object::GetPropertyText^2, Object::GetPropertyText);
SCRIPT_METHOD(Object::GetTextProperty^1, Object::GetTextProperty);
+ SCRIPT_METHOD(Object::SetProperty^2, Object::SetProperty);
+ SCRIPT_METHOD(Object::SetTextProperty^2, Object::SetTextProperty);
SCRIPT_METHOD(Object::MergeIntoBackground^0, Object::MergeIntoBackground);
SCRIPT_METHOD(Object::Move^5, Object::Move);
SCRIPT_METHOD(Object::RemoveTint^0, Object::RemoveTint);
@@ -109,6 +111,16 @@ void Object::GetTextProperty(ScriptMethodParams ¶ms) {
params._result = AGS3::Object_GetTextProperty(objj, property);
}
+void Object::SetProperty(ScriptMethodParams ¶ms) {
+ PARAMS3(ScriptObject *, objj, const char *, property, int, value);
+ params._result = AGS3::Object_SetProperty(objj, property, value);
+}
+
+void Object::SetTextProperty(ScriptMethodParams ¶ms) {
+ PARAMS3(ScriptObject *, objj, const char *, property, const char *, value);
+ params._result = AGS3::Object_SetTextProperty(objj, property, value);
+}
+
void Object::MergeIntoBackground(ScriptMethodParams ¶ms) {
PARAMS1(ScriptObject *, objj);
AGS3::Object_MergeIntoBackground(objj);
diff --git a/engines/ags/plugins/core/object.h b/engines/ags/plugins/core/object.h
index 90d095da6a2..5e4e9d5497f 100644
--- a/engines/ags/plugins/core/object.h
+++ b/engines/ags/plugins/core/object.h
@@ -40,6 +40,8 @@ public:
void GetProperty(ScriptMethodParams ¶ms);
void GetPropertyText(ScriptMethodParams ¶ms);
void GetTextProperty(ScriptMethodParams ¶ms);
+ void SetProperty(ScriptMethodParams ¶ms);
+ void SetTextProperty(ScriptMethodParams ¶ms);
void MergeIntoBackground(ScriptMethodParams ¶ms);
void Move(ScriptMethodParams ¶ms);
void RemoveTint(ScriptMethodParams ¶ms);
diff --git a/engines/ags/plugins/core/room.cpp b/engines/ags/plugins/core/room.cpp
index 0c3cf00b548..09ea3bf06e7 100644
--- a/engines/ags/plugins/core/room.cpp
+++ b/engines/ags/plugins/core/room.cpp
@@ -32,6 +32,8 @@ void Room::AGS_EngineStartup(IAGSEngine *engine) {
SCRIPT_METHOD(Room::GetDrawingSurfaceForBackground^1, Room::GetDrawingSurfaceForBackground);
SCRIPT_METHOD(Room::GetProperty^1, Room::GetProperty);
SCRIPT_METHOD(Room::GetTextProperty^1, Room::GetTextProperty);
+ SCRIPT_METHOD(Room::SetProperty^2, Room::SetProperty);
+ SCRIPT_METHOD(Room::SetTextProperty^2, Room::SetTextProperty);
SCRIPT_METHOD(Room::get_BottomEdge, Room::GetBottomEdge);
SCRIPT_METHOD(Room::get_ColorDepth, Room::GetColorDepth);
SCRIPT_METHOD(Room::get_Height, Room::GetHeight);
@@ -59,6 +61,16 @@ void Room::GetTextProperty(ScriptMethodParams ¶ms) {
params._result = AGS3::Room_GetTextProperty(property);
}
+void Room::SetProperty(ScriptMethodParams ¶ms) {
+ PARAMS2(const char *, property, int, value);
+ params._result = AGS3::Room_SetProperty(property, value);
+}
+
+void Room::SetTextProperty(ScriptMethodParams ¶ms) {
+ PARAMS2(const char *, property, const char *, value);
+ params._result = AGS3::Room_SetTextProperty(property, value);
+}
+
void Room::GetBottomEdge(ScriptMethodParams ¶ms) {
params._result = AGS3::Room_GetBottomEdge();
}
diff --git a/engines/ags/plugins/core/room.h b/engines/ags/plugins/core/room.h
index 0f509109752..d5d560a0b5e 100644
--- a/engines/ags/plugins/core/room.h
+++ b/engines/ags/plugins/core/room.h
@@ -37,6 +37,8 @@ public:
void GetDrawingSurfaceForBackground(ScriptMethodParams ¶ms);
void GetProperty(ScriptMethodParams ¶ms);
void GetTextProperty(ScriptMethodParams ¶ms);
+ void SetProperty(ScriptMethodParams ¶ms);
+ void SetTextProperty(ScriptMethodParams ¶ms);
void GetBottomEdge(ScriptMethodParams ¶ms);
void GetColorDepth(ScriptMethodParams ¶ms);
void GetHeight(ScriptMethodParams ¶ms);
Commit: 416c6982cddbb99b4335d30afd1ac7cb62479d6e
https://github.com/scummvm/scummvm/commit/416c6982cddbb99b4335d30afd1ac7cb62479d6e
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Updated build version (3.6.0.38)
>From upstream c9ce4cfc457713abadc6a1a4cfb4b47aa0667382
Changed paths:
engines/ags/shared/core/def_version.h
diff --git a/engines/ags/shared/core/def_version.h b/engines/ags/shared/core/def_version.h
index 24fc3c488fe..f50e937a2cf 100644
--- a/engines/ags/shared/core/def_version.h
+++ b/engines/ags/shared/core/def_version.h
@@ -22,9 +22,9 @@
#ifndef AGS_SHARED_CORE_DEFVERSION_H
#define AGS_SHARED_CORE_DEFVERSION_H
-#define ACI_VERSION_STR "3.6.0.37"
+#define ACI_VERSION_STR "3.6.0.38"
#if defined (RC_INVOKED) // for MSVC resource compiler
-#define ACI_VERSION_MSRC_DEF 3.6.0.37
+#define ACI_VERSION_MSRC_DEF 3.6.0.38
#endif
#define SPECIAL_VERSION ""
Commit: 91d7299405bea2b03568384410b628f1710f2b5d
https://github.com/scummvm/scummvm/commit/91d7299405bea2b03568384410b628f1710f2b5d
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: (again) fixed buttons not updated visually on interface enable
Complements / reimplements f310a08
>From upstream b0e2fe40c1d73674a7b868a87152be6029df6cac
Changed paths:
engines/ags/engine/ac/global_game.cpp
engines/ags/engine/ac/global_gui.cpp
engines/ags/engine/ac/gui.cpp
engines/ags/engine/ac/room.cpp
engines/ags/engine/game/savegame.cpp
engines/ags/engine/main/game_run.cpp
engines/ags/shared/gui/gui_main.cpp
engines/ags/shared/gui/gui_main.h
diff --git a/engines/ags/engine/ac/global_game.cpp b/engines/ags/engine/ac/global_game.cpp
index 1d87897232d..def0412c4cf 100644
--- a/engines/ags/engine/ac/global_game.cpp
+++ b/engines/ags/engine/ac/global_game.cpp
@@ -424,7 +424,7 @@ int SetGameOption(int opt, int setting) {
GUI::Options.DisabledStyle = static_cast<GuiDisableStyle>(_GP(game).options[OPT_DISABLEOFF]);
// If GUI was disabled at this time then also update it, as visual style could've changed
if (_GP(play).disabled_user_interface > 0) {
- GUI::MarkAllGUIForUpdate();
+ GUI::MarkAllGUIForUpdate(true, false);
}
} else if (opt == OPT_PORTRAITSIDE) {
if (setting == 0) // set back to Left
diff --git a/engines/ags/engine/ac/global_gui.cpp b/engines/ags/engine/ac/global_gui.cpp
index 8d3f2df278f..c74f09e7c64 100644
--- a/engines/ags/engine/ac/global_gui.cpp
+++ b/engines/ags/engine/ac/global_gui.cpp
@@ -75,8 +75,8 @@ void InterfaceOn(int ifn) {
debug_script_log("GUI %d turned on", ifn);
// modal interface
if (_GP(guis)[ifn].PopupStyle == kGUIPopupModal) PauseGame();
- // clear the cached mouse position
_GP(guis)[ifn].MarkControlsChanged();
+ _GP(guis)[ifn].ResetOverControl(); // clear the cached mouse position
_GP(guis)[ifn].Poll(_G(mousex), _G(mousey));
}
@@ -91,9 +91,9 @@ void InterfaceOff(int ifn) {
if (_GP(guis)[ifn].MouseOverCtrl >= 0) {
// Make sure that the overpic is turned off when the GUI goes off
_GP(guis)[ifn].GetControl(_GP(guis)[ifn].MouseOverCtrl)->OnMouseLeave();
- _GP(guis)[ifn].MouseOverCtrl = -1;
}
_GP(guis)[ifn].MarkControlsChanged();
+ _GP(guis)[ifn].ResetOverControl(); // clear the cached mouse position
// modal interface
if (_GP(guis)[ifn].PopupStyle == kGUIPopupModal) UnPauseGame();
}
@@ -207,11 +207,10 @@ void SetGUIBackgroundPic(int guin, int slotn) {
}
void DisableInterface() {
- if ((_GP(play).disabled_user_interface == 0) && // only if was enabled before
- (GUI::Options.DisabledStyle != kGuiDis_Unchanged)) {
- // If GUI looks change when disabled, then update them all
- GUI::MarkAllGUIForUpdate();
- }
+ // If GUI looks change when disabled, then mark all of them for redraw
+ bool redraw_gui = (_GP(play).disabled_user_interface == 0) && // only if was enabled before
+ (GUI::Options.DisabledStyle != kGuiDis_Unchanged);
+ GUI::MarkAllGUIForUpdate(redraw_gui, true);
_GP(play).disabled_user_interface++;
set_mouse_cursor(CURS_WAIT);
}
@@ -221,9 +220,8 @@ void EnableInterface() {
if (_GP(play).disabled_user_interface < 1) {
_GP(play).disabled_user_interface = 0;
set_default_cursor();
- if (GUI::Options.DisabledStyle != kGuiDis_Unchanged) { // If GUI looks change when disabled, then update them all
- GUI::MarkAllGUIForUpdate();
- }
+ // If GUI looks change when disabled, then mark all of them for redraw
+ GUI::MarkAllGUIForUpdate(GUI::Options.DisabledStyle != kGuiDis_Unchanged, true);
}
}
diff --git a/engines/ags/engine/ac/gui.cpp b/engines/ags/engine/ac/gui.cpp
index 0ad27e68c64..77e1f8b7a7a 100644
--- a/engines/ags/engine/ac/gui.cpp
+++ b/engines/ags/engine/ac/gui.cpp
@@ -445,9 +445,8 @@ void update_gui_disabled_status() {
}
if (all_buttons_was != _G(all_buttons_disabled)) {
- // As controls become enabled we must notify parent GUIs
- // to let them reset control-under-mouse detection
- GUI::MarkAllGUIForUpdate();
+ // Mark guis for redraw and reset control-under-mouse detection
+ GUI::MarkAllGUIForUpdate(GUI::Options.DisabledStyle != kGuiDis_Unchanged, true);
if (GUI::Options.DisabledStyle != kGuiDis_Unchanged) {
invalidate_screen();
}
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 2af5e39bd32..216df43bb6f 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -855,7 +855,7 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
_G(our_eip) = 220;
update_polled_stuff();
debug_script_log("Now in room %d", _G(displayed_room));
- GUI::MarkAllGUIForUpdate();
+ GUI::MarkAllGUIForUpdate(true, true);
pl_run_plugin_hooks(AGSE_ENTERROOM, _G(displayed_room));
}
@@ -892,8 +892,6 @@ void new_room(int newnum, CharacterInfo *forchar) {
if (_GP(usetup).clear_cache_on_room_change) {
// Delete all cached sprites
_GP(spriteset).DisposeAll();
-
- GUI::MarkAllGUIForUpdate();
}
load_new_room(newnum, forchar);
diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index 366b01239d7..9bcc575c63c 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -596,7 +596,7 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
recreate_overlay_ddbs();
- GUI::MarkAllGUIForUpdate();
+ GUI::MarkAllGUIForUpdate(true, true);
RestoreViewportsAndCameras(r_data);
diff --git a/engines/ags/engine/main/game_run.cpp b/engines/ags/engine/main/game_run.cpp
index e6ca01d049c..dd810b53e19 100644
--- a/engines/ags/engine/main/game_run.cpp
+++ b/engines/ags/engine/main/game_run.cpp
@@ -910,9 +910,8 @@ static int UpdateWaitMode() {
auto was_disabled_for = _G(restrict_until).disabled_for;
set_default_cursor();
- if (GUI::Options.DisabledStyle != kGuiDis_Unchanged) { // If GUI looks change when disabled, then update them all
- GUI::MarkAllGUIForUpdate();
- }
+ // If GUI looks change when disabled, then mark all of them for redraw
+ GUI::MarkAllGUIForUpdate(GUI::Options.DisabledStyle != kGuiDis_Unchanged, true);
_GP(play).disabled_user_interface--;
_G(restrict_until).disabled_for = 0;
@@ -956,9 +955,9 @@ static int GameTick() {
static void SetupLoopParameters(int untilwhat, const void *data_ptr = nullptr, int data1 = 0, int data2 = 0) {
_GP(play).disabled_user_interface++;
- if (GUI::Options.DisabledStyle != kGuiDis_Unchanged) { // If GUI looks change when disabled, then update them all
- GUI::MarkAllGUIForUpdate();
- }
+ // If GUI looks change when disabled, then mark all of them for redraw
+ GUI::MarkAllGUIForUpdate(GUI::Options.DisabledStyle != kGuiDis_Unchanged, true);
+
// Only change the mouse cursor if it hasn't been specifically changed first
// (or if it's speech, always change it)
if (((_G(cur_cursor) == _G(cur_mode)) || (untilwhat == UNTIL_NOOVERLAY)) &&
diff --git a/engines/ags/shared/gui/gui_main.cpp b/engines/ags/shared/gui/gui_main.cpp
index b72025a9d35..da159965122 100644
--- a/engines/ags/shared/gui/gui_main.cpp
+++ b/engines/ags/shared/gui/gui_main.cpp
@@ -208,6 +208,13 @@ void GUIMain::ClearChanged() {
_hasControlsChanged = false;
}
+void GUIMain::ResetOverControl() {
+ // Force it to re-check for which control is under the mouse
+ MouseWasAt.X = -1;
+ MouseWasAt.Y = -1;
+ MouseOverCtrl = -1;
+}
+
void GUIMain::AddControl(GUIControlType type, int32_t id, GUIObject *control) {
_ctrlRefs.emplace_back(type, id);
_controls.push_back(control);
@@ -681,11 +688,15 @@ void DrawTextAlignedHor(Bitmap *ds, const char *text, int font, color_t text_col
wouttext_outline(ds, line.X1, y, font, text_color, text);
}
-void MarkAllGUIForUpdate() {
+void MarkAllGUIForUpdate(bool redraw, bool reset_over_ctrl) {
for (auto &gui : _GP(guis)) {
- gui.MarkChanged();
- for (int i = 0; i < gui.GetControlCount(); ++i)
- gui.GetControl(i)->MarkChanged();
+ if (redraw) {
+ gui.MarkChanged();
+ for (int i = 0; i < gui.GetControlCount(); ++i)
+ gui.GetControl(i)->MarkChanged();
+ }
+ if (reset_over_ctrl)
+ gui.ResetOverControl();
}
}
@@ -788,7 +799,7 @@ static HError ResortGUI(bool bwcompat_ctrl_zorder = false) {
}
gui.ResortZOrder();
}
- MarkAllGUIForUpdate();
+ MarkAllGUIForUpdate(true, true);
return HError::None();
}
diff --git a/engines/ags/shared/gui/gui_main.h b/engines/ags/shared/gui/gui_main.h
index 6bcc115500b..f082b9017fe 100644
--- a/engines/ags/shared/gui/gui_main.h
+++ b/engines/ags/shared/gui/gui_main.h
@@ -73,41 +73,43 @@ public:
public:
GUIMain();
- void InitDefaults();
+ void InitDefaults();
// Tells if the gui background supports alpha channel
- bool HasAlphaChannel() const;
+ bool HasAlphaChannel() const;
// Tells if GUI will react on clicking on it
- bool IsClickable() const;
+ bool IsClickable() const;
// Tells if GUI's visibility is overridden and it won't be displayed on
// screen regardless of Visible property (until concealed mode is off).
- bool IsConcealed() const;
+ bool IsConcealed() const;
// Tells if gui is actually meant to be displayed on screen.
// Normally Visible property determines whether GUI is allowed to be seen,
// but there may be other settings that override it.
- bool IsDisplayed() const;
+ bool IsDisplayed() const;
// Tells if given coordinates are within interactable area of gui
// NOTE: this currently tests for actual visibility and Clickable property
- bool IsInteractableAt(int x, int y) const;
+ bool IsInteractableAt(int x, int y) const;
// Tells if gui is a text window
- bool IsTextWindow() const;
+ bool IsTextWindow() const;
// Tells if GUI is *allowed* to be displayed and interacted with.
// This does not necessarily mean that it is displayed right now, because
// GUI may be hidden for other reasons, including overriding behavior.
// For example GUI with kGUIPopupMouseY style will not be shown unless
// mouse cursor is at certain position on screen.
- bool IsVisible() const;
+ bool IsVisible() const;
// Tells if GUI has graphically changed recently
- bool HasChanged() const;
- bool HasControlsChanged() const;
+ bool HasChanged() const;
+ bool HasControlsChanged() const;
// Manually marks GUI as graphically changed
// NOTE: this only matters if GUI's own graphic changes (content, size etc),
// but not its state (visible) or texture drawing mode (transparency, etc).
- void MarkChanged();
- void MarkControlsChanged();
+ void MarkChanged();
+ void MarkControlsChanged();
// Clears changed flag
- void ClearChanged();
+ void ClearChanged();
+ // Resets control-under-mouse detection.
+ void ResetOverControl();
// Finds a control under given screen coordinates, returns control's child ID.
// Optionally allows extra leeway (offset in all directions) to let the user grab tiny controls.
@@ -228,7 +230,7 @@ void DrawTextAligned(Bitmap *ds, const char *text, int font, color_t text_color,
void DrawTextAlignedHor(Bitmap *ds, const char *text, int font, color_t text_color, int x1, int x2, int y, FrameAlignment align);
// Mark all existing GUI for redraw
-void MarkAllGUIForUpdate();
+void MarkAllGUIForUpdate(bool redraw, bool reset_over_ctrl);
// Mark all translatable GUI controls for redraw
void MarkForTranslationUpdate();
// Mark all GUI which use the given font for recalculate/redraw;
Commit: e0d2bc88604714ca6d1e99a953ee1cc577ddcec8
https://github.com/scummvm/scummvm/commit/e0d2bc88604714ca6d1e99a953ee1cc577ddcec8
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: Fix malloc/delete mismatch with RoomStatus::tsdata
>From upstream cf31083808f19ae314212e7b451709cfd5d6f05d
Changed paths:
engines/ags/engine/ac/room.cpp
engines/ags/engine/game/savegame_v321.cpp
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 216df43bb6f..b2139cc08b9 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -216,7 +216,7 @@ void save_room_data_segment() {
_G(croom)->tsdatasize = _G(roominst)->globaldatasize;
if (_G(croom)->tsdatasize > 0) {
- _G(croom)->tsdata = (char *)malloc(_G(croom)->tsdatasize + 10);
+ _G(croom)->tsdata = new char[_G(croom)->tsdatasize + 10];
memcpy(_G(croom)->tsdata, &_G(roominst)->globaldata[0], _G(croom)->tsdatasize);
}
diff --git a/engines/ags/engine/game/savegame_v321.cpp b/engines/ags/engine/game/savegame_v321.cpp
index aa9bdf8ca3e..440572c7a0e 100644
--- a/engines/ags/engine/game/savegame_v321.cpp
+++ b/engines/ags/engine/game/savegame_v321.cpp
@@ -135,7 +135,7 @@ static void restore_game_room_state(Stream *in) {
if (roomstat->beenhere) {
ReadRoomStatus_Aligned(roomstat, in);
if (roomstat->tsdatasize > 0) {
- roomstat->tsdata = (char *)malloc(roomstat->tsdatasize + 8); // JJS: Why allocate 8 additional bytes?
+ roomstat->tsdata = new char[roomstat->tsdatasize + 8]; // JJS: Why allocate 8 additional bytes?
in->Read(&roomstat->tsdata[0], roomstat->tsdatasize);
}
}
@@ -325,7 +325,7 @@ static void restore_game_displayed_room_status(Stream *in, RestoredData &r_data)
ReadRoomStatus_Aligned(&_GP(troom), in);
if (_GP(troom).tsdatasize > 0) {
- _GP(troom).tsdata = (char *)malloc(_GP(troom).tsdatasize + 5);
+ _GP(troom).tsdata = new char[_GP(troom).tsdatasize + 5];
in->Read(&_GP(troom).tsdata[0], _GP(troom).tsdatasize);
} else
_GP(troom).tsdata = nullptr;
Commit: 88f0170696dbd092282e27171978d93dd9da625b
https://github.com/scummvm/scummvm/commit/88f0170696dbd092282e27171978d93dd9da625b
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: Fixed RoomStatus::tsdata allocation of additional bytes
>From upstream 894ec8a85bd2c78438c8bfabee632b26f5323b07
Changed paths:
engines/ags/engine/ac/room.cpp
engines/ags/engine/game/savegame_v321.cpp
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index b2139cc08b9..26d04d6a72f 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -216,7 +216,7 @@ void save_room_data_segment() {
_G(croom)->tsdatasize = _G(roominst)->globaldatasize;
if (_G(croom)->tsdatasize > 0) {
- _G(croom)->tsdata = new char[_G(croom)->tsdatasize + 10];
+ _G(croom)->tsdata = new char[_G(croom)->tsdatasize];
memcpy(_G(croom)->tsdata, &_G(roominst)->globaldata[0], _G(croom)->tsdatasize);
}
diff --git a/engines/ags/engine/game/savegame_v321.cpp b/engines/ags/engine/game/savegame_v321.cpp
index 440572c7a0e..7a64440bbf4 100644
--- a/engines/ags/engine/game/savegame_v321.cpp
+++ b/engines/ags/engine/game/savegame_v321.cpp
@@ -135,7 +135,7 @@ static void restore_game_room_state(Stream *in) {
if (roomstat->beenhere) {
ReadRoomStatus_Aligned(roomstat, in);
if (roomstat->tsdatasize > 0) {
- roomstat->tsdata = new char[roomstat->tsdatasize + 8]; // JJS: Why allocate 8 additional bytes?
+ roomstat->tsdata = new char[roomstat->tsdatasize];
in->Read(&roomstat->tsdata[0], roomstat->tsdatasize);
}
}
@@ -325,7 +325,7 @@ static void restore_game_displayed_room_status(Stream *in, RestoredData &r_data)
ReadRoomStatus_Aligned(&_GP(troom), in);
if (_GP(troom).tsdatasize > 0) {
- _GP(troom).tsdata = new char[_GP(troom).tsdatasize + 5];
+ _GP(troom).tsdata = new char[_GP(troom).tsdatasize];
in->Read(&_GP(troom).tsdata[0], _GP(troom).tsdatasize);
} else
_GP(troom).tsdata = nullptr;
Commit: 26375b823b183b9529127cf79b40fe501425e6cc
https://github.com/scummvm/scummvm/commit/26375b823b183b9529127cf79b40fe501425e6cc
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: Used std::vector for RoomStatus::tsdata
>From upstream 849a0f3153511087bd93c4d7d1ba898d4ab28cfa
Changed paths:
engines/ags/engine/ac/room.cpp
engines/ags/engine/ac/room_status.cpp
engines/ags/engine/ac/room_status.h
engines/ags/engine/game/savegame_v321.cpp
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 26d04d6a72f..1754919c878 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -216,8 +216,8 @@ void save_room_data_segment() {
_G(croom)->tsdatasize = _G(roominst)->globaldatasize;
if (_G(croom)->tsdatasize > 0) {
- _G(croom)->tsdata = new char[_G(croom)->tsdatasize];
- memcpy(_G(croom)->tsdata, &_G(roominst)->globaldata[0], _G(croom)->tsdatasize);
+ _G(croom)->tsdata.resize(_G(croom)->tsdatasize);
+ memcpy(_G(croom)->tsdata.data(), &_G(roominst)->globaldata[0], _G(croom)->tsdatasize);
}
}
@@ -673,9 +673,9 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
else if (_GP(thisroom).CompiledScript != nullptr) {
compile_room_script();
if (_G(croom)->tsdatasize > 0) {
- if (_G(croom)->tsdatasize != _G(roominst)->globaldatasize)
+ if (_G(croom)->tsdatasize != (unsigned) _G(roominst)->globaldatasize)
quit("room script data segment size has changed");
- memcpy(&_G(roominst)->globaldata[0], _G(croom)->tsdata, _G(croom)->tsdatasize);
+ memcpy(&_G(roominst)->globaldata[0], _G(croom)->tsdata.data(), _G(croom)->tsdatasize);
}
}
_G(our_eip) = 207;
diff --git a/engines/ags/engine/ac/room_status.cpp b/engines/ags/engine/ac/room_status.cpp
index ef42d360920..7fc2508e8be 100644
--- a/engines/ags/engine/ac/room_status.cpp
+++ b/engines/ags/engine/ac/room_status.cpp
@@ -49,22 +49,16 @@ RoomStatus::RoomStatus() {
beenhere = 0;
numobj = 0;
tsdatasize = 0;
- tsdata = nullptr;
memset(®ion_enabled, 0, sizeof(region_enabled));
memset(&walkbehind_base, 0, sizeof(walkbehind_base));
memset(&interactionVariableValues, 0, sizeof(interactionVariableValues));
}
-RoomStatus::~RoomStatus() {
- if (tsdata)
- delete[] tsdata;
-}
+RoomStatus::~RoomStatus() {}
void RoomStatus::FreeScriptData() {
- if (tsdata)
- delete[] tsdata;
- tsdata = nullptr;
+ tsdata.clear();
tsdatasize = 0;
}
@@ -89,7 +83,7 @@ void RoomStatus::ReadFromFile_v321(Stream *in) {
int16_t dummy[MAX_LEGACY_ROOM_FLAGS]; // cannot seek with AlignedStream
in->ReadArrayOfInt16(dummy, MAX_LEGACY_ROOM_FLAGS); // flagstates (OBSOLETE)
- tsdatasize = in->ReadInt32();
+ tsdatasize = static_cast<uint32_t>(in->ReadInt32());
in->ReadInt32(); // tsdata
for (int i = 0; i < MAX_ROOM_HOTSPOTS; ++i) {
intrHotspot[i].ReadFromSavedgame_v321(in);
@@ -162,10 +156,10 @@ void RoomStatus::ReadFromSavegame(Stream *in, int save_ver) {
in->ReadArrayOfInt32(interactionVariableValues, MAX_GLOBAL_VARIABLES);
}
- tsdatasize = in->ReadInt32();
+ tsdatasize = static_cast<uint32_t>(in->ReadInt32());
if (tsdatasize) {
- tsdata = new char[tsdatasize];
- in->Read(tsdata, tsdatasize);
+ tsdata.resize(tsdatasize);
+ in->Read(tsdata.data(), tsdatasize);
}
}
@@ -199,9 +193,9 @@ void RoomStatus::WriteToSavegame(Stream *out) const {
out->WriteArrayOfInt32(interactionVariableValues, MAX_GLOBAL_VARIABLES);
}
- out->WriteInt32(tsdatasize);
+ out->WriteInt32(static_cast<int32_t>(tsdatasize));
if (tsdatasize)
- out->Write(tsdata, tsdatasize);
+ out->Write(tsdata.data(), tsdatasize);
}
// JJS: Replacement for the global roomstats array in the original engine.
diff --git a/engines/ags/engine/ac/room_status.h b/engines/ags/engine/ac/room_status.h
index 2562a267dbf..b708299f7a4 100644
--- a/engines/ags/engine/ac/room_status.h
+++ b/engines/ags/engine/ac/room_status.h
@@ -53,8 +53,8 @@ struct RoomStatus {
int beenhere = 0;
uint32_t numobj = 0;
std::vector<RoomObject> obj;
- int tsdatasize = 0;
- char *tsdata = nullptr;
+ uint32_t tsdatasize = 0;
+ std::vector<char> tsdata;
Interaction intrHotspot[MAX_ROOM_HOTSPOTS];
std::vector<Interaction> intrObject;
Interaction intrRegion[MAX_ROOM_REGIONS];
diff --git a/engines/ags/engine/game/savegame_v321.cpp b/engines/ags/engine/game/savegame_v321.cpp
index 7a64440bbf4..a409e0171ed 100644
--- a/engines/ags/engine/game/savegame_v321.cpp
+++ b/engines/ags/engine/game/savegame_v321.cpp
@@ -135,8 +135,8 @@ static void restore_game_room_state(Stream *in) {
if (roomstat->beenhere) {
ReadRoomStatus_Aligned(roomstat, in);
if (roomstat->tsdatasize > 0) {
- roomstat->tsdata = new char[roomstat->tsdatasize];
- in->Read(&roomstat->tsdata[0], roomstat->tsdatasize);
+ roomstat->tsdata.resize(roomstat->tsdatasize);
+ in->Read(roomstat->tsdata.data(), roomstat->tsdatasize);
}
}
}
@@ -325,10 +325,10 @@ static void restore_game_displayed_room_status(Stream *in, RestoredData &r_data)
ReadRoomStatus_Aligned(&_GP(troom), in);
if (_GP(troom).tsdatasize > 0) {
- _GP(troom).tsdata = new char[_GP(troom).tsdatasize];
- in->Read(&_GP(troom).tsdata[0], _GP(troom).tsdatasize);
+ _GP(troom).tsdata.resize(_GP(troom).tsdatasize);
+ in->Read(_GP(troom).tsdata.data(), _GP(troom).tsdatasize);
} else
- _GP(troom).tsdata = nullptr;
+ _GP(troom).tsdata.clear();
}
}
Commit: f58c4d9bdb24a1176b78e8e8734ca5fa1e292c04
https://github.com/scummvm/scummvm/commit/f58c4d9bdb24a1176b78e8e8734ca5fa1e292c04
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Common: replaced couple of smart ptr arrays with std::vector
>From upstream c1afae64fe348c64ee4a8c8888349ae267241395
Changed paths:
engines/ags/engine/ac/dialog.cpp
engines/ags/globals.h
engines/ags/shared/game/main_game_file.cpp
engines/ags/shared/game/main_game_file.h
diff --git a/engines/ags/engine/ac/dialog.cpp b/engines/ags/engine/ac/dialog.cpp
index fa10284709f..1223bdc745a 100644
--- a/engines/ags/engine/ac/dialog.cpp
+++ b/engines/ags/engine/ac/dialog.cpp
@@ -182,7 +182,7 @@ int run_dialog_script(int dialogID, int offse, int optionIndex) {
if (offse == -1)
return result;
- unsigned char *script = _G(old_dialog_scripts)[dialogID].get() + offse;
+ unsigned char *script = _G(old_dialog_scripts)[dialogID].data() + offse;
unsigned short param1 = 0;
unsigned short param2 = 0;
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 80498217e70..62fe79cd659 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -535,7 +535,7 @@ public:
int _said_text = 0;
int _longestline = 0;
// Old dialog support
- std::vector< std::shared_ptr<unsigned char> > _old_dialog_scripts;
+ std::vector<std::vector<uint8_t>> _old_dialog_scripts;
std::vector<String> _old_speech_lines;
/**@}*/
diff --git a/engines/ags/shared/game/main_game_file.cpp b/engines/ags/shared/game/main_game_file.cpp
index 187336ea71b..3419a5bba37 100644
--- a/engines/ags/shared/game/main_game_file.cpp
+++ b/engines/ags/shared/game/main_game_file.cpp
@@ -266,7 +266,7 @@ void ReadViews(GameSetupStruct &game, std::vector<ViewStruct> &views, Stream *in
}
void ReadDialogs(std::vector<DialogTopic> &dialog,
- std::vector< std::shared_ptr<unsigned char> > &old_dialog_scripts,
+ std::vector<std::vector<uint8_t>> &old_dialog_scripts,
std::vector<String> &old_dialog_src,
std::vector<String> &old_speech_lines,
Stream *in, GameDataVersion data_ver, int dlg_count) {
@@ -282,8 +282,8 @@ void ReadDialogs(std::vector<DialogTopic> &dialog,
old_dialog_src.resize(dlg_count);
for (int i = 0; i < dlg_count; ++i) {
// NOTE: originally this was read into dialog[i].optionscripts
- old_dialog_scripts[i].reset(Common::SharedPtr<unsigned char>(new unsigned char[dialog[i].codesize], Common::ArrayDeleter<unsigned char>()));
- in->Read(old_dialog_scripts[i].get(), dialog[i].codesize);
+ old_dialog_scripts[i].resize(dialog[i].codesize);
+ in->Read(old_dialog_scripts[i].data(), dialog[i].codesize);
// Encrypted text script
int script_text_len = in->ReadInt32();
@@ -685,10 +685,8 @@ HGameFileError ReadSpriteFlags(LoadedGameEntities &ents, Stream *in, GameDataVer
return new MainGameFileError(kMGFErr_TooManySprites, String::FromFormat("Count: %zu, max: %zu", sprcount, (size_t)SpriteCache::MAX_SPRITE_INDEX + 1));
ents.SpriteCount = sprcount;
- ents.SpriteFlags.clear();
ents.SpriteFlags.resize(sprcount);
-
- in->Read(&ents.SpriteFlags[0], sprcount);
+ in->Read(ents.SpriteFlags.data(), sprcount);
return HGameFileError::None();
}
diff --git a/engines/ags/shared/game/main_game_file.h b/engines/ags/shared/game/main_game_file.h
index 3b8cc59742d..5dced939921 100644
--- a/engines/ags/shared/game/main_game_file.h
+++ b/engines/ags/shared/game/main_game_file.h
@@ -120,12 +120,12 @@ struct LoadedGameEntities {
// Original sprite data (when it was read into const-sized arrays)
size_t SpriteCount;
- Common::Array<byte> SpriteFlags;
+ std::vector<uint8_t> SpriteFlags; // SPF_* flags
// Old dialog support
// legacy compiled dialog script of its own format,
// requires separate interpreting
- std::vector< std::shared_ptr<unsigned char> > OldDialogScripts;
+ std::vector<std::vector<uint8_t>> OldDialogScripts;
// probably, actual dialog script sources kept within some older games
std::vector<String> OldDialogSources;
// speech texts displayed during dialog
Commit: 2cffebe3a505d3a0cad212f7ef1606b73440d163
https://github.com/scummvm/scummvm/commit/2cffebe3a505d3a0cad212f7ef1606b73440d163
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: use unique_ptr to store raw image in ObjectCache
>From upstream a06d97dc88887395f3f961ab8e3fbda277733795
Changed paths:
engines/ags/engine/ac/draw.cpp
engines/ags/engine/ac/draw.h
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 436510be156..8fc1c72922c 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -388,7 +388,7 @@ void init_game_drawdata() {
_GP(charcache).resize(_GP(game).numcharacters);
for (int i = 0; i < MAX_ROOM_OBJECTS; ++i)
- _G(objcache)[i].image = nullptr;
+ _G(objcache)[i] = ObjectCache();
size_t actsps_num = _GP(game).numcharacters + MAX_ROOM_OBJECTS;
_GP(actsps).resize(actsps_num);
@@ -430,16 +430,12 @@ void dispose_room_drawdata() {
void clear_drawobj_cache() {
// clear the character cache
for (auto &cc : _GP(charcache)) {
- if (cc.in_use)
- delete cc.image;
- cc.image = nullptr;
- cc.in_use = false;
+ cc = ObjectCache();
}
// clear the object cache
for (int i = 0; i < MAX_ROOM_OBJECTS; ++i) {
- delete _G(objcache)[i].image;
- _G(objcache)[i].image = nullptr;
+ _G(objcache)[i] = ObjectCache();
}
// room overlays cache
@@ -1244,8 +1240,7 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
}
if ((!hardwareAccelerated) && (_G(gfxDriver)->HasAcceleratedTransform())) {
- // They want to draw it in software mode with the D3D driver,
- // so force a redraw
+ // They want to draw it in software mode with the D3D driver, so force a redraw
_G(objcache)[aa].sppic = -389538;
}
@@ -1272,7 +1267,7 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
(_G(walk_behind_baselines_changed) == 0))
return 1;
recycle_bitmap(actsp.Bmp, coldept, sprwidth, sprheight);
- actsp.Bmp->Blit(_G(objcache)[aa].image, 0, 0, 0, 0, _G(objcache)[aa].image->GetWidth(), _G(objcache)[aa].image->GetHeight());
+ actsp.Bmp->Blit(_G(objcache)[aa].image.get(), 0, 0, 0, 0, _G(objcache)[aa].image->GetWidth(), _G(objcache)[aa].image->GetHeight());
return 0;
}
@@ -1304,7 +1299,7 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
}
// Re-use the bitmap if it's the same size
- _G(objcache)[aa].image = recycle_bitmap(_G(objcache)[aa].image, coldept, sprwidth, sprheight);
+ recycle_bitmap(_G(objcache)[aa].image, coldept, sprwidth, sprheight);
// Create the cached image and store it
_G(objcache)[aa].image->Blit(actsp.Bmp.get(), 0, 0);
_G(objcache)[aa].sppic = _G(objs)[aa].num;
@@ -1535,7 +1530,7 @@ void prepare_characters_for_drawing() {
(_GP(charcache)[aa].lightlev == light_level)) {
if (_G(walkBehindMethod) == DrawOverCharSprite) {
recycle_bitmap(actsp.Bmp, _GP(charcache)[aa].image->GetColorDepth(), _GP(charcache)[aa].image->GetWidth(), _GP(charcache)[aa].image->GetHeight());
- actsp.Bmp->Blit(_GP(charcache)[aa].image, 0, 0);
+ actsp.Bmp->Blit(_GP(charcache)[aa].image.get(), 0, 0);
} else {
usingCachedImage = true;
}
@@ -1618,7 +1613,7 @@ void prepare_characters_for_drawing() {
// update the character cache with the new image
_GP(charcache)[aa].in_use = true;
- _GP(charcache)[aa].image = recycle_bitmap(_GP(charcache)[aa].image, coldept, actsp.Bmp->GetWidth(), actsp.Bmp->GetHeight());
+ recycle_bitmap(_GP(charcache)[aa].image, coldept, actsp.Bmp->GetWidth(), actsp.Bmp->GetHeight());
_GP(charcache)[aa].image->Blit(actsp.Bmp.get(), 0, 0);
} // end if !cache.inUse
diff --git a/engines/ags/engine/ac/draw.h b/engines/ags/engine/ac/draw.h
index ab457390151..c61509f099c 100644
--- a/engines/ags/engine/ac/draw.h
+++ b/engines/ags/engine/ac/draw.h
@@ -88,7 +88,7 @@ struct ObjTexture {
// ObjectCache stores cached object data, used to determine
// if active sprite / texture should be reconstructed
struct ObjectCache {
- Shared::Bitmap *image = nullptr;
+ std::unique_ptr<AGS::Shared::Bitmap> image;
bool in_use = false;
int sppic = 0;
short tintr = 0, tintg = 0, tintb = 0, tintamnt = 0, tintlight = 0;
Commit: 3d4856d321866b2e24ebd071b141a1f9fb6c17aa
https://github.com/scummvm/scummvm/commit/3d4856d321866b2e24ebd071b141a1f9fb6c17aa
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: for HW renderers - don't create redundant object cache images
I'm baffled how I did not notice this behavior earlier, but engine was
created at least 2 redundant intermediate bitmaps meant to cache
transformed sprites per each object and character on screen for
HW-accelerated renderers, - which they do not need, as they don't
use software transformations.
The resulting effect won't be too notable for low-res games with low
amount of simultaneous objects, but may be quite significant for the
high-res games with multiple large objects in the room.
>From upstream cca997fe83ec5f7014677a69095a7c9ec1494cd9
Changed paths:
engines/ags/engine/ac/draw.cpp
engines/ags/engine/ac/draw.h
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 8fc1c72922c..4f2b6453e07 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -92,6 +92,7 @@ ObjTexture::~ObjTexture() {
}
ObjTexture &ObjTexture::operator=(ObjTexture &&o) {
+ SpriteID = o.SpriteID;
if (Ddb) {
assert(_G(gfxDriver));
_G(gfxDriver)->DestroyDDB(Ddb);
@@ -790,7 +791,8 @@ Engine::IDriverDependantBitmap* recycle_ddb_sprite(Engine::IDriverDependantBitma
}
void sync_object_texture(ObjTexture &obj, bool has_alpha = false, bool opaque = false) {
- obj.Ddb = recycle_ddb_sprite(obj.Ddb, obj.SpriteID, obj.Bmp.get(), has_alpha, opaque);
+ Bitmap *use_bmp = obj.Bmp.get() ? obj.Bmp.get() : _GP(spriteset)[obj.SpriteID];
+ obj.Ddb = recycle_ddb_sprite(obj.Ddb, obj.SpriteID, use_bmp, has_alpha, opaque);
}
//------------------------------------------------------------------------
@@ -1026,11 +1028,12 @@ void get_local_tint(int xpp, int ypp, int nolight,
// Applies the specified RGB Tint or Light Level to the actsps
-// sprite indexed with actspsindex
-void apply_tint_or_light(int actspsindex, int light_level,
- int tint_amount, int tint_red, int tint_green,
- int tint_blue, int tint_light, int coldept,
- Bitmap *blitFrom) {
+// sprite indexed with actspsindex.
+// Used for software render mode only.
+static void apply_tint_or_light(int actspsindex, int light_level,
+ int tint_amount, int tint_red, int tint_green,
+ int tint_blue, int tint_light, int coldept,
+ Bitmap *blitFrom) {
// In a 256-colour game, we cannot do tinting or lightning
// (but we can do darkening, if light_level < 0)
@@ -1091,7 +1094,13 @@ void apply_tint_or_light(int actspsindex, int light_level,
}
}
-Bitmap *transform_sprite(Bitmap *src, bool src_has_alpha, std::unique_ptr<Bitmap> &dst, const Size dst_sz, GraphicFlip flip) {
+// Generates a transformed sprite, using src image and parameters;
+
+// * if transformation is necessary - writes into dst and returns dst;
+// * if no transformation is necessary - simply returns src;
+// Used for software render mode only.
+static Bitmap *transform_sprite(Bitmap *src, bool src_has_alpha, std::unique_ptr<Bitmap> &dst,
+ const Size dst_sz, GraphicFlip flip = Shared::kFlip_None) {
if ((src->GetSize() == dst_sz) && (flip == kFlip_None))
return src; // No transform: return source image
@@ -1133,7 +1142,8 @@ Bitmap *transform_sprite(Bitmap *src, bool src_has_alpha, std::unique_ptr<Bitmap
// Draws the specified 'sppic' sprite onto _GP(actsps)[useindx] at the
// specified width and height, and flips the sprite if necessary.
// Returns 1 if something was drawn to actsps; returns 0 if no
-// scaling or stretching was required, in which case nothing was done
+// scaling or stretching was required, in which case nothing was done.
+// Used for software render mode only.
static bool scale_and_flip_sprite(int useindx, int sppic, int newwidth, int newheight, bool hmirror) {
Bitmap *src = _GP(spriteset)[sppic];
Bitmap *result = transform_sprite(src, (_GP(game).SpriteInfos[sppic].Flags & SPF_ALPHACHANNEL) != 0,
@@ -1141,10 +1151,14 @@ static bool scale_and_flip_sprite(int useindx, int sppic, int newwidth, int newh
return result != src;
}
-// create the actsps[aa] image with the object drawn correctly
-// returns 1 if nothing at all has changed and actsps is still
-// intact from last time; 0 otherwise
-int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysUseSoftware) {
+// Create the actsps[aa] image with the object drawn correctly.
+// Returns true if nothing at all has changed and actsps is still
+// intact from last time; false otherwise.
+// Hardware-accelerated renderers always return true, because they do not
+// require altering the raw bitmap itself.
+// Except if alwaysUseSoftware is set, in which case even HW renderers
+// construct the image in software mode as well.
+bool construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysUseSoftware) {
bool hardwareAccelerated = !alwaysUseSoftware && _G(gfxDriver)->HasAcceleratedTransform();
if (_GP(spriteset)[_G(objs)[aa].num] == nullptr)
@@ -1221,12 +1235,13 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
const int useindx = aa; // actsps array index
auto &actsp = _GP(actsps)[useindx];
actsp.SpriteID = _G(objs)[aa].num; // for texture sharing
- if ((hardwareAccelerated) &&
- (_G(walkBehindMethod) != DrawOverCharSprite) &&
- (_G(objcache)[aa].image != nullptr) &&
- (_G(objcache)[aa].sppic == _G(objs)[aa].num) &&
- (actsp.Bmp != nullptr)) {
+ // NOTE: we need cached bitmap if:
+ // * it's a software renderer, otherwise
+ // * the walk-behind method is DrawOverCharSprite
+ if ((hardwareAccelerated) && (_G(walkBehindMethod) != DrawOverCharSprite)) {
// HW acceleration
+ bool has_texture_change = _G(objcache)[aa].sppic != _G(objs)[aa].num;
+ _G(objcache)[aa].sppic = _G(objs)[aa].num;
_G(objcache)[aa].tintamnt = tint_level;
_G(objcache)[aa].tintr = tint_red;
_G(objcache)[aa].tintg = tint_green;
@@ -1235,10 +1250,12 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
_G(objcache)[aa].lightlev = light_level;
_G(objcache)[aa].zoom = zoom_level;
_G(objcache)[aa].mirrored = isMirrored;
-
- return 1;
+ return has_texture_change;
}
+ //
+ // Software mode below
+ //
if ((!hardwareAccelerated) && (_G(gfxDriver)->HasAcceleratedTransform())) {
// They want to draw it in software mode with the D3D driver, so force a redraw
_G(objcache)[aa].sppic = -389538;
@@ -1258,17 +1275,17 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
// the image is the same, we can use it cached!
if ((_G(walkBehindMethod) != DrawOverCharSprite) &&
(actsp.Bmp != nullptr))
- return 1;
+ return true;
// Check if the X & Y co-ords are the same, too -- if so, there
// is scope for further optimisations
if ((_G(objcache)[aa].x == _G(objs)[aa].x) &&
(_G(objcache)[aa].y == _G(objs)[aa].y) &&
(actsp.Bmp != nullptr) &&
(_G(walk_behind_baselines_changed) == 0))
- return 1;
+ return true;
recycle_bitmap(actsp.Bmp, coldept, sprwidth, sprheight);
actsp.Bmp->Blit(_G(objcache)[aa].image.get(), 0, 0, 0, 0, _G(objcache)[aa].image->GetWidth(), _G(objcache)[aa].image->GetHeight());
- return 0;
+ return false; // image was modified
}
// Not cached, so draw the image
@@ -1279,7 +1296,6 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
actspsUsed = scale_and_flip_sprite(useindx, _G(objs)[aa].num, sprwidth, sprheight, isMirrored);
}
if (!actspsUsed) {
- // ensure actsps exists // CHECKME: why do we need this in hardware accel mode too?
recycle_bitmap(actsp.Bmp, coldept, src_sprwidth, src_sprheight);
}
@@ -1311,7 +1327,7 @@ int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysU
_G(objcache)[aa].lightlev = light_level;
_G(objcache)[aa].zoom = zoom_level;
_G(objcache)[aa].mirrored = isMirrored;
- return 0;
+ return false; // image was modified
}
// This is only called from draw_screen_background, but it's separated
@@ -1326,7 +1342,7 @@ void prepare_objects_for_drawing() {
continue;
int tehHeight;
- int actspsIntact = construct_object_gfx(aa, nullptr, &tehHeight, false);
+ bool actspsIntact = construct_object_gfx(aa, nullptr, &tehHeight, false);
const int useindx = aa; // actsps array index
auto &actsp = _GP(actsps)[useindx];
@@ -1580,8 +1596,10 @@ void prepare_characters_for_drawing() {
_GP(charcache)[aa].lightlev = light_level;
// If cache needs to be re-drawn
- if (!_GP(charcache)[aa].in_use) {
-
+ // NOTE: we need cached bitmap if:
+ // * it's a software renderer, otherwise
+ // * the walk-behind method is DrawOverCharSprite
+ if (((!_G(gfxDriver)->HasAcceleratedTransform()) || (_G(walkBehindMethod) == DrawOverCharSprite)) && !_GP(charcache)[aa].in_use) {
// create the base sprite in _GP(actsps)[useindx], which will
// be scaled and/or flipped, as appropriate
bool actspsUsed = false;
@@ -1616,7 +1634,7 @@ void prepare_characters_for_drawing() {
recycle_bitmap(_GP(charcache)[aa].image, coldept, actsp.Bmp->GetWidth(), actsp.Bmp->GetHeight());
_GP(charcache)[aa].image->Blit(actsp.Bmp.get(), 0, 0);
- } // end if !cache.inUse
+ } // end if !cache.in_use
int usebasel = chin->get_baseline();
diff --git a/engines/ags/engine/ac/draw.h b/engines/ags/engine/ac/draw.h
index c61509f099c..61af0eff02c 100644
--- a/engines/ags/engine/ac/draw.h
+++ b/engines/ags/engine/ac/draw.h
@@ -65,7 +65,8 @@ struct RoomCameraDrawData {
struct ObjTexture {
// Sprite ID
uint32_t SpriteID = UINT32_MAX;
- // Raw bitmap
+ // Raw bitmap; used for software render mode,
+ // or when particular object types require generated image.
std::unique_ptr<Shared::Bitmap> Bmp;
// Corresponding texture, created by renderer
Engine::IDriverDependantBitmap *Ddb = nullptr;
@@ -76,8 +77,8 @@ struct ObjTexture {
Point Off;
ObjTexture() = default;
- ObjTexture(Shared::Bitmap *bmp, Engine::IDriverDependantBitmap *ddb, int x, int y, int xoff = 0, int yoff = 0)
- : Bmp(bmp), Ddb(ddb), Pos(x, y), Off(xoff, yoff) {
+ ObjTexture(uint32_t sprite_id, Shared::Bitmap *bmp, Engine::IDriverDependantBitmap *ddb, int x, int y, int xoff = 0, int yoff = 0)
+ : SpriteID(sprite_id), Bmp(bmp), Ddb(ddb), Pos(x, y), Off(xoff, yoff) {
}
ObjTexture(ObjTexture &&o);
~ObjTexture();
@@ -180,11 +181,6 @@ void draw_gui_sprite_v330(Shared::Bitmap *ds, int pic, int x, int y, bool use_al
void draw_gui_sprite(Shared::Bitmap *ds, bool use_alpha, int xpos, int ypos,
Shared::Bitmap *image, bool src_has_alpha, Shared::BlendMode blend_mode = Shared::kBlendMode_Alpha, int alpha = 0xFF);
-// Generates a transformed sprite, using src image and parameters;
-// * if transformation is necessary - writes into dst and returns dst;
-// * if no transformation is necessary - simply returns src;
-Shared::Bitmap *transform_sprite(Shared::Bitmap *src, bool src_has_alpha, std::unique_ptr<Shared::Bitmap> &dst,
- const Size dst_sz, Shared::GraphicFlip flip = Shared::kFlip_None);
// Render game on screen
void render_to_screen();
// Callbacks for the graphics driver
@@ -192,10 +188,16 @@ void draw_game_screen_callback();
void GfxDriverOnInitCallback(void *data);
bool GfxDriverNullSpriteCallback(int x, int y);
void putpixel_compensate(Shared::Bitmap *g, int xx, int yy, int col);
-// create the actsps[aa] image with the object drawn correctly
-// returns 1 if nothing at all has changed and actsps is still
-// intact from last time; 0 otherwise
-int construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysUseSoftware);
+// Create the actsps[aa] image with the object drawn correctly.
+// Returns true if nothing at all has changed and actsps is still
+// intact from last time; false otherwise.
+// Hardware-accelerated do not require altering the raw bitmap itself,
+// so they only detect whether the sprite ID itself has changed.
+// Software renderers modify the cached bitmap whenever any visual
+// effect changes (scaling, tint, etc).
+// * alwaysUseSoftware option forces HW renderers to construct the image
+// in software mode as well.
+bool construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool alwaysUseSoftware);
// Returns a cached character image prepared for the render
Shared::Bitmap *get_cached_character_image(int charid);
// Returns a cached object image prepared for the render
Commit: 16658128f680e23d9426058fed1401aae3d24411
https://github.com/scummvm/scummvm/commit/16658128f680e23d9426058fed1401aae3d24411
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Common: revert lzwexpand to expanding to mem, for better speed
This somewhat reverts 2b9f130 , while keeping tidier code and safer args.
Switching from lzwexpand_to_mem to using streams only caused speed
regression, which became notable for hi-res games with LZW sprite
compression (a 3.6.0 feature).
For this revert we instead load compressed data into a buffer in whole,
then pass two memory buffer pointers to lzw_expand, where it reads
and writes memory directly.
Testing a high-res (1920x1080) game with lots of sprite streaming
showed speed improvement of this function by around 200%.
The downside is the temporary buffer for reading compressed
data too.
In theory, same could be done for lzwcompress afterwards.
>From upstream 6959004676916568c6fca210702d669f61741e13
Changed paths:
engines/ags/globals.h
engines/ags/shared/ac/sprite_file.cpp
engines/ags/shared/util/compress.cpp
engines/ags/shared/util/compress.h
engines/ags/shared/util/lzw.cpp
engines/ags/shared/util/lzw.h
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 62fe79cd659..de6c7f2c498 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -1064,7 +1064,7 @@ public:
uint8_t *_lzbuffer = nullptr;
int *_node = nullptr;
int _pos = 0;
- size_t _outbytes = 0, _maxsize = 0, _putbytes = 0;
+ size_t _outbytes = 0;
/**@}*/
diff --git a/engines/ags/shared/ac/sprite_file.cpp b/engines/ags/shared/ac/sprite_file.cpp
index 63160effa38..1148909334d 100644
--- a/engines/ags/shared/ac/sprite_file.cpp
+++ b/engines/ags/shared/ac/sprite_file.cpp
@@ -396,7 +396,7 @@ HError SpriteFile::LoadSprite(sprkey_t index, Shared::Bitmap *&sprite) {
switch (hdr.Compress) {
case kSprCompress_RLE: rle_decompress(im_data.Buf, im_data.Size, im_data.BPP, _stream.get());
break;
- case kSprCompress_LZW: lzw_decompress(im_data.Buf, im_data.Size, im_data.BPP, _stream.get());
+ case kSprCompress_LZW: lzw_decompress(im_data.Buf, im_data.Size, im_data.BPP, _stream.get(), in_data_size);
break;
default: assert(!"Unsupported compression type!"); break;
}
diff --git a/engines/ags/shared/util/compress.cpp b/engines/ags/shared/util/compress.cpp
index 9ab0bf97d73..cf93223c5ab 100644
--- a/engines/ags/shared/util/compress.cpp
+++ b/engines/ags/shared/util/compress.cpp
@@ -341,14 +341,15 @@ void lzw_compress(const uint8_t *data, size_t data_sz, int /*image_bpp*/, Shared
lzwcompress(&mem_in, out);
}
-void lzw_decompress(uint8_t *data, size_t data_sz, int /*image_bpp*/, Shared::Stream *in) {
+void lzw_decompress(uint8_t *data, size_t data_sz, int /*image_bpp*/, Shared::Stream *in, size_t in_sz) {
// LZW algorithm that we use fails on sequence less than 16 bytes.
if (data_sz < 16) {
in->Read(data, data_sz);
return;
}
- MemoryStream ms(data, data_sz, kStream_Write);
- lzwexpand(in, &ms, data_sz);
+ std::vector<uint8_t> in_buf(in_sz);
+ in->Read(in_buf.data(), in_sz);
+ lzwexpand(in_buf.data(), in_sz, data, data_sz);
}
void save_lzw(Stream *out, const Bitmap *bmpp, const RGB(*pal)[256]) {
@@ -401,11 +402,10 @@ Bitmap *load_lzw(Stream *in, int dst_bpp, RGB(*pal)[256]) {
const soff_t end_pos = in->GetPosition() + comp_sz;
// First decompress data into the memory buffer
- std::vector<uint8_t> membuf;
- {
- VectorStream memws(membuf, kStream_Write);
- lzwexpand(in, &memws, uncomp_sz);
- }
+ std::vector<uint8_t> inbuf(comp_sz);
+ std::vector<uint8_t> membuf(uncomp_sz);
+ in->Read(inbuf.data(), comp_sz);
+ lzwexpand(inbuf.data(), comp_sz, membuf.data(), uncomp_sz);
// Open same buffer for reading and get params and pixels
VectorStream mem_in(membuf);
diff --git a/engines/ags/shared/util/compress.h b/engines/ags/shared/util/compress.h
index d0c43c64d69..8172164390d 100644
--- a/engines/ags/shared/util/compress.h
+++ b/engines/ags/shared/util/compress.h
@@ -47,7 +47,7 @@ void skip_rle_bitmap8(Shared::Stream *in);
// LZW compression
void lzw_compress(const uint8_t *data, size_t data_sz, int image_bpp, Shared::Stream *out);
-void lzw_decompress(uint8_t *data, size_t data_sz, int image_bpp, Shared::Stream *in);
+void lzw_decompress(uint8_t *data, size_t data_sz, int image_bpp, Shared::Stream *in, size_t in_sz);
// Saves bitmap with an optional palette compressed by LZW
void save_lzw(Shared::Stream *out, const Shared::Bitmap *bmpp, const RGB(*pal)[256] = nullptr);
// Loads bitmap decompressing
diff --git a/engines/ags/shared/util/lzw.cpp b/engines/ags/shared/util/lzw.cpp
index 5ba42212a31..18c3aa516af 100644
--- a/engines/ags/shared/util/lzw.cpp
+++ b/engines/ags/shared/util/lzw.cpp
@@ -21,12 +21,13 @@
//=============================================================================
//
-// LZW compression -- the LZW/GIF patent has expired, so we can use it now!!!
+// LZW compression.
//
//=============================================================================
#include "ags/shared/util/lzw.h"
#include "ags/shared/ac/common.h" // quit
+#include "ags/shared/util/bbop.h"
#include "ags/shared/util/stream.h"
#include "ags/globals.h"
@@ -197,66 +198,61 @@ bool lzwcompress(Stream *lzw_in, Stream *out) {
return true;
}
-inline void myputc(uint8_t ccc, Stream *out) {
- if (_G(maxsize) > 0) {
- _G(putbytes)++;
- if (_G(putbytes) > _G(maxsize))
- return;
- }
-
- _G(outbytes)++;
- out->WriteInt8(ccc);
-}
-
-bool lzwexpand(Stream *lzw_in, Stream *out, size_t out_size) {
+bool lzwexpand(const uint8_t *src, size_t src_sz, uint8_t *dst, size_t dst_sz) {
int bits, ch, i, j, len, mask;
- char *lzbuffer;
- _G(outbytes) = 0; _G(putbytes) = 0;
- _G(maxsize) = out_size;
+ uint8_t *dst_ptr = dst;
+ const uint8_t *src_ptr = src;
- lzbuffer = (char *)malloc(N);
- if (lzbuffer == nullptr) {
- return false;
+ if (dst_sz == 0)
+ return false; // nowhere to expand to
+
+ _G(lzbuffer) = (uint8_t *)malloc(N);
+ if (_G(lzbuffer) == nullptr) {
+ return false; // not enough memory
}
i = N - F;
- // this end condition just checks for EOF, which is no good to us
- while ((bits = lzw_in->ReadByte()) != -1) {
+ // Read from the src and expand, until either src or dst runs out of space
+ while ((static_cast<size_t>(src_ptr - src) < src_sz) &&
+ (static_cast<size_t>(dst_ptr - dst) < dst_sz)) {
+ bits = *(src_ptr++);
for (mask = 0x01; mask & 0xFF; mask <<= 1) {
if (bits & mask) {
+ if (static_cast<size_t>(src_ptr - src) > (src_sz - sizeof(int16_t)))
+ break;
+
short jshort = 0;
- jshort = lzw_in->ReadInt16();
+ jshort = BBOp::Int16FromLE(*(reinterpret_cast<const int16_t *>(src_ptr)));
+ src_ptr += sizeof(int16_t);
j = jshort;
len = ((j >> 12) & 15) + 3;
j = (i - j - 1) & (N - 1);
+ if (static_cast<size_t>(dst_ptr - dst) > (dst_sz - len))
+ break; // not enough dest buffer
+
while (len--) {
- myputc(lzbuffer[i] = lzbuffer[j], out);
+ *(dst_ptr++) = (_G(lzbuffer)[i] = _G(lzbuffer)[j]);
j = (j + 1) & (N - 1);
i = (i + 1) & (N - 1);
}
} else {
- ch = lzw_in->ReadByte();
- myputc(lzbuffer[i] = ch, out);
+ ch = *(src_ptr++);
+ *(dst_ptr++) = (_G(lzbuffer)[i] = static_cast<uint8_t>(ch));
i = (i + 1) & (N - 1);
}
- if ((_G(putbytes) >= _G(maxsize)) && (_G(maxsize) > 0))
- break;
-
- if ((lzw_in->EOS()) && (_G(maxsize) > 0)) {
- free(lzbuffer);
- return false;
+ if ((static_cast<size_t>(dst_ptr - dst) >= dst_sz) ||
+ (static_cast<size_t>(src_ptr - src) >= src_sz)) {
+ break; // not enough dest buffer for the next pass
}
- } // end for mask
+ } // end for mask
- if ((_G(putbytes) >= _G(maxsize)) && (_G(maxsize) > 0))
- break;
}
- free(lzbuffer);
- return true;
+ free(_G(lzbuffer));
+ return (src_ptr - src) == src_sz;
}
} // namespace AGS3
diff --git a/engines/ags/shared/util/lzw.h b/engines/ags/shared/util/lzw.h
index 5ca4749e72c..e0be281aca5 100644
--- a/engines/ags/shared/util/lzw.h
+++ b/engines/ags/shared/util/lzw.h
@@ -35,7 +35,9 @@ class Stream;
using namespace AGS; // FIXME later
bool lzwcompress(Shared::Stream *lzw_in, Shared::Stream *out);
-bool lzwexpand(Shared::Stream *lzw_in, Shared::Stream *out, size_t out_size);
+// Expands lzw-compressed data from src to dst.
+// the dst buffer should be large enough, or the uncompression will not be complete.
+bool lzwexpand(const uint8_t *src, size_t src_sz, uint8_t *dst, size_t dst_sz);
} // namespace AGS3
Commit: 818b6705618e8f2dbb98a90a71c090313d9a892e
https://github.com/scummvm/scummvm/commit/818b6705618e8f2dbb98a90a71c090313d9a892e
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: fixed text parser could substring with negative length
The example when this could happen:
Parser.Said("climb,get in bed");
where "climb", "get" and "bed" are dictionary words.
>From upstream b633ca77076137e2402faa903f5b6fbcd3f4c3bc
Changed paths:
engines/ags/engine/ac/parser.cpp
diff --git a/engines/ags/engine/ac/parser.cpp b/engines/ags/engine/ac/parser.cpp
index edcc79ef0e4..4884a962a78 100644
--- a/engines/ags/engine/ac/parser.cpp
+++ b/engines/ags/engine/ac/parser.cpp
@@ -239,14 +239,15 @@ int parse_sentence(const char *src_text, int *numwords, short *wordarray, short
int continueSearching = 1;
while (continueSearching) {
- const char *textStart = &text[1];
+ const char *textStart = ++text; // begin with next char
+ // find where the next word ends
while ((text[0] == ',') || (Common::isAlnum((unsigned char)text[0]) != 0))
text++;
continueSearching = 0;
- if (text[0] == ' ') {
+ if (text[0] == 0 || text[0] == ' ') {
Common::strcpy_s(thisword, textStart);
thisword[text - textStart] = 0;
// forward past any multi-word alternatives
Commit: afed888bb5dbf6d87d148cc825072f673520c177
https://github.com/scummvm/scummvm/commit/afed888bb5dbf6d87d148cc825072f673520c177
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: avoid dirty rects outside software render surface
>From upstream c4dce7eb4a0ab4d2440a8b7e637ea8a7f9ed2c00
Changed paths:
engines/ags/engine/ac/draw_software.cpp
diff --git a/engines/ags/engine/ac/draw_software.cpp b/engines/ags/engine/ac/draw_software.cpp
index 4e2465c738f..5498031b40c 100644
--- a/engines/ags/engine/ac/draw_software.cpp
+++ b/engines/ags/engine/ac/draw_software.cpp
@@ -185,17 +185,20 @@ void invalidate_rect_on_surf(int x1, int y1, int x2, int y2, DirtyRects &rects)
return;
}
+ if (x1 > x2 || y1 > y2)
+ return;
+
int a;
const Size &surfsz = rects.SurfaceSize;
- if (x1 >= surfsz.Width) x1 = surfsz.Width - 1;
- if (y1 >= surfsz.Height) y1 = surfsz.Height - 1;
+
+ if (x1 >= surfsz.Width || y1 >= surfsz.Height || x2 < 0 || y2 < 0)
+ return;
+
if (x2 >= surfsz.Width) x2 = surfsz.Width - 1;
if (y2 >= surfsz.Height) y2 = surfsz.Height - 1;
if (x1 < 0) x1 = 0;
if (y1 < 0) y1 = 0;
- if (x2 < 0) x2 = 0;
- if (y2 < 0) y2 = 0;
rects.NumDirtyRegions++;
// ** Span code
Commit: 0f86678e2d0b40e52a1c61b726a680778b527369
https://github.com/scummvm/scummvm/commit/0f86678e2d0b40e52a1c61b726a680778b527369
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: only clear _stageScreen after it's dirty
>From upstream d60022c715f15d0454ffe04d4ce8d331c34e3045
Changed paths:
engines/ags/engine/gfx/gfx_driver_base.cpp
diff --git a/engines/ags/engine/gfx/gfx_driver_base.cpp b/engines/ags/engine/gfx/gfx_driver_base.cpp
index 1da1c80b7f7..f3ebcfa0f52 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.cpp
+++ b/engines/ags/engine/gfx/gfx_driver_base.cpp
@@ -247,14 +247,15 @@ bool VideoMemoryGraphicsDriver::DoNullSpriteCallback(int x, int y) {
if (!_nullSpriteCallback)
error("Unhandled attempt to draw null sprite");
_stageScreenDirty = false;
- _stageVirtualScreen->ClearTransparent();
// NOTE: this is not clear whether return value of callback may be
// relied on. Existing plugins do not seem to return anything but 0,
// even if they handle this event.
_stageScreenDirty |= _nullSpriteCallback(x, y) != 0;
if (_stageScreenDirty) {
- if (_stageVirtualScreenDDB)
+ if (_stageVirtualScreenDDB) {
UpdateDDBFromBitmap(_stageVirtualScreenDDB, _stageVirtualScreen.get(), true);
+ _stageVirtualScreen->ClearTransparent();
+ }
else
_stageVirtualScreenDDB = CreateDDBFromBitmap(_stageVirtualScreen.get(), true);
return true;
Commit: d6b03229d7c07f43fea2d87c6a5ab11a801b9d06
https://github.com/scummvm/scummvm/commit/d6b03229d7c07f43fea2d87c6a5ab11a801b9d06
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Common: move scanline safety check to assert
>From upstream 6804e9f4e09e12066fb33dc3dc03e3ce04c7846d
Changed paths:
engines/ags/shared/gfx/allegro_bitmap.h
diff --git a/engines/ags/shared/gfx/allegro_bitmap.h b/engines/ags/shared/gfx/allegro_bitmap.h
index d57fab036c9..7cc8333ece1 100644
--- a/engines/ags/shared/gfx/allegro_bitmap.h
+++ b/engines/ags/shared/gfx/allegro_bitmap.h
@@ -149,10 +149,12 @@ public:
// Get scanline for direct reading
inline const unsigned char *GetScanLine(int index) const {
- return (index >= 0 && index < GetHeight()) ? _alBitmap->getBasePtr(0, index) : nullptr;
+ assert(index >= 0 && index < GetHeight());
+ return _alBitmap->getBasePtr(0, index);
}
inline unsigned char *GetScanLine(int index) {
- return (index >= 0 && index < GetHeight()) ? (unsigned char *)_alBitmap->getBasePtr(0, index) : nullptr;
+ assert(index >= 0 && index < GetHeight());
+ return (unsigned char *)_alBitmap->getBasePtr(0, index);
}
// Get bitmap's mask color (transparent color)
Commit: 08133581934b6eaaa4e11ad835c0f923db678b5b
https://github.com/scummvm/scummvm/commit/08133581934b6eaaa4e11ad835c0f923db678b5b
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Fix empty statement warnings
Partially from upstream bb1ecf6f8b89dfaca7c7079e2183b982561004b8
Changed paths:
engines/ags/shared/font/fonts.cpp
diff --git a/engines/ags/shared/font/fonts.cpp b/engines/ags/shared/font/fonts.cpp
index c8977b6c0f1..8a71caa3be9 100644
--- a/engines/ags/shared/font/fonts.cpp
+++ b/engines/ags/shared/font/fonts.cpp
@@ -69,7 +69,7 @@ bool font_first_renderer_loaded() {
}
bool is_font_loaded(size_t fontNumber) {
- return fontNumber < _GP(fonts).size() && _GP(fonts)[fontNumber].Renderer != nullptr;;
+ return fontNumber < _GP(fonts).size() && _GP(fonts)[fontNumber].Renderer != nullptr;
}
// Finish font's initialization
Commit: a76b930e87ec78f4abbf717f08508fec8c25ef8e
https://github.com/scummvm/scummvm/commit/a76b930e87ec78f4abbf717f08508fec8c25ef8e
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Common: bufferedstream add default and remove unused break
>From upstream 957ad1ad7cb2d1df396f57de52c3808c28c53bb6
Changed paths:
engines/ags/shared/util/buffered_stream.cpp
diff --git a/engines/ags/shared/util/buffered_stream.cpp b/engines/ags/shared/util/buffered_stream.cpp
index 1bd0a076135..e26078fd01e 100644
--- a/engines/ags/shared/util/buffered_stream.cpp
+++ b/engines/ags/shared/util/buffered_stream.cpp
@@ -179,10 +179,10 @@ int32_t BufferedStream::WriteByte(uint8_t val) {
bool BufferedStream::Seek(soff_t offset, StreamSeek origin) {
soff_t want_pos = -1;
switch (origin) {
- case StreamSeek::kSeekCurrent: want_pos = _position + offset; break;
- case StreamSeek::kSeekBegin: want_pos = _start + offset; break;
- case StreamSeek::kSeekEnd: want_pos = _end + offset; break;
- default: break;
+ case StreamSeek::kSeekCurrent: want_pos = _position + offset; break;
+ case StreamSeek::kSeekBegin: want_pos = _start + offset; break;
+ case StreamSeek::kSeekEnd: want_pos = _end + offset; break;
+ default: return false;
}
// clamp
Commit: 8205b5b9329fbb019ac8179ce33d0266b3e3ef98
https://github.com/scummvm/scummvm/commit/8205b5b9329fbb019ac8179ce33d0266b3e3ef98
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Allegro: remove unused bmp_unwrite_line
Partially from upstream 4552d777f8fbe1a8364f2416795cf3214a10575e
Changed paths:
engines/ags/lib/aastr-0.1.1/aarot.cpp
engines/ags/lib/aastr-0.1.1/aastr.cpp
engines/ags/lib/allegro/gfx.cpp
engines/ags/lib/allegro/gfx.h
diff --git a/engines/ags/lib/aastr-0.1.1/aarot.cpp b/engines/ags/lib/aastr-0.1.1/aarot.cpp
index f05f90082d4..d8725bbde2a 100644
--- a/engines/ags/lib/aastr-0.1.1/aarot.cpp
+++ b/engines/ags/lib/aastr-0.1.1/aarot.cpp
@@ -516,8 +516,6 @@ static void _aa_rotate_bitmap(BITMAP *_src, BITMAP *_dst, int _x, int _y, fixed
aa_ADVANCE(*rsc, rscinc, rscdd, rsci1, rsci2);
aa_ADVANCE(rdx, rdxinc, rdxdd, rdxi1, rdxi2);
}
-
- bmp_unwrite_line(_dst);
}
/*
diff --git a/engines/ags/lib/aastr-0.1.1/aastr.cpp b/engines/ags/lib/aastr-0.1.1/aastr.cpp
index b3ac82194fc..334009dbc17 100644
--- a/engines/ags/lib/aastr-0.1.1/aastr.cpp
+++ b/engines/ags/lib/aastr-0.1.1/aastr.cpp
@@ -197,8 +197,6 @@ static void _aa_stretch_blit(BITMAP *_src, BITMAP *_dst,
aa_ADVANCE(sy, yinc, ydd, yi1, yi2);
}
-
- bmp_unwrite_line(_dst);
}
/*
diff --git a/engines/ags/lib/allegro/gfx.cpp b/engines/ags/lib/allegro/gfx.cpp
index 9ea88d6ec2a..1038823afac 100644
--- a/engines/ags/lib/allegro/gfx.cpp
+++ b/engines/ags/lib/allegro/gfx.cpp
@@ -202,10 +202,6 @@ byte *bmp_write_line(BITMAP *bmp, int line) {
return bmp->line[line];
}
-void bmp_unwrite_line(BITMAP *bmp) {
- // No implementation needed
-}
-
void bmp_write8(byte *addr, int color) {
*addr = color;
}
diff --git a/engines/ags/lib/allegro/gfx.h b/engines/ags/lib/allegro/gfx.h
index 019e579d94f..6b1ba3d4355 100644
--- a/engines/ags/lib/allegro/gfx.h
+++ b/engines/ags/lib/allegro/gfx.h
@@ -210,7 +210,6 @@ extern bool is_linear_bitmap(BITMAP *bmp);
extern bool is_planar_bitmap(BITMAP *bmp);
extern void bmp_select(BITMAP *bmp);
extern byte *bmp_write_line(BITMAP *bmp, int line);
-extern void bmp_unwrite_line(BITMAP *bmp);
extern void bmp_write8(byte *addr, int color);
extern void bmp_write15(byte *addr, int color);
extern void bmp_write16(byte *addr, int color);
Commit: bfc5f63026297c51caed54ad612eac1ce3f62a5d
https://github.com/scummvm/scummvm/commit/bfc5f63026297c51caed54ad612eac1ce3f62a5d
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS :Engine: draw fix, true means texture don't change
>From upstream d5958eab884c079c00845c35e46ef0302152ded5
Changed paths:
engines/ags/engine/ac/draw.cpp
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 4f2b6453e07..ad9aae4a1c6 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -1240,7 +1240,7 @@ bool construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool always
// * the walk-behind method is DrawOverCharSprite
if ((hardwareAccelerated) && (_G(walkBehindMethod) != DrawOverCharSprite)) {
// HW acceleration
- bool has_texture_change = _G(objcache)[aa].sppic != _G(objs)[aa].num;
+ bool is_texture_intact = _G(objcache)[aa].sppic != _G(objs)[aa].num;
_G(objcache)[aa].sppic = _G(objs)[aa].num;
_G(objcache)[aa].tintamnt = tint_level;
_G(objcache)[aa].tintr = tint_red;
@@ -1250,7 +1250,7 @@ bool construct_object_gfx(int aa, int *drawnWidth, int *drawnHeight, bool always
_G(objcache)[aa].lightlev = light_level;
_G(objcache)[aa].zoom = zoom_level;
_G(objcache)[aa].mirrored = isMirrored;
- return has_texture_change;
+ return is_texture_intact;
}
//
Commit: 2b028c586fc3365d79b9b4e9d3c5a86be72e61cd
https://github.com/scummvm/scummvm/commit/2b028c586fc3365d79b9b4e9d3c5a86be72e61cd
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: hotfixed BitmapToVideoMem after 6804e9f
>From upstream 0b3d4dc8b72cce99920bea44094a8c7a3e423f49
Changed paths:
engines/ags/engine/gfx/gfx_driver_base.cpp
diff --git a/engines/ags/engine/gfx/gfx_driver_base.cpp b/engines/ags/engine/gfx/gfx_driver_base.cpp
index f3ebcfa0f52..f197707b859 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.cpp
+++ b/engines/ags/engine/gfx/gfx_driver_base.cpp
@@ -347,9 +347,9 @@ void VideoMemoryGraphicsDriver::BitmapToVideoMem(const Bitmap *bitmap, const boo
bool lastPixelWasTransparent = false;
for (int y = 0; y < tile->height; y++) {
lastPixelWasTransparent = false;
- const uint8_t *scanline_before = bitmap->GetScanLine(y + tile->y - 1);
+ const uint8_t *scanline_before = (y > 0) ? bitmap->GetScanLine(y + tile->y - 1) : nullptr;
const uint8_t *scanline_at = bitmap->GetScanLine(y + tile->y);
- const uint8_t *scanline_after = bitmap->GetScanLine(y + tile->y + 1);
+ const uint8_t *scanline_after = (y < tile->height - 1) ? bitmap->GetScanLine(y + tile->y + 1) : nullptr;
unsigned int *memPtrLong = (unsigned int *)dst_ptr;
for (int x = 0; x < tile->width; x++) {
Commit: 2359c13d234375a0165b6f023f0f9bc90209f3b4
https://github.com/scummvm/scummvm/commit/2359c13d234375a0165b6f023f0f9bc90209f3b4
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: moved global sprite offset & flip to the parent batch transform
Partially from upstream 76a2a22ebfd5a8513337a64d6d4e857295ee38bc
Changed paths:
engines/ags/engine/ac/draw.cpp
engines/ags/engine/gfx/gfx_driver_base.cpp
engines/ags/engine/gfx/gfx_driver_base.h
engines/ags/engine/gfx/graphics_driver.h
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index ad9aae4a1c6..2be1ba117e9 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -687,7 +687,7 @@ void render_black_borders() {
void render_to_screen() {
// Stage: final plugin callback (still drawn on game screen
if (pl_any_want_hook(AGSE_FINALSCREENDRAW)) {
- _G(gfxDriver)->BeginSpriteBatch(_GP(play).GetMainViewport(), SpriteTransform(), Point(0, _GP(play).shake_screen_yoff), (GraphicFlip)_GP(play).screen_flipped);
+ _G(gfxDriver)->BeginSpriteBatch(_GP(play).GetMainViewport(), SpriteTransform(0, _GP(play).shake_screen_yoff), (GraphicFlip)_GP(play).screen_flipped);
_G(gfxDriver)->DrawSprite(AGSE_FINALSCREENDRAW, 0, nullptr);
_G(gfxDriver)->EndSpriteBatch();
}
@@ -701,11 +701,21 @@ void render_to_screen() {
while (!succeeded && !_G(want_exit) && !_G(abort_engine)) {
// try
// {
- // For software renderer, need to blacken upper part of the game frame when shaking screen moves image down
- const Rect &viewport = _GP(play).GetMainViewport();
- if (_GP(play).shake_screen_yoff > 0 && !_G(gfxDriver)->RequiresFullRedrawEachFrame())
- _G(gfxDriver)->ClearRectangle(viewport.Left, viewport.Top, viewport.GetWidth() - 1, _GP(play).shake_screen_yoff, nullptr);
- _G(gfxDriver)->Render(0, _GP(play).shake_screen_yoff, (GraphicFlip)_GP(play).screen_flipped);
+ if (_G(gfxDriver)->RequiresFullRedrawEachFrame()) {
+ _G(gfxDriver)->Render();
+ }
+ else {
+ // NOTE: the shake yoff and global flip here will only be used by a software renderer;
+ // as hw renderers have these as transform parameters for the parent scene nodes.
+ // This may be a matter for the future code improvement.
+ //
+ // For software renderer, need to blacken upper part of the game frame when shaking screen moves image down
+ if (_GP(play).shake_screen_yoff > 0) {
+ const Rect &viewport = _GP(play).GetMainViewport();
+ _G(gfxDriver)->ClearRectangle(viewport.Left, viewport.Top, viewport.GetWidth() - 1, _GP(play).shake_screen_yoff, nullptr);
+ }
+ _G(gfxDriver)->Render(0, _GP(play).shake_screen_yoff, (GraphicFlip)_GP(play).screen_flipped);
+ }
#if AGS_PLATFORM_OS_ANDROID
if (_GP(game).color_depth == 1)
@@ -2085,7 +2095,7 @@ static void construct_room_view() {
0.f);
if (_G(gfxDriver)->RequiresFullRedrawEachFrame()) {
// we draw everything as a sprite stack
- _G(gfxDriver)->BeginSpriteBatch(view_rc, room_trans, Point(0, _GP(play).shake_screen_yoff), (GraphicFlip)_GP(play).screen_flipped);
+ _G(gfxDriver)->BeginSpriteBatch(view_rc, room_trans);
} else {
if (_GP(CameraDrawData)[viewport->GetID()].Frame == nullptr && _GP(CameraDrawData)[viewport->GetID()].IsOverlap) {
// room background is prepended to the sprite stack
@@ -2102,7 +2112,7 @@ static void construct_room_view() {
} else {
// room background is drawn by dirty rects system
PBitmap bg_surface = draw_room_background(viewport.get());
- _G(gfxDriver)->BeginSpriteBatch(view_rc, room_trans, Point(), kFlip_None, bg_surface);
+ _G(gfxDriver)->BeginSpriteBatch(view_rc, room_trans, kFlip_None, bg_surface);
}
}
put_sprite_list_on_screen(true);
@@ -2114,7 +2124,7 @@ static void construct_room_view() {
// Schedule ui rendering
static void construct_ui_view() {
- _G(gfxDriver)->BeginSpriteBatch(_GP(play).GetUIViewportAbs(), SpriteTransform(), Point(0, _GP(play).shake_screen_yoff), (GraphicFlip)_GP(play).screen_flipped);
+ _G(gfxDriver)->BeginSpriteBatch(_GP(play).GetUIViewportAbs());
draw_gui_and_overlays();
_G(gfxDriver)->EndSpriteBatch();
clear_draw_list();
@@ -2194,6 +2204,10 @@ void construct_game_scene(bool full_redraw) {
if (_G(displayed_room) >= 0)
_GP(play).UpdateRoomCameras();
+ // Begin with the parent scene node, defining global offset and flip
+ _G(gfxDriver)->BeginSpriteBatch(_GP(play).GetMainViewport(), SpriteTransform(0, _GP(play).shake_screen_yoff),
+ (GraphicFlip)_GP(play).screen_flipped);
+
// Stage: room viewports
if (_GP(play).screen_is_faded_out == 0 && _GP(play).complete_overlay_on == 0) {
if (_G(displayed_room) >= 0) {
@@ -2211,21 +2225,15 @@ void construct_game_scene(bool full_redraw) {
if (_GP(play).screen_is_faded_out == 0) {
construct_ui_view();
}
-}
-void construct_game_screen_overlay(bool draw_mouse) {
- if (pl_any_want_hook(AGSE_POSTSCREENDRAW)) {
- _G(gfxDriver)->BeginSpriteBatch(_GP(play).GetMainViewport(),
- SpriteTransform(), Point(0, _GP(play).shake_screen_yoff),
- (GraphicFlip)_GP(play).screen_flipped);
- _G(gfxDriver)->DrawSprite(AGSE_POSTSCREENDRAW, 0, nullptr);
- _G(gfxDriver)->EndSpriteBatch();
- }
+ // End the parent scene node
+ _G(gfxDriver)->EndSpriteBatch();
+}
- // TODO: find out if it's okay to move cursor animation and state update
- // to the update loop instead of doing it in the drawing routine
+void update_mouse_cursor() {
+ // update mouse position (mousex, mousey)
+ ags_domouse();
// update animating mouse cursor
- ags_domouse(); // update mouse pos (mousex, mousey)
if (_GP(game).mcurs[_G(cur_cursor)].view >= 0) {
// only on mousemove, and it's not moving
if (((_GP(game).mcurs[_G(cur_cursor)].flags & MCF_ANIMMOVE) != 0) &&
@@ -2253,10 +2261,23 @@ void construct_game_screen_overlay(bool draw_mouse) {
_G(lastmx) = _G(mousex);
_G(lastmy) = _G(mousey);
}
+}
+
+void construct_game_screen_overlay(bool draw_mouse) {
+ if (pl_any_want_hook(AGSE_POSTSCREENDRAW)) {
+ _G(gfxDriver)->BeginSpriteBatch(_GP(play).GetMainViewport(), SpriteTransform(0, _GP(play).shake_screen_yoff), (GraphicFlip)_GP(play).screen_flipped);
+ _G(gfxDriver)->DrawSprite(AGSE_POSTSCREENDRAW, 0, nullptr);
+ _G(gfxDriver)->EndSpriteBatch();
+ }
+
+ // TODO: find out if it's okay to move cursor animation and state update
+ // to the update loop instead of doing it in the drawing routine
+ update_mouse_cursor();
+ // Add mouse cursor pic, and global screen tint effect
if (_GP(play).screen_is_faded_out == 0) {
// Stage: mouse cursor
- _G(gfxDriver)->BeginSpriteBatch(_GP(play).GetMainViewport(), SpriteTransform(), Point(0, _GP(play).shake_screen_yoff), (GraphicFlip)_GP(play).screen_flipped);
+ _G(gfxDriver)->BeginSpriteBatch(_GP(play).GetMainViewport(), SpriteTransform(0, _GP(play).shake_screen_yoff), (GraphicFlip)_GP(play).screen_flipped);
if (draw_mouse && !_GP(play).mouse_cursor_hidden) {
_G(gfxDriver)->DrawSprite(_G(mousex) - _G(hotx), _G(mousey) - _G(hoty), _G(mouseCursor));
invalidate_sprite(_G(mousex) - _G(hotx), _G(mousey) - _G(hoty), _G(mouseCursor), false);
@@ -2270,6 +2291,7 @@ void construct_game_screen_overlay(bool draw_mouse) {
render_black_borders();
}
+ // Add global screen fade effect
if (_GP(play).screen_is_faded_out != 0 && _G(gfxDriver)->RequiresFullRedrawEachFrame()) {
_G(gfxDriver)->BeginSpriteBatch(_GP(play).GetMainViewport(), SpriteTransform());
_G(gfxDriver)->SetScreenFade(_GP(play).fade_to_red, _GP(play).fade_to_green, _GP(play).fade_to_blue);
@@ -2419,7 +2441,7 @@ void render_graphics(IDriverDependantBitmap *extraBitmap, int extraX, int extraY
// TODO: extraBitmap is a hack, used to place an additional gui element
// on top of the screen. Normally this should be a part of the game UI stage.
if (extraBitmap != nullptr) {
- _G(gfxDriver)->BeginSpriteBatch(_GP(play).GetUIViewportAbs(), SpriteTransform(), Point(0, _GP(play).shake_screen_yoff), (GraphicFlip)_GP(play).screen_flipped);
+ _G(gfxDriver)->BeginSpriteBatch(_GP(play).GetUIViewportAbs(), SpriteTransform(0, _GP(play).shake_screen_yoff), (GraphicFlip)_GP(play).screen_flipped);
invalidate_sprite(extraX, extraY, extraBitmap, false);
_G(gfxDriver)->DrawSprite(extraX, extraY, extraBitmap);
_G(gfxDriver)->EndSpriteBatch();
diff --git a/engines/ags/engine/gfx/gfx_driver_base.cpp b/engines/ags/engine/gfx/gfx_driver_base.cpp
index f197707b859..9480f04cc5b 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.cpp
+++ b/engines/ags/engine/gfx/gfx_driver_base.cpp
@@ -66,8 +66,8 @@ Rect GraphicsDriverBase::GetRenderDestination() const {
}
void GraphicsDriverBase::BeginSpriteBatch(const Rect &viewport, const SpriteTransform &transform,
- const Point offset, GraphicFlip flip, PBitmap surface) {
- _spriteBatchDesc.push_back(SpriteBatchDesc(_actSpriteBatch, viewport, transform, offset, flip, surface));
+ GraphicFlip flip, PBitmap surface) {
+ _spriteBatchDesc.push_back(SpriteBatchDesc(_actSpriteBatch, viewport, transform, flip, surface));
_actSpriteBatch = _spriteBatchDesc.size() - 1;
InitSpriteBatch(_actSpriteBatch, _spriteBatchDesc[_actSpriteBatch]);
}
diff --git a/engines/ags/engine/gfx/gfx_driver_base.h b/engines/ags/engine/gfx/gfx_driver_base.h
index e7003528725..ba8aaa25602 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.h
+++ b/engines/ags/engine/gfx/gfx_driver_base.h
@@ -51,20 +51,17 @@ struct SpriteBatchDesc {
Rect Viewport;
// Optional model transformation, to be applied to each sprite
SpriteTransform Transform;
- // Global node offset applied to the whole batch as the last transform
- Point Offset;
- // Global node flip applied to the whole batch as the last transform
+ // Optional flip, applied to the whole batch as the last transform
Shared::GraphicFlip Flip = Shared::kFlip_None;
// Optional bitmap to draw sprites upon. Used exclusively by the software rendering mode.
PBitmap Surface;
SpriteBatchDesc() = default;
- SpriteBatchDesc(uint32_t parent, const Rect viewport, const SpriteTransform & transform, const Point offset = Point(),
+ SpriteBatchDesc(uint32_t parent, const Rect viewport, const SpriteTransform & transform,
Shared::GraphicFlip flip = Shared::kFlip_None, PBitmap surface = nullptr)
: Parent(parent)
, Viewport(viewport)
, Transform(transform)
- , Offset(offset)
, Flip(flip)
, Surface(surface) {
}
@@ -105,7 +102,7 @@ public:
Rect GetRenderDestination() const override;
void BeginSpriteBatch(const Rect &viewport, const SpriteTransform &transform,
- const Point offset = Point(), Shared::GraphicFlip flip = Shared::kFlip_None, PBitmap surface = nullptr) override;
+ Shared::GraphicFlip flip = Shared::kFlip_None, PBitmap surface = nullptr) override;
void EndSpriteBatch() override;
void ClearDrawLists() override;
diff --git a/engines/ags/engine/gfx/graphics_driver.h b/engines/ags/engine/gfx/graphics_driver.h
index 92012fdf12a..58e0e53d047 100644
--- a/engines/ags/engine/gfx/graphics_driver.h
+++ b/engines/ags/engine/gfx/graphics_driver.h
@@ -152,8 +152,8 @@ public:
// sprites to this batch's list.
// Beginning a batch while the previous was not ended will create a sub-batch
// (think of it as of a child scene node).
- virtual void BeginSpriteBatch(const Rect &viewport, const SpriteTransform &transform,
- const Point offset = Point(), Shared::GraphicFlip flip = Shared::kFlip_None, PBitmap surface = nullptr) = 0;
+ virtual void BeginSpriteBatch(const Rect &viewport, const SpriteTransform &transform = SpriteTransform(),
+ Shared::GraphicFlip flip = Shared::kFlip_None, PBitmap surface = nullptr) = 0;
// Ends current sprite batch
virtual void EndSpriteBatch() = 0;
// Adds sprite to the active batch
Commit: b7080efc96ff18cd8291a581733b1f68a9ec46b9
https://github.com/scummvm/scummvm/commit/b7080efc96ff18cd8291a581733b1f68a9ec46b9
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: for hw renderers split viewport and camera in 2 sprite batches
Partially from upstream 5d6c075013a0c83fb2ad5b58f0313e5e2eb4f728
Changed paths:
engines/ags/engine/ac/draw.cpp
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 2be1ba117e9..8f302eedff9 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -2021,7 +2021,7 @@ void draw_gui_and_overlays() {
if (s.id < 0) continue; // not a group parent (gui)
// Create a sub-batch
_G(gfxDriver)->BeginSpriteBatch(RectWH(s.x, s.y, s.ddb->GetWidth(), s.ddb->GetHeight()),
- SpriteTransform(0, 0, 1.f, 1.f, 0.f, s.ddb->GetAlpha()));
+ SpriteTransform(s.x, s.y, 1.f, 1.f, 0.f, s.ddb->GetAlpha()));
const int draw_index = _GP(guiobjddbref)[s.id];
for (const auto &obj_id : _GP(guis)[s.id].GetControlsDrawOrder()) {
GUIObject *obj = _GP(guis)[s.id].GetControl(obj_id);
@@ -2089,14 +2089,25 @@ static void construct_room_view() {
continue;
const Rect &view_rc = _GP(play).GetRoomViewportAbs(viewport->GetID());
const Rect &cam_rc = camera->GetRect();
- SpriteTransform room_trans(-cam_rc.Left, -cam_rc.Top,
- (float)view_rc.GetWidth() / (float)cam_rc.GetWidth(),
- (float)view_rc.GetHeight() / (float)cam_rc.GetHeight(),
- 0.f);
+ const float view_sx = (float)view_rc.GetWidth() / (float)cam_rc.GetWidth();
+ const float view_sy = (float)view_rc.GetHeight() / (float)cam_rc.GetHeight();
+
if (_G(gfxDriver)->RequiresFullRedrawEachFrame()) {
- // we draw everything as a sprite stack
- _G(gfxDriver)->BeginSpriteBatch(view_rc, room_trans);
+ // For hw renderer we draw everything as a sprite stack;
+ // viewport-camera pair is done as 2 nested scene nodes,
+ // where first defines how camera's image translates into the viewport on screen,
+ // and second - how room's image translates into the camera.
+ _G(gfxDriver)->BeginSpriteBatch(view_rc, SpriteTransform(view_rc.Left, view_rc.Top, view_sx, view_sy));
+ _G(gfxDriver)->BeginSpriteBatch(Rect(), SpriteTransform(-cam_rc.Left, -cam_rc.Top));
+ put_sprite_list_on_screen(true);
+ _G(gfxDriver)->EndSpriteBatch();
+ _G(gfxDriver)->EndSpriteBatch();
} else {
+ // For software renderer - combine viewport and camera in one batch,
+ // due to how the room drawing is implemented currently in the software mode.
+ // TODO: review this later?
+ SpriteTransform room_trans(-cam_rc.Left, -cam_rc.Top, view_sx, view_sy, 0.f);
+
if (_GP(CameraDrawData)[viewport->GetID()].Frame == nullptr && _GP(CameraDrawData)[viewport->GetID()].IsOverlap) {
// room background is prepended to the sprite stack
// TODO: here's why we have blit whole piece of background now:
@@ -2114,9 +2125,9 @@ static void construct_room_view() {
PBitmap bg_surface = draw_room_background(viewport.get());
_G(gfxDriver)->BeginSpriteBatch(view_rc, room_trans, kFlip_None, bg_surface);
}
- }
put_sprite_list_on_screen(true);
_G(gfxDriver)->EndSpriteBatch();
+ }
}
clear_draw_list();
Commit: 7825fc3c638d263d95d979c8b1e43737b227476c
https://github.com/scummvm/scummvm/commit/7825fc3c638d263d95d979c8b1e43737b227476c
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Common: unswitch loop in indexed bitmap unpacking
>From upstream 689b7ee8573194eea8f72375fbdd56b849ca7e81
Changed paths:
engines/ags/shared/ac/sprite_file.cpp
diff --git a/engines/ags/shared/ac/sprite_file.cpp b/engines/ags/shared/ac/sprite_file.cpp
index 1148909334d..aa8a542d21e 100644
--- a/engines/ags/shared/ac/sprite_file.cpp
+++ b/engines/ags/shared/ac/sprite_file.cpp
@@ -109,17 +109,29 @@ static void UnpackIndexedBitmap(Bitmap *image, const uint8_t *data, size_t data_
const uint8_t bpp = image->GetBPP();
const size_t dst_size = image->GetWidth() * image->GetHeight() * image->GetBPP();
uint8_t *dst = image->GetDataForWriting(), *dst_end = dst + dst_size;
- for (size_t p = 0; (p < data_size) && (dst < dst_end); ++p, dst += bpp) {
- uint8_t index = data[p];
- assert(index < pal_count);
- uint32_t color = (index < pal_count) ? palette[index] : palette[0];
- switch (bpp) {
- case 2: *((uint16_t *)dst) = color; break;
- case 4: *((uint32_t *)dst) = color; break;
- default: assert(0); return;
+
+ switch (bpp) {
+ case 2:
+ for (size_t p = 0; (p < data_size) && (dst < dst_end); ++p, dst += bpp) {
+ uint8_t index = data[p];
+ assert(index < pal_count);
+ uint32_t color = palette[(index < pal_count) ? index : 0];
+ *((uint16_t *)dst) = color;
+ }
+ break;
+ case 4:
+ for (size_t p = 0; (p < data_size) && (dst < dst_end); ++p, dst += bpp) {
+ uint8_t index = data[p];
+ assert(index < pal_count);
+ uint32_t color = palette[(index < pal_count) ? index : 0];
+ *((uint32_t *)dst) = color;
+ }
+ break;
+ default:
+ assert(0);
+ return;
}
}
-}
static inline SpriteFormat PaletteFormatForBPP(int bpp) {
Commit: 7e3ffd01611232dfcb4fb04032a0be52fcf4dd6c
https://github.com/scummvm/scummvm/commit/7e3ffd01611232dfcb4fb04032a0be52fcf4dd6c
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: unswitch loop in Bitmap to Video memory
bmp to video don't test depth per pixel
>From upstream 85344c94e2367fe3bb8eb3b9249329c1d1b49f24
Changed paths:
engines/ags/engine/gfx/gfx_driver_base.cpp
diff --git a/engines/ags/engine/gfx/gfx_driver_base.cpp b/engines/ags/engine/gfx/gfx_driver_base.cpp
index 9480f04cc5b..c5931aeacfd 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.cpp
+++ b/engines/ags/engine/gfx/gfx_driver_base.cpp
@@ -345,16 +345,16 @@ void VideoMemoryGraphicsDriver::BitmapToVideoMem(const Bitmap *bitmap, const boo
char *dst_ptr, const int dst_pitch, const bool usingLinearFiltering) {
const int src_depth = bitmap->GetColorDepth();
bool lastPixelWasTransparent = false;
- for (int y = 0; y < tile->height; y++) {
- lastPixelWasTransparent = false;
- const uint8_t *scanline_before = (y > 0) ? bitmap->GetScanLine(y + tile->y - 1) : nullptr;
- const uint8_t *scanline_at = bitmap->GetScanLine(y + tile->y);
- const uint8_t *scanline_after = (y < tile->height - 1) ? bitmap->GetScanLine(y + tile->y + 1) : nullptr;
- unsigned int *memPtrLong = (unsigned int *)dst_ptr;
-
- for (int x = 0; x < tile->width; x++) {
- switch (src_depth) {
- case 8: {
+ switch (src_depth) {
+ case 8: {
+ for (int y = 0; y < tile->height; y++) {
+ lastPixelWasTransparent = false;
+ const uint8_t *scanline_before = (y > 0) ? bitmap->GetScanLine(y + tile->y - 1) : nullptr;
+ const uint8_t *scanline_at = bitmap->GetScanLine(y + tile->y);
+ const uint8_t *scanline_after = (y < tile->height - 1) ? bitmap->GetScanLine(y + tile->y + 1) : nullptr;
+ unsigned int *memPtrLong = (unsigned int *)dst_ptr;
+
+ for (int x = 0; x < tile->width; x++) {
const unsigned char *srcData = (const unsigned char *)&scanline_at[(x + tile->x) * sizeof(char)];
if (*srcData == MASK_COLOR_8) {
if (!usingLinearFiltering)
@@ -386,9 +386,19 @@ void VideoMemoryGraphicsDriver::BitmapToVideoMem(const Bitmap *bitmap, const boo
lastPixelWasTransparent = false;
}
}
- break;
}
- case 16: {
+ dst_ptr += dst_pitch;
+ }
+ } break;
+ case 16: {
+ for (int y = 0; y < tile->height; y++) {
+ lastPixelWasTransparent = false;
+ const uint8_t *scanline_before = (y > 0) ? bitmap->GetScanLine(y + tile->y - 1) : nullptr;
+ const uint8_t *scanline_at = bitmap->GetScanLine(y + tile->y);
+ const uint8_t *scanline_after = (y < tile->height - 1) ? bitmap->GetScanLine(y + tile->y + 1) : nullptr;
+ unsigned int *memPtrLong = (unsigned int *)dst_ptr;
+
+ for (int x = 0; x < tile->width; x++) {
const unsigned short *srcData = (const unsigned short *)&scanline_at[(x + tile->x) * sizeof(short)];
if (*srcData == MASK_COLOR_16) {
if (!usingLinearFiltering)
@@ -420,9 +430,19 @@ void VideoMemoryGraphicsDriver::BitmapToVideoMem(const Bitmap *bitmap, const boo
lastPixelWasTransparent = false;
}
}
- break;
}
- case 32: {
+ dst_ptr += dst_pitch;
+ }
+ } break;
+ case 32: {
+ for (int y = 0; y < tile->height; y++) {
+ lastPixelWasTransparent = false;
+ const uint8_t *scanline_before = (y > 0) ? bitmap->GetScanLine(y + tile->y - 1) : nullptr;
+ const uint8_t *scanline_at = bitmap->GetScanLine(y + tile->y);
+ const uint8_t *scanline_after = (y < tile->height - 1) ? bitmap->GetScanLine(y + tile->y + 1) : nullptr;
+ unsigned int *memPtrLong = (unsigned int *)dst_ptr;
+
+ for (int x = 0; x < tile->width; x++) {
const unsigned int *srcData = (const unsigned int *)&scanline_at[(x + tile->x) * sizeof(int)];
if (*srcData == MASK_COLOR_32) {
if (!usingLinearFiltering)
@@ -456,49 +476,73 @@ void VideoMemoryGraphicsDriver::BitmapToVideoMem(const Bitmap *bitmap, const boo
lastPixelWasTransparent = false;
}
}
- break;
- }
- default:
- break;
}
+ dst_ptr += dst_pitch;
}
- dst_ptr += dst_pitch;
+ } break;
+ default:
+ break;
}
}
void VideoMemoryGraphicsDriver::BitmapToVideoMemOpaque(const Bitmap *bitmap, const bool has_alpha, const TextureTile *tile,
char *dst_ptr, const int dst_pitch) {
const int src_depth = bitmap->GetColorDepth();
- for (int y = 0; y < tile->height; y++) {
- const uint8_t *scanline_at = bitmap->GetScanLine(y + tile->y);
- unsigned int *memPtrLong = (unsigned int *)dst_ptr;
- for (int x = 0; x < tile->width; x++) {
- switch (src_depth) {
- case 8: {
+ switch (src_depth) {
+ case 8: {
+ for (int y = 0; y < tile->height; y++) {
+ const uint8_t *scanline_at = bitmap->GetScanLine(y + tile->y);
+ unsigned int *memPtrLong = (unsigned int *)dst_ptr;
+
+ for (int x = 0; x < tile->width; x++) {
const unsigned char *srcData = (const unsigned char *)&scanline_at[(x + tile->x) * sizeof(char)];
memPtrLong[x] = VMEMCOLOR_RGBA(algetr8(*srcData), algetg8(*srcData), algetb8(*srcData), 0xFF);
- break;
}
- case 16: {
+
+ dst_ptr += dst_pitch;
+ }
+ } break;
+ case 16: {
+ for (int y = 0; y < tile->height; y++) {
+ const uint8_t *scanline_at = bitmap->GetScanLine(y + tile->y);
+ unsigned int *memPtrLong = (unsigned int *)dst_ptr;
+
+ for (int x = 0; x < tile->width; x++) {
const unsigned short *srcData = (const unsigned short *)&scanline_at[(x + tile->x) * sizeof(short)];
memPtrLong[x] = VMEMCOLOR_RGBA(algetr16(*srcData), algetg16(*srcData), algetb16(*srcData), 0xFF);
- break;
}
- case 32: {
- const unsigned int *srcData = (const unsigned int *)&scanline_at[(x + tile->x) * sizeof(int)];
- if (has_alpha)
+
+ dst_ptr += dst_pitch;
+ }
+ } break;
+ case 32: {
+ if (has_alpha) {
+ for (int y = 0; y < tile->height; y++) {
+ const uint8_t *scanline_at = bitmap->GetScanLine(y + tile->y);
+ unsigned int *memPtrLong = (unsigned int *)dst_ptr;
+
+ for (int x = 0; x < tile->width; x++) {
+ const unsigned int *srcData = (const unsigned int *)&scanline_at[(x + tile->x) * sizeof(int)];
memPtrLong[x] = VMEMCOLOR_RGBA(algetr32(*srcData), algetg32(*srcData), algetb32(*srcData), algeta32(*srcData));
- else
- memPtrLong[x] = VMEMCOLOR_RGBA(algetr32(*srcData), algetg32(*srcData), algetb32(*srcData), 0xFF);
- break;
+ }
+ dst_ptr += dst_pitch;
}
- default:
- break;
+ } else {
+ for (int y = 0; y < tile->height; y++) {
+ const uint8_t *scanline_at = bitmap->GetScanLine(y + tile->y);
+ unsigned int *memPtrLong = (unsigned int *)dst_ptr;
+
+ for (int x = 0; x < tile->width; x++) {
+ const unsigned int *srcData = (const unsigned int *)&scanline_at[(x + tile->x) * sizeof(int)];
+ memPtrLong[x] = VMEMCOLOR_RGBA(algetr32(*srcData), algetg32(*srcData), algetb32(*srcData), 0xFF);
+ }
+ dst_ptr += dst_pitch;
}
}
-
- dst_ptr += dst_pitch;
+ } break;
+ default:
+ break;
}
}
Commit: 97d08215b5c3dc52f62d3ddf17a9e277879e30dc
https://github.com/scummvm/scummvm/commit/97d08215b5c3dc52f62d3ddf17a9e277879e30dc
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: Use a single function to send messages to editor debugger
>From upstream 003243d6c925d176d6e206bed7c1c930952ba2da
Changed paths:
engines/ags/engine/debugging/debug.cpp
engines/ags/engine/debugging/debugger.h
engines/ags/engine/main/game_run.cpp
engines/ags/engine/main/game_start.cpp
engines/ags/engine/main/quit.cpp
diff --git a/engines/ags/engine/debugging/debug.cpp b/engines/ags/engine/debugging/debug.cpp
index 58fceec3df6..1993742ca52 100644
--- a/engines/ags/engine/debugging/debug.cpp
+++ b/engines/ags/engine/debugging/debug.cpp
@@ -73,6 +73,23 @@ IAGSEditorDebugger *GetEditorDebugger(const char * /*instanceToken*/) {
#endif
+void send_message_to_debugger(const std::vector<std::pair<String, String> > &tag_values, const String &command) {
+ String messageToSend = String::FromFormat(R"(<?xml version=" 1.0 " encoding=" Windows - 1252 "?><Debugger Command=" % s ">)", command.GetCStr());
+#if AGS_PLATFORM_OS_WINDOWS
+ messageToSend.Append(String::FromFormat(" <EngineWindow>%d</EngineWindow> ", (int)sys_win_get_window()));
+#endif
+
+ for (const auto &tag_value : tag_values) {
+ String tag_line = String::FromFormat(" <%s><![CDATA[%s]]></%s> ",
+ tag_value.first.GetCStr(), tag_value.second.GetCStr(), tag_value.first.GetCStr());
+ messageToSend.Append(tag_line);
+ }
+
+ messageToSend.Append("</Debugger>\n");
+
+ _G(editor_debugger)->SendMessageToEditor(messageToSend.GetCStr());
+}
+
static const char *OutputMsgBufID = "buffer";
static const char *OutputFileID = "file";
static const char *OutputSystemID = "stdout";
@@ -210,6 +227,7 @@ void init_debug(const ConfigTree &cfg, bool stderr_only) {
void apply_debug_config(const ConfigTree &cfg) {
apply_log_config(cfg, OutputSystemID, /* defaults */ true, { DbgGroupOption(kDbgGroup_Main, kDbgMsg_Info) });
bool legacy_log_enabled = CfgReadBoolInt(cfg, "misc", "log", false);
+
apply_log_config(cfg, OutputFileID,
/* defaults */
legacy_log_enabled, {
@@ -314,30 +332,25 @@ struct Breakpoint {
int lineNumber = 0;
};
-bool send_message_to_editor(const char *msg, const char *errorMsg) {
+bool send_state_to_debugger(const String& msg, const String& errorMsg) {
// Get either saved callstack from a script error, or current execution point
- String callStack = (errorMsg && cc_has_error()) ?
+ String callStack = (!errorMsg.IsEmpty() && cc_has_error()) ?
cc_get_error().CallStack : cc_get_callstack();
if (callStack.IsEmpty())
return false;
- String message;
- message.AppendFmt("<?xml version=\"1.0\" encoding=\"Windows-1252\"?><Debugger Command=\"%s\">", msg);
-#if AGS_PLATFORM_OS_WINDOWS
- message.AppendFmt(" <EngineWindow>%d</EngineWindow> ", (int)sys_win_get_window());
-#endif
- message.AppendFmt(" <ScriptState><![CDATA[%s]]></ScriptState> ", callStack.GetCStr());
- if (errorMsg != nullptr) {
- message.AppendFmt(" <ErrorMessage><![CDATA[%s]]></ErrorMessage> ", errorMsg);
+ std::vector<std::pair<String, String>> script_info = {{"ScriptState", callStack}};
+
+ if (!errorMsg.IsEmpty()) {
+ script_info.emplace_back("ErrorMessage", errorMsg);
}
- message.Append("</Debugger>");
- _G(editor_debugger)->SendMessageToEditor(message.GetCStr());
+ send_message_to_debugger(script_info, msg);
return true;
}
-bool send_message_to_editor(const char *msg) {
- return send_message_to_editor(msg, nullptr);
+bool send_state_to_debugger(const char *msg) {
+ return send_state_to_debugger(String(msg), String());
}
bool init_editor_debugging() {
@@ -356,11 +369,11 @@ bool init_editor_debugging() {
// Wait for the editor to send the initial breakpoints
// and then its READY message
- while (check_for_messages_from_editor() != 2) {
+ while (check_for_messages_from_debugger() != 2) {
_G(platform)->Delay(10);
}
- send_message_to_editor("START");
+ send_state_to_debugger("START");
Debug::Printf(kDbgMsg_Info, "External debugger initialized");
return true;
}
@@ -369,7 +382,7 @@ bool init_editor_debugging() {
return false;
}
-int check_for_messages_from_editor() {
+int check_for_messages_from_debugger() {
if (_G(editor_debugger)->IsMessageAvailable()) {
char *msg = _G(editor_debugger)->GetNextMessage();
if (msg == nullptr) {
@@ -442,17 +455,17 @@ int check_for_messages_from_editor() {
-bool send_exception_to_editor(const char *qmsg) {
+bool send_exception_to_debugger(const char *qmsg) {
#if AGS_PLATFORM_OS_WINDOWS
_G(want_exit) = false;
// allow the editor to break with the error message
if (editor_window_handle != NULL)
SetForegroundWindow(editor_window_handle);
- if (!send_message_to_editor("ERROR", qmsg))
+ if (!send_state_to_debugger("ERROR", qmsg))
return false;
- while ((check_for_messages_from_editor() == 0) && (!_G(want_exit))) {
+ while ((check_for_messages_from_debugger() == 0) && (!_G(want_exit))) {
_G(platform)->Delay(10);
}
#endif
@@ -466,7 +479,7 @@ void break_into_debugger() {
if (editor_window_handle != NULL)
SetForegroundWindow(editor_window_handle);
- send_message_to_editor("BREAK");
+ send_state_to_debugger("BREAK");
_G(game_paused_in_debugger) = 1;
while (_G(game_paused_in_debugger)) {
diff --git a/engines/ags/engine/debugging/debugger.h b/engines/ags/engine/debugging/debugger.h
index 60ad55026e8..9a60c29f0ff 100644
--- a/engines/ags/engine/debugging/debugger.h
+++ b/engines/ags/engine/debugging/debugger.h
@@ -29,9 +29,12 @@ namespace AGS3 {
struct IAGSEditorDebugger;
struct ScriptPosition;
-int check_for_messages_from_editor();
-bool send_message_to_editor(const char *msg);
-bool send_exception_to_editor(const char *qmsg);
+int check_for_messages_from_debugger();
+bool send_state_to_debugger(const char *msg);
+bool send_exception_to_debugger(const char *qmsg);
+// Returns current script's location and callstack
+AGS::Shared::String get_cur_script(int numberOfLinesOfCallStack);
+bool get_script_position(ScriptPosition &script_pos);
void check_debug_keys();
#define DBG_NOIFACE 1
diff --git a/engines/ags/engine/main/game_run.cpp b/engines/ags/engine/main/game_run.cpp
index dd810b53e19..28944bc0e0b 100644
--- a/engines/ags/engine/main/game_run.cpp
+++ b/engines/ags/engine/main/game_run.cpp
@@ -1048,7 +1048,7 @@ void update_polled_stuff() {
quit("||exit!");
} else if (_G(editor_debugging_initialized))
- check_for_messages_from_editor();
+ check_for_messages_from_debugger();
}
} // namespace AGS3
diff --git a/engines/ags/engine/main/game_start.cpp b/engines/ags/engine/main/game_start.cpp
index 3e2a444e12f..4ed18111ed9 100644
--- a/engines/ags/engine/main/game_start.cpp
+++ b/engines/ags/engine/main/game_start.cpp
@@ -65,7 +65,7 @@ void start_game_init_editor_debugging() {
auto waitUntil = AGS_Clock::now() + std::chrono::milliseconds(500);
while (waitUntil > AGS_Clock::now()) {
// pick up any breakpoints in game_start
- check_for_messages_from_editor();
+ check_for_messages_from_debugger();
}
ccSetDebugHook(scriptDebugHook);
diff --git a/engines/ags/engine/main/quit.cpp b/engines/ags/engine/main/quit.cpp
index b2ccbe0f3b2..34b060ff315 100644
--- a/engines/ags/engine/main/quit.cpp
+++ b/engines/ags/engine/main/quit.cpp
@@ -61,8 +61,8 @@ using namespace AGS::Engine;
void quit_tell_editor_debugger(const String &qmsg, QuitReason qreason) {
if (_G(editor_debugging_initialized)) {
if (qreason & kQuitKind_GameException)
- _G(handledErrorInEditor) = send_exception_to_editor(qmsg.GetCStr());
- send_message_to_editor("EXIT");
+ _G(handledErrorInEditor) = send_exception_to_debugger(qmsg.GetCStr());
+ send_state_to_debugger("EXIT");
_G(editor_debugger)->Shutdown();
}
}
Commit: d563f6dec9116c4cbd07767f70bf61f381b669bf
https://github.com/scummvm/scummvm/commit/d563f6dec9116c4cbd07767f70bf61f381b669bf
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Updated build version (3.6.0.39)
>From upstream ae3dd50f4693988906eff9d8872965756a3bc869
Changed paths:
engines/ags/shared/core/def_version.h
diff --git a/engines/ags/shared/core/def_version.h b/engines/ags/shared/core/def_version.h
index f50e937a2cf..390f6c14293 100644
--- a/engines/ags/shared/core/def_version.h
+++ b/engines/ags/shared/core/def_version.h
@@ -22,9 +22,9 @@
#ifndef AGS_SHARED_CORE_DEFVERSION_H
#define AGS_SHARED_CORE_DEFVERSION_H
-#define ACI_VERSION_STR "3.6.0.38"
+#define ACI_VERSION_STR "3.6.0.39"
#if defined (RC_INVOKED) // for MSVC resource compiler
-#define ACI_VERSION_MSRC_DEF 3.6.0.38
+#define ACI_VERSION_MSRC_DEF 3.6.0.39
#endif
#define SPECIAL_VERSION ""
Commit: 5a2405d29144b45f6fe53d3cf5532def37c72a10
https://github.com/scummvm/scummvm/commit/5a2405d29144b45f6fe53d3cf5532def37c72a10
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: debug use AppendFmt at send msg and clang-tidy fixes
>From upstream 96f0b3d5e216fbba6df3cb47df3d28687b4dd5e4
Changed paths:
engines/ags/engine/debugging/debug.cpp
engines/ags/globals.h
diff --git a/engines/ags/engine/debugging/debug.cpp b/engines/ags/engine/debugging/debug.cpp
index 1993742ca52..0d8f534b086 100644
--- a/engines/ags/engine/debugging/debug.cpp
+++ b/engines/ags/engine/debugging/debug.cpp
@@ -80,9 +80,7 @@ void send_message_to_debugger(const std::vector<std::pair<String, String> > &tag
#endif
for (const auto &tag_value : tag_values) {
- String tag_line = String::FromFormat(" <%s><![CDATA[%s]]></%s> ",
- tag_value.first.GetCStr(), tag_value.second.GetCStr(), tag_value.first.GetCStr());
- messageToSend.Append(tag_line);
+ messageToSend.AppendFmt(" <%s><![CDATA[%s]]></%s> ", tag_value.first.GetCStr(), tag_value.second.GetCStr(), tag_value.first.GetCStr());
}
messageToSend.Append("</Debugger>\n");
@@ -125,19 +123,19 @@ std::vector<String> parse_log_multigroup(const String &group_str) {
for (size_t i = 0; i < group_str.GetLength(); ++i) {
switch (group_str[i]) {
case 'm':
- grplist.push_back("main");
+ grplist.emplace_back("main");
break;
case 'g':
- grplist.push_back("game");
+ grplist.emplace_back("game");
break;
case 's':
- grplist.push_back("script");
+ grplist.emplace_back("script");
break;
case 'c':
- grplist.push_back("sprcache");
+ grplist.emplace_back("sprcache");
break;
case 'o':
- grplist.push_back("manobj");
+ grplist.emplace_back("manobj");
break;
}
}
@@ -180,7 +178,7 @@ void apply_log_config(const ConfigTree &cfg, const String &log_id,
dbgout->ClearGroupFilters();
if (value.IsEmpty() || value.CompareNoCase("default") == 0) {
- for (const auto opt : def_opts)
+ for (const auto &opt : def_opts)
dbgout->SetGroupFilter(opt.first, opt.second);
} else {
const auto options = value.Split(',');
@@ -517,9 +515,8 @@ void scriptDebugHook(ccInstance *ccinst, int linenum) {
const char *scriptName = ccinst->runningInst->instanceof->GetSectionName(ccinst->pc);
- for (size_t i = 0; i < _G(breakpoints).size(); ++i) {
- if ((_G(breakpoints)[i].lineNumber == linenum) &&
- (strcmp(_G(breakpoints)[i].scriptName, scriptName) == 0)) {
+ for (const auto &breakpoint : _G(breakpoints)) {
+ if ((breakpoint.lineNumber == linenum) && (strcmp(breakpoint.scriptName, scriptName) == 0)) {
break_into_debugger();
break;
}
@@ -533,7 +530,7 @@ void check_debug_keys() {
if (_GP(play).debug_mode) {
// do the run-time script debugging
- const Uint8 *ks = SDL_GetKeyboardState(NULL);
+ const Uint8 *ks = SDL_GetKeyboardState(nullptr);
if ((!ks[SDL_SCANCODE_SCROLLLOCK]) && (scrlockWasDown))
scrlockWasDown = 0;
else if ((ks[SDL_SCANCODE_SCROLLLOCK]) && (!scrlockWasDown)) {
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index de6c7f2c498..04316edfff3 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -790,7 +790,6 @@ public:
// The version of the engine the loaded game was compiled for (if available)
Version _game_compiled_version;
int _game_paused = 0;
- char _pexbuf[STD_BUFFER_SIZE] = { 0 };
unsigned int _load_new_game = 0;
int _load_new_game_restore = -1;
// TODO: refactor these global vars into function arguments
Commit: 48592b9eee44c672e7e315c15fd127f9ad4b2dc7
https://github.com/scummvm/scummvm/commit/48592b9eee44c672e7e315c15fd127f9ad4b2dc7
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: add screen functions to plugin exports
Reimplemented from upstream 5497c87cc1443d155bd89a76dddf91934b7e0bb5
Changed paths:
A engines/ags/plugins/core/screen.cpp
A engines/ags/plugins/core/screen.h
engines/ags/engine/ac/screen.h
diff --git a/engines/ags/engine/ac/screen.h b/engines/ags/engine/ac/screen.h
index 55c2f3859bc..9efcde8a18b 100644
--- a/engines/ags/engine/ac/screen.h
+++ b/engines/ags/engine/ac/screen.h
@@ -22,8 +22,19 @@
#ifndef AGS_ENGINE_AC_SCREEN_H
#define AGS_ENGINE_AC_SCREEN_H
+#include "ags/engine/ac/dynobj/script_user_object.h"
+
namespace AGS3 {
+int Screen_GetScreenWidth();
+int Screen_GetScreenHeight();
+bool Screen_GetAutoSizeViewport();
+void Screen_SetAutoSizeViewport(bool on);
+int Screen_GetViewportCount();
+ScriptViewport *Screen_GetViewport();
+ScriptViewport *Screen_GetAnyViewport(int index);
+ScriptUserObject *Screen_RoomToScreenPoint(int roomx, int roomy);
+
namespace AGS {
namespace Shared {
class Bitmap;
diff --git a/engines/ags/plugins/core/screen.cpp b/engines/ags/plugins/core/screen.cpp
new file mode 100644
index 00000000000..6ef73b85527
--- /dev/null
+++ b/engines/ags/plugins/core/screen.cpp
@@ -0,0 +1,79 @@
+/* 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
+ * (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/core/screen.h"
+#include "ags/engine/ac/screen.h"
+
+namespace AGS3 {
+namespace Plugins {
+namespace Core {
+
+void Screen::AGS_EngineStartup(IAGSEngine *engine) {
+ ScriptContainer::AGS_EngineStartup(engine);
+
+ SCRIPT_METHOD(Screen::get_Height, Screen::GetScreenHeight);
+ SCRIPT_METHOD(Screen::get_Width, Screen::GetScreenWidth);
+ SCRIPT_METHOD(Screen::get_AutoSizeViewportOnRoomLoad, Screen::GetAutoSizeViewport);
+ SCRIPT_METHOD(Screen::set_AutoSizeViewportOnRoomLoad, Screen::SetAutoSizeViewport);
+ SCRIPT_METHOD(Screen::get_Viewport, Screen::GetViewport);
+ SCRIPT_METHOD(Screen::get_ViewportCount, Screen::GetViewportCount);
+ SCRIPT_METHOD(Screen::geti_Viewports, Screen::GetAnyViewport);
+ SCRIPT_METHOD(Screen::RoomToScreenPoint, Screen::RoomToScreenPoint);
+}
+
+void Screen::GetScreenHeight(ScriptMethodParams ¶ms) {
+ params._result = AGS3::Screen_GetScreenHeight();
+}
+
+void Screen::GetScreenWidth(ScriptMethodParams ¶ms) {
+ params._result = AGS3::Screen_GetScreenWidth();
+}
+
+void Screen::GetAutoSizeViewport(ScriptMethodParams ¶ms) {
+ params._result = AGS3::Screen_GetAutoSizeViewport();
+}
+
+void Screen::SetAutoSizeViewport(ScriptMethodParams ¶ms) {
+ PARAMS1(bool, on);
+ AGS3::Screen_SetAutoSizeViewport(on);
+}
+
+void Screen::GetViewport(ScriptMethodParams ¶ms) {
+ params._result = AGS3::Screen_GetAnyViewport();
+}
+
+void Screen::GetViewportCount(ScriptMethodParams ¶ms) {
+ params._result = AGS3::Screen_GetViewportCount();
+}
+
+void Screen::GetAnyViewport(ScriptMethodParams ¶ms) {
+ PARAMS1(int, index);
+ params._result = AGS3::Room_GetColorDepth(index);
+}
+
+void Screen::RoomToScreenPoint(ScriptMethodParams ¶ms) {
+ PARAMS2(int, roomx, int, roomy);
+ params._result = AGS3::Room_GetHeight(roomx, roomy);
+}
+
+} // namespace Core
+} // namespace Plugins
+} // namespace AGS3
diff --git a/engines/ags/plugins/core/screen.h b/engines/ags/plugins/core/screen.h
new file mode 100644
index 00000000000..6d0bcc1a2b4
--- /dev/null
+++ b/engines/ags/plugins/core/screen.h
@@ -0,0 +1,51 @@
+/* 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
+ * (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_CORE_SCREEN_H
+#define AGS_PLUGINS_CORE_SCREEN_H
+
+#include "ags/plugins/ags_plugin.h"
+
+namespace AGS3 {
+namespace Plugins {
+namespace Core {
+
+class Screen : public ScriptContainer {
+ BUILT_IN_HASH(Screen)
+public:
+ virtual ~Screen() {}
+ void AGS_EngineStartup(IAGSEngine *engine) override;
+
+ void GetScreenHeight(ScriptMethodParams ¶ms);
+ void GetScreenWidth(ScriptMethodParams ¶ms);
+ void GetAutoSizeViewport(ScriptMethodParams ¶ms);
+ void SetAutoSizeViewport(ScriptMethodParams ¶ms);
+ void GetViewport(ScriptMethodParams ¶ms);
+ void GetViewportCount(ScriptMethodParams ¶ms);
+ void GetAnyViewport(ScriptMethodParams ¶ms);
+ void RoomToScreenPoint(ScriptMethodParams ¶ms);
+};
+
+} // namespace Core
+} // namespace Plugins
+} // namespace AGS3
+
+#endif
Commit: af16689b2b3f944914caaf89cf247c616256f0b7
https://github.com/scummvm/scummvm/commit/af16689b2b3f944914caaf89cf247c616256f0b7
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Plugin: SnowRain adjust height/baseline before entering room
>From upstream 1e3a66df0e3bc0f7bbb743a5fec4b2966ea9df66
Changed paths:
engines/ags/plugins/ags_snow_rain/ags_snow_rain.cpp
diff --git a/engines/ags/plugins/ags_snow_rain/ags_snow_rain.cpp b/engines/ags/plugins/ags_snow_rain/ags_snow_rain.cpp
index cec3c53c5a9..f403a818be1 100644
--- a/engines/ags/plugins/ags_snow_rain/ags_snow_rain.cpp
+++ b/engines/ags/plugins/ags_snow_rain/ags_snow_rain.cpp
@@ -67,7 +67,6 @@ void AGSSnowRain::AGS_EngineStartup(IAGSEngine *engine) {
SCRIPT_METHOD(srSetBaseline, AGSSnowRain::srSetBaseline);
_engine->RequestEventHook(AGSE_PREGUIDRAW);
- _engine->RequestEventHook(AGSE_PRESCREENDRAW);
_engine->RequestEventHook(AGSE_ENTERROOM);
_engine->RequestEventHook(AGSE_SAVEGAME);
_engine->RequestEventHook(AGSE_RESTOREGAME);
@@ -82,6 +81,12 @@ int64 AGSSnowRain::AGS_EngineOnEvent(int event, NumberPtr data) {
if (_snow.IsActive())
_snow.UpdateWithDrift();
} else if (event == AGSE_ENTERROOM) {
+ // Get screen size when entering a room
+ // FIXME: Upsteam uses srSetBaseline that doubles the height value if screenHeight == 400.
+ // That doesn't seem to make a difference. Also the implementation changed in later commits
+ _engine->GetScreenDimensions(&_screenWidth, &_screenHeight, &_screenColorDepth);
+ _rain.SetBaseline(0, _screenHeight);
+ _snow.SetBaseline(0, _screenHeight);
_rain.EnterRoom();
_snow.EnterRoom();
} else if (event == AGSE_RESTOREGAME) {
@@ -92,10 +97,6 @@ int64 AGSSnowRain::AGS_EngineOnEvent(int event, NumberPtr data) {
Serializer s(_engine, data, false);
_rain.syncGame(s);
_snow.syncGame(s);
- } else if (event == AGSE_PRESCREENDRAW) {
- // Get screen size once here
- _engine->GetScreenDimensions(&_screenWidth, &_screenHeight , &_screenColorDepth);
- _engine->UnrequestEventHook(AGSE_PRESCREENDRAW);
}
return 0;
Commit: b828199c2596805fa29631d10fb6a507331112e4
https://github.com/scummvm/scummvm/commit/b828199c2596805fa29631d10fb6a507331112e4
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: renderers support creating DDB as a render target
Partially from upstream 4c8218e9ca4da7403ff14e45c57584517d2abc2f
Changed paths:
engines/ags/engine/gfx/ali_3d_scummvm.cpp
engines/ags/engine/gfx/ali_3d_scummvm.h
engines/ags/engine/gfx/gfx_driver_base.h
engines/ags/engine/gfx/graphics_driver.h
diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.cpp b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
index 8686d75e117..3cea00c5301 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.cpp
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
@@ -251,6 +251,10 @@ IDriverDependantBitmap *ScummVMRendererGraphicsDriver::CreateDDBFromBitmap(Bitma
return new ALSoftwareBitmap(bitmap, opaque, hasAlpha);
}
+IDriverDependantBitmap *ScummVMRendererGraphicsDriver::CreateRenderTargetDDB(int width, int height, int color_depth, bool opaque) {
+ return new ALSoftwareBitmap(width, height, color_depth, opaque);
+}
+
void ScummVMRendererGraphicsDriver::UpdateDDBFromBitmap(IDriverDependantBitmap *bitmapToUpdate, Bitmap *bitmap, bool hasAlpha) {
ALSoftwareBitmap *alSwBmp = (ALSoftwareBitmap *)bitmapToUpdate;
alSwBmp->_bmp = bitmap;
diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.h b/engines/ags/engine/gfx/ali_3d_scummvm.h
index 768a91fcfe2..526356077a8 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.h
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.h
@@ -176,6 +176,7 @@ public:
int GetCompatibleBitmapFormat(int color_depth) override;
IDriverDependantBitmap *CreateDDB(int width, int height, int color_depth, bool opaque) override;
IDriverDependantBitmap *CreateDDBFromBitmap(Bitmap *bitmap, bool hasAlpha, bool opaque) override;
+ IDriverDependantBitmap *CreateRenderTargetDDB(int width, int height, int color_depth, bool opaque) override;
void UpdateDDBFromBitmap(IDriverDependantBitmap *ddb, Bitmap *bitmap, bool hasAlpha) override;
void DestroyDDB(IDriverDependantBitmap *ddb) override;
diff --git a/engines/ags/engine/gfx/gfx_driver_base.h b/engines/ags/engine/gfx/gfx_driver_base.h
index ba8aaa25602..3e59a8d00ea 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.h
+++ b/engines/ags/engine/gfx/gfx_driver_base.h
@@ -223,7 +223,9 @@ public:
void SetMemoryBackBuffer(Bitmap *backBuffer) override;
Bitmap *GetStageBackBuffer(bool mark_dirty) override;
bool GetStageMatrixes(RenderMatrixes &rm) override;
+ // Creates new texture using given parameters
IDriverDependantBitmap *CreateDDB(int width, int height, int color_depth, bool opaque) override = 0;
+ // Creates new texture and copy bitmap contents over
IDriverDependantBitmap *CreateDDBFromBitmap(Bitmap *bitmap, bool hasAlpha, bool opaque = false) override;
// Get shared texture from cache, or create from bitmap and assign ID
IDriverDependantBitmap *GetSharedDDB(uint32_t sprite_id, Bitmap *bitmap, bool hasAlpha, bool opaque) override;
@@ -235,7 +237,7 @@ public:
protected:
// Create texture data with the given parameters
- virtual TextureData *CreateTextureData(int width, int height, bool opaque) = 0;
+ virtual TextureData *CreateTextureData(int width, int height, bool opaque, bool as_render_target = false) = 0;
// Update texture data from the given bitmap
virtual void UpdateTextureData(TextureData *txdata, Bitmap *bmp, bool opaque, bool hasAlpha) = 0;
// Create DDB using preexisting texture data
diff --git a/engines/ags/engine/gfx/graphics_driver.h b/engines/ags/engine/gfx/graphics_driver.h
index 58e0e53d047..4234ff1b4ad 100644
--- a/engines/ags/engine/gfx/graphics_driver.h
+++ b/engines/ags/engine/gfx/graphics_driver.h
@@ -133,11 +133,17 @@ public:
// Gets closest recommended bitmap format (currently - only color depth) for the given original format.
// Engine needs to have game bitmaps brought to the certain range of formats, easing conversion into the video bitmaps.
virtual int GetCompatibleBitmapFormat(int color_depth) = 0;
+
// Creates a "raw" DDB, without pixel initialization
virtual IDriverDependantBitmap *CreateDDB(int width, int height, int color_depth, bool opaque = false) = 0;
- // Creates DDB, initializes from the given bitmap
+ // Creates DDB, initializes from the given bitmap.
virtual IDriverDependantBitmap *CreateDDBFromBitmap(Shared::Bitmap *bitmap, bool hasAlpha, bool opaque = false) = 0;
+ // Creates DDB intended to be used as a render target (allow render other DDBs on it).
+ virtual IDriverDependantBitmap *CreateRenderTargetDDB(int width, int height, int color_depth, bool opaque = false) = 0;
+ // Updates DBB using the given bitmap; bitmap must have same size and format
+ // as the one that this DDB was initialized with.
virtual void UpdateDDBFromBitmap(IDriverDependantBitmap *bitmapToUpdate, Shared::Bitmap *bitmap, bool hasAlpha) = 0;
+ // Destroy the DDB.
virtual void DestroyDDB(IDriverDependantBitmap *bitmap) = 0;
// Get shared texture from cache, or create from bitmap and assign ID
Commit: f0887a3b9f032306a2915715bbc5c23c26745fb2
https://github.com/scummvm/scummvm/commit/f0887a3b9f032306a2915715bbc5c23c26745fb2
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: in gfx drivers record sprite range for each batch
Partially from upstream eaa806927bf4608195fe58de405750836093032c
Changed paths:
engines/ags/engine/gfx/ali_3d_scummvm.h
engines/ags/engine/gfx/gfx_driver_base.cpp
engines/ags/engine/gfx/gfx_driver_base.h
diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.h b/engines/ags/engine/gfx/ali_3d_scummvm.h
index 526356077a8..3cb25562ea8 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.h
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.h
@@ -230,6 +230,11 @@ public:
void SetGraphicsFilter(PSDLRenderFilter filter);
+protected:
+ size_t GetLastDrawEntryIndex() override {
+ return _spriteList.size();
+ }
+
private:
Graphics::Screen *_screen = nullptr;
PSDLRenderFilter _filter;
diff --git a/engines/ags/engine/gfx/gfx_driver_base.cpp b/engines/ags/engine/gfx/gfx_driver_base.cpp
index c5931aeacfd..188dc89616c 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.cpp
+++ b/engines/ags/engine/gfx/gfx_driver_base.cpp
@@ -39,6 +39,7 @@ GraphicsDriverBase::GraphicsDriverBase()
// Initialize default sprite batch, it will be used when no other batch was activated
_actSpriteBatch = 0;
_spriteBatchDesc.push_back(SpriteBatchDesc());
+ _spriteBatchRange.push_back(std::make_pair((size_t) 0, (size_t) 0));
}
bool GraphicsDriverBase::IsModeSet() const {
@@ -68,18 +69,23 @@ Rect GraphicsDriverBase::GetRenderDestination() const {
void GraphicsDriverBase::BeginSpriteBatch(const Rect &viewport, const SpriteTransform &transform,
GraphicFlip flip, PBitmap surface) {
_spriteBatchDesc.push_back(SpriteBatchDesc(_actSpriteBatch, viewport, transform, flip, surface));
+ _spriteBatchRange.push_back(std::make_pair(GetLastDrawEntryIndex(), (size_t) SIZE_MAX));
_actSpriteBatch = _spriteBatchDesc.size() - 1;
InitSpriteBatch(_actSpriteBatch, _spriteBatchDesc[_actSpriteBatch]);
}
void GraphicsDriverBase::EndSpriteBatch() {
+ _spriteBatchRange[_actSpriteBatch].second = GetLastDrawEntryIndex();
_actSpriteBatch = _spriteBatchDesc[_actSpriteBatch].Parent;
}
void GraphicsDriverBase::ClearDrawLists() {
ResetAllBatches();
_actSpriteBatch = 0;
- _spriteBatchDesc.resize(1);
+ _spriteBatchDesc.clear();
+ _spriteBatchRange.clear();
+ _spriteBatchDesc.push_back(SpriteBatchDesc());
+ _spriteBatchRange.push_back(std::make_pair((size_t) 0, (size_t) 0));
}
void GraphicsDriverBase::OnInit() {
diff --git a/engines/ags/engine/gfx/gfx_driver_base.h b/engines/ags/engine/gfx/gfx_driver_base.h
index 3e59a8d00ea..bad0b2794cc 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.h
+++ b/engines/ags/engine/gfx/gfx_driver_base.h
@@ -143,6 +143,8 @@ protected:
virtual void OnSetFilter();
// Initialize sprite batch and allocate necessary resources
virtual void InitSpriteBatch(size_t index, const SpriteBatchDesc &desc) = 0;
+ // Gets the index of a last draw entry (sprite)
+ virtual size_t GetLastDrawEntryIndex() = 0;
// Clears sprite lists
virtual void ResetAllBatches() = 0;
@@ -163,7 +165,10 @@ protected:
GFXDRV_CLIENTCALLBACKINITGFX _initGfxCallback;
// Sprite batch parameters
- SpriteBatchDescs _spriteBatchDesc; // sprite batches list
+ SpriteBatchDescs _spriteBatchDesc;
+ // The range of sprites in this sprite batch (counting nested sprites):
+ // the last of the previous batch, and the last of the current.
+ std::vector<std::pair<size_t, size_t>> _spriteBatchRange;
size_t _actSpriteBatch; // active batch index
};
Commit: 711ca20dd194d159714d011daf778ddb92a51294
https://github.com/scummvm/scummvm/commit/711ca20dd194d159714d011daf778ddb92a51294
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: abort in case failed both to switch and restore gfx mode
This may be a temporary solution, but it's necessary, because otherwise
engine will fail later, with a seemingly unrelated error, which will
be harder to diagnose.
>From upstream 902568c4eba9dba4eb762882890c6e8a308683aa
Changed paths:
engines/ags/engine/main/engine.cpp
diff --git a/engines/ags/engine/main/engine.cpp b/engines/ags/engine/main/engine.cpp
index 94b6be7bca8..b8c5a790e4d 100644
--- a/engines/ags/engine/main/engine.cpp
+++ b/engines/ags/engine/main/engine.cpp
@@ -1244,16 +1244,15 @@ bool engine_try_switch_windowed_gfxmode() {
// If failed, try switching back to previous gfx mode
res = graphics_mode_set_dm(old_dm) &&
graphics_mode_set_render_frame(old_frame);
+ if (!res)
+ quitprintf("Failed to restore graphics mode.");
}
- if (res) {
- // If succeeded (with any case), update engine objects that rely on
- // active display mode.
- if (!_G(gfxDriver)->GetDisplayMode().IsRealFullscreen())
- init_desktop = get_desktop_size();
- engine_post_gfxmode_setup(init_desktop);
- }
-
+ // If succeeded (with any case), update engine objects that rely on
+ // active display mode.
+ if (!_G(gfxDriver)->GetDisplayMode().IsRealFullscreen())
+ init_desktop = get_desktop_size();
+ engine_post_gfxmode_setup(init_desktop);
// Make sure that we don't receive window events queued during init
sys_flush_events();
return res;
Commit: 982abc24f3cbc863890a869f49a05dc8214d8476
https://github.com/scummvm/scummvm/commit/982abc24f3cbc863890a869f49a05dc8214d8476
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: create raw draw screens only on plugin's demand
This significantly reduces memory usage, as screens will be only
created for sprite batches, during which the plugin requested
memory backbuffer for drawing.
Partially from upstream 1b71780d6e94eca33ee3234fd138213874640ab1
Changed paths:
engines/ags/engine/gfx/gfx_driver_base.cpp
engines/ags/engine/gfx/gfx_driver_base.h
diff --git a/engines/ags/engine/gfx/gfx_driver_base.cpp b/engines/ags/engine/gfx/gfx_driver_base.cpp
index 188dc89616c..8fb58491f8c 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.cpp
+++ b/engines/ags/engine/gfx/gfx_driver_base.cpp
@@ -40,6 +40,7 @@ GraphicsDriverBase::GraphicsDriverBase()
_actSpriteBatch = 0;
_spriteBatchDesc.push_back(SpriteBatchDesc());
_spriteBatchRange.push_back(std::make_pair((size_t) 0, (size_t) 0));
+ _rendSpriteBatch = UINT32_MAX;
}
bool GraphicsDriverBase::IsModeSet() const {
@@ -163,8 +164,10 @@ void VideoMemoryGraphicsDriver::SetMemoryBackBuffer(Bitmap * /*backBuffer*/) {
}
Bitmap *VideoMemoryGraphicsDriver::GetStageBackBuffer(bool mark_dirty) {
+ if (_rendSpriteBatch == UINT32_MAX)
+ return nullptr;
_stageScreenDirty |= mark_dirty;
- return _stageVirtualScreen.get();
+ return GetStageScreenRaw(_rendSpriteBatch);
}
bool VideoMemoryGraphicsDriver::GetStageMatrixes(RenderMatrixes &rm) {
@@ -223,50 +226,68 @@ void VideoMemoryGraphicsDriver::UpdateSharedDDB(uint32_t sprite_id, Bitmap *bitm
_txRefs.erase(found);
}
-PBitmap VideoMemoryGraphicsDriver::CreateStageScreen(size_t index, const Size &sz) {
+void VideoMemoryGraphicsDriver::SetStageScreen(size_t index, const Size &sz) {
if (_stageScreens.size() <= index)
_stageScreens.resize(index + 1);
- if (sz.IsNull())
- _stageScreens[index].reset();
- else if (_stageScreens[index] == nullptr || _stageScreens[index]->GetSize() != sz)
- _stageScreens[index].reset(new Bitmap(sz.Width, sz.Height, _mode.ColorDepth));
- return _stageScreens[index];
+ _stageScreens[index].Size = sz;
}
-PBitmap VideoMemoryGraphicsDriver::GetStageScreen(size_t index) {
- if (index < _stageScreens.size())
- return _stageScreens[index];
- return nullptr;
+Bitmap *VideoMemoryGraphicsDriver::GetStageScreenRaw(size_t index) {
+ assert(index < _stageScreens.size());
+ if (_stageScreens.size() <= index)
+ return nullptr;
+
+ auto &scr = _stageScreens[index];
+ const Size sz = scr.Size;
+ if (scr.Bitmap && (scr.Bitmap->GetSize() != sz)) {
+ scr.Bitmap.reset();
+ if (scr.DDB)
+ DestroyDDB(scr.DDB);
+ scr.DDB = nullptr;
+ }
+ if (!scr.Bitmap && !sz.IsNull()) {
+ scr.Bitmap.reset(new Bitmap(sz.Width, sz.Height, _mode.ColorDepth));
+ scr.DDB = CreateDDB(sz.Width, sz.Height, _mode.ColorDepth, false);
+ }
+ return scr.Bitmap.get();
+}
+
+IDriverDependantBitmap *VideoMemoryGraphicsDriver::UpdateStageScreenDDB(size_t index) {
+ assert((index < _stageScreens.size()) && _stageScreens[index].DDB);
+ if ((_stageScreens.size() <= index) || !_stageScreens[index].Bitmap || !_stageScreens[index].DDB)
+ return nullptr;
+
+ auto &scr = _stageScreens[index];
+ UpdateDDBFromBitmap(scr.DDB, scr.Bitmap.get(), true);
+ scr.Bitmap->ClearTransparent();
+ return scr.DDB;
}
void VideoMemoryGraphicsDriver::DestroyAllStageScreens() {
- if (_stageVirtualScreenDDB)
+ if (_stageVirtualScreenDDB) // FIXME: Not in upstream
this->DestroyDDB(_stageVirtualScreenDDB);
_stageVirtualScreenDDB = nullptr;
- for (size_t i = 0; i < _stageScreens.size(); ++i)
- _stageScreens[i].reset();
- _stageVirtualScreen.reset();
+ for (size_t i = 0; i < _stageScreens.size(); ++i) {
+ if (_stageScreens[i].DDB)
+ DestroyDDB(_stageScreens[i].DDB);
+ }
+ _stageScreens.clear();
}
-bool VideoMemoryGraphicsDriver::DoNullSpriteCallback(int x, int y) {
+IDriverDependantBitmap *VideoMemoryGraphicsDriver::DoNullSpriteCallback(int x, int y) {
if (!_nullSpriteCallback)
error("Unhandled attempt to draw null sprite");
_stageScreenDirty = false;
// NOTE: this is not clear whether return value of callback may be
// relied on. Existing plugins do not seem to return anything but 0,
- // even if they handle this event.
+ // even if they handle this event. This is why we also set
+ // _stageScreenDirty in certain plugin API function implementations.
_stageScreenDirty |= _nullSpriteCallback(x, y) != 0;
if (_stageScreenDirty) {
- if (_stageVirtualScreenDDB) {
- UpdateDDBFromBitmap(_stageVirtualScreenDDB, _stageVirtualScreen.get(), true);
- _stageVirtualScreen->ClearTransparent();
- }
- else
- _stageVirtualScreenDDB = CreateDDBFromBitmap(_stageVirtualScreen.get(), true);
- return true;
+ return UpdateStageScreenDDB(_rendSpriteBatch);
}
- return false;
+ return nullptr;
}
IDriverDependantBitmap *VideoMemoryGraphicsDriver::MakeFx(int r, int g, int b) {
diff --git a/engines/ags/engine/gfx/gfx_driver_base.h b/engines/ags/engine/gfx/gfx_driver_base.h
index bad0b2794cc..6b931c23b2d 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.h
+++ b/engines/ags/engine/gfx/gfx_driver_base.h
@@ -169,7 +169,11 @@ protected:
// The range of sprites in this sprite batch (counting nested sprites):
// the last of the previous batch, and the last of the current.
std::vector<std::pair<size_t, size_t>> _spriteBatchRange;
- size_t _actSpriteBatch; // active batch index
+ // The index of a currently filled sprite batch
+ size_t _actSpriteBatch;
+ // The index of a currently rendered sprite batch
+ // (or -1 / UINT32_MAX if we are outside of the render pass)
+ uint32_t _rendSpriteBatch;
};
@@ -255,13 +259,19 @@ protected:
// Stage screens are raw bitmap buffers meant to be sent to plugins on demand
// at certain drawing stages. If used at least once these buffers are then
// rendered as additional sprites in their respected order.
- PBitmap CreateStageScreen(size_t index, const Size &sz);
- PBitmap GetStageScreen(size_t index);
+ // Presets a stage screen with the given size.
+ void SetStageScreen(size_t index, const Size &sz);
+ // Returns a raw bitmap for the given stage screen.
+ Bitmap *GetStageScreenRaw(size_t index);
+ // Updates and returns a DDB for the given stage screen;
+ // clears the raw bitmap after copying to the texture.
+ IDriverDependantBitmap *UpdateStageScreenDDB(size_t index);
+ // Disposes all the stage screen raw bitmaps and DDBs.
void DestroyAllStageScreens();
// Use engine callback to acquire replacement for the null sprite;
- // returns true if the sprite was provided onto the virtual screen,
- // and false if this entry should be skipped.
- bool DoNullSpriteCallback(int x, int y);
+ // returns a DDB if the sprite was provided onto the virtual screen,
+ // and nullptr if this entry should be skipped.
+ IDriverDependantBitmap *DoNullSpriteCallback(int x, int y);
// Prepare and get fx item from the pool
IDriverDependantBitmap *MakeFx(int r, int g, int b);
@@ -292,8 +302,16 @@ protected:
int _vmem_b_shift_32;
private:
- // Virtual screens for rendering stages (sprite batches)
- std::vector<PBitmap> _stageScreens;
+ // Stage virtual screens are used to let plugins draw custom graphics
+ // in between render stages (between room and GUI, after GUI, and so on).
+ // TODO: possibly may be optimized further by having only 1 bitmap/ddb
+ // pair, and subbitmaps for raw drawing on separate stages.
+ struct StageScreen {
+ Size Size; // Size preset (bitmap may be created later)
+ std::unique_ptr<Bitmap> Bitmap;
+ IDriverDependantBitmap *DDB = nullptr;
+ };
+ std::vector<StageScreen> _stageScreens;
// Flag which indicates whether stage screen was drawn upon during engine
// callback and has to be inserted into sprite stack.
bool _stageScreenDirty;
Commit: 6343759e0996cc4287651fcb4d08e947289bffdd
https://github.com/scummvm/scummvm/commit/6343759e0996cc4287651fcb4d08e947289bffdd
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: changed member names in StageScreen to avoid conflicts
>From upstream 874953aea46a23f2ea49ee571cbce28fdc701f25
Changed paths:
engines/ags/engine/gfx/gfx_driver_base.cpp
engines/ags/engine/gfx/gfx_driver_base.h
diff --git a/engines/ags/engine/gfx/gfx_driver_base.cpp b/engines/ags/engine/gfx/gfx_driver_base.cpp
index 8fb58491f8c..86fd4c750f6 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.cpp
+++ b/engines/ags/engine/gfx/gfx_driver_base.cpp
@@ -229,7 +229,7 @@ void VideoMemoryGraphicsDriver::UpdateSharedDDB(uint32_t sprite_id, Bitmap *bitm
void VideoMemoryGraphicsDriver::SetStageScreen(size_t index, const Size &sz) {
if (_stageScreens.size() <= index)
_stageScreens.resize(index + 1);
- _stageScreens[index].Size = sz;
+ _stageScreens[index].PresetSize = sz;
}
Bitmap *VideoMemoryGraphicsDriver::GetStageScreenRaw(size_t index) {
@@ -238,28 +238,28 @@ Bitmap *VideoMemoryGraphicsDriver::GetStageScreenRaw(size_t index) {
return nullptr;
auto &scr = _stageScreens[index];
- const Size sz = scr.Size;
- if (scr.Bitmap && (scr.Bitmap->GetSize() != sz)) {
- scr.Bitmap.reset();
+ const Size sz = scr.PresetSize;
+ if (scr.Raw && (scr.Raw->GetSize() != sz)) {
+ scr.Raw.reset();
if (scr.DDB)
DestroyDDB(scr.DDB);
scr.DDB = nullptr;
}
- if (!scr.Bitmap && !sz.IsNull()) {
- scr.Bitmap.reset(new Bitmap(sz.Width, sz.Height, _mode.ColorDepth));
+ if (!scr.Raw && !sz.IsNull()) {
+ scr.Raw.reset(new Bitmap(sz.Width, sz.Height, _mode.ColorDepth));
scr.DDB = CreateDDB(sz.Width, sz.Height, _mode.ColorDepth, false);
}
- return scr.Bitmap.get();
+ return scr.Raw.get();
}
IDriverDependantBitmap *VideoMemoryGraphicsDriver::UpdateStageScreenDDB(size_t index) {
assert((index < _stageScreens.size()) && _stageScreens[index].DDB);
- if ((_stageScreens.size() <= index) || !_stageScreens[index].Bitmap || !_stageScreens[index].DDB)
+ if ((_stageScreens.size() <= index) || !_stageScreens[index].Raw || !_stageScreens[index].DDB)
return nullptr;
auto &scr = _stageScreens[index];
- UpdateDDBFromBitmap(scr.DDB, scr.Bitmap.get(), true);
- scr.Bitmap->ClearTransparent();
+ UpdateDDBFromBitmap(scr.DDB, scr.Raw.get(), true);
+ scr.Raw->ClearTransparent();
return scr.DDB;
}
diff --git a/engines/ags/engine/gfx/gfx_driver_base.h b/engines/ags/engine/gfx/gfx_driver_base.h
index 6b931c23b2d..3a535431426 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.h
+++ b/engines/ags/engine/gfx/gfx_driver_base.h
@@ -307,8 +307,8 @@ private:
// TODO: possibly may be optimized further by having only 1 bitmap/ddb
// pair, and subbitmaps for raw drawing on separate stages.
struct StageScreen {
- Size Size; // Size preset (bitmap may be created later)
- std::unique_ptr<Bitmap> Bitmap;
+ Size PresetSize; // Size preset (bitmap may be created later)
+ std::unique_ptr<Bitmap> Raw;
IDriverDependantBitmap *DDB = nullptr;
};
std::vector<StageScreen> _stageScreens;
Commit: cd43ec26ede04882ba178478dc0b6271468f847c
https://github.com/scummvm/scummvm/commit/cd43ec26ede04882ba178478dc0b6271468f847c
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Common: wrong clamping in memory stream
>From upstream 020189c4c3e8be9c68fb9f6c0896c7d3506d1113
Changed paths:
engines/ags/shared/util/memory_stream.cpp
diff --git a/engines/ags/shared/util/memory_stream.cpp b/engines/ags/shared/util/memory_stream.cpp
index 08fb485afc9..5fa8fa4f093 100644
--- a/engines/ags/shared/util/memory_stream.cpp
+++ b/engines/ags/shared/util/memory_stream.cpp
@@ -124,7 +124,7 @@ bool MemoryStream::Seek(soff_t offset, StreamSeek origin) {
return false;
}
_pos = static_cast<size_t>(MAX<soff_t>(0, pos));
- _pos = static_cast<size_t>(MIN<soff_t>(_len, pos)); // clamp to EOS
+ _pos = std::min(_len, _pos); // clamp to EOS
return true;
}
Commit: 491f59d3feb4c29c3247c9ab55f5899302577e01
https://github.com/scummvm/scummvm/commit/491f59d3feb4c29c3247c9ab55f5899302577e01
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Plugin: fix pal_render logic mistakes
>From upstream 91ecc267e8ab607e0948416c82433da6f7802dde
Changed paths:
engines/ags/plugins/ags_pal_render/ags_pal_render.cpp
diff --git a/engines/ags/plugins/ags_pal_render/ags_pal_render.cpp b/engines/ags/plugins/ags_pal_render/ags_pal_render.cpp
index ee1c670ab8d..14fa164bc62 100644
--- a/engines/ags/plugins/ags_pal_render/ags_pal_render.cpp
+++ b/engines/ags/plugins/ags_pal_render/ags_pal_render.cpp
@@ -769,7 +769,7 @@ void AGSPalRender::IterateStars(ScriptMethodParams ¶ms) {
stars[i].x = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sw) << 1) - sw;
if (stars[i].x < 1.0 && stars[i].x > -1.0) stars[i].x = (float)sw;
stars[i].y = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sh) << 1) - sh;
- if (stars[i].y < 1.0 && stars[i].y > 1.0) stars[i].y = (float)sh;
+ if (stars[i].y < 1.0 && stars[i].y > -1.0) stars[i].y = (float)sh;
stars[i].z = (float)MAX_DEPTH;
//stars[i].color = (rand () %240);
}
@@ -921,7 +921,7 @@ void AGSPalRender::DrawStars(ScriptMethodParams ¶ms) {
stars[i].x = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sw) << 1) - sw;
if (stars[i].x < 1.0 && stars[i].x > -1.0) stars[i].x = (float)sw;
stars[i].y = (float)((::AGS::g_vm->getRandomNumber(0x7fffffff) % sh) << 1) - sh;
- if (stars[i].y < 1.0 && stars[i].y > 1.0) stars[i].y = (float)sh;
+ if (stars[i].y < 1.0 && stars[i].y > -1.0) stars[i].y = (float)sh;
stars[i].z = (float)MAX_DEPTH;
//stars[i].color = (rand () %240);
} else if (stars[i].z > 0) {
Commit: 823eda79911c0fdd7c4f9a90b885a373ed5d8a39
https://github.com/scummvm/scummvm/commit/823eda79911c0fdd7c4f9a90b885a373ed5d8a39
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: renamed "NullSpriteCallback", give more meaningful name
>From upstream e3c6f5f0b607b8d3a747fa56bdac723ff833f482
Changed paths:
engines/ags/engine/ac/draw.cpp
engines/ags/engine/ac/draw.h
engines/ags/engine/gfx/ali_3d_scummvm.cpp
engines/ags/engine/gfx/gfx_driver_base.cpp
engines/ags/engine/gfx/gfx_driver_base.h
engines/ags/engine/gfx/graphics_driver.h
engines/ags/engine/main/engine_setup.cpp
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 8f302eedff9..6ad7b4143bf 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -2062,12 +2062,12 @@ void put_sprite_list_on_screen(bool in_room) {
_G(our_eip) = 1100;
}
-bool GfxDriverNullSpriteCallback(int x, int y) {
+bool GfxDriverSpriteEvtCallback(int evt, int data) {
if (_G(displayed_room) < 0) {
// if no room loaded, various stuff won't be initialized yet
return 1;
}
- return (pl_run_plugin_hooks(x, y) != 0);
+ return (pl_run_plugin_hooks(evt, data) != 0);
}
void GfxDriverOnInitCallback(void *data) {
diff --git a/engines/ags/engine/ac/draw.h b/engines/ags/engine/ac/draw.h
index 61af0eff02c..275a55d6574 100644
--- a/engines/ags/engine/ac/draw.h
+++ b/engines/ags/engine/ac/draw.h
@@ -186,7 +186,7 @@ void render_to_screen();
// Callbacks for the graphics driver
void draw_game_screen_callback();
void GfxDriverOnInitCallback(void *data);
-bool GfxDriverNullSpriteCallback(int x, int y);
+bool GfxDriverSpriteEvtCallback(int evt, int data);
void putpixel_compensate(Shared::Bitmap *g, int xx, int yy, int col);
// Create the actsps[aa] image with the object drawn correctly.
// Returns true if nothing at all has changed and actsps is still
diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.cpp b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
index 3cea00c5301..6a70bf5531a 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.cpp
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
@@ -376,8 +376,8 @@ size_t ScummVMRendererGraphicsDriver::RenderSpriteBatch(const ALSpriteBatch &bat
for (; (from < _spriteList.size()) && (_spriteList[from].node == batch.ID); ++from) {
const auto &sprite = _spriteList[from];
if (sprite.ddb == nullptr) {
- if (_nullSpriteCallback)
- _nullSpriteCallback(sprite.x, sprite.y);
+ if (_spriteEvtCallback)
+ _spriteEvtCallback(sprite.x, sprite.y);
else
error("Unhandled attempt to draw null sprite");
diff --git a/engines/ags/engine/gfx/gfx_driver_base.cpp b/engines/ags/engine/gfx/gfx_driver_base.cpp
index 86fd4c750f6..d602572254e 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.cpp
+++ b/engines/ags/engine/gfx/gfx_driver_base.cpp
@@ -34,7 +34,7 @@ namespace Engine {
GraphicsDriverBase::GraphicsDriverBase()
: _pollingCallback(nullptr)
, _drawScreenCallback(nullptr)
- , _nullSpriteCallback(nullptr)
+ , _spriteEvtCallback(nullptr)
, _initGfxCallback(nullptr) {
// Initialize default sprite batch, it will be used when no other batch was activated
_actSpriteBatch = 0;
@@ -275,15 +275,15 @@ void VideoMemoryGraphicsDriver::DestroyAllStageScreens() {
_stageScreens.clear();
}
-IDriverDependantBitmap *VideoMemoryGraphicsDriver::DoNullSpriteCallback(int x, int y) {
- if (!_nullSpriteCallback)
+IDriverDependantBitmap *VideoMemoryGraphicsDriver::DoSpriteEvtCallback(int evt, int data) {
+ if (!_spriteEvtCallback)
error("Unhandled attempt to draw null sprite");
_stageScreenDirty = false;
// NOTE: this is not clear whether return value of callback may be
// relied on. Existing plugins do not seem to return anything but 0,
// even if they handle this event. This is why we also set
// _stageScreenDirty in certain plugin API function implementations.
- _stageScreenDirty |= _nullSpriteCallback(x, y) != 0;
+ _stageScreenDirty |= _spriteEvtCallback(evt, data) != 0;
if (_stageScreenDirty) {
return UpdateStageScreenDDB(_rendSpriteBatch);
}
diff --git a/engines/ags/engine/gfx/gfx_driver_base.h b/engines/ags/engine/gfx/gfx_driver_base.h
index 3a535431426..98a6f6408e5 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.h
+++ b/engines/ags/engine/gfx/gfx_driver_base.h
@@ -116,8 +116,8 @@ public:
void SetCallbackOnInit(GFXDRV_CLIENTCALLBACKINITGFX callback) override {
_initGfxCallback = callback;
}
- void SetCallbackForNullSprite(GFXDRV_CLIENTCALLBACKXY callback) override {
- _nullSpriteCallback = callback;
+ void SetCallbackOnSpriteEvt(GFXDRV_CLIENTCALLBACKEVT callback) override {
+ _spriteEvtCallback = callback;
}
protected:
@@ -161,7 +161,7 @@ protected:
GFXDRV_CLIENTCALLBACK _pollingCallback;
GFXDRV_CLIENTCALLBACK _drawScreenCallback;
GFXDRV_CLIENTCALLBACK _drawPostScreenCallback;
- GFXDRV_CLIENTCALLBACKXY _nullSpriteCallback;
+ GFXDRV_CLIENTCALLBACKEVT _spriteEvtCallback;
GFXDRV_CLIENTCALLBACKINITGFX _initGfxCallback;
// Sprite batch parameters
@@ -268,10 +268,10 @@ protected:
IDriverDependantBitmap *UpdateStageScreenDDB(size_t index);
// Disposes all the stage screen raw bitmaps and DDBs.
void DestroyAllStageScreens();
- // Use engine callback to acquire replacement for the null sprite;
+ // Use engine callback to pass a render event;
// returns a DDB if the sprite was provided onto the virtual screen,
// and nullptr if this entry should be skipped.
- IDriverDependantBitmap *DoNullSpriteCallback(int x, int y);
+ IDriverDependantBitmap *DoSpriteEvtCallback(int evt, int data);
// Prepare and get fx item from the pool
IDriverDependantBitmap *MakeFx(int r, int g, int b);
diff --git a/engines/ags/engine/gfx/graphics_driver.h b/engines/ags/engine/gfx/graphics_driver.h
index 4234ff1b4ad..afa5dc35693 100644
--- a/engines/ags/engine/gfx/graphics_driver.h
+++ b/engines/ags/engine/gfx/graphics_driver.h
@@ -92,7 +92,7 @@ struct RenderMatrixes {
typedef void (*GFXDRV_CLIENTCALLBACK)();
-typedef bool (*GFXDRV_CLIENTCALLBACKXY)(int x, int y);
+typedef bool (*GFXDRV_CLIENTCALLBACKEVT)(int evt, int data);
typedef void (*GFXDRV_CLIENTCALLBACKINITGFX)(void *data);
class IGraphicsDriver {
@@ -124,10 +124,10 @@ public:
// TODO: get rid of draw screen callback at some point when all fade functions are more or less grouped in one
virtual void SetCallbackToDrawScreen(GFXDRV_CLIENTCALLBACK callback, GFXDRV_CLIENTCALLBACK post_callback) = 0;
virtual void SetCallbackOnInit(GFXDRV_CLIENTCALLBACKINITGFX callback) = 0;
- // The NullSprite callback is called in the main render loop when a
- // null sprite is encountered. You can use this to hook into the rendering
- // process.
- virtual void SetCallbackForNullSprite(GFXDRV_CLIENTCALLBACKXY callback) = 0;
+ // The event callback is called in the main render loop when a
+ // event entry is encountered inside a sprite list.
+ // You can use this to hook into the rendering process.
+ virtual void SetCallbackOnSpriteEvt(GFXDRV_CLIENTCALLBACKEVT callback) = 0;
// Clears the screen rectangle. The coordinates are expected in the **native game resolution**.
virtual void ClearRectangle(int x1, int y1, int x2, int y2, RGB *colorToUse) = 0;
// Gets closest recommended bitmap format (currently - only color depth) for the given original format.
diff --git a/engines/ags/engine/main/engine_setup.cpp b/engines/ags/engine/main/engine_setup.cpp
index 985925b28a6..5a08c7d5452 100644
--- a/engines/ags/engine/main/engine_setup.cpp
+++ b/engines/ags/engine/main/engine_setup.cpp
@@ -160,14 +160,14 @@ void engine_adjust_for_rotation_settings() {
void engine_post_gfxmode_driver_setup() {
_G(gfxDriver)->SetCallbackForPolling(update_polled_stuff);
_G(gfxDriver)->SetCallbackToDrawScreen(draw_game_screen_callback, construct_engine_overlay);
- _G(gfxDriver)->SetCallbackForNullSprite(GfxDriverNullSpriteCallback);
+ _G(gfxDriver)->SetCallbackOnSpriteEvt(GfxDriverSpriteEvtCallback);
}
// Reset gfx driver callbacks
void engine_pre_gfxmode_driver_cleanup() {
_G(gfxDriver)->SetCallbackForPolling(nullptr);
_G(gfxDriver)->SetCallbackToDrawScreen(nullptr, nullptr);
- _G(gfxDriver)->SetCallbackForNullSprite(nullptr);
+ _G(gfxDriver)->SetCallbackOnSpriteEvt(nullptr);
_G(gfxDriver)->SetMemoryBackBuffer(nullptr);
}
Commit: 1e3bb9c241644fe7ced483ec2739fa80a1584614
https://github.com/scummvm/scummvm/commit/1e3bb9c241644fe7ced483ec2739fa80a1584614
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: support optional size and position for gfxdriver's stage screen
This is primarily for backwards compatibility with the older plugins,
that relied only on software drawing.
Previously we added "stage screens" to the hardware-accelerated
graphic drivers (Direct3D/OpenGL), which provide a surface for
plugins to draw upon. If used, these surfaces would then be rendered
as plain sprites in 3D scene at certain place in the sprite sequence.
The remaining problem (left unnoticed) was that the surfaces which
correspond to the two room render callbacks (right after background,
and right after all objects) did not follow the room camera position and
scaling correctly (not all, tbh). This commit addresses these problems by
letting the engine to request certain size and optional position for these
"stage screens" for particular sprite batches.
Partially from upstream 2d43bffc2cb07935ae72d7c5677ad622c8b4d37e
Changed paths:
engines/ags/engine/ac/draw.cpp
engines/ags/engine/gfx/ali_3d_scummvm.cpp
engines/ags/engine/gfx/ali_3d_scummvm.h
engines/ags/engine/gfx/gfx_driver_base.cpp
engines/ags/engine/gfx/gfx_driver_base.h
engines/ags/engine/gfx/graphics_driver.h
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 6ad7b4143bf..76c0594e513 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -2099,6 +2099,7 @@ static void construct_room_view() {
// and second - how room's image translates into the camera.
_G(gfxDriver)->BeginSpriteBatch(view_rc, SpriteTransform(view_rc.Left, view_rc.Top, view_sx, view_sy));
_G(gfxDriver)->BeginSpriteBatch(Rect(), SpriteTransform(-cam_rc.Left, -cam_rc.Top));
+ _G(gfxDriver)->SetStageScreen(cam_rc.GetSize(), cam_rc.Left, cam_rc.Top);
put_sprite_list_on_screen(true);
_G(gfxDriver)->EndSpriteBatch();
_G(gfxDriver)->EndSpriteBatch();
diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.cpp b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
index 6a70bf5531a..d1b812bf899 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.cpp
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
@@ -329,6 +329,10 @@ void ScummVMRendererGraphicsDriver::SetScreenTint(int red, int green, int blue)
}
}
+void ScummVMRendererGraphicsDriver::SetStageScreen(const Size & /*sz*/, int /*x*/, int /*y*/) {
+ // unsupported, as using _stageVirtualScreen instead
+}
+
void ScummVMRendererGraphicsDriver::RenderToBackBuffer() {
// Close unended batches, and issue a warning
assert(_actSpriteBatch == 0);
diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.h b/engines/ags/engine/gfx/ali_3d_scummvm.h
index 3cb25562ea8..aa815713cb4 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.h
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.h
@@ -196,6 +196,7 @@ public:
void DrawSprite(int x, int y, IDriverDependantBitmap *ddb) override;
void SetScreenFade(int red, int green, int blue) override;
void SetScreenTint(int red, int green, int blue) override;
+ void SetStageScreen(const Size &sz, int x = 0, int y = 0) override;
void RenderToBackBuffer() override;
void Render() override;
diff --git a/engines/ags/engine/gfx/gfx_driver_base.cpp b/engines/ags/engine/gfx/gfx_driver_base.cpp
index d602572254e..772af791cf1 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.cpp
+++ b/engines/ags/engine/gfx/gfx_driver_base.cpp
@@ -226,10 +226,14 @@ void VideoMemoryGraphicsDriver::UpdateSharedDDB(uint32_t sprite_id, Bitmap *bitm
_txRefs.erase(found);
}
-void VideoMemoryGraphicsDriver::SetStageScreen(size_t index, const Size &sz) {
+void VideoMemoryGraphicsDriver::SetStageScreen(const Size &sz, int x, int y) {
+ SetStageScreen(_actSpriteBatch, sz, x, y);
+}
+
+void VideoMemoryGraphicsDriver::SetStageScreen(size_t index, const Size &sz, int x, int y) {
if (_stageScreens.size() <= index)
_stageScreens.resize(index + 1);
- _stageScreens[index].PresetSize = sz;
+ _stageScreens[index].Position = RectWH(x, y, sz.Width, sz.Height);
}
Bitmap *VideoMemoryGraphicsDriver::GetStageScreenRaw(size_t index) {
@@ -238,7 +242,7 @@ Bitmap *VideoMemoryGraphicsDriver::GetStageScreenRaw(size_t index) {
return nullptr;
auto &scr = _stageScreens[index];
- const Size sz = scr.PresetSize;
+ const Size sz = scr.Position.GetSize();
if (scr.Raw && (scr.Raw->GetSize() != sz)) {
scr.Raw.reset();
if (scr.DDB)
@@ -252,7 +256,7 @@ Bitmap *VideoMemoryGraphicsDriver::GetStageScreenRaw(size_t index) {
return scr.Raw.get();
}
-IDriverDependantBitmap *VideoMemoryGraphicsDriver::UpdateStageScreenDDB(size_t index) {
+IDriverDependantBitmap *VideoMemoryGraphicsDriver::UpdateStageScreenDDB(size_t index, int &x, int &y) {
assert((index < _stageScreens.size()) && _stageScreens[index].DDB);
if ((_stageScreens.size() <= index) || !_stageScreens[index].Raw || !_stageScreens[index].DDB)
return nullptr;
@@ -260,6 +264,8 @@ IDriverDependantBitmap *VideoMemoryGraphicsDriver::UpdateStageScreenDDB(size_t i
auto &scr = _stageScreens[index];
UpdateDDBFromBitmap(scr.DDB, scr.Raw.get(), true);
scr.Raw->ClearTransparent();
+ x = scr.Position.Left;
+ y = scr.Position.Top;
return scr.DDB;
}
@@ -275,7 +281,7 @@ void VideoMemoryGraphicsDriver::DestroyAllStageScreens() {
_stageScreens.clear();
}
-IDriverDependantBitmap *VideoMemoryGraphicsDriver::DoSpriteEvtCallback(int evt, int data) {
+IDriverDependantBitmap *VideoMemoryGraphicsDriver::DoSpriteEvtCallback(int evt, int data, int &x, int &y) {
if (!_spriteEvtCallback)
error("Unhandled attempt to draw null sprite");
_stageScreenDirty = false;
@@ -285,7 +291,7 @@ IDriverDependantBitmap *VideoMemoryGraphicsDriver::DoSpriteEvtCallback(int evt,
// _stageScreenDirty in certain plugin API function implementations.
_stageScreenDirty |= _spriteEvtCallback(evt, data) != 0;
if (_stageScreenDirty) {
- return UpdateStageScreenDDB(_rendSpriteBatch);
+ return UpdateStageScreenDDB(_rendSpriteBatch, x, y);
}
return nullptr;
}
diff --git a/engines/ags/engine/gfx/gfx_driver_base.h b/engines/ags/engine/gfx/gfx_driver_base.h
index 98a6f6408e5..10b242561fd 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.h
+++ b/engines/ags/engine/gfx/gfx_driver_base.h
@@ -244,6 +244,9 @@ public:
void UpdateSharedDDB(uint32_t sprite_id, Bitmap *bitmap, bool hasAlpha, bool opaque) override;
void DestroyDDB(IDriverDependantBitmap* ddb) override;
+ // Sets stage screen parameters for the current batch.
+ void SetStageScreen(const Size &sz, int x = 0, int y = 0) override;
+
protected:
// Create texture data with the given parameters
virtual TextureData *CreateTextureData(int width, int height, bool opaque, bool as_render_target = false) = 0;
@@ -259,19 +262,20 @@ protected:
// Stage screens are raw bitmap buffers meant to be sent to plugins on demand
// at certain drawing stages. If used at least once these buffers are then
// rendered as additional sprites in their respected order.
- // Presets a stage screen with the given size.
- void SetStageScreen(size_t index, const Size &sz);
+ // Presets a stage screen with the given position (size is obligatory, offsets not).
+ void SetStageScreen(size_t index, const Size &sz, int x = 0, int y = 0);
// Returns a raw bitmap for the given stage screen.
Bitmap *GetStageScreenRaw(size_t index);
- // Updates and returns a DDB for the given stage screen;
+ // Updates and returns a DDB for the given stage screen, and optional x,y position;
// clears the raw bitmap after copying to the texture.
- IDriverDependantBitmap *UpdateStageScreenDDB(size_t index);
+ IDriverDependantBitmap *UpdateStageScreenDDB(size_t index, int &x, int &y);
// Disposes all the stage screen raw bitmaps and DDBs.
void DestroyAllStageScreens();
// Use engine callback to pass a render event;
- // returns a DDB if the sprite was provided onto the virtual screen,
- // and nullptr if this entry should be skipped.
- IDriverDependantBitmap *DoSpriteEvtCallback(int evt, int data);
+ // returns a DDB if anything was drawn onto the current stage screen
+ // (in which case it also fills optional x,y position),
+ // or nullptr if this entry should be skipped.
+ IDriverDependantBitmap *DoSpriteEvtCallback(int evt, int data, int &x, int &y);
// Prepare and get fx item from the pool
IDriverDependantBitmap *MakeFx(int r, int g, int b);
@@ -307,7 +311,7 @@ private:
// TODO: possibly may be optimized further by having only 1 bitmap/ddb
// pair, and subbitmaps for raw drawing on separate stages.
struct StageScreen {
- Size PresetSize; // Size preset (bitmap may be created later)
+ Rect Position; // bitmap size and pos preset (bitmap may be created later)
std::unique_ptr<Bitmap> Raw;
IDriverDependantBitmap *DDB = nullptr;
};
diff --git a/engines/ags/engine/gfx/graphics_driver.h b/engines/ags/engine/gfx/graphics_driver.h
index afa5dc35693..5ac4a8ac951 100644
--- a/engines/ags/engine/gfx/graphics_driver.h
+++ b/engines/ags/engine/gfx/graphics_driver.h
@@ -169,6 +169,12 @@ public:
// Adds tint overlay fx to the active batch
// TODO: redesign this to allow various post-fx per sprite batch?
virtual void SetScreenTint(int red, int green, int blue) = 0;
+ // Sets stage screen parameters for the current batch.
+ // Currently includes size and optional position offset;
+ // the position is relative, as stage screens are using sprite batch transforms.
+ // Stage screens are used to let plugins do raw drawing during render callbacks.
+ // TODO: find a better term? note, it's used in several places around renderers.
+ virtual void SetStageScreen(const Size &sz, int x = 0, int y = 0) = 0;
// Clears all sprite batches, resets batch counter
virtual void ClearDrawLists() = 0;
virtual void RenderToBackBuffer() = 0;
Commit: c6864a8a67c745e792199853813b3f5032afd27f
https://github.com/scummvm/scummvm/commit/c6864a8a67c745e792199853813b3f5032afd27f
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: added _rendSpriteBatch counter to software renderer
>From upstream 5d051d614cafe2a4f73cc4399eeb78cb38d8ed2d
Changed paths:
engines/ags/engine/gfx/ali_3d_scummvm.cpp
diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.cpp b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
index d1b812bf899..7a5ff72724f 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.cpp
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
@@ -356,6 +356,7 @@ void ScummVMRendererGraphicsDriver::RenderToBackBuffer() {
const Rect &viewport = batch_desc.Viewport;
const SpriteTransform &transform = batch_desc.Transform;
+ _rendSpriteBatch = batch.ID;
virtualScreen->SetClip(viewport);
Bitmap *surface = batch.Surface.get();
const int view_offx = viewport.Left;
@@ -373,6 +374,7 @@ void ScummVMRendererGraphicsDriver::RenderToBackBuffer() {
}
_stageVirtualScreen = virtualScreen;
}
+ _rendSpriteBatch = UINT32_MAX;
ClearDrawLists();
}
Commit: b3a7b2e8ded4c90baa915b5495a24309ce394bb2
https://github.com/scummvm/scummvm/commit/b3a7b2e8ded4c90baa915b5495a24309ce394bb2
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Updated build version (3.6.0.40) and copyright year to 2023
Partially from upstream bacd73914fbad9d48c5390de16c545bf82acd669
Changed paths:
engines/ags/shared/core/def_version.h
diff --git a/engines/ags/shared/core/def_version.h b/engines/ags/shared/core/def_version.h
index 390f6c14293..90027318fee 100644
--- a/engines/ags/shared/core/def_version.h
+++ b/engines/ags/shared/core/def_version.h
@@ -22,13 +22,13 @@
#ifndef AGS_SHARED_CORE_DEFVERSION_H
#define AGS_SHARED_CORE_DEFVERSION_H
-#define ACI_VERSION_STR "3.6.0.39"
+#define ACI_VERSION_STR "3.6.0.40"
#if defined (RC_INVOKED) // for MSVC resource compiler
-#define ACI_VERSION_MSRC_DEF 3.6.0.39
+#define ACI_VERSION_MSRC_DEF 3.6.0.40
#endif
#define SPECIAL_VERSION ""
-#define ACI_COPYRIGHT_YEARS "2011-2022"
+#define ACI_COPYRIGHT_YEARS "2011-2023"
#endif
Commit: 88a1083e0d67042c54cb0dea99bc4405ea2db3b4
https://github.com/scummvm/scummvm/commit/88a1083e0d67042c54cb0dea99bc4405ea2db3b4
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Move strlen out of loops
>From upstream b476dfca4b40bc2ca59b7f0fd793543524397ccf
Changed paths:
engines/ags/engine/script/cc_instance.cpp
engines/ags/plugins/ags_sprite_font/sprite_font_renderer.cpp
engines/ags/plugins/ags_sprite_font/sprite_font_renderer_clifftop.cpp
engines/ags/plugins/ags_sprite_font/variable_width_sprite_font.cpp
engines/ags/plugins/ags_sprite_font/variable_width_sprite_font_clifftop.cpp
diff --git a/engines/ags/engine/script/cc_instance.cpp b/engines/ags/engine/script/cc_instance.cpp
index 81674279112..b0dc7f96db7 100644
--- a/engines/ags/engine/script/cc_instance.cpp
+++ b/engines/ags/engine/script/cc_instance.cpp
@@ -1278,12 +1278,12 @@ RuntimeScriptValue ccInstance::GetSymbolAddress(const char *symname) const {
char altName[200];
snprintf(altName, sizeof(altName), "%s$", symname);
RuntimeScriptValue rval_null;
-
+ size_t len_altName = strlen(altName);
for (k = 0; k < instanceof->numexports; k++) {
if (strcmp(instanceof->exports[k], symname) == 0)
return exports[k];
// mangled function name
- if (strncmp(instanceof->exports[k], altName, strlen(altName)) == 0)
+ if (strncmp(instanceof->exports[k], altName, len_altName) == 0)
return exports[k];
}
return rval_null;
diff --git a/engines/ags/plugins/ags_sprite_font/sprite_font_renderer.cpp b/engines/ags/plugins/ags_sprite_font/sprite_font_renderer.cpp
index 8e26382fdb9..380ec42f5ca 100644
--- a/engines/ags/plugins/ags_sprite_font/sprite_font_renderer.cpp
+++ b/engines/ags/plugins/ags_sprite_font/sprite_font_renderer.cpp
@@ -110,8 +110,8 @@ void SpriteFontRenderer::RenderText(const char *text, int fontNumber, BITMAP *de
//BITMAP *vScreen = _engine->GetVirtualScreen();
//_engine->SetVirtualScreen(destination);
-
- for (int i = 0; i < (int)strlen(text); i++) {
+ int len_text = (int)strlen(text);
+ for (int i = 0; i < len_text; i++) {
char c = text[i];
c -= font->MinChar;
int row = c / font->Columns;
diff --git a/engines/ags/plugins/ags_sprite_font/sprite_font_renderer_clifftop.cpp b/engines/ags/plugins/ags_sprite_font/sprite_font_renderer_clifftop.cpp
index 58a24350b1b..491765db267 100644
--- a/engines/ags/plugins/ags_sprite_font/sprite_font_renderer_clifftop.cpp
+++ b/engines/ags/plugins/ags_sprite_font/sprite_font_renderer_clifftop.cpp
@@ -38,8 +38,8 @@ bool SpriteFontRendererClifftop::SupportsExtendedCharacters(int fontNumber) {
void SpriteFontRendererClifftop::RenderText(const char *text, int fontNumber, BITMAP *destination, int x, int y, int colour) {
SpriteFont *font = getFontFor(fontNumber);
-
- for (int i = 0; i < (int)strlen(text); i++) {
+ int len_text = (int)strlen(text);
+ for (int i = 0; i < len_text; i++) {
char c = text[i];
c -= font->MinChar;
int row = c / font->Columns;
diff --git a/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font.cpp b/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font.cpp
index 986981e7159..f215300cfa5 100644
--- a/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font.cpp
+++ b/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font.cpp
@@ -51,7 +51,8 @@ bool VariableWidthSpriteFontRenderer::SupportsExtendedCharacters(int fontNumber)
int VariableWidthSpriteFontRenderer::GetTextWidth(const char *text, int fontNumber) {
int total = 0;
VariableWidthFont *font = getFontFor(fontNumber);
- for (int i = 0; i < (int)strlen(text); i++) {
+ int len_text = (int)strlen(text);
+ for (int i = 0; i < len_text; i++) {
if (font->characters.count(text[i]) > 0) {
total += font->characters[text[i]].Width;
if (text[i] != ' ') total += font->Spacing;
@@ -62,7 +63,8 @@ int VariableWidthSpriteFontRenderer::GetTextWidth(const char *text, int fontNumb
int VariableWidthSpriteFontRenderer::GetTextHeight(const char *text, int fontNumber) {
VariableWidthFont *font = getFontFor(fontNumber);
- for (int i = 0; i < (int)strlen(text); i++) {
+ int len_text = (int)strlen(text);
+ for (int i = 0; i < len_text; i++) {
if (font->characters.count(text[i]) > 0) {
return font->characters[text[i]].Height;
}
@@ -156,7 +158,8 @@ VariableWidthFont *VariableWidthSpriteFontRenderer::getFontFor(int fontNum) {
void VariableWidthSpriteFontRenderer::RenderText(const char *text, int fontNumber, BITMAP *destination, int x, int y, int colour) {
VariableWidthFont *font = getFontFor(fontNumber);
int totalWidth = 0;
- for (int i = 0; i < (int)strlen(text); i++) {
+ int len_text = (int)strlen(text);
+ for (int i = 0; i < len_text; i++) {
char c = text[i];
BITMAP *src = _engine->GetSpriteGraphic(font->SpriteNumber);
@@ -164,7 +167,6 @@ void VariableWidthSpriteFontRenderer::RenderText(const char *text, int fontNumbe
totalWidth += font->characters[c].Width;
if (text[i] != ' ') totalWidth += font->Spacing;
}
-
}
diff --git a/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font_clifftop.cpp b/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font_clifftop.cpp
index df5607cf1f1..f896c26f26f 100644
--- a/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font_clifftop.cpp
+++ b/engines/ags/plugins/ags_sprite_font/variable_width_sprite_font_clifftop.cpp
@@ -35,7 +35,8 @@ VariableWidthSpriteFontRendererClifftop::~VariableWidthSpriteFontRendererCliffto
void VariableWidthSpriteFontRendererClifftop::RenderText(const char *text, int fontNumber, BITMAP *destination, int x, int y, int colour) {
VariableWidthFont *font = getFontFor(fontNumber);
int totalWidth = 0;
- for (int i = 0; i < (int)strlen(text); i++) {
+ int len_text = (int)strlen(text);
+ for (int i = 0; i < len_text; i++) {
char c = text[i];
BITMAP *src = _engine->GetSpriteGraphic(font->SpriteNumber);
Commit: da88b81fdfed1e2c0bca6db61fc09e2e0146caff
https://github.com/scummvm/scummvm/commit/da88b81fdfed1e2c0bca6db61fc09e2e0146caff
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: SnowRain: do not override user-set baselines
Reimplemented from upstream a01f58a826e56746b3fc5e503bebb3f3dcbcf884
Changed paths:
engines/ags/plugins/ags_snow_rain/ags_snow_rain.cpp
engines/ags/plugins/ags_snow_rain/weather.cpp
engines/ags/plugins/ags_snow_rain/weather.h
diff --git a/engines/ags/plugins/ags_snow_rain/ags_snow_rain.cpp b/engines/ags/plugins/ags_snow_rain/ags_snow_rain.cpp
index f403a818be1..ad135d1ac8b 100644
--- a/engines/ags/plugins/ags_snow_rain/ags_snow_rain.cpp
+++ b/engines/ags/plugins/ags_snow_rain/ags_snow_rain.cpp
@@ -82,11 +82,7 @@ int64 AGSSnowRain::AGS_EngineOnEvent(int event, NumberPtr data) {
_snow.UpdateWithDrift();
} else if (event == AGSE_ENTERROOM) {
// Get screen size when entering a room
- // FIXME: Upsteam uses srSetBaseline that doubles the height value if screenHeight == 400.
- // That doesn't seem to make a difference. Also the implementation changed in later commits
_engine->GetScreenDimensions(&_screenWidth, &_screenHeight, &_screenColorDepth);
- _rain.SetBaseline(0, _screenHeight);
- _snow.SetBaseline(0, _screenHeight);
_rain.EnterRoom();
_snow.EnterRoom();
} else if (event == AGSE_RESTOREGAME) {
diff --git a/engines/ags/plugins/ags_snow_rain/weather.cpp b/engines/ags/plugins/ags_snow_rain/weather.cpp
index 51f01da8dce..149806ad827 100644
--- a/engines/ags/plugins/ags_snow_rain/weather.cpp
+++ b/engines/ags/plugins/ags_snow_rain/weather.cpp
@@ -193,6 +193,10 @@ bool Weather::IsActive() {
void Weather::EnterRoom() {
_mAmount = _mTargetAmount;
+
+ // If baseline is not fixed, reset and clamp to the new screenHeight
+ if (!_mBaselineFixed)
+ ResetBaseline();
}
void Weather::ClipToRange(int &variable, int min, int max) {
@@ -209,7 +213,7 @@ void Weather::Initialize() {
SetTransparency(0, 0);
SetWindSpeed(0);
- SetBaseline(0, 200);
+ ResetBaseline();
if (_mIsSnow)
SetFallSpeed(10, 70);
@@ -347,6 +351,15 @@ void Weather::SetBaseline(int top, int bottom) {
if (_mDeltaBaseline == 0)
_mDeltaBaseline = 1;
+
+ _mBaselineFixed = true;
+}
+
+void Weather::ResetBaseline() {
+ _mTopBaseline = 0;
+ _mBottomBaseline = _screenHeight;
+ _mDeltaBaseline = _screenHeight;
+ _mBaselineFixed = false;
}
void Weather::SetAmount(int amount) {
diff --git a/engines/ags/plugins/ags_snow_rain/weather.h b/engines/ags/plugins/ags_snow_rain/weather.h
index ceecb173794..9d3d6ee6a9c 100644
--- a/engines/ags/plugins/ags_snow_rain/weather.h
+++ b/engines/ags/plugins/ags_snow_rain/weather.h
@@ -88,6 +88,7 @@ private:
float _mWindSpeed = 0;
+ bool _mBaselineFixed;
int _mTopBaseline = 0;
int _mBottomBaseline = 0;
int _mDeltaBaseline = 0;
@@ -122,7 +123,11 @@ public:
void SetDefaultView(int view, int loop);
void SetTransparency(int min_value, int max_value);
void SetWindSpeed(int value);
+ // Sets baseline and marks baseline as fixed
void SetBaseline(int top, int bottom);
+ // Resets baselines to the (0, screen_height);
+ // marks baseline for auto-update on screen change
+ void ResetBaseline();
void SetAmount(int amount);
void SetFallSpeed(int min_value, int max_value);
};
Commit: 0f90b07118aec14c73180942cebbf026670f6421
https://github.com/scummvm/scummvm/commit/0f90b07118aec14c73180942cebbf026670f6421
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Common: also assert in GetScanLineForWriting()
>From upstream 872598fea699341c7de82484b43678d91dcc425e
Changed paths:
engines/ags/shared/gfx/allegro_bitmap.h
diff --git a/engines/ags/shared/gfx/allegro_bitmap.h b/engines/ags/shared/gfx/allegro_bitmap.h
index 7cc8333ece1..a6794b72d8e 100644
--- a/engines/ags/shared/gfx/allegro_bitmap.h
+++ b/engines/ags/shared/gfx/allegro_bitmap.h
@@ -233,7 +233,8 @@ public:
// TODO: think how to increase safety over this (some fixed memory buffer class with iterator?)
// Gets scanline for directly writing into it
inline unsigned char *GetScanLineForWriting(int index) {
- return (index >= 0 && index < GetHeight()) ? _alBitmap->line[index] : nullptr;
+ assert(index >= 0 && index < GetHeight());
+ return _alBitmap->line[index];
}
inline unsigned char *GetDataForWriting() {
return _alBitmap->line[0];
Commit: 7b5bcb881a2d002e2d5567f457a4eb7422b58cfe
https://github.com/scummvm/scummvm/commit/7b5bcb881a2d002e2d5567f457a4eb7422b58cfe
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: fail when reading game data should return error
>From upstream 416c456db0b20f5896506f86525faec0a353893f
Changed paths:
engines/ags/engine/main/game_file.cpp
diff --git a/engines/ags/engine/main/game_file.cpp b/engines/ags/engine/main/game_file.cpp
index 0b0647c7e9d..650c8ed7836 100644
--- a/engines/ags/engine/main/game_file.cpp
+++ b/engines/ags/engine/main/game_file.cpp
@@ -175,6 +175,8 @@ HError load_game_file() {
return err;
err = (HError)ReadGameData(ents, src.InputStream.get(), src.DataVersion);
+ if (!err)
+ return err;
src.InputStream.reset();
//-------------------------------------------------------------------------
Commit: 26c2a748deb48df26b0ba03217a07c6c0b37ae8b
https://github.com/scummvm/scummvm/commit/26c2a748deb48df26b0ba03217a07c6c0b37ae8b
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Alfont: fix leak, release before freeing last reference
>From upstream 43c5560bd6d2f28a31ec402081c7fa7c5bbf78de
Changed paths:
engines/ags/lib/alfont/alfont.cpp
diff --git a/engines/ags/lib/alfont/alfont.cpp b/engines/ags/lib/alfont/alfont.cpp
index b585969c888..0d233170c71 100644
--- a/engines/ags/lib/alfont/alfont.cpp
+++ b/engines/ags/lib/alfont/alfont.cpp
@@ -955,8 +955,11 @@ void alfont_textout_aa_ex(BITMAP *bmp, ALFONT_FONT *f, const char *s, int x, int
/* is it under or over or too far to the right of the clipping rect then
we can assume the string is clipped */
- if ((y + f->face_h < bmp->ct) || (y > bmp->cb) || (x > bmp->cr))
+ if ((y + f->face_h < bmp->ct) || (y > bmp->cb) || (x > bmp->cr)) {
+ if(s_pointer) free(s_pointer);
+ s_pointer = NULL;
return;
+ }
//build transparency
if (f->transparency != 255) {
@@ -2052,8 +2055,11 @@ void alfont_textout_ex(BITMAP * bmp, ALFONT_FONT * f, const char *s, int x, int
/* is it under or over or too far to the right of the clipping rect then
we can assume the string is clipped */
- if ((y + f->face_h < bmp->ct) || (y > bmp->cb) || (x > bmp->cr))
+ if ((y + f->face_h < bmp->ct) || (y > bmp->cb) || (x > bmp->cr)) {
+ if(s_pointer) free(s_pointer);
+ s_pointer = NULL;
return;
+ }
//build transparency
if (f->transparency != 255) {
Commit: f0c18ccacb6d61b0b10258c020716a194ef5beaf
https://github.com/scummvm/scummvm/commit/f0c18ccacb6d61b0b10258c020716a194ef5beaf
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: fixed GUI sorting for cases when ZOrder is equal
Was broken by fcc873e
>From upstream ff210b2ce50cea0e903cd1d09fa7ad1734a862b0
Changed paths:
engines/ags/engine/ac/gui.cpp
diff --git a/engines/ags/engine/ac/gui.cpp b/engines/ags/engine/ac/gui.cpp
index 77e1f8b7a7a..c66931b6ef0 100644
--- a/engines/ags/engine/ac/gui.cpp
+++ b/engines/ags/engine/ac/gui.cpp
@@ -406,9 +406,9 @@ void replace_macro_tokens(const char *text, String &fixed_text) {
}
}
-
bool sort_gui_less(const int g1, const int g2) {
- return _GP(guis)[g1].ZOrder < _GP(guis)[g2].ZOrder;
+ return (_GP(guis)[g1].ZOrder < _GP(guis)[g2].ZOrder) ||
+ ((_GP(guis)[g1].ZOrder == _GP(guis)[g2].ZOrder) && (g1 < g2));
}
void update_gui_zorder() {
Commit: 1bc1c49dbf35c986bf92cad5491c7482f8eb63f9
https://github.com/scummvm/scummvm/commit/1bc1c49dbf35c986bf92cad5491c7482f8eb63f9
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: fixed missing channels after restoring old save in updated game
>From upstream d5ded80f8219b1f04e484c369d647bbc9ed8edd8
Changed paths:
engines/ags/engine/ac/dynobj/cc_dynamic_object.cpp
engines/ags/engine/ac/dynobj/cc_dynamic_object.h
engines/ags/engine/game/savegame.cpp
engines/ags/engine/media/audio/audio.cpp
engines/ags/engine/media/audio/audio.h
diff --git a/engines/ags/engine/ac/dynobj/cc_dynamic_object.cpp b/engines/ags/engine/ac/dynobj/cc_dynamic_object.cpp
index 0f59d9fcba8..a0bb167de27 100644
--- a/engines/ags/engine/ac/dynobj/cc_dynamic_object.cpp
+++ b/engines/ags/engine/ac/dynobj/cc_dynamic_object.cpp
@@ -93,12 +93,12 @@ void ccAttemptDisposeObject(int32_t handle) {
}
// translate between object handles and memory addresses
-int32_t ccGetObjectHandleFromAddress(const char *address) {
+int32_t ccGetObjectHandleFromAddress(const void *address) {
// set to null
if (address == nullptr)
return 0;
- int32_t handl = _GP(pool).AddressToHandle(address);
+ int32_t handl = _GP(pool).AddressToHandle((const char *)address);
ManagedObjectLog("Line %d WritePtr: %08X to %d", _G(currentline), address, handl);
diff --git a/engines/ags/engine/ac/dynobj/cc_dynamic_object.h b/engines/ags/engine/ac/dynobj/cc_dynamic_object.h
index f92e03dd117..ecaf2dd441d 100644
--- a/engines/ags/engine/ac/dynobj/cc_dynamic_object.h
+++ b/engines/ags/engine/ac/dynobj/cc_dynamic_object.h
@@ -123,7 +123,7 @@ extern int ccUnserializeAllObjects(Shared::Stream *in, ICCObjectReader *callba
// dispose the object if RefCount==0
extern void ccAttemptDisposeObject(int32_t handle);
// translate between object handles and memory addresses
-extern int32_t ccGetObjectHandleFromAddress(const char *address);
+extern int32_t ccGetObjectHandleFromAddress(const void *address);
// TODO: not sure if it makes any sense whatsoever to use "const char*"
// in these functions, might as well change to char* or just void*.
extern const char *ccGetObjectAddressFromHandle(int32_t handle);
diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index 9bcc575c63c..fe45c725e1c 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -379,7 +379,7 @@ void DoBeforeRestore(PreservedParams &pp) {
free_do_once_tokens();
// unregister gui controls from API exports
- // TODO: find out why are we doing this here? is this really necessary?
+ // CHECKME: find out why are we doing this here? why only to gui controls?
for (int i = 0; i < _GP(game).numgui; ++i) {
unexport_gui_controls(i);
}
@@ -452,8 +452,13 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
_G(dynamicallyCreatedSurfaces)[i] = r_data.DynamicSurfaces[i];
}
+ // Re-export any missing audio channel script objects, e.g. if restoring old save
+ export_missing_audiochans();
+
+ // CHECKME: find out why are we doing this here? why only to gui controls?
for (int i = 0; i < _GP(game).numgui; ++i)
export_gui_controls(i);
+
update_gui_zorder();
if (create_global_script()) {
diff --git a/engines/ags/engine/media/audio/audio.cpp b/engines/ags/engine/media/audio/audio.cpp
index 9a5e6d1ef48..b383b568c99 100644
--- a/engines/ags/engine/media/audio/audio.cpp
+++ b/engines/ags/engine/media/audio/audio.cpp
@@ -462,6 +462,13 @@ void stop_and_destroy_channel(int chid) {
stop_and_destroy_channel_ex(chid, true);
}
+void export_missing_audiochans() {
+ for (int i = 0; i < _GP(game).numCompatGameChannels; ++i) {
+ int h = ccGetObjectHandleFromAddress(&_G(scrAudioChannel)[i]);
+ if (h <= 0)
+ ccRegisterManagedObject(&_G(scrAudioChannel)[i], &_GP(ccDynamicAudio));
+ }
+}
// ***** BACKWARDS COMPATIBILITY WITH OLD AUDIO SYSTEM ***** //
diff --git a/engines/ags/engine/media/audio/audio.h b/engines/ags/engine/media/audio/audio.h
index 28659305a7f..03394266a8d 100644
--- a/engines/ags/engine/media/audio/audio.h
+++ b/engines/ags/engine/media/audio/audio.h
@@ -72,6 +72,8 @@ ScriptAudioChannel *play_audio_clip(ScriptAudioClip *clip, int priority, int rep
ScriptAudioChannel *play_audio_clip_by_index(int audioClipIndex);
void stop_and_destroy_channel_ex(int chid, bool resetLegacyMusicSettings);
void stop_and_destroy_channel(int chid);
+// Exports missing AudioChannel objects to script (for importing older saves)
+void export_missing_audiochans();
// ***** BACKWARDS COMPATIBILITY WITH OLD AUDIO SYSTEM ***** //
int get_old_style_number_for_sound(int sound_number);
Commit: 5b7f95075ee90337c93dffad60010613e208dd51
https://github.com/scummvm/scummvm/commit/5b7f95075ee90337c93dffad60010613e208dd51
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: removed unused global var
>From upstream b2dc19eef19f1498e4510de5672cb65c281d33d4
Changed paths:
engines/ags/globals.h
diff --git a/engines/ags/globals.h b/engines/ags/globals.h
index 04316edfff3..c9188dc51bd 100644
--- a/engines/ags/globals.h
+++ b/engines/ags/globals.h
@@ -302,7 +302,6 @@ public:
std::array<AmbientSound> *_ambient;
ScriptAudioChannel *_scrAudioChannel;
- char _acaudio_buffer[256];
int _reserved_channel_count = 0;
// This is an indicator of a music played by an old audio system
Commit: e62a2c3504170eae9d994c5311a1f98cb66ba8a2
https://github.com/scummvm/scummvm/commit/e62a2c3504170eae9d994c5311a1f98cb66ba8a2
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: don't reset batch surfaces in software driver's ResetAllBatches
>From upstream 662318d0dc1e877a334e91b1a964a41de2b46573
Changed paths:
engines/ags/engine/gfx/ali_3d_scummvm.cpp
diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.cpp b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
index 7a5ff72724f..0f89bd3f48e 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.cpp
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
@@ -306,7 +306,8 @@ void ScummVMRendererGraphicsDriver::InitSpriteBatch(size_t index, const SpriteBa
}
void ScummVMRendererGraphicsDriver::ResetAllBatches() {
- _spriteBatches.clear();
+ // NOTE: we don't release batches themselves here, only sprite lists.
+ // This is because we cache batch surfaces, for perfomance reasons.
_spriteList.clear();
}
Commit: 43723e170a771b79201c5b1480425d07c40586cb
https://github.com/scummvm/scummvm/commit/43723e170a771b79201c5b1480425d07c40586cb
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: in SetMemoryBackBuffer() don't reset batch surfs during render
In ALSoftwareGraphicsDriver:
* Save index of a currently rendered sprite batch (or none, if not inside
a render pass).
* In SetMemoryBackBuffer() don't reset virtual screen subbitmaps
unless we are outside render pass.
* In InitSpriteBatch() also test if batch's surface is subbitmap to the
current virtual screen (in case one was replaced, but batch's surface
stayed).
Partially from upstream 5dd078961020da6478347dac01dea729471333d1
Changed paths:
engines/ags/engine/gfx/ali_3d_scummvm.cpp
engines/ags/lib/allegro/gfx.cpp
engines/ags/lib/allegro/gfx.h
engines/ags/shared/gfx/allegro_bitmap.h
diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.cpp b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
index 0f89bd3f48e..94308e700ad 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.cpp
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
@@ -289,8 +289,10 @@ void ScummVMRendererGraphicsDriver::InitSpriteBatch(size_t index, const SpriteBa
else if (desc.Transform.ScaleX == 1.f && desc.Transform.ScaleY == 1.f) {
// We need this subbitmap for plugins, which use _stageVirtualScreen and are unaware of possible multiple viewports;
// TODO: there could be ways to optimize this further, but best is to update plugin rendering hooks (and upgrade plugins)
- if (!batch.Surface || !batch.IsVirtualScreen || batch.Surface->GetWidth() != src_w || batch.Surface->GetHeight() != src_h
- || batch.Surface->GetSubOffset() != desc.Viewport.GetLT()) {
+ if (!batch.Surface || !batch.IsVirtualScreen ||
+ (batch.Surface->GetWidth() != src_w) || (batch.Surface->GetHeight() != src_h) ||
+ (!batch.Surface->IsSameBitmap(virtualScreen)) ||
+ (batch.Surface->GetSubOffset() != desc.Viewport.GetLT())) {
Rect rc = RectWH(desc.Viewport.Left, desc.Viewport.Top, desc.Viewport.GetWidth(), desc.Viewport.GetHeight());
batch.Surface.reset(BitmapHelper::CreateSubBitmap(virtualScreen, rc));
}
@@ -575,7 +577,11 @@ void ScummVMRendererGraphicsDriver::SetMemoryBackBuffer(Bitmap *backBuffer) {
}
_stageVirtualScreen = virtualScreen;
- // Reset old virtual screen's subbitmaps
+ // Reset old virtual screen's subbitmaps;
+ // NOTE: this MUST NOT be called in the midst of the RenderSpriteBatches!
+ assert(_rendSpriteBatch == UINT32_MAX);
+ if (_rendSpriteBatch != UINT32_MAX)
+ return;
for (auto &batch : _spriteBatches) {
if (batch.IsVirtualScreen)
batch.Surface.reset();
diff --git a/engines/ags/lib/allegro/gfx.cpp b/engines/ags/lib/allegro/gfx.cpp
index 1038823afac..4e0f791a9b9 100644
--- a/engines/ags/lib/allegro/gfx.cpp
+++ b/engines/ags/lib/allegro/gfx.cpp
@@ -194,6 +194,19 @@ bool is_linear_bitmap(BITMAP *bmp) {
return true;
}
+bool is_same_bitmap(BITMAP *bmp1, BITMAP *bmp2) {
+ if ((bmp1 == nullptr) || (bmp2 == nullptr))
+ return false;
+ if (bmp1 == bmp2)
+ return true;
+
+ // TODO: allegro also returns true if one bmp is a sub of the other,
+ // i.e. they share the same id
+ // This (if needed?) would require a different implementation
+
+ return false;
+}
+
void bmp_select(BITMAP *bmp) {
// No implementation needed
}
diff --git a/engines/ags/lib/allegro/gfx.h b/engines/ags/lib/allegro/gfx.h
index 6b1ba3d4355..218749a2e60 100644
--- a/engines/ags/lib/allegro/gfx.h
+++ b/engines/ags/lib/allegro/gfx.h
@@ -207,6 +207,7 @@ extern void pivot_sprite(BITMAP *bmp, const BITMAP *sprite, int x, int y, int cx
extern bool is_screen_bitmap(BITMAP *bmp);
extern bool is_video_bitmap(BITMAP *bmp);
extern bool is_linear_bitmap(BITMAP *bmp);
+extern bool is_same_bitmap(BITMAP *bmp1, BITMAP *bmp2);
extern bool is_planar_bitmap(BITMAP *bmp);
extern void bmp_select(BITMAP *bmp);
extern byte *bmp_write_line(BITMAP *bmp, int line);
diff --git a/engines/ags/shared/gfx/allegro_bitmap.h b/engines/ags/shared/gfx/allegro_bitmap.h
index a6794b72d8e..62e184490de 100644
--- a/engines/ags/shared/gfx/allegro_bitmap.h
+++ b/engines/ags/shared/gfx/allegro_bitmap.h
@@ -101,6 +101,11 @@ public:
return _alBitmap->isSubBitmap();
}
+ // Do both bitmaps share same data (usually: subbitmaps, or parent/subbitmap)
+ inline bool IsSameBitmap(Bitmap *other) const {
+ return is_same_bitmap(_alBitmap, other->_alBitmap) != 0;
+ }
+
// Checks if bitmap cannot be used
inline bool IsNull() const {
return !_alBitmap;
Commit: 50d8eaddcfdb589a6a254a2650fedc02da1a1faf
https://github.com/scummvm/scummvm/commit/50d8eaddcfdb589a6a254a2650fedc02da1a1faf
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: in IAGSEngine::SetVirtualScreen set Stage buffer, not whole VS
When plugin calls SetVirtualScreen (for software renderer), don't
replace whole virtual screen, instead replace only the current
render stage buffer.
This is complementary to the older changes in software renderer,
made during development of AGS 3.5.0, which featured advanced
room viewports and cameras. Since that change, separate render
stages could draw on sub-bitmaps of smaller size.
While IAGSEngine::GetVirtualScreen() was adjusted to follow that
change, and return not the whole virtual screen, but only a "stage
buffer" (which may be a VS sub-bitmap, or an intermediate bitmap
created specifically for this render stage), SetVirtualScreen() was
NOT adjusted accordingly and kept replacing whole VS. As a
result, this discrepancy could cause logical errors, as well as
crashes with plugins that use this API (e.g. original SnowRain
plugin).
The immediate reason of error is that plugin would remember a
pointer returned from GetVirtualScreen (which is a stage buffer),
and then try to set it back with SetVirtualScreen. As a result,
engine's own stage buffer is assigned as a full virtual screen.
>From upstream 09143ea7fbf8474f78932116ae1c81ceff4de95a
Changed paths:
engines/ags/engine/gfx/ali_3d_scummvm.cpp
engines/ags/engine/gfx/ali_3d_scummvm.h
engines/ags/engine/gfx/gfx_driver_base.cpp
engines/ags/engine/gfx/gfx_driver_base.h
engines/ags/engine/gfx/graphics_driver.h
engines/ags/plugins/ags_plugin.cpp
diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.cpp b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
index 94308e700ad..c4f2f6a5454 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.cpp
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.cpp
@@ -375,8 +375,8 @@ void ScummVMRendererGraphicsDriver::RenderToBackBuffer() {
} else {
cur_spr = RenderSpriteBatch(batch, cur_spr, virtualScreen, view_offx + transform.X, view_offy + transform.Y);
}
- _stageVirtualScreen = virtualScreen;
}
+ _stageVirtualScreen = virtualScreen;
_rendSpriteBatch = UINT32_MAX;
ClearDrawLists();
}
@@ -389,7 +389,8 @@ size_t ScummVMRendererGraphicsDriver::RenderSpriteBatch(const ALSpriteBatch &bat
_spriteEvtCallback(sprite.x, sprite.y);
else
error("Unhandled attempt to draw null sprite");
-
+ // Stage surface could have been replaced by plugin
+ surface = _stageVirtualScreen;
continue;
} else if (sprite.ddb == reinterpret_cast<ALSoftwareBitmap *>(DRAWENTRY_TINT)) {
// draw screen tint fx
@@ -570,7 +571,9 @@ Bitmap *ScummVMRendererGraphicsDriver::GetMemoryBackBuffer() {
}
void ScummVMRendererGraphicsDriver::SetMemoryBackBuffer(Bitmap *backBuffer) {
- if (backBuffer) {
+ // We need to also test internal AL BITMAP pointer, because we may receive it raw from plugin,
+ // in which case the Bitmap object may be a different wrapper over our own virtual screen.
+ if (backBuffer && (backBuffer->GetAllegroBitmap() != _origVirtualScreen->GetAllegroBitmap())) {
virtualScreen = backBuffer;
} else {
virtualScreen = _origVirtualScreen.get();
@@ -592,6 +595,16 @@ Bitmap *ScummVMRendererGraphicsDriver::GetStageBackBuffer(bool /*mark_dirty*/) {
return _stageVirtualScreen;
}
+void ScummVMRendererGraphicsDriver::SetStageBackBuffer(Bitmap *backBuffer) {
+ Bitmap *cur_stage = (_rendSpriteBatch == UINT32_MAX) ? virtualScreen : _spriteBatches[_rendSpriteBatch].Surface.get();
+ // We need to also test internal AL BITMAP pointer, because we may receive it raw from plugin,
+ // in which case the Bitmap object may be a different wrapper over our own virtual screen.
+ if (backBuffer && (backBuffer->GetAllegroBitmap() != cur_stage->GetAllegroBitmap()))
+ _stageVirtualScreen = backBuffer;
+ else
+ _stageVirtualScreen = cur_stage;
+}
+
bool ScummVMRendererGraphicsDriver::GetCopyOfScreenIntoBitmap(Bitmap *destination, bool at_native_res, GraphicResolution *want_fmt) {
(void)at_native_res; // software driver always renders at native resolution at the moment
// software filter is taught to copy to any size
diff --git a/engines/ags/engine/gfx/ali_3d_scummvm.h b/engines/ags/engine/gfx/ali_3d_scummvm.h
index aa815713cb4..bfeb47d53e1 100644
--- a/engines/ags/engine/gfx/ali_3d_scummvm.h
+++ b/engines/ags/engine/gfx/ali_3d_scummvm.h
@@ -223,6 +223,7 @@ public:
Bitmap *GetMemoryBackBuffer() override;
void SetMemoryBackBuffer(Bitmap *backBuffer) override;
Bitmap *GetStageBackBuffer(bool mark_dirty) override;
+ void SetStageBackBuffer(Bitmap *backBuffer) override;
bool GetStageMatrixes(RenderMatrixes & /*rm*/) override {
return false; /* not supported */
}
diff --git a/engines/ags/engine/gfx/gfx_driver_base.cpp b/engines/ags/engine/gfx/gfx_driver_base.cpp
index 772af791cf1..d25229bcffd 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.cpp
+++ b/engines/ags/engine/gfx/gfx_driver_base.cpp
@@ -170,6 +170,10 @@ Bitmap *VideoMemoryGraphicsDriver::GetStageBackBuffer(bool mark_dirty) {
return GetStageScreenRaw(_rendSpriteBatch);
}
+void VideoMemoryGraphicsDriver::SetStageBackBuffer(Bitmap *backBuffer) {
+ // do nothing, video-memory drivers don't support this
+}
+
bool VideoMemoryGraphicsDriver::GetStageMatrixes(RenderMatrixes &rm) {
rm = _stageMatrixes;
return true;
diff --git a/engines/ags/engine/gfx/gfx_driver_base.h b/engines/ags/engine/gfx/gfx_driver_base.h
index 10b242561fd..cd00edc563d 100644
--- a/engines/ags/engine/gfx/gfx_driver_base.h
+++ b/engines/ags/engine/gfx/gfx_driver_base.h
@@ -231,6 +231,7 @@ public:
Bitmap *GetMemoryBackBuffer() override;
void SetMemoryBackBuffer(Bitmap *backBuffer) override;
Bitmap *GetStageBackBuffer(bool mark_dirty) override;
+ void SetStageBackBuffer(Bitmap *backBuffer) override;
bool GetStageMatrixes(RenderMatrixes &rm) override;
// Creates new texture using given parameters
IDriverDependantBitmap *CreateDDB(int width, int height, int color_depth, bool opaque) override = 0;
diff --git a/engines/ags/engine/gfx/graphics_driver.h b/engines/ags/engine/gfx/graphics_driver.h
index 5ac4a8ac951..4701e5e94fe 100644
--- a/engines/ags/engine/gfx/graphics_driver.h
+++ b/engines/ags/engine/gfx/graphics_driver.h
@@ -219,7 +219,11 @@ public:
virtual void SetMemoryBackBuffer(Shared::Bitmap *backBuffer) = 0;
// Returns memory backbuffer for the current rendering stage (or base virtual screen if called outside of render pass).
// All renderers should support this.
- virtual Shared::Bitmap *GetStageBackBuffer(bool mark_dirty) = 0;
+ virtual Shared::Bitmap *GetStageBackBuffer(bool mark_dirty = false) = 0;
+ // Sets custom backbuffer bitmap to render current render stage to.
+ // Passing NULL pointer will tell renderer to switch back to its original stage buffer.
+ // Note that only software renderer supports this.
+ virtual void SetStageBackBuffer(Shared::Bitmap *backBuffer) = 0;
// Retrieves 3 transform matrixes for the current rendering stage: world (model), view and projection.
// These matrixes will be filled in accordance to the renderer's compatible format;
// returns false if renderer does not use matrixes (not a 3D renderer).
diff --git a/engines/ags/plugins/ags_plugin.cpp b/engines/ags/plugins/ags_plugin.cpp
index 6f624b7e51e..49975b3e540 100644
--- a/engines/ags/plugins/ags_plugin.cpp
+++ b/engines/ags/plugins/ags_plugin.cpp
@@ -299,15 +299,15 @@ void IAGSEngine::DrawTextWrapped(int32 xx, int32 yy, int32 wid, int32 font, int3
void IAGSEngine::SetVirtualScreen(BITMAP *bmp) {
if (!_G(gfxDriver)->UsesMemoryBackBuffer()) {
debug_script_warn("SetVirtualScreen: this plugin requires software graphics driver to work correctly.");
- // we let it continue since gfxDriver is supposed to ignore this request without throwing an exception
+ return;
}
if (bmp) {
_GP(glVirtualScreenWrap).WrapAllegroBitmap(bmp, true);
- _G(gfxDriver)->SetMemoryBackBuffer(&_GP(glVirtualScreenWrap));
+ _G(gfxDriver)->SetStageBackBuffer(&_GP(glVirtualScreenWrap));
} else {
_GP(glVirtualScreenWrap).Destroy();
- _G(gfxDriver)->SetMemoryBackBuffer(nullptr);
+ _G(gfxDriver)->SetStageBackBuffer(nullptr);
}
}
Commit: 3d91a8835e7c3cb5f3af27b2d13342e7c0a8b716
https://github.com/scummvm/scummvm/commit/3d91a8835e7c3cb5f3af27b2d13342e7c0a8b716
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: fixed button keeps "mouse over" pic after Visible = false
>From upstream dcec61ba9825be21a0d2009a73b2af24df6a912d
Changed paths:
engines/ags/engine/ac/gui_control.cpp
diff --git a/engines/ags/engine/ac/gui_control.cpp b/engines/ags/engine/ac/gui_control.cpp
index a88eddb098b..401b73d9c6d 100644
--- a/engines/ags/engine/ac/gui_control.cpp
+++ b/engines/ags/engine/ac/gui_control.cpp
@@ -65,6 +65,9 @@ void GUIControl_SetVisible(GUIObject *guio, int visible) {
const bool on = visible != 0;
if (on != guio->IsVisible()) {
guio->SetVisible(on);
+ // Make sure that the overpic is turned off when the GUI goes off
+ if (!on && (_GP(guis)[guio->ParentId].MouseOverCtrl == guio->Id))
+ guio->OnMouseLeave();
}
}
Commit: 89ea094df157f65b3853040c302018fc4e3b309c
https://github.com/scummvm/scummvm/commit/89ea094df157f65b3853040c302018fc4e3b309c
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: fixed idle_anim_speed after restoring old save in updated game
>From upstream 0f19fc3d2b9efbc4eb809032bcb7d60b652e1150
Changed paths:
engines/ags/engine/game/savegame_components.cpp
engines/ags/shared/ac/character_info.cpp
engines/ags/shared/ac/character_info.h
engines/ags/shared/ac/game_setup_struct.cpp
engines/ags/shared/ac/game_setup_struct.h
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index f1d0be3b39b..afeba56e66a 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -496,7 +496,7 @@ HSaveError ReadCharacters(Stream *in, int32_t cmp_ver, const PreservedParams & /
if (!AssertGameContent(err, in->ReadInt32(), _GP(game).numcharacters, "Characters"))
return err;
for (int i = 0; i < _GP(game).numcharacters; ++i) {
- _GP(game).chars[i].ReadFromFile(in);
+ _GP(game).chars[i].ReadFromFile(in, kGameVersion_Undefined, cmp_ver);
_GP(charextra)[i].ReadFromSavegame(in, cmp_ver);
Properties::ReadValues(_GP(play).charProps[i], in);
if (_G(loaded_game_file_version) <= kGameVersion_272)
diff --git a/engines/ags/shared/ac/character_info.cpp b/engines/ags/shared/ac/character_info.cpp
index 0b220b7814f..66675ee2eb8 100644
--- a/engines/ags/shared/ac/character_info.cpp
+++ b/engines/ags/shared/ac/character_info.cpp
@@ -29,7 +29,7 @@ namespace AGS3 {
using AGS::Shared::Stream;
-void CharacterInfo::ReadFromFile(Stream *in) {
+void CharacterInfo::ReadFromFile(Stream *in, GameDataVersion data_ver, int save_ver) {
defview = in->ReadInt32();
talkview = in->ReadInt32();
view = in->ReadInt32();
@@ -77,8 +77,10 @@ void CharacterInfo::ReadFromFile(Stream *in) {
in->Read(scrname, MAX_SCRIPT_NAME_LEN);
on = in->ReadInt8();
- if (_G(loaded_game_file_version) < kGameVersion_360_16)
+ if ((data_ver > kGameVersion_Undefined && data_ver < kGameVersion_360_16) ||
+ (save_ver >= 0 && save_ver < 2)) {
idle_anim_speed = animspeed + 5;
+ }
}
void CharacterInfo::WriteToFile(Stream *out) {
diff --git a/engines/ags/shared/ac/character_info.h b/engines/ags/shared/ac/character_info.h
index cc73de68bc6..19984971e8f 100644
--- a/engines/ags/shared/ac/character_info.h
+++ b/engines/ags/shared/ac/character_info.h
@@ -24,6 +24,7 @@
#include "ags/lib/std/vector.h"
#include "ags/shared/ac/common_defines.h" // constants
+#include "ags/shared/ac/game_version.h"
#include "ags/shared/core/types.h"
namespace AGS3 {
@@ -131,7 +132,7 @@ struct CharacterInfo {
void update_character_idle(CharacterExtras *chex, int &doing_nothing);
void update_character_follower(int &char_index, std::vector<int> &followingAsSheep, int &doing_nothing);
- void ReadFromFile(Shared::Stream *in);
+ void ReadFromFile(Shared::Stream *in, GameDataVersion data_ver, int save_ver = -1);
void WriteToFile(Shared::Stream *out);
};
diff --git a/engines/ags/shared/ac/game_setup_struct.cpp b/engines/ags/shared/ac/game_setup_struct.cpp
index 5d2abc2c536..e429187ecc1 100644
--- a/engines/ags/shared/ac/game_setup_struct.cpp
+++ b/engines/ags/shared/ac/game_setup_struct.cpp
@@ -211,7 +211,7 @@ void GameSetupStruct::WriteMouseCursors_Aligned(Stream *out) {
void GameSetupStruct::read_characters(Shared::Stream *in) {
chars = new CharacterInfo[numcharacters];
- ReadCharacters_Aligned(in);
+ ReadCharacters_Aligned(in, false);
}
void GameSetupStruct::read_lipsync(Shared::Stream *in, GameDataVersion data_ver) {
@@ -243,10 +243,10 @@ void GameSetupStruct::read_messages(Shared::Stream *in, GameDataVersion data_ver
load_messages = nullptr;
}
-void GameSetupStruct::ReadCharacters_Aligned(Stream *in) {
+void GameSetupStruct::ReadCharacters_Aligned(Stream *in, bool is_save) {
AlignedStream align_s(in, Shared::kAligned_Read);
for (int iteratorCount = 0; iteratorCount < numcharacters; ++iteratorCount) {
- chars[iteratorCount].ReadFromFile(&align_s);
+ chars[iteratorCount].ReadFromFile(&align_s, is_save ? kGameVersion_Undefined : _G(loaded_game_file_version), 0);
align_s.Reset();
}
}
@@ -363,7 +363,7 @@ void GameSetupStruct::ReadFromSaveGame_v321(Stream *in, char *gswas, ccScript *c
in->ReadArrayOfInt32(&options[0], OPT_HIGHESTOPTION_321 + 1);
options[OPT_LIPSYNCTEXT] = in->ReadByte();
- ReadCharacters_Aligned(in);
+ ReadCharacters_Aligned(in, true);
}
//=============================================================================
diff --git a/engines/ags/shared/ac/game_setup_struct.h b/engines/ags/shared/ac/game_setup_struct.h
index b8df68e0730..434dd020e68 100644
--- a/engines/ags/shared/ac/game_setup_struct.h
+++ b/engines/ags/shared/ac/game_setup_struct.h
@@ -22,7 +22,6 @@
#ifndef AGS_SHARED_AC_GAME_SETUP_STRUCT_H
#define AGS_SHARED_AC_GAME_SETUP_STRUCT_H
-//#include "ags/lib/std/array.h"
#include "ags/lib/std/vector.h"
#include "ags/shared/ac/audio_clip_type.h"
#include "ags/shared/ac/character_info.h" // TODO: constants to separate header
@@ -147,7 +146,7 @@ struct GameSetupStruct : public GameSetupStructBase {
void read_lipsync(Shared::Stream *in, GameDataVersion data_ver);
void read_messages(Shared::Stream *in, GameDataVersion data_ver);
- void ReadCharacters_Aligned(Shared::Stream *in);
+ void ReadCharacters_Aligned(Shared::Stream *in, bool is_save);
void WriteCharacters_Aligned(Shared::Stream *out);
//------------------------------
// Part 3
Commit: 2daaef2d486b40d103c705598164134a7adeca9e
https://github.com/scummvm/scummvm/commit/2daaef2d486b40d103c705598164134a7adeca9e
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: updated SavegameVersion (had few cmp changes since last one)
>From upstream 84417e8c73815bcd35f4a6812d6f118cfb3acacb
Changed paths:
engines/ags/engine/game/savegame.h
diff --git a/engines/ags/engine/game/savegame.h b/engines/ags/engine/game/savegame.h
index 47b76788a31..8dc326aa8ae 100644
--- a/engines/ags/engine/game/savegame.h
+++ b/engines/ags/engine/game/savegame.h
@@ -62,8 +62,9 @@ enum SavegameVersion {
kSvgVersion_350_final = 11,
kSvgVersion_350_final2 = 12,
kSvgVersion_351 = 13,
- kSvgVersion_360beta = 3060023,
- kSvgVersion_Current = kSvgVersion_360beta,
+ kSvgVersion_360_beta = 3060023,
+ kSvgVersion_360_final = 3060041,
+ kSvgVersion_Current = kSvgVersion_360_final,
kSvgVersion_LowestSupported = kSvgVersion_321 // change if support dropped
};
Commit: 9a469f1e2bfad943ef944bb7da26c5304a2c6d4f
https://github.com/scummvm/scummvm/commit/9a469f1e2bfad943ef944bb7da26c5304a2c6d4f
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: support fixing up RoomStatuses restored from older save formats
This allows to properly fixup (upgrade) RoomStatus structs
restored from a older format save in an upgraded game.
For example: game was upgraded from 3.4.0 to 3.6.0, but player
tries loading 3.4.0 save. In this situation the engine must know and
keep track of what version each RoomStatus was saved in.
This is necessary, because RoomStatus can only be updated upon
loading a corresponding room file (when entering a room). This
means that multiple RoomStatus objects will be staying in memory
not being upgraded yet, until player enters particular room.
>From upstream 205232af5909e0a257494ff404f36003b004ebc4
Changed paths:
engines/ags/engine/ac/room.cpp
engines/ags/engine/ac/room_status.cpp
engines/ags/engine/ac/room_status.h
engines/ags/engine/game/savegame_components.cpp
diff --git a/engines/ags/engine/ac/room.cpp b/engines/ags/engine/ac/room.cpp
index 1754919c878..2d285691065 100644
--- a/engines/ags/engine/ac/room.cpp
+++ b/engines/ags/engine/ac/room.cpp
@@ -533,7 +533,7 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
_GP(thisroom).LocalVariables[i].Value = _G(croom)->interactionVariableValues[i];
// Always copy object and hotspot names for < 3.6.0 games, because they were not settable
- if (_G(loaded_game_file_version) < kGameVersion_360_16) {
+ if ((_G(loaded_game_file_version) < kGameVersion_360_16) || (_G(croom)->contentFormat < kRoomStatSvgVersion_36025)) {
for (size_t cc = 0; cc < _GP(thisroom).Objects.size(); ++cc)
_G(croom)->obj[cc].name = _GP(thisroom).Objects[cc].Name;
for (int cc = 0; cc < MAX_ROOM_HOTSPOTS; cc++)
@@ -597,6 +597,8 @@ void load_new_room(int newnum, CharacterInfo *forchar) {
_G(croom)->beenhere = 1;
_G(in_new_room) = 2;
}
+ // Reset contentFormat hint to avoid doing fixups later
+ _G(croom)->contentFormat = kRoomStatSvgVersion_Current;
if (_GP(thisroom).EventHandlers == nullptr) {
// legacy interactions
diff --git a/engines/ags/engine/ac/room_status.cpp b/engines/ags/engine/ac/room_status.cpp
index 7fc2508e8be..47ee11312b8 100644
--- a/engines/ags/engine/ac/room_status.cpp
+++ b/engines/ags/engine/ac/room_status.cpp
@@ -46,6 +46,7 @@ void HotspotState::WriteToSavegame(Shared::Stream *out) const {
}
RoomStatus::RoomStatus() {
+ contentFormat = kRoomStatSvgVersion_Current; // set current to avoid fixups
beenhere = 0;
numobj = 0;
tsdatasize = 0;
@@ -74,6 +75,7 @@ void RoomStatus::ReadFromFile_v321(Stream *in) {
FreeScriptData();
FreeProperties();
+ contentFormat = kRoomStatSvgVersion_Initial;
beenhere = in->ReadInt32();
numobj = in->ReadInt32();
obj.resize(MAX_ROOM_OBJECTS_v300);
@@ -120,7 +122,7 @@ void RoomStatus::ReadRoomObjects_Aligned(Shared::Stream *in) {
}
}
-void RoomStatus::ReadFromSavegame(Stream *in, int save_ver) {
+void RoomStatus::ReadFromSavegame(Stream *in, RoomStatSvgVersion save_ver) {
FreeScriptData();
FreeProperties();
@@ -161,6 +163,14 @@ void RoomStatus::ReadFromSavegame(Stream *in, int save_ver) {
tsdata.resize(tsdatasize);
in->Read(tsdata.data(), tsdatasize);
}
+
+ contentFormat = save_ver;
+ if (save_ver >= kRoomStatSvgVersion_36041) {
+ contentFormat = (RoomStatSvgVersion)in->ReadInt32();
+ in->ReadInt32(); // reserved
+ in->ReadInt32();
+ in->ReadInt32();
+ }
}
void RoomStatus::WriteToSavegame(Stream *out) const {
@@ -196,6 +206,12 @@ void RoomStatus::WriteToSavegame(Stream *out) const {
out->WriteInt32(static_cast<int32_t>(tsdatasize));
if (tsdatasize)
out->Write(tsdata.data(), tsdatasize);
+
+ // kRoomStatSvgVersion_36041
+ out->WriteInt32(contentFormat);
+ out->WriteInt32(0); // reserved
+ out->WriteInt32(0);
+ out->WriteInt32(0);
}
// JJS: Replacement for the global roomstats array in the original engine.
diff --git a/engines/ags/engine/ac/room_status.h b/engines/ags/engine/ac/room_status.h
index b708299f7a4..2df4b7567d0 100644
--- a/engines/ags/engine/ac/room_status.h
+++ b/engines/ags/engine/ac/room_status.h
@@ -23,6 +23,7 @@
#define AGS_ENGINE_AC_ROOM_STATUS_H
#include "ags/engine/ac/room_object.h"
+#include "ags/engine/game/savegame.h"
#include "ags/shared/game/room_struct.h"
#include "ags/shared/game/interactions.h"
#include "ags/shared/util/string_types.h"
@@ -47,8 +48,16 @@ struct HotspotState {
void WriteToSavegame(Shared::Stream *out) const;
};
-// This struct is saved in the save games - it contains everything about
-// a room that could change
+// Savegame data format for RoomStatus
+// TODO: fill in other versions (lookup the code history)
+enum RoomStatSvgVersion {
+ kRoomStatSvgVersion_Initial = 0,
+ kRoomStatSvgVersion_36025 = 3,
+ kRoomStatSvgVersion_36041 = 4,
+ kRoomStatSvgVersion_Current = kRoomStatSvgVersion_36041
+};
+
+// RoomStatus contains everything about a room that could change at runtime.
struct RoomStatus {
int beenhere = 0;
uint32_t numobj = 0;
@@ -76,6 +85,13 @@ struct RoomStatus {
EventBlock misccond;
#endif
+ // A version of a save this RoomStatus was restored from.
+ // This is used as a hint when merging RoomStatus with the loaded room file (upon room enter).
+ // We need this for cases when an old format save is restored within an upgraded game
+ // (for example, game was upgraded from 3.4.0 to 3.6.0, but player tries loading 3.4.0 save),
+ // because room files are only loaded once entered, so we cannot fixup all RoomStatuses at once.
+ RoomStatSvgVersion contentFormat;
+
RoomStatus();
~RoomStatus();
@@ -84,7 +100,7 @@ struct RoomStatus {
void ReadFromFile_v321(Shared::Stream *in);
void ReadRoomObjects_Aligned(Shared::Stream *in);
- void ReadFromSavegame(Shared::Stream *in, int save_ver);
+ void ReadFromSavegame(Shared::Stream *in, RoomStatSvgVersion save_ver);
void WriteToSavegame(Shared::Stream *out) const;
};
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index afeba56e66a..d4ce41d7dc9 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -883,7 +883,7 @@ HSaveError ReadRoomStates(Stream *in, int32_t cmp_ver, const PreservedParams & /
if (!AssertFormatTagStrict(err, in, "RoomState", true))
return err;
RoomStatus *roomstat = getRoomStatus(id);
- roomstat->ReadFromSavegame(in, cmp_ver);
+ roomstat->ReadFromSavegame(in, (RoomStatSvgVersion)cmp_ver);
if (!AssertFormatTagStrict(err, in, "RoomState", false))
return err;
}
@@ -977,7 +977,7 @@ HSaveError ReadThisRoom(Stream *in, int32_t cmp_ver, const PreservedParams & /*p
// read the current troom state, in case they saved in temporary room
if (!in->ReadBool())
- _GP(troom).ReadFromSavegame(in, cmp_ver);
+ _GP(troom).ReadFromSavegame(in, (RoomStatSvgVersion)cmp_ver);
return HSaveError::None();
}
@@ -1110,15 +1110,15 @@ struct ComponentHandlers {
},
{
"Room States",
- 3,
- 0,
+ kRoomStatSvgVersion_36041,
+ kRoomStatSvgVersion_Initial,
WriteRoomStates,
ReadRoomStates
},
{
"Loaded Room State",
- 3, // must correspond to "Room States"
- 0,
+ kRoomStatSvgVersion_36041, // must correspond to "Room States"
+ kRoomStatSvgVersion_Initial,
WriteThisRoom,
ReadThisRoom
},
Commit: 953356c758ed920a966147614f0dfdd68fa5620e
https://github.com/scummvm/scummvm/commit/953356c758ed920a966147614f0dfdd68fa5620e
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Common: call OnMouseLeave on focused control in ResetOverControl()
>From upstream b8de51fedf0318e8243e1fc3872c61f366a23144
Changed paths:
engines/ags/shared/gui/gui_main.cpp
diff --git a/engines/ags/shared/gui/gui_main.cpp b/engines/ags/shared/gui/gui_main.cpp
index da159965122..5946327eaed 100644
--- a/engines/ags/shared/gui/gui_main.cpp
+++ b/engines/ags/shared/gui/gui_main.cpp
@@ -209,6 +209,8 @@ void GUIMain::ClearChanged() {
}
void GUIMain::ResetOverControl() {
+ if (MouseOverCtrl >= 0)
+ _controls[MouseOverCtrl]->OnMouseLeave();
// Force it to re-check for which control is under the mouse
MouseWasAt.X = -1;
MouseWasAt.Y = -1;
Commit: 9743b0dd6c5973fa1d57f2c811c3545a4aef3d17
https://github.com/scummvm/scummvm/commit/9743b0dd6c5973fa1d57f2c811c3545a4aef3d17
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: restored GUI draw sort, where equal z is resolved with IDs
NOTE: the code theoretically allows any object to be sorted this
way, but the problem is, the ID sequences are not shared, and
multiple object types may have same IDs.
This is something to consider in the future.
Changed paths:
engines/ags/engine/ac/draw.cpp
diff --git a/engines/ags/engine/ac/draw.cpp b/engines/ags/engine/ac/draw.cpp
index 76c0594e513..9d111c213d0 100644
--- a/engines/ags/engine/ac/draw.cpp
+++ b/engines/ags/engine/ac/draw.cpp
@@ -852,13 +852,15 @@ static void add_to_sprite_list(IDriverDependantBitmap *ddb, int x, int y, int zo
_GP(sprlist).push_back(sprite);
}
-// z-order sorting function for sprites
+// Sprite drawing order sorting function,
+// where equal zorder is resolved by comparing optional IDs too.
static bool spritelistentry_less(const SpriteListEntry &e1, const SpriteListEntry &e2) {
- return (e1.zorder < e2.zorder);
+ return (e1.zorder < e2.zorder) ||
+ ((e1.zorder == e2.zorder) && (e1.id < e2.id));
}
-// room-specialized function to sort the sprites into baseline order
-// has special handling for walk-behinds (this is complicated...)
+// Room-specialized function to sort the sprites into baseline order;
+// does not account for IDs, but has special handling for walk-behinds.
static bool spritelistentry_room_less(const SpriteListEntry &e1, const SpriteListEntry &e2) {
if (e1.zorder == e2.zorder) {
if (e1.takesPriorityIfEqual)
Commit: 15d43b09adf4d0afcde7c3e94a5abdc1d52d3423
https://github.com/scummvm/scummvm/commit/15d43b09adf4d0afcde7c3e94a5abdc1d52d3423
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Common: add AGS_PLATFORM_MOBILE for Android and iOS
Partially from upstream 4404881c6a49e3a74f316998ee46368b00895fc7
Changed paths:
engines/ags/engine/main/graphics_mode.cpp
engines/ags/shared/core/platform.h
diff --git a/engines/ags/engine/main/graphics_mode.cpp b/engines/ags/engine/main/graphics_mode.cpp
index 0cdc7d02b53..cf3d1a89bd9 100644
--- a/engines/ags/engine/main/graphics_mode.cpp
+++ b/engines/ags/engine/main/graphics_mode.cpp
@@ -42,7 +42,7 @@
namespace AGS3 {
// Don't try to figure out the window size on the mac because the port resizes itself.
-#if AGS_PLATFORM_OS_MACOS || defined(ALLEGRO_SDL2) || AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_ANDROID
+#if AGS_PLATFORM_OS_MACOS || defined(ALLEGRO_SDL2) || AGS_PLATFORM_MOBILE
#define USE_SIMPLE_GFX_INIT
#endif
diff --git a/engines/ags/shared/core/platform.h b/engines/ags/shared/core/platform.h
index a4a108d8e5e..9f2b6415e22 100644
--- a/engines/ags/shared/core/platform.h
+++ b/engines/ags/shared/core/platform.h
@@ -137,8 +137,10 @@ namespace AGS3 {
#define AGS_PLATFORM_DEBUG (0)
#endif
+#define AGS_PLATFORM_MOBILE ((AGS_PLATFORM_OS_ANDROID) || (AGS_PLATFORM_OS_IOS))
+
#define AGS_HAS_DIRECT3D (AGS_PLATFORM_OS_WINDOWS)
-#define AGS_HAS_OPENGL (AGS_PLATFORM_OS_WINDOWS || AGS_PLATFORM_OS_ANDROID || AGS_PLATFORM_OS_IOS || AGS_PLATFORM_OS_LINUX)
+#define AGS_HAS_OPENGL (AGS_PLATFORM_OS_WINDOWS || AGS_PLATFORM_OS_LINUX || AGS_PLATFORM_MOBILE)
#define AGS_OPENGL_ES2 (AGS_PLATFORM_OS_ANDROID)
// Only allow searching around for game data on desktop systems;
Commit: 9a4817653cc7aed253cb8fdcf71fe6ce58d6c514
https://github.com/scummvm/scummvm/commit/9a4817653cc7aed253cb8fdcf71fe6ce58d6c514
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: resizable flag is necessary for fullscreen app rotation
>From upstream 51a7e64efd628e62c73b1b1b8011d22ec83b0c38
Changed paths:
engines/ags/engine/platform/base/sys_main.cpp
diff --git a/engines/ags/engine/platform/base/sys_main.cpp b/engines/ags/engine/platform/base/sys_main.cpp
index d81ca47e957..d19fb314858 100644
--- a/engines/ags/engine/platform/base/sys_main.cpp
+++ b/engines/ags/engine/platform/base/sys_main.cpp
@@ -154,6 +154,9 @@ SDL_Window *sys_window_create(const char *window_title, int w, int h, WindowMode
case kWnd_FullDesktop: flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; break;
}
flags |= ex_flags;
+#if (AGS_PLATFORM_MOBILE)
+ flags |= SDL_WINDOW_RESIZABLE;
+#endif
window = SDL_CreateWindow(
window_title,
SDL_WINDOWPOS_CENTERED_DISPLAY(DEFAULT_DISPLAY_INDEX),
Commit: 07bbbcd233dd3fd8b9404a0a9e554db2ef573693
https://github.com/scummvm/scummvm/commit/07bbbcd233dd3fd8b9404a0a9e554db2ef573693
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:28Z
Commit Message:
AGS: Engine: replaced couple more shared_ptr<char> with vector<char>
>From upstream 1cccdfea5c1009123de7ba25be72b2757f74d06f
Changed paths:
engines/ags/engine/game/savegame.cpp
engines/ags/engine/game/savegame_components.cpp
engines/ags/engine/game/savegame_internal.h
engines/ags/engine/game/savegame_v321.cpp
engines/ags/plugins/ags_plugin.cpp
engines/ags/shared/game/main_game_file.cpp
engines/ags/shared/game/plugin_info.h
diff --git a/engines/ags/engine/game/savegame.cpp b/engines/ags/engine/game/savegame.cpp
index fe45c725e1c..009edff8b1d 100644
--- a/engines/ags/engine/game/savegame.cpp
+++ b/engines/ags/engine/game/savegame.cpp
@@ -467,14 +467,14 @@ HSaveError DoAfterRestore(const PreservedParams &pp, const RestoredData &r_data)
}
// read the global data into the newly created script
- if (r_data.GlobalScript.Data.get())
- memcpy(_G(gameinst)->globaldata, r_data.GlobalScript.Data.get(),
+ if (!r_data.GlobalScript.Data.empty())
+ memcpy(_G(gameinst)->globaldata, &r_data.GlobalScript.Data.front(),
MIN((size_t)_G(gameinst)->globaldatasize, r_data.GlobalScript.Len));
// restore the script module data
for (size_t i = 0; i < _G(numScriptModules); ++i) {
- if (r_data.ScriptModules[i].Data.get())
- memcpy(_GP(moduleInst)[i]->globaldata, r_data.ScriptModules[i].Data.get(),
+ if (!r_data.ScriptModules[i].Data.empty())
+ memcpy(_GP(moduleInst)[i]->globaldata, &r_data.ScriptModules[i].Data.front(),
MIN((size_t)_GP(moduleInst)[i]->globaldatasize, r_data.ScriptModules[i].Len));
}
diff --git a/engines/ags/engine/game/savegame_components.cpp b/engines/ags/engine/game/savegame_components.cpp
index d4ce41d7dc9..02e4d5e524c 100644
--- a/engines/ags/engine/game/savegame_components.cpp
+++ b/engines/ags/engine/game/savegame_components.cpp
@@ -835,8 +835,9 @@ HSaveError ReadScriptModules(Stream *in, int32_t cmp_ver, const PreservedParams
if (!AssertGameContent(err, data_len, pp.GlScDataSize, "global script data"))
return err;
r_data.GlobalScript.Len = data_len;
- r_data.GlobalScript.Data.reset(new char[data_len]);
- in->Read(r_data.GlobalScript.Data.get(), data_len);
+ r_data.GlobalScript.Data.resize(data_len);
+ if (data_len > 0)
+ in->Read(&r_data.GlobalScript.Data.front(), data_len);
if (!AssertGameContent(err, in->ReadInt32(), _G(numScriptModules), "Script Modules"))
return err;
@@ -846,8 +847,9 @@ HSaveError ReadScriptModules(Stream *in, int32_t cmp_ver, const PreservedParams
if (!AssertGameObjectContent(err, data_len, pp.ScMdDataSize[i], "script module data", "module", i))
return err;
r_data.ScriptModules[i].Len = data_len;
- r_data.ScriptModules[i].Data.reset(new char[data_len]);
- in->Read(r_data.ScriptModules[i].Data.get(), data_len);
+ r_data.ScriptModules[i].Data.resize(data_len);
+ if (data_len > 0)
+ in->Read(&r_data.ScriptModules[i].Data.front(), data_len);
}
return err;
}
diff --git a/engines/ags/engine/game/savegame_internal.h b/engines/ags/engine/game/savegame_internal.h
index 56e76ae973e..92721a56fca 100644
--- a/engines/ags/engine/game/savegame_internal.h
+++ b/engines/ags/engine/game/savegame_internal.h
@@ -72,7 +72,7 @@ struct RestoredData {
std::vector<Bitmap *> DynamicSurfaces;
// Scripts global data
struct ScriptData {
- std::shared_ptr<char> Data;
+ std::vector<char> Data;
size_t Len;
ScriptData();
diff --git a/engines/ags/engine/game/savegame_v321.cpp b/engines/ags/engine/game/savegame_v321.cpp
index a409e0171ed..31f4a6b75a8 100644
--- a/engines/ags/engine/game/savegame_v321.cpp
+++ b/engines/ags/engine/game/savegame_v321.cpp
@@ -94,8 +94,9 @@ static HSaveError restore_game_scripts(Stream *in, const PreservedParams &pp, Re
return new SavegameError(kSvgErr_GameContentAssertion, "Mismatching size of global script data.");
}
r_data.GlobalScript.Len = gdatasize;
- r_data.GlobalScript.Data.reset(new char[gdatasize]);
- in->Read(r_data.GlobalScript.Data.get(), gdatasize);
+ r_data.GlobalScript.Data.resize(gdatasize);
+ if (gdatasize > 0)
+ in->Read(&r_data.GlobalScript.Data.front(), gdatasize);
if ((uint32_t)in->ReadInt32() != _G(numScriptModules)) {
return new SavegameError(kSvgErr_GameContentAssertion, "Mismatching number of script modules.");
@@ -107,8 +108,9 @@ static HSaveError restore_game_scripts(Stream *in, const PreservedParams &pp, Re
return new SavegameError(kSvgErr_GameContentAssertion, String::FromFormat("Mismatching size of script module data, module %d.", i));
}
r_data.ScriptModules[i].Len = module_size;
- r_data.ScriptModules[i].Data.reset(new char[module_size]);
- in->Read(r_data.ScriptModules[i].Data.get(), module_size);
+ r_data.ScriptModules[i].Data.resize(module_size);
+ if (module_size > 0)
+ in->Read(&r_data.ScriptModules[i].Data.front(), module_size);
}
return HSaveError::None();
}
diff --git a/engines/ags/plugins/ags_plugin.cpp b/engines/ags/plugins/ags_plugin.cpp
index 49975b3e540..4e046ce2aa2 100644
--- a/engines/ags/plugins/ags_plugin.cpp
+++ b/engines/ags/plugins/ags_plugin.cpp
@@ -869,9 +869,9 @@ Engine::GameInitError pl_register_plugins(const std::vector<Shared::PluginInfo>
// Copy plugin info
apl->filename = name;
- if (info.DataLen) {
+ if (info.DataLen > 0) {
apl->savedata = (char *)malloc(info.DataLen);
- memcpy(apl->savedata, info.Data.get(), info.DataLen);
+ memcpy(apl->savedata, &info.Data.front(), info.DataLen);
}
apl->savedatasize = info.DataLen;
diff --git a/engines/ags/shared/game/main_game_file.cpp b/engines/ags/shared/game/main_game_file.cpp
index 3419a5bba37..101d6c918fb 100644
--- a/engines/ags/shared/game/main_game_file.cpp
+++ b/engines/ags/shared/game/main_game_file.cpp
@@ -379,8 +379,8 @@ HGameFileError ReadPlugins(std::vector<PluginInfo> &infos, Stream *in) {
PluginInfo info;
info.Name = name;
if (datasize > 0) {
- info.Data.reset(new char[datasize]);
- in->Read(info.Data.get(), datasize);
+ info.Data.resize(datasize);
+ in->Read(&info.Data.front(), datasize);
}
info.DataLen = datasize;
infos.push_back(info);
diff --git a/engines/ags/shared/game/plugin_info.h b/engines/ags/shared/game/plugin_info.h
index 2a9238ff73c..ed4297dc861 100644
--- a/engines/ags/shared/game/plugin_info.h
+++ b/engines/ags/shared/game/plugin_info.h
@@ -42,7 +42,7 @@ struct PluginInfo {
// (File)name of plugin
String Name;
// Custom data for plugin
- std::shared_ptr<char> Data;
+ std::vector<char> Data;
size_t DataLen;
PluginInfo() : DataLen(0) {
Commit: bdec317f270c7f3e530604f4ac4a602da5bb8e23
https://github.com/scummvm/scummvm/commit/bdec317f270c7f3e530604f4ac4a602da5bb8e23
Author: Walter Agazzi (walter.agazzi at protonmail.com)
Date: 2023-03-12T20:58:29Z
Commit Message:
AGS: Updated build version (3.6.0.41)
Partially from upstream 81b5fbc917d83a02cebc152969fd769b2b7b9b15
Changed paths:
engines/ags/shared/core/def_version.h
diff --git a/engines/ags/shared/core/def_version.h b/engines/ags/shared/core/def_version.h
index 90027318fee..cc83d48c666 100644
--- a/engines/ags/shared/core/def_version.h
+++ b/engines/ags/shared/core/def_version.h
@@ -22,9 +22,9 @@
#ifndef AGS_SHARED_CORE_DEFVERSION_H
#define AGS_SHARED_CORE_DEFVERSION_H
-#define ACI_VERSION_STR "3.6.0.40"
+#define ACI_VERSION_STR "3.6.0.41"
#if defined (RC_INVOKED) // for MSVC resource compiler
-#define ACI_VERSION_MSRC_DEF 3.6.0.40
+#define ACI_VERSION_MSRC_DEF 3.6.0.41
#endif
#define SPECIAL_VERSION ""
Commit: be309e97ebc76f9935bb80ee6bc9280f6655b5ac
https://github.com/scummvm/scummvm/commit/be309e97ebc76f9935bb80ee6bc9280f6655b5ac
Author: D G Turner (digitall at scummvm.org)
Date: 2023-03-12T20:58:29Z
Commit Message:
AGS: Fix GCC Compiler Warnings
Changed paths:
engines/ags/engine/debugging/debugger.h
engines/ags/shared/util/lzw.cpp
diff --git a/engines/ags/engine/debugging/debugger.h b/engines/ags/engine/debugging/debugger.h
index 9a60c29f0ff..e0af049e32e 100644
--- a/engines/ags/engine/debugging/debugger.h
+++ b/engines/ags/engine/debugging/debugger.h
@@ -34,7 +34,6 @@ bool send_state_to_debugger(const char *msg);
bool send_exception_to_debugger(const char *qmsg);
// Returns current script's location and callstack
AGS::Shared::String get_cur_script(int numberOfLinesOfCallStack);
-bool get_script_position(ScriptPosition &script_pos);
void check_debug_keys();
#define DBG_NOIFACE 1
diff --git a/engines/ags/shared/util/lzw.cpp b/engines/ags/shared/util/lzw.cpp
index 18c3aa516af..ef6a6c9823e 100644
--- a/engines/ags/shared/util/lzw.cpp
+++ b/engines/ags/shared/util/lzw.cpp
@@ -252,7 +252,7 @@ bool lzwexpand(const uint8_t *src, size_t src_sz, uint8_t *dst, size_t dst_sz) {
}
free(_G(lzbuffer));
- return (src_ptr - src) == src_sz;
+ return static_cast<size_t>(src_ptr - src) == src_sz;
}
} // namespace AGS3
More information about the Scummvm-git-logs
mailing list